From c0ce6a53d4175bd0fd913b917e9238e6ef194003 Mon Sep 17 00:00:00 2001 From: Ulty Date: Sun, 8 Oct 2023 09:53:42 +0200 Subject: [PATCH] COFantasy: charge action now moves the token. --- COFantasy/3.13/COFantasy.js | 8809 +++++++++++++++++++---------------- COFantasy/3.13/doc.html | 2773 +++++------ COFantasy/COFantasy.js | 8809 +++++++++++++++++++---------------- COFantasy/ChangeLog.md | 9 + COFantasy/doc.html | 2773 +++++------ 5 files changed, 12247 insertions(+), 10926 deletions(-) diff --git a/COFantasy/3.13/COFantasy.js b/COFantasy/3.13/COFantasy.js index 686a34728..7d63d0529 100644 --- a/COFantasy/3.13/COFantasy.js +++ b/COFantasy/3.13/COFantasy.js @@ -37,49 +37,49 @@ const generateUUID = (function() { }; //--------------- end generateRowID ---------------------------------------- -const COF_BETA = true; +const COF_BETA = false; let COF_loaded = false; -// Le script utilise la partie COFantasy de la variable d'état state -// Pour plus de facilité, on utilise stateCOF = state.COFantasy -// Champs utilisés: +// Le script utilise la partie COFantasy de la variable d'\xE9tat state +// Pour plus de facilit\xE9, on utilise stateCOF = state.COFantasy +// Champs utilis\xE9s: // - options : les options de jeu -// - setting_arran : toutes les fiches utilisent les règles Terres d'Arran +// - setting_arran : toutes les fiches utilisent les r\xE8gles Terres d'Arran // - setting_mixte : on a un mixte de fiches classiques et Terres d'Arran -// - roundMarkerId : l'id du token utilisé pour l'aura d'initiative -// - combat : défini si le jeu est en mode tour par tour, contient : +// - roundMarkerId : l'id du token utilis\xE9 pour l'aura d'initiative +// - combat : d\xE9fini si le jeu est en mode tour par tour, contient : // - pageId : la pageid du combat // - activeTokenId : id du token dont c'est le tour -// - activeTokenName : nom du token dont c'est le tour, au cas où l'id change -// - tour : numéro de tour dans le combat +// - activeTokenName : nom du token dont c'est le tour, au cas o\xF9 l'id change +// - tour : num\xE9ro de tour dans le combat // - init : niveau d'initiative courant // - armeesDesMorts : map de token id vers perso // - auras : liste des auras actives // - aurasCounts : computeur pour id des auras // - usureOff : on ne compte plus l'usure du combat -// - personnageCibleCree : pour savoir si on a créé un personnage cible (avec 0 PV pour centrer les aoe) -// - tablesCrees : pour savoir si on a créé les tables par défaut -// - gameMacros : la liste des macros créées par le script +// - personnageCibleCree : pour savoir si on a cr\xE9\xE9 un personnage cible (avec 0 PV pour centrer les aoe) +// - tablesCrees : pour savoir si on a cr\xE9\xE9 les tables par d\xE9faut +// - gameMacros : la liste des macros cr\xE9\xE9es par le script // - chargeFantastique : tout ce dont on a besoin pour une charge fantastique en cours (TODO: passer sous combat) // - eventId : compteur d'events pour avoir une id unique -// - tokensTemps : liste de tokens à durée de vie limitée, effacés à la fin du combat -// - effetAuD20 : les effets qui se produisent à chaque jet de dé. -// chaque effet est déterminé par un champ, puis pour chaque champ, -// - min: valeur minimale du dé pour déclencher -// - max: valeur maximale du dé pour déclencher -// - fct: nom de la fonction à appeler -// - nomFin: nom à afficher pour le statut et mettre fin aux événements +// - tokensTemps : liste de tokens \xE0 dur\xE9e de vie limit\xE9e, effac\xE9s \xE0 la fin du combat +// - effetAuD20 : les effets qui se produisent \xE0 chaque jet de d\xE9. +// chaque effet est d\xE9termin\xE9 par un champ, puis pour chaque champ, +// - min: valeur minimale du d\xE9 pour d\xE9clencher +// - max: valeur maximale du d\xE9 pour d\xE9clencher +// - fct: nom de la fonction \xE0 appeler +// - nomFin: nom \xE0 afficher pour le statut et mettre fin aux \xE9v\xE9nements // par exemple, foudreDuTemps pour les foudres du temps -// - tenebresMagiques : état général de ténèbres magiques -// - jetsEnCours : pour laisser le MJ montrer ou non un jet qui lui a été montré à lui seul +// - tenebresMagiques : \xE9tat g\xE9n\xE9ral de t\xE9n\xE8bres magiques +// - jetsEnCours : pour laisser le MJ montrer ou non un jet qui lui a \xE9t\xE9 montr\xE9 \xE0 lui seul // - currentAttackDisplay : pour pouvoir remontrer des display aux joueurs // - pause : le jeu est en pause -// - prescience : un personnage sur la carte de combat a la capacité prescience (TODO: passer sous combat) +// - prescience : un personnage sur la carte de combat a la capacit\xE9 prescience (TODO: passer sous combat) // - nextPrescience : pour le changement de tour car prescience ne revient que d'un tour -// - afterDisplay : données à afficher après un display -// - version : la version du script en cours, pour détecter qu'on change de version -// statistiques : des statistiques pour les jets de dés +// - afterDisplay : donn\xE9es \xE0 afficher apr\xE8s un display +// - version : la version du script en cours, pour d\xE9tecter qu'on change de version +// statistiques : des statistiques pour les jets de d\xE9s // statistiquesEnPause var COFantasy = COFantasy || function() { @@ -97,6 +97,7 @@ var COFantasy = COFantasy || function() { const BS_LABEL_DANGER = 'background-color: #d9534f;'; const DEFAULT_DYNAMIC_INIT_IMG = 'https://s3.amazonaws.com/files.d20.io/images/4095816/086YSl3v0Kz3SlDAu245Vg/thumb.png?1400535580'; const IMG_INVISIBLE = 'https://s3.amazonaws.com/files.d20.io/images/24377109/6L7tn91HZLAQfrLKQI7-Ew/thumb.png?1476950708'; + const IMG_BOMB = 'https://s3.amazonaws.com/files.d20.io/images/361033841/dmwnChkZNCI9a0_uKfGcNg/thumb.png?1695976505'; let markerCatalog = {}; let eventHistory = []; @@ -120,7 +121,7 @@ var COFantasy = COFantasy || function() { const defaultOptions = { regles: { - explications: "Options qui influent sur les règles du jeu", + explications: "Options qui influent sur les r\xE8gles du jeu", type: 'options', val: { divers: { @@ -128,105 +129,105 @@ var COFantasy = COFantasy || function() { type: 'options', val: { forme_d_arbre_amelioree: { - explications: "+50% à l'effet de la peau d'écorce en forme d'arbre.", + explications: "+50% \xE0 l'effet de la peau d'\xE9corce en forme d'arbre.", val: true, type: 'bool' }, poudre_explosif: { - explications: "Les armes à poudre font des dégâts explosifs", + explications: "Les armes \xE0 poudre font des d\xE9g\xE2ts explosifs", val: true, type: 'bool' }, interchangeable_attaque: { - explications: "La capacité interchangeable donne moins de DEF mais plus d'attaque", + explications: "La capacit\xE9 interchangeable donne moins de DEF mais plus d'attaque", val: true, type: 'bool' }, coups_critiques_etendus: { - explications: "Coup critique à une attaque dès qu'elle dépasse DEF + 10", + explications: "Coup critique \xE0 une attaque d\xE8s qu'elle d\xE9passe DEF + 10", val: false, type: 'bool' }, echec_critique_boule_de_feu: { - explications: "Nombre de mètre dont le centre d'une boule de feu peut être déplacé de manière aléatoire en cas d'échec critique. La probabilité est inversement proportionelle à la distance.", + explications: "Nombre de m\xE8tre dont le centre d'une boule de feu peut \xEAtre d\xE9plac\xE9 de mani\xE8re al\xE9atoire en cas d'\xE9chec critique. La probabilit\xE9 est inversement proportionelle \xE0 la distance.", val: 12, type: 'int' } } }, dommages: { - explications: "Règles optionnelles sur les dommages", + explications: "R\xE8gles optionnelles sur les dommages", type: 'options', val: { blessures_graves: { - explications: "Si on arrive à 0 PV, on perd 1PR, et si on a plus de PR, on a une blessure grave.", + explications: "Si on arrive \xE0 0 PV, on perd 1PR, et si on a plus de PR, on a une blessure grave.", val: true, type: 'bool' }, degats_importants: { - explications: "Si les DMs dépassent CON+niveau en une attaque, on applique aussi la règle de blessure grave. Si la valeur de cette option est 0, la règles n'est pas appliquée. Sinon, la règle n'est appliquée que si, de plus, les DMs dépassent maxPV / valeur.", + explications: "Si les DMs d\xE9passent CON+niveau en une attaque, on applique aussi la r\xE8gle de blessure grave. Si la valeur de cette option est 0, la r\xE8gles n'est pas appliqu\xE9e. Sinon, la r\xE8gle n'est appliqu\xE9e que si, de plus, les DMs d\xE9passent maxPV / valeur.", val: 3, type: 'int' }, dm_minimum: { - explications: "Dégâts minimum d'une attaque ou autre source de DM.", + explications: "D\xE9g\xE2ts minimum d'une attaque ou autre source de DM.", val: 0, type: 'int' }, crit_elementaire: { - explications: "Les DMs constants d'un autre type que celui de l'arme sont aussi multipliés en cas de critique", + explications: "Les DMs constants d'un autre type que celui de l'arme sont aussi multipli\xE9s en cas de critique", val: false, type: 'bool' }, max_rune_protection: { - explications: "Les DMs qu'une rune de protection est capable d'absorber sont limités à 10x le rang du forgesort dans la voie des runes", + explications: "Les DMs qu'une rune de protection est capable d'absorber sont limit\xE9s \xE0 10x le rang du forgesort dans la voie des runes", val: true, type: 'bool' }, dm_explosifs: { - explications: "Tous les dés de DM sont explosifs", + explications: "Tous les d\xE9s de DM sont explosifs", val: false, type: 'bool' } } }, haute_DEF: { - explications: "Options de jeu pour gérer la haute DEF", + explications: "Options de jeu pour g\xE9rer la haute DEF", type: 'options', val: { usure_DEF: { - explications: "Malus de -2 en DEF tous les n tours. Mettre à 0 pour ne pas avoir de malus d'usure", + explications: "Malus de -2 en DEF tous les n tours. Mettre \xE0 0 pour ne pas avoir de malus d'usure", val: 6, type: 'int' }, bonus_attaque_groupe: { - explications: "Lors d'une attaque de groupe, bonus à la touche par créature supplémentaire", + explications: "Lors d'une attaque de groupe, bonus \xE0 la touche par cr\xE9ature suppl\xE9mentaire", val: 2, type: 'int' }, crit_attaque_groupe: { - explications: "Lors d'une attaque de groupe, si le jet de touche dépasse DEF + cette valeur, les dommages sont doublés (0 = jamais)", + explications: "Lors d'une attaque de groupe, si le jet de touche d\xE9passe DEF + cette valeur, les dommages sont doubl\xE9s (0 = jamais)", val: 5, type: 'int' } } }, initiative: { - explications: "Options qui influent sur les règles du jeu", + explications: "Options qui influent sur les r\xE8gles du jeu", type: 'options', val: { initiative_variable: { - explications: "Ajoute 1d6 à l'initiative, lancé une fois par combat par type de créature", + explications: "Ajoute 1d6 \xE0 l'initiative, lanc\xE9 une fois par combat par type de cr\xE9ature", val: false, type: 'bool' }, initiative_variable_individuelle: { - explications: "Lancer l'initiative variable pour chaque créature (nécessite d'activer l'Initiative variable)", + explications: "Lancer l'initiative variable pour chaque cr\xE9ature (n\xE9cessite d'activer l'Initiative variable)", val: false, type: 'bool' }, joueurs_lancent_init: { - explications: "Fait apparaître un bouton pour que les joueurs lancent leur initiative (nécessite d'activer l'Initiative variable)", + explications: "Fait appara\xEEtre un bouton pour que les joueurs lancent leur initiative (n\xE9cessite d'activer l'Initiative variable)", val: false, type: 'bool' } @@ -237,12 +238,12 @@ var COFantasy = COFantasy || function() { type: 'options', val: { mana_totale: { - explications: "Tous les sorts ont un coût, celui des tempêtes de mana est multiplié par 3", + explications: "Tous les sorts ont un co\xFBt, celui des temp\xEAtes de mana est multipli\xE9 par 3", val: false, type: 'bool' }, contrecoup: { - explications: "Avec la Mana Totale, permet au lanceur de sort de payer un déficit de PM en PV (COF p. 181)", + explications: "Avec la Mana Totale, permet au lanceur de sort de payer un d\xE9ficit de PM en PV (COF p. 181)", val: false, type: 'bool' }, @@ -252,7 +253,7 @@ var COFantasy = COFantasy || function() { type: 'bool' }, elixirs_sorts: { - explications: "Toutes fabrications d'élixir sont considérées comme des sorts (qui peuvent coûter de la mana)", + explications: "Toutes fabrications d'\xE9lixir sont consid\xE9r\xE9es comme des sorts (qui peuvent co\xFBter de la mana)", val: true, type: 'bool' }, @@ -265,17 +266,17 @@ var COFantasy = COFantasy || function() { type: 'options', val: { MJ_voit_actions: { - explications: "À chaque nouveau personnage en combat, montre le choix d'actions au MJ, même pour les PJs.", + explications: "\xC0 chaque nouveau personnage en combat, montre le choix d'actions au MJ, m\xEAme pour les PJs.", val: false, type: 'bool' }, MJ_valide_affichage_attaques: { - explications: "Les résultats des attaques sont d'abord montrées au MJ seul, qui peut ensuite les montrer aux joueurs", + explications: "Les r\xE9sultats des attaques sont d'abord montr\xE9es au MJ seul, qui peut ensuite les montrer aux joueurs", val: false, type: 'bool' }, MJ_valide_affichage_jets: { - explications: "Les résultats des jets de caractéristiques sont d'abord montrées au MJ seul, qui peut ensuite les montrer aux joueurs", + explications: "Les r\xE9sultats des jets de caract\xE9ristiques sont d'abord montr\xE9es au MJ seul, qui peut ensuite les montrer aux joueurs", val: false, type: 'bool' }, @@ -300,96 +301,96 @@ var COFantasy = COFantasy || function() { type: 'bool' }, duree_effets: { - explications: "Le script indique la durée des effets associés aux tokens", + explications: "Le script indique la dur\xE9e des effets associ\xE9s aux tokens", val: false, type: 'bool' }, init_dynamique: { - explications: "Fait apparaître une aura dynamique sur le token qui a l'initiative", + explications: "Fait appara\xEEtre une aura dynamique sur le token qui a l'initiative", val: true, type: 'bool' }, markers_personnalises: { - explications: "Utilisation des markers personnalisés commençant par cof", + explications: "Utilisation des markers personnalis\xE9s commen\xE7ant par cof", val: true, type: 'bool' }, table_crit: { - explications: "Utilisation d'une table de critiques nommée Echec-Critique-Contact", + explications: "Utilisation d'une table de critiques nomm\xE9e Echec-Critique-Contact", val: false, type: 'bool' }, depense_mana: { - explications: "Le script précise la quantité de mana utilisée dans le chat à chaque fois", + explications: "Le script pr\xE9cise la quantit\xE9 de mana utilis\xE9e dans le chat \xE0 chaque fois", val: false, type: 'bool' } } }, images: { - explications: "Images par défaut", + explications: "Images par d\xE9faut", type: 'options', val: { image_init: { - explications: "Image utilisée pour indiquer le personnage dont c'est le tour", + explications: "Image utilis\xE9e pour indiquer le personnage dont c'est le tour", type: 'image', val: DEFAULT_DYNAMIC_INIT_IMG }, image_double: { - explications: 'Image utilisée pour la capacité dédoublement', + explications: 'Image utilis\xE9e pour la capacit\xE9 d\xE9doublement', type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/33854984/q10B3KtWsCxcMczLo4BSUw/thumb.png?1496303265" }, image_ombre: { - explications: "Image utilisée pour l'ombre mortelle", + explications: "Image utilis\xE9e pour l'ombre mortelle", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/2781735/LcllgIHvqvu0HAbWdXZbJQ/thumb.png?13900368485" }, image_arbre: { - explications: "Image utilisée pour la forme d'arbre", + explications: "Image utilis\xE9e pour la forme d'arbre", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/52767134/KEGYUXeKnxZr5dbDwQEO4Q/thumb.png?15248300835" }, image_mur_de_force: { - explication: "Image utilisée pour un mur de force sphérique", + explication: "Image utilis\xE9e pour un mur de force sph\xE9rique", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/33213510/5r3NGSso1QBJMJewTEKv0A/thumb.png?1495195634" }, image_mur_de_vent: { - explication: "Image utilisée pour un mur de vent sphérique", + explication: "Image utilis\xE9e pour un mur de vent sph\xE9rique", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/308931095/X5zH4itb9QI9La8O7KfMBQ/thumb.png?1665585092" }, prison_vegetale: { - explication: "Image utilisée pour la prison végétale", + explication: "Image utilis\xE9e pour la prison v\xE9g\xE9tale", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/254738719/c97DFw6JlEePDVXBf-MPsA/thumb.png?1636471250" }, zone_de_vie: { - explication: "Image utilisée pour les zones de vie", + explication: "Image utilis\xE9e pour les zones de vie", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/349749304/q3q75jWu9Izlci5YB688WA/thumb.png?1689005544" } } }, sons: { - explications: "Sons par défaut", + explications: "Sons par d\xE9faut", type: 'options', val: { attaque_echec_critique: { - explication: "Son utilisé pour les échecs critiques d'attaques", + explication: "Son utilis\xE9 pour les \xE9checs critiques d'attaques", type: 'son', val: '' }, attaque_reussite_critique: { - explication: "Son utilisé pour les réussites critiques d'attaques", + explication: "Son utilis\xE9 pour les r\xE9ussites critiques d'attaques", type: 'son', val: '' } } }, macros_a_jour: { - explications: "Met automatiquement les macros à jour", + explications: "Met automatiquement les macros \xE0 jour", type: 'bool', val: true } @@ -416,43 +417,43 @@ var COFantasy = COFantasy || function() { } } - //Liste de tables par défaut + //Liste de tables par d\xE9faut const gameTables = [{ name: "Echec-Critique-Contact", showplayers: false, items: [{ - name: "FOR - Bousculé : le personnage est renversé par son adversaire. Il subit un dé malus au test de FOR si l’adversaire " + - "est d’une catégorie de taille supérieure et bénéficie d’un dé bonus dans le cas inverse. " + - "Il subit une attaque gratuite de la part d’un adversaire pendant qu’il est étalé au sol (-5 en DEF).", + name: "FOR - Bouscul\xE9 : le personnage est renvers\xE9 par son adversaire. Il subit un d\xE9 malus au test de FOR si l\x2019adversaire " + + "est d\x2019une cat\xE9gorie de taille sup\xE9rieure et b\xE9n\xE9ficie d\x2019un d\xE9 bonus dans le cas inverse. " + + "Il subit une attaque gratuite de la part d\x2019un adversaire pendant qu\x2019il est \xE9tal\xE9 au sol (-5 en DEF).", weight: 1, }, { - name: "DEX - Maladresse : le personnage laisse tomber au sol l'objet avec lequel il attaque. S’il essaye de le ramasser, " + + name: "DEX - Maladresse : le personnage laisse tomber au sol l'objet avec lequel il attaque. S\x2019il essaye de le ramasser, " + "il subit une attaque gratuite.", weight: 1, }, { - name: "CON - Coup de mou: le personnage subit l’état affaibli pendant 3 rounds. Ou il peut annuler cet état en reprenant" + - "son souffle par une action limitée.", + name: "CON - Coup de mou: le personnage subit l\x2019\xE9tat affaibli pendant 3 rounds. Ou il peut annuler cet \xE9tat en reprenant" + + "son souffle par une action limit\xE9e.", weight: 1, }, { - name: "INT - Erreur tactique : le personnage subit une attaque (gratuite) d’un adversaire à son contact.", + name: "INT - Erreur tactique : le personnage subit une attaque (gratuite) d\x2019un adversaire \xE0 son contact.", weight: 1, }, { name: "SAG - Distrait : le personnage se laisse distraire et ne voit pas venir la prochaine attaque, " + - "l’adversaire bénéficiera d’un bonus de +10.", + "l\x2019adversaire b\xE9n\xE9ficiera d\x2019un bonus de +10.", weight: 1, }, { - name: "CHA - Ridicule : le personnage fait un faux mouvement à la fois douloureux et ridicule, il subit " + - "l’état étourdi pendant un round pour reprendre contenance.", + name: "CHA - Ridicule : le personnage fait un faux mouvement \xE0 la fois douloureux et ridicule, il subit " + + "l\x2019\xE9tat \xE9tourdi pendant un round pour reprendre contenance.", weight: 1, }, { - name: "Votre arme se brise. S’il s’agit d’une arme magique, le dé DM est simplement réduit d'une catégorie " + - "(2d6/d12=>d10=>d8=>d6=>d4=>d3) jusqu’à la fin du combat.", + name: "Votre arme se brise. S\x2019il s\x2019agit d\x2019une arme magique, le d\xE9 DM est simplement r\xE9duit d'une cat\xE9gorie " + + "(2d6/d12=>d10=>d8=>d6=>d4=>d3) jusqu\x2019\xE0 la fin du combat.", weight: 1, }, { - name: "Une pièce d’armure bouge et elle devient plus gênante que protectrice : malus en DEF et en attaque pour le reste du combat. Cuir : -1, Maille : -2, Plaque -3.", + name: "Une pi\xE8ce d\x2019armure bouge et elle devient plus g\xEAnante que protectrice : malus en DEF et en attaque pour le reste du combat. Cuir : -1, Maille : -2, Plaque -3.", weight: 1, }, { - name: "Simple échec de l'attaque", + name: "Simple \xE9chec de l'attaque", weight: 12, }, ], }, ]; @@ -536,7 +537,7 @@ var COFantasy = COFantasy || function() { return false; } - // Attention, def, la valeur par défaut, doit être la même que sur la fiche + // Attention, def, la valeur par d\xE9faut, doit \xEAtre la m\xEAme que sur la fiche // personnage peut ne pas avoir de token function ficheAttribute(personnage, name, def) { let attr = charAttribute(personnage.charId, name, { @@ -555,7 +556,7 @@ var COFantasy = COFantasy || function() { return attrAsInt(attr, def, defPresent); } - //Il faut une valeur par défaut, qui correspond à celle de la fiche + //Il faut une valeur par d\xE9faut, qui correspond \xE0 celle de la fiche function ficheAttributeAsBool(personnage, name, def) { let attr = charAttribute(personnage.charId, name, { caseInsensitive: true @@ -564,7 +565,7 @@ var COFantasy = COFantasy || function() { return attrAsBool(attr); } - //Attention à ne pas utiliser si l'attribut ne dépend pas du token + //Attention \xE0 ne pas utiliser si l'attribut ne d\xE9pend pas du token //defPresent est optionnel //personnage peut ne pas avoir de token function attributeAsInt(personnage, name, def, defPresent) { @@ -661,7 +662,7 @@ var COFantasy = COFantasy || function() { function charPredicateAsBool(charId, name) { let pred = stateCOF.predicats[charId]; - if (pred) return pred; + if (pred) return pred[name]; let raw = ''; let attr = charAttribute(charId, 'predicats_script', { caseInsensitive: true @@ -705,8 +706,8 @@ var COFantasy = COFantasy || function() { } - //Problème : ça ne peut pas marcher pour les boucliers en main gauche - //car ça utilise lui-même un bouclier... + //Probl\xE8me : \xE7a ne peut pas marcher pour les boucliers en main gauche + //car \xE7a utilise lui-m\xEAme un bouclier... function getPredicates(perso) { if (perso.predicates === undefined) { const estMook = perso.token && perso.token.get('bar1_link') === ''; @@ -720,12 +721,12 @@ var COFantasy = COFantasy || function() { raw += '\n' + perso.arme.predicats; if (perso.armeGauche && perso.armeGauche.predicats) raw += '\n' + perso.armeGauche.predicats; - } else if (perso.arme) { //possible si appelé depuis armesEnMain + } else if (perso.arme) { //possible si appel\xE9 depuis armesEnMain if (perso.arme.predicats) raw += '\n' + perso.arme.predicats; - } else { //il faut chercher les prédicats des armes en main - //On n'appelle pas armesEnMain pour éviter la récursion - //et pour éviter trop de calcul + } else { //il faut chercher les pr\xE9dicats des armes en main + //On n'appelle pas armesEnMain pour \xE9viter la r\xE9cursion + //et pour \xE9viter trop de calcul let attrArmes = tokenAttribute(perso, 'armeEnMain'); if (attrArmes.length > 0) { let att; @@ -813,7 +814,7 @@ var COFantasy = COFantasy || function() { caseInsensitive: true }); if (typePerso.length > 0 && typePerso[0].get('current') == 'PNJ') - return; //Les fiches de PNJ sont les mêmes + return; //Les fiches de PNJ sont les m\xEAmes let setting = charAttribute(c.id, 'option_setting', { caseInsensitive: true }); @@ -825,7 +826,7 @@ var COFantasy = COFantasy || function() { else charsGenerique.push(c); }); if (charsArran.length <= charsGenerique.length) { - log("Utilisation des règles COF génériques"); + log("Utilisation des r\xE8gles COF g\xE9n\xE9riques"); if (charsArran.length > 0) { error("Attention, des personnages suivent les options de jeu des Terres d'Arran (voir le log pour la liste)", charsArran); charsArran.forEach(function(c) { @@ -837,7 +838,7 @@ var COFantasy = COFantasy || function() { } return; } - log("Utilisation des règles des Terres d'Arran"); + log("Utilisation des r\xE8gles des Terres d'Arran"); if (charsGenerique.length > 0) { error("Attention, des personnages ne suivent pas les options de jeu des Terres d'Arran (voir le log pour la liste)", charsGenerique); charsGenerique.forEach(function(c) { @@ -871,7 +872,7 @@ var COFantasy = COFantasy || function() { effet_de_marker[m.tag] = effet; } else if (ms) { if (effet_de_marker[ms] && effet_de_marker[ms] != effet) { - sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le même icone"); + sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le m\xEAme icone"); } effet_de_marker[ms] = effet; } else { @@ -882,7 +883,7 @@ var COFantasy = COFantasy || function() { function splitIdName(idn) { let pos = idn.indexOf(' '); if (pos < 1 || pos >= idn.length) { - error("idName mal formé", idn); + error("idName mal form\xE9", idn); return; } let name = idn.substring(pos + 1); @@ -892,8 +893,8 @@ var COFantasy = COFantasy || function() { }; } - //Renvoie le token et le charId. Si l'id ne correspond à rien, cherche si - //on trouve un nom de token, sur la page passée en argument (ou sinon + //Renvoie le token et le charId. Si l'id ne correspond \xE0 rien, cherche si + //on trouve un nom de token, sur la page pass\xE9e en argument (ou sinon //sur la page active de la campagne) function persoOfId(id, name, pageId, allPages) { let token = getObj('graphic', id); @@ -928,14 +929,14 @@ var COFantasy = COFantasy || function() { } else return undefined; } if (tokens.length > 1) { - error("Ambigüité sur le choix d'un token : il y a " + - tokens.length + " tokens nommés " + name, tokens); + error("Ambig\xFCit\xE9 sur le choix d'un token : il y a " + + tokens.length + " tokens nomm\xE9s " + name, tokens); } token = tokens[0]; } let charId = token.get('represents'); if (charId === '') { - error("le token sélectionné ne représente pas de personnage", token); + error("le token s\xE9lectionn\xE9 ne repr\xE9sente pas de personnage", token); return undefined; } return { @@ -944,7 +945,7 @@ var COFantasy = COFantasy || function() { }; } - //Retourne le perso correspondant à un token id suivi du nom de token + //Retourne le perso correspondant \xE0 un token id suivi du nom de token //Permet d'avoir une information robuste en cas d'interruption du script //peuple tokName function persoOfIdName(idn, pageId, allPages) { @@ -952,7 +953,7 @@ var COFantasy = COFantasy || function() { if (sp === undefined) return; let perso = persoOfId(sp.id, sp.name, pageId, allPages); if (perso === undefined) { - log("Impossible de trouver le personnage correspondant à " + sp.name); + log("Impossible de trouver le personnage correspondant \xE0 " + sp.name); return; } perso.tokName = perso.token.get('name'); @@ -989,16 +990,17 @@ var COFantasy = COFantasy || function() { roundMarker.remove(); roundMarker = undefined; stateCOF.roundMarkerId = undefined; - } else if (stateCOF.roundMarkerId) { + } else { + stateCOF.roundMarkerId = undefined; let roundMarkers = findObjs({ _type: 'graphic', represents: '', name: 'Init marker', + layer: 'map', }); roundMarkers.forEach(function(rm) { rm.remove(); }); - stateCOF.roundMarkerId = undefined; } } @@ -1010,7 +1012,7 @@ var COFantasy = COFantasy || function() { } if (sync != threadSync) return; if (token) { - // Cas spéciaux du cavaliers + // Cas sp\xE9ciaux du cavaliers let pageId = token.get('pageid'); let personnage = persoOfId(token.id); let monteSur = tokenAttribute(personnage, 'monteSur'); @@ -1049,7 +1051,7 @@ var COFantasy = COFantasy || function() { return false; }); } catch (uriError) { - log("Erreur de décodage URI dans la note GM de " + token.get('name') + " : " + gmNotes); + log("Erreur de d\xE9codage URI dans la note GM de " + token.get('name') + " : " + gmNotes); } roundMarker = createObj('graphic', roundMarkerSpec); if (roundMarker === undefined && localImage) { @@ -1063,12 +1065,12 @@ var COFantasy = COFantasy || function() { roundMarker = createObj('graphic', roundMarkerSpec); } if (roundMarker === undefined) { - error("Impossible de créer le token pour l'aura dynamique", roundMarkerSpec); + error("Impossible de cr\xE9er le token pour l'aura dynamique", roundMarkerSpec); return false; } stateCOF.roundMarkerId = roundMarker.id; if (roundMarkerSpec.layer === 'map') toFront(roundMarker); - // Ne pas amener une monture montée en avant pour éviter de cacher le cavalier + // Ne pas amener une monture mont\xE9e en avant pour \xE9viter de cacher le cavalier if (cavalier && monture) { toFront(monture.token); toFront(cavalier.token); @@ -1096,7 +1098,7 @@ var COFantasy = COFantasy || function() { token.set('aura2_radius', ''); token.set('showplayers_aura2', false); } else { - // Cas des tokens personnalisés + // Cas des tokens personnalis\xE9s if (statusForInitEnemy && statusForInitAlly) { token.set(statusForInitAlly, false); token.set(statusForInitEnemy, false); @@ -1104,14 +1106,75 @@ var COFantasy = COFantasy || function() { } } - //Appelé au lancement du script, mise à jour de certaines variables globales + function trouveOuCreeCible() { + let persos = findObjs({ + _type: 'character', + name: 'Cible', + controlledby: 'all' + }); + if (persos.length > 0) return persos[0]; + let pages = findObjs({ + _type: 'page' + }); + if (pages.length > 0) { + let pageId = pages[0].id; + let charCible = createObj('character', { + name: 'Cible', + controlledby: 'all', + inplayerjournals: 'all', + avatar: 'https://s3.amazonaws.com/files.d20.io/images/33041174/5JdDVh-34C-kZglTE1aq-w/max.png?1494837870', + }); + if (charCible) { + let attrPV = charAttribute(charCible.id, 'PV', { + caseInsensitive: true + }); + if (attrPV.length > 0) attrPV = attrPV[0]; + else attrPV = createObj('attribute', { + name: 'PV', + characterid: charCible.id, + current: 0, + max: 0 + }); + let attrType = charAttribute(charCible.id, 'type_personnage', { + caseInsensitive: true + }); + if (attrType.length > 0) { + attrType[0].setWithWorker('current', 'PNJ'); + } else { + attrType = createObj('attribute', { + name: 'type_personnage', + characterid: charCible.id, + current: 'PJ', + }); + attrType.setWithWorker('current', 'PNJ'); + } + let tokenCible = createObj('graphic', { + name: 'Cible', + layer: 'objects', + _pageid: pageId, + imgsrc: 'https://s3.amazonaws.com/files.d20.io/images/33041174/5JdDVh-34C-kZglTE1aq-w/thumb.png?1494837870', + represents: charCible.id, + width: PIX_PER_UNIT, + height: PIX_PER_UNIT, + bar1_link: attrPV ? attrPV.id : '' + }); + if (tokenCible) { + setDefaultTokenForCharacter(charCible, tokenCible); + tokenCible.remove(); + } + return charCible; + } + } + } + + //Appel\xE9 au lancement du script, mise \xE0 jour de certaines variables globales function setStateCOF() { stateCOF = state.COFantasy; - stateCOF.predicats = {}; //prédicats par charId. + stateCOF.predicats = {}; //pr\xE9dicats par charId. if (stateCOF.roundMarkerId) { roundMarker = getObj('graphic', stateCOF.roundMarkerId); if (roundMarker === undefined) { - log("Le marqueur d'init a changé d'id"); + log("Le marqueur d'init a chang\xE9 d'id"); let roundMarkers = findObjs({ _type: 'graphic', represents: '', @@ -1141,68 +1204,10 @@ var COFantasy = COFantasy || function() { } } if (!stateCOF.personnageCibleCree) { - //On cherche si un personnage cible existe déjà - let persos = findObjs({ - _type: 'character', - name: 'Cible', - controlledby: 'all' - }); - if (persos.length === 0) { - let pages = findObjs({ - _type: 'page' - }); - if (pages.length > 0) { - let pageId = pages[0].id; - let charCible = createObj('character', { - name: 'Cible', - controlledby: 'all', - inplayerjournals: 'all', - avatar: 'https://s3.amazonaws.com/files.d20.io/images/33041174/5JdDVh-34C-kZglTE1aq-w/max.png?1494837870', - }); - if (charCible) { - let attrPV = charAttribute(charCible.id, 'PV', { - caseInsensitive: true - }); - if (attrPV.length > 0) attrPV = attrPV[0]; - else attrPV = createObj('attribute', { - name: 'PV', - characterid: charCible.id, - current: 0, - max: 0 - }); - let attrType = charAttribute(charCible.id, 'type_personnage', { - caseInsensitive: true - }); - if (attrType.length > 0) { - attrType[0].setWithWorker('current', 'PNJ'); - } else { - attrType = createObj('attribute', { - name: 'type_personnage', - characterid: charCible.id, - current: 'PJ', - }); - attrType.setWithWorker('current', 'PNJ'); - } - let tokenCible = createObj('graphic', { - name: 'Cible', - layer: 'objects', - _pageid: pageId, - imgsrc: 'https://s3.amazonaws.com/files.d20.io/images/33041174/5JdDVh-34C-kZglTE1aq-w/thumb.png?1494837870', - represents: charCible.id, - width: PIX_PER_UNIT, - height: PIX_PER_UNIT, - bar1_link: attrPV ? attrPV.id : '' - }); - if (tokenCible) { - setDefaultTokenForCharacter(charCible, tokenCible); - tokenCible.remove(); - } - } - } - } + trouveOuCreeCible(); stateCOF.personnageCibleCree = true; } - //Création des tables par défaut + //Cr\xE9ation des tables par d\xE9faut if (!stateCOF.tablesCrees) { let allTables = findObjs({ _type: 'rollabletable', @@ -1259,7 +1264,7 @@ var COFantasy = COFantasy || function() { m.set('visibleto', ngm.visibleto); if (ngm.istokenaction != gm.istokenaction && m.get('istokenaction') == gm.istokenaction) m.set('istokenaction', ngm.istokenaction); - sendChat('COF', '/w GM Macro ' + ngm.name + ' mise à jour.'); + sendChat('COF', '/w GM Macro ' + ngm.name + ' mise \xE0 jour.'); }); } else { ngm = gameMacros.find(function(ngm) { @@ -1278,14 +1283,14 @@ var COFantasy = COFantasy || function() { m.set('visibleto', ngm.visibleto); if (ngm.istokenaction != gm.istokenaction && m.get('istokenaction') == gm.istokenaction) m.set('istokenaction', ngm.istokenaction); - sendChat('COF', '/w GM Macro ' + ngm.name + ' mise à jour.'); + sendChat('COF', '/w GM Macro ' + ngm.name + ' mise \xE0 jour.'); }); } else { macros.forEach(function(m) { if (m.get('name') != gm.name) return; if (m.get('action') != gm.action) return; m.remove(); - sendChat('COF', '/w GM Macro ' + gm.name + ' effacée.'); + sendChat('COF', '/w GM Macro ' + gm.name + ' effac\xE9e.'); }); } } @@ -1301,7 +1306,7 @@ var COFantasy = COFantasy || function() { return macro.get('name') == ngm.name; }); if (prev === undefined) { - sendChat('COF', '/w GM Macro ' + ngm.name + ' créée.'); + sendChat('COF', '/w GM Macro ' + ngm.name + ' cr\xE9\xE9e.'); if (ngm.inBar) inBar.push(ngm.name); mjs.forEach(function(playerId, i) { if (i === 0 || ngm.visibleto === '') { @@ -1313,10 +1318,10 @@ var COFantasy = COFantasy || function() { } }); } else { - //Peut-être la première fois, vérifier les macros + //Peut-\xEAtre la premi\xE8re fois, v\xE9rifier les macros if (stateCOF.macros) { - //ancienne version, et on avait copié les macros - //on enlève juste Escalier, et on remplace par Monter et Descendre + //ancienne version, et on avait copi\xE9 les macros + //on enl\xE8ve juste Escalier, et on remplace par Monter et Descendre let mesc = macros.find(function(m) { return m.get('name') == 'Escalier'; }); @@ -1346,7 +1351,7 @@ var COFantasy = COFantasy || function() { return macro.get('name') == m.name; }); if (prev === undefined) { - sendChat('COF', '/w GM Macro ' + m.name + ' créée.'); + sendChat('COF', '/w GM Macro ' + m.name + ' cr\xE9\xE9e.'); if (m.inBar) inBar.push(m.name); mjs.forEach(function(playerId, i) { if (i === 0 || m.visibleto === '') { @@ -1359,16 +1364,16 @@ var COFantasy = COFantasy || function() { } } if (inBar.length > 0) { - sendChat('COF', "/w GM Macros à mettre dans la barre d'action du MJ : " + inBar.join(', ')); + sendChat('COF', "/w GM Macros \xE0 mettre dans la barre d'action du MJ : " + inBar.join(', ')); } stateCOF.gameMacros = gameMacros; } - // Récupération des token Markers attachés à la campagne image, nom, tag, Id + // R\xE9cup\xE9ration des token Markers attach\xE9s \xE0 la campagne image, nom, tag, Id const markers = JSON.parse(Campaign().get('token_markers')); markers.forEach(function(m) { markerCatalog[m.name] = m; }); - // Option Markers personnalisés activé + // Option Markers personnalis\xE9s activ\xE9 if (stateCOF.options.affichage.val.markers_personnalises.val) { const cof_states_perso = { assomme: 'status_cof-assomme', @@ -1386,10 +1391,10 @@ var COFantasy = COFantasy || function() { blesse: 'status_cof-blesse', encombre: 'status_cof-encombre', penombre: 'status_cof-penombre', - //enseveli: 'status_edge-crack' -> À dessiner + //enseveli: 'status_edge-crack' -> \xC0 dessiner chef: 'status_cof-chef', }; - // On boucle sur la liste des états pour vérifier que les markers sont bien présents ! + // On boucle sur la liste des \xE9tats pour v\xE9rifier que les markers sont bien pr\xE9sents ! let markersAbsents = []; let ancientSet = true; for (let etat in cof_states_perso) { @@ -1431,7 +1436,7 @@ var COFantasy = COFantasy || function() { default: if (ms) { if (effet_de_marker[ms] && effet_de_marker[ms] != effet) { - sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le même icone"); + sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le m\xEAme icone"); } effet_de_marker[ms] = effet; } @@ -1447,7 +1452,7 @@ var COFantasy = COFantasy || function() { default: if (ms) { if (effet_de_marker[ms] && effet_de_marker[ms] != effet) { - sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le même icone"); + sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le m\xEAme icone"); } effet_de_marker[ms] = effet; } @@ -1457,9 +1462,9 @@ var COFantasy = COFantasy || function() { markersAbsents.forEach(function(m) { log("Marker " + m + " introuvable"); }); - log("Markers personnalisés activés."); + log("Markers personnalis\xE9s activ\xE9s."); } else { - log("Utilisation des markers par défaut"); + log("Utilisation des markers par d\xE9faut"); } } //Construction de la table markers => etat @@ -1478,7 +1483,7 @@ var COFantasy = COFantasy || function() { return res; } - // retourne un tableau contenant la liste des ID de joueurs connectés controllant le personnage lié au Token + // retourne un tableau contenant la liste des ID de joueurs connect\xE9s controllant le personnage li\xE9 au Token function getPlayerIds(perso) { let character = getObj('character', perso.charId); if (character === undefined) return; @@ -1527,7 +1532,7 @@ var COFantasy = COFantasy || function() { return res; } - //PNJ au sens de la fiche utilisée, pas forcément en jeu + //PNJ au sens de la fiche utilis\xE9e, pas forc\xE9ment en jeu //perso peut ne pas avoir de token function persoEstPNJ(perso) { if (perso.pnj) return true; @@ -1588,7 +1593,7 @@ var COFantasy = COFantasy || function() { return true; } - //Met le champ field à value du token dans evt, pour permettre le undo + //Met le champ field \xE0 value du token dans evt, pour permettre le undo //Retourne evt.affectes[token.id] function affectToken(token, field, value, evt) { evt.affectes = evt.affectes || {}; @@ -1658,7 +1663,7 @@ var COFantasy = COFantasy || function() { sendChat(dest, msg); } - //Chuchote le message à tous les joueurs présents qui controllent le + //Chuchote le message \xE0 tous les joueurs pr\xE9sents qui controllent le //personnage, plus le MJ function whisperChar(charId, msg) { let character = getObj('character', charId); @@ -1785,7 +1790,7 @@ var COFantasy = COFantasy || function() { // resultatDesSeuls (rempli par la fonction si true) //Renvoie 1dk + bonus, avec le texte //champs val et roll - //de peut être un nombre > 0 ou bien le résultat de parseDice + //de peut \xEAtre un nombre > 0 ou bien le r\xE9sultat de parseDice function rollDePlus(de, options) { options = options || {}; options.nbDes = options.nbDes || 1; @@ -1846,7 +1851,7 @@ var COFantasy = COFantasy || function() { return res; } - //Si evt est défini, alors on considère qu'il faut y mettre la valeur actuelle + //Si evt est d\xE9fini, alors on consid\xE8re qu'il faut y mettre la valeur actuelle function updateCurrentBar(perso, barNumber, val, evt, maxVal) { let token = perso.token; let prevToken; @@ -1893,7 +1898,7 @@ var COFantasy = COFantasy || function() { if (maxVal) aset.max = maxVal; attr.setWithWorker(aset); if (HTdeclared) HealthColors.Update(token, prevToken); - //Gestion du lien des PVs entre familier et son maître + //Gestion du lien des PVs entre familier et son ma\xEEtre if (barNumber == 1) { let nomPersoLie = predicateAsBool(perso, 'PVPartagesAvec'); if (nomPersoLie) { @@ -2046,6 +2051,7 @@ var COFantasy = COFantasy || function() { light_losangle: token.get('light_losangle'), light_multiplier: token.get('light_multiplier'), adv_fow_view_distance: token.get('adv_fow_view_distance'), + gmnotes: token.get('gmnotes'), }; } @@ -2054,7 +2060,7 @@ var COFantasy = COFantasy || function() { case 'FOR': return 'force'; case 'DEX': - if (accent) return 'dextérité'; + if (accent) return 'dext\xE9rit\xE9'; return 'dexterite'; case 'CON': return 'constitution'; @@ -2073,9 +2079,9 @@ var COFantasy = COFantasy || function() { return 'pnj_' + m.toLowerCase(); } - //Retourne le mod de la caractéristque entière. + //Retourne le mod de la caract\xE9ristque enti\xE8re. //si carac n'est pas une carac, retourne 0 - //perso peut ne pas avoir de token ou être juste un charId + //perso peut ne pas avoir de token ou \xEAtre juste un charId function modCarac(perso, carac) { if (perso.charId === undefined) perso = { charId: perso @@ -2133,11 +2139,11 @@ var COFantasy = COFantasy || function() { } //options peut contenir - // msg: un message à afficher + // msg: un message \xE0 afficher // maxVal: la valeur max de l'attribut - // secret: le message n'est pas affiché pour tout le monde. - // charAttr: si présent, on utilise un attribut de personnage - // renvoie l'attribut créé ou mis à jour + // secret: le message n'est pas affich\xE9 pour tout le monde. + // charAttr: si pr\xE9sent, on utilise un attribut de personnage + // renvoie l'attribut cr\xE9\xE9 ou mis \xE0 jour function setTokenAttr(personnage, attribute, value, evt, options) { let charId = personnage.charId; let token = personnage.token; @@ -2157,7 +2163,7 @@ var COFantasy = COFantasy || function() { }; let name = 'inconnu'; if (token) name = token.get('name'); - error("Création d'un attribut undefined pour " + name, args); + error("Cr\xE9ation d'un attribut undefined pour " + name, args); return; } let attr = findObjs({ @@ -2185,7 +2191,7 @@ var COFantasy = COFantasy || function() { let taille = taillePersonnage(personnage, 4); if (taille == 5) { arme.deuxMains = false; - sendPerso(personnage, "peut maintenant tenir " + arme.name + " à une main"); + sendPerso(personnage, "peut maintenant tenir " + arme.name + " \xE0 une main"); degainerArme(personnage, arme.label, evt); } } @@ -2199,11 +2205,11 @@ var COFantasy = COFantasy || function() { token.set('height', height); break; case 'formeDArbre': - //On copie les PVs pour pouvoir les restaurer à la fin de l'effet + //On copie les PVs pour pouvoir les restaurer \xE0 la fin de l'effet setTokenAttr(personnage, 'anciensPV', token.get('bar1_value'), evt, { maxVal: token.get('bar1_max') }); - //On va créer une copie de token, mais avec une image d'arbre + //On va cr\xE9er une copie de token, mais avec une image d'arbre let tokenFields = getTokenFields(token, pageId, personnage.charId); let tokenArbre; let imageArbre = predicateAsBool(personnage, 'tokenFormeDArbre'); @@ -2218,7 +2224,7 @@ var COFantasy = COFantasy || function() { if (tokenArbre) { evt.tokens = evt.tokens || []; evt.tokens.push(tokenArbre); - //On met l'ancien token dans le gmlayer, car si l'image vient du marketplace, il est impossible de le recréer depuis l'API + //On met l'ancien token dans le gmlayer, car si l'image vient du marketplace, il est impossible de le recr\xE9er depuis l'API setToken(token, 'layer', 'gmlayer', evt); setTokenAttr(personnage, 'changementDeToken', true, evt); replaceInTurnTracker(token.id, tokenArbre.id, evt); @@ -2316,7 +2322,7 @@ var COFantasy = COFantasy || function() { return attr; } - // evt peut être undefined + // evt peut \xEAtre undefined // options peut avoir les champs msg et secret function removeTokenAttr(personnage, attribute, evt, options) { attribute = fullAttributeName(personnage, attribute, options); @@ -2353,8 +2359,8 @@ var COFantasy = COFantasy || function() { }); } - //cherche l'attribut attribute de valeur par défaut def - //et lui ajoute la valeur val. Crée l'attribut si besoin + //cherche l'attribut attribute de valeur par d\xE9faut def + //et lui ajoute la valeur val. Cr\xE9e l'attribut si besoin //retourne la nouvelle valeur de l'attribut function addToAttributeAsInt(perso, attribute, def, val, evt) { evt.attributes = evt.attributes || []; @@ -2400,11 +2406,11 @@ var COFantasy = COFantasy || function() { //options: //fromTemp si on est en train de supprimer un effet temporaire - //affectToken si on a déjà changé le statusmarkers (on vient donc d'un changement à la main d'un marker + //affectToken si on a d\xE9j\xE0 chang\xE9 le statusmarkers (on vient donc d'un changement \xE0 la main d'un marker function setState(personnage, etat, value, evt, options) { let token = personnage.token; if (value && predicateAsBool(personnage, 'immunite_' + etat)) { - sendPerso(personnage, 'ne peut pas être ' + stringOfEtat(etat, personnage)); + sendPerso(personnage, 'ne peut pas \xEAtre ' + stringOfEtat(etat, personnage)); return false; } options = options || {}; @@ -2458,7 +2464,7 @@ var COFantasy = COFantasy || function() { } } } - if (!value) { //On enlève le save si il y en a un + if (!value) { //On enl\xE8ve le save si il y en a un removeTokenAttr(personnage, etat + 'Save', evt); removeTokenAttr(personnage, etat + 'SaveParTour', evt); } @@ -2484,7 +2490,7 @@ var COFantasy = COFantasy || function() { token.set('light_losangle', 0); } //Normalement, ne peut plus suivre personne ? - //Si il peut parce qu'il touche ou tient une corde, réutiliser la macro + //Si il peut parce qu'il touche ou tient une corde, r\xE9utiliser la macro //pour suivre nePlusSuivre(personnage, pageId, evt); } else { @@ -2501,7 +2507,7 @@ var COFantasy = COFantasy || function() { let attrInvisible = tokenAttribute(personnage, 'tokenInvisible'); if (value) { if (attrInvisible.length === 0) { - //On va créer une copie de token, mais avec une image invisible et aura visible seulement de ceux qui contrôlent le token + //On va cr\xE9er une copie de token, mais avec une image invisible et aura visible seulement de ceux qui contr\xF4lent le token let tokenFields = getTokenFields(token, pageId, personnage.charId); tokenFields.layer = 'objects'; tokenFields.aura1_radius = 0; @@ -2522,7 +2528,7 @@ var COFantasy = COFantasy || function() { } evt.tokens = evt.tokens || []; evt.tokens.push(tokenInvisible); - //On met l'ancien token dans le gmlayer, car si l'image vient du marketplace, il est impossible de le recréer depuis l'API + //On met l'ancien token dans le gmlayer, car si l'image vient du marketplace, il est impossible de le recr\xE9er depuis l'API setToken(token, 'layer', 'gmlayer', evt); setTokenAttr(personnage, 'tokenInvisible', token.id, evt, { maxVal: tokenInvisible.id @@ -2536,7 +2542,7 @@ var COFantasy = COFantasy || function() { } } } - } else { //On enlève l'état invisible + } else { //On enl\xE8ve l'\xE9tat invisible if (attrInvisible.length > 0) { let tokenOriginel = getObj('graphic', attrInvisible[0].get('current')); if (!tokenOriginel) { @@ -2553,7 +2559,7 @@ var COFantasy = COFantasy || function() { }); if (tokenOriginel.length > 0) tokenOriginel = tokenOriginel[0]; else { - error("Impossible de retrouver le token de départ de " + token.get('name') + " quand on enlève l'état invisible", attrInvisible); + error("Impossible de retrouver le token de d\xE9part de " + token.get('name') + " quand on enl\xE8ve l'\xE9tat invisible", attrInvisible); tokenOriginel = false; } } @@ -2573,7 +2579,7 @@ var COFantasy = COFantasy || function() { }); if (tokenCourant.length > 0) tokenCourant = tokenCourant[0]; else { - error("Impossible de retrouver le token visible de " + token.get('name') + " quand on enlève l'état invisible", attrInvisible); + error("Impossible de retrouver le token visible de " + token.get('name') + " quand on enl\xE8ve l'\xE9tat invisible", attrInvisible); tokenCourant = false; } } @@ -2613,7 +2619,7 @@ var COFantasy = COFantasy || function() { switch (etat) { case 'mort': { - //On s'assure de mettre les PV de la cible à 0 (pour les insta kills sans dommages) + //On s'assure de mettre les PV de la cible \xE0 0 (pour les insta kills sans dommages) if (token.get('bar1_value') > 0) updateCurrentBar(personnage, 1, 0, evt); nePlusSuivre(personnage, pageId, evt); lockToken(personnage, evt); @@ -2632,14 +2638,14 @@ var COFantasy = COFantasy || function() { removeTokenAttr(personnage, 'estMontePar', evt); removeTokenAttr(personnage, 'positionSurMonture', evt); } - //On libère les personnages enveloppés, si il y en a. + //On lib\xE8re les personnages envelopp\xE9s, si il y en a. let attrEnveloppe = tokenAttribute(personnage, 'enveloppe'); attrEnveloppe.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); if (cible) { let envDM = a.get('max'); if (envDM.startsWith('etreinte')) { - //On a une étreinte, on enlève donc l'état immobilisé + //On a une \xE9treinte, on enl\xE8ve donc l'\xE9tat immobilis\xE9 setState(cible, 'immobilise', false, evt); } evt.deletedAttributes = evt.deletedAttributes || []; @@ -2650,7 +2656,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); } else if (cube.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + cube.tokName); + sendPerso(cible, 'se lib\xE8re de ' + cube.tokName); toFront(cible.token); evt.deletedAttributes.push(a); a.remove(); @@ -2661,14 +2667,14 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //Si le mort est enveloppé, il est relaché + //Si le mort est envelopp\xE9, il est relach\xE9 attrEnveloppe = tokenAttribute(personnage, 'enveloppePar'); attrEnveloppe.forEach(function(a) { let cube = persoOfIdName(a.get('current'), pageId); if (cube) { let envDiff = a.get('max'); if (envDiff.startsWith('etreinte')) { - //On a une étreinte, on enlève donc l'état immobilisé + //On a une \xE9treinte, on enl\xE8ve donc l'\xE9tat immobilis\xE9 setState(personnage, 'immobilise', false, evt); } evt.deletedAttributes = evt.deletedAttributes || []; @@ -2688,7 +2694,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages agrippés, si il y en a. + //On lib\xE8re les personnages agripp\xE9s, si il y en a. let attrAgrippe = tokenAttribute(personnage, 'agrippe'); attrAgrippe.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2698,7 +2704,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); if (a.get('max')) setState(cible, 'immobilise', false, evt); evt.deletedAttributes.push(a); @@ -2710,7 +2716,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages dévorés, si il y en a. + //On lib\xE8re les personnages d\xE9vor\xE9s, si il y en a. let attrDevore = tokenAttribute(personnage, 'devore'); attrDevore.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2720,7 +2726,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); setState(cible, 'immobilise', false, evt); evt.deletedAttributes.push(a); @@ -2731,7 +2737,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages écrasés, si il y en a. + //On lib\xE8re les personnages \xE9cras\xE9s, si il y en a. let attrEcrase = tokenAttribute(personnage, 'ecrase'); attrEcrase.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2741,7 +2747,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); evt.deletedAttributes.push(a); a.remove(); @@ -2751,7 +2757,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages avalés, si il y en a. + //On lib\xE8re les personnages aval\xE9s, si il y en a. let attrGobe = tokenAttribute(personnage, 'aGobe'); attrGobe.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2772,7 +2778,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages sous étreinte et immolation + //On lib\xE8re les personnages sous \xE9treinte et immolation let attrEtreinteImmole = tokenAttribute(personnage, 'etreinteImmole'); attrEtreinteImmole.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2782,7 +2788,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); setState(cible, 'immobilise', false, evt); evt.deletedAttributes.push(a); @@ -2793,7 +2799,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages sous étreinte de scorpion + //On lib\xE8re les personnages sous \xE9treinte de scorpion let attrEtreinteScorpion = tokenAttribute(personnage, 'etreinteScorpionSur'); attrEtreinteScorpion.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2804,7 +2810,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); evt.deletedAttributes.push(a); a.remove(); @@ -2852,7 +2858,7 @@ var COFantasy = COFantasy || function() { attaqueExplosion(msg); } } - //On termine les effets temporaires liés au personnage + //On termine les effets temporaires li\xE9s au personnage let etlAttr = tokenAttribute(personnage, 'effetsTemporairesLies'); if (etlAttr.length > 0) { etlAttr = etlAttr[0]; @@ -2875,7 +2881,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(etlAttr); etlAttr.remove(); } - //On enlève les auras + //On enl\xE8ve les auras if (stateCOF.combat && (predicateAsBool(personnage, 'auraDrainDeForce') || attributeAsBool(personnage, 'aura')) ) { @@ -2895,7 +2901,7 @@ var COFantasy = COFantasy || function() { } else if (charAttributeAsBool(personnage, 'armeeConjuree')) { removeFromTurnTracker(personnage, evt); deleteTokenWithUndo(personnage.token, evt); - sendPerso(personnage, 'disparaît'); + sendPerso(personnage, 'dispara\xEEt'); let armeeChar = getObj('character', personnage.charId); if (armeeChar) { evt.deletedCharacters = evt.deletedCharacters || []; @@ -2915,7 +2921,7 @@ var COFantasy = COFantasy || function() { armeeChar.remove(); } } else if (!estNonVivant(personnage)) { - //Cherche si certains peuvent siphoner l'âme + //Cherche si certains peuvent siphoner l'\xE2me let allToks = findObjs({ _type: 'graphic', @@ -2923,7 +2929,7 @@ var COFantasy = COFantasy || function() { _subtype: 'token', layer: 'objects' }); - //On cherche d'abord si un siphon des âmes est prioritaire + //On cherche d'abord si un siphon des \xE2mes est prioritaire let prioriteSiphon = []; allToks = allToks.filter(function(tok) { if (tok.id == token.id) return false; @@ -2948,7 +2954,7 @@ var COFantasy = COFantasy || function() { let jetSiphon = "(1d6"; if (bonus > 0) jetSiphon += '+' + bonus; jetSiphon += ")"; - sendChat('COF', "/w GM " + personnage.token.get('name') + " est un personnage joueur, possible qu'il ne soit pas vraiment mort mais juste inconscient. S'il est vraiment mort, faire le siphon des âmes par " + siphoneur.token.get('name') + " à la main " + jetSiphon); + sendChat('COF', "/w GM " + personnage.token.get('name') + " est un personnage joueur, possible qu'il ne soit pas vraiment mort mais juste inconscient. S'il est vraiment mort, faire le siphon des \xE2mes par " + siphoneur.token.get('name') + " \xE0 la main " + jetSiphon); } else { prioriteSiphon.sort(function(a, b) { return b.priorite - a.priorite; @@ -2963,7 +2969,7 @@ var COFantasy = COFantasy || function() { } let p = x.perso; if (fractionPriorite < 1) { - whisperChar(p.charId, "ne réussit pas à siphoner l'âme de " + token.get('name') + " un autre pouvoir l'a siphonée avant lui"); + whisperChar(p.charId, "ne r\xE9ussit pas \xE0 siphoner l'\xE2me de " + token.get('name') + " un autre pouvoir l'a siphon\xE9e avant lui"); return true; } let bonus = predicateAsInt(p, 'siphonDesAmes', 0); @@ -2973,7 +2979,7 @@ var COFantasy = COFantasy || function() { nbDes }); let soinTotal = soin.val; - //Le montant total des soins ne peut excéder les pv max du personnage qui vient de mourrir. + //Le montant total des soins ne peut exc\xE9der les pv max du personnage qui vient de mourrir. let display = true; if (soinTotal > pvMax) { soinTotal = pvMax; @@ -2982,12 +2988,12 @@ var COFantasy = COFantasy || function() { if (soinTotal < 1) soinTotal = 1; soin.val = soinTotal; soin.val = Math.ceil(soin.val * fractionPriorite / 100); - //Cherche si il y a un perso lié + //Cherche si il y a un perso li\xE9 let lie = personnageAmeLiee(p, pageId, allToks); soigneToken(p, soin.val, evt, function(s) { - let siphMsg = "siphone l'âme de " + token.get('name') + - ". " + onGenre(p, 'Il', 'Elle') + " récupère "; + let siphMsg = "siphone l'\xE2me de " + token.get('name') + + ". " + onGenre(p, 'Il', 'Elle') + " r\xE9cup\xE8re "; if (s == soinTotal) { if (display) siphMsg += soin.roll + " pv."; else siphMsg += s + " pv (jet " + soin.roll + ")."; @@ -3002,8 +3008,8 @@ var COFantasy = COFantasy || function() { let soin2 = soinTotal - s + Math.floor(s / 5); soigneToken(lie, soin2, evt, function(s) { let siphMsg = - "récupère une partie de l'âme de " + token.get('name') + - " siphonée par " + nomPerso(p) + ". " + onGenre(lie, 'Il', 'Elle') + " récupère " + s + " pv."; + "r\xE9cup\xE8re une partie de l'\xE2me de " + token.get('name') + + " siphon\xE9e par " + nomPerso(p) + ". " + onGenre(lie, 'Il', 'Elle') + " r\xE9cup\xE8re " + s + " pv."; if (s == soin2) { fraction = 0; } else { @@ -3012,15 +3018,15 @@ var COFantasy = COFantasy || function() { pvMax -= s; whisperChar(lie.charId, siphMsg); }, function() { - whisperChar(lie.charId, "sent qu'" + onGenre(lie, 'il', 'elle') + " aurait pu bénéficier d'une âme"); + whisperChar(lie.charId, "sent qu'" + onGenre(lie, 'il', 'elle') + " aurait pu b\xE9n\xE9ficier d'une \xE2me"); }); } }, function() { if (lie) { soigneToken(lie, soin.val, evt, function(s) { - let siphMsg = "siphone l'âme de " + token.get('name') + - " grâce à " + nomPerso(p) + ". " + onGenre(lie, 'Il', 'Elle') + " récupère "; + let siphMsg = "siphone l'\xE2me de " + token.get('name') + + " gr\xE2ce \xE0 " + nomPerso(p) + ". " + onGenre(lie, 'Il', 'Elle') + " r\xE9cup\xE8re "; if (s == soinTotal) { siphMsg += soin.roll + " pv."; fraction = 0; @@ -3032,11 +3038,11 @@ var COFantasy = COFantasy || function() { whisperChar(lie.charId, siphMsg); }, function() { whisperChar(p.charId, - "est déjà au maximum de point de vie. " + onGenre(p, 'Il', 'Elle') + " laisse échapper l'âme de " + token.get('name')); + "est d\xE9j\xE0 au maximum de point de vie. " + onGenre(p, 'Il', 'Elle') + " laisse \xE9chapper l'\xE2me de " + token.get('name')); }); } else { whisperChar(p.charId, - "est déjà au maximum de point de vie. " + onGenre(p, 'Il', 'Elle') + " laisse échapper l'âme de " + token.get('name')); + "est d\xE9j\xE0 au maximum de point de vie. " + onGenre(p, 'Il', 'Elle') + " laisse \xE9chapper l'\xE2me de " + token.get('name')); } }); }); @@ -3076,7 +3082,7 @@ var COFantasy = COFantasy || function() { } //fonction avec callback, mais synchrone - // n'ajoute pas evt à l'historique + // n'ajoute pas evt \xE0 l'historique function soigneToken(perso, soins, evt, callTrue, callMax, options) { options = options || {}; let token = perso.token; @@ -3113,7 +3119,7 @@ var COFantasy = COFantasy || function() { let ds = parseInt(a.get('current')); if (ds > 0) { if (an[0].length < 2) { - error("Match non trouvé pour les soins", an); + error("Match non trouv\xE9 pour les soins", an); return; } if (soinsImpossible.has(an[1])) { @@ -3181,7 +3187,7 @@ var COFantasy = COFantasy || function() { } } } - // On cherche si il y a des DM temporaires à soigner + // On cherche si il y a des DM temporaires \xE0 soigner if (bar1 > pvmax) { let hasMana = (ficheAttributeAsInt(perso, 'PM', 0) > 0); let dmgTemp; @@ -3226,7 +3232,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(perso, 'reactionAllergique')) { removeTokenAttr(perso, 'reactionAllergique', evt, { - msg: ": les soins mettent fin à la réaction allergique" + msg: ": les soins mettent fin \xE0 la r\xE9action allergique" }); } } @@ -3263,7 +3269,7 @@ var COFantasy = COFantasy || function() { return scale; } - // si le token est plus grand que thresh, réduit la distance + // si le token est plus grand que thresh, r\xE9duit la distance function tokenSize(tok, thresh) { let size = (tok.get('width') + tok.get('height')) / 2; if (size > thresh) return ((size - thresh) / 2); @@ -3309,7 +3315,7 @@ var COFantasy = COFantasy || function() { } //Distance en pixels entre un token et un segment - //le segment est donné par ses extrémités, sous forme de {x, y} + //le segment est donn\xE9 par ses extr\xE9mit\xE9s, sous forme de {x, y} function distancePixTokenSegment(token, pt1, pt2) { let pt = pointOfToken(token); let seg = { @@ -3319,26 +3325,26 @@ var COFantasy = COFantasy || function() { let vec = { x: pt.x - pt1.x, y: pt.y - pt1.y - }; //vecteur de pt1 à pt - //On regarde d'abord si le projeté de token sur (pt1, pt2) est dans le segment + }; //vecteur de pt1 \xE0 pt + //On regarde d'abord si le projet\xE9 de token sur (pt1, pt2) est dans le segment let ps = seg.x * vec.x + seg.y * vec.y; if (ps <= 0) { //On est avant pt1 return Math.sqrt(vec.x * vec.x + vec.y * vec.y); } let dseg = seg.x * seg.x + seg.y * seg.y; - if (ps >= dseg) { //On est après pt2, on retourne donc la distance pt pt2 + if (ps >= dseg) { //On est apr\xE8s pt2, on retourne donc la distance pt pt2 let x = pt.x - pt2.x; let y = pt.y - pt2.y; return Math.sqrt(x * x + y * y); } - //On calcule le déterminant de vec et seg + //On calcule le d\xE9terminant de vec et seg let det = vec.x * seg.y - vec.y * seg.x; //Et on divise par la longueur du segment return Math.abs(det) / Math.sqrt(dseg); } //options peut avoir les champs: - // - strict1 = true si on considère que tok1 doit avoir une taille nulle + // - strict1 = true si on consid\xE8re que tok1 doit avoir une taille nulle // - strict2 // - allonge function distanceCombat(tok1, tok2, pageId, options) { @@ -3346,7 +3352,7 @@ var COFantasy = COFantasy || function() { pageId = tok1.get('pageid'); } options = options || {}; - //perso montés + //perso mont\xE9s let pseudoTok1 = tok1; if (!options.strict1) { let perso1 = persoOfToken(tok1); @@ -3379,7 +3385,7 @@ var COFantasy = COFantasy || function() { } //Attention, seulement faire pour les tokens avec une image dans la librairie - //C'est toujours le cas pour un token créé par le script + //C'est toujours le cas pour un token cr\xE9\xE9 par le script function deleteTokenWithUndo(token, evt) { let tokenFields = getTokenFields(token); evt.deletedTokens = evt.deletedTokens || []; @@ -3387,8 +3393,8 @@ var COFantasy = COFantasy || function() { token.remove(); } - //L'argument effetC doit être le nom complet, pas la base - //evt.deletedAttributes doit être défini + //L'argument effetC doit \xEAtre le nom complet, pas la base + //evt.deletedAttributes doit \xEAtre d\xE9fini function enleverEffetAttribut(charId, effetC, attrName, extension, evt) { let attrSave = attributeExtending(charId, attrName, effetC, extension); attrSave. @@ -3398,14 +3404,14 @@ var COFantasy = COFantasy || function() { }); } - function finDEffet(attr, effet, attrName, charId, evt, options) { //L'effet arrive en fin de vie, doit être supprimé + function finDEffet(attr, effet, attrName, charId, evt, options) { //L'effet arrive en fin de vie, doit \xEAtre supprim\xE9 options = options || {}; evt.deletedAttributes = evt.deletedAttributes || []; let res; let newInit = []; let efComplet = effetComplet(effet, attrName); - //Si on a un attrSave, alors on a déjà imprimé le message de fin d'effet - if (options.attrSave) { //on a un attribut associé à supprimer) + //Si on a un attrSave, alors on a d\xE9j\xE0 imprim\xE9 le message de fin d'effet + if (options.attrSave) { //on a un attribut associ\xE9 \xE0 supprimer) evt.deletedAttributes.push(options.attrSave); options.attrSave.remove(); } else if (options.gardeAutresAttributs === undefined) { //On cherche si il y en a un @@ -3426,7 +3432,7 @@ var COFantasy = COFantasy || function() { let character; let combat = stateCOF.combat; switch (effet) { - case 'affecteParAura': //voir si l'aura est toujours là + case 'affecteParAura': //voir si l'aura est toujours l\xE0 if (combat && combat.auras && efComplet.length > 15) { let id = efComplet.substring(15, efComplet.length - 1); let aura = combat.auras.find(function(a) { @@ -3476,7 +3482,7 @@ var COFantasy = COFantasy || function() { if (arme && arme.armeDeGrand) { let taille = taillePersonnage(perso, 4); if (taille == 4 && arme.label != perso.attrArmeEnMain.get('max')) { - sendPerso(perso, "ne peut plus tenir " + arme.name + " à une main"); + sendPerso(perso, "ne peut plus tenir " + arme.name + " \xE0 une main"); degainerArme(perso, arme.label, evt, { deuxMains: true }); @@ -3675,22 +3681,22 @@ var COFantasy = COFantasy || function() { function(s) { options.print = function(m) {}; //Pour ne pas afficher le message final. let tempsEffectif = Math.ceil(s / regen); - sendPerso(perso, "récupère encore " + s + " PV en " + tempsEffectif + " tours."); + sendPerso(perso, "r\xE9cup\xE8re encore " + s + " PV en " + tempsEffectif + " tours."); }); } - //Régénération d'une carac physique affaiblie de 1d4, si il y en a. + //R\xE9g\xE9n\xE9ration d'une carac physique affaiblie de 1d4, si il y en a. if (attributeAsInt(perso, 'affaiblissementdeconstitution', 0) > 0) { let d4 = rollDePlus(4); diminueAffaiblissement(perso, 'constitution', d4.val, evt); - sendPerso(perso, "récupère " + d4.roll + " points de constitution"); + sendPerso(perso, "r\xE9cup\xE8re " + d4.roll + " points de constitution"); } else if (attributeAsInt(perso, 'affaiblissementdeforce', 0) > 0) { let d4 = rollDePlus(4); diminueAffaiblissement(perso, 'force', d4.val, evt); - sendPerso(perso, "récupère " + d4.roll + " points de force"); + sendPerso(perso, "r\xE9cup\xE8re " + d4.roll + " points de force"); } else if (attributeAsInt(perso, 'affaiblissementdedexterite', 0) > 0) { let d4 = rollDePlus(4); diminueAffaiblissement(perso, 'dexterite', d4.val, evt); - sendPerso(perso, "récupère " + d4.roll + " points de dextérité"); + sendPerso(perso, "r\xE9cup\xE8re " + d4.roll + " points de dext\xE9rit\xE9"); } }); break; @@ -3699,7 +3705,7 @@ var COFantasy = COFantasy || function() { case 'arbreAnime': case 'objetAnime': case 'degradationZombie': //effacer le personnage - //Dans le cas d'un Zombie, diminuer la limite du nécromant si nécessaire + //Dans le cas d'un Zombie, diminuer la limite du n\xE9cromant si n\xE9cessaire if (effet == 'degradationZombie') { let attrNecromant = charAttribute(charId, 'necromant'); if (attrNecromant.length > 0) { @@ -3811,7 +3817,7 @@ var COFantasy = COFantasy || function() { abilities: charAbilities, allies: [] }; - // Retrait du perso de toutes les listes d'alliés + // Retrait du perso de toutes les listes d'alli\xE9s for (const [perso, alliesPerso] of Object.entries(alliesParPerso)) { if (alliesPerso.has(charId)) { deletedChar.allies.push(perso); @@ -3903,7 +3909,7 @@ var COFantasy = COFantasy || function() { if (pv == 0) { //jshint ignore:line mort(perso, undefined, evt); } else { - //On note qu'il l'a déjà fait pour qu'il ne puisse le refaire dans le combat + //On note qu'il l'a d\xE9j\xE0 fait pour qu'il ne puisse le refaire dans le combat setTokenAttr(perso, 'aAgiAZeroPV', true, evt); } }); @@ -3947,7 +3953,7 @@ var COFantasy = COFantasy || function() { }; if (getState(perso, 'mort')) return; if (!combat) { - sendChat('', "Il restait un effet retardé " + effetRetarde + " qui devait se déclencher pour " + token.get('name')); + sendChat('', "Il restait un effet retard\xE9 " + effetRetarde + " qui devait se d\xE9clencher pour " + token.get('name')); return; } let duree = getIntValeurOfEffet(perso, efComplet, 1); @@ -3979,7 +3985,7 @@ var COFantasy = COFantasy || function() { charId: charId }; if (getState(perso, 'mort')) return; - whisperChar(charId, "Le poison commence à faire effet !"); + whisperChar(charId, "Le poison commence \xE0 faire effet !"); setTokenAttr(perso, 'poisonAffaiblissantLong', true, evt, {}); }); break; @@ -3988,7 +3994,7 @@ var COFantasy = COFantasy || function() { let messageRetarde = efComplet.substring(15, efComplet.length - 1); iterTokensOfAttribute(charId, options.pageId, efComplet, attrName, function(token) { whisperChar(charId, messageRetarde); - //Puis on regarde si il y a une valeur à afficher + //Puis on regarde si il y a une valeur \xE0 afficher let perso = { token: token, charId: charId @@ -4001,7 +4007,7 @@ var COFantasy = COFantasy || function() { break; case 'tenebres': iterTokensOfAttribute(charId, options.pageId, efComplet, attrName, function(token) { - //Puis on regarde si il y a une valeur à afficher + //Puis on regarde si il y a une valeur \xE0 afficher let perso = { token: token, charId: charId @@ -4013,7 +4019,7 @@ var COFantasy = COFantasy || function() { break; case 'brumes': iterTokensOfAttribute(charId, options.pageId, efComplet, attrName, function(token) { - //Puis on regarde si il y a une valeur à afficher + //Puis on regarde si il y a une valeur \xE0 afficher let perso = { token: token, charId: charId @@ -4106,7 +4112,7 @@ var COFantasy = COFantasy || function() { } evt.deletedAttributes.push(attr); attr.remove(); - //Débloque les tokens si l'effet les immobilisait + //D\xE9bloque les tokens si l'effet les immobilisait switch (effet) { case 'bloqueManoeuvre': case 'prisonVegetale': @@ -4133,7 +4139,7 @@ var COFantasy = COFantasy || function() { } } - //retourne le personnage du compagnon s'il est présent et actif + //retourne le personnage du compagnon s'il est pr\xE9sent et actif function compagnonPresent(personnage, nomCompagnon) { let compagnon = predicateAsBool(personnage, nomCompagnon); if (compagnon) { @@ -4201,7 +4207,7 @@ var COFantasy = COFantasy || function() { } //Pour savoir si un personnage est un personnage joueur - // -> fiche de PJ + dé de vie + token lié + controllé par au moins un joueur. + // -> fiche de PJ + d\xE9 de vie + token li\xE9 + controll\xE9 par au moins un joueur. function estPJ(perso) { if (persoEstPNJ(perso)) return false; let dv = ficheAttributeAsInt(perso, 'DV', 0); @@ -4221,50 +4227,50 @@ var COFantasy = COFantasy || function() { }); }*/ - /* Événements, utilisés pour les undo, en particulier undo pour refaire - * une action quand une règle le permet (utilisation de points de chance, etc..) - * Champ d'un événement (variables evt en général dans le code): + /* \xC9v\xE9nements, utilis\xE9s pour les undo, en particulier undo pour refaire + * une action quand une r\xE8gle le permet (utilisation de points de chance, etc..) + * Champ d'un \xE9v\xE9nement (variables evt en g\xE9n\xE9ral dans le code): * id : identificateur unique (int) - * type : description de l'événement (string) - * affectes : liste de tokens affectés par l'événement - * tokens : liste des tokens créés - * deletedTokens : liste de tokens effacés - * !!!!! -> ne garde pas les tokens effacés si on n'est pas sûr que son image est au bon endroit. Typiquement, on ne va le faire que pour les tokens crées dans le script - * attributes : liste de attributs créés ou modifiés - * deletesAttributes: lites des attributs effacés - * characters : liste des personnages créés + * type : description de l'\xE9v\xE9nement (string) + * affectes : liste de tokens affect\xE9s par l'\xE9v\xE9nement + * tokens : liste des tokens cr\xE9\xE9s + * deletedTokens : liste de tokens effac\xE9s + * !!!!! -> ne garde pas les tokens effac\xE9s si on n'est pas s\xFBr que son image est au bon endroit. Typiquement, on ne va le faire que pour les tokens cr\xE9es dans le script + * attributes : liste de attributs cr\xE9\xE9s ou modifi\xE9s + * deletesAttributes: lites des attributs effac\xE9s + * characters : liste des personnages cr\xE9\xE9s * characterNames : liste de character * name - * defaultTokens : liste de tokens par défaut (objet) + * defaultTokens : liste de tokens par d\xE9faut (objet) * (character, defaultToken) - * deletedCharacters: liste des personnages effacés - * combat : valeur de la variable d'état combat + * deletedCharacters: liste des personnages effac\xE9s + * combat : valeur de la variable d'\xE9tat combat * updateNextInitSet: valeur de l'ensemble des tokens dont il faut recalculer l'init - * turnorder : le turnorder (si il a changé) + * turnorder : le turnorder (si il a chang\xE9) * initiativepage : true si le turnorder est actif - * personnage : le perso qui 'fait' l'événement - * succes : stoque si l'attaque était un succès (bool) - * action : sauvegarde des paramètres de l'evt, pour la rejouer - * - caracteristique : carac testée (pour un jet) + * personnage : le perso qui 'fait' l'\xE9v\xE9nement + * succes : stoque si l'attaque \xE9tait un succ\xE8s (bool) + * action : sauvegarde des param\xE8tres de l'evt, pour la rejouer + * - caracteristique : carac test\xE9e (pour un jet) * - titre : titre du jet - * - playerId : id du joueur qui a lancé l'action - * - selected : cibles sélectionnés des l'action + * - playerId : id du joueur qui a lanc\xE9 l'action + * - selected : cibles s\xE9lectionn\xE9s des l'action * - attaquant: personnage attaquant (TODO: voir si doublon avec personnage) * - cibles: liste des cibles d'attaque, avec leurs tags - * - weaponStats: stats de l'arme (ou attaque) utilisée - * - rolls: les jets de l'action, pour les avoir à l'identique - * les dégâts sont stoqués dans chaque cible, dans cible.rollsDmg + * - weaponStats: stats de l'arme (ou attaque) utilis\xE9e + * - rolls: les jets de l'action, pour les avoir \xE0 l'identique + * les d\xE9g\xE2ts sont stoqu\xE9s dans chaque cible, dans cible.rollsDmg * - attack: les jets de l'attaque - * - etat_e_index_targetid: save pour entrer dans l'état e + * - etat_e_index_targetid: save pour entrer dans l'\xE9tat e * - effet_e_index_targetid: save pour l'effet e - * - attaquant_pietinement_targetid: jet de l'attaquant pour le piétinement - * - defenseur_pietinement_targetid: jet de du défenseur pour le piétinement + * - attaquant_pietinement_targetid: jet de l'attaquant pour le pi\xE9tinement + * - defenseur_pietinement_targetid: jet de du d\xE9fenseur pour le pi\xE9tinement * - options : options de l'action - * attenteResultat : permet de savoir que le jet est en attente de décision pour savoir si c'est un succès ou non (quand il n'y a pas de difficulté donnée et que le personnage est sous l'emprise d'une malédiction) + * attenteResultat : permet de savoir que le jet est en attente de d\xE9cision pour savoir si c'est un succ\xE8s ou non (quand il n'y a pas de difficult\xE9 donn\xE9e et que le personnage est sous l'emprise d'une mal\xE9diction) */ function addEvent(evt) { if (evt.id) { - error("Tentative d'ajouter un événement déjà dans l'historique", evt); + error("Tentative d'ajouter un \xE9v\xE9nement d\xE9j\xE0 dans l'historique", evt); return; } evt.id = stateCOF.eventId++; @@ -4304,11 +4310,11 @@ var COFantasy = COFantasy || function() { } } - //Si evt n'est pas défini, annule le dernier evt + //Si evt n'est pas d\xE9fini, annule le dernier evt function undoEvent(evt) { if (evt === undefined) { if (eventHistory.length === 0) { - sendChat('COF', "/w GM Historique d'évènements vide"); + sendChat('COF', "/w GM Historique d'\xE9v\xE8nements vide"); return; } evt = eventHistory.pop(); @@ -4346,7 +4352,7 @@ var COFantasy = COFantasy || function() { } if (evt.defaultTokens) { evt.defaultTokens.forEach(function(dt) { - //On cherche d'abord un token qui représente dt.character + //On cherche d'abord un token qui repr\xE9sente dt.character let tokens = findObjs({ _type: 'graphic', represents: dt.character.id @@ -4431,7 +4437,7 @@ var COFantasy = COFantasy || function() { }); }); } - // On le remet chez ses alliés + // On le remet chez ses alli\xE9s if (character.allies.length > 0) { Object.values(character.allies).forEach(function(allie) { let alliesPerso = alliesParPerso[allie] || new Set(); @@ -4499,7 +4505,7 @@ var COFantasy = COFantasy || function() { } if (_.has(evt, 'combat')) { let combat = stateCOF.combat; - //regarde si le token actif a changé + //regarde si le token actif a chang\xE9 if (evt.combat && (!combat || evt.combat.activeTokenId != combat.activeTokenId) && stateCOF.options.affichage.val.init_dynamique.val) { @@ -4529,24 +4535,27 @@ var COFantasy = COFantasy || function() { stateCOF.tokensTemps.push(tt); }); } - if (evt.tokensTemps) { //ceux pour lesquels on a diminué la durée + if (evt.tokensTemps) { //ceux pour lesquels on a diminu\xE9 la dur\xE9e evt.tokensTemps.forEach(function(tt) { if (tt.tt) tt.tt.duree = tt.ancienneDuree; }); } } - //origin peut être un message ou un nom de joueur + //origin peut \xEAtre un message ou un nom de joueur function sendPlayer(origin, msg, playerId) { let dest = origin; - if (origin.who) { - playerId = playerId || getPlayerIdFromMsg(origin); - if (playerIsGM(playerId)) dest = 'GM'; - else dest = origin.who; + if (origin.who !== undefined) { + if (origin.who === '') dest = 'GM'; + else { + playerId = playerId || getPlayerIdFromMsg(origin); + if (playerId == 'API' || playerIsGM(playerId)) dest = 'GM'; + else dest = origin.who; + } } if (dest.includes('"')) { sendChat('COF', msg); - log("Impossible d'envoyer des messages privés à " + dest + " car le nom contient des guillemets"); + log("Impossible d'envoyer des messages priv\xE9s \xE0 " + dest + " car le nom contient des guillemets"); } sendChat('COF', '/w "' + dest + '" ' + msg); } @@ -4576,7 +4585,7 @@ var COFantasy = COFantasy || function() { case 'FOR': return "de force"; case 'DEX': - return "de dextérité"; + return "de dext\xE9rit\xE9"; case 'CON': return "de constitution"; case 'SAG': @@ -4590,7 +4599,7 @@ var COFantasy = COFantasy || function() { } } - //msg peut être un message ou un playerId + //msg peut \xEAtre un message ou un playerId function peutController(msg, perso) { if (msg === undefined) return true; let playerId = getPlayerIdFromMsg(msg); @@ -4623,12 +4632,12 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let action = evt.action; if (action === undefined) { - error("Erreur interne du bouton de confirmation: l'évènement n'a pas d'action", cmd); + error("Erreur interne du bouton de confirmation: l'\xE9v\xE8nement n'a pas d'action", cmd); return; } let options = action.currentOptions || {}; @@ -4669,7 +4678,7 @@ var COFantasy = COFantasy || function() { let prev = aff.prev; let tok = aff.affecte; if (prev === undefined || tok === undefined) { - error("Pas d'état précédant", aff); + error("Pas d'\xE9tat pr\xE9c\xE9dant", aff); return; } let prevTok; @@ -4678,7 +4687,7 @@ var COFantasy = COFantasy || function() { tok.set(key, val); }); if (HTdeclared) HealthColors.Update(tok, prevTok); - sendChat("COF", "État de " + tok.get("name") + " restauré."); + sendChat("COF", "\xC9tat de " + tok.get("name") + " restaur\xE9."); }); } @@ -4695,7 +4704,7 @@ var COFantasy = COFantasy || function() { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string } - //Remplace une macro ou ability par sa définition (récursivement) + //Remplace une macro ou ability par sa d\xE9finition (r\xE9cursivement) function replaceAction(action, perso, macros, abilities) { let remplacement = false; if (action.indexOf('#') >= 0) { @@ -4712,7 +4721,7 @@ var COFantasy = COFantasy || function() { if (!remplacement) macros = macros.filter(function(m, k) { return (k != i); - }); //Pour éviter la récursion + }); //Pour \xE9viter la r\xE9cursion remplacement = true; } }); @@ -4728,7 +4737,7 @@ var COFantasy = COFantasy || function() { let daName = '%' + aName; if (action.indexOf(daName) >= 0) { action = action.replace(daName, a.get('action')); - if (!remplacement) abilities = abilities.splice(i); //Pour éviter la récursion + if (!remplacement) abilities = abilities.splice(i); //Pour \xE9viter la r\xE9cursion remplacement = true; } daName = '%{selected|' + aName + '}'; @@ -4737,7 +4746,7 @@ var COFantasy = COFantasy || function() { if (!remplacement) abilities = abilities.filter(function(m, k) { return (k != i); - }); //Pour éviter la récursion + }); //Pour \xE9viter la r\xE9cursion remplacement = true; } }); @@ -4818,7 +4827,8 @@ var COFantasy = COFantasy || function() { weaponStats.modificateurs = fieldAsString(att, 'armemodificateurs', ''); weaponStats.typeDegats = fieldAsString(att, 'armetypedegats', 'tranchant'); weaponStats.options = fieldAsString(att, 'armeoptions', ''); - weaponStats.options = weaponStats.options.trim(); + //On remplace les \n par des blancs pour l'affichage, sinon \xE7a bug + weaponStats.options = weaponStats.options.replace(/\n/g, ' ').trim(); weaponStats.predicats = fieldAsString(att, 'armepredicats', ''); switch (weaponStats.typeAttaque) { case 'Naturel': @@ -4849,7 +4859,7 @@ var COFantasy = COFantasy || function() { armeDeCreatureFeerique(perso, weaponStats, 3); break; default: - //On cherche si c'est une arme à 2 mains + //On cherche si c'est une arme \xE0 2 mains //Ne devrait pas servir, on a toujours un type, maintenant let t = weaponStats.name.toLowerCase(); if (t.includes('2 mains') || t.includes('deux mains')) { @@ -4864,19 +4874,19 @@ var COFantasy = COFantasy || function() { } } } - //Informations dans le champ spécial + //Informations dans le champ sp\xE9cial let champDivers = weaponStats.divers; if (champDivers === '') champDivers = weaponStats.predicats; else if (weaponStats.predicats !== '') champDivers += '\n' + weaponStats.predicats; let pred = predicateOfRaw(champDivers); - //On transfert les prédicats connus dans weaponStats + //On transfert les pr\xE9dicats connus dans weaponStats if (pred.charge) weaponStats.charge = toInt(pred.charge, 1); weaponStats.eclaire = toInt(pred.eclaire); weaponStats.eclaireFaible = toInt(pred.eclaireFaible); weaponStats.batarde = pred.batarde; if (weaponStats.batarde && weaponStats.deuxMains) { - error("L'arme " + weaponStats.name + " est déclarée comme batârde, il faudrait en faire une arme à une main par défaut", weaponStats); + error("L'arme " + weaponStats.name + " est d\xE9clar\xE9e comme bat\xE2rde, il faudrait en faire une arme \xE0 une main par d\xE9faut", weaponStats); weaponStats.deuxMains = undefined; } if (pred.armeDeGrand) { @@ -4885,22 +4895,26 @@ var COFantasy = COFantasy || function() { if (taille < 5) weaponStats.deuxMains = true; else weaponStats.deuxMains = false; } - //Identification des catégories d'armes utilisées en jeu + //Identification des cat\xE9gories d'armes utilis\xE9es en jeu identifierArme(weaponStats, pred, 'arc', /\barc\b/i); - identifierArme(weaponStats, pred, 'arbalete', /\barbal[eè]te\b/i); - identifierArme(weaponStats, pred, 'baton', /\bb[aâ]ton\b/i); + identifierArme(weaponStats, pred, 'arbalete', /\barbal[e\xE8]te\b/i); + identifierArme(weaponStats, pred, 'baton', /\bb[a\xE2]ton\b/i); identifierArme(weaponStats, pred, 'hache', /\bhache\b/i); - identifierArme(weaponStats, pred, 'epee', /\b[eé]p[eé]e\b/i); - identifierArme(weaponStats, pred, 'epieu', /\b[eé]pieu\b/i); + identifierArme(weaponStats, pred, 'epee', /\b[e\xE9]p[e\xE9]e\b/i); + identifierArme(weaponStats, pred, 'epieu', /\b[e\xE9]pieu\b/i); identifierArme(weaponStats, pred, 'fronde', /\bfronde\b/i); identifierArme(weaponStats, pred, 'marteau', /\bmarteau\b/i); identifierArme(weaponStats, pred, 'masse', /\bmasse\b/i); - identifierArme(weaponStats, pred, 'rapiere', /\brapi[eè]re\b/i); + identifierArme(weaponStats, pred, 'rapiere', /\brapi[e\xE8]re\b/i); identifierArme(weaponStats, pred, 'poudre', /\bpoudre\b/i); identifierArme(weaponStats, pred, 'sabre', /\b(katana|wakizachi|boken|demi-lame|vivelame|sabre)\b/i); if (weaponStats.arc && predicateAsBool(perso, 'arcDeMaitre')) { weaponStats.portee += 20; } + if (weaponStats.poudre && predicateAsBool(perso, 'poudrePuissante')) { + weaponStats.portee += 10; + weaponStats.attDMBonusCommun += 2; + } return weaponStats; } @@ -4928,8 +4942,8 @@ var COFantasy = COFantasy || function() { bar2 = parseInt(token.get('bar2_value')); if (isNaN(bar2)) { if (token.get('bar1_link') === '') bar2 = 0; - else { //devrait être lié à la mana courante - sendPerso(personnage, "*** Attention, la barre de mana du token n'est pas liée à la mana de la fiche ***"); + else { //devrait \xEAtre li\xE9 \xE0 la mana courante + sendPerso(personnage, "*** Attention, la barre de mana du token n'est pas li\xE9e \xE0 la mana de la fiche ***"); bar2 = parseInt(manaAttr[0].get('current')); } } @@ -4972,7 +4986,7 @@ var COFantasy = COFantasy || function() { } //depasse est un string qui commence par --depasseLimite - //args doit être défini et contient des valeur à modifier : + //args doit \xEAtre d\xE9fini et contient des valeur \xE0 modifier : // - mana // - text function peutDepasserLimite(depasse, perso, attrName, args) { @@ -5014,6 +5028,8 @@ var COFantasy = COFantasy || function() { if (condition.valeur === undefined) return !attributeAsBool(perso, condition.attribute); return testAttribut(perso, condition.attrbute, condition.valeur, condition); + case 'premiereAttaque': + return attributeAsBool(perso, 'attributDeCombat_premiereAttaque'); } return false; case 'mana': @@ -5026,7 +5042,10 @@ var COFantasy = COFantasy || function() { case 'limiteParJour': if (cmd.length < 2) return false; let limiteParJour = parseInt(cmd[1]); - if (isNaN(limiteParJour) || limiteParJour < 1) return false; + if (isNaN(limiteParJour)) { + limiteParJour = predicateAsInt(perso, cmd[1], 0, 1); + } + if (limiteParJour < 1) return false; let ressourceParJour = defResource; if (cmd.length > 2) { cmd.splice(0, 2); @@ -5036,7 +5055,7 @@ var COFantasy = COFantasy || function() { if (attributeAsInt(perso, ressourceParJour, limiteParJour) > 0) { return false; } - //Reste le cas où on peut dépasser cette limite par jour + //Reste le cas o\xF9 on peut d\xE9passer cette limite par jour let depasse = options.find(function(o) { return o.startsWith('depasseLimite '); }); @@ -5057,7 +5076,10 @@ var COFantasy = COFantasy || function() { case 'limiteParCombat': if (cmd.length < 2) return false; let limiteParCombat = parseInt(cmd[1]); - if (isNaN(limiteParCombat) || limiteParCombat < 1) return false; + if (isNaN(limiteParCombat)) { + limiteParCombat = predicateAsInt(perso, cmd[1], 0, 1); + } + if (limiteParCombat < 1) return false; let ressourceParCombat = defResource; if (cmd.length > 2) { cmd.splice(0, 2); @@ -5074,13 +5096,15 @@ var COFantasy = COFantasy || function() { if (cmd.length < 2) return false; let armeAssociee = getWeaponStats(perso, cmd[1]); return armeAssociee && armeAssociee.armeDeJet && armeAssociee.nbArmesDeJet < 1; + case 'traquenard': + return attributeAsBool(perso, 'attributDeCombat_premiereAttaque'); } return false; }); return ai; } - //Enlève les chaînes de type ?{..} pour être sûr que l'action est impossible + //Enl\xE8ve les cha\xEEnes de type ?{..} pour \xEAtre s\xFBr que l'action est impossible function removeUserInputs(act) { let m = act.match(/\?\{[^\}]*\}/g); if (!m) return act; @@ -5102,7 +5126,7 @@ var COFantasy = COFantasy || function() { if (labelArmePrincipale) perso.arme = getWeaponStats(perso, labelArmePrincipale); let labelArmeGauche = attr[0].get('max'); if (labelArmeGauche) { - if (labelArmeGauche == labelArmePrincipale) { //arme tenue à 2 mains + if (labelArmeGauche == labelArmePrincipale) { //arme tenue \xE0 2 mains perso.arme.deuxMains = true; } else { perso.armeGauche = getWeaponStats(perso, labelArmeGauche); @@ -5120,7 +5144,7 @@ var COFantasy = COFantasy || function() { function listAllMunitions(perso) { if (perso.munitions) return perso.munitions; let rawList = extractRepeating(perso, 'munitions'); - let liste = {}; //liste triée par label de munition + let liste = {}; //liste tri\xE9e par label de munition for (let pref in rawList) { let ra = rawList[pref]; if (ra.labelmunition === undefined) ra.labelmunition = 0; @@ -5135,11 +5159,11 @@ var COFantasy = COFantasy || function() { return liste; } - //Les options de l'arme doivent déjà être dans act + //Les options de l'arme doivent d\xE9j\xE0 \xEAtre dans act function demandeMunition(perso, weaponStats, options, act) { if (act.includes('--munition')) return act; let typeMunition; - if (weaponStats.arc) typeMunition = 'Flèche'; + if (weaponStats.arc) typeMunition = 'Fl\xE8che'; else if (weaponStats.arbalete) typeMunition = 'Carreau'; else if (weaponStats.poudre) typeMunition = 'Balle'; else if (weaponStats.fronde) typeMunition = 'Autre'; //TODO: ajouter le type bille sur la fiche @@ -5148,7 +5172,7 @@ var COFantasy = COFantasy || function() { let munitionsDeType = []; for (let label in munitions) { let munition = munitions[label]; - let tm = fieldAsString(munition, 'typemunition', 'Flèche'); + let tm = fieldAsString(munition, 'typemunition', 'Fl\xE8che'); if (tm != typeMunition) return; let nb = fieldAsInt(munition, 'qtemunition', 1); if (nb > 0) munitionsDeType.push(munition); @@ -5163,12 +5187,19 @@ var COFantasy = COFantasy || function() { return act + demande + '}'; } + //arm doit \xEAtre le r\xE9sultat de getWeaponStats + function armeDechargee(perso, arme) { + if (!arme.charge) return false; + let currentCharge = attributeAsInt(perso, 'charge_' + arme.label, arme.charge); + return currentCharge === 0; + } + //options peut avoir les champs: // - ressource, un attribut // - overlay // - buttonStyle // - attackStats - // et la fonction peut écrire actionImpossible = true dans options. + // et la fonction peut \xE9crire actionImpossible = true dans options. function bouton(action, text, perso, options) { if (action === undefined || action.trim() === '') return text; else action = action.trim(); @@ -5181,12 +5212,12 @@ var COFantasy = COFantasy || function() { if (character) perso.name = character.get('name'); else perso.name = nomPerso(perso); } - //Cas de plusieurs actions après expansion + //Cas de plusieurs actions apr\xE8s expansion let actions = action.split('\n'); //Cherche le picto et le style let style = ''; let picto = ''; - let groupe; //Pour générer un bouton d'attaque de groupe. À revoir + let groupe; //Pour g\xE9n\xE9rer un bouton d'attaque de groupe. \xC0 revoir actions = actions.map(function(act) { act = act.trim(); if (act.startsWith("/as ")) { @@ -5197,7 +5228,7 @@ var COFantasy = COFantasy || function() { let actSansChoix = removeUserInputs(act); const args = actSansChoix.split(' --'); let defRessource = ''; - if (act.startsWith('!cof-guerison ')) defRessource = 'guérison'; + if (act.startsWith('!cof-guerison ')) defRessource = 'gu\xE9rison'; let dai = { text }; @@ -5205,13 +5236,13 @@ var COFantasy = COFantasy || function() { options.actionImpossible = true; else text = dai.text; if (!options.actionImpossible) { - if (act.startsWith('!cof-soin ') && !actSansChoix.includes('--limitePar') && !actSansChoix.includes('--dose')) { //Limitations spéficiques + if (act.startsWith('!cof-soin ') && !actSansChoix.includes('--limitePar') && !actSansChoix.includes('--dose')) { //Limitations sp\xE9ficiques let rangSoin = predicateAsInt(perso, 'voieDesSoins', 0); let cmd = args[0].split(' '); if (cmd.includes('leger')) { let soinsLegers = attributeAsInt(perso, 'soinsLegers', 0); if (soinsLegers >= rangSoin) { - //Peut-être qu'on peut encore dépasser la limite + //Peut-\xEAtre qu'on peut encore d\xE9passer la limite let depasse = actSansChoix.indexOf('--depasseLimite '); if (depasse > 0) { let dp = { @@ -5226,7 +5257,7 @@ var COFantasy = COFantasy || function() { } else if (cmd.includes('modere')) { let soinsModeres = attributeAsInt(perso, 'soinsModeres', 0); if (soinsModeres >= rangSoin) { - //Peut-être qu'on peut encore dépasser la limite + //Peut-\xEAtre qu'on peut encore d\xE9passer la limite let depasse = actSansChoix.indexOf('--depasseLimite '); if (depasse > 0) { let dp = { @@ -5245,7 +5276,7 @@ var COFantasy = COFantasy || function() { let attackLabel = cmd[1]; let arme = getWeaponStats(perso, attackLabel); if (arme !== undefined && arme.charge) { - let currentCharge = attributeAsInt(perso, 'charge_' + attackLabel, 0); + let currentCharge = attributeAsInt(perso, 'charge_' + arme.label, arme.charge); if (currentCharge >= arme.charge) options.actionImpossible = true; } @@ -5253,7 +5284,7 @@ var COFantasy = COFantasy || function() { } else if (act.startsWith('!cof-attack ')) { let cmd = act.split(' '); if (cmd.length > 3 && cmd[3] == '-1') { - //Selon l'arme en main, une action peut être possible ou non + //Selon l'arme en main, une action peut \xEAtre possible ou non let weaponStats = armesEnMain(perso); if (weaponStats) { options.attackStats = options.attackStats || weaponStats; @@ -5261,6 +5292,8 @@ var COFantasy = COFantasy || function() { (weaponStats.deuxMains && attributeAsBool(perso, 'espaceExigu')) || (weaponStats.portee && (cmd.includes('--attaqueFlamboyante') || cmd.includes('--seulementContact'))) || + (!cmd.includes('--semonce') && !cmd.includes('--tirDeBarrage') && armeDechargee(perso, weaponStats)) || + (cmd.includes('--semonce') && attributeAsInt(perso, 'attaqueADistanceRatee', 0) != 1) || (cmd.includes('--ricochets') && !(weaponStats.armeDeJet || weaponStats.options.includes('--aussiArmeDeJet'))); } } @@ -5305,7 +5338,7 @@ var COFantasy = COFantasy || function() { } act = demandeMunition(perso, attackStats, options, act); } - //On cherche la portée dans les options (ça a la priorité) + //On cherche la port\xE9e dans les options (\xE7a a la priorit\xE9) args.forEach(function(o) { if (o.startsWith('portee ')) { let p = parseInt(o.substring(7)); @@ -5426,13 +5459,13 @@ var COFantasy = COFantasy || function() { } } if (act.indexOf('@{selected') !== -1) { - // cas spécial pour @{selected|token_id} où l'on remplace toutes les occurences par token.id + // cas sp\xE9cial pour @{selected|token_id} o\xF9 l'on remplace toutes les occurences par token.id act = act.replace(new RegExp(escapeRegExp('@{selected|token_id}'), 'g'), tid); act = act.replace(new RegExp(escapeRegExp('@{selected|token_name}'), 'g'), nomPerso(perso)); let tmp = act.split('@{selected'); tmp.forEach(function(elem) { if (elem.startsWith('|')) { - // attribut demandé + // attribut demand\xE9 let attribute_name = elem.substring(0, elem.indexOf("}")).substr(1); let carac = caracOfMod(attribute_name); let replacement; @@ -5470,12 +5503,12 @@ var COFantasy = COFantasy || function() { act.indexOf('--enVue') == -1 && act.indexOf('--disque') == -1 && act.indexOf('--target ' + tid) == -1) { - //Si on n'a pas de cible, on fait comme si le token était sélectionné. + //Si on n'a pas de cible, on fait comme si le token \xE9tait s\xE9lectionn\xE9. let add_token = " --target " + tid; if (act.indexOf(' --allie') >= 0) { if (act.indexOf('--lanceur') == -1) add_token = " --lanceur " + tid; - else add_token = ""; //La cible sont les alliés de --lanceur. + else add_token = ""; //La cible sont les alli\xE9s de --lanceur. } if (act.indexOf(' --message ') != -1) act = act.replace(' --message ', add_token + ' --message '); else act += add_token; @@ -5511,8 +5544,8 @@ var COFantasy = COFantasy || function() { } } - //Fonction séparée pour pouvoir envoyer un frame à plusieurs joueurs - // playerId peut être undefined (en particulier pour envoyer au mj) + //Fonction s\xE9par\xE9e pour pouvoir envoyer un frame \xE0 plusieurs joueurs + // playerId peut \xEAtre undefined (en particulier pour envoyer au mj) function addFramedHeader(display, playerId, chuchote) { let perso1 = display.perso1; let perso2 = display.perso2; @@ -5650,9 +5683,9 @@ var COFantasy = COFantasy || function() { display.header = res; } - //Si options.chuchote est vrai, la frame est chuchotée au joueur qui fait l'action - //Si options.chuchote est un nom, on chuchote la frame à ce nom - //Pour retarder la décision sur la cible de chuchotement, utiliser options.retarder + //Si options.chuchote est vrai, la frame est chuchot\xE9e au joueur qui fait l'action + //Si options.chuchote est un nom, on chuchote la frame \xE0 ce nom + //Pour retarder la d\xE9cision sur la cible de chuchotement, utiliser options.retarder function startFramedDisplay(playerId, action, perso, options) { options = options || {}; if (options.secret) { @@ -5723,7 +5756,7 @@ var COFantasy = COFantasy || function() { display.output += ""; } - //newLine indique qu'on commence une nouvelle rangée + //newLine indique qu'on commence une nouvelle rang\xE9e function addCellInFramedDisplay(display, cell, size, newLine, fond) { size = size || 100; if (display.endColumn) { @@ -5763,7 +5796,7 @@ var COFantasy = COFantasy || function() { nomLimite += 'Jour'; break; default: - error("Unité d'utilisation de capacité " + capa + " non reconnue", unite); + error("Unit\xE9 d'utilisation de capacit\xE9 " + capa + " non reconnue", unite); return; } return nomLimite + '__' + capa; @@ -5796,14 +5829,14 @@ var COFantasy = COFantasy || function() { expliquer("Perte de substance : -10 aux interactions sociales"); bonus -= 10; if (perteDeSubstance >= 15) { - expliquer("Perte de substance : faire un test de CHA 15 pour se faire remarquer à chaque tour"); + expliquer("Perte de substance : faire un test de CHA 15 pour se faire remarquer \xE0 chaque tour"); } } } return bonus; } - //expliquer est optionnel, et si présent, il faut msg + //expliquer est optionnel, et si pr\xE9sent, il faut msg function malusArmure(personnage, expliquer, msg) { let malusArmure = 0; if (personnage.malusArmure === undefined) { @@ -5828,7 +5861,7 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'graceFelineVoleur')) { let bonusGraceFeline = modCarac(personnage, 'charisme'); if (bonusGraceFeline > 0) { - expliquer("Grâce féline : +" + bonusGraceFeline + " en acrobaties"); + expliquer("Gr\xE2ce f\xE9line : +" + bonusGraceFeline + " en acrobaties"); bonus += bonusGraceFeline; } } @@ -5838,14 +5871,13 @@ var COFantasy = COFantasy || function() { } let a = predicateAsInt(personnage, 'ameFeline', 0); if (a > 0) { - expliquer("Âme féline : +" + a + " en acrobaties"); + expliquer("\xC2me f\xE9line : +" + a + " en acrobaties"); bonus += a; } break; } case 'baratiner': case 'bluffer': - case 'convaincre': bonus += bonusInteractionsSociales(personnage, expliquer); break; case 'course': @@ -5853,18 +5885,18 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'graceFelineVoleur')) { let bonusGraceFeline = modCarac(personnage, 'charisme'); if (bonusGraceFeline > 0) { - expliquer("Grâce féline : +" + bonusGraceFeline + " en course"); + expliquer("Gr\xE2ce f\xE9line : +" + bonusGraceFeline + " en course"); bonus += bonusGraceFeline; } } let a = predicateAsInt(personnage, 'ameFeline', 0); if (a > 0) { - expliquer("Âme féline : +" + a + " en course"); + expliquer("\xC2me f\xE9line : +" + a + " en course"); bonus += a; } a = predicateAsInt(personnage, 'vitesseDuFelin', 0); if (a > 0) { - expliquer("Vitesse du félin : +" + a + " en course"); + expliquer("Vitesse du f\xE9lin : +" + a + " en course"); bonus += a; } break; @@ -5875,10 +5907,10 @@ var COFantasy = COFantasy || function() { bonus += 5; } break; - case 'discrétion': + case 'discr\xE9tion': case 'discretion': if (attributeAsBool(personnage, 'foretVivanteEnnemie')) { - expliquer("Forêt hostile : -5 en discrétion"); + expliquer("For\xEAt hostile : -5 en discr\xE9tion"); bonus -= 5; } let perteDeSubstance = 0; @@ -5886,31 +5918,39 @@ var COFantasy = COFantasy || function() { perteDeSubstance = attributeAsInt(personnage, 'perteDeSubstance', 0); if (perteDeSubstance >= 5) { if (perteDeSubstance < 7) { - expliquer("Perte de substance : +2 en discrétion"); + expliquer("Perte de substance : +2 en discr\xE9tion"); bonus += 2; } else if (perteDeSubstance < 10) { - expliquer("Perte de substance : +5 en discrétion"); + expliquer("Perte de substance : +5 en discr\xE9tion"); bonus += 5; } else { - expliquer("Perte de substance : +10 en discrétion"); + expliquer("Perte de substance : +10 en discr\xE9tion"); bonus += 10; } } if (predicateAsBool(personnage, 'toutPetit') && !attributeAsBool(personnage, 'grandeTaille')) { - expliquer("Tout petit : +5 en discrétion"); + expliquer("Tout petit : +5 en discr\xE9tion"); bonus += 5; + } else if (predicateAsBool(personnage, 'petiteTaille')) { + expliquer("Petite taille : +2 en discr\xE9tion"); + bonus += 2; + } + let rapideCommeSonOmbre = predicateAsInt(personnage, 'rapideCommeSonOmbre', 0, 3); + if (rapideCommeSonOmbre > 0) { + expliquer("Rapide comme son ombre : +" + rapideCommeSonOmbre + " en discr\xE9tion"); + bonus += rapideCommeSonOmbre; } break; case 'intimidation': bonus += bonusArgumentDeTaille(personnage, expliquer); if (predicateAsBool(personnage, 'ordreDuChevalierDragon') && attributeAsBool(personnage, 'monteSur')) { - expliquer("Chevalier Dragon monté : +5 en intimidation"); + expliquer("Chevalier Dragon mont\xE9 : +5 en intimidation"); bonus += 5; } bonus += bonusInteractionsSociales(personnage, expliquer); if (predicateAsBool(personnage, 'batonDesRunesMortes') && (attributeAsBool(personnage, 'runeLizura') || attributeAsBool(personnage, 'runeMitrah'))) { - expliquer("Recouvert" + eForFemale(personnage) + " de la boue noire du bâton : +5 aux tests d'intimidation"); + expliquer("Recouvert" + eForFemale(personnage) + " de la boue noire du b\xE2ton : +5 aux tests d'intimidation"); bonus += 5; } break; @@ -5919,18 +5959,18 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'graceFelineVoleur')) { let bonusGraceFeline = modCarac(personnage, 'charisme'); if (bonusGraceFeline > 0) { - expliquer("Grâce féline : +" + bonusGraceFeline + " en escalade"); + expliquer("Gr\xE2ce f\xE9line : +" + bonusGraceFeline + " en escalade"); bonus += bonusGraceFeline; } } let a = predicateAsInt(personnage, 'ameFeline', 0); if (a > 0) { - expliquer("Âme féline : +" + a + " en escalade"); + expliquer("\xC2me f\xE9line : +" + a + " en escalade"); bonus += a; } a = predicateAsInt(personnage, 'vitesseDuFelin', 0); if (a > 0) { - expliquer("Vitesse du félin : +" + a + " en escalade"); + expliquer("Vitesse du f\xE9lin : +" + a + " en escalade"); bonus += a; } break; @@ -5938,20 +5978,20 @@ var COFantasy = COFantasy || function() { case 'mentir': bonus += bonusInteractionsSociales(personnage, expliquer); break; - case 'négociation': + case 'n\xE9gociation': case 'negociation': bonus += bonusArgumentDeTaille(personnage, expliquer); bonus += bonusInteractionsSociales(personnage, expliquer); break; case 'orientation': if (attributeAsBool(personnage, 'foretVivanteEnnemie')) { - expliquer("Forêt hostile : -5 en orientation"); + expliquer("For\xEAt hostile : -5 en orientation"); bonus -= 5; } break; case 'perception': if (attributeAsBool(personnage, 'foretVivanteEnnemie')) { - expliquer("Forêt hostile : -5 en perception"); + expliquer("For\xEAt hostile : -5 en perception"); bonus -= 5; } if (compagnonPresent(personnage, 'guetteur')) { @@ -5965,9 +6005,10 @@ var COFantasy = COFantasy || function() { } break; case 'persuasion': + case 'convaincre': bonus += bonusArgumentDeTaille(personnage, expliquer); if (predicateAsBool(personnage, 'ordreDuChevalierDragon') && attributeAsBool(personnage, 'monteSur')) { - expliquer("Chevalier Dragon monté : +5 en persuasion"); + expliquer("Chevalier Dragon mont\xE9 : +5 en persuasion"); bonus += 5; } bonus += bonusInteractionsSociales(personnage, expliquer); @@ -5978,25 +6019,25 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'graceFelineVoleur')) { let bonusGraceFeline = modCarac(personnage, 'charisme'); if (bonusGraceFeline > 0) { - expliquer("Grâce féline : +" + bonusGraceFeline + " en saut"); + expliquer("Gr\xE2ce f\xE9line : +" + bonusGraceFeline + " en saut"); bonus += bonusGraceFeline; } } let a = predicateAsInt(personnage, 'ameFeline', 0); if (a > 0) { - expliquer("Âme féline : +" + a + " en saut"); + expliquer("\xC2me f\xE9line : +" + a + " en saut"); bonus += a; } a = predicateAsInt(personnage, 'vitesseDuFelin', 0); if (a > 0) { - expliquer("Vitesse du félin : +" + a + " en saut"); + expliquer("Vitesse du f\xE9lin : +" + a + " en saut"); bonus += a; } break; } case 'survie': if (attributeAsBool(personnage, 'foretVivanteEnnemie')) { - expliquer("Forêt hostile : -5 en survie"); + expliquer("For\xEAt hostile : -5 en survie"); bonus -= 5; } break; @@ -6024,7 +6065,7 @@ var COFantasy = COFantasy || function() { let bonusChantDesHeros = getIntValeurOfEffet(personnage, 'chantDesHeros', 1); let chantDesHerosIntense = attributeAsInt(personnage, 'chantDesHerosTempeteDeManaIntense', 0); bonusChantDesHeros += chantDesHerosIntense; - expliquer("Chant des héros : +" + bonusChantDesHeros + " au jet"); + expliquer("Chant des h\xE9ros : +" + bonusChantDesHeros + " au jet"); bonus += bonusChantDesHeros; if (chantDesHerosIntense && evt) removeTokenAttr(personnage, 'chantDesHerosTempeteDeManaIntense', evt); @@ -6033,7 +6074,7 @@ var COFantasy = COFantasy || function() { let bonusBenediction = getIntValeurOfEffet(personnage, 'benediction', 1); let benedictionIntense = attributeAsInt(personnage, 'benedictionTempeteDeManaIntense', 0); bonusBenediction += benedictionIntense; - expliquer("Bénédiction : +" + bonusBenediction + " au jet"); + expliquer("B\xE9n\xE9diction : +" + bonusBenediction + " au jet"); bonus += bonusBenediction; if (benedictionIntense && evt) removeTokenAttr(personnage, 'benedictionTempeteDeManaIntense', evt); @@ -6048,7 +6089,7 @@ var COFantasy = COFantasy || function() { removeTokenAttr(personnage, 'inspirationTempeteDeManaIntense', evt); } if (attributeAsBool(personnage, 'lameDeLigneePerdue')) { - expliquer("Lame de lignée perdue : -1 au jet"); + expliquer("Lame de lign\xE9e perdue : -1 au jet"); bonus -= 1; } if (attributeAsBool(personnage, 'strangulation')) { @@ -6059,7 +6100,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'nueeDInsectes')) { let malusNuee = 2 + attributeAsInt(personnage, 'nueeDInsectesTempeteDeManaIntense', 0); - expliquer("Nuée d\'insectes : -" + malusNuee + " au jet"); + expliquer("Nu\xE9e d\'insectes : -" + malusNuee + " au jet"); bonus -= malusNuee; if (malusNuee > 2 && evt) removeTokenAttr(personnage, 'nueeDInsectesTempeteDeManaIntense', evt); @@ -6067,13 +6108,13 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(personnage, 'nueeDeCriquets')) { let malusNueeCriquets = 3 + attributeAsInt(personnage, 'nueeDeCriquetsTempeteDeManaIntense', 0); - expliquer("Nuée de criquets : -" + malusNueeCriquets + " au jet"); + expliquer("Nu\xE9e de criquets : -" + malusNueeCriquets + " au jet"); bonus -= malusNueeCriquets; if (malusNueeCriquets > 3 && evt) removeTokenAttr(personnage, 'nueeDeCriquetsTempeteDeManaIntense', evt); } if (attributeAsBool(personnage, 'nueeDeScorpions')) { - expliquer("Nuée de scorpions : -3 au jet"); + expliquer("Nu\xE9e de scorpions : -3 au jet"); bonus -= 3; } if (attributeAsBool(personnage, 'etatExsangue')) { @@ -6081,12 +6122,12 @@ var COFantasy = COFantasy || function() { bonus -= 2; } if (attributeAsBool(personnage, 'putrefactionOutrTombe')) { - expliquer("Putréfié : -2 au jet"); + expliquer("Putr\xE9fi\xE9 : -2 au jet"); bonus -= 2; } let fortifie = attributeAsInt(personnage, 'fortifie', 0); if (fortifie > 0) { - expliquer("Fortifié : +3 au jet"); + expliquer("Fortifi\xE9 : +3 au jet"); bonus += 3; if (evt) { fortifie--; @@ -6101,18 +6142,18 @@ var COFantasy = COFantasy || function() { !predicateAsBool(personnage, 'porteurDuBouclierDeGrabuge') && !attributeAsBool(personnage, 'sangDeLArbreCoeur')) { let malusOndesCorruptrices = attributeAsInt(personnage, 'ondesCorruptrices', 2); - let msgOndesCorruptrices = "Nauséeu" + onGenre(personnage, "x", "se"); + let msgOndesCorruptrices = "Naus\xE9eu" + onGenre(personnage, "x", "se"); msgOndesCorruptrices += " : -" + malusOndesCorruptrices; expliquer(msgOndesCorruptrices + " aux tests"); bonus -= malusOndesCorruptrices; } if (attributeAsBool(personnage, 'fievreux')) { bonus -= 2; - expliquer("Fiévreu" + onGenre(personnage, 'x', 'se') + " : -2 aux tests"); + expliquer("Fi\xE9vreu" + onGenre(personnage, 'x', 'se') + " : -2 aux tests"); } if (attributeAsBool(personnage, 'secoue')) { bonus -= 2; - expliquer("Secoué" + eForFemale(personnage) + " : -2 aux tests"); + expliquer("Secou\xE9" + eForFemale(personnage) + " : -2 aux tests"); } let bonusCondition = attributeAsInt(personnage, 'modificateurTests', 0); if (bonusCondition != 0) { @@ -6120,7 +6161,7 @@ var COFantasy = COFantasy || function() { if (bonusCondition > 0) { expliquer("Bonus de condition : +" + bonusCondition); } else { - expliquer("Pénalité de condition : " + bonusCondition); + expliquer("P\xE9nalit\xE9 de condition : " + bonusCondition); } } if (attributeAsBool(personnage, 'sensDuDevoir')) { @@ -6152,7 +6193,7 @@ var COFantasy = COFantasy || function() { options.bonusPreds.forEach(function(pred) { let bonusPred = predicateAsInt(personnage, pred, 0); if (bonusPred !== 0) { - expliquer("Prédicat " + pred + " : " + ((bonusPred < 0) ? "-" : "+") + bonusPred); + expliquer("Pr\xE9dicat " + pred + " : " + ((bonusPred < 0) ? "-" : "+") + bonusPred); bonus += bonusPred; } }); @@ -6209,12 +6250,12 @@ var COFantasy = COFantasy || function() { } //retourne un entier - // evt n'est défini que si la caractéristique est effectivement utilisée + // evt n'est d\xE9fini que si la caract\xE9ristique est effectivement utilis\xE9e function bonusTestCarac(carac, personnage, options, testId, evt, explications) { const expliquer = function(msg) { if (explications) explications.push(msg); }; - // D'abord la partie qui dépend de la caractéristique + // D'abord la partie qui d\xE9pend de la caract\xE9ristique let bonus = modCarac(personnage, caracOfMod(carac)); if (!persoEstPNJ(personnage)) { bonus += ficheAttributeAsInt(personnage, carac + "_BONUS", 0); @@ -6238,11 +6279,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'aspectDuDemon')) { bonusAspectDuDemon = getIntValeurOfEffet(personnage, 'aspectDuDemon', 2); - expliquer("Aspect du démon : +" + bonusAspectDuDemon + " au jet de DEX"); + expliquer("Aspect du d\xE9mon : +" + bonusAspectDuDemon + " au jet de DEX"); bonus += bonusAspectDuDemon; } if (attributeAsBool(personnage, 'osBrises')) { - expliquer("Des os sont brisés : -2 au jet de DEX"); + expliquer("Des os sont bris\xE9s : -2 au jet de DEX"); bonus -= 2; } if (attributeAsBool(personnage, 'espaceExigu')) { @@ -6255,19 +6296,19 @@ var COFantasy = COFantasy || function() { bonus -= 1; } if (attributeAsBool(personnage, 'reactionAllergique')) { - expliquer("Démangeaisons : -2 au jet de DEX"); + expliquer("D\xE9mangeaisons : -2 au jet de DEX"); bonus -= 2; } let conditions = attributeAsInt(personnage, 'conditionsHostiles', 0, 2); if (conditions > 0 && (!predicateAsBool(personnage, 'marcheSylvestre') || conditions > 4)) { let msgConditions = "Conditions "; if (conditions < 5) msgConditions += "hostiles"; - else msgConditions += "extrêmes"; + else msgConditions += "extr\xEAmes"; msgConditions += " : -" + conditions + " au jet de DEX"; expliquer(msgConditions); bonus -= conditions; } - if (expertiseSpecialisee == 'dex' || expertiseSpecialisee == 'dexterite' || expertiseSpecialisee == 'dextérité') { + if (expertiseSpecialisee == 'dex' || expertiseSpecialisee == 'dexterite' || expertiseSpecialisee == 'dext\xE9rit\xE9') { expliquer("Expertise : +5 aux jets de DEX"); bonus += 5; } @@ -6286,11 +6327,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'aspectDuDemon')) { bonusAspectDuDemon = getIntValeurOfEffet(personnage, 'aspectDuDemon', 2); - expliquer("Aspect du démon : +" + bonusAspectDuDemon + " au jet de FOR"); + expliquer("Aspect du d\xE9mon : +" + bonusAspectDuDemon + " au jet de FOR"); bonus += bonusAspectDuDemon; } if (attributeAsBool(personnage, 'osBrises')) { - expliquer("Des os sont brisés : -2 au jet de FOR"); + expliquer("Des os sont bris\xE9s : -2 au jet de FOR"); bonus -= 2; } if (attributeAsBool(personnage, 'espaceExigu')) { @@ -6311,7 +6352,7 @@ var COFantasy = COFantasy || function() { bonusInt += ficheAttributeAsInt(personnage, "INT_BONUS", 0); } if (bonusInt > bonusCarac) { - let msgGrosseTete = "Grosse tête : "; + let msgGrosseTete = "Grosse t\xEAte : "; if (bonusInt > 0) msgGrosseTete += '+'; msgGrosseTete += bonusInt + " au lieu de "; if (bonusCarac > 0) msgGrosseTete += '+'; @@ -6324,7 +6365,7 @@ var COFantasy = COFantasy || function() { if (conditions > 0 && (!predicateAsBool(personnage, 'marcheSylvestre') || conditions > 4)) { let msgConditions = "Conditions "; if (conditions < 5) msgConditions += "hostiles"; - else msgConditions += "extrêmes"; + else msgConditions += "extr\xEAmes"; msgConditions += " : -" + conditions + " au jet de FOR"; expliquer(msgConditions); bonus -= conditions; @@ -6339,7 +6380,7 @@ var COFantasy = COFantasy || function() { { if (attributeAsBool(personnage, 'secretsDeLAuDela')) { bonus += 5; - expliquer("Secrets de l'au-delà : +5"); + expliquer("Secrets de l'au-del\xE0 : +5"); } if (expertiseSpecialisee == 'int' || expertiseSpecialisee == 'intelligence') { expliquer("Expertise : +5 aux jets d'INT"); @@ -6361,7 +6402,7 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'batonDesRunesMortes') && (attributeAsBool(personnage, 'runeLizura') || attributeAsBool(personnage, 'runeMitrah'))) { if (!options.competence || options.competence.trim().toLowerCase() != 'intimidation') { - expliquer("Recouvert" + eForFemale(personnage) + " de la boue noire du bâton : -10 aux tests de CHA"); + expliquer("Recouvert" + eForFemale(personnage) + " de la boue noire du b\xE2ton : -10 aux tests de CHA"); bonus -= 10; } } @@ -6380,13 +6421,13 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'controleDuMetabolisme')) { let mod = modCarac(personnage, 'charisme'); if (mod > 0) { - expliquer("Controle du métabolisme : +" + mod + " au jet de CON"); + expliquer("Controle du m\xE9tabolisme : +" + mod + " au jet de CON"); bonus += mod; } } if (attributeAsBool(personnage, 'aspectDuDemon')) { bonusAspectDuDemon = getIntValeurOfEffet(personnage, 'aspectDuDemon', 2); - expliquer("Aspect du démon : +" + bonusAspectDuDemon + " au jet de CON"); + expliquer("Aspect du d\xE9mon : +" + bonusAspectDuDemon + " au jet de CON"); bonus += bonusAspectDuDemon; } if (expertiseSpecialisee == 'con' || expertiseSpecialisee == 'constitution') { @@ -6435,15 +6476,13 @@ var COFantasy = COFantasy || function() { } } } else { - let msgComp = "Compétence " + options.competence + " : "; - if (bonusCompetence === 0) { - msgComp += 0; - } else { + if (bonusCompetence !== 0) { + let msgComp = "Comp\xE9tence " + options.competence + " : "; bonus += bonusCompetence; if (bonusCompetence > 0) msgComp += "+" + bonusCompetence; else msgComp += bonusCompetence; + expliquer(msgComp); } - expliquer(msgComp); let malus = fieldAsString(competenceTrouvee, 'comp_malus', ''); if (malus == 'armure') { bonus -= malusArmure(personnage, expliquer, ''); @@ -6465,7 +6504,7 @@ var COFantasy = COFantasy || function() { // Puis la partie commune options = options || {}; bonus += bonusTestToutesCaracs(personnage, options, testId, evt, expliquer); - //Pas besoin de mettre la valeur de caractéristique si c'est le seul bonus + //Pas besoin de mettre la valeur de caract\xE9ristique si c'est le seul bonus if (explications && explications.length == 1) explications.pop(); return bonus; } @@ -6527,7 +6566,7 @@ var COFantasy = COFantasy || function() { fct = tremblementDeTerre; break; default: - error("Impossible de trouver la fonction liée à l'effet " + e, ev); + error("Impossible de trouver la fonction li\xE9e \xE0 l'effet " + e, ev); return; } } @@ -6543,34 +6582,34 @@ var COFantasy = COFantasy || function() { let pl = getPlayerIds(perso); if (pl === undefined) return; let playerId; - if (pl.length > 0) playerId = pl[0]; //Utilisé juste pour la couleur + if (pl.length > 0) playerId = pl[0]; //Utilis\xE9 juste pour la couleur let display = startFramedDisplay(playerId, titre, perso, { chuchote: 'GM' }); switch (d6.val) { case 1: { - let commande = '!cof-dmg 4d6 --psave DEX 15 --titre Éboulement majeur'; - addLineToFramedDisplay(display, "Éboulement majeur : sélectionnez les tokens dans la zone et " + boutonSimple(commande, 'cliquez ici')); + let commande = '!cof-dmg 4d6 --psave DEX 15 --titre \xC9boulement majeur'; + addLineToFramedDisplay(display, "\xC9boulement majeur : s\xE9lectionnez les tokens dans la zone et " + boutonSimple(commande, 'cliquez ici')); break; } case 2: case 3: { - let commande = '!cof-dmg 2d6 --psave DEX 15 --titre Éboulement mineur'; - addLineToFramedDisplay(display, "Éboulement mineur : choisissez un personnage au hasard et " + boutonSimple(commande, 'cliquez ici')); + let commande = '!cof-dmg 2d6 --psave DEX 15 --titre \xC9boulement mineur'; + addLineToFramedDisplay(display, "\xC9boulement mineur : choisissez un personnage au hasard et " + boutonSimple(commande, 'cliquez ici')); break; } case 6: { let commande = '!cof-set-state renverse true --save DEX 12'; - addLineToFramedDisplay(display, "Le sol tremble et se fissure : sélectionnez les personnages dans une zone d'environ 10 mètres et " + boutonSimple(commande, 'cliquez ici')); + addLineToFramedDisplay(display, "Le sol tremble et se fissure : s\xE9lectionnez les personnages dans une zone d'environ 10 m\xE8tres et " + boutonSimple(commande, 'cliquez ici')); break; } default: // 4 ou 5 { let commande = '!cof-effet-temp tremblementMineur 1'; - addLineToFramedDisplay(display, "Tremblement mineur : sélectionnez les personnages dans la zone et " + boutonSimple(commande, 'cliquez ici')); + addLineToFramedDisplay(display, "Tremblement mineur : s\xE9lectionnez les personnages dans la zone et " + boutonSimple(commande, 'cliquez ici')); break; } } @@ -6585,14 +6624,14 @@ var COFantasy = COFantasy || function() { let pl = getPlayerIds(perso); if (pl === undefined) return; let playerId; - if (pl.length > 0) playerId = pl[0]; //Utilisé juste pour la couleur + if (pl.length > 0) playerId = pl[0]; //Utilis\xE9 juste pour la couleur let display = startFramedDisplay(playerId, titre, perso); let explications = []; let np = nomPerso(perso); switch (d6.val) { case 1: { - addLineToFramedDisplay(display, np + " est frappé" + eForFemale(perso) + " de plein fouet !"); + addLineToFramedDisplay(display, np + " est frapp\xE9" + eForFemale(perso) + " de plein fouet !"); let options = { partialSave: { carac: 'DEX', @@ -6624,7 +6663,7 @@ var COFantasy = COFantasy || function() { dmg.display = buildinline(dmg.roll.inlinerolls[dmgRollNumber], dmg.type); dealDamage(perso, dmg, [], evt, false, options, explications, function(dmgDisplay, dmgFinal) { addLineToFramedDisplay(display, - np + " reçoit " + dmgDisplay + " DM"); + np + " re\xE7oit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); @@ -6642,7 +6681,7 @@ var COFantasy = COFantasy || function() { save: { carac: 'FOR', seuil: 10, - msgPour: "pour ne pas être tomber" + msgPour: "pour ne pas \xEAtre tomber" } }; let evt = { @@ -6658,7 +6697,7 @@ var COFantasy = COFantasy || function() { addEvent(evt); let saveOpts = { msgPour: options.msgPour, - msgRate: ", raté.", + msgRate: ", rat\xE9.", }; let expliquer = function(s) { explications.push(s); @@ -6671,7 +6710,7 @@ var COFantasy = COFantasy || function() { textDist = distance.val / 2; seuil = 2; } - textDist += distance.val > seuil ? ' mètres' : ' mètre'; + textDist += distance.val > seuil ? ' m\xE8tres' : ' m\xE8tre'; sendChat('', '[[2d6]]', function(resDmg) { let afterEvaluateDmg = resDmg[0].content.split(' '); let dmgRollNumber = rollNumber(afterEvaluateDmg[0]); @@ -6681,12 +6720,12 @@ var COFantasy = COFantasy || function() { type: 'electrique' }; dealDamage(perso, dmg, [], evt, false, options, explications, function(dmgDisplay, dmgFinal) { - addLineToFramedDisplay(display, np + " est projeté" + eForFemale(perso) + " de " + textDist + " par la foudre, et subit " + dmgDisplay + " DM"); + addLineToFramedDisplay(display, np + " est projet\xE9" + eForFemale(perso) + " de " + textDist + " par la foudre, et subit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); if (reussite) { - addLineToFramedDisplay(display, np + " résiste, la distance de projection passe de " + distance.roll + " à " + (distance.val / 2)); + addLineToFramedDisplay(display, np + " r\xE9siste, la distance de projection passe de " + distance.roll + " \xE0 " + (distance.val / 2)); } else { setState(perso, 'renverse', true, evt); } @@ -6707,7 +6746,7 @@ var COFantasy = COFantasy || function() { save: { carac: 'CON', seuil: 10, - msgPour: ' pour ne pas être affaibli' + eForFemale(perso) + msgPour: ' pour ne pas \xEAtre affaibli' + eForFemale(perso) } }; const evt = { @@ -6735,17 +6774,17 @@ var COFantasy = COFantasy || function() { return ficheAttributeAsInt(perso, 'pc', 3); } - // Test de caractéristique + // Test de caract\xE9ristique // options : bonusAttrs, bonusPreds, bonus, roll - // Après le test, lance callback(testRes, explications - // testRes.texte est l'affichage du jet de dé - // testRes.reussite indique si le jet est réussi + // Apr\xE8s le test, lance callback(testRes, explications + // testRes.texte est l'affichage du jet de d\xE9 + // testRes.reussite indique si le jet est r\xE9ussi // testRes.echecCritique, testRes.critique pour le type // testRes.valeur pour la valeur totale du jet - // testRes.rerolls pour le texte avec les boutons de rerolls adaptés. - // testRes.modifiers pour les boutons qui peuvent être activés sur le roll, qu'il soit réussi ou non. - // Pour que les boutons de rerolls fonctionnent, le type d'évènement doit être supporté par redoEvent() - // ne rajoute pas evt à l'historique + // testRes.rerolls pour le texte avec les boutons de rerolls adapt\xE9s. + // testRes.modifiers pour les boutons qui peuvent \xEAtre activ\xE9s sur le roll, qu'il soit r\xE9ussi ou non. + // Pour que les boutons de rerolls fonctionnent, le type d'\xE9v\xE8nement doit \xEAtre support\xE9 par redoEvent() + // ne rajoute pas evt \xE0 l'historique function testCaracteristique(personnage, carac, seuil, testId, options, evt, callback) { //asynchrone options = options || {}; let testRes = {}; @@ -6849,10 +6888,10 @@ var COFantasy = COFantasy || function() { boutonSimple("!cof-bouton-chance " + evt.id + " " + testId, "Chance") + " (reste " + pc + " PC)"; } - if (stateCOF.combat && attributeAsBool(personnage, 'runeForgesort_énergie') && - attributeAsInt(personnage, 'limiteParCombat_runeForgesort_énergie', 1) > 0 && + if (stateCOF.combat && attributeAsBool(personnage, 'runeForgesort_\xE9nergie') && + attributeAsInt(personnage, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0 && (carac == 'FOR' || carac == 'CON' || carac == 'DEX')) { - testRes.rerolls += '
' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'énergie"); + testRes.rerolls += '
' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'\xE9nergie"); } if (stateCOF.combat && capaciteDisponible(personnage, 'petitVeinard', 'combat')) { testRes.rerolls += '
' + boutonSimple("!cof-bouton-petit-veinard " + evt.id + " " + testId, "Petit veinard"); @@ -6873,18 +6912,18 @@ var COFantasy = COFantasy || function() { testRes.modifiers += "
" + boutonSimple("!cof-pacte-sanglant " + evt.id + " 5 " + testId, "Pacte sanglant (+5)"); } } - if (jetCache) sendChat('COF', "/w GM Jet caché : " + buildinline(roll) + bonusText); + if (jetCache) sendChat('COF', "/w GM Jet cach\xE9 : " + buildinline(roll) + bonusText); callback(testRes, explications); }); } catch (e) { - error("Erreur pendant l'évaluation de " + rollExpr + " dans un test de caractéristiques"); + error("Erreur pendant l'\xE9valuation de " + rollExpr + " dans un test de caract\xE9ristiques"); log(e.name + ": " + e.message); } } //callback peut prendre en argument une structure avec les champs: // - texte: Le texte du jet - // - total : Le résultat total du jet + // - total : Le r\xE9sultat total du jet // - echecCritique, critique pour indiquer si 1 ou 20 // - roll: le inlineroll function jetCaracteristique(personnage, carac, options, testId, evt, callback) { @@ -6925,15 +6964,15 @@ var COFantasy = COFantasy || function() { total: d20roll + bonusCarac, }; if (d20roll <= plageEC) { - rtext += " -> échec critique"; + rtext += " -> \xE9chec critique"; rt.echecCritique = true; } else if (d20roll == 20) { - rtext += " -> réussite critique"; + rtext += " -> r\xE9ussite critique"; rt.critique = true; } else if (bonusCarac !== 0 && !jetCache) rtext += " = " + rt.total; rt.texte = rtext; rt.roll = roll; - if (jetCache) sendChat('COF', "/w GM Jet caché de caractéristique : " + buildinline(roll) + bonusText); + if (jetCache) sendChat('COF', "/w GM Jet cach\xE9 de caract\xE9ristique : " + buildinline(roll) + bonusText); callback(rt, explications); }); } @@ -6986,7 +7025,7 @@ var COFantasy = COFantasy || function() { let dest = joueurJ.get('displayname'); if (dest.includes('"')) { sendChat('COF', display.action); - log("Impossible d'envoyer des messages privés à " + dest + " car le nom contient des guillemets"); + log("Impossible d'envoyer des messages priv\xE9s \xE0 " + dest + " car le nom contient des guillemets"); } sendChat('COF', '/w "' + dest + '" ' + display.action); } @@ -7024,12 +7063,12 @@ var COFantasy = COFantasy || function() { if (difficulte === undefined) { jetCaracteristique(perso, caracteristique, options, testId, evt, function(rt, explications) { - addLineToFramedDisplay(display, "Résultat : " + rt.texte); + addLineToFramedDisplay(display, "R\xE9sultat : " + rt.texte); explications.forEach(function(m) { addLineToFramedDisplay(display, m, 80); }); addStatistics(playerId, ["Jet de carac", caracteristique], rt.roll); - // Maintenant, on diminue la malédiction si le test est un échec + // Maintenant, on diminue la mal\xE9diction si le test est un \xE9chec let attrMalediction = tokenAttribute(perso, 'malediction'); if (attrMalediction.length > 0) { if (rt.echecCritique) @@ -7037,8 +7076,8 @@ var COFantasy = COFantasy || function() { else if (!rt.critique) { let action = "!cof-resultat-jet " + evt.id; let ligne = "L'action est-elle "; - ligne += bouton(action + " reussi", "réussie", perso); - ligne += " ou " + bouton(action + " rate", "ratée", perso); + ligne += bouton(action + " reussi", "r\xE9ussie", perso); + ligne += " ou " + bouton(action + " rate", "rat\xE9e", perso); ligne += " ?"; addLineToFramedDisplay(display, ligne); evt.attenteResultat = true; @@ -7051,10 +7090,10 @@ var COFantasy = COFantasy || function() { '
' + boutonSimple("!cof-bouton-chance " + evt.id + " " + testId, "Chance") + " (reste " + pc + " PC)"; } - if (stateCOF.combat && attributeAsBool(perso, 'runeForgesort_énergie') && - attributeAsInt(perso, 'limiteParCombat_runeForgesort_énergie', 1) > 0 && + if (stateCOF.combat && attributeAsBool(perso, 'runeForgesort_\xE9nergie') && + attributeAsInt(perso, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0 && (caracteristique == 'FOR' || caracteristique == 'CON' || caracteristique == 'DEX')) { - boutonsReroll += '
' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'énergie"); + boutonsReroll += '
' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'\xE9nergie"); } if (stateCOF.combat && capaciteDisponible(perso, 'petitVeinard', 'combat')) { boutonsReroll += '
' + boutonSimple("!cof-bouton-petit-veinard " + evt.id + " " + testId, "Petit veinard"); @@ -7080,15 +7119,15 @@ var COFantasy = COFantasy || function() { } else { testCaracteristique(perso, caracteristique, difficulte, testId, options, evt, function(tr, explications) { - addLineToFramedDisplay(display, "Résultat : " + tr.texte); + addLineToFramedDisplay(display, "R\xE9sultat : " + tr.texte); explications.forEach(function(m) { addLineToFramedDisplay(display, m, 80); }); if (tr.reussite) { - let msgReussite = options.messageSiSucces || "C'est réussi."; + let msgReussite = options.messageSiSucces || "C'est r\xE9ussi."; addLineToFramedDisplay(display, msgReussite + tr.modifiers); } else { - let msgRate = "C'est raté." + tr.rerolls + tr.modifiers; + let msgRate = "C'est rat\xE9." + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, msgRate); } sendDisplayJetPerso(display, playerId, options); @@ -7101,8 +7140,8 @@ var COFantasy = COFantasy || function() { function boutonsCompetences(display, perso, carac, msg, fond) { let action = msg.content; action = action.replace(/ --competences /, ''); - action = action.replace(/ --competences/, ''); //au cas où ce serait le dernier argument - let args = action.substring(9); //on enlève !cof-jet + action = action.replace(/ --competences/, ''); //au cas o\xF9 ce serait le dernier argument + let args = action.substring(9); //on enl\xE8ve !cof-jet if (!args.startsWith(carac)) action = "!cof-jet " + carac + " " + args; let overlay; switch (carac) { @@ -7110,7 +7149,7 @@ var COFantasy = COFantasy || function() { overlay = 'Force'; break; case 'DEX': - overlay = 'Dextérité'; + overlay = 'Dext\xE9rit\xE9'; break; case 'CON': overlay = 'Constitution'; @@ -7157,8 +7196,8 @@ var COFantasy = COFantasy || function() { addCellInFramedDisplay(display, cell, 80, false, fond); } - // prend une distance en mètre et retourne une distance dans l'unité - // utilisée sur la page du personnage + // prend une distance en m\xE8tre et retourne une distance dans l'unit\xE9 + // utilis\xE9e sur la page du personnage function scaleDistance(perso, distance) { if (perso.scale) return distance * perso.scale; let pageId = perso.pageId; @@ -7192,7 +7231,7 @@ var COFantasy = COFantasy || function() { perso.scale = 39.3701; break; default: - sendChat('COF', "Attention, unité de mesure de la page (" + unit + ") non reconnue"); + sendChat('COF', "Attention, unit\xE9 de mesure de la page (" + unit + ") non reconnue"); perso.scale = 1; } return distance * perso.scale; @@ -7214,9 +7253,9 @@ var COFantasy = COFantasy || function() { return pageId; } - // si défini, callback est appelé à chaque élément de selected + // si d\xE9fini, callback est appel\xE9 \xE0 chaque \xE9l\xE9ment de selected // qui n'est pas un personnage - // iter seulement sur les élément qui correspondent à des personnages + // iter seulement sur les \xE9l\xE9ment qui correspondent \xE0 des personnages function iterSelected(selected, iter, callback) { selected.forEach(function(sel) { let token = getObj('graphic', sel._id); @@ -7253,9 +7292,9 @@ var COFantasy = COFantasy || function() { return true; } - //traduction des coordonées de path en coordonées réelles sur la carte + //traduction des coordon\xE9es de path en coordon\xE9es r\xE9elles sur la carte function translatePathCoordinates(x, y, p) { - //D'abord on calcule les coordonnées relatives au centre + //D'abord on calcule les coordonn\xE9es relatives au centre x -= p.width / 2; y -= p.height / 2; //Puis on applique le scale @@ -7266,7 +7305,7 @@ var COFantasy = COFantasy || function() { let s = Math.sin(p.angle); x = c * x + s * y; y = c * y - s * x; - //Et finalement on ajoute les coordonnées du centre + //Et finalement on ajoute les coordonn\xE9es du centre x += p.left; y += p.top; return { @@ -7301,7 +7340,7 @@ var COFantasy = COFantasy || function() { }); return chemin; }); - //On rajoute les portes fermées. + //On rajoute les portes ferm\xE9es. let doors = findObjs({ _type: 'door', _pageid: pageId, @@ -7323,7 +7362,7 @@ var COFantasy = COFantasy || function() { return murs; } - //vérifie si de la nouvelle position on peut voir le suivi + //v\xE9rifie si de la nouvelle position on peut voir le suivi function obstaclePresent(nsx, nsy, pt, murs) { if (nsx == pt.x && nsy == pt.y) return false; let ps = { @@ -7442,7 +7481,7 @@ var COFantasy = COFantasy || function() { if (saufAllies) allies = (new Set(allies)).add(actif.charId); } else { if (msg.selected === undefined || msg.selected.length === 0) { - error("Pas d'allié car pas de token sélectionné", msg); + error("Pas d'alli\xE9 car pas de token s\xE9lectionn\xE9", msg); return; } iterSelected(msg.selected, function(personnage) { @@ -7471,7 +7510,7 @@ var COFantasy = COFantasy || function() { let ci = tok.get('represents'); if (ci === '') return; if (!allies.has(ci)) return; - //On enlève le token actif, mais seulement pour allies + //On enl\xE8ve le token actif, mais seulement pour allies if (cmdSplit[0] == 'allies') { if (actives.indexOf(function(perso) { return perso.charId == ci; @@ -7502,7 +7541,7 @@ var COFantasy = COFantasy || function() { return; case 'target': if (cmdSplit.length < 2) { - error("Il manque l'id de la cible (après --target)", cmd); + error("Il manque l'id de la cible (apr\xE8s --target)", cmd); return; } selected.push({ @@ -7512,50 +7551,57 @@ var COFantasy = COFantasy || function() { case 'disque': case 'disquePasseMur': if (options.ignoreDisque) return; - let centre; + let tokenCentre; let rayon; if (cmdSplit.length < 3) { if (actif && cmdSplit.length > 1) { - centre = actif; + tokenCentre = actif.token; rayon = parseInt(cmdSplit[1]); } else { - error("Pas assez d'arguments pour définir un disque", cmdSplit); + error("Pas assez d'arguments pour d\xE9finir un disque", cmdSplit); return; } } else { - centre = persoOfId(cmdSplit[1], cmdSplit[1], pageId); - if (centre === undefined) { - error("le premier argument du disque n'est pas un token valide", cmdSplit); - return; + tokenCentre = getObj('graphic', cmdSplit[1]); + if (!tokenCentre) { + let centre = persoOfId(cmdSplit[1], cmdSplit[1], pageId); + if (centre === undefined) { + error("le premier argument du disque n'est pas un token valide", cmdSplit); + return; + } + tokenCentre = centre.token; } + pageId = tokenCentre.get('pageid'); rayon = parseInt(cmdSplit[2]); } if (isNaN(rayon) || rayon < 0) { - error("Rayon du disque mal défini", cmdSplit); + error("Rayon du disque mal d\xE9fini", cmdSplit); return; } - let tokenCentre = centre.token; let portee = 0; if (cmdSplit.length > 3) { portee = parseInt(cmdSplit[3]); if (isNaN(portee) || portee < 0) { - error("La portée du disque est mal formée", cmdSplit); + error("La port\xE9e du disque est mal form\xE9e", cmdSplit); return; } if (actif === undefined) { - error("Pas de token sélectionné pour calculer la distance du disque", msg); + error("Pas de token s\xE9lectionn\xE9 pour calculer la distance du disque", msg); return; } if (distanceCombat(tokenCentre, actif.token, pageId, { strict1: true }) > portee) { - sendPerso(actif, "Le centre de l'effet est placé trop loin (portée " + portee + " m)"); + sendPerso(actif, "Le centre de l'effet est plac\xE9 trop loin (port\xE9e " + portee + " m)"); return; } } aoe = aoe || {}; aoe.type = 'disque'; - aoe.centre = tokenCentre; + aoe.centre = { + left: tokenCentre.get('left'), + top: tokenCentre.get('top') + }; aoe.rayon = rayon; page = page || getObj("page", pageId); if (cmdSplit[0] == 'disque') @@ -7575,7 +7621,7 @@ var COFantasy = COFantasy || function() { layer: 'objects' }); allToksDisque.forEach(function(obj) { - if (actif && portee === 0 && obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-même + if (actif && portee === 0 && obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-m\xEAme let objCharId = obj.get('represents'); if (objCharId === '') return; if (getState({ @@ -7600,8 +7646,8 @@ var COFantasy = COFantasy || function() { spawnFx(tokenCentre.get('left'), tokenCentre.get('top'), options.targetFx, pageId); } if (tokenCentre.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir le disque - tokenCentre.remove(); //On l'enlève, normalement plus besoin + //C'est juste un token utilis\xE9 pour d\xE9finir le disque + tokenCentre.remove(); //On l'enl\xE8ve, normalement plus besoin delete options.targetFx; } return; @@ -7611,7 +7657,7 @@ var COFantasy = COFantasy || function() { observateur = persoOfId(cmdSplit[1], cmdSplit[1], pageId); } if (observateur === undefined) { - error("Impossible de trouver la personne à partir de laquelle on sélectionne les tokens en vue", msg); + error("Impossible de trouver la personne \xE0 partir de laquelle on s\xE9lectionne les tokens en vue", msg); return; } page = page || getObj("page", pageId); @@ -7629,7 +7675,7 @@ var COFantasy = COFantasy || function() { layer: 'objects' }); tokensEnVue.forEach(function(obj) { - if (actif && obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-même + if (actif && obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-m\xEAme let objCharId = obj.get('represents'); if (objCharId === '') return; if (obj.get('bar1_max') == 0) return; // jshint ignore:line @@ -7645,12 +7691,12 @@ var COFantasy = COFantasy || function() { return; case 'alliesEnVue': if (actif === undefined) { - error("Impossible de trouver la personne dont on sélectionne les lliés en vue", msg); + error("Impossible de trouver la personne dont on s\xE9lectionne les lli\xE9s en vue", msg); return; } let alliesEnVue = alliesParPerso[actif.charId]; if (alliesEnVue === undefined) { - log("Personnage sans allié", actif); + log("Personnage sans alli\xE9", actif); return; } page = page || getObj("page", pageId); @@ -7668,7 +7714,7 @@ var COFantasy = COFantasy || function() { layer: 'objects' }); tokensAlliesEnVue.forEach(function(obj) { - if (obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-même + if (obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-m\xEAme let objCharId = obj.get('represents'); if (objCharId === '') return; if (!alliesEnVue.has(objCharId)) return; @@ -7708,7 +7754,7 @@ var COFantasy = COFantasy || function() { } } - //msg peut être directement le playerId ou un message + //msg peut \xEAtre directement le playerId ou un message function getPlayerIdFromMsg(msg) { if (msg.playerid === undefined) return msg; let playerId = msg.playerid; @@ -7727,7 +7773,7 @@ var COFantasy = COFantasy || function() { name: nom }); if (characters.length === 0) { - error("Impossible de trouver l'id du joueur " + nom, msg); + //error("Impossible de trouver l'id du joueur " + nom, msg); return playerId; } let pids = characters[0].get('controlledby'); @@ -7745,7 +7791,7 @@ var COFantasy = COFantasy || function() { //!cof-jet [carac] [difficulte] // - carac : FOR, DEX, CON, INT, SAG, CHA - // Les tokens sélectionnés sont ceux qui doivent faire le jet + // Les tokens s\xE9lectionn\xE9s sont ceux qui doivent faire le jet function jet(msg) { let opts = msg.content.split(' --'); let cmd = opts.shift().split(' '); @@ -7758,13 +7804,13 @@ var COFantasy = COFantasy || function() { switch (args[0]) { case 'nom': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } args.shift(); let nom = args.join(' '); if (options.nom && options.nom != nom) { - error("Nom du jet défini deux fois !", options.nom); + error("Nom du jet d\xE9fini deux fois !", options.nom); } options.nom = nom; if (options.competence) { @@ -7774,26 +7820,26 @@ var COFantasy = COFantasy || function() { return; case 'attribut': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } options.bonusAttrs.push(args[1]); return; case 'predicat': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } options.bonusPreds.push(args[1]); return; case 'bonus': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } let bonus = parseInt(args[1]); if (isNaN(bonus)) { - error("Le bonus doit être un nombre", opts); + error("Le bonus doit \xEAtre un nombre", opts); return; } options.bonus = (options.bonus || 0) + bonus; @@ -7804,12 +7850,12 @@ var COFantasy = COFantasy || function() { return; case 'plageEchecCritique': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } let plageEC = parseInt(args[1]); if (isNaN(plageEC) || plageEC < 0 || plageEC > 19) { - error("La plage d'échecs critqiques doit être un nombre positif inférieur à 19", opts); + error("La plage d'\xE9checs critqiques doit \xEAtre un nombre positif inf\xE9rieur \xE0 19", opts); return; } options.plageEchecCritique = plageEC; @@ -7821,17 +7867,17 @@ var COFantasy = COFantasy || function() { }); getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Utilisation de !cof-jet sans sélection de token", playerId); + sendPlayer(msg, "Utilisation de !cof-jet sans s\xE9lection de token", playerId); return; } - if (cmd.length < 2) { //On demande la carac et la compétence, si définies dans un handout Compétence + if (cmd.length < 2) { //On demande la carac et la comp\xE9tence, si d\xE9finies dans un handout Comp\xE9tence if (options.nom) { - error("Il manque la caractéristique à utiliser pour la compétence " + options.nom, msg.content); + error("Il manque la caract\xE9ristique \xE0 utiliser pour la comp\xE9tence " + options.nom, msg.content); return; } let fond = listeCompetences.nombre > 25; iterSelected(selected, function(perso) { - let display = startFramedDisplay(playerId, "Jet de caractéristique", perso, { + let display = startFramedDisplay(playerId, "Jet de caract\xE9ristique", perso, { chuchote: true }); startTableInFramedDisplay(display); @@ -7856,7 +7902,7 @@ var COFantasy = COFantasy || function() { let display = startFramedDisplay(playerId, "Jet " + deCarac(caracteristique), perso, { chuchote: true }); - addLineToFramedDisplay(display, "Choisissez la compétence"); + addLineToFramedDisplay(display, "Choisissez la comp\xE9tence"); startTableInFramedDisplay(display); boutonsCompetences(display, perso, caracteristique, msg); endTableInFramedDisplay(display); @@ -7895,7 +7941,7 @@ var COFantasy = COFantasy || function() { } if (options.bonus) titre += " (" + ((options.bonus > 0) ? '+' : '') + options.bonus + ")"; - if (difficulte !== undefined) titre += " difficulté " + difficulte; + if (difficulte !== undefined) titre += " difficult\xE9 " + difficulte; iterSelected(selected, function(perso) { jetPerso(perso, caracteristique, difficulte, titre, playerId, options); }); //fin de iterSelected @@ -7910,7 +7956,7 @@ var COFantasy = COFantasy || function() { } const evt = findEvent(args[1]); if (evt === undefined) { - error("Le jet est trop ancien ou éte annulé", args); + error("Le jet est trop ancien ou \xE9te annul\xE9", args); return; } if (evt.personnage === undefined) { @@ -7921,12 +7967,12 @@ var COFantasy = COFantasy || function() { let message = evt.type + " "; if (args[2] == 'rate') { diminueMalediction(evt.personnage, evt); - message += "raté."; - } else message += "réussi."; + message += "rat\xE9."; + } else message += "r\xE9ussi."; sendPerso(evt.personnage, message); delete evt.attenteResultat; } else { - sendPlayer(msg, "Résultat déjà décidé"); + sendPlayer(msg, "R\xE9sultat d\xE9j\xE0 d\xE9cid\xE9"); } } @@ -7946,7 +7992,7 @@ var COFantasy = COFantasy || function() { function optionsDeTempeteDeMana(msg) { if (tempeteDeManaCourante.vide) { - error("Pas de tempête de mana en cours", tempeteDeManaCourante); + error("Pas de temp\xEAte de mana en cours", tempeteDeManaCourante); return; } let perso = tempeteDeManaCourante.perso; @@ -7996,7 +8042,7 @@ var COFantasy = COFantasy || function() { tempeteDeManaCourante.intense = it; } } - let title = "Tempête de mana"; + let title = "Temp\xEAte de mana"; if (tempeteDeManaCourante.cout) { title += " de puissance " + tempeteDeManaCourante.cout; } @@ -8011,14 +8057,14 @@ var COFantasy = COFantasy || function() { if (tempeteDeManaCourante.dureeDeBase && tempeteDeManaCourante.dm === undefined && tempeteDeManaCourante.soins === undefined) - ajouterOptionTempete(display, "duree", "Durée", restant); + ajouterOptionTempete(display, "duree", "Dur\xE9e", restant); if (tempeteDeManaCourante.porteeDeBase) - ajouterOptionTempete(display, "portee", "Portée", restant); + ajouterOptionTempete(display, "portee", "Port\xE9e", restant); ajouterOptionTempete(display, "rapide", "Rapide", restant); if (tempeteDeManaCourante.altruistePossible) { let la = 'Magie altruiste : '; if (restant || tempeteDeManaCourante.altruiste) { - let tla = "Sélectionner"; + let tla = "S\xE9lectionner"; if (tempeteDeManaCourante.altruiste) { tla = nomPerso(tempeteDeManaCourante.altruiste); } @@ -8077,7 +8123,7 @@ var COFantasy = COFantasy || function() { if (max === undefined || max > niveau - (mana / cout_par_effet)) max = Math.floor(niveau - (mana / cout_par_effet)); if (max < 1) { - sendPerso(perso, "ne peut pas dépenser plus de mana en tempête de mana (niveau " + niveau + ", mana déjà dépensée " + mana + ")"); + sendPerso(perso, "ne peut pas d\xE9penser plus de mana en temp\xEAte de mana (niveau " + niveau + ", mana d\xE9j\xE0 d\xE9pens\xE9e " + mana + ")"); return; } tempeteDeManaCourante.max = max; @@ -8126,7 +8172,7 @@ var COFantasy = COFantasy || function() { } else { let intensite = parseInt(ta); if (isNaN(ta) || ta <= 0) { - error("Option de tempête de mana " + ta + " non reconnue", cmd); + error("Option de temp\xEAte de mana " + ta + " non reconnue", cmd); break; } options.tempeteDeManaIntense = options.tempeteDeManaIntense || 0; @@ -8142,12 +8188,13 @@ var COFantasy = COFantasy || function() { } function parseCondition(args) { - if (args.length > 0 && (args[0] == 'crit' || args[0] == 'critique')) { - return { - type: 'critique' - }; - } + if (args.length === 0) return; switch (args[0]) { + case 'crit': + case 'critique': + return { + type: 'critique' + }; case 'etat': if (args.length < 2) { error("condition non reconnue", args); @@ -8233,7 +8280,7 @@ var COFantasy = COFantasy || function() { } case 'predicatCible': if (args.length < 2) { - error("Il manque le prédicat de la cible", args); + error("Il manque le pr\xE9dicat de la cible", args); return; } let valeur; @@ -8254,6 +8301,10 @@ var COFantasy = COFantasy || function() { race: args[1], text: args[1] }; + case 'premiereAttaque': + return { + type: 'premiereAttaque' + }; case 'deAttaque': if (args.length < 2) { error("condition non reconnue", args); @@ -8261,8 +8312,8 @@ var COFantasy = COFantasy || function() { } let valeurDeAttaque = parseInt(args[1]); if (isNaN(valeurDeAttaque)) { - error("La condition de dé d'attaque doit être un nombre", args); - // on continue exprès pour tomber dans le cas par défaut + error("La condition de d\xE9 d'attaque doit \xEAtre un nombre", args); + // on continue expr\xE8s pour tomber dans le cas par d\xE9faut } else { return { type: 'deAttaque', @@ -8290,7 +8341,7 @@ var COFantasy = COFantasy || function() { function getFx(cmd, argName, obj, funName) { if (cmd.length < 2) { - let errMsg = "Il manque un argument à l'option --" + argName; + let errMsg = "Il manque un argument \xE0 l'option --" + argName; if (funName) errMsg += " de " + funName; sendChat("COF", errMsg); return; @@ -8323,7 +8374,7 @@ var COFantasy = COFantasy || function() { dm.nbDe = parseInt(exprDM.substring(0, indexD)); if (isNaN(dm.nbDe) || dm.nbDe < 0) { if (msg) - error("Expression de " + msg + ' ' + exprDM + " mal formée", expr); + error("Expression de " + msg + ' ' + exprDM + " mal form\xE9e", expr); return; } exprDM = exprDM.substring(indexD + 1); @@ -8372,12 +8423,12 @@ var COFantasy = COFantasy || function() { } const res = parseCarac(cmd[1]); if (res === undefined) { - error("Le premier argument de save n'est pas une caractéristique", cmd); + error("Le premier argument de save n'est pas une caract\xE9ristique", cmd); return; } res.seuil = parseInt(cmd[2]); if (isNaN(res.seuil)) { - error("Le deuxième argument de --psave n'est pas un nombre", cmd); + error("Le deuxi\xE8me argument de --psave n'est pas un nombre", cmd); return; } if (cmd.length > 3) { @@ -8389,24 +8440,23 @@ var COFantasy = COFantasy || function() { case 'carac': case 'carac2': case 'seuil': - error("Argument supplémentaire de save inconnu", cmd); + error("Argument suppl\xE9mentaire de save inconnu", cmd); return; case 'tempete': let ti = 1; if (oa.length > 1) { - ti = parseInt(oa[1]); - if (isNaN(ti)) ti = 1; + ti = toInt(oa[1], 1); } res.tempete = ti; return; case 'contact': if (oa.length < 2) { - error("Il manque la difficulté pour les cibles au contact"); + error("Il manque la difficult\xE9 pour les cibles au contact"); return; } let diff = parseInt(oa[1]); if (isNaN(diff)) { - error("La difficulté pour les cibles au contact n'est pas un nombre"); + error("La difficult\xE9 pour les cibles au contact n'est pas un nombre"); return; } res.contact = diff; @@ -8419,9 +8469,33 @@ var COFantasy = COFantasy || function() { return res; } + // Pour les limites par jour, combat ou tour, + // cmd[1] est la valeur ou un pr\xE9dicat + // cmd[2] est la ressource + function parseLimite(cmd, type) { + let l = parseInt(cmd[1]); + if (isNaN(l)) { + l = { + predicat: cmd[1] + }; + } else if (l < 1) { + error("La limite " + type + " doit \xEAtre un nombre positif", cmd); + return; + } else { + l = { + val: l + }; + } + if (cmd.length > 2) { + cmd.splice(0, 2); + l.ressource = cmd.join('_'); + } + return l; + } + //juste le traitement d'une liste d'options - // lastEtat : dernier de etats et effets, pour savoir à quoi appliquer --save - // lastType : dernier type de dégâts infligés + // lastEtat : dernier de etats et effets, pour savoir \xE0 quoi appliquer --save + // lastType : dernier type de d\xE9g\xE2ts inflig\xE9s // scope : pour les conditionnelles function parseAttackOptions(attaquant, optArgs, lastEtat, lastType, scope, playerId, msg, targetToken, attackLabel, weaponStats, options) { optArgs.forEach(function(arg) { @@ -8492,7 +8566,7 @@ var COFantasy = COFantasy || function() { case 'tirDeBarrage': case 'test': case 'traquenard': - case 'tueurDeGeants': //obsolète + case 'tueurDeGeants': //obsol\xE8te case 'tueurDeGrands': case 'grenaille': case 'attaqueArmeeConjuree': @@ -8510,7 +8584,7 @@ var COFantasy = COFantasy || function() { return; case 'aussiArmeDeJet': if (cmd.length < 2) { - error("Il faut préciser l'arme associée à celle-ci pour --aussiArmeDeJet", cmd); + error("Il faut pr\xE9ciser l'arme associ\xE9e \xE0 celle-ci pour --aussiArmeDeJet", cmd); return; } options.aussiArmeDeJet = cmd[1]; @@ -8520,7 +8594,7 @@ var COFantasy = COFantasy || function() { options.avantage = options.avantage || 1; options.avantage++; return; - case 'désavantage': + case 'd\xE9savantage': case 'desavantage': options.avantage = options.avantage || 1; options.avantage--; @@ -8541,7 +8615,7 @@ var COFantasy = COFantasy || function() { case 'nom': case 'special': if (cmd.length < 1) { - error("Il manque le nom après l'option --" + cmd[0], cmd); + error("Il manque le nom apr\xE8s l'option --" + cmd[0], cmd); return; } options[cmd[0]] = cmd.slice(1).join(' ').trim(); @@ -8549,7 +8623,7 @@ var COFantasy = COFantasy || function() { case 'toucher': case 'modifiePortee': if (cmd.length < 1) { - error("Il manque la valeur après l'option --" + cmd[0], cmd); + error("Il manque la valeur apr\xE8s l'option --" + cmd[0], cmd); return; } let intArg = parseInt(cmd[1]); @@ -8561,7 +8635,7 @@ var COFantasy = COFantasy || function() { return; case 'crit': if (cmd.length < 1) { - error("Il manque la valeur après l'option --crit", cmd); + error("Il manque la valeur apr\xE8s l'option --crit", cmd); return; } let crit = parseInt(cmd[1]); @@ -8575,15 +8649,15 @@ var COFantasy = COFantasy || function() { return; case 'dm': if (cmd.length < 1) { - error("Il manque la valeur après l'option --dm", cmd); + error("Il manque la valeur apr\xE8s l'option --dm", cmd); return; } - let dm = parseDice(cmd.slice(1).join(''), 'dégâts'); + let dm = parseDice(cmd.slice(1).join(''), 'd\xE9g\xE2ts'); if (dm) options.dm = dm; return; case 'portee': if (cmd.length < 1) { - error("Il manque la valeur après l'option --portee", cmd); + error("Il manque la valeur apr\xE8s l'option --portee", cmd); return; } let portee = parseInt(cmd[1]); @@ -8603,7 +8677,7 @@ var COFantasy = COFantasy || function() { return; case 'attaqueMagiqueDe': if (cmd.length < 1) { - error("Il manque le nom du personnage après l'option --attaqueMagiqueDe", cmd); + error("Il manque le nom du personnage apr\xE8s l'option --attaqueMagiqueDe", cmd); return; } let attaqueMagiqueDe = cmd.slice(1).join(' '); @@ -8612,22 +8686,22 @@ var COFantasy = COFantasy || function() { name: attaqueMagiqueDe }); if (ficheAttaqueMagique.length === 0) { - error("Il n'existe pas de personnage nommé " + attaqueMagiqueDe, cmd); + error("Il n'existe pas de personnage nomm\xE9 " + attaqueMagiqueDe, cmd); return; } if (ficheAttaqueMagique.length > 1) { - error("Attention, il existe plus d'un pesonnage nommé " + attaqueMagiqueDe, cmd); + error("Attention, il existe plus d'un pesonnage nomm\xE9 " + attaqueMagiqueDe, cmd); } let amCid = { charId: ficheAttaqueMagique[0].id }; let toucher = computeArmeAtk(amCid, '@{ATKMAG}'); if (isNaN(toucher)) { - error("Impossible de déterminer l'attaque de " + attaqueMagiqueDe, toucher); + error("Impossible de d\xE9terminer l'attaque de " + attaqueMagiqueDe, toucher); return; } if (options.toucher !== undefined) { - error("Attention, on a à la fois une option toucher et une option attaqueMagiqueDe. On ignore l'option --toucher", optArgs); + error("Attention, on a \xE0 la fois une option toucher et une option attaqueMagiqueDe. On ignore l'option --toucher", optArgs); } options.toucher = toucher; return; @@ -8648,14 +8722,14 @@ var COFantasy = COFantasy || function() { } scope.ignoreRD = parseInt(cmd[1]); if (isNaN(scope.ignoreRD) || scope.ignoreRD < 1) { - log("Pas un nombre positif après --ignoreRD, interprété comme ignore toute la RD"); + log("Pas un nombre positif apr\xE8s --ignoreRD, interpr\xE9t\xE9 comme ignore toute la RD"); scope.ignoreRD = undefined; scope.ignoreTouteRD = true; } return; case 'tueurDe': if (cmd.length < 2) { - log("Il faut préciser --tueurDe quoi"); + log("Il faut pr\xE9ciser --tueurDe quoi"); return; } options.tueurDe = options.tueurDe || []; @@ -8666,7 +8740,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { niveauMagie = parseInt(cmd[1]); if (isNaN(niveauMagie) || niveauMagie < 1) { - error("Le niveau de magie doit être au moins 1", cmd); + error("Le niveau de magie doit \xEAtre au moins 1", cmd); niveauMagie = 1; } } @@ -8677,16 +8751,16 @@ var COFantasy = COFantasy || function() { return; case 'tempsRecharge': if (cmd.length < 3) { - error("Il manque un argument à l'option --tempsRecharge de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --tempsRecharge de !cof-attack", cmd); return; } if (!estEffetTemp(cmd[1])) { - error("Le premier argument de l'option --tempsRecharge doit être un effet temporaire répertorié", cmd); + error("Le premier argument de l'option --tempsRecharge doit \xEAtre un effet temporaire r\xE9pertori\xE9", cmd); return; } let tr = parseInt(cmd[2]); if (isNaN(tr)) { - error("Le deuxième argument de l'option --tempsRecharge doit être un nombre", cmd); + error("Le deuxi\xE8me argument de l'option --tempsRecharge doit \xEAtre un nombre", cmd); return; } options.tempsRecharge = { @@ -8696,7 +8770,7 @@ var COFantasy = COFantasy || function() { return; case 'plus': if (cmd.length < 2) { - error("Il manque un argument à l'option --plus de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --plus de !cof-attack", cmd); return; } let val = arg.substring(arg.indexOf(' ') + 1); @@ -8708,7 +8782,7 @@ var COFantasy = COFantasy || function() { break; case 'plusCrit': if (cmd.length < 2) { - error("Il manque un argument à l'option --plusCrit de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --plusCrit de !cof-attack", cmd); return; } let valCrit = arg.substring(arg.indexOf(' ') + 1); @@ -8721,7 +8795,7 @@ var COFantasy = COFantasy || function() { case 'dmSiRate': case 'dmCible': if (cmd.length < 2) { - error("Il manque un argument à l'option --" + cmd[0] + " de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --" + cmd[0] + " de !cof-attack", cmd); return; } let valDm = arg.substring(arg.indexOf(' ') + 1); @@ -8732,7 +8806,7 @@ var COFantasy = COFantasy || function() { break; case 'effet': if (cmd.length < 2) { - error("Il manque un argument à l'option --effet de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --effet de !cof-attack", cmd); return; } let effet = cmd[1]; @@ -8745,7 +8819,7 @@ var COFantasy = COFantasy || function() { duree = parseInt(cmd[2]); if (isNaN(duree) || duree < 1) { error( - "Le deuxième argument de --effet doit être un nombre positif", + "Le deuxi\xE8me argument de --effet doit \xEAtre un nombre positif", cmd); return; } @@ -8771,7 +8845,7 @@ var COFantasy = COFantasy || function() { typeDmg: lastType }; } else { - error(cmd[1] + " n'est pas un effet temporaire répertorié", cmd); + error(cmd[1] + " n'est pas un effet temporaire r\xE9pertori\xE9", cmd); return; } scope.effets = scope.effets || []; @@ -8779,7 +8853,7 @@ var COFantasy = COFantasy || function() { return; case 'valeur': if (cmd.length < 2) { - error("Il manque un argument à l'option --valeur de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --valeur de !cof-attack", cmd); return; } if (scope.effets === undefined || scope.effets.length === 0) { @@ -8825,10 +8899,10 @@ var COFantasy = COFantasy || function() { case 'etatSi': case 'etat': if (cmd.length < 3 && cmd[0] == 'etatSi') { - error("Il manque un argument à l'option --etatSi de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --etatSi de !cof-attack", cmd); return; } else if (cmd.length < 2) { - error("Il manque un argument à l'option --etat de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --etat de !cof-attack", cmd); return; } let etat = cmd[1]; @@ -8850,7 +8924,7 @@ var COFantasy = COFantasy || function() { if (cmd[0] == 'etat' && cmd.length > 3) { if (!isCarac(cmd[2]) && (cmd[2].length != 6 || !isCarac(cmd[2].substring(0, 3)) || !isCarac(cmd[2].substring(3, 6)))) { - error("Caractéristique du jet de sauvegarde incorrecte", cmd); + error("Caract\xE9ristique du jet de sauvegarde incorrecte", cmd); return; } lastEtat.saveCarac = cmd[2]; @@ -8860,7 +8934,7 @@ var COFantasy = COFantasy || function() { } else { lastEtat.saveDifficulte = parseInt(cmd[3]); if (isNaN(lastEtat.saveDifficulte)) { - error("Difficulté du jet de sauvegarde incorrecte", cmd); + error("Difficult\xE9 du jet de sauvegarde incorrecte", cmd); delete lastEtat.saveCarac; delete lastEtat.saveDifficulte; } @@ -8870,7 +8944,7 @@ var COFantasy = COFantasy || function() { return; case 'peur': if (cmd.length < 3) { - error("Il manque un argument à l'option --peur de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --peur de !cof-attack", cmd); return; } scope.peur = { @@ -8878,10 +8952,10 @@ var COFantasy = COFantasy || function() { duree: parseInt(cmd[2]) }; if (isNaN(scope.peur.seuil)) { - error("Le premier argument de --peur doit être un nombre (le seuil)", cmd); + error("Le premier argument de --peur doit \xEAtre un nombre (le seuil)", cmd); } if (isNaN(scope.peur.duree) || scope.peur.duree <= 0) { - error("Le deuxième argument de --peur doit être un nombre positif (la durée)", cmd); + error("Le deuxi\xE8me argument de --peur doit \xEAtre un nombre positif (la dur\xE9e)", cmd); } return; case 'feu': @@ -8912,7 +8986,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { vampirise = parseInt(cmd[1]); if (isNaN(vampirise)) { - error("Il faut un pourcentage entier comme argument à --vampirise", cmd); + error("Il faut un pourcentage entier comme argument \xE0 --vampirise", cmd); vampirise = 100; } } @@ -8943,7 +9017,7 @@ var COFantasy = COFantasy || function() { break; case 'disparition': if (cmd.length < 2) { - error("Il manque un argument à l'option --disparition de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --disparition de !cof-attack", cmd); return; } let disparition = parseInt(cmd[1]); @@ -8995,7 +9069,7 @@ var COFantasy = COFantasy || function() { case 'save': if (lastEtat) { if (lastEtat.save) { - error("Redéfinition de la condition de save pour un effet", optArgs); + error("Red\xE9finition de la condition de save pour un effet", optArgs); } let saveParams = parseSave(cmd); if (saveParams) { @@ -9013,7 +9087,7 @@ var COFantasy = COFantasy || function() { case 'saveParJour': if (lastEtat) { if (lastEtat[cmd[0]]) { - error("Redéfinition de la condition de save pour un effet", optArgs); + error("Red\xE9finition de la condition de save pour un effet", optArgs); } let saveParTourParams = parseSave(cmd); if (saveParTourParams) { @@ -9034,12 +9108,12 @@ var COFantasy = COFantasy || function() { case 'mana': { if (cmd.length < 2) { - error("Usage : --mana coût", cmd); + error("Usage : --mana co\xFBt", cmd); return; } let mana = parseInt(cmd[1]); if (isNaN(mana) || mana < 0) { - error("Le coût en mana doit être un nombre positif"); + error("Le co\xFBt en mana doit \xEAtre un nombre positif"); return; } if (scope.mana === undefined) scope.mana = 0; @@ -9053,7 +9127,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { cout = parseInt(cmd[1]); if (isNaN(cout) || cout < 0) { - error("Le coût de la magie rapide n'est pas un entier positif", cmd); + error("Le co\xFBt de la magie rapide n'est pas un entier positif", cmd); cout = 1; } } @@ -9071,7 +9145,7 @@ var COFantasy = COFantasy || function() { } else { let base = parseInt(cmd[1]); if (isNaN(base)) { - error("L'argument de --magieEnArmure doit être un nombre ou mana", cmd); + error("L'argument de --magieEnArmure doit \xEAtre un nombre ou mana", cmd); return; } options.magieEnArmure = { @@ -9089,7 +9163,7 @@ var COFantasy = COFantasy || function() { } let rang = parseInt(cmd[1]); if (isNaN(rang) || rang < 1) { - error("Le rang doit être un nombre positif"); + error("Le rang doit \xEAtre un nombre positif"); return; } scope.rang = rang; @@ -9103,7 +9177,7 @@ var COFantasy = COFantasy || function() { } let bAtt = parseInt(cmd[1]); if (isNaN(bAtt)) { - error("Le bonus (" + cmd[0] + ") doit être un nombre"); + error("Le bonus (" + cmd[0] + ") doit \xEAtre un nombre"); return; } if (scope[cmd[0]] === undefined) scope[cmd[0]] = 0; @@ -9117,7 +9191,7 @@ var COFantasy = COFantasy || function() { } let b2Att = parseInt(cmd[1]); if (isNaN(b2Att)) { - error("Le bonus (" + cmd[0] + ") doit être un nombre"); + error("Le bonus (" + cmd[0] + ") doit \xEAtre un nombre"); return; } if (options[cmd[0]] === undefined) options[cmd[0]] = 0; @@ -9163,12 +9237,12 @@ var COFantasy = COFantasy || function() { } return; case 'munition': - if (options.munition) { //on évite la récursion - error("Plusieurs options --munition. Seule la première est prise en compte", cmd); + if (options.munition) { //on \xE9vite la r\xE9cursion + error("Plusieurs options --munition. Seule la premi\xE8re est prise en compte", cmd); return; } if (cmd.length < 2) { - error("Pour les munitions, il faut préciser le label de la munition", cmd); + error("Pour les munitions, il faut pr\xE9ciser le label de la munition", cmd); return; } let labelMunition = cmd[1]; @@ -9198,13 +9272,13 @@ var COFantasy = COFantasy || function() { } return; } - sendPlayer(msg, "Utilisez plutôt les munitions définies sur la fiche", playerId); - //Compatibilité avec ancienne version: - let tauxPertes = 100; //Par défaut, les munitions sont perdues + sendPlayer(msg, "Utilisez plut\xF4t les munitions d\xE9finies sur la fiche", playerId); + //Compatibilit\xE9 avec ancienne version: + let tauxPertes = 100; //Par d\xE9faut, les munitions sont perdues if (cmd.length > 2) tauxPertes = parseInt(cmd[2]); if (isNaN(tauxPertes) || tauxPertes < 0 || tauxPertes > 100) { - error("Le taux de pertes des munitions doit être un nombre entre 0 et 100"); + error("Le taux de pertes des munitions doit \xEAtre un nombre entre 0 et 100"); tauxPertes = 100; } options.munition = { @@ -9214,7 +9288,7 @@ var COFantasy = COFantasy || function() { return; case "ligne": if (options.aoe) { - error("Deux options pour définir une aoe", optArgs); + error("Deux options pour d\xE9finir une aoe", optArgs); return; } options.aoe = { @@ -9223,7 +9297,7 @@ var COFantasy = COFantasy || function() { return; case 'disque': if (options.aoe) { - error("Deux options pour définir une aoe", optArgs); + error("Deux options pour d\xE9finir une aoe", optArgs); return; } if (cmd.length < 2) { @@ -9244,14 +9318,14 @@ var COFantasy = COFantasy || function() { return; case 'cone': if (options.aoe) { - error("Deux options pour définir une aoe", optArgs); + error("Deux options pour d\xE9finir une aoe", optArgs); return; } let angle = 90; if (cmd.length > 1) { angle = parseInt(cmd[1]); if (isNaN(angle) || angle < 0 || angle > 360) { - error("Paramètre d'angle du cone incorrect", cmd); + error("Param\xE8tre d'angle du cone incorrect", cmd); angle = 90; } } @@ -9267,7 +9341,7 @@ var COFantasy = COFantasy || function() { } let targetS = persoOfId(cmd[1]); if (targetS === undefined) { - error("Cible supplémentaire invalide", cmd); + error("Cible suppl\xE9mentaire invalide", cmd); return; } if (targetToken.id == targetS.token.id) return; @@ -9322,63 +9396,45 @@ var COFantasy = COFantasy || function() { } return; case 'limiteParJour': - if (cmd.length < 2) { - error("Il manque la limite journalière", cmd); - return; - } - let limiteParJour = parseInt(cmd[1]); - if (isNaN(limiteParJour) || limiteParJour < 1) { - error("La limite journalière doit être un nombre positif", cmd); + { + if (cmd.length < 2) { + error("Il manque la limite journali\xE8re", cmd); + return; + } + let limiteParJour = parseLimite(cmd, "journali\xE8re"); + if (limiteParJour) scope.limiteParJour = limiteParJour; return; } - scope.limiteParJour = limiteParJour; - if (cmd.length > 2) { - cmd.splice(0, 2); - scope.limiteParJourRessource = cmd.join('_'); - } - return; case 'limiteParCombat': - if (cmd.length < 2) { - scope.limiteParCombat = 1; - return; - } - let limiteParCombat = parseInt(cmd[1]); - if (isNaN(limiteParCombat) || limiteParCombat < 1) { - error("La limite par combat doit être un nombre positif", cmd); + { + if (cmd.length < 2) { + scope.limiteParCombat = 1; + return; + } + let limiteParCombat = parseLimite(cmd, "par combat"); + if (limiteParCombat) scope.limiteParCombat = limiteParCombat; return; } - scope.limiteParCombat = limiteParCombat; - if (cmd.length > 2) { - cmd.splice(0, 2); - scope.limiteParCombatRessource = cmd.join('_'); - } - return; case 'limiteParTour': - if (cmd.length < 2) { - scope.limiteParTour = 1; - return; - } - let limiteParTour = parseInt(cmd[1]); - if (isNaN(limiteParTour) || limiteParTour < 1) { - error("La limite par tour doit être un nombre positif", cmd); + { + if (cmd.length < 2) { + scope.limiteParTour = 1; + return; + } + let limiteParTour = parseLimite(cmd, "par tour"); + if (limiteParTour) scope.limiteParTour = limiteParTour; return; } - scope.limiteParTour = limiteParTour; - if (cmd.length > 2) { - cmd.splice(0, 2); - scope.limiteParTourRessource = cmd.join('_'); - } - return; case 'decrAttribute': if (cmd.length < 2) { - error("Erreur interne d'une commande générée par bouton", cmd); + error("Erreur interne d'une commande g\xE9n\xE9r\xE9e par bouton", cmd); return; } let attr = getObj('attribute', cmd[1]); if (attr === undefined) { attr = tokenAttribute(attaquant, cmd[1]); if (attr.length === 0) { - log("Attribut à changer perdu"); + log("Attribut \xE0 changer perdu"); log(cmd); return; } @@ -9388,7 +9444,7 @@ var COFantasy = COFantasy || function() { return; case 'decrLimitePredicatParTour': if (cmd.length < 2) { - error("Erreur interne d'une commande générée par bouton", cmd); + error("Erreur interne d'une commande g\xE9n\xE9r\xE9e par bouton", cmd); return; } scope.decrLimitePredicatParTour = cmd[1]; @@ -9400,7 +9456,7 @@ var COFantasy = COFantasy || function() { } let forceMin = parseInt(cmd[1]); if (isNaN(forceMin)) { - error("La force minimum doit être un nombre", cmd); + error("La force minimum doit \xEAtre un nombre", cmd); return; } scope.forceMinimum = forceMin; @@ -9412,7 +9468,7 @@ var COFantasy = COFantasy || function() { } let arcComposite = parseInt(cmd[1]); if (isNaN(arcComposite)) { - error("Le bonus d'arc composite doit être un nombre", cmd); + error("Le bonus d'arc composite doit \xEAtre un nombre", cmd); return; } scope.arcComposite = arcComposite; @@ -9428,7 +9484,7 @@ var COFantasy = COFantasy || function() { scope.dmgCoef += incrDmgCoef; return; } - scope.dmgCoef++; //Par défaut, incrémente de 1 + scope.dmgCoef++; //Par d\xE9faut, incr\xE9mente de 1 return; case 'toucheDoubleDmg': options.toucheDoubleDmg = true; @@ -9446,7 +9502,7 @@ var COFantasy = COFantasy || function() { scope.diviseDmg *= divise; return; } - scope.diviseDmg *= 2; //Par défaut, divise par 2 + scope.diviseDmg *= 2; //Par d\xE9faut, divise par 2 return; case 'divisePortee': scope.divisePortee = (scope.divisePortee || 1); @@ -9459,7 +9515,7 @@ var COFantasy = COFantasy || function() { scope.divisePortee *= divise; return; } - scope.divisePortee *= 2; //Par défaut, divise par 2 + scope.divisePortee *= 2; //Par d\xE9faut, divise par 2 return; case 'incrCritCoef': scope.critCoef = (scope.critCoef || 1); @@ -9472,7 +9528,7 @@ var COFantasy = COFantasy || function() { scope.critCoef += incrCritCoef; return; } - scope.critCoef++; //Par défaut, incrémente de 1 + scope.critCoef++; //Par d\xE9faut, incr\xE9mente de 1 return; case 'if': let ifCond = parseCondition(cmd.slice(1)); @@ -9523,7 +9579,7 @@ var COFantasy = COFantasy || function() { } let iteL = psElse.ite[psElse.ite.length - 1]; if (iteL.else) { - error("Il y a déjà un --else pour ce --if", cmd); + error("Il y a d\xE9j\xE0 un --else pour ce --if", cmd); return; } delete scope.parentScope; @@ -9536,7 +9592,7 @@ var COFantasy = COFantasy || function() { } case 'message': if (cmd.length < 2) { - error("Il manque le message après --message", cmd); + error("Il manque le message apr\xE8s --message", cmd); return; } scope.messages = scope.messages || []; @@ -9544,11 +9600,11 @@ var COFantasy = COFantasy || function() { return; case 'allonge': if (cmd.length < 2) { - error("Il manque le message après --allonge", cmd); + error("Il manque le message apr\xE8s --allonge", cmd); return; } if (options.allonge !== undefined) { - log("Redéfinition de l'allong"); + log("Red\xE9finition de l'allong"); } options.allonge = parseFloat(cmd[1]); if (isNaN(options.allonge)) { @@ -9571,7 +9627,7 @@ var COFantasy = COFantasy || function() { scope.enveloppe.expression = cmd[3]; } if (scope.enveloppe.expression === undefined) { - error("Il n'est pas encore possible d'utiliser l'option --enveloppe sans expression si le label de l'attaque n'est pas défini", cmd); + error("Il n'est pas encore possible d'utiliser l'option --enveloppe sans expression si le label de l'attaque n'est pas d\xE9fini", cmd); scope.enveloppe = undefined; } return; @@ -9598,7 +9654,7 @@ var COFantasy = COFantasy || function() { case 'imgAttackSuccesChampion': case 'imgAttackSuccesCritique': if (cmd.length < 1) { - error("Il manque une image après --" + cmd[0], cmd); + error("Il manque une image apr\xE8s --" + cmd[0], cmd); return; } options[cmd[0]] = cmd[1]; @@ -9611,12 +9667,12 @@ var COFantasy = COFantasy || function() { case 'soundAttackSuccesChampion': case 'soundAttackSuccesCritique': if (cmd.length < 1) { - error("Il manque le son après --" + cmd[0], cmd); + error("Il manque le son apr\xE8s --" + cmd[0], cmd); return; } options[cmd[0]] = cmd.slice(1).join(' '); return; - //Anciennes variantes, gardées pour la compatibilité + //Anciennes variantes, gard\xE9es pour la compatibilit\xE9 case 'img-attack-echec-critique': case 'img-attack-echec': case 'img-attack-echec-clignotement': @@ -9626,7 +9682,7 @@ var COFantasy = COFantasy || function() { case 'img-attack-succes-champion': case 'img-attack-succes-critique': if (cmd.length < 1) { - error("Il manque une image après --" + cmd[0], cmd); + error("Il manque une image apr\xE8s --" + cmd[0], cmd); return; } let imgCmd = @@ -9644,7 +9700,7 @@ var COFantasy = COFantasy || function() { case 'sound-attack-succes-champion': case 'sound-attack-succes-critique': if (cmd.length < 2) { - error("Il manque le son après --" + cmd[0], cmd); + error("Il manque le son apr\xE8s --" + cmd[0], cmd); return; } let soundCmd = cmd[0].replace('-a', 'A').replace('-e', 'E').replace('-c', 'C').replace('-n', 'N').replace('-s', 'S').replace('-t', 'T'); @@ -9670,7 +9726,7 @@ var COFantasy = COFantasy || function() { case 'FOR': carac = 'force'; break; - case 'dextérité': + case 'dext\xE9rit\xE9': case 'DEX': carac = 'dexterite'; break; @@ -9691,12 +9747,12 @@ var COFantasy = COFantasy || function() { carac = 'random'; break; default: - error("Le premier argument de affaiblirCarac n'est pas une caractéristique", cmd); + error("Le premier argument de affaiblirCarac n'est pas une caract\xE9ristique", cmd); return; } let valAff = parseDice(cmd[2]); if (!valAff || !dePositif(valAff)) { - error("Le deuxième argument de --affaiblirCarac doit être un nombre", cmd); + error("Le deuxi\xE8me argument de --affaiblirCarac doit \xEAtre un nombre", cmd); return; } if (valAff === 0) return; @@ -9709,12 +9765,12 @@ var COFantasy = COFantasy || function() { return; case 'difficulteCarac': if (cmd.length < 2) { - error("Il manque la caractéristique à laquelle mesurer le jet d'attaque", cmd); + error("Il manque la caract\xE9ristique \xE0 laquelle mesurer le jet d'attaque", cmd); return; } options.difficulteCarac = parseCarac(cmd[1]); if (options.difficulteCarac === undefined) { - error("L'argument de --difficulteCarac n'est pas une caractéristique", cmd); + error("L'argument de --difficulteCarac n'est pas une caract\xE9ristique", cmd); } return; case 'attackId': @@ -9724,6 +9780,54 @@ var COFantasy = COFantasy || function() { } options.attackId = cmd[1]; return; + case 'terrainDifficile': + { + let terrainDifficile = options.terrainDifficile || { + duree: 1, + imgsrc: IMG_INVISIBLE, + nom: "Terrain difficile" + }; + if (cmd.length > 1) { //le premier argument est la dur\xE9e de l'effet + terrainDifficile.duree = toInt(cmd[1], 1); + if (cmd.length > 2) { //le second argument est le nom du terrain + terrainDifficile.nom = cmd[2].replace(/_/g, ' '); + if (cmd.length > 3) { //le troisi\xE8me argument est l'url de l'image + let imgsrc = cmd[3].replace(':', ':'); + terrainDifficile.imgsrc = normalizeTokenImg(imgsrc); + } + } + } + options.terrainDifficile = terrainDifficile; + return; + } + case 'deplaceDe': + { + if (cmd.length < 2) { + error("Il faut pr\xE9ciser une distance maximale pour --deplaceDe", cmd); + return; + } + let deplaceDe = {}; + deplaceDe.max = parseInt(cmd[1]); + if (isNaN(deplaceDe.max) || deplaceDe.max < 0) { + error("Distance de deplacement incorrect", cmd); + return; + } + if (cmd.length > 2) { + if (cmd[2] == 'saut') deplaceDe.saut = true; + else { + let dmax = parseInt(cmd[2]); + if (isNaN(dmax) || dmax < deplaceDe.max) { + error("Argument de d\xE9placement " + cmd[2] + " non reconnu", cmd); + } else { + deplaceDe.min = deplaceDe.max; + deplaceDe.max = dmax; + } + if (cmd.length > 3 && cmd[3] == 'saut') deplaceDe.saut = true; + } + } + options.deplaceDe = deplaceDe; + return; + } default: let armeMagique = cmd[0].match(/^\+([0-9]+)$/); if (armeMagique && armeMagique.length > 0) { @@ -9747,7 +9851,7 @@ var COFantasy = COFantasy || function() { } } }); - closeIte(scope); //pour fermer les endif mal formés et éviter les boucles + closeIte(scope); //pour fermer les endif mal form\xE9s et \xE9viter les boucles return { lastEtat, lastType, @@ -9779,7 +9883,7 @@ var COFantasy = COFantasy || function() { } let pageId = attaquant.token.get('pageid'); let targetToken = getObj('graphic', args[2]); - if (targetToken === undefined) { //reste la possibilité de trouver un token de ce nom + if (targetToken === undefined) { //reste la possibilit\xE9 de trouver un token de ce nom let tokens = findObjs({ _type: 'graphic', _subtype: 'token', @@ -9787,12 +9891,12 @@ var COFantasy = COFantasy || function() { name: args[2] }); if (tokens.length == 0) { - error("le second argument de !cof-attack doit être un token", args[2]); + error("le second argument de !cof-attack doit \xEAtre un token", args[2]); return; } if (tokens.length > 1) { - error("Ambigüité sur le choix d'un token : il y a " + - tokens.length + " tokens nommés " + args[2], tokens); + error("Ambig\xFCit\xE9 sur le choix d'un token : il y a " + + tokens.length + " tokens nomm\xE9s " + args[2], tokens); } targetToken = tokens[0]; } @@ -9803,7 +9907,7 @@ var COFantasy = COFantasy || function() { let weaponStats; let attaqueArray; try { - attaqueArray = JSON.parse(attackLabel); //plus documenté depuis 2020 + attaqueArray = JSON.parse(attackLabel); //plus document\xE9 depuis 2020 } catch (e) {} if (Array.isArray(attaqueArray) && attaqueArray.length > 4 && attaqueArray[1].length > 1 && attaqueArray[3].length > 3) { @@ -9850,10 +9954,10 @@ var COFantasy = COFantasy || function() { return; } if (weaponStats.deuxMains && attributeAsBool(attaquant, 'espaceExigu')) { - sendPerso(attaquant, "ne peut pas utiliser d'arme à deux mains dans un espace aussi exigu."); + sendPerso(attaquant, "ne peut pas utiliser d'arme \xE0 deux mains dans un espace aussi exigu."); return; } - //Si c'est aussi une arme de jet, et que le personnage attaque à distance, on va utiliser la version arme de jet de l'attaque. + //Si c'est aussi une arme de jet, et que le personnage attaque \xE0 distance, on va utiliser la version arme de jet de l'attaque. let msgIndex = msg.content; let indexAussiJet = msgIndex.indexOf('--aussiArmeDeJet '); if (indexAussiJet == -1 && weaponStats.options) { @@ -9879,7 +9983,7 @@ var COFantasy = COFantasy || function() { } //Ajout des options de l'arme let wo = weaponStats.options.trim(); - //Pour la partie options, il est possible qu'elle soit déjà passée en ligne de commande + //Pour la partie options, il est possible qu'elle soit d\xE9j\xE0 pass\xE9e en ligne de commande if (wo !== '' && ((optArgs.length < 1 || !optArgs[0].startsWith('attaqueOptions'))) || indexAussiJet > 0) { wo = ' ' + wo; wo.split(' --').reverse().forEach(function(o) { @@ -9923,7 +10027,7 @@ var COFantasy = COFantasy || function() { break; case 'magique': options.magique = true; - options.type = 'energie'; //Les dégâts magiques sans type associé sont supposés de type énergie, l'équivalent de force dans PF1 + options.type = 'energie'; //Les d\xE9g\xE2ts magiques sans type associ\xE9 sont suppos\xE9s de type \xE9nergie, l'\xE9quivalent de force dans PF1 break; case 'tranchant': case 'percant': @@ -9932,7 +10036,7 @@ var COFantasy = COFantasy || function() { break; } let lastEtat; //dernier de etats et effets - let lastType = options.type; //dernier type de dégâts infligés + let lastType = options.type; //dernier type de d\xE9g\xE2ts inflig\xE9s let scope = options; //Pour les conditionnelles parseAttackOptions(attaquant, optArgs, lastEtat, lastType, scope, playerId, msg, targetToken, attackLabel, weaponStats, options); let bene = predicateAsInt(attaquant, 'benedictionSuperieure', 0); @@ -9946,7 +10050,7 @@ var COFantasy = COFantasy || function() { options.additionalDmg = options.additionalDmg || []; if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, rang: options.rang, @@ -9972,7 +10076,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -9989,7 +10093,7 @@ var COFantasy = COFantasy || function() { } } else { if (options.tempeteDeManaDuree) { - sendPlayerAndGM(msg, playerId, "Attention, l'option tempête de mana pour la durée n'est pas prise en compte. Utiliser l'option --pasDeDmg si le sort ne fait pas de DM"); + sendPlayerAndGM(msg, playerId, "Attention, l'option temp\xEAte de mana pour la dur\xE9e n'est pas prise en compte. Utiliser l'option --pasDeDmg si le sort ne fait pas de DM"); options.tempeteDeManaDuree = false; if (options.tempeteDeMana && options.tempeteDeMana.cout) options.tempeteDeMana.cout--; @@ -10019,30 +10123,30 @@ var COFantasy = COFantasy || function() { if (f) f(evt); } - // Fait dépenser de la mana, dep doit contenir une dépense possible + // Fait d\xE9penser de la mana, dep doit contenir une d\xE9pense possible function depenseMana(perso, dep, msg, evt) { if (!dep || dep.cout_null) return; updateCurrentBar(perso, 2, dep.pm, evt); msg = msg || ''; if (dep.depense_pv) { - let source = reglesOptionelles.mana.val.brulure_de_magie.val ? "de la Brûlure de Magie" : "du Contrecoup"; + let source = reglesOptionelles.mana.val.brulure_de_magie.val ? "de la Br\xFBlure de Magie" : "du Contrecoup"; updateCurrentBar(perso, 1, dep.pv, evt); let pre = 'p'; if (stateCOF.options.affichage.val.depense_mana.val && dep.depense_pm > 0) - pre = "dépense " + dep.depense_pm + " PM et p"; - sendPerso(perso, pre + "erd " + dep.depense_pv + " PV à cause " + source + " pour " + msg); + pre = "d\xE9pense " + dep.depense_pm + " PM et p"; + sendPerso(perso, pre + "erd " + dep.depense_pv + " PV \xE0 cause " + source + " pour " + msg); } else { if (stateCOF.options.affichage.val.depense_mana.val) - sendPerso(perso, "dépense " + dep.depense_pm + " PM pour " + msg); + sendPerso(perso, "d\xE9pense " + dep.depense_pm + " PM pour " + msg); } let niveau = ficheAttributeAsInt(perso, 'niveau', 1); if (reglesOptionelles.mana.val.mana_totale.val) { if (dep.depense_pm > niveau * 3) { - sendPerso(perso, "Attention, la dépense totale de mana est supérieure au niveau * 3"); + sendPerso(perso, "Attention, la d\xE9pense totale de mana est sup\xE9rieure au niveau * 3"); } } else { if (dep.depense_pm > niveau) { - sendPerso(perso, "Attention, la dépense totale de mana est supérieure au niveau"); + sendPerso(perso, "Attention, la d\xE9pense totale de mana est sup\xE9rieure au niveau"); } } return; @@ -10071,7 +10175,7 @@ var COFantasy = COFantasy || function() { case 'animal': return estAnimal(perso); case 'demon': - case 'démon': + case 'd\xE9mon': return estDemon(perso); case 'dragon': return estDraconique(perso); @@ -10079,9 +10183,9 @@ var COFantasy = COFantasy || function() { case 'elfe-noir': return estElfeNoir(perso); case 'fee': - case 'fée': + case 'f\xE9e': return estFee(perso); - case 'géant': + case 'g\xE9ant': case 'geant': return estGeant(perso); case 'gobelin': @@ -10097,7 +10201,7 @@ var COFantasy = COFantasy || function() { } } - //Si l'attribut est un mod. de caractéristique, va chercher le + //Si l'attribut est un mod. de caract\xE9ristique, va chercher le //bon attribut, selon que perso est un PNJ ou nom function valAttribute(perso, originalAttr, caracAttr) { if (caracAttr) { @@ -10109,10 +10213,10 @@ var COFantasy = COFantasy || function() { return charAttributeAsInt(perso, originalAttr, 0); } - //test si l'attribut est présent et si sa valeur est bonne + //test si l'attribut est pr\xE9sent et si sa valeur est bonne // options peut contenir - // fiche : si on cherche un attribut de fiche, et dans ce cas, le champ def donne la valeur par défaut - // local : si c'est un attribut différent selon le mook + // fiche : si on cherche un attribut de fiche, et dans ce cas, le champ def donne la valeur par d\xE9faut + // local : si c'est un attribut diff\xE9rent selon le mook function testAttribut(perso, attrName, valeur, options) { let attr; if (options.fiche) { @@ -10130,7 +10234,7 @@ var COFantasy = COFantasy || function() { if (cond == 'toujoursVrai') return true; switch (cond.type) { case 'moins': - // Au cas où on utilise les MOD au lieu de l'attribut de base: + // Au cas o\xF9 on utilise les MOD au lieu de l'attribut de base: let caracAttr = caracOfMod(cond.attribute); let attackerAttr = valAttribute(attaquant, cond.attribute, caracAttr); let resMoins = true; @@ -10188,13 +10292,13 @@ var COFantasy = COFantasy || function() { case 'deAttaque': if (options && options.auto) return false; if (deAttaque === undefined) { - error("Condition de dé d'attaque non supportée ici", cond); + error("Condition de d\xE9 d'attaque non support\xE9e ici", cond); return true; } return deAttaque >= cond.seuil; case 'echecCritique': if (deAttaque === undefined) { - error("Condition de dé d'attaque non supportée ici", cond); + error("Condition de d\xE9 d'attaque non support\xE9e ici", cond); return true; } return deAttaque == 1; @@ -10206,6 +10310,8 @@ var COFantasy = COFantasy || function() { return cibles.every(function(target) { return target.critique; }); + case 'premiereAttaque': + return !attributeAsBool(attaquant, 'attributDeCombat_premiereAttaque'); default: error("Condition non reconnue", cond); } @@ -10238,7 +10344,7 @@ var COFantasy = COFantasy || function() { case 'mana': case 'bonusAttaque': case 'bonusContreArmure': - case 'bonusContreBouclier': //numériques additives + case 'bonusContreBouclier': //num\xE9riques additives opt[field] = opt[field] || 0; opt[field] += branch[field]; break; @@ -10285,11 +10391,11 @@ var COFantasy = COFantasy || function() { attr.set('current', oldval - 1); break; case 'decrLimitePredicatParTour': - //Ne fait que diminuer l'attribut, n'empêche pas l'attaque + //Ne fait que diminuer l'attribut, n'emp\xEAche pas l'attaque let pred = branch.decrLimitePredicatParTour; let test = testLimiteUtilisationsCapa(attaquant, pred, 'tour', "ne peut plus utiliser " + pred + " ce tour", - "Attaque impossible, pas de prédicat " + pred); + "Attaque impossible, pas de pr\xE9dicat " + pred); if (test === undefined) break; utiliseCapacite(attaquant, test, evt); break; @@ -10308,7 +10414,7 @@ var COFantasy = COFantasy || function() { if (etat.aTraiter === 0) callback(); } - //Evaluation récursive des if-then-else + //Evaluation r\xE9cursive des if-then-else function evalITE(attaquant, target, deAttaque, options, phase, evt, explications, scope, callback, inTarget, etatParent) { etatParent = etatParent || {}; if (scope.ite === undefined || scope.ite.length < 1) { @@ -10324,6 +10430,7 @@ var COFantasy = COFantasy || function() { switch (ite.condition.type) { case 'etat': case 'attribut': + case 'premiereAttaque': resCondition = testCondition(ite.condition, attaquant, [], deAttaque); break; case 'deAttaque': @@ -10377,7 +10484,7 @@ var COFantasy = COFantasy || function() { callIfAllDone(etatParent, callback); return true; } - let msgPour = " pour résister à un effet"; + let msgPour = " pour r\xE9sister \xE0 un effet"; let msgRate = ", " + nomPerso(target) + " rate son jet de sauvegarde"; let saveOpts = { msgPour: msgPour, @@ -10391,7 +10498,7 @@ var COFantasy = COFantasy || function() { }; const saveId = condInTarget ? 'ifSave_' + etatParent.aTraiter + '_' + target.token.id : 'ifSave_' + etatParent.aTraiter + '_' + attaquant.token.id; - if (phase > 0) { //le save a déjà été résolu + if (phase > 0) { //le save a d\xE9j\xE0 \xE9t\xE9 r\xE9solu condInTarget = true; resCondition = target.saveResults && target.saveResults[saveId]; break; @@ -10407,7 +10514,7 @@ var COFantasy = COFantasy || function() { branch = ite.else; target.saveResults[saveId] = true; } else { - branch = ite.then; //on teste si le save est raté + branch = ite.then; //on teste si le save est rat\xE9 target.saveResults[saveId] = false; } if (branch === undefined) { @@ -10430,7 +10537,7 @@ var COFantasy = COFantasy || function() { else branch = ite.else; if (branch === undefined) { callIfAllDone(etatParent, callback); - return condInTarget; //On garde l'ite si on dépend de la cible + return condInTarget; //On garde l'ite si on d\xE9pend de la cible } //On copie les champs de scope dans options ou dans target if (phase === 0) @@ -10443,7 +10550,7 @@ var COFantasy = COFantasy || function() { }); } - // Retourne tous les attributs dans attrs, de nom name ou commençant par name_ + // Retourne tous les attributs dans attrs, de nom name ou commen\xE7ant par name_ function allAttributesNamed(attrs, name) { let reg = new RegExp("^" + name + "($|_|\\()"); return attrs.filter(function(obj) { @@ -10559,7 +10666,7 @@ var COFantasy = COFantasy || function() { already = already || new Set(); let pid = [perso.charId, perso.token.id]; if (already.has(pid)) { - error("Il y a un cycle d'initiatives dérivées les unes des autres impliquant " + nomPerso(perso), already); + error("Il y a un cycle d'initiatives d\xE9riv\xE9es les unes des autres impliquant " + nomPerso(perso), already); return perso; } let persoD = initDerivee(perso, already); @@ -10590,7 +10697,7 @@ var COFantasy = COFantasy || function() { // retourne undefined sinon } - //ne rajoute pas evt à l'historique + //ne rajoute pas evt \xE0 l'historique function persoInit(perso, evt, already) { let persoD = initDerivee(perso); if (persoD) perso = persoD; @@ -10604,13 +10711,13 @@ var COFantasy = COFantasy || function() { init += ficheAttributeAsInt(perso, 'mod_initiative', 0); } if (attributeAsBool(perso, 'formeDArbre')) init = 7; - //Règle optionelle : +1d6, à lancer en entrant en combat + //R\xE8gle optionelle : +1d6, \xE0 lancer en entrant en combat if (reglesOptionelles.initiative.val.initiative_variable.val) { let bonusVariable; let jetPartage; if (reglesOptionelles.initiative.val.initiative_variable_individuelle.val) { // Un jet par perso mook bonusVariable = attributeAsInt(perso, 'bonusInitVariable', 0); - } else { //Un seul pour tous les mook du même personnage + } else { //Un seul pour tous les mook du m\xEAme personnage bonusVariable = charAttributeAsInt(perso, 'bonusInitVariable', 0); jetPartage = true; } @@ -10624,7 +10731,7 @@ var COFantasy = COFantasy || function() { let msgSecret = perso.token.get('layer') == 'gmlayer'; if (!jetCache) { msg += onGenre(perso, 'Il', 'Elle') + " fait " + rollD6.roll; - msg += " à son jet d'initiative"; + msg += " \xE0 son jet d'initiative"; } setTokenAttr(perso, 'bonusInitVariable', bonusVariable, evt, { msg: msg, @@ -10639,9 +10746,9 @@ var COFantasy = COFantasy || function() { init += attributeAsInt(perso, 'bonusInitEmbuscade', 0); // Familier if (compagnonPresent(perso, 'familier')) init += 2; - // Sixième sens en sort + // Sixi\xE8me sens en sort if (attributeAsBool(perso, 'sixiemeSens')) init += 2; - // Voie du chef d'armée rangs 2 et 3 (Capitaine) + // Voie du chef d'arm\xE9e rangs 2 et 3 (Capitaine) let bonusCapitaine = aUnCapitaine(perso, evt); if (bonusCapitaine) init += parseInt(bonusCapitaine); if (predicateAsBool(perso, 'graceFeline')) { @@ -10668,19 +10775,20 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(perso, 'intelligenceDuCombat')) { init += modCarac(perso, 'intelligence'); } - // Réflexes felins de la Voie du pourfendeur + // R\xE9flexes felins de la Voie du pourfendeur init += predicateAsInt(perso, 'reflexesFelins', 0); - // Âme féline (félis) + // \xC2me f\xE9line (f\xE9lis) init += predicateAsInt(perso, 'ameFeline', 0); init += predicateAsInt(perso, 'vitesseDuFelin', 0); init += predicateAsInt(perso, 'espritVide', 0, 3); init += predicateAsInt(perso, 'pasDuVent', 0, 1); //Prescience de l'ensorceleur if (attributeAsBool(perso, 'prescienceUtilisee')) init += 10; - //Forêt vivante + //For\xEAt vivante if (attributeAsBool(perso, 'foretVivanteEnnemie')) { init -= 5; } + init += predicateAsInt(perso, 'rapideCommeSonOmbre', 0, 3); return init; } @@ -10701,12 +10809,12 @@ var COFantasy = COFantasy || function() { }); } - //ne rajoute pas evt à l'historique - //options: recompute : si pas encore agi, on remet à sa place dans le turn order - //already est là pour éviter les récursions infinies + //ne rajoute pas evt \xE0 l'historique + //options: recompute : si pas encore agi, on remet \xE0 sa place dans le turn order + //already est l\xE0 pour \xE9viter les r\xE9cursions infinies //boutonRoll: vient de l'utilisation d'un bouton de roll function initiative(selected, evt, recompute, already, boutonRoll) { //set initiative for selected tokens - // Toujours appelé quand on entre en combat + // Toujours appel\xE9 quand on entre en combat // Initialise le compteur de tour, si besoin // Assumption: all tokens that have not acted yet are those before the turn // counter. @@ -10716,7 +10824,7 @@ var COFantasy = COFantasy || function() { // Tokens appearing before the turn are sorted if (!Campaign().get('initiativepage')) evt.initiativepage = false; let debutCombat = false; - if (!stateCOF.combat) { //actions de début de combat + if (!stateCOF.combat) { //actions de d\xE9but de combat evt.combat = false; stateCOF.combat = { tour: 1, @@ -10731,7 +10839,7 @@ var COFantasy = COFantasy || function() { }]), initiativepage: true }); - removeAllAttributes('transeDeGuérison', evt); + removeAllAttributes('transeDeGu\xE9rison', evt); debutCombat = true; } const combat = stateCOF.combat; @@ -10739,7 +10847,7 @@ var COFantasy = COFantasy || function() { Campaign().set('initiativepage', true); } let to = getTurnOrder(combat, evt); - if (to.pasAgi.length === 0) { // Fin de tour, on met le tour à la fin et on retrie + if (to.pasAgi.length === 0) { // Fin de tour, on met le tour \xE0 la fin et on retrie to.pasAgi = to.dejaAgi; to.dejaAgi = []; } @@ -10749,7 +10857,7 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(perso) { let pageId = perso.token.get('pageid'); combat.pageId = pageId; - //Si besoin, on stoque les PVs de début de combat + //Si besoin, on stoque les PVs de d\xE9but de combat if (!attributeAsBool(perso, 'PVsDebutCombat')) { setTokenAttr(perso, 'PVsDebutCombat', perso.token.get('bar1_value'), evt); } @@ -10774,7 +10882,7 @@ var COFantasy = COFantasy || function() { } } let init = persoInit(perso, evt); - // On place le token à sa place dans la liste du tour + // On place le token \xE0 sa place dans la liste du tour let dejaIndex = to.dejaAgi.findIndex(function(elt) { return (elt.id == perso.token.id); @@ -10791,7 +10899,7 @@ var COFantasy = COFantasy || function() { updateNextInit(perso); return true; } else { - return false; //On enlève le perso des pasAgi + return false; //On enl\xE8ve le perso des pasAgi } } push = false; //Sinon, comme on ne recalcule pas, on le laisse @@ -10839,7 +10947,7 @@ var COFantasy = COFantasy || function() { }; addAura(perso, aura, aurasCreees, combat, evt); }); - //Les autres persos qui entrent en combat en même temps + //Les autres persos qui entrent en combat en m\xEAme temps let ajouterEnCombat = predicatesNamed(perso, 'entrerEnCombatAvec'); if (ajouterEnCombat.length > 0) { let aec = new Set(ajouterEnCombat); @@ -10871,7 +10979,7 @@ var COFantasy = COFantasy || function() { to.dejaAgi[dejaIndex].pr = init; } }); - if (debutCombat) { //On cherche si un des personnages de la carte a la capacité Prescience + if (debutCombat) { //On cherche si un des personnages de la carte a la capacit\xE9 Prescience let allToks = findObjs({ _type: 'graphic', @@ -10887,7 +10995,7 @@ var COFantasy = COFantasy || function() { }; return capaciteDisponible(perso, 'prescience', 'combat'); }); - if (prescience) { //Il faut stoquer les positions de tous les token pour le retour en arrière. + if (prescience) { //Il faut stoquer les positions de tous les token pour le retour en arri\xE8re. stateCOF.prescience = { evt: evt, dernieresPositions: [] @@ -10934,7 +11042,7 @@ var COFantasy = COFantasy || function() { function initiativeInterface(msg) { getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - error("Dans !cof-init : rien à faire, pas de token selectionné", msg); + error("Dans !cof-init : rien \xE0 faire, pas de token selectionn\xE9", msg); return; } aura_token_on_turn = msg.content.indexOf('--aura') !== -1; @@ -11060,7 +11168,7 @@ var COFantasy = COFantasy || function() { }); return r !== undefined; } catch (uriError) { - log("Erreur de décodage URI dans la note GM de " + token.get('name') + " : " + gmNotes); + log("Erreur de d\xE9codage URI dans la note GM de " + token.get('name') + " : " + gmNotes); } } return false; @@ -11070,9 +11178,9 @@ var COFantasy = COFantasy || function() { return false; } - // bonus d'attaque d'un token, indépendament des options + // bonus d'attaque d'un token, ind\xE9pendament des options // Mise en commun pour attack et attaque-magique - // options pour modifier éventuellement l'affichage si pas de DM et pour mettre à jour options.bonusDM si présent + // options pour modifier \xE9ventuellement l'affichage si pas de DM et pour mettre \xE0 jour options.bonusDM si pr\xE9sent function bonusDAttaque(personnage, explications, evt, options) { explications = explications || []; let tempAttkMod; // Utilise la barre 3 de l'attaquant @@ -11099,7 +11207,7 @@ var COFantasy = COFantasy || function() { attributeAsInt(personnage, 'chantDesHerosTempeteDeManaIntense', 0); bonusChantDesHeros += chantDesHerosIntense; attBonus += bonusChantDesHeros; - explications.push("Chant des héros => +" + bonusChantDesHeros + " en Attaque"); + explications.push("Chant des h\xE9ros => +" + bonusChantDesHeros + " en Attaque"); if (chantDesHerosIntense) removeTokenAttr(personnage, 'chantDesHerosTempeteDeManaIntense', evt); } @@ -11108,7 +11216,7 @@ var COFantasy = COFantasy || function() { let benedictionIntense = attributeAsInt(personnage, 'benedictionTempeteDeManaIntense', 0); bonusBenediction += benedictionIntense; attBonus += bonusBenediction; - explications.push("Bénédiction => +" + bonusBenediction + " en Attaque"); + explications.push("B\xE9n\xE9diction => +" + bonusBenediction + " en Attaque"); if (benedictionIntense) removeTokenAttr(personnage, 'benedictionTempeteDeManaIntense', evt); } @@ -11123,17 +11231,17 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'lameDeLigneePerdue')) { attBonus -= 1; - explications.push("Lame de lignée perdue => -1 en Attaque"); + explications.push("Lame de lign\xE9e perdue => -1 en Attaque"); } if (attributeAsBool(personnage, 'strangulation')) { let malusStrangulation = 1 + attributeAsInt(personnage, 'dureeStrangulation', 0); attBonus -= malusStrangulation; - explications.push("L'attaquant est étranglé => -" + malusStrangulation + " en Attaque"); + explications.push("L'attaquant est \xE9trangl\xE9 => -" + malusStrangulation + " en Attaque"); } if (getState(personnage, 'renverse')) { attBonus -= 5; - explications.push("Attaquant à terre => -5 en Attaque"); + explications.push("Attaquant \xE0 terre => -5 en Attaque"); } let attrPosture = tokenAttribute(personnage, 'postureDeCombat'); if (attrPosture.length > 0) { @@ -11156,7 +11264,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'cadavreAnime')) { attBonus -= 4; - explications.push("Cadavre animé => -2 en Attaque"); + explications.push("Cadavre anim\xE9 => -2 en Attaque"); } let bonusCapitaine = aUnCapitaine(personnage, evt); if (bonusCapitaine) { @@ -11171,13 +11279,13 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(personnage, 'forceDeGeant')) { let bonusForceDeGeant = getIntValeurOfEffet(personnage, 'forceDeGeant', 2); attBonus += bonusForceDeGeant; - explications.push("Force de géant => +" + bonusForceDeGeant + " en Attaque"); + explications.push("Force de g\xE9ant => +" + bonusForceDeGeant + " en Attaque"); } if (attributeAsBool(personnage, 'nueeDInsectes')) { let malusNuee = 2 + attributeAsInt(personnage, 'nueeDInsectesTempeteDeManaIntense', 0); attBonus -= malusNuee; - explications.push("Nuée d\'insectes => -" + malusNuee + " en Attaque"); + explications.push("Nu\xE9e d\'insectes => -" + malusNuee + " en Attaque"); if (malusNuee > 2) removeTokenAttr(personnage, 'nueeDInsectesTempeteDeManaIntense', evt); } @@ -11185,13 +11293,13 @@ var COFantasy = COFantasy || function() { let malusNueeCriquets = 3 + attributeAsInt(personnage, 'nueeDeCriquetsTempeteDeManaIntense', 0); attBonus -= malusNueeCriquets; - explications.push("Nuée de criquets => -" + malusNueeCriquets + " en Attaque"); + explications.push("Nu\xE9e de criquets => -" + malusNueeCriquets + " en Attaque"); if (malusNueeCriquets > 3) removeTokenAttr(personnage, 'nueeDeCriquetsTempeteDeManaIntense', evt); } if (attributeAsBool(personnage, 'nueeDeScorpions')) { attBonus -= 3; - explications.push("Nuée de scorpions => -3 en Attaque"); + explications.push("Nu\xE9e de scorpions => -3 en Attaque"); } if (attributeAsBool(personnage, 'etatExsangue')) { attBonus -= 2; @@ -11199,7 +11307,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'armeBrulante')) { attBonus -= 2; - explications.push("Arme brûlante => -2 en Attaque"); + explications.push("Arme br\xFBlante => -2 en Attaque"); } if (marcheSylvestreActive(personnage)) { attBonus += 2; @@ -11207,11 +11315,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'prisonVegetale')) { attBonus -= getIntValeurOfEffet(personnage, 'prisonVegetale', 2); - explications.push("Prison végétale : -2 en Attaque"); + explications.push("Prison v\xE9g\xE9tale : -2 en Attaque"); } if (attributeAsBool(personnage, 'toiles')) { attBonus -= getIntValeurOfEffet(personnage, 'toiles', 2); - explications.push("Entravé : -2 en Attaque"); + explications.push("Entrav\xE9 : -2 en Attaque"); } if (attributeAsBool(personnage, 'masqueDuPredateur')) { let bonusMasque = getIntValeurOfEffet(personnage, 'masqueDuPredateur', modCarac(personnage, 'sagesse')); @@ -11219,10 +11327,10 @@ var COFantasy = COFantasy || function() { bonusMasque += masqueIntense; attBonus += bonusMasque; if (options && options.bonusDM !== undefined) { - explications.push("Masque du prédateur : +" + bonusMasque + " en Attaque et DM"); + explications.push("Masque du pr\xE9dateur : +" + bonusMasque + " en Attaque et DM"); options.bonusDM += bonusMasque; } else { - explications.push("Masque du prédateur : +" + bonusMasque + " en Attaque"); + explications.push("Masque du pr\xE9dateur : +" + bonusMasque + " en Attaque"); } if (masqueIntense) removeTokenAttr(personnage, 'masqueDuPredateurTempeteDeManaIntense', evt); @@ -11231,15 +11339,15 @@ var COFantasy = COFantasy || function() { getIntValeurOfEffet(personnage, 'masqueDuPredateurAmeLiee', 1); attBonus += bonusMasque; if (options && options.bonusDM !== undefined) { - explications.push("Masque du prédateur lié : +" + bonusMasque + " en Attaque et DM"); + explications.push("Masque du pr\xE9dateur li\xE9 : +" + bonusMasque + " en Attaque et DM"); options.bonusDM += bonusMasque; } else { - explications.push("Masque du prédateur lié : +" + bonusMasque + " en Attaque"); + explications.push("Masque du pr\xE9dateur li\xE9 : +" + bonusMasque + " en Attaque"); } } if (attributeAsBool(personnage, 'armeSecreteBarde')) { attBonus -= 10; - explications.push("Déstabilisé par une action de charme => -10 en Attaque"); + explications.push("D\xE9stabilis\xE9 par une action de charme => -10 en Attaque"); } if (attributeAsBool(personnage, 'espaceExigu')) { let bonusForce = modCarac(personnage, 'force'); @@ -11251,28 +11359,28 @@ var COFantasy = COFantasy || function() { attBonus -= 1; } if (attributeAsBool(personnage, 'agrippeParUnDemon')) { - explications.push("agrippé : -3 en Attaque"); + explications.push("agripp\xE9 : -3 en Attaque"); attBonus -= 3; } if (attributeAsBool(personnage, 'ondesCorruptrices') && !attributeAsBool(personnage, 'sangDeLArbreCoeur') && !predicateAsBool(personnage, 'porteurDuBouclierDeGrabuge')) { let malus = attributeAsInt(personnage, 'ondesCorruptrices', 2); - explications.push("nauséeux : -" + malus + " aux tests"); + explications.push("naus\xE9eux : -" + malus + " aux tests"); attBonus -= malus; } if (attributeAsBool(personnage, 'inconfort')) { let inconfortValeur = attributeAsInt(personnage, 'inconfortValeur', 0); attBonus -= inconfortValeur; - explications.push("Gêne due à l'armure : -" + inconfortValeur); + explications.push("G\xEAne due \xE0 l'armure : -" + inconfortValeur); } if (attributeAsBool(personnage, 'putrefactionOutreTombe')) { attBonus -= 2; - explications.push("Putréfaction => -2 en Attaque"); + explications.push("Putr\xE9faction => -2 en Attaque"); } if (attributeAsBool(personnage, 'secoue')) { attBonus -= 2; - let msg = "Secoué" + eForFemale(personnage) + " => -2 en Attaque"; + let msg = "Secou\xE9" + eForFemale(personnage) + " => -2 en Attaque"; explications.push(msg); } if (attributeAsBool(personnage, 'bonusAttaqueTemp')) { @@ -11293,7 +11401,7 @@ var COFantasy = COFantasy || function() { let bonus = getIntValeurOfEffet(personnage, 'detournerLeRegard', 2); let msg; if (bonus < 5) { - msg = "Détourne le regard"; + msg = "D\xE9tourne le regard"; } else { msg = "Ferme les yeux"; } @@ -11324,8 +11432,8 @@ var COFantasy = COFantasy || function() { switch (ficheAttribute(perso, 'taille', '').trim().toLowerCase()) { case "minuscule": return 1; - case "très petit": - case "très petite": + case "tr\xE8s petit": + case "tr\xE8s petite": case "tres petit": return 2; case "petit": @@ -11339,14 +11447,15 @@ var COFantasy = COFantasy || function() { case "grand": case "grande": return 5; - case "énorme": + case "\xE9norme": case "enorme": return 6; case "colossal": case "colossale": return 7; - default: //On passe à la méthode suivante + default: //On passe \xE0 la m\xE9thode suivante } + if (predicateAsBool(perso, 'petiteTaille')) return 3; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.trim().toLowerCase(); @@ -11366,7 +11475,7 @@ var COFantasy = COFantasy || function() { case 'demi-orque': case 'orque': case 'gnome': - case 'âme-forgée': + case '\xE2me-forg\xE9e': return 4; case 'centaure': case 'demi-ogre': @@ -11379,11 +11488,11 @@ var COFantasy = COFantasy || function() { //Retourne un encodage des tailes : // 1 : minuscule - // 2 : très petit + // 2 : tr\xE8s petit // 3 : petit // 4 : moyen // 5 : grand - // 6 : énorme + // 6 : \xE9norme // 7 : colossal function taillePersonnage(perso, def) { if (perso.taille) return perso.taille; @@ -11393,7 +11502,7 @@ var COFantasy = COFantasy || function() { return taille; } - //tm doit être stateCOF.tenebresMagiques, et bien défini. + //tm doit \xEAtre stateCOF.tenebresMagiques, et bien d\xE9fini. function eclaireParFioleDeLumiere(perso, tm) { let fio = tm.fioleDeLumiere; if (fio === undefined || fio.porteur === undefined) return false; @@ -11423,7 +11532,7 @@ var COFantasy = COFantasy || function() { if (options.difficultePVmax) { let pvmax = parseInt(target.token.get('bar1_max')); if (isNaN(pvmax)) { - error("Points de vie de " + nomPerso(target) + " mal formés", + error("Points de vie de " + nomPerso(target) + " mal form\xE9s", target.token.get('bar1_max')); return 0; } @@ -11431,7 +11540,7 @@ var COFantasy = COFantasy || function() { } else if (options.difficultePV) { let pv = parseInt(target.token.get('bar1_value')); if (isNaN(pv)) { - error("Points de vie de " + nomPerso(target) + " mal formés", + error("Points de vie de " + nomPerso(target) + " mal form\xE9s", target.token.get('bar1_value')); return 0; } @@ -11493,7 +11602,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'armureDuMage')) { let bonusArmureDuMage = getIntValeurOfEffet(target, 'armureDuMage', 4); - if (defense > 12) defense += bonusArmureDuMage / 2; // On a déjà une armure physique, ça ne se cumule pas. + if (defense > 12) defense += bonusArmureDuMage / 2; // On a d\xE9j\xE0 une armure physique, \xE7a ne se cumule pas. else defense += bonusArmureDuMage; } defense += ficheAttributeAsInt(target, 'DEFDIV', 0); @@ -11503,7 +11612,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(target, 'inconfort')) { let inconfortValeur = attributeAsInt(target, "inconfortValeur", 0); defense -= inconfortValeur; - explications.push("L'adversaire est gêné par son armure : -" + inconfortValeur + " en DEF"); + explications.push("L'adversaire est g\xEAn\xE9 par son armure : -" + inconfortValeur + " en DEF"); } let formeDarbre; if (attributeAsBool(target, 'formeDArbre')) { @@ -11512,12 +11621,12 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'statueDeBois')) defense = 10; else if (attributeAsBool(target, 'petrifie')) defense = 5; - // Malus de défense global pour les longs combats + // Malus de d\xE9fense global pour les longs combats let combat = stateCOF.combat; if (combat && reglesOptionelles.haute_DEF.val.usure_DEF.val && !combat.usureOff && combat.tour > 1) defense -= (Math.floor((combat.tour - 1) / reglesOptionelles.haute_DEF.val.usure_DEF.val) * 2); - // Autres modificateurs de défense + // Autres modificateurs de d\xE9fense defense += attributeAsInt(target, 'defenseTotale', 0); let pacifisme = predicateAsInt(target, 'pacifisme', 0, 5); if (pacifisme > 0 && !attributeAsBool(target, 'attributDeCombat_pacifismeAnnule')) @@ -11538,14 +11647,14 @@ var COFantasy = COFantasy || function() { bonusPeau = Math.ceil(bonusPeau * 1.5); } defense += bonusPeau; - explications.push("Peau d'écorce : +" + bonusPeau + " en DEF"); + explications.push("Peau d'\xE9corce : +" + bonusPeau + " en DEF"); if (peauIntense && evt && !options.test) removeTokenAttr(target, 'peauDEcorceTempeteDeManaIntense', evt); } if (attributeAsBool(target, 'peauDEcorceAmeLiee')) { let bonus = getIntValeurOfEffet(target, 'peauDEcorceAmeLiee', 1); defense += bonus; - explications.push("Peau d'écorce liée : +" + bonus + " en DEF"); + explications.push("Peau d'\xE9corce li\xE9e : +" + bonus + " en DEF"); } if (attributeAsBool(target, 'champDeProtection')) { let bonusChamp = @@ -11565,13 +11674,13 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'sixiemeSens')) { defense += 2; - explications.push("Sixième sens : +2 DEF"); + explications.push("Sixi\xE8me sens : +2 DEF"); } if (getState(target, 'surpris')) defense -= 5; if (getState(target, 'renverse')) defense -= 5; if (getState(target, 'aveugle') || attributeAsBool(target, 'aveugleManoeuvre')) { if (options.contact && predicateAsBool(target, 'radarMental') && attaquant && !estNonVivant(attaquant)) { - explications.push(tokenName + " est aveugle, mais bénéficie de son radar mental"); + explications.push(tokenName + " est aveugle, mais b\xE9n\xE9ficie de son radar mental"); } else { defense -= 5; } @@ -11581,7 +11690,7 @@ var COFantasy = COFantasy || function() { if (getState(target, 'invisible') && attaquant && !attributeAsBool(attaquant, 'detectionDeLInvisible')) { if (options.distance) { if (options.tirAveugle) { - explications.push("Cible invisible, mais " + nomPerso(attaquant) + " sait tirer à l'aveugle"); + explications.push("Cible invisible, mais " + nomPerso(attaquant) + " sait tirer \xE0 l'aveugle"); } else { defense += 10; explications.push("Invisible : +10 en DEF"); @@ -11617,13 +11726,13 @@ var COFantasy = COFantasy || function() { defense += modCarac(target, 'intelligence'); } if (attributeAsBool(target, 'armeSecreteBarde')) { - explications.push(tokenName + " est déstabilisé par une action de charme => -10 en DEF"); + explications.push(tokenName + " est d\xE9stabilis\xE9 par une action de charme => -10 en DEF"); defense -= 10; } if (options.metal && attributeAsBool(target, 'magnetisme')) { let magnetisme = getIntValeurOfEffet(target, 'magnetisme', 5); defense += magnetisme; - explications.push(tokenName + " contrôle le magnétisme (+" + magnetisme + " DEF)"); + explications.push(tokenName + " contr\xF4le le magn\xE9tisme (+" + magnetisme + " DEF)"); } if (attributeAsBool(target, 'diversionManoeuvre')) { let diversion = getIntValeurOfEffet(target, 'diversionManoeuvre', -5); @@ -11632,7 +11741,7 @@ var COFantasy = COFantasy || function() { } if (options.attaqueMentale && predicateAsBool(target, 'bouclierPsi')) { defense += 5; - explications.push(tokenName + " bénéficie d'un bouclier psi => +5 DEF"); + explications.push(tokenName + " b\xE9n\xE9ficie d'un bouclier psi => +5 DEF"); } if (attributeAsBool(target, 'monteSur')) { if (predicateAsBool(target, 'montureLoyale')) { @@ -11641,7 +11750,7 @@ var COFantasy = COFantasy || function() { } if (options.contact && predicateAsBool(target, "horsDePortee")) { defense += 5; - explications.push(tokenName + " est hors de portée sur sa monture => +5 DEF"); + explications.push(tokenName + " est hors de port\xE9e sur sa monture => +5 DEF"); } } let attrsProtegePar = findObjs({ @@ -11657,20 +11766,20 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes = evt.deletedAttributes || []; evt.deletedAttributes.push(attr); attr.remove(); - sendPerso(target, "n'est plus protégé : son protecteur n'est pas sur la page"); + sendPerso(target, "n'est plus prot\xE9g\xE9 : son protecteur n'est pas sur la page"); } return; } let nameProtecteur = nomPerso(protecteur); if (!isActive(protecteur)) { - explications.push(nameProtecteur + " n'est pas en état de protéger " + + explications.push(nameProtecteur + " n'est pas en \xE9tat de prot\xE9ger " + tokenName); return; } let distTargetProtecteur = distanceCombat(target.token, protecteur.token, pageId); if (distTargetProtecteur > 0) { explications.push(nameProtecteur + " est trop loin de " + - tokenName + " pour le protéger"); + tokenName + " pour le prot\xE9ger"); return; } if (ficheAttributeAsInt(protecteur, 'defbouclieron', 0) === 0) { @@ -11684,7 +11793,7 @@ var COFantasy = COFantasy || function() { if (persoEstPNJ(protecteur)) defBouclierProtecteur = 2; else defBouclierProtecteur = ficheAttributeAsInt(protecteur, 'defbouclier', 0) + predicateAsInt(protecteur, 'bouclierDeLaFoi', 0, 1); defense += defBouclierProtecteur; - explications.push(nameProtecteur + " protège " + + explications.push(nameProtecteur + " prot\xE8ge " + tokenName + " de son bouclier (+" + defBouclierProtecteur + " DEF)"); } }); @@ -11706,7 +11815,7 @@ var COFantasy = COFantasy || function() { let attaqueAOutrance = attributeAsInt(target, 'attaqueAOutrance', 0); if (attaqueAOutrance) { defense -= attaqueAOutrance; - explications.push("Attaque à outrance => -" + attaqueAOutrance + " DEF"); + explications.push("Attaque \xE0 outrance => -" + attaqueAOutrance + " DEF"); } let niveau = ficheAttributeAsInt(target, 'niveau', 1); let instinctSurvie = predicateAsInt(target, 'instinctDeSurvie', 0, niveau * 5); @@ -11720,7 +11829,7 @@ var COFantasy = COFantasy || function() { defense += predicateAsInt(target, 'DEF_magie', 0); if (predicateAsBool(target, 'chasseurDeSorciere')) { defense += 2; - explications.push("Chasseur de sorcière => +2 DEF"); + explications.push("Chasseur de sorci\xE8re => +2 DEF"); } } if (marcheSylvestreActive(target)) { @@ -11729,11 +11838,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'prisonVegetale')) { defense -= getIntValeurOfEffet(target, 'prisonVegetale', 2); - explications.push("Prison végétale => -2 DEF"); + explications.push("Prison v\xE9g\xE9tale => -2 DEF"); } if (attributeAsBool(target, 'toiles')) { defense -= getIntValeurOfEffet(target, 'toiles', 2); - explications.push("Entravé => -2 DEF"); + explications.push("Entrav\xE9 => -2 DEF"); } if (attributeAsBool(target, 'protectionContreLeMal') && (attaquant && estMauvais(attaquant))) { @@ -11759,7 +11868,7 @@ var COFantasy = COFantasy || function() { explications.push(msgRage + " du berserk => " + modRage + " DEF"); defense += modRage; } else if (attributeAsBool(target, 'frenesieMinotaure')) { - explications.push("Frenésie => -2 en DEF"); + explications.push("Fren\xE9sie => -2 en DEF"); defense -= 2; } let combatEnPhalange = predicateAsBool(target, 'combatEnPhalange'); @@ -11816,36 +11925,36 @@ var COFantasy = COFantasy || function() { defense += predicateAsInt(target, 'voieDesRunes', 0, 1); if (attributeAsBool(target, 'attaqueRisquee')) { defense -= 4; - explications.push("Suite à une attaque risquée, -4 en DEF"); + explications.push("Suite \xE0 une attaque risqu\xE9e, -4 en DEF"); } let armeTarget = armesEnMain(target); //peuple target.arme et armeGauche - //gestion de l'épieu + //gestion de l'\xE9pieu if (attaquant) { if (armeTarget && armeTarget.epieu && !armesEnMain(attaquant)) { defense += 2; - explications.push("Épieu contre une attaque sans arme => +2 DEF"); + explications.push("\xC9pieu contre une attaque sans arme => +2 DEF"); } } if (options.distance) { let bonusCouvert = attributeAsInt(target, 'bonusCouvert'); if (bonusCouvert) { if (attaquant && predicateAsBool(attaquant, 'joliCoup')) { - explications.push("Cible à couvert, mais " + nomPerso(attaquant) + " sait bien viser"); + explications.push("Cible \xE0 couvert, mais " + nomPerso(attaquant) + " sait bien viser"); } else { defense += bonusCouvert; - explications.push("Cible à couvert => +" + bonusCouvert + " DEF"); + explications.push("Cible \xE0 couvert => +" + bonusCouvert + " DEF"); } } if (attributeAsBool(target, 'progresserACouvert')) { if (attaquant && predicateAsBool(attaquant, 'joliCoup')) { - explications.push("Cible à couvert de bouclier, mais " + nomPerso(attaquant) + " sait bien viser"); + explications.push("Cible \xE0 couvert de bouclier, mais " + nomPerso(attaquant) + " sait bien viser"); } else { defense += 5; - explications.push("Cible à couvert de bouclier => +5 DEF"); + explications.push("Cible \xE0 couvert de bouclier => +5 DEF"); } } } - //Chair à canon + //Chair \xE0 canon if (capaciteDisponible(target, 'chairACanon', 'tour')) { let tokensChairACanon = findObjs({ _type: 'graphic', @@ -11887,15 +11996,15 @@ var COFantasy = COFantasy || function() { switch (taillePersonnage(attaquant, 4)) { case 5: defense += 2; - explications.push(nomPerso(target) + " réduit la distance => +2 en DEF"); + explications.push(nomPerso(target) + " r\xE9duit la distance => +2 en DEF"); break; case 6: defense += 3; - explications.push(nomPerso(target) + " réduit la distance => +3 en DEF"); + explications.push(nomPerso(target) + " r\xE9duit la distance => +3 en DEF"); break; case 7: defense += 4; - explications.push(nomPerso(target) + " réduit la distance => +4 en DEF"); + explications.push(nomPerso(target) + " r\xE9duit la distance => +4 en DEF"); } } if (attaquant && predicateAsBool(target, 'insignifiant')) { @@ -11912,11 +12021,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'etreinteImmole')) { defense -= 5; - explications.push(nomPerso(target) + " étreint quelqu'un => -5 en DEF"); + explications.push(nomPerso(target) + " \xE9treint quelqu'un => -5 en DEF"); } if (attributeAsBool(target, 'etreinteScorpionRatee')) { defense -= 5; - explications.push(nomPerso(target) + " est étreint par un scorpion => -5 DEF"); + explications.push(nomPerso(target) + " est \xE9treint par un scorpion => -5 DEF"); } if (attaquant && predicateAsBool(target, 'langageSombreHetre') && estElfeNoir(attaquant)) { defense += 1; @@ -11924,7 +12033,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'presenceGlaciale')) { let defenseGlaciale = getIntValeurOfEffet(target, 'presenceGlaciale', 4); - explications.push("Présence glaciale => +" + defenseGlaciale + " en DEF"); + explications.push("Pr\xE9sence glaciale => +" + defenseGlaciale + " en DEF"); defense += defenseGlaciale; } if (attributeAsBool(target, 'cyclone')) { @@ -11956,24 +12065,24 @@ var COFantasy = COFantasy || function() { defense += 10; } if (options.contact && attributeAsBool(target, 'tenirADistance')) { - explications.push("Tient l'ennemi à distance => +5 en DEF"); + explications.push("Tient l'ennemi \xE0 distance => +5 en DEF"); defense += 5; } let tm = stateCOF.tenebresMagiques; if (tm) { if (estDemon(target)) { if (eclaireParFioleDeLumiere(target, tm)) { - explications.push("Aveuglé par la fiole de lumière => -2 en DEF"); + explications.push("Aveugl\xE9 par la fiole de lumi\xE8re => -2 en DEF"); defense -= 2; } } else if (attaquant && !eclaireParFioleDeLumiere(attaquant, tm)) { - explications.push("Ténèbres magiques => -5 en DEF"); + explications.push("T\xE9n\xE8bres magiques => -5 en DEF"); defense -= 5; } } if (attributeAsBool(target, 'agrippeParUnDemon')) { - explications.push("agrippé => -3 en DEF"); + explications.push("agripp\xE9 => -3 en DEF"); defense -= 3; } if (estNecromancie(options) && attributeAsBool(target, 'sangDeLArbreCoeur')) { @@ -11981,7 +12090,7 @@ var COFantasy = COFantasy || function() { defense += 5; } if (predicateAsBool(target, 'liberateurDeDorn') && estGeant(attaquant)) { - explications.push('Libérateur de Dorn => +2 en DEF'); + explications.push('Lib\xE9rateur de Dorn => +2 en DEF'); defense += 2; } let pirouettes = predicateAsInt(target, 'pirouettes', 0); @@ -11999,14 +12108,14 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'paradeCroisee')) { let bonus = getIntValeurOfEffet(target, 'paradeCroisee', 2); - explications.push("Parade croisée => +" + bonus + " en DEF"); + explications.push("Parade crois\xE9e => +" + bonus + " en DEF"); defense += bonus; } let conditions = attributeAsInt(target, 'conditionsHostiles', 0, 2); if (conditions > 0 && (!predicateAsBool(target, 'marcheSylvestre') || conditions > 4)) { let msgConditions = "Conditions "; if (conditions < 5) msgConditions += "hostiles"; - else msgConditions += "extrêmes"; + else msgConditions += "extr\xEAmes"; msgConditions += " : -" + conditions + " en DEF"; explications.push(msgConditions); defense -= conditions; @@ -12026,7 +12135,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(target, 'detournerLeRegard')) { let bonus = getIntValeurOfEffet(target, 'detournerLeRegard', 2); if (bonus < 5) { - explications.push("Détourne le regard => -" + bonus + " en DEF"); + explications.push("D\xE9tourne le regard => -" + bonus + " en DEF"); } else { explications.push("Ferme les yeux => -" + bonus + " en DEF"); } @@ -12034,13 +12143,16 @@ var COFantasy = COFantasy || function() { } defense += predicateAsInt(target, 'DEF', 0); if (attaquant && predicateAsBool(target, 'armeDeLEte') && predicateAsBool(attaquant, 'creatureDeLHiver')) { - explications.push("Protégé par une arme de l'été => +25 en DEF"); + explications.push("Prot\xE9g\xE9 par une arme de l'\xE9t\xE9 => +25 en DEF"); defense += 25; } + if (predicateAsBool(target, 'petiteTaille') && !attributeAsBool(target, 'agrandissement')) { + defense += 1; + } return defense; } - // renvoie l'attribut créé ou mis à jour + // renvoie l'attribut cr\xE9\xE9 ou mis \xE0 jour function setAttrDuree(perso, attr, duree, evt, msg, secret) { let options = { maxVal: getInit(), @@ -12050,23 +12162,23 @@ var COFantasy = COFantasy || function() { return setTokenAttr(perso, attr, duree, evt, options); } - //Tous les bonus de DM normalement calculés dans bonusAttaqueA + //Tous les bonus de DM normalement calcul\xE9s dans bonusAttaqueA function bonusDMA(attaquant, weaponName, evt, explications, options) { if (options.pasDeDmg) return; options.bonusDM = 0; if (attributeAsBool(attaquant, 'baroudHonneurActif')) { - explications.push(nomPerso(attaquant) + " porte une dernière attaque et s'effondre"); + explications.push(nomPerso(attaquant) + " porte une derni\xE8re attaque et s'effondre"); mort(attaquant, function(m) { explications.push(m); }, evt); removeTokenAttr(attaquant, 'baroudHonneurActif', evt); } if (attributeAsBool(attaquant, 'reactionViolente')) { - explications.push("Réaction violente => +1d6 DM"); + explications.push("R\xE9action violente => +1d6 DM"); options.reactionViolente = true; } if (attributeAsBool(attaquant, 'drainDeForce')) { - explications.push("Force drainée => -2 aux DM"); + explications.push("Force drain\xE9e => -2 aux DM"); options.drainDeForce = true; } if (options.contact) { @@ -12077,11 +12189,11 @@ var COFantasy = COFantasy || function() { explications.push(msg); } if (attributeAsBool(attaquant, 'enrage')) { - explications.push("Enragé => +1d6 DM"); + explications.push("Enrag\xE9 => +1d6 DM"); options.enrage = true; } if (attributeAsBool(attaquant, 'rage')) { - explications.push("Enragé => +2 DM"); + explications.push("Enrag\xE9 => +2 DM"); options.rage = true; } let rageBerserk = tokenAttribute(attaquant, 'rageDuBerserk'); @@ -12095,7 +12207,7 @@ var COFantasy = COFantasy || function() { options.rageBerserk = 1; } } else if (attributeAsBool(attaquant, 'frenesieMinotaure')) { - explications.push("Frénésie : +1d6 aux DM"); + explications.push("Fr\xE9n\xE9sie : +1d6 aux DM"); options.rageBerserk = 1; } if (predicateAsBool(attaquant, 'ambidextreDuelliste')) { @@ -12165,7 +12277,7 @@ var COFantasy = COFantasy || function() { let gobant = persoOfIdName(attrGobe[0].get('current'), attaquant.token.get('pageid')); if (gobant === undefined) { - error("Attribut estGobePar mal formé", attrGobe[0].get('current')); + error("Attribut estGobePar mal form\xE9", attrGobe[0].get('current')); attrGobe[0].remove(); unlockToken(attaquant, evt); } else { @@ -12184,7 +12296,7 @@ var COFantasy = COFantasy || function() { let energieImpie = attributeAsInt(attaquant, 'energieImpie', 0); if (energieImpie) { options.bonusDM += energieImpie; - explications.push("Énergie impie => +" + energieImpie + " DM"); + explications.push("\xC9nergie impie => +" + energieImpie + " DM"); } if (options.arcComposite) { let force = modCarac(attaquant, 'force'); @@ -12199,7 +12311,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(attaquant, 'fievreux')) { options.fievreux = true; - explications.push("Fiévreu" + onGenre(attaquant, 'x', 'se') + " => -2 DM"); + explications.push("Fi\xE9vreu" + onGenre(attaquant, 'x', 'se') + " => -2 DM"); } if (options.expertDuCombatDM && !options.pasDeDmg) { let valDesExpert = options.rolls.expertDuCombatDM || rollDePlus(6); @@ -12226,7 +12338,7 @@ var COFantasy = COFantasy || function() { let masqueIntense = attributeAsInt(attaquant, 'masqueDuPredateurTempeteDeManaIntense', 0); bonusMasque += masqueIntense; options.bonusDM += bonusMasque; - explications.push("Masque du prédateur : +" + bonusMasque + " aux DM"); + explications.push("Masque du pr\xE9dateur : +" + bonusMasque + " aux DM"); if (masqueIntense) removeTokenAttr(attaquant, 'masqueDuPredateurTempeteDeManaIntense', evt); } else if (attributeAsBool(attaquant, 'masqueDuPredateurAmeLiee')) { @@ -12234,7 +12346,7 @@ var COFantasy = COFantasy || function() { getIntValeurOfEffet(attaquant, 'masqueDuPredateurAmeLiee', 1); if (bonusMasque > 0) { options.bonusDM += bonusMasque; - explications.push("Masque du prédateur lié : +" + bonusMasque + " aux DM"); + explications.push("Masque du pr\xE9dateur li\xE9 : +" + bonusMasque + " aux DM"); } } if (options.attaqueFlamboyante && options.contact) { @@ -12247,7 +12359,7 @@ var COFantasy = COFantasy || function() { let bonus = getIntValeurOfEffet(attaquant, 'detournerLeRegard', 2); let msg; if (bonus < 5) { - msg = "Détourne le regard"; + msg = "D\xE9tourne le regard"; } else { msg = "Ferme les yeux"; } @@ -12258,7 +12370,7 @@ var COFantasy = COFantasy || function() { return; } - //Bonus en Attaque qui ne dépendent pas du défenseur + //Bonus en Attaque qui ne d\xE9pendent pas du d\xE9fenseur //Remplit le champs options.bonusDM (en partant de 0) function bonusAttaqueA(attaquant, weaponName, evt, explications, options) { let attBonus = 0; @@ -12270,18 +12382,18 @@ var COFantasy = COFantasy || function() { attBonus += 2; if (options.tirDouble.stats && options.tirDouble.stats.name) { explications.push(nomPerso(attaquant) + " tire avec " + - weaponName + " et " + options.tirDouble.stats.name + " à la fois !"); + weaponName + " et " + options.tirDouble.stats.name + " \xE0 la fois !"); } else { explications.push(nomPerso(attaquant) + " tire avec 2 " + - weaponName + "s à la fois !"); + weaponName + "s \xE0 la fois !"); } } if (options.chance) { attBonus += options.chance; let pc = options.chance / 10; - explications.push(pc + " point" + ((pc > 1) ? "s" : "") + " de chance dépensé => +" + options.chance + " en Attaque"); + explications.push(pc + " point" + ((pc > 1) ? "s" : "") + " de chance d\xE9pens\xE9 => +" + options.chance + " en Attaque"); } - if (options.semonce) { + if (options.semonce && attributeAsInt(attaquant, 'attaqueADistanceRatee', 0) == 1) { attBonus += 5; } if (!options.pasDeDmg && !options.feinte) { @@ -12297,7 +12409,7 @@ var COFantasy = COFantasy || function() { } if (options.attaqueAssuree) { attBonus += 5; - explications.push("Attaque assurée => +5 en Attaque et DM/2"); + explications.push("Attaque assur\xE9e => +5 en Attaque et DM/2"); } if (ficheAttributeAsBool(attaquant, 'attaque_dm_temp_check')) { options.attaqueDmTemp = true; @@ -12321,11 +12433,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(attaquant, 'criDuPredateur')) { attBonus += 1; - explications.push("Cri du prédateur => +1 en attaque"); + explications.push("Cri du pr\xE9dateur => +1 en attaque"); } if (attributeAsBool(attaquant, 'baroudHonneurActif')) { attBonus += 5; - explications.push(nomPerso(attaquant) + " porte une dernière attaque et s'effondre"); + explications.push(nomPerso(attaquant) + " porte une derni\xE8re attaque et s'effondre"); mort(attaquant, function(m) { explications.push(m); }, evt); @@ -12340,7 +12452,7 @@ var COFantasy = COFantasy || function() { let cavalierEm = predicateAsInt(attaquant, 'cavalierEmerite'); if (cavalierEm) { attBonus += cavalierEm; - let explCavalierEmerite = "avalier émérite => +" + cavalierEm + " en Attaque"; + let explCavalierEmerite = "avalier \xE9m\xE9rite => +" + cavalierEm + " en Attaque"; if (options.displayName) { explCavalierEmerite = nomPerso(attaquant) + " est un c" + explCavalierEmerite; } else { @@ -12364,15 +12476,15 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(attaquant, 'reactionViolente')) { attBonus += 2; if (options.pasDeDmg) - explications.push("Réaction violente => +2 en Attaque"); + explications.push("R\xE9action violente => +2 en Attaque"); else { - explications.push("Réaction violente => +2 en Attaque et +1d6 DM"); + explications.push("R\xE9action violente => +2 en Attaque et +1d6 DM"); options.reactionViolente = true; } } if (attributeAsBool(attaquant, 'drainDeForce')) { attBonus -= 2; - let msg = "Force drainée => -2 en Attaque"; + let msg = "Force drain\xE9e => -2 en Attaque"; if (options.pasDeDmg || !options.contact) explications.push(msg); else explications.push(msg + " et aux DM"); options.drainDeForce = true; @@ -12380,7 +12492,7 @@ var COFantasy = COFantasy || function() { let energieImpie = attributeAsInt(attaquant, 'energieImpie', 0); if (energieImpie) { attBonus += energieImpie; - let msg = "Énergie impie => +" + energieImpie + " en Attaque"; + let msg = "\xC9nergie impie => +" + energieImpie + " en Attaque"; if (!options.pasDeDmg) { msg += " et aux DM"; options.bonusDM += energieImpie; @@ -12400,21 +12512,21 @@ var COFantasy = COFantasy || function() { attBonus += 5; options.enrage = true; if (options.pasDeDmg) - explications.push("Enragé => +5 en Attaque"); + explications.push("Enrag\xE9 => +5 en Attaque"); else - explications.push("Enragé => +5 en Attaque et +1d6 DM"); + explications.push("Enrag\xE9 => +5 en Attaque et +1d6 DM"); } if (attributeAsBool(attaquant, 'rage')) { attBonus += 2; if (options.pasDeDmg) - explications.push("Enragé => +2 en Attaque"); + explications.push("Enrag\xE9 => +2 en Attaque"); else - explications.push("Enragé => +2 en Attaque et +2 DM"); + explications.push("Enrag\xE9 => +2 en Attaque et +2 DM"); options.rage = true; } if (attributeAsBool(attaquant, 'aspectDuDemon')) { attBonus += getIntValeurOfEffet(attaquant, 'aspectDuDemon', 2); - explications.push("Aspect de démon => +2 en Attaque"); + explications.push("Aspect de d\xE9mon => +2 en Attaque"); } let rageBerserk = tokenAttribute(attaquant, 'rageDuBerserk'); if (rageBerserk.length > 0) { @@ -12441,9 +12553,9 @@ var COFantasy = COFantasy || function() { } else if (attributeAsBool(attaquant, 'frenesieMinotaure')) { attBonus += 2; if (options.pasDeDmg) - explications.push("Frénésie : +2 en Attaque"); + explications.push("Fr\xE9n\xE9sie : +2 en Attaque"); else - explications.push("Frénésie : +2 en Attaque et +1d6 aux DM"); + explications.push("Fr\xE9n\xE9sie : +2 en Attaque et +1d6 aux DM"); options.rageBerserk = 1; } if (ficheAttributeAsBool(attaquant, 'attaque_risquee_check')) { @@ -12451,7 +12563,7 @@ var COFantasy = COFantasy || function() { } if (options.attaqueRisquee) { attBonus += 2; - explications.push("Attaque risquée => +2 en Attaque"); + explications.push("Attaque risqu\xE9e => +2 en Attaque"); if (!options.test) { setAttrDuree(attaquant, 'attaqueRisquee', 1, evt); } @@ -12510,7 +12622,7 @@ var COFantasy = COFantasy || function() { pv = parseInt(attaquant.token.get('bar1_value')); if (pv <= frenesie) { attBonus += 2; - explications.push("Frénésie => +2 en Attaque"); + explications.push("Fr\xE9n\xE9sie => +2 en Attaque"); } } if (predicateAsBool(attaquant, 'hausserLeTon')) { @@ -12554,18 +12666,18 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(attaquant, 'enerve')) { attBonus -= 2; - explications.push("Attaquant énervé => -2 en Attaque"); + explications.push("Attaquant \xE9nerv\xE9 => -2 en Attaque"); } if (attributeAsBool(attaquant, 'osBrises')) { attBonus -= 2; - explications.push("Des os sont brisés => -2 en Attaque"); + explications.push("Des os sont bris\xE9s => -2 en Attaque"); } let attrGobe = tokenAttribute(attaquant, 'estGobePar'); if (attrGobe.length > 0) { let gobant = persoOfIdName(attrGobe[0].get('current'), attaquant.token.get('pageid')); if (gobant === undefined) { - error("Attribut estGobePar mal formé", attrGobe[0].get('current')); + error("Attribut estGobePar mal form\xE9", attrGobe[0].get('current')); attrGobe[0].remove(); unlockToken(attaquant, evt); } else { @@ -12607,7 +12719,7 @@ var COFantasy = COFantasy || function() { } if (actif) { attBonus += 1; - explications.push("Arme de prédiléction => +1 en Attaque"); + explications.push("Arme de pr\xE9dil\xE9ction => +1 en Attaque"); } } if (options.arcComposite) { @@ -12630,7 +12742,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(attaquant, 'fievreux')) { attBonus -= 2; options.fievreux = true; - explications.push("Fiévreu" + onGenre(attaquant, 'x', 'se') + " => -2 en Att. et DM"); + explications.push("Fi\xE9vreu" + onGenre(attaquant, 'x', 'se') + " => -2 en Att. et DM"); } if (options.expertDuCombatTouche) { let valDesExpert = options.rolls.expertDuCombatTouche || rollDePlus(6); @@ -12703,7 +12815,7 @@ var COFantasy = COFantasy || function() { if (conditions > 0 && (!predicateAsBool(attaquant, 'marcheSylvestre') || conditions > 4)) { let msgConditions = "Conditions "; if (conditions < 5) msgConditions += "hostiles"; - else msgConditions += "extrêmes"; + else msgConditions += "extr\xEAmes"; msgConditions += " : -" + conditions + " en attaque"; explications.push(msgConditions); attBonus -= conditions; @@ -12742,12 +12854,12 @@ var COFantasy = COFantasy || function() { return attBonus; } - //Tous les bonus de DM normalement calculés dans bonusAttaqueD + //Tous les bonus de DM normalement calcul\xE9s dans bonusAttaqueD function bonusDMD(attaquant, target, portee, pageId, evt, explications, options) { let chasseurEmerite = predicateAsBool(attaquant, 'chasseurEmerite') && estAnimal(target); if (chasseurEmerite) { - let explChasseurEmerite = "hasseur émérite => +2 aux DM"; + let explChasseurEmerite = "hasseur \xE9m\xE9rite => +2 aux DM"; if (options.displayName) { explChasseurEmerite = nomPerso(attaquant) + ' est un c' + explChasseurEmerite; } else { @@ -12766,7 +12878,7 @@ var COFantasy = COFantasy || function() { }); }); if (ennemiJure) { - let explEnnemiJure = "Attaque sur ennemi juré => + 1d6 aux DM"; + let explEnnemiJure = "Attaque sur ennemi jur\xE9 => + 1d6 aux DM"; if (options.aoe) explEnnemiJure += " contre " + nomPerso(target); explications.push(explEnnemiJure); target.ennemiJure = true; @@ -12792,7 +12904,7 @@ var COFantasy = COFantasy || function() { let attrFeinte = tokenAttribute(target, 'feinte_' + nomPerso(attaquant)); if (attrFeinte.length > 0 && attrFeinte[0].get('current')) { let niveauTouche = attrFeinte[0].get('max'); - if (niveauTouche > 0) { //La feinte avait touché cette cible + if (niveauTouche > 0) { //La feinte avait touch\xE9 cette cible let msgFeinte = "Feinte => "; let faireMouche = predicateAsInt(attaquant, 'faireMouche', 0); if (faireMouche > 0) { @@ -12817,7 +12929,7 @@ var COFantasy = COFantasy || function() { let cibleAgrippee = persoOfIdName(a.get('current'), pageId); if (cibleAgrippee && cibleAgrippee.id == target.id && !attributeAsBool(cibleAgrippee, 'agrippeParUnDemon')) { - explications.push("Cible agrippée => +1d6 DM"); + explications.push("Cible agripp\xE9e => +1d6 DM"); target.estAgrippee = true; } }); @@ -12840,15 +12952,15 @@ var COFantasy = COFantasy || function() { } } if (predicateAsBool(attaquant, 'liberateurDeDorn') && estGeant(target)) { - explications.push("Libérateur de Dorn => +2d6 DM"); + explications.push("Lib\xE9rateur de Dorn => +2d6 DM"); target.cibleLiberateurDeDorn = true; } if (predicateAsBool(attaquant, 'liberateurDeKerserac') && (estGeant(target) || estInsecte(target) || estElfeNoir(target))) { - explications.push("Libérateur de Kerserac => +1d6 DM"); + explications.push("Lib\xE9rateur de Kerserac => +1d6 DM"); target.cibleLiberateurDeKerserac = true; } if (predicateAsBool(attaquant, 'liberateurDAnathazerin') && (estInsecte(target) || estElfeNoir(target))) { - explications.push("Libérateur d'Anathazerïn => +2d6 DM"); + explications.push("Lib\xE9rateur d'Anathazer\xEFn => +2d6 DM"); target.cibleLiberateurDAnathazerin = true; } let attrMeneurCible = tokenAttribute(target, 'meneurDHommesCible'); @@ -12858,7 +12970,7 @@ var COFantasy = COFantasy || function() { if (meneurDHommes && alliesParPerso[meneurDHommes.charId] && alliesParPerso[meneurDHommes.charId].has(attaquant.charId)) { target.cibleMeneurDHommes = true; - explications.push(nomPerso(meneurDHommes) + " a désigné " + nomPerso(target) + + explications.push(nomPerso(meneurDHommes) + " a d\xE9sign\xE9 " + nomPerso(target) + " comme la cible des attaques du groupe : +1d6 DM"); } } @@ -12874,22 +12986,22 @@ var COFantasy = COFantasy || function() { return; } - //Bonus d'attaque qui dépendent de la cible + //Bonus d'attaque qui d\xE9pendent de la cible function bonusAttaqueD(attaquant, target, portee, pageId, evt, explications, options) { let attBonus = 0; if (target.bonusAttaque) attBonus += target.bonusAttaque; if (getState(attaquant, 'aveugle')) { if (options.distance) { if (options.tirAveugle) { - explications.push("Attaquant aveuglé, mais il sait tirer à l'aveugle"); + explications.push("Attaquant aveugl\xE9, mais il sait tirer \xE0 l'aveugle"); } else { attBonus -= 10; - explications.push("Attaquant aveuglé => -10 en Attaque à distance"); + explications.push("Attaquant aveugl\xE9 => -10 en Attaque \xE0 distance"); } } else { if (!predicateAsBool(attaquant, 'radarMental') || estNonVivant(target)) { attBonus -= 5; - explications.push("Attaquant aveuglé => -5 en Attaque"); + explications.push("Attaquant aveugl\xE9 => -5 en Attaque"); } } } else if (attributeAsBool(attaquant, 'aveugleManoeuvre')) { @@ -12897,24 +13009,24 @@ var COFantasy = COFantasy || function() { attBonus -= 5; options.aveugleManoeuvre = true; if (options.pasDeDmg) - explications.push("Attaquant aveuglé => -5 en Attaque"); + explications.push("Attaquant aveugl\xE9 => -5 en Attaque"); else - explications.push("Attaquant aveuglé => -5 en Attaque et aux DM"); + explications.push("Attaquant aveugl\xE9 => -5 en Attaque et aux DM"); } } else if (getState(attaquant, 'invisible') && !attributeAsBool(target, 'detectionDeLInvisible')) { attBonus += 5; explications.push("Attaque venant d'un personnage invisible => +5 en Attaque"); } else if (options.distance && getState(attaquant, 'penombre')) { if (options.tirAveugle) { - explications.push("Attaquant dans la pénombre, mais il sait tirer à l'aveugle"); + explications.push("Attaquant dans la p\xE9nombre, mais il sait tirer \xE0 l'aveugle"); } else { attBonus -= 5; - explications.push("Attaquant dans la pénombre => -5 en Attaque à distance"); + explications.push("Attaquant dans la p\xE9nombre => -5 en Attaque \xE0 distance"); } } if (options.mainsDEnergie) { - if (options.aoe) error("Mains d'énergie n'est pas compatible avec les AOE", options.aoe); - // On vérifie si la cible porte une armure + if (options.aoe) error("Mains d'\xE9nergie n'est pas compatible avec les AOE", options.aoe); + // On v\xE9rifie si la cible porte une armure let targetArmorDef = 0; if (persoEstPNJ(target)) { if (ficheAttributeAsBool(target, 'defarmureon', false)) targetArmorDef = 5; @@ -12923,11 +13035,11 @@ var COFantasy = COFantasy || function() { } if (isNaN(targetArmorDef) || targetArmorDef === 0) { attBonus += 2; - explications.push("Mains d'énergie => +2 en Attaque (cible sans armure)"); + explications.push("Mains d'\xE9nergie => +2 en Attaque (cible sans armure)"); } else { let bonusMain = Math.min(5, 2 + targetArmorDef); attBonus += bonusMain; - explications.push("Mains d'énergie => +" + bonusMain + " en Attaque"); + explications.push("Mains d'\xE9nergie => +" + bonusMain + " en Attaque"); } } if (options.aoe === undefined && options.auto === undefined && portee > 0) { @@ -12939,7 +13051,7 @@ var COFantasy = COFantasy || function() { predicateAsBool(attaquant, 'chasseurEmerite') && estAnimal(target); if (chasseurEmerite) { attBonus += 2; - let explChasseurEmerite = "hasseur émérite => +2 en Attaque"; + let explChasseurEmerite = "hasseur \xE9m\xE9rite => +2 en Attaque"; if (options.displayName) { explChasseurEmerite = nomPerso(attaquant) + ' est un c' + explChasseurEmerite; } else { @@ -12961,7 +13073,7 @@ var COFantasy = COFantasy || function() { if (ennemiJure) { let ejSag = modCarac(attaquant, 'sagesse'); attBonus += ejSag; - let explEnnemiJure = "Attaque sur ennemi juré => +" + ejSag + " en attaque"; + let explEnnemiJure = "Attaque sur ennemi jur\xE9 => +" + ejSag + " en attaque"; if (!options.pasDeDmg) explEnnemiJure += " et +1d6 aux DM"; if (options.aoe) explEnnemiJure += " contre " + nomPerso(target); explications.push(explEnnemiJure); @@ -12996,9 +13108,9 @@ var COFantasy = COFantasy || function() { if (options.tueurDeGeants && estGeant(target)) { attBonus += 2; if (options.pasDeDmg) - explications.push("Tueur de géant => +2 en Attaque"); + explications.push("Tueur de g\xE9ant => +2 en Attaque"); else - explications.push("Tueur de géant => +2 att. et 2d6 DM"); + explications.push("Tueur de g\xE9ant => +2 att. et 2d6 DM"); target.tueurDeGeants = true; } if (options.tueurDe) { @@ -13022,7 +13134,7 @@ var COFantasy = COFantasy || function() { attBonus += bonusFeinte; let msgFeinte = "Feinte => +" + bonusFeinte + " en attaque"; let niveauTouche = attrFeinte[0].get('max'); - if (niveauTouche > 0) { //La feinte avait touché cette cible + if (niveauTouche > 0) { //La feinte avait touch\xE9 cette cible let faireMouche = predicateAsInt(attaquant, 'faireMouche', 0); if (faireMouche > 0) { if (options.contact && !options.pasDeDmg) { @@ -13038,7 +13150,6 @@ var COFantasy = COFantasy || function() { if (options.attaqueFlamboyanteBonus) msgFeinte += "+" + options.attaqueFlamboyanteBonus; msgFeinte += " DM"; - } } } @@ -13052,7 +13163,7 @@ var COFantasy = COFantasy || function() { }); if (expose) { attBonus += 10; - explications.push("L'adversaire est exposé : +10"); + explications.push("L'adversaire est expos\xE9 : +10"); } } if (options.contact) { @@ -13061,7 +13172,7 @@ var COFantasy = COFantasy || function() { ficheAttributeAsInt(attaquant, 'force', 10) <= ficheAttributeAsInt(target, 'force', 10) && parseInt(attaquant.token.get("bar1_max")) <= parseInt(target.token.get("bar1_max"))) { attBonus -= 2; - explications.push("Effrayé => -2 en Attaque"); + explications.push("Effray\xE9 => -2 en Attaque"); } } let attrAgrippe = tokenAttribute(attaquant, 'agrippe'); @@ -13071,9 +13182,9 @@ var COFantasy = COFantasy || function() { !attributeAsBool(cibleAgrippee, 'agrippeParUnDemon')) { attBonus += 5; if (options.pasDeDmg) - explications.push("Cible agrippée => +5 em Attaque"); + explications.push("Cible agripp\xE9e => +5 em Attaque"); else - explications.push("Cible agrippée => +5 att. et 1d6 DM"); + explications.push("Cible agripp\xE9e => +5 att. et 1d6 DM"); target.estAgrippee = true; } }); @@ -13090,7 +13201,7 @@ var COFantasy = COFantasy || function() { _pageid: pageId, layer: 'objects' }); - //On compte les tokens au contact de l'attaquant et du défenseur et alliés de l'attaquant + //On compte les tokens au contact de l'attaquant et du d\xE9fenseur et alli\xE9s de l'attaquant let allies = alliesParPerso[attaquant.charId]; if (allies) { let alliesAuContact = 0; @@ -13112,7 +13223,7 @@ var COFantasy = COFantasy || function() { } } } - if (options.attaqueEnMeute) { + if (options.attaqueEnMeute || alliesDAttaqueEnMeute.has(attaquant.charId)) { let attaqueParMeute = tokenAttribute(target, 'attaqueParMeute'); if (attaqueParMeute.length > 0) { attaqueParMeute = attaqueParMeute[0]; @@ -13126,7 +13237,7 @@ var COFantasy = COFantasy || function() { } autreAttaquant = true; }); - if (autreAttaquant) { + if (autreAttaquant && options.attaqueEnMeute) { attBonus += options.attaqueEnMeute; explications.push("Attaque en meute => +" + options.attaqueEnMeute + " pour toucher"); } @@ -13148,7 +13259,7 @@ var COFantasy = COFantasy || function() { if (tm) { if (estDemon(attaquant)) { if (eclaireParFioleDeLumiere(attaquant, tm)) { - explications.push("Aveuglé par la fiole de lumière => -2 en Attaque"); + explications.push("Aveugl\xE9 par la fiole de lumi\xE8re => -2 en Attaque"); attBonus -= 2; } } else if (!eclaireParFioleDeLumiere(target, tm)) { @@ -13173,34 +13284,34 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(attaquant, 'liberateurDeDorn') && estGeant(target)) { attBonus += 2; if (options.pasDeDmg) { - explications.push("Libérateur de Dorn => +2 en attaque"); + explications.push("Lib\xE9rateur de Dorn => +2 en attaque"); } else { - explications.push("Libérateur de Dorn => +2 en attaque et +2d6 DM"); + explications.push("Lib\xE9rateur de Dorn => +2 en attaque et +2d6 DM"); target.cibleLiberateurDeDorn = true; } } if (predicateAsBool(attaquant, 'liberateurDeKerserac') && (estGeant(target) || estInsecte(target) || estElfeNoir(target))) { attBonus += 2; if (options.pasDeDmg) { - explications.push("Libérateur de Kerserac => +2 en attaque"); + explications.push("Lib\xE9rateur de Kerserac => +2 en attaque"); } else { - explications.push("Libérateur de Kerserac => +2 en attaque et +1d6 DM"); + explications.push("Lib\xE9rateur de Kerserac => +2 en attaque et +1d6 DM"); target.cibleLiberateurDeKerserac = true; } } if (predicateAsBool(attaquant, 'liberateurDAnathazerin') && (estInsecte(target) || estElfeNoir(target))) { attBonus += 2; if (options.pasDeDmg) { - explications.push("Libérateur d'Anathazerïn => +2 en attaque"); + explications.push("Lib\xE9rateur d'Anathazer\xEFn => +2 en attaque"); } else { - explications.push("Libérateur d'Anathazerïn => +2 en attaque et +2d6 DM"); + explications.push("Lib\xE9rateur d'Anathazer\xEFn => +2 en attaque et +2d6 DM"); target.cibleLiberateurDAnathazerin = true; } } if (predicateAsBool(attaquant, 'tenacite')) { let bonus = attributeAsInt(target, 'attributDeCombat_tenaciteDe' + nomPerso(attaquant), 0); if (bonus > 0) { - explications.push("Ténacité => +" + bonus + " en attaque"); + explications.push("T\xE9nacit\xE9 => +" + bonus + " en attaque"); attBonus += bonus; } } @@ -13212,7 +13323,7 @@ var COFantasy = COFantasy || function() { alliesParPerso[meneurDHommes.charId].has(attaquant.charId)) { attBonus += 2; if (!options.pasDeDmg) target.cibleMeneurDHommes = true; - explications.push(nomPerso(meneurDHommes) + " a désigné " + nomPerso(target) + + explications.push(nomPerso(meneurDHommes) + " a d\xE9sign\xE9 " + nomPerso(target) + " comme la cible des attaques du groupe : +2 attaque, +1d6 DM"); } } @@ -13278,14 +13389,14 @@ var COFantasy = COFantasy || function() { if (res.length === 0) { let ace = tokenAttribute(perso, classeEffet); if (ace.length > 0) { - error(nomPerso(perso) + " a une classe d'effets " + classeEffet + " mais pas d'effet associé", ace); + error(nomPerso(perso) + " a une classe d'effets " + classeEffet + " mais pas d'effet associ\xE9", ace); ace[0].remove(); } } return res; } - //Si le dépassement de limite est possible, renvoie un nouveau depMana, sinon renvoie false + //Si le d\xE9passement de limite est possible, renvoie un nouveau depMana, sinon renvoie false function depasseLimite(perso, nomAttr, msgImpossible, msg, evt, options) { if (options.depasseLimite) { options.mana = options.mana || 0; @@ -13302,8 +13413,84 @@ var COFantasy = COFantasy || function() { return false; } - //Retourne true si il existe une limite qui empêche de lancer le sort - //N'ajoute pas l'événement à l'historique + //Retourne false si il existe la limitePar+type qui emp\xEAche de faire l'action + // type peut \xEAtre Jour, Combat ou Tour + // si c'est ok, renvoie depMana, \xE9ventuellement mis \xE0 jour + function testLimitePar(perso, type, options, depMana, defRessource, msg, evt, explications) { + let nom = 'limitePar' + type; + let opt = options[nom]; + if (opt) { + let msgType = ''; + let temps = ''; + switch (type) { + case 'Jour': + msgType = "journali\xE8re"; + temps = "aujourd'hui"; + break; + case 'Combat': + if (!stateCOF.combat) { + sendPerso(perso, "ne peut pas faire cette action en dehors des combats", options.secret); + return false; + } + msgType = "par combat"; + temps = "pour ce combat"; + break; + case 'Tour': + if (!stateCOF.combat) { + sendPerso(perso, "ne peut pas faire cette action en dehors des combats", options.secret); + return false; + } + msgType = "par tour"; + temps = "durant ce tour"; + break; + } + if (!perso) { + error("Impossible de savoir \xE0 qui appliquer la limite " + msgType, options); + return false; + } + let ressource = nom + '_'; + if (opt.ressource) + ressource += opt.ressource; + else + ressource += defRessource; + let limite = 0; + if (opt.val) limite = opt.val; + else if (opt.predicat) + limite = predicateAsInt(perso, opt.predicat, 0, 1); + else { + error("Limite " + msgType + " mal form\xE9e", opt); + return false; + } + let utilisations = attributeAsInt(perso, ressource, limite); + if (utilisations === 0) { + depMana = depasseLimite(perso, ressource, "ne peut plus faire cette action " + temps, msg, evt, options); + if (depMana) utilisations = 1; + else return false; + } + setTokenAttr(perso, ressource, utilisations - 1, evt); + if (opt.ressource) { + let msgLimite = nomPerso(perso) + " "; + if (utilisations < 2) msgLimite += "ne pourra plus utiliser "; + else { + msgLimite += "pourra encore utiliser "; + if (utilisations == 2) msgLimite += "une fois "; + else msgLimite += (utilisations - 1) + " fois "; + } + msgLimite += opt.ressource + " " + temps; + if (explications) { + stateCOF.afterDisplay = stateCOF.afterDisplay || []; + stateCOF.afterDisplay.push({ + msg: msgLimite, + destinataire: perso + }); + } else sendPerso(perso, msgLimite, true); + } + } + return depMana; + } + + //Retourne true si il existe une limite qui emp\xEAche de lancer le sort + //N'ajoute pas l'\xE9v\xE9nement \xE0 l'historique //explications est optionnel function limiteRessources(personnage, options, defResource, msg, evt, explications) { let depMana = { @@ -13327,8 +13514,8 @@ var COFantasy = COFantasy || function() { } if (m > 0) { if (reglesOptionelles.mana.val.mana_totale.val) options.mana += m; - //Le plus cohérent avec la mana totale consiste à diviser ce malus par 3, - //arrondi au supérieur + //Le plus coh\xE9rent avec la mana totale consiste \xE0 diviser ce malus par 3, + //arrondi au sup\xE9rieur else options.mana += Math.ceil(m / 3); } } @@ -13337,127 +13524,17 @@ var COFantasy = COFantasy || function() { depMana = depenseManaPossible(personnage, options.mana, msg); if (!depMana) return true; } else { - error("Impossible de savoir qui doit dépenser de la mana", options); - return true; - } - } - let ressource = ''; - if (defResource !== undefined) ressource = defResource; - let utilisations; - if (options.limiteParJour) { - if (!personnage) { - error("Impossible de savoir à qui appliquer la limite journalière", options); - return true; - } - if (options.limiteParJourRessource) - ressource = "limiteParJour_" + options.limiteParJourRessource; - else - ressource = "limiteParJour_" + defResource; - utilisations = - attributeAsInt(personnage, ressource, options.limiteParJour); - if (utilisations === 0) { - depMana = depasseLimite(personnage, ressource, "ne peut plus faire cette action aujourd'hui", msg, evt, options); - if (depMana) utilisations = 1; - else return true; - } - setTokenAttr(personnage, ressource, utilisations - 1, evt); - if (options.limiteParJourRessource) { - let msgJour = nomPerso(personnage) + " "; - if (utilisations < 2) msgJour += "ne pourra plus utiliser "; - else { - msgJour += "pourra encore utiliser "; - if (utilisations == 2) msgJour += "une fois "; - else msgJour += (utilisations - 1) + " fois "; - } - msgJour += options.limiteParJourRessource + " aujourd'hui."; - if (explications) { - stateCOF.afterDisplay = stateCOF.afterDisplay || []; - stateCOF.afterDisplay.push({ - msg: msgJour, - destinataire: personnage - }); - } else sendPerso(personnage, msgJour, true); - } - } - if (options.limiteParCombat) { - if (personnage) { - if (!stateCOF.combat) { - sendPerso(personnage, "ne peut pas faire cette action en dehors des combats", options.secret); - return true; - } - if (options.limiteParCombatRessource) - ressource = "limiteParCombat_" + options.limiteParCombatRessource; - else - ressource = "limiteParCombat_" + defResource; - utilisations = - attributeAsInt(personnage, ressource, options.limiteParCombat); - if (utilisations === 0) { - let msgToSend = "ne peut plus faire cette action pour ce combat"; - sendPerso(personnage, msgToSend, options.secret); - return true; - } - setTokenAttr(personnage, ressource, utilisations - 1, evt); - if (options.limiteParCombatRessource) { - let msgCombat = nomPerso(personnage) + " "; - if (utilisations < 2) msgCombat += "ne pourra plus utiliser "; - else { - msgCombat += "pourra encore utiliser "; - if (utilisations == 2) msgCombat += "une fois "; - else msgCombat += (utilisations - 1) + " fois "; - } - msgCombat += options.limiteParCombatRessource + " durant ce combat."; - if (explications) { - stateCOF.afterDisplay = stateCOF.afterDisplay || []; - stateCOF.afterDisplay.push({ - msg: msgCombat, - destinataire: personnage - }); - } else sendPerso(personnage, msgCombat, true); - } - } else { - error("Impossible de savoir à qui appliquer la limite par combat", options); - return true; - } - } - if (options.limiteParTour) { - if (personnage) { - if (!stateCOF.combat) { - sendPerso(personnage, "ne peut pas faire cette action en dehors des combats", options.secret); - return true; - } - if (options.limiteParTourRessource) - ressource = "limiteParTour_" + options.limiteParTourRessource; - else - ressource = "limiteParTour_" + defResource; - utilisations = attributeAsInt(personnage, ressource, options.limiteParTour); - if (utilisations === 0) { - let msgToSend = "ne peut plus faire cette action pour ce tour"; - sendPerso(personnage, msgToSend, options.secret); - return true; - } - setTokenAttr(personnage, ressource, utilisations - 1, evt); - if (options.limiteParTourRessource) { - let msgCombat = nomPerso(personnage) + " "; - if (utilisations < 2) msgCombat += "ne pourra plus utiliser "; - else { - msgCombat += "pourra encore utiliser "; - if (utilisations == 2) msgCombat += "une fois "; - else msgCombat += (utilisations - 1) + " fois "; - } - msgCombat += options.limiteParTourRessource + " durant ce tour."; - if (explications) { - stateCOF.afterDisplay = stateCOF.afterDisplay || []; - stateCOF.afterDisplay.push({ - msg: msgCombat, - destinataire: personnage - }); - } else sendPerso(personnage, msgCombat, options.secret); - } - } else { - error("Impossible de savoir à qui appliquer la limite par tour", options); + error("Impossible de savoir qui doit d\xE9penser de la mana", options); return true; } } + depMana = testLimitePar(personnage, 'Jour', options, depMana, defResource, msg, evt, explications); + if (!depMana) return true; + depMana = testLimitePar(personnage, 'Combat', options, depMana, defResource, msg, evt, explications); + if (!depMana) return true; + if (!depMana) return true; + depMana = testLimitePar(personnage, 'Tour', options, depMana, defResource, msg, evt, explications); + if (!depMana) return true; if (options.tempsRecharge) { if (personnage) { if (attributeAsBool(personnage, options.tempsRecharge.effet)) { @@ -13468,7 +13545,7 @@ var COFantasy = COFantasy || function() { setAttrDuree(personnage, options.tempsRecharge.effet, options.tempsRecharge.duree, evt); } } else { - error("Impossible de savoir à qui s'applique le temps de recharge", options); + error("Impossible de savoir \xE0 qui s'applique le temps de recharge", options); return true; } } @@ -13482,7 +13559,7 @@ var COFantasy = COFantasy || function() { } setTokenAttr(personnage, 'dose_' + options.dose, doses - 1, evt); } else { - error("Impossible de savoir qui doit dépenser la dose", options); + error("Impossible de savoir qui doit d\xE9penser la dose", options); return true; } } @@ -13496,7 +13573,7 @@ var COFantasy = COFantasy || function() { } setTokenAttr(personnage, nomAttr, currentAttr + 1, evt); } else { - error("Impossible de savoir à qui appliquer la limitation", options); + error("Impossible de savoir \xE0 qui appliquer la limitation", options); return true; } } @@ -13526,11 +13603,11 @@ var COFantasy = COFantasy || function() { if (personnage) { let test = testLimiteUtilisationsCapa(personnage, pred, 'tour', "ne peut plus utiliser " + pred + " ce tour", - "Action impossible, pas de prédicat " + pred); + "Action impossible, pas de pr\xE9dicat " + pred); if (test === undefined) return true; utiliseCapacite(personnage, test, evt); } else { - error("Impossible de savoir à qui appliquer la limitation du prédicat " + pred, options); + error("Impossible de savoir \xE0 qui appliquer la limitation du pr\xE9dicat " + pred, options); return true; } } @@ -13540,8 +13617,8 @@ var COFantasy = COFantasy || function() { //asynchrone //callback(resultat, crit, roll1, roll2): - // resultat peut être 0, 1 ou 2 : 0 = match null, 1 le perso 1 gagne, 2 le perso 2 gagne. - // crit peut être 1 si un des deux perso a fait une réussite critique et pas l'autre, -1 si un des personnage a fait un échec critique et pas l'autre, et 0 sinon + // resultat peut \xEAtre 0, 1 ou 2 : 0 = match null, 1 le perso 1 gagne, 2 le perso 2 gagne. + // crit peut \xEAtre 1 si un des deux perso a fait une r\xE9ussite critique et pas l'autre, -1 si un des personnage a fait un \xE9chec critique et pas l'autre, et 0 sinon function testOppose(rollId, perso1, carac1, options1, perso2, carac2, options2, explications, evt, callback) { if (carac2 === undefined) carac2 = carac1; let nom1 = nomPerso(perso1); @@ -13581,9 +13658,9 @@ var COFantasy = COFantasy || function() { let texte1 = "Jet " + deCarac(carac1) + " de " + nom1 + " : " + rt1.texte; if (reussite == 2) { if ((carac1 == 'FOR' || carac1 == 'DEX' || carac1 == 'CON') && - attributeAsBool(perso1, 'runeForgesort_énergie') && - attributeAsInt(perso1, 'limiteParCombat_runeForgesort_énergie', 1) > 0) { - texte1 += "
" + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + rollId + "_roll1", "Rune d'énergie"); + attributeAsBool(perso1, 'runeForgesort_\xE9nergie') && + attributeAsInt(perso1, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0) { + texte1 += "
" + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + rollId + "_roll1", "Rune d'\xE9nergie"); } if (!rt1.echecCritique && !rt2.critique) { let pcPerso1 = pointsDeChance(perso1); @@ -13613,9 +13690,9 @@ var COFantasy = COFantasy || function() { let texte2 = "Jet " + deCarac(carac2) + " de " + nom2 + " : " + rt2.texte; if (reussite == 1) { if ((carac2 == 'FOR' || carac2 == 'DEX' || carac2 == 'CON') && - attributeAsBool(perso2, 'runeForgesort_énergie') && - attributeAsInt(perso2, 'limiteParCombat_runeForgesort_énergie', 1) > 0) { - texte2 += "
" + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + rollId + "_roll2", "Rune d'énergie"); + attributeAsBool(perso2, 'runeForgesort_\xE9nergie') && + attributeAsInt(perso2, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0) { + texte2 += "
" + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + rollId + "_roll2", "Rune d'\xE9nergie"); } if (!rt2.echecCritique && !rt1.critique) { let pcPerso2 = pointsDeChance(perso2); @@ -13643,16 +13720,15 @@ var COFantasy = COFantasy || function() { explications.push(m); }); callback(reussite, crit, rt1.roll, rt2.roll); - }); //Fin du jet du deuxième perso + }); //Fin du jet du deuxi\xE8me perso }); //Fin du jet du premier perso } function bonusPlusViteQueSonOmbre(perso, arme) { let p = predicateAsBool(perso, 'plusViteQueSonOmbre'); if (!p) return 0; - // L'arme doit être chargée - if (arme.charge && attributeAsInt(perso, 'charge_' + arme.label, 0) === 0) - return 0; + // L'arme doit \xEAtre charg\xE9e + if (armeDechargee(perso, arme)) return 0; if (p === true) { if (arme.poudre) return 10; return 0; @@ -13669,7 +13745,7 @@ var COFantasy = COFantasy || function() { return 0; } - // prend en compte l'unité de mesure utilisée sur la page + // prend en compte l'unit\xE9 de mesure utilis\xE9e sur la page function ajouteUneLumiere(perso, nomLumiere, radius, dimRadius, evt) { radius = scaleDistance(perso, radius); if (dimRadius !== '') dimRadius = scaleDistance(perso, dimRadius); @@ -13680,7 +13756,7 @@ var COFantasy = COFantasy || function() { let brightLight = radius; if (udl) { if (isNaN(brightLight) || brightLight < 0) { - error("Lumière avec un rayon négatif", radius); + error("Lumi\xE8re avec un rayon n\xE9gatif", radius); return; } } @@ -13688,7 +13764,7 @@ var COFantasy = COFantasy || function() { if (ct.get('bar1_link') === '') attrName += "_" + ct.get('name'); if (ct.get('bar1_max')) { let lumiereSurPerso; - //Cas particulier où le personnage est un vrai personnage qui ne fait pas de lumière + //Cas particulier o\xF9 le personnage est un vrai personnage qui ne fait pas de lumi\xE8re if (!udl && !ct.get('light_radius')) { lumiereSurPerso = true; setToken(ct, 'light_radius', radius, evt); @@ -13733,7 +13809,7 @@ var COFantasy = COFantasy || function() { name: nomLumiere, }); if (tokLumiere === undefined) { - error("Problème lors de la création du token de lumière", perso); + error("Probl\xE8me lors de la cr\xE9ation du token de lumi\xE8re", perso); return; } evt.tokens = [tokLumiere]; @@ -13755,7 +13831,7 @@ var COFantasy = COFantasy || function() { setToken(tokLumiere, 'light_dimradius', dimRadius, evt); setToken(tokLumiere, 'light_otherplayers', true, evt); } - if (ct.get('bar1_max')) { //Lumière liée à un token + if (ct.get('bar1_max')) { //Lumi\xE8re li\xE9e \xE0 un token let attr = createObj('attribute', { characterid: perso.charId, name: attrName, @@ -13765,14 +13841,14 @@ var COFantasy = COFantasy || function() { evt.attributes = [{ attribute: attr, }]; - } else { //cible temporaire, à effacer + } else { //cible temporaire, \xE0 effacer ct.remove(); } } - //renvoie le nom de l'arme si l'arme est déjà tenue en main + //renvoie le nom de l'arme si l'arme est d\xE9j\xE0 tenue en main // options.seulementDroite permet de ne rengainer que l'arme droite - // options.deuxMains permet de prendre une arme à 2 mains + // options.deuxMains permet de prendre une arme \xE0 2 mains function degainerArme(perso, labelArme, evt, options) { let pageId = perso.pageId; if (pageId === undefined) { @@ -13790,11 +13866,11 @@ var COFantasy = COFantasy || function() { nouvelleArme = getWeaponStats(perso, labelArme); if (nouvelleArme && nouvelleArme.armeGauche) options.gauche = true; let nouvelleArmeGauche; - let labelArmeGauche; //définie seulement si on dégaine l'arme gauche - // et toujours différent de labelArme + let labelArmeGauche; //d\xE9finie seulement si on d\xE9gaine l'arme gauche + // et toujours diff\xE9rent de labelArme if (options.armeGaucheLabel) { if (options.armeGaucheLabel == labelArme) { - sendPerso("ne peut dégainer la même arme dans les deux mains"); + sendPerso("ne peut d\xE9gainer la m\xEAme arme dans les deux mains"); return; } if (options.gauche) { @@ -13804,7 +13880,7 @@ var COFantasy = COFantasy || function() { options.gauche = false; //vrai seulement si on ne sort que l'arme gauche nouvelleArme = getWeaponStats(perso, options.armeGaucheLabel); if (nouvelleArme && nouvelleArme.armeGauche) { - sendPerso("ne peut dégainer 2 armes gauches à la fois"); + sendPerso("ne peut d\xE9gainer 2 armes gauches \xE0 la fois"); return; } } else { @@ -13836,7 +13912,7 @@ var COFantasy = COFantasy || function() { if (labelArmeActuelleGauche == labelArme) rienAFaire = true; else { changementDePrise = true; - message += "prend son arme à deux mains"; + message += "prend son arme \xE0 deux mains"; attrArmeActuelle.set('max', labelArme); } } @@ -13846,24 +13922,24 @@ var COFantasy = COFantasy || function() { if (labelArmeActuelle == labelArme) { if (labelArmeActuelleGauche == labelArme) { changementDePrise = true; - message += "prend son arme à une main"; + message += "prend son arme \xE0 une main"; if (!labelArmeGauche) { attrArmeActuelle.set('max', ''); } } else { - if (labelArmeGauche) //on dégaine 2 armes + if (labelArmeGauche) //on d\xE9gaine 2 armes rienAFaire = labelArmeActuelleGauche == labelArmeGauche; else rienAFaire = true; } } } if (rienAFaire) { - //Pas besoin de dégainer. + //Pas besoin de d\xE9gainer. if (options.weaponStats) return options.weaponStats.name; if (nouvelleArme) return nouvelleArme.name; return; } - //On dégaine une nouvelle arme, il faut rengainer l'ancienne + //On d\xE9gaine une nouvelle arme, il faut rengainer l'ancienne if (labelArmeActuelle) { //dans ce cas, pas options.gauche ancienneArme = getWeaponStats(perso, labelArmeActuelle); if (ancienneArme === undefined) { @@ -13911,8 +13987,8 @@ var COFantasy = COFantasy || function() { } } else attrArmeActuelle = undefined; const estMook = perso.token && perso.token.get('bar1_link') === ''; - //Puis on dégaine - //mais on vérifie que l'arme existe, sinon c'est juste un ordre de rengainer + //Puis on d\xE9gaine + //mais on v\xE9rifie que l'arme existe, sinon c'est juste un ordre de rengainer if (nouvelleArme === undefined) { if (attrArmeActuelle) { if (options.seulementDroite && labelArmeActuelleGauche) { @@ -13931,7 +14007,7 @@ var COFantasy = COFantasy || function() { } if (nouvelleArmeGauche) { if (ficheAttributeAsInt(perso, 'defbouclieron', 0)) { - sendPerso(perso, "enlève son bouclier", options.secret); + sendPerso(perso, "enl\xE8ve son bouclier", options.secret); setFicheAttr(perso, 'defbouclieron', 0, evt, { default: 0 }); @@ -13939,7 +14015,7 @@ var COFantasy = COFantasy || function() { } if (nouvelleArme.deuxMains || options.deuxMains) { if (ficheAttributeAsInt(perso, 'defbouclieron', 0)) { - sendPerso(perso, "enlève son bouclier", options.secret); + sendPerso(perso, "enl\xE8ve son bouclier", options.secret); setFicheAttr(perso, 'defbouclieron', 0, evt, { default: 0 }); @@ -13991,17 +14067,17 @@ var COFantasy = COFantasy || function() { } if (options.messages) { if (changementDePrise) { - if (nouvelleArmeGauche) message += ", et dégaine " + nouvelleArmeGauche.name; + if (nouvelleArmeGauche) message += ", et d\xE9gaine " + nouvelleArmeGauche.name; } else { - message += "dégaine " + nouvelleArme.name; + message += "d\xE9gaine " + nouvelleArme.name; if (nouvelleArmeGauche) message += " et " + nouvelleArmeGauche.name; } options.messages.push(message); } else { if (changementDePrise) { - if (nouvelleArmeGauche) message += ", et dégaine " + nouvelleArmeGauche.name; + if (nouvelleArmeGauche) message += ", et d\xE9gaine " + nouvelleArmeGauche.name; } else { - message = "dégaine " + nouvelleArme.name; + message = "d\xE9gaine " + nouvelleArme.name; if (nouvelleArmeGauche) message += " et " + nouvelleArmeGauche.name; } sendPerso(perso, message, options.secret); @@ -14047,7 +14123,7 @@ var COFantasy = COFantasy || function() { }); return !regenPossible; } - //On enlève les doublons de cibles qui partagent leurs PVs; + //On enl\xE8ve les doublons de cibles qui partagent leurs PVs; function enleveDoublonsPartagePV(cibles) { let ciblesAvecPVsPartages = new Set(); //va aussi peupler le champ name des cibles @@ -14066,9 +14142,9 @@ var COFantasy = COFantasy || function() { ciblesAvecPVsPartages.add(cp); }); } else if (persoEstPNJ(target)) { - //cible la moins prioritaire, on l'enlève si on trouve un autre représentant + //cible la moins prioritaire, on l'enl\xE8ve si on trouve un autre repr\xE9sentant let representantPresent = cibles.find(function(target2, index2) { - if (index2 <= index) return false; //déjà traité + if (index2 <= index) return false; //d\xE9j\xE0 trait\xE9 if (target2.name === undefined) { let target2Char = getObj('character', target2.charId); if (target2Char === undefined) return false; @@ -14083,7 +14159,7 @@ var COFantasy = COFantasy || function() { //N'a pas de familier mais n'est pas un PNJ //On cherche si il existe un autre perso plus prioritaire. let representantFamilier = cibles.find(function(target2, index2) { - if (index2 < index) return false; //déjà traité + if (index2 < index) return false; //d\xE9j\xE0 trait\xE9 if (target2.name === undefined) { let target2Char = getObj('character', target2.charId); if (target2Char === undefined) return false; @@ -14107,6 +14183,58 @@ var COFantasy = COFantasy || function() { return cibles; } + function tokensSurTrajet(token, ptCible, rayonToken, allToks, murs, saut) { + let pt = pointOfToken(token); + if (murs) { + if (obstaclePresent(pt.x, pt.y, ptCible, murs)) return ["mur"]; + } + let dp = distancePoints(pt, ptCible); + let liste_obstacles = []; + allToks.forEach(function(obj) { + if (obj.id == token.id) return; + let objCharId = obj.get('represents'); + let perso = { + token: obj, + charId: objCharId + }; + if (objCharId !== '' && + (getState(perso, 'mort') || + getState(perso, 'assomme') || getState(perso, 'endormi') || + (attributeAsBool(perso, 'intangible') && attributeAsInt(perso, 'intangibleValeur', 1)) || + (attributeAsBool(perso, 'intangibleInvisible') && attributeAsInt(perso, 'intangibleInvisibleValeur', 1)) + ) + ) + return; + //On regarde si le token est une monture de token + let attrMonte = tokenAttribute(perso, 'estMontePar'); + let estMonture = attrMonte.find(function(a) { + let sp = splitIdName(a.get('current')); + if (sp === undefined) return false; + return sp.id == token.id; + }); + if (estMonture) return; + let ptObj = pointOfToken(obj); + let obj_dist = distancePoints(ptCible, ptObj); + if (obj_dist > dp) return; + //Pour le point d'arriv\xE9e, il faut vraiment que ce soit libre + let rayonObjet = tokenSizeAsCircle(obj) / 2; + if (obj_dist < (rayonObjet + rayonToken) * 0.9) { + liste_obstacles.push(obj.get('name')); + return; + } + //On ignore les autres obstacles si on saute + if (saut) return; + obj_dist = distancePixToken(token, obj); + if (obj_dist > dp) return; + let distToTrajectory = distancePixTokenSegment(obj, pt, ptCible); + // On mod\xE9lise le token comme un disque + let rayonObj = tokenSizeAsCircle(obj) / 2; + if (distToTrajectory > rayonObj) return; + liste_obstacles.push(obj.get('name')); + }); + return liste_obstacles; + } + //targetToken est soit un token, soit une structure avec un champs cibles qui contient toutes les cibles function attack(playerName, playerId, attaquant, targetToken, weaponStats, options) { // Attacker and target infos @@ -14122,15 +14250,16 @@ var COFantasy = COFantasy || function() { } attaquant.name = attaquant.name || attacker.get("name"); let pageId = attackingToken.get('pageid'); + options.pageId = pageId; let weaponName = options.nom || weaponStats.name; //Options automatically set by some attributes if (attributeAsBool(attaquant, 'paralysieRoublard')) { if (attributeAsBool(attaquant, 'enrage')) { - sendPerso(attaquant, "est trop enragé pour sentir la douleur"); + sendPerso(attaquant, "est trop enrag\xE9 pour sentir la douleur"); } else if (predicateAsBool(attaquant, 'proprioception')) { - sendPerso(attaquant, "est immunisé à la douleur"); + sendPerso(attaquant, "est immunis\xE9 \xE0 la douleur"); } else { - sendPerso(attaquant, "ne peut pas attaquer car il est paralysé de douleur"); + sendPerso(attaquant, "ne peut pas attaquer car il est paralys\xE9 de douleur"); attackCallback(options); return; } @@ -14177,7 +14306,7 @@ var COFantasy = COFantasy || function() { weaponStats.attDice = options.dm.dice; weaponStats.attDMBonusCommun = options.dm.bonus; } else if (weaponStats.batarde && weaponStats.deuxMains) { - let dm = parseDice(weaponStats.batarde, 'dégâts'); + let dm = parseDice(weaponStats.batarde, 'd\xE9g\xE2ts'); if (dm) { weaponStats.attNbDices = dm.nbDe; weaponStats.attDice = dm.dice; @@ -14224,15 +14353,19 @@ var COFantasy = COFantasy || function() { if (stats2.divers && stats2.divers.includes('d3')) stats2.attDice = 3; options.tirDouble.stats = stats2; } - //Pour les explosions, la portée est 0 mais avec un disque + //Pour les explosions, la port\xE9e est 0 mais avec un disque if (options.explosion) { if (options.aoe === undefined) { options.aoe = { type: 'disque', - rayon: portee + rayon: portee, + centre: { + left: attackingToken.get('left'), + top: attackingToken.get('top') + }, }; } else if (options.aoe.type != 'disque') { - error("Option explosion ignorée, car l'attaque est une aoe qui n'est pas un disque", options); + error("Option explosion ignor\xE9e, car l'attaque est une aoe qui n'est pas un disque", options); } } if (portee > 0) { @@ -14259,9 +14392,9 @@ var COFantasy = COFantasy || function() { } options.contact = true; } - //Ce qui peut empêcher l'attaque quelles que soient les cibles + //Ce qui peut emp\xEAcher l'attaque quelles que soient les cibles if (options.avecd12 && ((estAffaibli(attaquant) && !predicateAsBool(attaquant, 'insensibleAffaibli')) || getState(attaquant, 'immobilise'))) { - sendPerso(attaquant, "ne peut pas utiliser cette capacité quand il est affaibli."); + sendPerso(attaquant, "ne peut pas utiliser cette capacit\xE9 quand il est affaibli."); attackCallback(options); return; } @@ -14276,30 +14409,12 @@ var COFantasy = COFantasy || function() { attackCallback(options); return; } - //Pour l'option grenaille implicite, il faut vérifier que toutes les charge de l'arme sont des charges de grenaille - let chargesArme = []; + //Pour l'option grenaille implicite, il faut v\xE9rifier que toutes les charges de l'arme sont des charges de grenaille let attackLabel = weaponStats.label; - if (attackLabel) { - chargesArme = findObjs({ - _type: 'attribute', - _characterid: attackingCharId, - name: 'charge_' + attackLabel - }); - if (!options.grenaille && chargesArme.length > 0) { - let chargesGrenaille = findObjs({ - _type: 'attribute', - _characterid: attackingCharId, - name: 'chargeGrenaille_' + attackLabel - }); - if (chargesGrenaille.length > 0) { - let chargesTotales = parseInt(chargesArme[0].get('current')); - if (!isNaN(chargesTotales)) { - let grenailles = parseInt(chargesGrenaille[0].get('current')); - if (!isNaN(grenailles) && grenailles >= chargesTotales) - options.grenaille = true; - } - } - } + if (attackLabel && weaponStats.charge && !options.grenaille) { + let currentCharges = attributeAsInt(attaquant, 'charge_' + attackLabel, weaponStats.charge); + if (currentCharges > 0) + options.grenaille = attributeAsInt(attaquant, 'chargeGrenaille_' + attackLabel, 0) >= currentCharges; } if (options.grenaille) { portee = portee / 10; @@ -14344,18 +14459,20 @@ var COFantasy = COFantasy || function() { options.fx = options.fx || effet.id; } if (options.eclairDEnergie && !options.redo) { - //On augmente le nombre de dés de 1 et on utilise l'attaque magique + //On augmente le nombre de d\xE9s de 1 et on utilise l'attaque magique weaponStats.attNbDices++; weaponStats.attSkill = '@{ATKMAG}'; options.contondant = undefined; options.type = 'energie'; options.messages = options.messages || []; - options.messages.push("Éclair d'énergie !"); + options.messages.push("\xC9clair d'\xE9nergie !"); } - //Détermination de la (ou des) cible(s) + //D\xE9termination de la (ou des) cible(s) let nomCiblePrincipale; //Utilise pour le cas mono-cible let cibles = []; - if (options.redo) { //Dans ce cas les cibles sont précisées dans targetToken + let murs; + let page; + if (options.redo) { //Dans ce cas les cibles sont pr\xE9cis\xE9es dans targetToken cibles = targetToken; if (cibles.length === 0) { error("Attaque sans cible", targetToken); @@ -14364,12 +14481,10 @@ var COFantasy = COFantasy || function() { } else if (cibles.length == 1) targetToken = cibles[0].token; nomCiblePrincipale = nomPerso(cibles[0]); } else { - let murs; let pc; - let page; nomCiblePrincipale = targetToken.get('name'); if (options.aoe) { - //cas de la boule de feu qui fait un échec critique : on déplace la cible si elle est artificielle + //cas de la boule de feu qui fait un \xE9chec critique : on d\xE9place la cible si elle est artificielle if (!options.redo && (options.demiAuto || options.toucheDoubleDmg) && (!options.triche || options.triche == 'echecCritique') && targetToken.get('bar1_max') == 0) { // jshint ignore:line @@ -14449,12 +14564,12 @@ var COFantasy = COFantasy || function() { }; } if (targetToken.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir la ligne + //C'est juste un token utilis\xE9 pour d\xE9finir la ligne if (options.fx) { spawnFxBetweenPoints(pta, ptt, options.fx, pageId); } cibles = []; - targetToken.remove(); //On l'enlève, normalement plus besoin + targetToken.remove(); //On l'enl\xE8ve, normalement plus besoin } let allToks = findObjs({ @@ -14471,7 +14586,7 @@ var COFantasy = COFantasy || function() { token: obj, charId: objCharId }; - if (nePeutPlusPrendreDM(cible, options)) return; //pas de dégâts aux morts + if (nePeutPlusPrendreDM(cible, options)) return; //pas de d\xE9g\xE2ts aux morts let distToTrajectory = distancePixTokenSegment(obj, pta, ptt); if (distToTrajectory > (obj.get('width') + obj.get('height')) / 4 + PIX_PER_UNIT / 4) return; @@ -14487,8 +14602,8 @@ var COFantasy = COFantasy || function() { { if (distanceTarget > portee) { sendPlayer(playerName, - "Le centre du disque visé est trop loin pour " + weaponName + - " (distance " + distanceTarget + ", portée " + portee + ")", + "Le centre du disque vis\xE9 est trop loin pour " + weaponName + + " (distance " + distanceTarget + ", port\xE9e " + portee + ")", playerId); attackCallback(options); return; @@ -14516,7 +14631,7 @@ var COFantasy = COFantasy || function() { } let t = attributeAsInt(cadavre, 'a0PVDepuis', 0); if (t < combat.tour - 1) { - sendPlayer(playerName, "La mort de " + nomPerso(cadavre) + " n'est pas assez récente", playerId); + sendPlayer(playerName, "La mort de " + nomPerso(cadavre) + " n'est pas assez r\xE9cente", playerId); attackCallback(options); return; } @@ -14525,18 +14640,22 @@ var COFantasy = COFantasy || function() { options.aoe.souffleDeMort.niveau = ficheAttributeAsInt(cadavre, 'niveau', 0); } - page = page || getObj("page", pageId); + options.aoe.centre = options.aoe.centre || { + left: targetToken.get('left'), + top: targetToken.get('top') + }; + page = page || getObj('page', pageId); murs = getWalls(page, pageId, murs); let allToksDisque = findObjs({ - _type: "graphic", + _type: 'graphic', _pageid: pageId, - _subtype: "token", - layer: "objects" + _subtype: 'token', + layer: 'objects' }); allToksDisque.forEach(function(obj) { if ((options.explosion || portee === 0) && - obj.id == tokenOrigine.id) return; //on ne se cible pas si le centre de l'aoe est soi-même + obj.id == tokenOrigine.id) return; //on ne se cible pas si le centre de l'aoe est soi-m\xEAme if (obj.get('bar1_max') == 0) return; // jshint ignore:line let objCharId = obj.get('represents'); if (objCharId === '') return; @@ -14544,7 +14663,7 @@ var COFantasy = COFantasy || function() { token: obj, charId: objCharId }; - if (nePeutPlusPrendreDM(cible, options)) return; //pas de dégâts aux morts + if (nePeutPlusPrendreDM(cible, options)) return; //pas de d\xE9g\xE2ts aux morts let distanceCentre = distanceCombat(targetToken, obj, pageId, { strict1: true @@ -14565,10 +14684,10 @@ var COFantasy = COFantasy || function() { cibles.push(cible); }); if (targetToken.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir le disque - targetToken.remove(); //On l'enlève, normalement plus besoin + //C'est juste un token utilis\xE9 pour d\xE9finir le disque + targetToken.remove(); //On l'enl\xE8ve, normalement plus besoin } - // La nouvelle portée (pour ne rien éliminer à l'étape suivante + // La nouvelle port\xE9e (pour ne rien \xE9liminer \xE0 l'\xE9tape suivante portee += options.aoe.rayon; break; } @@ -14579,12 +14698,12 @@ var COFantasy = COFantasy || function() { } let vecCentre = vecteurUnitaire(pta, ptt); let cosAngle = Math.cos(options.aoe.angle * Math.PI / 360.0); - //Pour éviter des artfacts d'arrondi: + //Pour \xE9viter des artfacts d'arrondi: cosAngle = (Math.floor(cosAngle * 1000000)) / 1000000; if (targetToken.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir le cone + //C'est juste un token utilis\xE9 pour d\xE9finir le cone cibles = []; - targetToken.remove(); //On l'enlève, normalement plus besoin + targetToken.remove(); //On l'enl\xE8ve, normalement plus besoin } page = page || getObj("page", pageId); murs = getWalls(page, pageId, murs); @@ -14603,12 +14722,12 @@ var COFantasy = COFantasy || function() { token: obj, charId: objCharId }; - if (nePeutPlusPrendreDM(cible, options)) return; //pas de dégâts aux morts + if (nePeutPlusPrendreDM(cible, options)) return; //pas de d\xE9g\xE2ts aux morts let pt = pointOfToken(obj); let vecObj = vecteurUnitaire(pta, pt); if (vecCentre.x * vecObj.x + vecCentre.y * vecObj.y < cosAngle) return; - // La distance sera comparée à la portée plus loin + // La distance sera compar\xE9e \xE0 la port\xE9e plus loin let objChar = getObj('character', objCharId); if (objChar === undefined) return; if (murs) { @@ -14626,16 +14745,16 @@ var COFantasy = COFantasy || function() { return; } } else { - if (tokenOrigine.id == targetToken.id && !options.echecTotal) { //même token pour attaquant et cible + if (tokenOrigine.id == targetToken.id && !options.echecTotal) { //m\xEAme token pour attaquant et cible sendPerso(attaquant, "s'attaque " + onGenre(attaquant, "lui", "elle") + - "-même ? Probablement une erreur à la sélection de la cible. On annule"); + "-m\xEAme ? Probablement une erreur \xE0 la s\xE9lection de la cible. On annule"); attackCallback(options); return; } let targetCharId = targetToken.get("represents"); if (targetCharId === "") { - error("Le token ciblé (" + nomCiblePrincipale + ") doit représenter un personnage ", targetToken); + error("Le token cibl\xE9 (" + nomCiblePrincipale + ") doit repr\xE9senter un personnage ", targetToken); attackCallback(options); return; } @@ -14661,7 +14780,7 @@ var COFantasy = COFantasy || function() { }); } } - //Les conditions qui peuvent empêcher l'attaque + //Les conditions qui peuvent emp\xEAcher l'attaque if (options.conditionAttaquant !== undefined) { if (!testCondition(options.conditionAttaquant, attaquant, cibles)) { sendPerso(attaquant, "ne peut pas utiliser " + weaponName); @@ -14669,7 +14788,7 @@ var COFantasy = COFantasy || function() { return; } } - //dernieresCiblesAttaquees contient en current les cibles attaquées, et en max les cibles sur lesquelles on a fait des ripostes + //dernieresCiblesAttaquees contient en current les cibles attaqu\xE9es, et en max les cibles sur lesquelles on a fait des ripostes let attrCiblesAttaquees = tokenAttribute(attaquant, 'dernieresCiblesAttaquees'); let ripostesDuTour = new Set(); if (attrCiblesAttaquees.length > 0) { @@ -14690,16 +14809,16 @@ var COFantasy = COFantasy || function() { return false; } if (options.seulementVivant && estNonVivant(target)) { - sendPlayer(playerName, "cette attaque n'affecte que les créatures vivantes", playerId); + sendPlayer(playerName, "cette attaque n'affecte que les cr\xE9atures vivantes", playerId); return false; } if (options.attaqueMentale) { if (predicateAsBool(target, 'sansEsprit')) { - sendPlayer(playerName, "cette attaque n'affecte que les créatures pensantes", playerId); + sendPlayer(playerName, "cette attaque n'affecte que les cr\xE9atures pensantes", playerId); return false; } if (predicateAsBool(target, 'vegetatif')) { - sendPlayer(playerName, "cette attaque n'affecte pas les créatures vég etatives", playerId); + sendPlayer(playerName, "cette attaque n'affecte pas les cr\xE9atures v\xE9g etatives", playerId); return false; } } @@ -14708,14 +14827,14 @@ var COFantasy = COFantasy || function() { return false; } if (attributeAsBool(attaquant, 'tenuADistanceManoeuvre(' + target.token.id + ')')) { - sendPerso(attaquant, "est tenu à distance de " + nomPerso(target) + ", " + onGenre(attaquant, "il", "elle") + " ne peut pas l'attaquer ce tour."); + sendPerso(attaquant, "est tenu \xE0 distance de " + nomPerso(target) + ", " + onGenre(attaquant, "il", "elle") + " ne peut pas l'attaquer ce tour."); return false; } if (charAttributeAsBool(target, 'armeeConjuree')) { return options.attaqueArmeeConjuree; } if (ripostesDuTour.has(target.token.id)) { - sendPerso(attaquant, "a déjà fait une riposte contre " + nomPerso(target)); + sendPerso(attaquant, "a d\xE9j\xE0 fait une riposte contre " + nomPerso(target)); return false; } if (options.ricochets) { @@ -14723,7 +14842,7 @@ var COFantasy = COFantasy || function() { return c.token.id == target.token.id; }); if (dejaTouche) { - sendPerso(attaquant, nomPerso(target) + " a déjà été touché par un précédent ricochet de cette attaque"); + sendPerso(attaquant, nomPerso(target) + " a d\xE9j\xE0 \xE9t\xE9 touch\xE9 par un pr\xE9c\xE9dent ricochet de cette attaque"); return false; } } @@ -14731,7 +14850,7 @@ var COFantasy = COFantasy || function() { }); if (cibles.length === 0) { if (options.aoe) { - sendPlayer(playerName, "aucune cible dans l'aire d'effet de " + weaponName + ", action annulée", + sendPlayer(playerName, "aucune cible dans l'aire d'effet de " + weaponName + ", action annul\xE9e", playerId); } attackCallback(options); @@ -14742,7 +14861,7 @@ var COFantasy = COFantasy || function() { let optDistance = {}; options.portee = portee; if (options.contact) optDistance.allonge = options.allonge; - // Si l'attaquant est monté, distance mesurée à partir de sa monture + // Si l'attaquant est mont\xE9, distance mesur\xE9e \xE0 partir de sa monture if (tokenOrigine.id == attackingToken.id) { let attrMonture = tokenAttribute(attaquant, 'monteSur'); if (attrMonture.length > 0) { @@ -14752,7 +14871,7 @@ var COFantasy = COFantasy || function() { } } cibles = cibles.filter(function(target) { - // Si la cible est montée, distance mesurée vers sa monture + // Si la cible est mont\xE9e, distance mesur\xE9e vers sa monture let pseudoTargetToken = target.token; let attrMonture = tokenAttribute(target, 'monteSur'); if (attrMonture.length > 0) { @@ -14763,11 +14882,17 @@ var COFantasy = COFantasy || function() { target.distance = distanceCombat(tokenOrigine, pseudoTargetToken, pageId, optDistance); if (options.intercepter || options.interposer) return true; - if (target.distance > portee && target.msgEsquiveFatale === undefined && !(target.chairACanon || target.intercepter)) { - if (options.aoe || options.auto) return false; //distance stricte - if (target.distance > (predicateAsBool(attaquant, 'tirParabolique') ? 3 : 2) * portee) return false; - // On peut aller jusqu'à 2x portee si unique cible et jet d'attaque, 3x si le personnage a Tir Parabolique - return true; + let porteeMax = portee; + if (!options.aoe) { + if (!options.auto) { + // On peut aller jusqu'\xE0 2x portee si unique cible et jet d'attaque, 3x si le personnage a Tir Parabolique + if (predicateAsBool(attaquant, 'tirParabolique')) porteeMax = 3 * portee; + else porteeMax = 2 * portee; + } + if (options.deplaceDe) porteeMax += options.deplaceDe.max; + } + if (target.distance > porteeMax && target.msgEsquiveFatale === undefined && !(target.chairACanon || target.intercepter)) { + return false; } if (target.distance === 0 && options.seulementDistance) { sendPerso(attaquant, "est trop proche de " + nomPerso(target) + " pour cette attaque"); @@ -14776,7 +14901,7 @@ var COFantasy = COFantasy || function() { return true; }); } - //On enlève les alliés si l'option saufAllies est active + //On enl\xE8ve les alli\xE9s si l'option saufAllies est active if (options.saufAllies) { let allies = new Set(); allies = alliesParPerso[attaquant.charId] || allies; @@ -14785,7 +14910,7 @@ var COFantasy = COFantasy || function() { return !(allies.has(target.charId)); }); } - //On vérifie que les cibles sont assez proches les unes des autres + //On v\xE9rifie que les cibles sont assez proches les unes des autres if (options.ciblesDansDisque && cibles.length > 1) { let l1, l2, t1, t2; cibles.forEach(function(target) { @@ -14798,7 +14923,7 @@ var COFantasy = COFantasy || function() { }); let maxpix = options.ciblesDansDisque * PIX_PER_UNIT / computeScale(pageId); if ((l2 - l1) > 2 * maxpix || (t2 - t1) > 2 * maxpix) { - sendPlayer(playerName, "Cibles trop éloignées les unes des autres"); + sendPlayer(playerName, "Cibles trop \xE9loign\xE9es les unes des autres"); attackCallback(options); return; } @@ -14809,14 +14934,14 @@ var COFantasy = COFantasy || function() { x: (l1 + l2) / 2, y: (t1 + t2) / 2 }; - //C'est approché, mais sûrement assez bon pour ce qui nous occupe + //C'est approch\xE9, mais s\xFBrement assez bon pour ce qui nous occupe let tropLoin = cibles.some(function(target) { let pt = pointOfToken(target.token); attackCallback(options); return (distancePoints(centre, pt) > maxpix + 1); }); if (tropLoin) { - sendPlayer(playerName, "Cibles trop éloignées les unes des autres"); + sendPlayer(playerName, "Cibles trop \xE9loign\xE9es les unes des autres"); attackCallback(options); return; } @@ -14824,17 +14949,112 @@ var COFantasy = COFantasy || function() { } if (cibles.length === 0) { if (options.aoe) { - sendPlayer(playerName, "aucune cible dans l'aire d'effet de " + weaponName + ", action annulée", + sendPlayer(playerName, "aucune cible dans l'aire d'effet de " + weaponName + ", action annul\xE9e", playerId); return; } if (!options.seulementDistance) { - sendPerso(attaquant, "est hors de portée de " + nomCiblePrincipale + " pour une attaque utilisant " + weaponName + ", action annulée"); + sendPerso(attaquant, "est hors de port\xE9e de " + nomCiblePrincipale + " pour une attaque utilisant " + weaponName + ", action annul\xE9e"); } return; } - //On enlève les doublons de cibles qui partagent leurs PVs; + //On enl\xE8ve les doublons de cibles qui partagent leurs PVs; cibles = enleveDoublonsPartagePV(cibles); + //On v\xE9rifie si le d\xE9placement est possible + if (options.deplaceDe && cibles.length == 1) { + let target = cibles[0]; + let deplaceDe = options.deplaceDe; + if (deplaceDe.min && deplaceDe.min > target.distance) { + sendPerso(attaquant, "est trop proche de sa cible pour cette action, on annule"); + return; + } + if (target.distance > 0) { + let rayonAttaquant = tokenSizeAsCircle(attackingToken) / 2; + let rayonTarget = tokenSizeAsCircle(target.token) / 2; + let distMin = rayonAttaquant + rayonTarget; + let dist = distancePixToken(attackingToken, target.token); + if (dist - distMin > portee) { + //On essaie 10 chemins : la position la plus proche, puis les 9 qui entourent la cible + let k = distMin / dist; + if (portee > 0 && dist - distMin > deplaceDe.max) { + //On ne peut pas d\xE9placer au contact, on va donc d\xE9placer \xE0 la limite de la port\xE9e + k = portee / dist; + } + let tx = target.token.get('left'); + let ty = target.token.get('top'); + let x = k * attackingToken.get('left') + (1 - k) * tx; + let y = k * attackingToken.get('top') + (1 - k) * ty; + let ptCible = { + x, + y + }; + //On regarde s'il existe un chemin possible sans passer par un token + let allToks = + findObjs({ + _type: 'graphic', + _pageid: pageId, + _subtype: 'token', + layer: 'objects' + }); + page = page || getObj('page', pageId); + murs = getWalls(page, pageId, murs); + let surTrajet = + tokensSurTrajet(attackingToken, ptCible, rayonAttaquant, allToks, murs, deplaceDe.saut); + if (surTrajet.length > 0) { + //On ne cherche les autres positions que pour les attaques au contact + if (options.contact) { + let diag = distMin / Math.SQRT2; + let positionsAlternatives = [{ + x: tx - diag, + y: ty - diag + }, { + x: tx, + y: ty - distMin + }, { + x: tx + diag, + y: ty - diag + }, { + x: tx - distMin, + y: ty + }, { + x: tx + distMin, + y: ty + }, { + x: tx - diag, + y: ty + diag + }, { + x: tx, + y: ty + distMin + }, { + x: tx + diag, + y: ty + diag + }]; + let pt = pointOfToken(attackingToken); + positionsAlternatives.sort(function(p1, p2) { + let d1 = distancePoints(pt, p1); + let d2 = distancePoints(pt, p2); + if (d1 < d2) return -1; + if (d2 < d1) return 1; + return 0; + }); + positionsAlternatives.forEach(function(ptCible) { + if (deplaceDe.positionFinale) return; + let ts = + tokensSurTrajet(attackingToken, ptCible, rayonAttaquant, allToks, murs, deplaceDe.saut); + if (ts.length === 0) deplaceDe.positionFinale = ptCible; + }); + } + if (!deplaceDe.positionFinale) { + let msg = "Il y a des obstacles sur le trajet : " + surTrajet.join(', '); + sendPerso(attaquant, msg); + return; + } + } else { + deplaceDe.positionFinale = ptCible; + } + } + } + } let evt = options.evt || { type: "Attaque", action: { @@ -14846,13 +15066,20 @@ var COFantasy = COFantasy || function() { options: options } }; + if (options.terrainDifficile && options.aoe && options.aoe.type == 'disque') { + ajouteTerrainDifficile(options, evt); + } if (options.attaqueArmeeConjuree) { setAttrDuree(attaquant, 'attaqueArmeeConjuree', 1, evt); } evt.action = evt.action || { options: JSON.parse(JSON.stringify(options)) //pour la chance etc. }; - //On met à jour l'arme en main, si nécessaire + if (options.deplaceDe && options.deplaceDe.positionFinale) { + let p = options.deplaceDe.positionFinale; + moveTokenWithUndo(attackingToken, p.x, p.y, evt); + } + //On met \xE0 jour l'arme en main, si n\xE9cessaire if (weaponStats.arme || weaponStats.armeGauche || (weaponStats.divers && weaponStats.divers.toLowerCase().includes('arme'))) { options.weaponStats = weaponStats; options.messages = options.messages || []; @@ -14863,16 +15090,16 @@ var COFantasy = COFantasy || function() { if (options.contact && weaponStats.arme && predicateAsBool(attaquant, 'frappeDuVide')) { if (attributeAsBool(attaquant, 'limiteParTour_frappeDuVidePossible')) options.frappeDuVide = true; - //Il faut noter la première attaque au contact + //Il faut noter la premi\xE8re attaque au contact setTokenAttr(attaquant, 'limiteParCombat_dejaFrappeContact', true, evt); } let riposte = predicateAsBool(attaquant, 'riposte'); - let attaqueEnMeute = predicateAsInt(attaquant, 'attaqueEnMeute', 0); + let attaqueEnMeute = predicateAsInt(attaquant, 'attaqueEnMeute', 0, 2); if (attaqueEnMeute > 0) options.attaqueEnMeute = attaqueEnMeute; options.lienEpique = predicateAsBool(attaquant, 'lienEpique'); - if (riposte || options.attaqueEnMeute || options.lienEpique) { - //Dans ce cas, il faut stoquer les cibles attaquées - //(dans le cas de riposte, pour ne pas les re-proposer en riposte + if (riposte || options.attaqueEnMeute || options.lienEpique || alliesDAttaqueEnMeute.has(attackingCharId)) { + //Dans ce cas, il faut stoquer les cibles attaqu\xE9es + //(dans le cas de riposte, pour ne pas les re-proposer en riposte) let listeCibles = cibles.map(function(target) { return target.token.id; @@ -14885,7 +15112,7 @@ var COFantasy = COFantasy || function() { } else { setTokenAttr(attaquant, 'dernieresCiblesAttaquees', listeCibles, evt); } - } else { //L'attribut existe déjà + } else { //L'attribut existe d\xE9j\xE0 attrCiblesAttaquees = attrCiblesAttaquees[0]; evt.attributes = evt.attributes || []; let attaquesDuTour = attrCiblesAttaquees.get('current'); @@ -14910,13 +15137,13 @@ var COFantasy = COFantasy || function() { let explications = []; if (options.messages) explications = [...options.messages]; if (options.magieRapide) explications.push("Magie rapide"); - //On fait les tests pour les cibles qui bénéficieraient d'un sanctuaire + //On fait les tests pour les cibles qui b\xE9n\xE9ficieraient d'un sanctuaire let ciblesATraiter = cibles.length; let cibleTraitee = function() { ciblesATraiter--; if (ciblesATraiter === 0) { evalITE(attaquant, undefined, undefined, options, 0, evt, explications, options, function() { - resoudreAttaque(attaquant, cibles, attackLabel, weaponName, weaponStats, playerId, pageId, evt, explications, options, chargesArme); + resoudreAttaque(attaquant, cibles, attackLabel, weaponName, weaponStats, playerId, pageId, evt, explications, options); }); } }; @@ -14932,10 +15159,10 @@ var COFantasy = COFantasy || function() { let testId = 'sanctuaire_' + cible.token.id; testCaracteristique(attaquant, 'SAG', 15, testId, options, evt, function(tr) { if (tr.reussite) { - cible.messages.push(nomPerso(attaquant) + " réussit à passer outre le sanctuaire de " + nomPerso(cible) + " (jet de SAG " + tr.texte + "≥15)" + tr.modifiers); + cible.messages.push(nomPerso(attaquant) + " r\xE9ussit \xE0 passer outre le sanctuaire de " + nomPerso(cible) + " (jet de SAG " + tr.texte + "≥15)" + tr.modifiers); cibleTraitee(); } else { - let msgRate = "ne peut se résoudre à attaquer " + nomPerso(cible) + " (sanctuaire, jet de SAG " + tr.texte + "< 15)" + tr.rerolls + tr.modifiers; + let msgRate = "ne peut se r\xE9soudre \xE0 attaquer " + nomPerso(cible) + " (sanctuaire, jet de SAG " + tr.texte + "< 15)" + tr.rerolls + tr.modifiers; sendPerso(attaquant, msgRate); attaqueImpossible = true; } @@ -14944,14 +15171,14 @@ var COFantasy = COFantasy || function() { cibleTraitee(); } }; - // Attaque de Disparition avec jet opposé + // Attaque de Disparition avec jet oppos\xE9 if (options.disparition) { - //L'immunité aux attaques sournoise est testée plus loin et ne devrait - //pas empêcher le bonus de +5 à l'attaque. + //L'immunit\xE9 aux attaques sournoise est test\xE9e plus loin et ne devrait + //pas emp\xEAcher le bonus de +5 \xE0 l'attaque. let rollId = 'disparition_' + cible.token.id; let options1 = {...options }; - options1.competence = 'discrétion'; + options1.competence = 'discr\xE9tion'; let options2 = {...options }; options2.competence = 'perception'; @@ -14959,13 +15186,13 @@ var COFantasy = COFantasy || function() { cible.messages, evt, function(resultat, crit, rt1, rt2) { if (resultat != 2) { - cible.messages.push(nomPerso(attaquant) + " réapparait à côté de " + nomPerso(cible) + " et lui porte une attaque mortelle !"); + cible.messages.push(nomPerso(attaquant) + " r\xE9apparait \xE0 c\xF4t\xE9 de " + nomPerso(cible) + " et lui porte une attaque mortelle !"); // rajout des bonus de sournoise options.bonusAttaque = (options.bonusAttaque || 0) + 5; options.sournoise = options.sournoise || 0; options.sournoise += options.disparition; } else { - cible.messages.push(nomPerso(cible) + " repère " + nomPerso(attaquant) + " à temps pour réagir."); + cible.messages.push(nomPerso(cible) + " rep\xE8re " + nomPerso(attaquant) + " \xE0 temps pour r\xE9agir."); } evalSanctuaire(); }); //fin de testOppose (asynchrone) @@ -14977,16 +15204,16 @@ var COFantasy = COFantasy || function() { explications.push("Tentative d'acrobatie pour surprendre " + nomPerso(cible)); testCaracteristique(attaquant, 'DEX', 15, rollId, rollOptions, evt, function(tr, expl) { - explications.push("Résultat : " + tr.texte + tr.modifiers); + explications.push("R\xE9sultat : " + tr.texte + tr.modifiers); expl.forEach(function(m) { explications.push(m); }); if (tr.reussite) { - explications.push("Réussite : " + nomPerso(attaquant) + " peut faire une attaque sournoise"); + explications.push("R\xE9ussite : " + nomPerso(attaquant) + " peut faire une attaque sournoise"); options.sournoise = options.sournoise || 0; options.sournoise += options.attaqueAcrobatique; } else { - explications.push("Raté, " + nomPerso(attaquant) + " réalise une attaque normale" + tr.rerolls); + explications.push("Rat\xE9, " + nomPerso(attaquant) + " r\xE9alise une attaque normale" + tr.rerolls); } evalSanctuaire(); }); @@ -14994,7 +15221,7 @@ var COFantasy = COFantasy || function() { }); } - // On affiche les options d'attaque à droite + // On affiche les options d'attaque \xE0 droite function afficherOptionsAttaque(perso, opt_display) { let action_opts = '!cof-options-d-attaque --target ' + perso.token.id; let text_opts = ''; @@ -15007,11 +15234,11 @@ var COFantasy = COFantasy || function() { } if (ficheAttributeAsInt(perso, 'attaque_risquee_check')) { if (text_opts !== '') text_opts += '
'; - text_opts += "Risquée"; + text_opts += "Risqu\xE9e"; } if (ficheAttributeAsInt(perso, 'attaque_assuree_check')) { if (text_opts !== '') text_opts += '
'; - text_opts += "Assurée"; + text_opts += "Assur\xE9e"; } if (ficheAttributeAsInt(perso, 'attaque_dm_temp_check')) { if (text_opts !== '') text_opts += '
'; @@ -15048,7 +15275,7 @@ var COFantasy = COFantasy || function() { let rawList; if (persoEstPNJ(perso)) rawList = extractRepeating(perso, 'pnjatk'); else rawList = extractRepeating(perso, 'armes'); - let liste = {}; //liste triée par label d'attaque + let liste = {}; //liste tri\xE9e par label d'attaque for (let pref in rawList) { let ra = rawList[pref]; if (ra.armelabel === undefined) ra.armelabel = 0; @@ -15073,7 +15300,7 @@ var COFantasy = COFantasy || function() { let rang = parseInt(ra.actionrang); if (isNaN(rang) || rang < 0) rang = 0; if (actions[rang]) { - error("Plusieurs actions de même rang " + rang + " dans la liste d'actions du tour", ra); + error("Plusieurs actions de m\xEAme rang " + rang + " dans la liste d'actions du tour", ra); continue; } actions[rang] = ra; @@ -15082,11 +15309,11 @@ var COFantasy = COFantasy || function() { return actions; } - // on récupère la valeur de l'action dont chaque Macro #/Ability % est mis dans un tableau 'action' + // on r\xE9cup\xE8re la valeur de l'action dont chaque Macro #/Ability % est mis dans un tableau 'action' //Pour chaque action, on a une commande, un texte et des options. //On appelle f(commande, texte, macros, attackStats) - // le dernier argument est optionnel, et n'est là que pour éviter d'avoir à recalculer attackStats - //actionsDuTour peut être un nombre entre 0 et 4 (listes sur la fiche), ou + // le dernier argument est optionnel, et n'est l\xE0 que pour \xE9viter d'avoir \xE0 recalculer attackStats + //actionsDuTour peut \xEAtre un nombre entre 0 et 4 (listes sur la fiche), ou // une ability function treatActions(perso, actionsDuTour, abilities, f) { let actions; // La liste des actions @@ -15147,7 +15374,7 @@ var COFantasy = COFantasy || function() { } else { actionCode = action.trim(); if (actionCode === '') return; - if (actionCode.startsWith('//')) return; //Ligne commentée + if (actionCode.startsWith('//')) return; //Ligne comment\xE9e } let actionCommands = actionCode.split(' '); actionCommands = actionCommands.filter(function(c) { @@ -15224,7 +15451,7 @@ var COFantasy = COFantasy || function() { case '!options': found = true; if (actionCommands.length > 1) { - options = actionCode.substring(8); //démarre par ' ' + options = actionCode.substring(8); //d\xE9marre par ' ' } break; case '!attaques': @@ -15272,8 +15499,8 @@ var COFantasy = COFantasy || function() { if (found) { actionsAAfficher = true; } else { - // Si on n'a toujours rien trouvé, on ajoute un petit log - log('Ability et macro non trouvé : ' + actionCode); + // Si on n'a toujours rien trouv\xE9, on ajoute un petit log + log('Ability et macro non trouv\xE9 : ' + actionCode); } }); } @@ -15298,7 +15525,7 @@ var COFantasy = COFantasy || function() { } else if (action == 'Attaques en traitre') { actions = findListeActions(attaquant, 'AttaqueEnTraitre', abilities); if (actions === undefined) - actions = findListeActions(attaquant, 'Attaques en traître', abilities); + actions = findListeActions(attaquant, 'Attaques en tra\xEEtre', abilities); } } let actionsOpportunite = []; @@ -15322,7 +15549,7 @@ var COFantasy = COFantasy || function() { }); actionsOpportunite.reverse(); } else { - //On affiche l'attaque avec l'arme en main + les attaques naturelles cochées + //On affiche l'attaque avec l'arme en main + les attaques naturelles coch\xE9es let listeAttaques = listAllAttacks(attaquant); for (let label in listeAttaques) { let arme = listeAttaques[label]; @@ -15344,14 +15571,14 @@ var COFantasy = COFantasy || function() { retarde: true, }; afficherOptionsAttaque(attaquant, opt_display); - //On crée un display sans le header + //On cr\xE9e un display sans le header let display = startFramedDisplay(undefined, "Attaque " + type + " possible", attaquant, opt_display); cibles.forEach(function(target) { - if (target.name === undefined) { //TODO vérifier que c'est utile + if (target.name === undefined) { //TODO v\xE9rifier que c'est utile let targetChar = getObj('character', target.charId); if (targetChar === undefined) { - error('Impossible de trouver le personnage représentant ' + nomPerso(target), target); + error('Impossible de trouver le personnage repr\xE9sentant ' + nomPerso(target), target); return; } target.name = targetChar.get('name'); @@ -15373,7 +15600,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, bouton(cmd, action.text, attaquant)); }); }); - // on envoie la liste aux joueurs qui gèrent l'attaquant + // on envoie la liste aux joueurs qui g\xE8rent l'attaquant let playerIds = getPlayerIds(attaquant); playerIds.forEach(function(playerid) { addFramedHeader(display, playerid, true); @@ -15394,7 +15621,7 @@ var COFantasy = COFantasy || function() { x.dmgTotal += bonusCrit.val; } - function immuniseAuType(target, dmgType, attaquant) { + function immuniseAuType(target, dmgType, attaquant, options) { if (predicateAsBool(target, 'immunite_' + dmgType)) { if (dmgType == 'acide' && predicateAsBool(attaquant, 'batonDesRunesMortes') && predicateAsBool(target, 'ennemiDuBatonDesRunesMortes')) return false; return true; @@ -15406,6 +15633,7 @@ var COFantasy = COFantasy || function() { return false; case 'poison': if (estNonVivant(target)) return true; + if (estDemon(target) && !(options && options.magique)) return true; if (predicateAsBool(target, 'vegetatif')) return true; if (attributeAsBool(target, 'sangDeLArbreCoeur')) return true; if (predicateOrAttributeAsBool(target, 'controleSanguin')) return true; @@ -15418,6 +15646,7 @@ var COFantasy = COFantasy || function() { return attributeAsBool(target, 'presenceGlaciale'); case 'maladie': if (estNonVivant(target)) return true; + if (estDemon(target) && !(options && options.magique)) return true; if (predicateAsBool(target, 'vegetatif')) return true; return attributeAsBool(target, 'sangDeLArbreCoeur'); case 'drain': @@ -15429,15 +15658,15 @@ var COFantasy = COFantasy || function() { function immuniseAsphyxie(target, expliquer) { if (predicateAsBool(target, 'creatureArtificielle') || estNonVivant(target)) { - if (expliquer) expliquer("L'asphyxie est sans effet sur une créature non-vivante"); + if (expliquer) expliquer("L'asphyxie est sans effet sur une cr\xE9ature non-vivante"); return true; } if (estDemon(target)) { - if (expliquer) expliquer("L'asphyxie est sans effet sur un démon"); + if (expliquer) expliquer("L'asphyxie est sans effet sur un d\xE9mon"); return true; } if (predicateAsBool(target, 'vegetatif')) { - if (expliquer) expliquer("L'asphyxie est sans effet sur une créature végétative"); + if (expliquer) expliquer("L'asphyxie est sans effet sur une cr\xE9ature v\xE9g\xE9tative"); return true; } return false; @@ -15460,9 +15689,9 @@ var COFantasy = COFantasy || function() { // Fonction asynchrone // displayRes est optionnel, et peut avoir 2 arguments - // - un texte affichant le jet de dégâts - // - la valeur finale des dégâts infligés - // crit est un booléen, il augmente de 1 (ou options.critCoef) le coefficient (option.dmgCoef) et active certains effets + // - un texte affichant le jet de d\xE9g\xE2ts + // - la valeur finale des d\xE9g\xE2ts inflig\xE9s + // crit est un bool\xE9en, il augmente de 1 (ou options.critCoef) le coefficient (option.dmgCoef) et active certains effets function dealDamage(target, dmg, otherDmg, evt, crit, options, explications, displayRes) { if (options === undefined) options = {}; let expliquer = function(msg) { @@ -15478,7 +15707,7 @@ var COFantasy = COFantasy || function() { (options.aoe === undefined && attributeAsBool(target, 'formeGazeuse')) || (predicateAsBool(target, 'apparition') && !options.energiePositive)) { - expliquer("L'attaque passe à travers de " + nomPerso(target)); + expliquer("L'attaque passe \xE0 travers de " + nomPerso(target)); if (displayRes) displayRes('0', 0, 0); return 0; } @@ -15503,7 +15732,7 @@ var COFantasy = COFantasy || function() { options.aoe.type == 'cone' && predicateAsBool(options.attaquant, 'ennemiDuBatonDesRunesMortes') && predicateAsBool(target, 'batonDesRunesMortes') && attributeAsBool(target, 'runeLizura')) { - expliquer("Lizura => immunité au souffle de " + nomPerso(options.attaquant)); + expliquer("Lizura => immunit\xE9 au souffle de " + nomPerso(options.attaquant)); if (displayRes) displayRes('0', 0, 0); return 0; } @@ -15514,7 +15743,7 @@ var COFantasy = COFantasy || function() { if (target.diviseDmg) diviseDmg *= target.diviseDmg; if (options.attaquant && predicateAsBool(options.attaquant, 'creatureDeLHiver') && predicateAsBool(target, 'armeDeLEte')) { diviseDmg += 4; - expliquer("L'arme de l'été divise les dégâts de l'attaque"); + expliquer("L'arme de l'\xE9t\xE9 divise les d\xE9g\xE2ts de l'attaque"); } if (options.attaqueEnEtantGobe) diviseDmg *= 2; if (options.sortilege && predicateAsBool(target, 'esquiveDeLaMagie')) @@ -15532,25 +15761,25 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(target, 'armureLourdeGuerrier') && ficheAttributeAsBool(target, 'defarmureon', false) && ficheAttributeAsInt(target, 'defarmure', 0) >= 7) { - expliquer("L'armure lourde de " + nomPerso(target) + " lui permet d'ignorer les dégâts critiques"); + expliquer("L'armure lourde de " + nomPerso(target) + " lui permet d'ignorer les d\xE9g\xE2ts critiques"); } else if (predicateAsBool(target, 'immuniteAuxCritiques')) { - expliquer("Le succès critique est sans effet"); + expliquer("Le succ\xE8s critique est sans effet"); } else { if (options.critCoef) critCoef = options.critCoef; if (target.critCoef) critCoef += target.critCoef; dmgCoef += critCoef; if (predicateAsBool(target, 'armureProtection') && ficheAttributeAsBool(target, 'defarmureon', false)) { - expliquer("L'armure de protection de " + nomPerso(target) + " le protège du critique"); + expliquer("L'armure de protection de " + nomPerso(target) + " le prot\xE8ge du critique"); diviseDmg++; } else if (predicateAsBool(target, 'bouclierProtection') && ficheAttributeAsInt(target, 'defbouclieron', 0)) { - expliquer("Le bouclier de protection de " + nomPerso(target) + " le protège du critique"); + expliquer("Le bouclier de protection de " + nomPerso(target) + " le prot\xE8ge du critique"); diviseDmg++; } else if (predicateAsBool(target, 'anneauProtection')) { - expliquer("L'anneau de protection de " + nomPerso(target) + " le protège du critique"); + expliquer("L'anneau de protection de " + nomPerso(target) + " le prot\xE8ge du critique"); diviseDmg++; } if (predicateAsBool(target, 'bouclierProtection') && ficheAttributeAsBool(target, 'defbouclieron', false)) { - expliquer("Le bouclier de protection de " + nomPerso(target) + " le protège du critique"); + expliquer("Le bouclier de protection de " + nomPerso(target) + " le prot\xE8ge du critique"); diviseDmg++; } } @@ -15616,16 +15845,17 @@ var COFantasy = COFantasy || function() { dmgTotal = x.dmgTotal; } addToDmgTotal(0, dmgTotal, dmg, expliquer, evt); - //On trie les DM supplémentaires selon leur type + //On trie les DM suppl\xE9mentaires selon leur type let dmgParType = {}; otherDmg.forEach(function(d) { if (_.has(dmgParType, d.type)) dmgParType[d.type].push(d); else dmgParType[d.type] = [d]; }); - // Dommages de même type que le principal, mais à part, donc non affectés par les critiques + // Dommages de m\xEAme type que le principal, mais \xE0 part, donc non affect\xE9s par les critiques let mainDmgType = dmg.type; let dmgExtra = dmgParType[mainDmgType]; - if (dmgExtra && dmgExtra.length > 0 && !immuniseAuType(target, mainDmgType, options.attaquant)) { + if (dmgExtra && dmgExtra.length > 0 && + !immuniseAuType(target, mainDmgType, options.attaquant, options)) { if (dmgCoef > 1) dmgDisplay = "(" + dmgDisplay + ")"; showTotal = true; let count = dmgExtra.length; @@ -15656,8 +15886,8 @@ var COFantasy = COFantasy || function() { // Effets quand on rentre en combat // attaquant est optionnel - // exlications doit être défini - // ne rajoute pas evt à l'historique + // exlications doit \xEAtre d\xE9fini + // ne rajoute pas evt \xE0 l'historique // revoie stateCOF.combat, garanti non false function entrerEnCombat(attaquant, cibles, explications, evt) { let selected = []; @@ -15700,7 +15930,7 @@ var COFantasy = COFantasy || function() { return initiative(selected, evt); //ne recalcule pas l'init } - //capa est le nom d'un prédicat. Si le prédicat est numérique, cela donne + //capa est le nom d'un pr\xE9dicat. Si le pr\xE9dicat est num\xE9rique, cela donne //la limite, sinon la limite est 1 // retourne // - utilisations: les nombre d'utilisations restantes, @@ -15722,7 +15952,7 @@ var COFantasy = COFantasy || function() { attribut = attribut[0]; utilisations = parseInt(attribut.get('current')); if (isNaN(utilisations)) { - error("Resource pour " + capa + " mal formée", attribut); + error("Resource pour " + capa + " mal form\xE9e", attribut); return; } } @@ -15912,7 +16142,7 @@ var COFantasy = COFantasy || function() { return attCar + ficheAttributeAsInt(attaquant, 'niveau', 1) + attDiv; } - //Retourne le label de l'attaque à l'arme de jet. + //Retourne le label de l'attaque \xE0 l'arme de jet. function estAussiArmeDeJet(options) { if (options.startsWith('-')) options = ' ' + options; options = options.split(' --'); @@ -16007,7 +16237,7 @@ var COFantasy = COFantasy || function() { }, }); } else { - let exprDuree = parseDice(value, 'durée'); + let exprDuree = parseDice(value, 'dur\xE9e'); let duree = randomInteger(6); if (exprDuree) { if (exprDuree.nbDe <= 0) { @@ -16034,7 +16264,7 @@ var COFantasy = COFantasy || function() { } else { error("Type de poison " + typePoison + " non reconnu.", poisonAttr); } - explications.push("L'arme est empoisonnée"); + explications.push("L'arme est empoisonn\xE9e"); return defPoison; } @@ -16047,7 +16277,7 @@ var COFantasy = COFantasy || function() { let nombreMunitionsEmpoisonnees = parseInt(infosPoisonMunitions.substring(index + 1)); if (!isNaN(seuil) && !isNaN(nombreMunitionsEmpoisonnees) && nombreMunitionsEmpoisonnees > 0) { let defPoison = effetPoison(poisonAttr, seuil, attaquant, explications, options); - explications.push("L'arme est empoisonnée"); + explications.push("L'arme est empoisonn\xE9e"); if (nombreMunitionsEmpoisonnees == 1) { evt.deletedAttributes = evt.deletedAttributes || []; evt.deletedAttributes.push(poisonAttr); @@ -16064,15 +16294,15 @@ var COFantasy = COFantasy || function() { } } - //N'ajoute pas evt à l'historique - function resoudreAttaque(attaquant, cibles, attackLabel, weaponName, weaponStats, playerId, pageId, evt, explications, options, chargesArme) { + //N'ajoute pas evt \xE0 l'historique + function resoudreAttaque(attaquant, cibles, attackLabel, weaponName, weaponStats, playerId, pageId, evt, explications, options) { let attackingCharId = attaquant.charId; let attackingToken = attaquant.token; let attackerTokName = nomPerso(attaquant); - attaquant.additionalDmg = [...options.additionalDmg]; // Reset du calcul des dommages additionnels liés à l'attaquant + attaquant.additionalDmg = [...options.additionalDmg]; // Reset du calcul des dommages additionnels li\xE9s \xE0 l'attaquant let sujetAttaquant = onGenre(attaquant, 'il', 'elle'); if (options.contact) { - //Prise en compte du corps élémentaire + //Prise en compte du corps \xE9l\xE9mentaire let typeCorpsElem = predicateAsBool(attaquant, 'corpsElementaire'); if (typeCorpsElem && typeCorpsElem !== true) { let nbDes = predicateAsInt(attaquant, 'nbCorpsElementaire', 1); @@ -16087,7 +16317,7 @@ var COFantasy = COFantasy || function() { // Les armes de jet if (weaponStats.armeDeJet && !estMook && !(options.ricochets && options.ricochets.cibles.length > 0)) { if (weaponStats.nbArmesDeJet < 1) { - sendPerso(attaquant, "plus de " + weaponName + " à lancer."); + sendPerso(attaquant, "plus de " + weaponName + " \xE0 lancer."); return; } let attrName = weaponStats.prefixe + 'armejetqte'; @@ -16103,12 +16333,12 @@ var COFantasy = COFantasy || function() { if (attr.length > 0) { attr = attr[0]; if (attr.length > 1) { - error("Plus d'un attribut pour la quantité d'armes de jet", attr); + error("Plus d'un attribut pour la quantit\xE9 d'armes de jet", attr); attr[1].remove(); } max = parseInt(attr.get('max')); if (isNaN(max) || max < 1) { - error("Maximum de " + weaponName + " mal formé, vérifier sur la fiche", attr); + error("Maximum de " + weaponName + " mal form\xE9, v\xE9rifier sur la fiche", attr); max = 1; } evt.attributes.push({ @@ -16127,19 +16357,19 @@ var COFantasy = COFantasy || function() { attribute: attr, }); } - //On cherche si l'arme de jet est empoisonée + //On cherche si l'arme de jet est empoison\xE9e let poisonAttr = tokenAttribute(attaquant, 'enduitDePoison_' + attackLabel); effetPoisonSurMunitions(poisonAttr, attaquant, explications, options, evt); let restant = weaponStats.nbArmesDeJet; if (randomInteger(100) < weaponStats.tauxDePerte) { if (weaponStats.tauxDePerte < 100) - explications.push(weaponName + " n'est pas récupérable"); + explications.push(weaponName + " n'est pas r\xE9cup\xE9rable"); attr.set('max', max - 1); options.armeDeJetPerdue = true; } restant--; attr.set('current', restant); - if (!options.armeDeJetPerdue) { //prépare pour un éventuel retour en main + if (!options.armeDeJetPerdue) { //pr\xE9pare pour un \xE9ventuel retour en main options.attrArmeDeJet = { attribute: attr, restant: restant @@ -16148,33 +16378,33 @@ var COFantasy = COFantasy || function() { if (restant === 0) { degainerArmeLancee(attaquant, attackLabel, evt); } - explications.push("Il reste " + restant + " " + weaponName + " à " + attackerTokName); + explications.push("Il reste " + restant + " " + weaponName + " \xE0 " + attackerTokName); } } if (options.aussiArmeDeJet && !estMook) { let armeAssociee = getWeaponStats(attaquant, options.aussiArmeDeJet); if (armeAssociee && armeAssociee.armeDeJet) { if (armeAssociee.nbArmesDeJet < 1) { - sendPerso(attaquant, "a déjà lancé tous ses " + weaponName); + sendPerso(attaquant, "a d\xE9j\xE0 lanc\xE9 tous ses " + weaponName); return; } } else { - error("L'arme de label " + options.aussiArmeDeJet + " n'est pas une arme de jet, option ignorée", armeAssociee); + error("L'arme de label " + options.aussiArmeDeJet + " n'est pas une arme de jet, option ignor\xE9e", armeAssociee); } } // Munitions if (options.munition) { if (estMook) { - error("Les munitions ne sont pas supportées pour les tokens qui ne sont pas liées à un personnage", attackingToken); + error("Les munitions ne sont pas support\xE9es pour les tokens qui ne sont pas li\xE9es \xE0 un personnage", attackingToken); } - if (options.munition.nom) { //Ancienne variante, obsolète depuis mars 2023 + if (options.munition.nom) { //Ancienne variante, obsol\xE8te depuis mars 2023 let munitionsAttr = findObjs({ _type: 'attribute', _characterid: attackingCharId, name: 'munition_' + options.munition.nom }); if (munitionsAttr.length === 0) { - sendPerso(attaquant, ": Pas de munition nommée " + options.munition.nom); + sendPerso(attaquant, ": Pas de munition nomm\xE9e " + options.munition.nom); return; } munitionsAttr = munitionsAttr[0]; @@ -16187,7 +16417,7 @@ var COFantasy = COFantasy || function() { } let munitionsMax = parseInt(munitionsAttr.get('max')); if (isNaN(munitionsMax)) { - error("Attribut de munitions mal formé", munitionsMax); + error("Attribut de munitions mal form\xE9", munitionsMax); return; } evt.attributes = evt.attributes || []; @@ -16196,7 +16426,7 @@ var COFantasy = COFantasy || function() { current: munitions, max: munitionsMax }); - //On cherche si la munition est empoisonnée + //On cherche si la munition est empoisonn\xE9e let poisonAttr = tokenAttribute(attaquant, 'enduitDePoison_munition_' + options.munition.nom); effetPoisonSurMunitions(poisonAttr, attaquant, explications, options, evt); munitions--; @@ -16206,12 +16436,12 @@ var COFantasy = COFantasy || function() { if (randomInteger(100) < options.munition.taux) munitionsMax--; } explications.push("Il reste " + munitions + " " + - options.munition.nom.replace(/_/g, ' ') + " à " + attackerTokName); + options.munition.nom.replace(/_/g, ' ') + " \xE0 " + attackerTokName); munitionsAttr.set('current', munitions); munitionsAttr.set('max', munitionsMax); } else { //Utilisation d'une munition de la fiche let m = options.munition; - let typeMunition = fieldAsString(m, 'typemunition', 'Flèche'); + let typeMunition = fieldAsString(m, 'typemunition', 'Fl\xE8che'); let nom = fieldAsString(m, 'nommunition', typeMunition); let munitions = fieldAsInt(m, 'qtemunition', 1); if (munitions < 1 || (options.tirDouble && munitions < 2)) { @@ -16221,7 +16451,7 @@ var COFantasy = COFantasy || function() { return; } let label = fieldAsString(m, 'labelmunition', '0'); - //On cherche si la munition est empoisonnée + //On cherche si la munition est empoisonn\xE9e let poisonAttr = tokenAttribute(attaquant, 'enduitDePoison_munition_' + label); effetPoisonSurMunitions(poisonAttr, attaquant, explications, options, evt); let munitionsMax = fieldAsInt(m, 'qtemunition_max', munitions); @@ -16245,8 +16475,8 @@ var COFantasy = COFantasy || function() { } else { msgm += "reste " + munitions + " "; } - msgm += nom + " à " + attackerTokName; - if (taux < 100 && perte > 0) msgm += ", et la munition utilisée n'est pas récupérable"; + msgm += nom + " \xE0 " + attackerTokName; + if (taux < 100 && perte > 0) msgm += ", et la munition utilis\xE9e n'est pas r\xE9cup\xE9rable"; explications.push(msgm); evt.attributes = evt.attributes || []; let name = m.prefixe + 'qtemunition'; @@ -16279,15 +16509,20 @@ var COFantasy = COFantasy || function() { } } } - // Armes chargées - if (options.semonce === undefined && options.tirDeBarrage === undefined) { + // Armes charg\xE9es + if ((!options.semonce || attributeAsInt(attaquant, 'attaqueADistanceRatee', 0) != 1) && !options.tirDeBarrage) { if (attackLabel && weaponStats && weaponStats.charge) { let currentCharge = 0; + let chargesArme = findObjs({ + _type: 'attribute', + _characterid: attackingCharId, + name: 'charge_' + attackLabel + }); if (chargesArme.length > 0) { currentCharge = parseInt(chargesArme[0].get('current')); } if (isNaN(currentCharge) || currentCharge < 1) { - sendPerso(attaquant, "ne peut pas attaquer avec " + weaponName + " car elle n'est pas chargée"); + sendPerso(attaquant, "ne peut pas attaquer avec " + weaponName + " car elle n'est pas charg\xE9e"); return; } if (options.tirDouble && @@ -16295,7 +16530,7 @@ var COFantasy = COFantasy || function() { currentCharge < 2) { sendPerso(attaquant, "ne peut pas faire de tir double avec ses" + weaponName + "s car " + - sujetAttaquant + " n'en a pas au moins 2 chargées"); + sujetAttaquant + " n'en a pas au moins 2 charg\xE9es"); return; } evt.attributes = evt.attributes || []; @@ -16304,7 +16539,7 @@ var COFantasy = COFantasy || function() { if (chargesGrenaille.length > 0) { let currentChargeGrenaille = parseInt(chargesGrenaille[0].get('current')); if (isNaN(currentChargeGrenaille) || currentChargeGrenaille < 1) { - sendPerso(attaquant, "ne peut pas attaquer avec " + weaponName + " car elle n'est pas chargée en grenaille"); + sendPerso(attaquant, "ne peut pas attaquer avec " + weaponName + " car elle n'est pas charg\xE9e en grenaille"); return; } if (options.tirDouble && @@ -16312,7 +16547,7 @@ var COFantasy = COFantasy || function() { currentChargeGrenaille < 2) { sendPerso(attaquant, "ne peut pas faire de tir double de grenaille avec ses" + weaponName + "s car " + - sujetAttaquant + " n'en a pas au moins 2 chargées de grenaille"); + sujetAttaquant + " n'en a pas au moins 2 charg\xE9es de grenaille"); return; } evt.attributes.push({ @@ -16333,7 +16568,7 @@ var COFantasy = COFantasy || function() { if (options.tirDouble && (!options.tirDouble.stats || options.tirDouble.label == attackLabel)) currentCharge -= 2; else currentCharge -= 1; - //Si l'arme n'est plus chargée, on peut perdre le bonus d'initiative + //Si l'arme n'est plus charg\xE9e, on peut perdre le bonus d'initiative if (currentCharge === 0 && bonusPlusViteQueSonOmbre(attaquant, weaponStats)) { updateNextInit(attaquant); @@ -16351,7 +16586,7 @@ var COFantasy = COFantasy || function() { if (chargesSecondeArme.length > 0) { let currentCharge2 = parseInt(chargesSecondeArme[0].get('current')); if (isNaN(currentCharge2) || currentCharge2 < 1) { - sendPerso(attaquant, "ne peut pas faire de tir double avec " + secondNom + " car ce n'est pas chargé"); + sendPerso(attaquant, "ne peut pas faire de tir double avec " + secondNom + " car ce n'est pas charg\xE9"); return; } evt.attributes = evt.attributes || []; @@ -16360,7 +16595,7 @@ var COFantasy = COFantasy || function() { if (chargesGrenaille2.length > 0) { let currentChargeGrenaille2 = parseInt(chargesGrenaille2[0].get('current')); if (isNaN(currentChargeGrenaille2) || currentChargeGrenaille2 < 1) { - sendPerso(attaquant, "ne peut pas faire de tir double avec " + secondNom + " car ce n'est pas chargé en grenaille"); + sendPerso(attaquant, "ne peut pas faire de tir double avec " + secondNom + " car ce n'est pas charg\xE9 en grenaille"); return; } evt.attributes.push({ @@ -16375,7 +16610,7 @@ var COFantasy = COFantasy || function() { attribute: chargesSecondeArme[0], current: currentCharge2 }); - chargesArme[0].set('current', currentCharge2 - 1); + chargesSecondeArme[0].set('current', currentCharge2 - 1); } } } @@ -16384,9 +16619,9 @@ var COFantasy = COFantasy || function() { } // Effets quand on rentre en combat entrerEnCombat(attaquant, cibles, explications, evt); - // On commence par le jet d'attaque de base : juste le ou les dés d'attaque - // et le modificateur d'arme et de caractéritiques qui apparaissent dans - // la description de l'attaque. Il faut quand même tenir compte des + // On commence par le jet d'attaque de base : juste le ou les d\xE9s d'attaque + // et le modificateur d'arme et de caract\xE9ritiques qui apparaissent dans + // la description de l'attaque. Il faut quand m\xEAme tenir compte des // chances de critique let crit = critEnAttaque(attaquant, weaponStats, options); let dice = 20; @@ -16402,7 +16637,7 @@ var COFantasy = COFantasy || function() { } } else if (getState(attaquant, 'immobilise')) { dice = 12; - explications.push("Attaquant immobilisé => D12 au lieu de D20 en Attaque"); + explications.push("Attaquant immobilis\xE9 => D12 au lieu de D20 en Attaque"); } else if (attributeAsBool(attaquant, 'mortMaisNAbandonnePas')) { dice = 12; explications.push("Attaquant mort mais n'abandonne pas => D12 au lieu de D20 en Attaque"); @@ -16426,7 +16661,7 @@ var COFantasy = COFantasy || function() { if (options.avantage !== undefined) { if (options.avantage > 0) nbDe = options.avantage; else { - nbDe = 2 - options.avantage; //désavantage + nbDe = 2 - options.avantage; //d\xE9savantage plusFort = false; } } @@ -16443,7 +16678,7 @@ var COFantasy = COFantasy || function() { // toEvaluateAttack inlines // 0: attack roll // 1: attack skill expression - // 2: dé de poudre + // 2: d\xE9 de poudre let toEvaluateAttack = attackExpression(attaquant, nbDe, dice, crit, plusFort, weaponStats); if (options.poudre) toEvaluateAttack += " [[1d20]]"; @@ -16482,17 +16717,17 @@ var COFantasy = COFantasy || function() { retarde: options.secret, auto: options.auto || options.ouvertureMortelle }); - // Cas des armes à poudre + // Cas des armes \xE0 poudre if (options.poudre && !predicateAsBool(attaquant, 'chimiste')) { let poudreNumber = rollNumber(afterEvaluateAttack[2]); let dePoudre = rollsAttack.inlinerolls[poudreNumber].results.total; explications.push( - "Dé de poudre : " + buildinline(rollsAttack.inlinerolls[poudreNumber])); + "D\xE9 de poudre : " + buildinline(rollsAttack.inlinerolls[poudreNumber])); if (dePoudre === 1) { evt.succes = false; if (d20roll === 1) { explications.push( - weaponName + " explose ! L'arme est complètement détruite"); + weaponName + " explose ! L'arme est compl\xE8tement d\xE9truite"); sendChat("", "[[2d6]]", function(res) { let rolls = res[0]; let explRoll = rolls.inlinerolls[0]; @@ -16513,7 +16748,7 @@ var COFantasy = COFantasy || function() { } else { explications.push( "La poudre explose dans " + weaponName + - ". L'arme est inutilisable jusqu'à la fin du combat"); + ". L'arme est inutilisable jusqu'\xE0 la fin du combat"); sendChat("", "[[1d6]]", function(res) { let rolls = res[0]; let explRoll = rolls.inlinerolls[0]; @@ -16550,7 +16785,7 @@ var COFantasy = COFantasy || function() { options.projection = true; } } - //Modificateurs en Attaque qui ne dépendent pas de la cible + //Modificateurs en Attaque qui ne d\xE9pendent pas de la cible let attBonusCommun = 0; if (!options.auto) { attBonusCommun = @@ -16560,36 +16795,36 @@ var COFantasy = COFantasy || function() { bonusDMA(attaquant, weaponName, evt, explications, options); } if (options.traquenard) { - if (attributeAsBool(attaquant, 'traquenardImpossible')) { - sendPerso(attaquant, "ne peut pas faire de traquenard, car ce n'est pas sa première attaque du combat"); + if (attributeAsBool(attaquant, 'attributDeCombat_premiereAttaque')) { + sendPerso(attaquant, "ne peut pas faire de traquenard, car ce n'est pas sa premi\xE8re attaque du combat"); return; } options.traquenard = persoInit(attaquant, evt); } - if (predicateAsBool(attaquant, 'traquenard') && !attributeAsBool(attaquant, 'traquenardImpossible')) { - setTokenAttr(attaquant, 'traquenardImpossible', true, evt); + if (!attributeAsBool(attaquant, 'attributDeCombat_premiereAttaque')) { + setTokenAttr(attaquant, 'attributDeCombat_premiereAttaque', true, evt); } - if (options.feinte) explications.push("Mais c'était une feinte..."); + if (options.feinte) explications.push("Mais c'\xE9tait une feinte..."); let mainDmgType = options.type || 'normal'; if (options.sortilege) options.ignoreObstacles = true; let echecCritique; - //Calcul des cibles touchées + //Calcul des cibles touch\xE9es //(et on ajuste le jet pour la triche) let ciblesTouchees = []; let count = cibles.length; cibles.forEach(function(target) { - // reset les champs de target qui vont être recalculés + // reset les champs de target qui vont \xEAtre recalcul\xE9s target.additionalDmg = []; target.effets = []; target.dmgCoef = 0; target.critCoef = 0; target.diviseDmg = 1; if (attributeAsBool(attaquant, 'menaceManoeuvre(' + target.token.id + ')')) { - explications.push(nomPerso(attaquant) + " attaque " + nomPerso(target) + " malgré la menace. " + nomPerso(target) + " a droit à une attaque au contact gratuite."); + explications.push(nomPerso(attaquant) + " attaque " + nomPerso(target) + " malgr\xE9 la menace. " + nomPerso(target) + " a droit \xE0 une attaque au contact gratuite."); removeTokenAttr(attaquant, 'menaceManoeuvre(' + target.token.id + ')', evt); setTokenAttr(attaquant, 'attaqueMalgreMenace(' + target.token.id + ')', 1, evt); } else if (attributeAsBool(attaquant, 'menaceManoeuvre(' + target.token.id + ',crit)')) { - explications.push(nomPerso(attaquant) + " attaque " + nomPerso(target) + " malgré la menace. " + nomPerso(target) + " a droit à une attaque au contact gratuite (DM x 2 !)."); + explications.push(nomPerso(attaquant) + " attaque " + nomPerso(target) + " malgr\xE9 la menace. " + nomPerso(target) + " a droit \xE0 une attaque au contact gratuite (DM x 2 !)."); removeTokenAttr(attaquant, 'menaceManoeuvre(' + target.token.id + ',crit)', evt); setTokenAttr(attaquant, 'attaqueMalgreMenace(' + target.token.id + ')', 2, evt); } @@ -16613,7 +16848,7 @@ var COFantasy = COFantasy || function() { target.percute = target.percute || options.percute; target.maxDmg = target.maxDmg || options.maxDmg; target.kiai = target.kiai || options.kiai; - //Les bonus d'attaque qui dépendent de la cible + //Les bonus d'attaque qui d\xE9pendent de la cible let bad = 0; if (!options.auto) bad = bonusAttaqueD(attaquant, target, weaponStats.portee, pageId, evt, target.messages, options); @@ -16622,7 +16857,7 @@ var COFantasy = COFantasy || function() { let amm = 'attaqueMalgreMenace(' + attaquant.token.id + ')'; if (options.contact && cibles.length == 1) { if (attributeAsBool(target, amm)) { - target.messages.push('Attaque automatique suite à une menace ignorée'); + target.messages.push('Attaque automatique suite \xE0 une menace ignor\xE9e'); options.auto = true; if (attributeAsInt(target, amm, 1) > 1) options.dmFoisDeux = true; target.additionalDmg.push({ @@ -16641,9 +16876,9 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '2' + options.d6 }); - target.messages.push(attackerTokName + " fait un traquenard à " + nomPerso(target)); + target.messages.push(attackerTokName + " fait un traquenard \xE0 " + nomPerso(target)); } else { - target.messages.push(attackerTokName + " n'est pas assez rapide pour faire un traquenard à " + nomPerso(target)); + target.messages.push(attackerTokName + " n'est pas assez rapide pour faire un traquenard \xE0 " + nomPerso(target)); } } let defautCuirasse = @@ -16676,7 +16911,7 @@ var COFantasy = COFantasy || function() { } let touche = true; let critique = false; - // Calcule si touché, et les messages de dégats et attaque + // Calcule si touch\xE9, et les messages de d\xE9gats et attaque if (options.auto) { addAttackSound("soundAttackSucces", weaponStats.divers, options); } else if (!options.interposer) { @@ -16684,7 +16919,7 @@ var COFantasy = COFantasy || function() { weaponStats.attaquePaire || weaponStats.attaqueImpaire; if (triche) { switch (triche) { - case "rate": + case 'rate': if (d20roll >= target.crit) { if (target.crit < 2) d20roll = 1; else d20roll = randomInteger(target.crit - 1); @@ -16696,7 +16931,7 @@ var COFantasy = COFantasy || function() { else d20roll = randomInteger(maxd20roll); } break; - case "touche": + case 'touche': if (d20roll == 1) d20roll = randomInteger(dice - 1) + 1; if ((d20roll + attSkill + attBonus) < defense) { let mind20roll = defense - attSkill - attBonus - 1; @@ -16740,7 +16975,7 @@ var COFantasy = COFantasy || function() { if (target.chatimentDuMale) { target.chatimentDuMaleRoll = target.chatimentDuMaleRoll || randomInteger(dice); target.chatimentDuMaleLowRoll = target.chatimentDuMaleRoll; - target.messages.push("Bénédiction de Maëdra => relance à " + target.chatimentDuMaleRoll + " du jet d'attaque contre un mâle"); + target.messages.push("B\xE9n\xE9diction de Ma\xEBdra => relance \xE0 " + target.chatimentDuMaleRoll + " du jet d'attaque contre un m\xE2le"); if (target.chatimentDuMaleRoll > targetd20roll) { targetd20roll = target.chatimentDuMaleRoll; target.chatimentDuMaleLowRoll = target.d20roll; @@ -16753,12 +16988,13 @@ var COFantasy = COFantasy || function() { if (getState(target, 'paralyse')) { paralyse = true; if (!options.attaqueAssuree) - target.messages.push("Cible paralysée => réussite critique automatique"); + target.messages.push("Cible paralys\xE9e => r\xE9ussite critique automatique"); } else if (getState(target, 'mort')) { paralyse = true; if (!options.attaqueAssuree) - target.messages.push("Cible inconsciente => réussite critique automatique"); + target.messages.push("Cible inconsciente => r\xE9ussite critique automatique"); } + target.margeDeToucher = attackRoll - defense; if (targetd20roll >= 15) { if (predicateAsBool(attaquant, 'champion')) options.champion = true; @@ -16776,13 +17012,13 @@ var COFantasy = COFantasy || function() { setTokenAttr(attaquant, 'etreinteImmole', idName(target), evt); setTokenAttr(target, 'etreinteImmolePar', idName(attaquant), evt); setState(target, 'immobilise', true, evt); - target.messages.push(nomPerso(attaquant) + " étreint " + nomPerso(target) + " et s'immole !"); + target.messages.push(nomPerso(attaquant) + " \xE9treint " + nomPerso(target) + " et s'immole !"); target.etreinteImmole = true; } if (options.etreinteScorpion) { setTokenAttr(attaquant, 'etreinteScorpionSur', idName(target), evt); setTokenAttr(target, 'etreinteScorpionPar', idName(attaquant), evt); - target.messages.push(nomPerso(attaquant) + " étreint " + nomPerso(target) + " !"); + target.messages.push(nomPerso(attaquant) + " \xE9treint " + nomPerso(target) + " !"); } if (targetd20roll >= 16 && options.contact) { let ecraser = predicateAsBool(attaquant, 'ecraser'); @@ -16803,7 +17039,7 @@ var COFantasy = COFantasy || function() { } let faireMouche; if (targetd20roll == 1 && options.chance === undefined) { - attackResult = " => échec critique"; + attackResult = " => \xE9chec critique"; attackResult += addAttackImg("imgAttackEchecCritique", weaponStats.divers, options); addAttackSound('soundAttackEchecCritique', weaponStats.divers, options); if (options.demiAuto) { @@ -16822,7 +17058,7 @@ var COFantasy = COFantasy || function() { } else if ((paralyse || options.ouvertureMortelle || targetd20roll == 20 || (targetd20roll >= target.crit && attackRoll >= defense) || (reglesOptionelles.divers.val.coups_critiques_etendus.val && attackRoll > defense + 9)) && !options.attaqueAssuree) { - attackResult = " => réussite critique"; + attackResult = " => r\xE9ussite critique"; attackResult += addAttackImg("imgAttackSuccesCritique", weaponStats.divers, options); addAttackSound('soundAttackSuccesCritique', weaponStats.divers, options); touche = true; @@ -16839,12 +17075,12 @@ var COFantasy = COFantasy || function() { } resetTenacite(attaquant, target, evt); } else if (options.champion || targetd20roll == 20 || paralyse) { - attackResult = " => succès"; + attackResult = " => succ\xE8s"; attackResult += addAttackImg("imgAttackSuccesChampion", weaponStats.divers, options); addAttackSound("soundAttackSuccesChampion", weaponStats.divers, options); resetTenacite(attaquant, target, evt); } else if (attackRoll < defense && targetd20roll < target.crit) { - attackResult = " => échec"; + attackResult = " => \xE9chec"; attackResult += addAttackImg("imgAttackEchec", weaponStats.divers, options); addAttackSound('soundAttackEchec', weaponStats.divers, options); evt.succes = false; @@ -16860,8 +17096,8 @@ var COFantasy = COFantasy || function() { } else touche = false; increaseTenacite(attaquant, target, evt); } else if (targetd20roll % 2 && attributeAsBool(target, 'clignotement')) { - target.messages.push(nomPerso(target) + " disparaît au moment où l'attaque aurait du l" + onGenre(target, 'e', 'a') + " toucher"); - attackResult = " => échec"; + target.messages.push(nomPerso(target) + " dispara\xEEt au moment o\xF9 l'attaque aurait du l" + onGenre(target, 'e', 'a') + " toucher"); + attackResult = " => \xE9chec"; attackResult += addAttackImg("imgAttackEchecClignotement", weaponStats.divers, options); addAttackSound('soundAttackEchecClignotement', weaponStats.divers, options); target.clignotement = true; @@ -16875,8 +17111,8 @@ var COFantasy = COFantasy || function() { target.dmgCoef--; evt.succes = false; } else touche = false; - } else { // Touché normal - attackResult = " => succès"; + } else { // Touch\xE9 normal + attackResult = " => succ\xE8s"; attackResult += addAttackImg("imgAttackSucces", weaponStats.divers, options); addAttackSound("soundAttackSucces", weaponStats.divers, options); resetTenacite(attaquant, target, evt); @@ -16889,7 +17125,7 @@ var COFantasy = COFantasy || function() { else if (attBonus < 0) bonusTexte += attBonus; if (ficheAttributeAsBool(attaquant, 'jets_caches', false)) { attRollValue = attackRoll; - sendChat('COF', "/w GM Jet caché d'attaque : " + buildinline(rollsAttack.inlinerolls[attRollNumber]) + bonusTexte); + sendChat('COF', "/w GM Jet cach\xE9 d'attaque : " + buildinline(rollsAttack.inlinerolls[attRollNumber]) + bonusTexte); } else { attRollValue = buildinline(rollsAttack.inlinerolls[attRollNumber]) + bonusTexte; } @@ -16945,7 +17181,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '2' + options.d6 }); - target.messages.push("Châtiment du mâle => +2d6 DM"); + target.messages.push("Ch\xE2timent du m\xE2le => +2d6 DM"); } } if (predicateAsBool(attaquant, 'batonDesRunesMortes') && attributeAsBool(attaquant, 'runeMelianil')) { @@ -16957,7 +17193,7 @@ var COFantasy = COFantasy || function() { target.messages.push("Melianil => +1d6 DM"); } if (attributeAsBool(target, 'momentDePerfection')) { - target.messages.push("Grâce à son instant de perfection, " + nomPerso(target) + " évite le coup !"); + target.messages.push("Gr\xE2ce \xE0 son instant de perfection, " + nomPerso(target) + " \xE9vite le coup !"); touche = false; evt.succes = false; } @@ -16970,7 +17206,7 @@ var COFantasy = COFantasy || function() { } } else { //Effet si on ne touche pas if (attributeAsBool(attaquant, 'momentDePerfection')) { - target.messages.push("Grâce à son instant de perfection, " + nomPerso(attaquant) + " touche !"); + target.messages.push("Gr\xE2ce \xE0 son instant de perfection, " + nomPerso(attaquant) + " touche !"); touche = true; evt.succes = true; } else { @@ -17002,6 +17238,11 @@ var COFantasy = COFantasy || function() { evt.succes = false; diminueMalediction(attaquant, evt); } + if (options.distance && predicateAsBool(attaquant, 'tirDeSemonce')) { + setTokenAttr(attaquant, 'attaqueADistanceRatee', 2, evt, { + maxVal: 1 + }); + } } } } @@ -17022,18 +17263,18 @@ var COFantasy = COFantasy || function() { let id = target.rollImageDecalee; if (id.val > 4) { target.touche = false; - target.messages.push(id.roll + ": l'attaque passe à travers l'image de " + nomPerso(target)); + target.messages.push(id.roll + ": l'attaque passe \xE0 travers l'image de " + nomPerso(target)); } else { - target.messages.push(id.roll + ": malgré l'image légèrement décalée de " + nomPerso(target) + " l'attaque touche"); + target.messages.push(id.roll + ": malgr\xE9 l'image l\xE9g\xE8rement d\xE9cal\xE9e de " + nomPerso(target) + " l'attaque touche"); } } else if (predicateAsBool(target, 'estUneIllusion')) { target.touche = false; - target.messages.push(nomPerso(target) + " disparait et se matérialise un peu plus loin"); + target.messages.push(nomPerso(target) + " disparait et se mat\xE9rialise un peu plus loin"); } } if (target.touche) { ciblesTouchees.push(target); - //Possibilités d'annuler l'attaque + //Possibilit\xE9s d'annuler l'attaque if (!options.pasDeDmg && isActive(target) && attributeAsBool(target, 'runeForgesort_protection') && attributeAsInt(target, 'limiteParCombat_runeForgesort_protection', 1) > 0) { @@ -17042,7 +17283,7 @@ var COFantasy = COFantasy || function() { options.preDmg[target.token.id].runeForgesort_protection = true; } if (!options.auto) { - //Seulement si elle n'est pas automatiquement réussie + //Seulement si elle n'est pas automatiquement r\xE9ussie if (isActive(target)) { if (!options.pasDeDmg && options.contact && !options.ignoreTouteRD) { @@ -17101,7 +17342,7 @@ var COFantasy = COFantasy || function() { } if (!options.aoe && capaciteDisponible(target, 'esquiveFatale', 'combat')) { if (target.ennemisAuContact === undefined) { - error(nomPerso(target) + " a la possibilité d'une esquive fatale, mais les ennemis au contact ne sont pas calculés", target); + error(nomPerso(target) + " a la possibilit\xE9 d'une esquive fatale, mais les ennemis au contact ne sont pas calcul\xE9s", target); } else { let ciblesEsquiveFatale = target.ennemisAuContact.filter(function(tok) { return (tok.id != attaquant.token.id); @@ -17157,7 +17398,7 @@ var COFantasy = COFantasy || function() { options.preDmg[target.token.id] = options.preDmg[target.token.id] || {}; options.preDmg[target.token.id].chairACanon = target.chairACanon; } - //Interception par un allié + //Interception par un alli\xE9 let alliesAvecInterception = []; if (target.alliesAuContact === undefined) { let allies = alliesParPerso[target.charId] || new Set(); @@ -17207,7 +17448,7 @@ var COFantasy = COFantasy || function() { alliesAvecInterception.push(perso); }); } - //On enlève les alliés qui sont cibles de l'attaque + //On enl\xE8ve les alli\xE9s qui sont cibles de l'attaque alliesAvecInterception = alliesAvecInterception.filter(function(p) { return cibles.every(function(c) { return c.token.id != p.token.id; @@ -17241,11 +17482,11 @@ var COFantasy = COFantasy || function() { } resolvePreDmgOptions(attaquant, ciblesTouchees, echecCritique, attackLabel, weaponStats, d20roll, display, options, evt, explications, pageId, cibles); } - }, true); //comme on est dans une boucle qui dépend de la cible, inTarget doit être vrai - }); //fin de détermination de toucher des cibles + }, true); //comme on est dans une boucle qui d\xE9pend de la cible, inTarget doit \xEAtre vrai + }); //fin de d\xE9termination de toucher des cibles }); // fin du jet d'attaque asynchrone } catch (e) { - error("Erreur pendant l'évaluation de " + toEvaluateAttack + " du test d'attaque", weaponStats); + error("Erreur pendant l'\xE9valuation de " + toEvaluateAttack + " du test d'attaque", weaponStats); log(e.name + ": " + e.message); } } @@ -17256,11 +17497,11 @@ var COFantasy = COFantasy || function() { function stringOfEtat(etat, perso) { if (etat == 'invisible') return etat; - else if (etat == 'penombre') return "dans la pénombre"; + else if (etat == 'penombre') return "dans la p\xE9nombre"; else if (etat == 'chef') return "est un leader"; let etext = etat; if (etat.endsWith('e')) { - etext = etat.substring(0, etat.length - 1) + 'é'; + etext = etat.substring(0, etat.length - 1) + '\xE9'; } if (perso === undefined) return etext; return etext + eForFemale(perso); @@ -17353,7 +17594,7 @@ var COFantasy = COFantasy || function() { function computeAttackDice(d, maxDmg, options) { if (isNaN(d) || d < 0) { - error("Dé d'attaque incorrect", d); + error("D\xE9 d'attaque incorrect", d); return 0; } let attDice = d; @@ -17412,7 +17653,7 @@ var COFantasy = COFantasy || function() { if (attCarBonus < 1) attCarBonus = ''; else attCarBonus = " +" + attCarBonus; } else { - target.messages.push(nomPerso(target) + " semble immunisé aux armes ordinaires"); + target.messages.push(nomPerso(target) + " semble immunis\xE9 aux armes ordinaires"); attNbDicesCible = 0; attCarBonus = ''; attDMBonus = ''; @@ -17423,7 +17664,7 @@ var COFantasy = COFantasy || function() { return addOrigin(attaquant.name, attNbDicesCible + symbde + attDiceCible + attCarBonus + attDMBonus); } - //retourne le mod de la caractéristique x, undefined si ce n'en est pas une + //retourne le mod de la caract\xE9ristique x, undefined si ce n'en est pas une function computeCarValue(perso, x) { switch (x) { case '@{FOR}': @@ -17497,7 +17738,7 @@ var COFantasy = COFantasy || function() { } sides = sides.split('|'); if (side < 0 || side >= sides.length) { - error("Le token de " + nomPerso(perso) + " n'a pas de face numéro " + side, sides); + error("Le token de " + nomPerso(perso) + " n'a pas de face num\xE9ro " + side, sides); return; } let oldSide = token.get('currentSide'); @@ -17509,40 +17750,40 @@ var COFantasy = COFantasy || function() { return oldSide; } - //Met un effet temporaire sur target. L'effet temporaire est spécifié dans ef + //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 être défini) - // - duree : true si c'est un effet à durée en tours - // - effetIndetermine : true si l'effet a une durée indéterminée (pas combat) - // - accumuleDuree : si la durée peut s'accumuler - // - typeDmg : le type de dégâts associé à l'effet, si pertinent + // - whisper : true si on doit chuchoter l'effet, undefined si on n'affiche pas (mais dans ce cas, target.messages doit \xEAtre d\xE9fini) + // - duree : true si c'est un effet \xE0 dur\xE9e en tours + // - effetIndetermine : true si l'effet a une dur\xE9e ind\xE9termin\xE9e (pas combat) + // - accumuleDuree : si la dur\xE9e peut s'accumuler + // - typeDmg : le type de d\xE9g\xE2ts associ\xE9 \xE0 l'effet, si pertinent // - message : la structure de messages (venant de messageEffetTemp ou autre) - // - dm : l'effet fait des dégâts + // - dm : l'effet fait des d\xE9g\xE2ts // - visible : l'effet est visible - // - prejudiciable : l'effet est préjudiciable (et donc cible de délivrance) - // - statusMarker : marker associé à l'effet + // - prejudiciable : l'effet est pr\xE9judiciable (et donc cible de d\xE9livrance) + // - statusMarker : marker associ\xE9 \xE0 l'effet // - pasDeMessageDActivation : pour ne pas afficher le message d'activation - // - image : lien d'une image à afficher - // - valeur : valeur associée à l'effet - // - valeurMax : champ max de l'attribut valeur associé à l'effet - // - saveParTour : caractéristiques du save par tour, si besoin. - // - saveActifParTour : caractéristiques du save actif par tour, si besoin. - // - attaquant : la personne à l'origine de l'effet - // - options : des options à mettre dans l'attribut d'options - // - tokenSide : change le côté du token à cette face + // - image : lien d'une image \xE0 afficher + // - valeur : valeur associ\xE9e \xE0 l'effet + // - valeurMax : champ max de l'attribut valeur associ\xE9 \xE0 l'effet + // - saveParTour : caract\xE9ristiques du save par tour, si besoin. + // - saveActifParTour : caract\xE9ristiques du save actif par tour, si besoin. + // - attaquant : la personne \xE0 l'origine de l'effet + // - options : des options \xE0 mettre dans l'attribut d'options + // - tokenSide : change le c\xF4t\xE9 du token \xE0 cette face function setEffetTemporaire(target, ef, duree, evt, options) { if (ef.effet == 'dedoublement') { if (attributeAsBool(target, 'dedouble') || attributeAsBool(target, 'dedoublement')) { if (ef.whisper !== undefined) { - whisperChar(target.charId, "a déjà été dédoublé pendant ce combat"); + whisperChar(target.charId, "a d\xE9j\xE0 \xE9t\xE9 d\xE9doubl\xE9 pendant ce combat"); } else { - target.messages.push(nomPerso(target) + " a déjà été dédoublé pendant ce combat"); + target.messages.push(nomPerso(target) + " a d\xE9j\xE0 \xE9t\xE9 d\xE9doubl\xE9 pendant ce combat"); } return; } let dedoubleMsg = - "Un double translucide de " + nomPerso(target) + " apparaît."; + "Un double translucide de " + nomPerso(target) + " appara\xEEt."; if (ef.attaquant) { dedoubleMsg += " Il est aux ordres de " + nomPerso(ef.attaquant); } @@ -17569,12 +17810,12 @@ var COFantasy = COFantasy || function() { if (estImmuniseAEffet(target, ef.effet)) { if (ef.whisper !== undefined) { if (ef.whisper === true) { - whisperChar(target.charId, "ne peut pas être affecté par l'effet de " + ef.effet); + whisperChar(target.charId, "ne peut pas \xEAtre affect\xE9 par l'effet de " + ef.effet); } else { - sendChar(target.charId, ef.whisper + "ne peut pas être affecté par l'effet de " + ef.effet); + sendChar(target.charId, ef.whisper + "ne peut pas \xEAtre affect\xE9 par l'effet de " + ef.effet); } } else { - target.messages.push(nomPerso(target) + " ne peut pas être affecté par l'effet de " + ef.effet); + target.messages.push(nomPerso(target) + " ne peut pas \xEAtre affect\xE9 par l'effet de " + ef.effet); } return; } @@ -17622,7 +17863,7 @@ var COFantasy = COFantasy || function() { accumuleAttr.set('current', duree + ',' + dureeAccumulee); } } - return; //Pas besoin de réappliquer, effet toujours en cours + return; //Pas besoin de r\xE9appliquer, effet toujours en cours } } let targetMsg = ''; @@ -17686,7 +17927,7 @@ var COFantasy = COFantasy || function() { setState(target, 'invisible', true, evt); break; case 'aspectDuDemon': - //On retire l'autre aspect du Nécromancien si il est présent + //On retire l'autre aspect du N\xE9cromancien si il est pr\xE9sent finDEffetDeNom(target, "aspectDeLaSuccube", evt); break; case 'aspectDeLaSuccube': @@ -17777,10 +18018,10 @@ var COFantasy = COFantasy || function() { } } - // Applique toutes les options de preDmg déjà sélectionnées - // Retourne vrai si l'option "continuer" a déjà été choisie + // Applique toutes les options de preDmg d\xE9j\xE0 s\xE9lectionn\xE9es + // Retourne vrai si l'option "continuer" a d\xE9j\xE0 \xE9t\xE9 choisie function resolvePreDmgOptions(attaquant, ciblesTouchees, echecCritique, attackLabel, weaponStats, d20roll, display, options, evt, explications, pageId, cibles) { - //Sauvegarde de l'état pour pouvoir relancer au niveau de cette fonction + //Sauvegarde de l'\xE9tat pour pouvoir relancer au niveau de cette fonction evt.action.currentOptions = options; evt.action.echecCritique = echecCritique; evt.action.attackLabel = attackLabel; @@ -17845,7 +18086,7 @@ var COFantasy = COFantasy || function() { if (preDmgToken.evitementGenerique && preDmgToken.evitementGenerique.length > 0) { let nbEvitementsGenerique = preDmgToken.evitementGenerique.length; let finaliseTargetPreDmg = function(msg, generalMsg) { - if (generalMsg !== '' && !continuer && !termineCible) { // rerolls uniquement si pas terminé + if (generalMsg !== '' && !continuer && !termineCible) { // rerolls uniquement si pas termin\xE9 explications.push(msg + generalMsg); } else { cible.messages.push(msg); @@ -17876,7 +18117,7 @@ var COFantasy = COFantasy || function() { }); if (regardPetrifiant && attributeAsBool(attaquant, 'detournerLeRegard') && getIntValeurOfEffet(attaquant, 'detournerLeRegard', 2) > 4) { - sendPerso(attaquant, "aperçoit " + nomPerso(regardPetrifiant) + " à travers ses paupières !"); + sendPerso(attaquant, "aper\xE7oit " + nomPerso(regardPetrifiant) + " \xE0 travers ses paupi\xE8res !"); let seuil = predicateAsInt(regardPetrifiant, 'regardPetrifiant', 0, 16) - 4; let commande = '!cof-effet petrifie --save CON ' + seuil + ' --lanceur ' + regardPetrifiant.token.id + ' --target ' + attaquant.token.id; @@ -17930,7 +18171,7 @@ var COFantasy = COFantasy || function() { let source = drains.find(function(d) { let sa = d.split(':'); if (sa.length != 2) { - log("Drain de sang mal formé : " + drains); + log("Drain de sang mal form\xE9 : " + drains); return false; } return attr.some(function(a) { @@ -17972,7 +18213,7 @@ var COFantasy = COFantasy || function() { }); let attackerTokName = nomPerso(attaquant); if (ciblesTouchees.length === 0 || options.test || options.feinte) { - //Évaluation finale pour le cas où l'attaque a raté + //\xC9valuation finale pour le cas o\xF9 l'attaque a rat\xE9 evalITE(attaquant, undefined, d20roll, options, 1, evt, explications, options, function() { if (options.attrArmeDeJet) { if (options.retourneEnMain) { @@ -17990,7 +18231,7 @@ var COFantasy = COFantasy || function() { options.attrArmeDeJet.attribute.set('current', options.attrArmeDeJet.restant + 1); explications.push(attackerTokName + " rattrape " + weaponStats.name); } else { - explications.push("Raté ! Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " à " + attackerTokName); + explications.push("Rat\xE9 ! Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " \xE0 " + attackerTokName); if (options.attrArmeDeJet.restant === 0) { degainerArmeLancee(attaquant, attackLabel, evt); } @@ -18002,7 +18243,7 @@ var COFantasy = COFantasy || function() { options.attrArmeDeJet.attribute.set('current', options.attrArmeDeJet.restant + 1); explications.push(weaponStats.name + " retourne dans la main de son lanceur"); } else { - explications.push("Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " à " + attackerTokName); + explications.push("Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " \xE0 " + attackerTokName); if (options.attrArmeDeJet.restant === 0) { degainerArmeLancee(attaquant, attackLabel, evt); } @@ -18015,12 +18256,12 @@ var COFantasy = COFantasy || function() { const attackingCharId = attaquant.charId; const attackingToken = attaquant.token; options.attaquant = attaquant; - //Les dégâts - //Dégâts insrits sur la ligne de l'arme + //Les d\xE9g\xE2ts + //D\xE9g\xE2ts insrits sur la ligne de l'arme let mainDmgType = options.type || 'normal'; let attNbDices = weaponStats.attNbDices; if (isNaN(attNbDices) || attNbDices < 0) { - error("Dés de l'attaque incorrect", attNbDices); + error("D\xE9s de l'attaque incorrect", attNbDices); return; } if (attNbDices) { @@ -18037,7 +18278,7 @@ var COFantasy = COFantasy || function() { } } } - // Les autres modifications aux dégâts qui ne dépendent pas de la cible + // Les autres modifications aux d\xE9g\xE2ts qui ne d\xE9pendent pas de la cible let attDMBonusCommun = ''; if (options.armeMagiquePlus) { attDMBonusCommun += " + " + options.armeMagiquePlus; @@ -18110,7 +18351,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '1' + options.d6, }); - explications.push("Même pas mal => +1" + options.d6 + " DM"); + explications.push("M\xEAme pas mal => +1" + options.d6 + " DM"); } if (!options.auto && options.attaqueEnPuissance) { attaquant.additionalDmg.push({ @@ -18140,20 +18381,20 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '1' + options.d6 }); - explications.push("Attaque à outrance => +1d6 DM"); + explications.push("Attaque \xE0 outrance => +1d6 DM"); } else { attaquant.additionalDmg.push({ type: mainDmgType, value: '2' + options.d6 }); - explications.push("Attaque à outrance => +2d6 DM"); + explications.push("Attaque \xE0 outrance => +2d6 DM"); } } if (attaquant.bonusCapitaine) attDMBonusCommun += " +" + attaquant.bonusCapitaine; - // Les autres sources de dégâts + // Les autres sources de d\xE9g\xE2ts if (options.distance) { - if (options.semonce) { + if (options.semonce && attributeAsInt(attaquant, 'attaqueADistanceRatee', 0) == 1) { attaquant.additionalDmg.push({ type: mainDmgType, value: '1' + options.d6 @@ -18168,7 +18409,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(attaquant, 'forceDeGeant')) { let bonusForceDeGeant = getIntValeurOfEffet(attaquant, 'forceDeGeant', 2); attDMBonusCommun += "+" + bonusForceDeGeant; - explications.push("Force de géant => +" + bonusForceDeGeant + " aux DM"); + explications.push("Force de g\xE9ant => +" + bonusForceDeGeant + " aux DM"); } if (options.frappeDuVide) { attaquant.additionalDmg.push({ @@ -18257,7 +18498,7 @@ var COFantasy = COFantasy || function() { explications.push(msgChampion); } ///////////////////////////////////////////////////////////////// - //Tout ce qui dépend de la cible + //Tout ce qui d\xE9pend de la cible let ciblesCount = ciblesTouchees.length; //Pour l'asynchronie let attaquesEnTraitrePossibles = {}; let finCibles = function() { @@ -18274,7 +18515,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, expl, 80); }); if (target.osBrises) { - addLineToFramedDisplay(display, nomPerso(target) + " a des os brisés "); + addLineToFramedDisplay(display, nomPerso(target) + " a des os bris\xE9s "); setTokenAttr(target, 'osBrises', true, evt); } }); @@ -18282,16 +18523,16 @@ var COFantasy = COFantasy || function() { for (let vid in attaquesEnTraitrePossibles) { let voleur = persoOfId(vid); if (voleur === undefined) continue; - if (capaciteDisponible(voleur, 'attaqueEnTraitre')) { - displayAttaqueOpportunite(vid, attaquesEnTraitrePossibles[vid], "en traître", 'Attaques en traitre', '--decrLimitePredicatParTour attaqueEnTraitre'); + if (capaciteDisponible(voleur, 'attaqueEnTraitre', 'tour')) { + displayAttaqueOpportunite(vid, attaquesEnTraitrePossibles[vid], "en tra\xEEtre", 'Attaques en traitre', '--decrLimitePredicatParTour attaqueEnTraitre'); } } } }; - //Le lien épique (+1d6 DM si les 2 attaquent la même cible + //Le lien \xE9pique (+1d6 DM si les 2 attaquent la m\xEAme cible let attaqueParLienEpique = new Set(); if (options.lienEpique) { - //On cherche les autres personnages avec le même lien épique + //On cherche les autres personnages avec le m\xEAme lien \xE9pique let allChars = findObjs({ type: 'character' }); @@ -18308,7 +18549,7 @@ var COFantasy = COFantasy || function() { }); } ciblesTouchees.forEach(function(target) { - //l'évaluation finale des conditions quand on sait si l'attaque a touché. + //l'\xE9valuation finale des conditions quand on sait si l'attaque a touch\xE9. evalITE(attaquant, target, d20roll, options, 1, evt, explications, options, function() { target.attaquant = attaquant; if (options.attrArmeDeJet) { @@ -18316,7 +18557,7 @@ var COFantasy = COFantasy || function() { options.attrArmeDeJet.attribute.set('current', options.attrArmeDeJet.restant + 1); explications.push(weaponStats.name + " retourne dans la main de son lanceur"); } else { - explications.push("Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " à " + attackerTokName); + explications.push("Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " \xE0 " + attackerTokName); if (options.attrArmeDeJet.restant === 0) { degainerArmeLancee(attaquant, attackLabel, evt); } @@ -18325,7 +18566,7 @@ var COFantasy = COFantasy || function() { } if (options.enveloppe !== undefined) { if (options.enveloppe.type == 'etreinte' && attributeAsBool(target, 'armureDEau')) { - target.messages.push("L'armure d'eau empêche " + nomPerso(target) + " d'être étreint"); + target.messages.push("L'armure d'eau emp\xEAche " + nomPerso(target) + " d'\xEAtre \xE9treint"); } else { let ligneEnveloppe = nomPerso(attaquant) + " peut "; let commandeEnvelopper = @@ -18333,7 +18574,7 @@ var COFantasy = COFantasy || function() { options.enveloppe.difficulte + ' ' + options.enveloppe.type + ' ' + options.enveloppe.expression; let verbeEnv = 'envelopper'; - if (options.enveloppe.type == 'etreinte') verbeEnv = 'étreindre'; + if (options.enveloppe.type == 'etreinte') verbeEnv = '\xE9treindre'; ligneEnveloppe += boutonSimple(commandeEnvelopper, verbeEnv); ligneEnveloppe += nomPerso(target); target.messages.push(ligneEnveloppe); @@ -18341,7 +18582,7 @@ var COFantasy = COFantasy || function() { } if (options.agripper) { if (attributeAsBool(target, 'armureDEau')) { - target.messages.push("L'armure d'eau empêche " + nomPerso(target) + " d'être aggripé"); + target.messages.push("L'armure d'eau emp\xEAche " + nomPerso(target) + " d'\xEAtre aggrip\xE9"); } else { let immobilise = estAussiGrandQue(attaquant, target); setTokenAttr(attaquant, 'agrippe', idName(target), evt); @@ -18349,7 +18590,7 @@ var COFantasy = COFantasy || function() { maxVal: immobilise }); if (immobilise) setState(target, 'immobilise', true, evt); - target.messages.push("est agrippé"); + target.messages.push("est agripp\xE9"); } } if (options.devorer) { @@ -18358,13 +18599,13 @@ var COFantasy = COFantasy || function() { let cmdAttaqueGratuite = '!cof-attack ' + attaquant.token.id + ' ' + target.token.id + ' ' + attackLabel; target.messages.push(boutonSimple(cmdAttaqueGratuite, 'Attaque gratuite')); } else { - target.messages.push(nomPerso(attaquant) + " a droit à une attaque gratuite contre " + nomPerso(target)); + target.messages.push(nomPerso(attaquant) + " a droit \xE0 une attaque gratuite contre " + nomPerso(target)); } let attackerForce = valAttribute(attaquant, 'FOR', 'force'); let targetForce = valAttribute(target, 'FOR', 'force'); if (targetForce <= attackerForce) { if (attributeAsBool(target, 'armureDEau')) { - target.messages.push("L'armure d'eau empêche " + nomPerso(target) + " d'être saisi"); + target.messages.push("L'armure d'eau emp\xEAche " + nomPerso(target) + " d'\xEAtre saisi"); } else { setState(target, 'renverse', true, evt); setState(target, 'immobilise', true, evt); @@ -18374,7 +18615,7 @@ var COFantasy = COFantasy || function() { } } if (options.attaqueViolente) { - target.messages.push(nomPerso(attaquant) + " fait une attaque violente. Jet de force opposé pour voir si " + nomPerso(target) + " se fait projeter"); + target.messages.push(nomPerso(attaquant) + " fait une attaque violente. Jet de force oppos\xE9 pour voir si " + nomPerso(target) + " se fait projeter"); target.effets.push({ attaqueViolente: true, save: true @@ -18383,25 +18624,25 @@ var COFantasy = COFantasy || function() { if (options.ecraser) { target.messages.push(nomPerso(attaquant) + " saisit " + nomPerso(target) + " entre ses bras puissants"); if (options.ecraser === true) { - error("Il faudrait préciser un label pour écraser", options.ecraser); + error("Il faudrait pr\xE9ciser un label pour \xE9craser", options.ecraser); } else { let cmdEcraser = '!cof-attack ' + attaquant.token.id + ' ' + target.token.id + ' ' + options.ecraser; - target.messages.push("et l'" + boutonSimple(cmdEcraser, 'écrase') + "."); + target.messages.push("et l'" + boutonSimple(cmdEcraser, '\xE9crase') + "."); } if (attributeAsBool(target, 'armureDEau')) { - target.messages.push("L'armure d'eau empêche " + nomPerso(target) + " d'être saisi"); + target.messages.push("L'armure d'eau emp\xEAche " + nomPerso(target) + " d'\xEAtre saisi"); } else { setTokenAttr(attaquant, 'ecrase', idName(target), evt); setTokenAttr(target, 'estEcrasePar', idName(attaquant), evt); } } if (options.saisirEtBroyer) { - target.messages.push(nomPerso(attaquant) + " soulève " + nomPerso(target) + " gesticulant" + eForFemale(target)); + target.messages.push(nomPerso(attaquant) + " soul\xE8ve " + nomPerso(target) + " gesticulant" + eForFemale(target)); if (attackLabel) { let cmdAttaqueGratuiteSaisi = '!cof-attack ' + attaquant.token.id + ' ' + target.token.id + ' ' + attackLabel + ' --bonusAttaque 5'; target.messages.push(boutonSimple(cmdAttaqueGratuiteSaisi, 'Attaque gratuite')); } else { - target.messages.push(nomPerso(attaquant) + " a droit à une attaque gratuite contre " + nomPerso(target)); + target.messages.push(nomPerso(attaquant) + " a droit \xE0 une attaque gratuite contre " + nomPerso(target)); } if (valAttribute(target, 'FOR', 'force') < valAttribute(attaquant, 'FOR', 'force')) { options.rolls = options.rolls || []; @@ -18418,7 +18659,7 @@ var COFantasy = COFantasy || function() { type: 'normal', value: Math.floor(distanceSaisiProjete.val) }); - target.messages.push(nomPerso(target) + " est projeté" + eForFemale(target) + " sur " + distanceSaisiProjete.roll + " mètres"); + target.messages.push(nomPerso(target) + " est projet\xE9" + eForFemale(target) + " sur " + distanceSaisiProjete.roll + " m\xE8tres"); } } if (options.projection && taillePersonnage(attaquant, 4) > taillePersonnage(target, 4)) { @@ -18452,10 +18693,10 @@ var COFantasy = COFantasy || function() { type: 'normal', value: dmgProjection }); - target.messages.push(nomPerso(target) + " est projeté sur " + distanceProjetee + " mètres"); + target.messages.push(nomPerso(target) + " est projet\xE9 sur " + distanceProjetee + " m\xE8tres"); } if (options.gober && taillePersonnage(attaquant, 4) > taillePersonnage(target, 4)) { - //On utilise la liste d'effets pour pouvoir gérer les jets asynchrones + //On utilise la liste d'effets pour pouvoir g\xE9rer les jets asynchrones target.effets.push({ gober: true, save: true @@ -18470,14 +18711,14 @@ var COFantasy = COFantasy || function() { type: 'normal', value: '2d6' }); - target.messages.push("Éventration => +2d6 DM"); + target.messages.push("\xC9ventration => +2d6 DM"); } } else { setTokenAttr(attaquant, 'limiteParTour_eventrationReussie', target.token.id, evt); } } let attDMBonus = attDMBonusCommun; - //Les modificateurs de dégâts qui dépendent de la cible + //Les modificateurs de d\xE9g\xE2ts qui d\xE9pendent de la cible if (target.tempDmg) { let forceTarg = modCarac(target, 'force'); if (forceTarg < 0) { @@ -18489,7 +18730,7 @@ var COFantasy = COFantasy || function() { if (options.pressionMortelle || target.pressionMortelle) { let pMortelle = tokenAttribute(target, 'pressionMortelle'); if (pMortelle.length === 0) { - sendPerso(attaquant, "essaie une pression mortelle, mais aucun point vital de " + nomPerso(target) + " n'a encore été affecté"); + sendPerso(attaquant, "essaie une pression mortelle, mais aucun point vital de " + nomPerso(target) + " n'a encore \xE9t\xE9 affect\xE9"); ciblesCount--; return; } @@ -18502,7 +18743,7 @@ var COFantasy = COFantasy || function() { let modDex = modCarac(attaquant, 'dexterite'); if (target.distance <= 5 * modDex) { attDMBonus += " + " + tirPrecis; - target.messages.push("Tir précis : +" + tirPrecis + " DM"); + target.messages.push("Tir pr\xE9cis : +" + tirPrecis + " DM"); } } } @@ -18510,7 +18751,7 @@ var COFantasy = COFantasy || function() { if (target.sournoise) sournoise += target.sournoise; if (target.critique && sournoise === 0 && predicateAsBool(attaquant, 'botteSecrete')) { sournoise = predicateAsInt(attaquant, 'attaqueSournoise', 1); - target.messages.push("Botte secrète !"); + target.messages.push("Botte secr\xE8te !"); } if (sournoise) { let limiteSournoisesParTour = predicateAsInt(attaquant, 'sournoisesParTour', 1); @@ -18520,7 +18761,7 @@ var COFantasy = COFantasy || function() { } else { setTokenAttr(attaquant, 'limiteParTour_sournoises', nbSournoises - 1, evt); if (predicateAsBool(target, 'immuniteAuxSournoises')) { - target.messages.push(nomPerso(target) + " est immunisé" + eForFemale(target) + " aux attaques sournoises"); + target.messages.push(nomPerso(target) + " est immunis\xE9" + eForFemale(target) + " aux attaques sournoises"); } else { if (options.ouvertureMortelle) { target.messages.push("Ouverture mortelle => + 2 x " + sournoise + options.d6 + " DM"); @@ -18530,13 +18771,13 @@ var COFantasy = COFantasy || function() { } let valueSournoise = sournoise + options.d6; if (predicateAsBool(target, 'armureProtection') && ficheAttributeAsBool(target, 'defarmureon', false)) { - target.messages.push("L'armure de protection de " + nomPerso(target) + " réduit l'attaque sournoise"); + target.messages.push("L'armure de protection de " + nomPerso(target) + " r\xE9duit l'attaque sournoise"); valueSournoise = "ceil(" + valueSournoise + "/2)"; } else if (predicateAsBool(target, 'bouclierProtection') && ficheAttributeAsInt(target, 'defbouclieron', 0)) { - target.messages.push("Le bouclier de protection de " + nomPerso(target) + " réduit l'attaque sournoise"); + target.messages.push("Le bouclier de protection de " + nomPerso(target) + " r\xE9duit l'attaque sournoise"); valueSournoise = "ceil(" + valueSournoise + "/2)"; } else if (predicateAsBool(target, 'anneauProtection')) { - target.messages.push("L'anneau de protection de " + nomPerso(target) + " réduit l'attaque sournoise"); + target.messages.push("L'anneau de protection de " + nomPerso(target) + " r\xE9duit l'attaque sournoise"); valueSournoise = "ceil(" + valueSournoise + "/2)"; } target.additionalDmg.push({ @@ -18564,7 +18805,7 @@ var COFantasy = COFantasy || function() { } if (predicateAsBool(attaquant, 'chasseurDeSorciere') && predicateAsBool(target, 'necromancien')) { attDMBonus += "+2"; - target.messages.push("Chasseur de sorcière => +2 en DM"); + target.messages.push("Chasseur de sorci\xE8re => +2 en DM"); } if (target.ennemiJure) { target.additionalDmg.push({ @@ -18619,7 +18860,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '1' + options.d6 }); - target.messages.push("Lien épique => + 1" + options.d6 + " DM"); + target.messages.push("Lien \xE9pique => + 1" + options.d6 + " DM"); } if (target.feinte) { let value = target.feinte + options.d6; @@ -18643,7 +18884,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '2d6' }); - target.messages.push("Cible énorme => +2d6 DM"); + target.messages.push("Cible \xE9norme => +2d6 DM"); } } if (options.contact && weaponStats.deuxMains && targetTaille > 4) { @@ -18653,18 +18894,18 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '1d6' }); - target.messages.push("Arme tenue à 2 mains => +1d6 DM"); + target.messages.push("Arme tenue \xE0 2 mains => +1d6 DM"); } else if (targetTaille > 5) { target.additionalDmg.push({ type: mainDmgType, value: '2d6' }); - target.messages.push("Arme tenue à 2 mains et cible énorme => +2d6 DM"); + target.messages.push("Arme tenue \xE0 2 mains et cible \xE9norme => +2d6 DM"); } } if (predicateAsBool(attaquant, 'grosMonstreGrosseArme')) { options.puissant = true; - target.messages.push("Gros Monstre, grosse arme => dégâts de base augmentés"); + target.messages.push("Gros Monstre, grosse arme => d\xE9g\xE2ts de base augment\xE9s"); } } if (attributeAsBool(target, 'hemorragie') && !options.sortilege && !options.armeNaturelle) { @@ -18674,7 +18915,7 @@ var COFantasy = COFantasy || function() { value: '1d6', drainDeSang: sourceDrain }); - target.messages.push("Hémorragie => +1d6 DM"); + target.messages.push("H\xE9morragie => +1d6 DM"); } if (!options.pasDeDmg) { let loupParmiLesLoups = predicateAsInt(attaquant, 'loupParmiLesLoups', 0); @@ -18695,7 +18936,7 @@ var COFantasy = COFantasy || function() { }); target.messages.push("Laissez-le moi ! => +1d6 DM"); } - //Bonus aux DMs dus au défi samouraï + //Bonus aux DMs dus au d\xE9fi samoura\xEF let defiSamouraiAttr = tokenAttribute(attaquant, 'defiSamourai'); if (defiSamouraiAttr.length > 0) { defiSamouraiAttr = defiSamouraiAttr[0]; @@ -18716,7 +18957,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: bonusDefi }); - target.messages.push(attackerTokName + " bénéficie d'un bonus de +" + bonusDefi + " aux DMs contre " + nomPerso(target)); + target.messages.push(attackerTokName + " b\xE9n\xE9ficie d'un bonus de +" + bonusDefi + " aux DMs contre " + nomPerso(target)); } } if (options.vicieux) { @@ -18749,7 +18990,7 @@ var COFantasy = COFantasy || function() { } //Additional damage let additionalDmg = attaquant.additionalDmg.concat(target.additionalDmg); - //On enlève les DM qui ne passent pas les conditions + //On enl\xE8ve les DM qui ne passent pas les conditions additionalDmg = additionalDmg.filter(function(dmSpec) { if (dmSpec.conditions === undefined) return true; return dmSpec.conditions.every(function(cond) { @@ -18800,7 +19041,7 @@ var COFantasy = COFantasy || function() { mainDmgRollExpr += " + " + dmSpec.value; return false; }); - // On ajoute le jet pour les dégâts de critiques supplémentaires + // On ajoute le jet pour les d\xE9g\xE2ts de critiques suppl\xE9mentaires if (target.critique && options.additionalCritDmg) { options.additionalCritDmg.forEach(function(dmSpec) { extraDmgRollExpr += " [[" + dmSpec.value + "]]"; @@ -18817,9 +19058,9 @@ var COFantasy = COFantasy || function() { value: mainDmgRollExpr }; // toEvaluateDmg inlines - // 0 : roll de dégâts principaux - // 1+ : les rolls de dégâts supplémentaires - // 1+nb dégâts supplémentaires + : rolls de dégâts critiques + // 0 : roll de d\xE9g\xE2ts principaux + // 1+ : les rolls de d\xE9g\xE2ts suppl\xE9mentaires + // 1+nb d\xE9g\xE2ts suppl\xE9mentaires + : rolls de d\xE9g\xE2ts critiques let toEvaluateDmg = "[[" + mainDmgRollExpr + "]]" + extraDmgRollExpr; sendChat('', toEvaluateDmg, function(resDmg) { let rollsDmg = target.rollsDmg || resDmg[0]; @@ -18841,8 +19082,8 @@ var COFantasy = COFantasy || function() { dmSpec.total = dmSpec.total || rRoll.results.total; let addDmType = dmSpec.type || 'normal'; dmSpec.display = dmSpec.display || buildinline(rRoll, addDmType, options.magique); - } else { //l'expression de DM additionel est mal formée - error("Expression de dégâts de critiques mal formée : " + options.additionalCritDmg[i].value, options.additionalCritDmg[i]); + } else { //l'expression de DM additionel est mal form\xE9e + error("Expression de d\xE9g\xE2ts de critiques mal form\xE9e : " + options.additionalCritDmg[i].value, options.additionalCritDmg[i]); } }); if (target.additionalCritDmg.length === 0) delete target.additionalCritDmg; @@ -18855,28 +19096,28 @@ var COFantasy = COFantasy || function() { dmSpec.total = dmSpec.total || rRoll.results.total; let addDmType = dmSpec.type; dmSpec.display = dmSpec.display || buildinline(rRoll, addDmType, options.magique); - } else { //l'expression de DM additionel est mal formée - error("Expression de dégâts supplémentaires mal formée : " + additionalDmg[i].value, additionalDmg[i]); + } else { //l'expression de DM additionel est mal form\xE9e + error("Expression de d\xE9g\xE2ts suppl\xE9mentaires mal form\xE9e : " + additionalDmg[i].value, additionalDmg[i]); } }); if (options.expertDuCombatDMSpec) { correctAdditionalDmg.push(options.expertDuCombatDMSpec); } additionalDmg = correctAdditionalDmg; - if (target.touche) { //Devrait être inutile ? + if (target.touche) { //Devrait \xEAtre inutile ? if (options.tirDeBarrage) - target.messages.push("Tir de barrage : undo si la cible décide de ne pas bouger"); + target.messages.push("Tir de barrage : undo si la cible d\xE9cide de ne pas bouger"); if (options.pointsVitaux) - target.messages.push(attackerTokName + " vise des points vitaux mais ne semble pas faire de dégâts"); + target.messages.push(attackerTokName + " vise des points vitaux mais ne semble pas faire de d\xE9g\xE2ts"); if (options.pressionMortelle || target.pressionMortelle) { removeTokenAttr(target, 'pressionMortelle', evt); - target.messages.push(attackerTokName + " libère la pression des points vitaux, l'effet est dévastateur !"); + target.messages.push(attackerTokName + " lib\xE8re la pression des points vitaux, l'effet est d\xE9vastateur !"); spawnFx(target.token.get('left'), target.token.get('top'), 'bomb-death', pageId); } - if (options.pasDeDmg === undefined) { //si l'attaque fait des DM, possibilité d'attaque en traître + if (options.pasDeDmg === undefined) { //si l'attaque fait des DM, possibilit\xE9 d'attaque en tra\xEEtre if (attaquant.alliesAvecAttaqueEnTraitre === undefined) { attaquant.alliesAvecAttaqueEnTraitre = []; - //On cherche tous les alliés ayant l'attaque en traitre + //On cherche tous les alli\xE9s ayant l'attaque en traitre const allies = alliesParPerso[attaquant.charId] || new Set(); allies.forEach(function(ci) { if (!charPredicateAsBool(ci, 'attaqueEnTraitre')) return; @@ -18909,7 +19150,7 @@ var COFantasy = COFantasy || function() { } }); } - // change l'état de la cible, si spécifié + // change l'\xE9tat de la cible, si sp\xE9cifi\xE9 if (target.enflamme) { let enflammePuissance = 1; if (options.puissant) enflammePuissance = 2; @@ -18939,7 +19180,7 @@ var COFantasy = COFantasy || function() { } // Draw effect, if any if (options.fx) { - //Pour les cones, on fait un seul effet, car c'est bien géré. + //Pour les cones, on fait un seul effet, car c'est bien g\xE9r\xE9. if (!options.aoe || options.aoe.type != 'cone') { let tokenOrigine = attackingToken; if (options.origineDeLAttaque) @@ -18960,9 +19201,9 @@ var COFantasy = COFantasy || function() { } target.rollsDmg = rollsDmg; // Compte le nombre de saves pour la synchronisation - // (On ne compte pas les psave, gérés dans dealDamage) + // (On ne compte pas les psave, g\xE9r\xE9s dans dealDamage) let saves = 0; - //ajoute les états sans save à la cible + //ajoute les \xE9tats sans save \xE0 la cible let etats = options.etats; if (target.etats) { if (etats) etats = etats.concat(target.etats); @@ -18989,9 +19230,9 @@ var COFantasy = COFantasy || function() { saves++; return; //on le fera plus tard } - if (ce.typeDmg && immuniseAuType(target, ce.typeDmg, attaquant)) { + if (ce.typeDmg && immuniseAuType(target, ce.typeDmg, attaquant, options)) { if (!target['msgImmunite_' + ce.typeDmg]) { - target.messages.push(nomPerso(target) + " ne semble pas affecté" + eForFemale(target) + " par " + stringOfType(ce.typeDmg)); + target.messages.push(nomPerso(target) + " ne semble pas affect\xE9" + eForFemale(target) + " par " + stringOfType(ce.typeDmg)); target['msgImmunite_' + ce.typeDmg] = true; } return; @@ -19000,7 +19241,7 @@ var COFantasy = COFantasy || function() { setState(target, ce.etat, true, evt); let msgEtat; if (ce.etat == 'mort') - msgEtat = 'tué' + eForFemale(target); + msgEtat = 'tu\xE9' + eForFemale(target); else msgEtat = stringOfEtat(ce.etat, target); target.messages.push(nomPerso(target) + " est " + msgEtat + " par l'attaque"); @@ -19017,14 +19258,14 @@ var COFantasy = COFantasy || function() { } else { if (ce.condition.type == "moins") { target.messages.push( - "Grâce à sa " + ce.condition.text + ", " + nomPerso(target) + + "Gr\xE2ce \xE0 sa " + ce.condition.text + ", " + nomPerso(target) + " n'est pas " + stringOfEtat(ce.etat, target)); } } }); } let savesEffets = 0; - // Ajoute les effets sans save à la cible + // Ajoute les effets sans save \xE0 la cible let effets = options.effets; if (target.effets) { if (effets) effets = effets.concat(target.effets); @@ -19058,7 +19299,7 @@ var COFantasy = COFantasy || function() { (estElfe(target) || (predicateAsInt(target, 'voieDeLArchange', 1) > 2 && attributeAsBool(target, 'formeDAnge'))) ) { - target.messages.push(nomPerso(target) + " est immunisé à la paralysie des goules"); + target.messages.push(nomPerso(target) + " est immunis\xE9 \xE0 la paralysie des goules"); return; } if (ef.effet == 'affaibliTemp' && estMortVivant(attaquant) && predicateAsInt(target, 'voieDeLArchange', 1) > 2 && attributeAsBool(target, 'formeDAnge')) { @@ -19070,9 +19311,9 @@ var COFantasy = COFantasy || function() { savesEffets++; return; //on le fera plus tard } - if (ef.typeDmg && immuniseAuType(target, ef.typeDmg, attaquant)) { + if (ef.typeDmg && immuniseAuType(target, ef.typeDmg, attaquant, options)) { if (!target['msgImmunite_' + ef.typeDmg]) { - target.messages.push(nomPerso(target) + " ne semble pas affecté par " + stringOfType(ef.typeDmg)); + target.messages.push(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(ef.typeDmg)); target['msgImmunite_' + ef.typeDmg] = true; } return; @@ -19107,17 +19348,17 @@ var COFantasy = COFantasy || function() { affaiblirCaracPerso(target, carac, aff.val, expliquer, evt); }); } - // Tout ce qui se passe après les saves (autres que saves de diminution des dmg + // Tout ce qui se passe apr\xE8s les saves (autres que saves de diminution des dmg let afterSaves = function() { if (saves > 0) return; //On n'a pas encore fait tous les saves if (target.utiliseRuneProtection) { target.messages.push(nomPerso(target) + " utilise sa Rune de Protection pour annuler les dommages"); addToAttributeAsInt(target, 'limiteParCombat_runeForgesort_protection', 1, -1, evt); - // Pas de dégâts, donc pas d'appel à dealDamage + // Pas de d\xE9g\xE2ts, donc pas d'appel \xE0 dealDamage finCibles(); } else if (options.pasDeDmg || (additionalDmg.length === 0 && mainDmgRoll.total === 0 && attNbDices === 0)) { - // Pas de dégâts, donc pas d'appel à dealDamage + // Pas de d\xE9g\xE2ts, donc pas d'appel \xE0 dealDamage finCibles(); } else { dealDamage(target, mainDmgRoll, additionalDmg, evt, target.critique, @@ -19128,12 +19369,12 @@ var COFantasy = COFantasy || function() { if (suce === 0) { setTokenAttr(attaquant, 'bufDEF', -3, evt); target.messages.push( - attackerTokName + " s'agrippe à " + nomPerso(target) + - " et commence à lui sucer le sang"); + attackerTokName + " s'agrippe \xE0 " + nomPerso(target) + + " et commence \xE0 lui sucer le sang"); } if (suce + dmg >= 6) { target.messages.push( - "Repus, " + attackerTokName + " se détache et s'envole"); + "Repus, " + attackerTokName + " se d\xE9tache et s'envole"); target.messages.push(nomPerso(target) + " se sent un peu faible..."); setState(target, 'affaibli', true, evt); let defbuf = attributeAsInt(attaquant, 'bufDEF', 0); @@ -19146,7 +19387,7 @@ var COFantasy = COFantasy || function() { setTokenAttr(attaquant, 'strigeSuce', suce + dmg, evt); if (suce > 0) target.messages.push( - attackerTokName + " continue à sucer le sang de " + nomPerso(target)); + attackerTokName + " continue \xE0 sucer le sang de " + nomPerso(target)); } } if (dmgDrain || (dmg > 0 && (options.vampirise || target.vampirise))) { @@ -19176,7 +19417,7 @@ var COFantasy = COFantasy || function() { if ((estMortVivant(attaquant) && predicateAsInt(target, 'voieDeLArchange', 1) > 2 && attributeAsBool(target, 'formeDAnge')) || (predicateAsBool(attaquant, 'vampire') && predicateAsBool(target, 'immuniteAbsorptionVampire')) ) { - target.messages.push(nomPerso(target) + "n'est pas affecté" + eForFemale(target) + " par l'absorption d'énergie"); + target.messages.push(nomPerso(target) + "n'est pas affect\xE9" + eForFemale(target) + " par l'absorption d'\xE9nergie"); } else { soigneToken(attaquant, absorptionEnergie, evt, function(soins) { target.messages.push( @@ -19200,7 +19441,7 @@ var COFantasy = COFantasy || function() { target.dmgMessage = "DM : "; if (ficheAttributeAsBool(attaquant, 'jets_caches', false)) { target.dmgMessage += dmg; - sendChat('COF', "/w GM Jet caché de dommages : " + dmgDisplay); + sendChat('COF', "/w GM Jet cach\xE9 de dommages : " + dmgDisplay); } else { target.dmgMessage += dmgDisplay; } @@ -19249,7 +19490,7 @@ var COFantasy = COFantasy || function() { target.messages, function(dmgDisplay, dmg, dmgDrain) { let dmgMsg = - "Décharge électrique sur " + attackerTokName + " : " + + "D\xE9charge \xE9lectrique sur " + attackerTokName + " : " + dmgDisplay; target.messages.push(dmgMsg); finCibles(); @@ -19296,7 +19537,7 @@ var COFantasy = COFantasy || function() { target.messages, function(dmgDisplay, dmg, dmgDrain) { let dmgMsg = - "" + attackerTokName + " est glacé : " + + "" + attackerTokName + " est glac\xE9 : " + dmgDisplay + " DM"; target.messages.push(dmgMsg); finCibles(); @@ -19360,17 +19601,17 @@ var COFantasy = COFantasy || function() { let expliquer = function(msg) { target.messages.push(msg); }; - //Ajoute les états avec save à la cible + //Ajoute les \xE9tats avec save \xE0 la cible let etatsAvecSave = function() { if (savesEffets > 0 || saveAffaiblissements > 0) return; //On n'a pas encore fini avec les effets et les affaiblissements if (etats && saves > 0) { etats.forEach(function(ce, index) { if (ce.save) { if (testCondition(ce.condition, attaquant, [target], d20roll, options)) { - let msgPour = " pour résister à un effet"; + let msgPour = " pour r\xE9sister \xE0 un effet"; let msgEtat; if (ce.etat == 'mort') - msgEtat = 'tué' + eForFemale(target); + msgEtat = 'tu\xE9' + eForFemale(target); else msgEtat = stringOfEtat(ce.etat, target); let msgRate = ", " + nomPerso(target) + " est " + msgEtat + " par l'attaque"; @@ -19405,7 +19646,7 @@ var COFantasy = COFantasy || function() { } else { if (ce.condition.type == "moins") { target.messages.push( - "Grâce à sa " + ce.condition.text + ", " + nomPerso(target) + + "Gr\xE2ce \xE0 sa " + ce.condition.text + ", " + nomPerso(target) + " n'est pas " + stringOfEtat(ce.etat, target)); } saves--; @@ -19415,7 +19656,7 @@ var COFantasy = COFantasy || function() { }); } else afterSaves(); }; - // Ajoute les effets avec save à la cible + // Ajoute les effets avec save \xE0 la cible let effetsAvecSave = function() { if (saveAffaiblissements > 0) return; //On n'a pas encore fini avec les affaiblissements if (effets && savesEffets > 0) { @@ -19427,13 +19668,13 @@ var COFantasy = COFantasy || function() { options, target.messages, evt, function(resultat, crit, rt1, rt2) { if (resultat == 2) { - target.messages.push(nomPerso(target) + " est entièrement avalé par " + attackerTokName); + target.messages.push(nomPerso(target) + " est enti\xE8rement aval\xE9 par " + attackerTokName); setTokenAttr(attaquant, 'aGobe', idName(target), evt); setTokenAttr(target, 'estGobePar', idName(attaquant), evt); moveTokenWithUndo(target.token, attaquant.token.get('left'), attaquant.token.get('top'), evt); } else { if (resultat === 0) diminueMalediction(attaquant, evt); - target.messages.push(nomPerso(target) + " n'est pas avalé."); + target.messages.push(nomPerso(target) + " n'est pas aval\xE9."); } saves--; savesEffets--; @@ -19446,14 +19687,14 @@ var COFantasy = COFantasy || function() { function(resultat, crit, rt1, rt2) { if (resultat == 2) { let distance = rollDePlus(6); - target.messages.push(nomPerso(target) + " est projeté" + eForFemale(target) + " à " + - distance.roll + " mètres et tombe au sol"); + target.messages.push(nomPerso(target) + " est projet\xE9" + eForFemale(target) + " \xE0 " + + distance.roll + " m\xE8tres et tombe au sol"); setState(target, 'renverse', true, evt); if (attackLabel) { let cmdAttaqueGratuite = '!cof-attack ' + attaquant.token.id + ' ' + target.token.id + ' ' + attackLabel; target.messages.push(boutonSimple(cmdAttaqueGratuite, 'Attaque gratuite')); } else { - target.messages.push(nomPerso(attaquant) + " a droit à une attaque gratuite contre " + nomPerso(target)); + target.messages.push(nomPerso(attaquant) + " a droit \xE0 une attaque gratuite contre " + nomPerso(target)); } } else { if (resultat === 0) diminueMalediction(attaquant, evt); @@ -19464,9 +19705,9 @@ var COFantasy = COFantasy || function() { etatsAvecSave(); }); } else { - if (ef.typeDmg && immuniseAuType(target, ef.typeDmg, attaquant)) { + if (ef.typeDmg && immuniseAuType(target, ef.typeDmg, attaquant, options)) { if (!target['msgImmunite_' + ef.typeDmg]) { - target.messages.push(nomPerso(target) + " ne semble pas affecté par " + stringOfType(ef.typeDmg)); + target.messages.push(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(ef.typeDmg)); target['msgImmunite_' + ef.typeDmg] = true; } saves--; @@ -19476,7 +19717,7 @@ var COFantasy = COFantasy || function() { } let msgPour = " pour "; if (ef.msgSave) msgPour += ef.msgSave; - else msgPour += "résister à un effet"; + else msgPour += "r\xE9sister \xE0 un effet"; let msgRate = ", " + nomPerso(target) + " "; if (ef.duree && ef.message) { msgRate += messageActivation(target, ef.message); @@ -19507,7 +19748,7 @@ var COFantasy = COFantasy || function() { if (reussite && duree && ef.save.demiDuree) { reussite = false; duree = Math.ceil(duree / 2); - if (stateCOF.options.affichage.val.duree_effets.val) expliquer("La durée est réduite à " + duree + " tours"); + if (stateCOF.options.affichage.val.duree_effets.val) expliquer("La dur\xE9e est r\xE9duite \xE0 " + duree + " tours"); } if (!reussite) { ef.attaquant = attaquant; @@ -19529,15 +19770,15 @@ var COFantasy = COFantasy || function() { options, target.messages, evt, function(resultat, crit, rt1, rt2) { if (resultat == 2) { - target.messages.push(nomPerso(target) + " est piétiné par " + attackerTokName + ", dommages doublés"); + target.messages.push(nomPerso(target) + " est pi\xE9tin\xE9 par " + attackerTokName + ", dommages doubl\xE9s"); setState(target, 'renverse', true, evt); target.dmgCoef = (target.dmgCoef || 0) + 1; target.touche++; if (target.percute) { - target.messages.push(nomPerso(target) + " est projeté à " + + target.messages.push(nomPerso(target) + " est projet\xE9 \xE0 " + rollDePlus(6, { bonus: 1 - }).roll + " mètres"); + }).roll + " m\xE8tres"); effets = effets || []; effets.push({ effet: 'etourdiTemp', @@ -19556,7 +19797,7 @@ var COFantasy = COFantasy || function() { } } else { if (resultat === 0) diminueMalediction(attaquant, evt); - target.messages.push(nomPerso(target) + " n'est pas piétiné."); + target.messages.push(nomPerso(target) + " n'est pas pi\xE9tin\xE9."); } effetsAvecSave(); }); @@ -19577,8 +19818,8 @@ var COFantasy = COFantasy || function() { carac = randomCaracForId(id, options); } let saveOpts = { - msgPour: " pour résister à un affaiblissement de " + carac, - msgRate: ", raté.", + msgPour: " pour r\xE9sister \xE0 un affaiblissement de " + carac, + msgRate: ", rat\xE9.", attaquant, rolls: options.rolls, sortilege: options.sortilege, @@ -19599,7 +19840,7 @@ var COFantasy = COFantasy || function() { }); } else effetPietinement(); }; - // Peut faire peur à la cible + // Peut faire peur \xE0 la cible if (options.peur) { peurOneToken(target, options.peur.seuil, options.peur.duree, { @@ -19628,12 +19869,12 @@ var COFantasy = COFantasy || function() { let msg; switch (d12roll) { case 1: - msg = "Échec total : "; + msg = "\xC9chec total : "; if (estMag) { - msg += "le lanceur de sort perd le contrôle de la magie qu'il canalise et subit 1d4 dommages en retour par rang du sort lancé. "; + msg += "le lanceur de sort perd le contr\xF4le de la magie qu'il canalise et subit 1d4 dommages en retour par rang du sort lanc\xE9. "; msg += boutonCritique("!cof-dmg ?{Rang du sort}d4 --ignoreRD"); } else { - msg += "l'attaquant se blesse lui-même et s'inflige la moitié des dégâts de son attaque. L'attaquant ne peut plus attaquer ce tour. "; + msg += "l'attaquant se blesse lui-m\xEAme et s'inflige la moiti\xE9 des d\xE9g\xE2ts de son attaque. L'attaquant ne peut plus attaquer ce tour. "; msg += boutonCritique("!cof-bouton-echec-total " + evt.id); } return msg; @@ -19647,38 +19888,38 @@ var COFantasy = COFantasy || function() { } else { difficulte = 12; } - msg = "Bousculé (FOR) : l'attaquant est déséquilibré par son attaque "; + msg = "Bouscul\xE9 (FOR) : l'attaquant est d\xE9s\xE9quilibr\xE9 par son attaque "; msg += boutonCritique("!cof-set-state renverse true --save FOR " + difficulte); return msg; case 3: if (avecArme) { - msg = "Maladresse (DEX) : l'attaquant laisse échapper son arme qui tombe hors de portée immédiate."; + msg = "Maladresse (DEX) : l'attaquant laisse \xE9chapper son arme qui tombe hors de port\xE9e imm\xE9diate."; msg += boutonCritique("!cof-degainer --save DEX 12"); return msg; } - msg = "Déséquilibré (DEX) : l'attaquant est Ralenti pendant 3 tours."; + msg = "D\xE9s\xE9quilibr\xE9 (DEX) : l'attaquant est Ralenti pendant 3 tours."; msg += boutonCritique("!cof-effet-temp ralentiTemp 3 --save DEX 12"); return msg; case 4: - msg = "Coup de mou (CON) : l'attaquant est affaibli pendant 3 tours, ou jusqu'à ce qu'il consacre un tour ou 1 PR pour se rétablir."; + msg = "Coup de mou (CON) : l'attaquant est affaibli pendant 3 tours, ou jusqu'\xE0 ce qu'il consacre un tour ou 1 PR pour se r\xE9tablir."; msg += boutonCritique("!cof-effet-temp affaibliTemp 3 --save CON 12"); return msg; case 5: if (estCac) { - msg = "Erreur tactique (INT) : le personnage provoque une attaque (gratuite) d’un adversaire à son contact."; + msg = "Erreur tactique (INT) : le personnage provoque une attaque (gratuite) d\x2019un adversaire \xE0 son contact."; msg += boutonCritique("!cof-jet INT 12"); } else if (estMag) { - msg = "Aveuglé (INT) : le personnage ne contrôle pas sa puissance et une partie de celle-ci émet un flash qui l'aveugle temporairement."; + msg = "Aveugl\xE9 (INT) : le personnage ne contr\xF4le pas sa puissance et une partie de celle-ci \xE9met un flash qui l'aveugle temporairement."; msg += boutonCritique("!cof-effet-temp aveugleTemp 3 --save INT 12 --saveParTour CON 12"); } else { - //TODO : Implémenter un bouton "mauvais calcul" réalisant une attaque automatique sur un des Obstacle - msg = "Mauvais calcul (INT) : le personnage a une chance de toucher une autre cible sur la trajectoire de son tir. Déterminer la cible au hasard et relancer une attaque sur cette nouvelle cible."; + //TODO : Impl\xE9menter un bouton "mauvais calcul" r\xE9alisant une attaque automatique sur un des Obstacle + msg = "Mauvais calcul (INT) : le personnage a une chance de toucher une autre cible sur la trajectoire de son tir. D\xE9terminer la cible au hasard et relancer une attaque sur cette nouvelle cible."; msg += boutonCritique("!cof-jet INT 12"); } return msg; case 6: if (estCac) { - msg = "Exposé (SAG) : l'adversaire dispose d'un bonus de +10 à la touche pendant un round."; + msg = "Expos\xE9 (SAG) : l'adversaire dispose d'un bonus de +10 \xE0 la touche pendant un round."; cibles.forEach(function(cible) { msg += boutonCritique("!cof-effet-temp expose 1 --valeur " + cible.token.id + " --save SAG 12"); }); @@ -19688,11 +19929,11 @@ var COFantasy = COFantasy || function() { } return msg; case 7: - msg = "Ridicule (CHA) : le personnage fait un faux mouvement à la fois douloureux et ridicule, il subit l’état étourdi pendant un round pour reprendre contenance. "; + msg = "Ridicule (CHA) : le personnage fait un faux mouvement \xE0 la fois douloureux et ridicule, il subit l\x2019\xE9tat \xE9tourdi pendant un round pour reprendre contenance. "; msg += boutonCritique("!cof-effet-temp etourdiTemp 1 --save CHA 12"); return msg; case 8: - msg = "Inconfort : Une pièce d’armure bouge et elle devient plus gênante que protectrice. Malus en DEF et en attaque pour le reste du combat => Cuir : -1, Maille : -2, Plaque -3. "; + msg = "Inconfort : Une pi\xE8ce d\x2019armure bouge et elle devient plus g\xEAnante que protectrice. Malus en DEF et en attaque pour le reste du combat => Cuir : -1, Maille : -2, Plaque -3. "; msg += boutonCritique("!cof-effet-combat inconfort --valeur ?{Malus ?|-1,1|-2,2|-3,3} --save CHA 12"); return msg; default: @@ -19706,13 +19947,13 @@ var COFantasy = COFantasy || function() { stateCOF.currentAttackDisplay = undefined; if (stateCOF.afterDisplay) { let ad = stateCOF.afterDisplay; - stateCOF.afterDisplay = undefined; //on efface avant au cas où le script crash + stateCOF.afterDisplay = undefined; //on efface avant au cas o\xF9 le script crash ad.forEach(function(d) { sendPerso(d.destinataire, d.msg, true); }); } } else { - sendPlayer(msg, "Pas de résultat d'attaque à montrer"); + sendPlayer(msg, "Pas de r\xE9sultat d'attaque \xE0 montrer"); } } @@ -19768,7 +20009,7 @@ var COFantasy = COFantasy || function() { } //Affichage final d'une attaque - // attaquant est optionnel, mais si il est présent, cibles doit être un tableau et options un objet + // attaquant est optionnel, mais si il est pr\xE9sent, cibles doit \xEAtre un tableau et options un objet function finaliseDisplay(display, explications, evt, attaquant, cibles, options, echecCritique) { echecCritique = echecCritique || false; explications.forEach(function(expl) { @@ -19796,7 +20037,7 @@ var COFantasy = COFantasy || function() { line += "
" + boutonSimple( "!cof-devier-les-coups " + evt.id + ' --target ' + target.token.id, - "dévier les coups"); + "d\xE9vier les coups"); nbBoutons++; } if (preDmgToken.paradeDeProjectiles) { @@ -19837,7 +20078,7 @@ var COFantasy = COFantasy || function() { } if (preDmgToken.resistanceALaMagieBarbare && preDmgToken.resistanceALaMagieBarbare !== 'reroll') { action = "!cof-resister-a-la-magie " + target.token.id + ' ' + evt.id; - line += "
" + boutonSimple(action, "tenter de résister à la magie"); + line += "
" + boutonSimple(action, "tenter de r\xE9sister \xE0 la magie"); nbBoutons++; } if (preDmgToken.cercleDeProtection && preDmgToken.cercleDeProtectionDe && @@ -19856,7 +20097,7 @@ var COFantasy = COFantasy || function() { } if (preDmgToken.chairACanon) { preDmgToken.chairACanon.forEach(function(tok) { - line += "
" + boutonSimple("!cof-chair-a-canon " + target.token.id + ' ' + tok.id + ' ' + evt.id, "utiliser " + tok.get('name') + " comme chair à canon"); + line += "
" + boutonSimple("!cof-chair-a-canon " + target.token.id + ' ' + tok.id + ' ' + evt.id, "utiliser " + tok.get('name') + " comme chair \xE0 canon"); nbBoutons++; }); } @@ -19920,9 +20161,9 @@ var COFantasy = COFantasy || function() { if (pc > 0 && !echecCritique) { addLineToFramedDisplay(display, boutonSimple("!cof-bouton-chance " + evt.id, "Chance") + " (reste " + pc + " PC)"); } - if (attributeAsBool(perso, 'runeForgesort_énergie') && - attributeAsInt(perso, 'limiteParCombat_runeForgesort_énergie', 1) > 0) { - addLineToFramedDisplay(display, boutonSimple("!cof-bouton-rune-energie " + evt.id, "Rune d'énergie")); + if (attributeAsBool(perso, 'runeForgesort_\xE9nergie') && + attributeAsInt(perso, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0) { + addLineToFramedDisplay(display, boutonSimple("!cof-bouton-rune-energie " + evt.id, "Rune d'\xE9nergie")); } if (capaciteDisponible(perso, 'petitVeinard', 'combat')) { addLineToFramedDisplay(display, boutonSimple("!cof-bouton-petit-veinard " + evt.id, "Petit veinard")); @@ -19953,13 +20194,13 @@ var COFantasy = COFantasy || function() { boutonSimple("!cof-bouton-pousser-kiai " + evt.id, "Kiai")); } if (capaciteDisponible(perso, 'petitVeinard', 'combat')) { - addLineToFramedDisplay(display, boutonSimple("!cof-bouton-petit-veinard " + evt.id, "Petit veinard") + " pour relancer un dé"); + addLineToFramedDisplay(display, boutonSimple("!cof-bouton-petit-veinard " + evt.id, "Petit veinard") + " pour relancer un d\xE9"); } } if (options && options.contact && cibles && attaquant && predicateAsBool(attaquant, 'enchainement')) { let cibleMorte = cibles.find(function(target) { - return target.token.get('bar1_value') == 0; + return target.pvPerdus && target.token.get('bar1_value') == 0; }); if (cibleMorte) { if (attaquant.ennemisAuContact === undefined) { @@ -19987,7 +20228,7 @@ var COFantasy = COFantasy || function() { attaquant.ennemisAuContact = tokensEnnemis; } if (attaquant.ennemisAuContact.length > 0) { - let msgEnchainement = nomPerso(attaquant) + " a droit à une attaque au contact gratuite contre "; + let msgEnchainement = nomPerso(attaquant) + " a droit \xE0 une attaque au contact gratuite contre "; let sep = ""; let armeEnMain = tokenAttribute(attaquant, 'armeEnMain'); let act; @@ -20077,7 +20318,8 @@ var COFantasy = COFantasy || function() { return c.token.id == tok.id; }); if (dejaTouche) return false; - if (distanceCombat(cible.token, tok, evt.action.pageId) > options.portee) return false; + let dist = distanceCombat(cible.token, tok, evt.action.pageId); + if (dist === 0 || dist > options.portee) return false; return true; }); let distance = distanceCombat(cible.token, attaquant.token, evt.action.pageId); @@ -20087,14 +20329,21 @@ var COFantasy = COFantasy || function() { activateRoundMarker(threadSync, cible.token); } let restants = options.ricochets.restants - 1; - let action = "!cof-attack " + attaquant.token.id + " @{target|token_id} " + evt.action.attackLabel + " --ricochets " + restants; + let baseAction = '!cof-attack ' + attaquant.token.id + ' '; + let optionsAction = ' ' + evt.action.attackLabel + ' --ricochets ' + restants; options.ricochets.cibles.forEach(function(c) { - action += ' ' + c.token.id; + optionsAction += ' ' + c.token.id; }); - action += ' ' + cible.token.id; + optionsAction += ' ' + cible.token.id; let msg = "Faire un "; - if (restants < 1) msg += "dernier "; - msg += boutonSimple(action, 'ricochet'); + if (restants === 0) msg += "dernier "; + if (tokens.length < 2) { + let action = baseAction + tokens[0].id + optionsAction; + msg += boutonSimple(action, 'ricochet vers ' + tokens[0].get('name')); + } else { + let action = baseAction + '@{target|token_id}' + optionsAction; + msg += boutonSimple(action, 'ricochet'); + } if (distance > options.portee) { if (restants < 1) msg += " (trop loin pour un retour en main)"; } else { @@ -20111,7 +20360,7 @@ var COFantasy = COFantasy || function() { } sendPerso(attaquant, "Plus de cible sur laquelle ricocher et trop loin pour un retour en main", true); } - } else { //on a raté, il faut remettre le rounMarker à sa place + } else { //on a rat\xE9, il faut remettre le rounMarker \xE0 sa place if (stateCOF.options.affichage.val.init_dynamique.val) { threadSync++; activateRoundMarker(threadSync, attaquant.token); @@ -20130,7 +20379,7 @@ var COFantasy = COFantasy || function() { } } - // RD spécifique au type + // RD sp\xE9cifique au type function typeRD(rd, dmgType) { if (dmgType === undefined || dmgType == 'normal') return 0; return (rd[dmgType] || 0); @@ -20141,7 +20390,7 @@ var COFantasy = COFantasy || function() { let proba1 = probaSucces(de, seuil, 1); return 1 - (1 - proba1) * (1 - proba1); } - if (seuil < 2) seuil = 2; // 1 est toujours un échec + if (seuil < 2) seuil = 2; // 1 est toujours un \xE9chec else if (seuil > 20) seuil = 20; return ((de - seuil) + 1) / de; } @@ -20231,31 +20480,32 @@ var COFantasy = COFantasy || function() { perso.dansAuraDeProfanation = res; return res; } - //s représente le save, avec une carac, une carac2 optionnelle et un seuil + //s repr\xE9sente le save, avec une carac, une carac2 optionnelle et un seuil //expliquer est une fonction qui prend en argument un string et le publie // options peut contenir les champs : - // - msgPour : message d'explication à afficher avant le jet - // - msgReussite : message à afficher en cas de réussite - // - msgRate : message à afficher si l'action rate - // - silencieuxSiPasAffecte: ne rien afficher pour les cibles immunisées - // - regard: l'attaque vient d'un regard, on peut détourner les yeux + // - msgPour : message d'explication \xE0 afficher avant le jet + // - msgReussite : message \xE0 afficher en cas de r\xE9ussite + // - msgRate : message \xE0 afficher si l'action rate + // - silencieuxSiPasAffecte: ne rien afficher pour les cibles immunis\xE9es + // - regard: l'attaque vient d'un regard, on peut d\xE9tourner les yeux // - attaquant : le {charId, token} de l'attaquant contre lequel le save se fait (si il y en a un) - // - type : le type de dégâts contre lequel on fait le save + // - type : le type de d\xE9g\xE2ts contre lequel on fait le save // - hideSaveTitle : cache le titre du save // - bonus : bonus au jet de save // s peut contenir: - // - carac : la caractéristique à utiliser pour le save - // - carac2 : caractéristique alternative - // - seuil : la difficulté du jet de sauvegarde - // - contact : la difficulté si la cible est au contact de options.attaquant + // - carac : la caract\xE9ristique \xE0 utiliser pour le save + // - carac2 : caract\xE9ristique alternative + // - seuil : la difficult\xE9 du jet de sauvegarde + // - contact : la difficult\xE9 si la cible est au contact de options.attaquant // - fauchage // - entrave (pour les action qui immobilisent, ralentissent ou paralysent) // - necromancie // - sortilege + // - augmenteAvecMargeDeToucher function save(s, target, saveId, expliquer, options, evt, afterSave) { - if (options.type && immuniseAuType(target, options.type, options.attaquant)) { + if (options.type && immuniseAuType(target, options.type, options.attaquant, options)) { if (!target['msgImmunite_' + options.type] && !options.silencieuxSiPasAffecte) { - expliquer(nomPerso(target) + " ne semble pas affecté par " + stringOfType(options.type)); + expliquer(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(options.type)); target['msgImmunite_' + options.type] = true; } afterSave(true, ''); @@ -20271,7 +20521,7 @@ var COFantasy = COFantasy || function() { } if (predicateAsBool(target, 'vegetatif')) { if (!options.silencieuxSiPasAffecte) - expliquer(nomPerso(target) + " est une créature végétative."); + expliquer(nomPerso(target) + " est une cr\xE9ature v\xE9g\xE9tative."); afterSave(true, ''); return; } @@ -20286,12 +20536,12 @@ var COFantasy = COFantasy || function() { } if (s.fauchage) { if (s.fauchage <= taillePersonnage(target, 4)) { - expliquer(nomPerso(target) + " est trop grand pour être fauché."); + expliquer(nomPerso(target) + " est trop grand pour \xEAtre fauch\xE9."); afterSave(true, ''); return; } if (predicateAsBool(target, 'inderacinable')) { - expliquer(nomPerso(target) + " est indéracinable."); + expliquer(nomPerso(target) + " est ind\xE9racinable."); afterSave(true, ''); return; } @@ -20300,7 +20550,7 @@ var COFantasy = COFantasy || function() { if (getState(target, 'mort') || getState(target, 'assomme') || getState(target, 'paralyse') || getState(target, 'endormi')) { if (!options.silencieuxSiPasAffecte) - expliquer(nomPerso(target) + " n'est pas en état d'éviter l'effet."); + expliquer(nomPerso(target) + " n'est pas en \xE9tat d'\xE9viter l'effet."); afterSave(false, ''); } } @@ -20314,23 +20564,23 @@ var COFantasy = COFantasy || function() { } if (s.entrave && predicateAsBool(target, 'actionLibre')) { bonus += 5; - expliquer("Action libre => +5 pour résister aux entraves"); + expliquer("Action libre => +5 pour r\xE9sister aux entraves"); } if (options.necromancie && attributeAsBool(target, 'sangDeLArbreCoeur')) { bonus += 5; - expliquer("Sang de l'Arbre-Coeur => +5 pour résister à la nécromancie"); + expliquer("Sang de l'Arbre-Coeur => +5 pour r\xE9sister \xE0 la n\xE9cromancie"); } if (options.type == 'poison') { if (predicateAsBool(target, 'liberateurDAnathazerin')) { bonus += 2; - expliquer("Libérateur d'Anathazerïn => +2 pour résister au poison"); + expliquer("Lib\xE9rateur d'Anathazer\xEFn => +2 pour r\xE9sister au poison"); } if (predicateAsBool(target, 'peauDEcorceAvancee') && attributeAsBool(target, 'peauDEcorce')) { let bonusPeau = getIntValeurOfEffet(target, 'peauDEcorce', 2); if (bonusPeau == 2 && predicateAsInt(target, 'voieDesForets', 0) > 3) bonusPeau = 4; bonus += bonusPeau; - expliquer("Peau d'écorce améliorée => +" + bonusPeau + " pour résister au poison"); + expliquer("Peau d'\xE9corce am\xE9lior\xE9e => +" + bonusPeau + " pour r\xE9sister au poison"); } } let bonusAttrs = []; @@ -20339,6 +20589,9 @@ var COFantasy = COFantasy || function() { if (s.contact && options.attaquant && distanceCombat(options.attaquant.token, target.token) === 0) { seuil = s.contact; } + if (s.augmenteAvecMargeDeToucher && target.margeDeToucher && target.margeDeToucher > 0) { + seuil += target.margeDeToucher; + } if (options.regard) { if (getState(target, 'aveugle')) { expliquer(nomPerso(target) + " ne voit rien."); @@ -20349,13 +20602,13 @@ var COFantasy = COFantasy || function() { switch (getIntValeurOfEffet(target, 'detournerLeRegard', 2)) { case 1: seuil -= 3; - expliquer("détourne un peu le regard => -3 à la difficulté"); + expliquer("d\xE9tourne un peu le regard => -3 \xE0 la difficult\xE9"); break; case 2: case 3: case 4: seuil -= 6; - expliquer("détourne le regard => -6 à la difficulté"); + expliquer("d\xE9tourne le regard => -6 \xE0 la difficult\xE9"); break; default: expliquer(nomPerso(target) + " ferme les yeux"); @@ -20365,7 +20618,7 @@ var COFantasy = COFantasy || function() { } } let carac = s.carac; - //Cas où le save peut se faire au choix parmis 2 caracs + //Cas o\xF9 le save peut se faire au choix parmis 2 caracs if (s.carac2) { carac = meilleureCarac(carac, s.carac2, target, seuil); } @@ -20415,11 +20668,11 @@ var COFantasy = COFantasy || function() { smsg += '">' + tr.texte + ''; } if (tr.reussite) { - smsg += " => réussite"; + smsg += " => r\xE9ussite"; if (options.msgReussite) smsg += options.msgReussite; smsg += tr.modifiers; } else { - smsg += " => échec"; + smsg += " => \xE9chec"; if (options.msgRate) smsg += options.msgRate; smsg += tr.rerolls + tr.modifiers; } @@ -20450,7 +20703,7 @@ var COFantasy = COFantasy || function() { return; } if ((sav.carac == 'CON' || sav.carac2 == 'CON') && estNonVivant(target)) { - expliquer("Les créatures non-vivantes sont immnunisées aux attaques qui demandent un test de constitution"); + expliquer("Les cr\xE9atures non-vivantes sont immnunis\xE9es aux attaques qui demandent un test de constitution"); afterSave({ succes: true, dmgDisplay: '0', @@ -20470,8 +20723,8 @@ var COFantasy = COFantasy || function() { return; } let saveOpts = { - msgPour: " pour réduire les dégâts", - msgReussite: ", dégâts divisés par 2", + msgPour: " pour r\xE9duire les d\xE9g\xE2ts", + msgReussite: ", d\xE9g\xE2ts divis\xE9s par 2", attaquant: ps.attaquant, rolls: ps.rolls, chanceRollId: ps.chanceRollId, @@ -20479,8 +20732,8 @@ var COFantasy = COFantasy || function() { energiePositive: ps.energiePositive }; if (totalSave) { - saveOpts.msgPour = " pour éviter les dégâts"; - saveOpts.msgReussite = ", dégâts évités"; + saveOpts.msgPour = " pour \xE9viter les d\xE9g\xE2ts"; + saveOpts.msgReussite = ", d\xE9g\xE2ts \xE9vit\xE9s"; } let saveId = 'parseSave_' + target.token.id; save(sav, target, saveId, expliquer, saveOpts, evt, @@ -20539,7 +20792,7 @@ var COFantasy = COFantasy || function() { if (r === '') return; let rds; let index = r.indexOf(':'); - if (index > 0) { //RD à un type particulier + if (index > 0) { //RD \xE0 un type particulier let type = r.substring(0, index); if (type == 'rdt' || type == 'sauf') return; if (type == 'magie') type = 'magique'; @@ -20550,7 +20803,7 @@ var COFantasy = COFantasy || function() { return; } index = r.indexOf('/'); - if (index > 0) { //RD sauf à des types + if (index > 0) { //RD sauf \xE0 des types rds = parseInt(r.substring(0, index)); if (isNaN(rds) || rds === 0) return; let sauf = r.substring(index + 1); @@ -20625,7 +20878,7 @@ var COFantasy = COFantasy || function() { case 'acide': return "l'acide"; case 'electrique': - return "l'électricité"; + return "l'\xE9lectricit\xE9"; case 'soniqe': return "le son"; case 'maladie': @@ -20642,7 +20895,7 @@ var COFantasy = COFantasy || function() { case 'FOR': return "la force"; case 'DEX': - return "la dextérité"; + return "la dext\xE9rit\xE9"; case 'CON': return "la constitution"; case 'INT': @@ -20668,7 +20921,7 @@ var COFantasy = COFantasy || function() { (predicateAsBool(target, 'protectionDMZone') || predicateAsBool(target, 'protectionDMZone_' + dmgType))) { divide(); - expliquer(nomPerso(target) + " est protégé contre les dégâts de zone"); + expliquer(nomPerso(target) + " est prot\xE9g\xE9 contre les d\xE9g\xE2ts de zone"); } if (predicateOrAttributeAsBool(target, 'resistanceA_' + dmgType) || predicateAsBool(target, 'diviseEffet_' + dmgType)) { divide(); @@ -20720,7 +20973,7 @@ var COFantasy = COFantasy || function() { divide(); } if (options.vampirise && predicateOrAttributeAsBool(target, 'controleSanguin')) { - expliquer(nomPerso(target) + " contrôle parfaitement son sang"); + expliquer(nomPerso(target) + " contr\xF4le parfaitement son sang"); divide(); } } @@ -20730,9 +20983,9 @@ var COFantasy = COFantasy || function() { return options.aoe && !options.sortilege && options.aoe.type == 'cone' && options.attaquant && estDraconique(options.attaquant); } - //On a déterminé les DM du type principal(possiblement après save des dmgExtra, maintenant on applique les résistances, puis on ajoute les DM d'autres types + //On a d\xE9termin\xE9 les DM du type principal(possiblement apr\xE8s save des dmgExtra, maintenant on applique les r\xE9sistances, puis on ajoute les DM d'autres types function dealDamageAfterDmgExtra(target, mainDmgType, dmgTotal, dmgDisplay, showTotal, dmgParType, dmgExtra, crit, options, evt, expliquer, displayRes) { - if (options.pointsVitaux && dmgTotal > 0) { //dégâts retardés pour une pression mortelle + if (options.pointsVitaux && dmgTotal > 0) { //d\xE9g\xE2ts retard\xE9s pour une pression mortelle let pMortelle = tokenAttribute(target, 'pressionMortelle'); let dmgPMort = dmgTotal; let numberPMort = 1; @@ -20755,9 +21008,9 @@ var COFantasy = COFantasy || function() { if (v > 1) rdElems = 2 * v; } } - if (dmgTotal > 0 && immuniseAuType(target, mainDmgType, options.attaquant)) { + if (dmgTotal > 0 && immuniseAuType(target, mainDmgType, options.attaquant, options)) { if (expliquer && !target['msgImmunite_' + mainDmgType]) { - expliquer(nomPerso(target) + " ne semble pas affecté par " + stringOfType(mainDmgType)); + expliquer(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(mainDmgType)); target['msgImmunite_' + mainDmgType] = true; } dmgTotal = 0; @@ -20866,13 +21119,13 @@ var COFantasy = COFantasy || function() { else dmSuivis[tv] = 0; }); }); - // Autres sources de dégâts + // Autres sources de d\xE9g\xE2ts // On compte d'abord les autres sources, pour la synchronisation let count = 0; for (let dt in dmgParType) { - if (immuniseAuType(target, dt, options.attaquant)) { + if (immuniseAuType(target, dt, options.attaquant, options)) { if (expliquer && !target['msgImmunite_' + dt]) { - expliquer(nomPerso(target) + " ne semble pas affecté par " + stringOfType(dt)); + expliquer(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(dt)); target['msgImmunite_' + dt] = true; } delete dmgParType[dt]; @@ -20884,7 +21137,7 @@ var COFantasy = COFantasy || function() { if (dmgType == mainDmgType) { count -= dmgParType[dmgType].length; if (count === 0) dealDamageAfterOthers(target, crit, options, evt, expliquer, displayRes, dmgTotal, dmgDisplay, showTotal, dmSuivis); - return; //type principal déjà géré + return; //type principal d\xE9j\xE0 g\xE9r\xE9 } showTotal = true; let dm = 0; @@ -21004,15 +21257,15 @@ var COFantasy = COFantasy || function() { } } - //Appelé quand on met à 0 PV + //Appel\xE9 quand on met \xE0 0 PV function mort(personnage, expliquer, evt) { - if (getState(personnage, 'mort')) return; //déjà mort + if (getState(personnage, 'mort')) return; //d\xE9j\xE0 mort if (predicateAsBool(personnage, 'energieDeLaMort')) { let duree = rollDePlus(6, { bonus: 5 }); - sendChat('', '/w GM ' + nomPerso(personnage) + ' réapparaîtra dans ' + duree.roll + ' tours.'); - let effet = 'messageRetarde(réapparition)'; + sendChat('', '/w GM ' + nomPerso(personnage) + ' r\xE9appara\xEEtra dans ' + duree.roll + ' tours.'); + let effet = 'messageRetarde(r\xE9apparition)'; setAttrDuree(personnage, effet, duree.val - 1, evt); setToken(personnage.token, 'layer', 'gmlayer', evt); if (personnage.attaquant) { @@ -21028,9 +21281,9 @@ var COFantasy = COFantasy || function() { let explications = []; dealDamage(personnage.attaquant, dmg, [], evt, false, {}, explications, function(dmgDisplay, dmgFinal, dmgDrain) { - setTokenAttr(personnage, effet + 'Valeur', nomPerso(personnage) + " réapparait avec " + dmgFinal + " PV en plus.", evt); + setTokenAttr(personnage, effet + 'Valeur', nomPerso(personnage) + " r\xE9apparait avec " + dmgFinal + " PV en plus.", evt); let attName = nomPerso(personnage); - let msg = "se transforme en brume noire qui traverse " + attName + " de part en part avant de disparaître dans une paroi en poussant un hululement inhumain. le froid de la mort inflige " + dmgDisplay + " DM à " + attName; + let msg = "se transforme en brume noire qui traverse " + attName + " de part en part avant de dispara\xEEtre dans une paroi en poussant un hululement inhumain. le froid de la mort inflige " + dmgDisplay + " DM \xE0 " + attName; if (expliquer) { expliquer(nomPerso(personnage) + ' ' + msg); } else { @@ -21085,11 +21338,11 @@ var COFantasy = COFantasy || function() { switch (charRace) { case 'insecte': case 'ankheg': - case 'araignée': + case 'araign\xE9e': case 'araignee': - case 'guêpe': + case 'gu\xEApe': case 'libellule': - case 'scarabée': + case 'scarab\xE9e': case 'scorpion': case 'strige': return true; @@ -21098,8 +21351,8 @@ var COFantasy = COFantasy || function() { } } - // retourne les nombre de PR restant, undefined si les PR ne sont pas définis - // current, max, et si défini, attribut + // retourne les nombre de PR restant, undefined si les PR ne sont pas d\xE9finis + // current, max, et si d\xE9fini, attribut function pointsDeRecuperation(perso) { if (!ficheAttributeAsBool(perso, 'option_pr', true)) return; let attrPR = charAttribute(perso.charId, 'pr', { @@ -21133,7 +21386,7 @@ var COFantasy = COFantasy || function() { }; } - // pr doit être défini, et pr.current > 0 + // pr doit \xEAtre d\xE9fini, et pr.current > 0 function enleverPointDeRecuperation(perso, pr, evt) { evt.attributes = evt.attributes || []; let attrPR; @@ -21181,18 +21434,18 @@ var COFantasy = COFantasy || function() { let pr = pointsDeRecuperation(target); if (!pr) return; if (pr.current > 0) { - expliquer("Les dégâts sont si importants que " + nomPerso(target) + " perd 1 PR"); + expliquer("Les d\xE9g\xE2ts sont si importants que " + nomPerso(target) + " perd 1 PR"); enleverPointDeRecuperation(target, pr, evt); } else if (getState(target, 'blesse')) { if (getState(target, 'mort')) { - expliquer("Avec la blessure grave, c'est vraiment la fin, " + nomPerso(target) + " ne se relèvera plus..."); + expliquer("Avec la blessure grave, c'est vraiment la fin, " + nomPerso(target) + " ne se rel\xE8vera plus..."); } else { - expliquer("Les dégâts sont trop importants, et " + nomPerso(target) + " s'effondre"); + expliquer("Les d\xE9g\xE2ts sont trop importants, et " + nomPerso(target) + " s'effondre"); mort(target, expliquer, evt); } } else { setState(target, 'blesse', true, evt); - expliquer("Les dégâts occasionnent une blessure grave !"); + expliquer("Les d\xE9g\xE2ts occasionnent une blessure grave !"); } } } @@ -21227,7 +21480,7 @@ var COFantasy = COFantasy || function() { attrs[0].set('current', newCur); } - function finDEffetDeNom(perso, effet, evt, options) { //Supprime l'effet si présent + function finDEffetDeNom(perso, effet, evt, options) { //Supprime l'effet si pr\xE9sent let attrs = tokenAttribute(perso, effet); if (attrs.length === 0) return; attrs = attrs[0]; @@ -21249,9 +21502,9 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(args[2]); if (evt === undefined) { - error("Impossible de trouver l'événement qui a causé la mort", args); + error("Impossible de trouver l'\xE9v\xE9nement qui a caus\xE9 la mort", args); evt = { - type: "Mettre à 0 PV" + type: "Mettre \xE0 0 PV" }; addEvent(evt); } @@ -21271,13 +21524,13 @@ var COFantasy = COFantasy || function() { } updateCurrentBar(target, 1, 0, evt); if (predicateAsBool(target, 'baroudHonneur')) { - let msgBarroud = nomPerso(target) + " devrait être mort"; + let msgBarroud = nomPerso(target) + " devrait \xEAtre mort"; msgBarroud += eForFemale(target) + ", mais "; - msgBarroud += onGenre(target, 'il', 'elle') + " continue à se battre !"; + msgBarroud += onGenre(target, 'il', 'elle') + " continue \xE0 se battre !"; expliquer(msgBarroud); setTokenAttr(target, 'baroudHonneurActif', true, evt); } else if (predicateAsBool(target, 'increvable') && attributeAsInt(target, 'limiteParCombat__increvable', predicateAsInt(target, 'increvable', 1)) > 0) { - let msgIncrevable = nomPerso(target) + " devrait être mort"; + let msgIncrevable = nomPerso(target) + " devrait \xEAtre mort"; msgIncrevable += eForFemale(target) + ", mais "; msgIncrevable += onGenre(target, 'il', 'elle') + " est increvable !"; expliquer(msgIncrevable); @@ -21286,25 +21539,25 @@ var COFantasy = COFantasy || function() { setTokenAttr(target, 'increvableActif', true, evt); } else if ((attributeAsBool(target, 'enrage') || predicateAsBool(target, 'durACuire')) && !attributeAsBool(target, 'aAgiAZeroPV')) { - let msgAgitZ = nomPerso(target) + " devrait être mort"; + let msgAgitZ = nomPerso(target) + " devrait \xEAtre mort"; msgAgitZ += eForFemale(target) + ", mais "; - msgAgitZ += onGenre(target, 'il', 'elle') + " continue à se battre !"; + msgAgitZ += onGenre(target, 'il', 'elle') + " continue \xE0 se battre !"; expliquer(msgAgitZ); if (!attributeAsBool(target, 'agitAZeroPV')) setAttrDuree(target, 'agitAZeroPV', 1, evt); } else if (predicateAsBool(target, 'nAbandonneJamais')) { if (attributeAsBool(target, 'mortMaisNAbandonnePas')) { - expliquer(nomPerso(target) + " est dans un état lamentable, mais continue à bouger. Il faudrait une action limitée pour le réduire en miettes."); + expliquer(nomPerso(target) + " est dans un \xE9tat lamentable, mais continue \xE0 bouger. Il faudrait une action limit\xE9e pour le r\xE9duire en miettes."); } else { - expliquer(nomPerso(target) + " est pratiquement détruit, mais continue à bouger !"); + expliquer(nomPerso(target) + " est pratiquement d\xE9truit, mais continue \xE0 bouger !"); setTokenAttr(target, 'mortMaisNAbandonnePas', true, evt); setState(target, 'ralenti', true, evt); } } else if (predicateAsBool(target, 'exsangue') && !attributeAsBool(target, 'etatExsangue')) { let msg; if (expliquer) { - expliquer(nomPerso(target) + " continue à agir malgré son état"); - } else msg = "continue à agir malgré son état"; + expliquer(nomPerso(target) + " continue \xE0 agir malgr\xE9 son \xE9tat"); + } else msg = "continue \xE0 agir malgr\xE9 son \xE9tat"; setTokenAttr(target, 'etatExsangue', true, evt, { msg }); @@ -21323,7 +21576,7 @@ var COFantasy = COFantasy || function() { let defierLaMort = charAttributeAsInt(target, 'defierLaMort', 10); let rollId = 'defierLaMort_' + target.token.id; let saveOpts = { - msgPour: " pour défier la mort", + msgPour: " pour d\xE9fier la mort", msgReussite: ", conserve 1 PV", rolls: options.rolls, chanceRollId: options.chanceRollId @@ -21345,7 +21598,7 @@ var COFantasy = COFantasy || function() { } postBarUpdateForDealDamage(target, dmgTotal, pvPerdus, bar1, tempDmg, dmgDisplay, showTotal, dmDrains, displayRes, evt, expliquer); }); - //On arrête là, car tout le reste est fait dans la continuation du save. + //On arr\xEAte l\xE0, car tout le reste est fait dans la continuation du save. return; } mettreAZeroPV(target, pvMax, evt, expliquer); @@ -21393,7 +21646,7 @@ var COFantasy = COFantasy || function() { if (rd > 0 && !options.aoe && options.attaquant && predicateAsBool(options.attaquant, 'ventreMou')) { let taille = taillePersonnage(target, 4); if (taille > 4) { - if (target.messages) target.messages.push("Ventre mou => L'attaque ignore la RD dûe à la taille"); + if (target.messages) target.messages.push("Ventre mou => L'attaque ignore la RD d\xFBe \xE0 la taille"); rd -= 3 * (taille - 4); if (taille > 6) rd--; if (rd < 0) rd = 0; @@ -21414,7 +21667,7 @@ var COFantasy = COFantasy || function() { else if (attributeAsBool(target, 'petrifie')) rd += 20; if (attributeAsBool(target, 'mutationSilhouetteMassive')) rd += 3; if (crit) { - let rdCrit = predicateAsInt(target, 'RD_critique', 0); //pour la compatibilité + let rdCrit = predicateAsInt(target, 'RD_critique', 0); //pour la compatibilit\xE9 if (ficheAttributeAsBool(target, 'casque_on', false)) rdCrit += ficheAttributeAsInt(target, 'casque_rd', 0); rd += rdCrit; @@ -21447,7 +21700,7 @@ var COFantasy = COFantasy || function() { } if (target.extraRDBouclier) { rd += target.extraRDBouclier; - expliquer(nomPerso(target) + " dévie le coup avec son bouclier"); + expliquer(nomPerso(target) + " d\xE9vie le coup avec son bouclier"); } if (target.ignoreTouteRD) rd = 0; else if (target.ignoreMoitieRD) rd = parseInt(rd / 2); @@ -21468,17 +21721,17 @@ var COFantasy = COFantasy || function() { if (dmgTotal <= rd) expliquer("La rune de protection absorbe tous les dommages"); else expliquer("La rune de protection encaisse " + target.utiliseRuneProtectionMax + " dommages"); } - //RD PeauDePierre à prendre en compte en dernier + //RD PeauDePierre \xE0 prendre en compte en dernier if (!target.defautCuirasse && !target.ignoreTouteRD && rd < dmgTotal && attributeAsBool(target, 'peauDePierreMag')) { let peauDePierreMagValeur = tokenAttribute(target, 'peauDePierreMagValeur'); if (peauDePierreMagValeur.length === 0) { - error("compteur de Peau de Pierre non trouvé", target); + error("compteur de Peau de Pierre non trouv\xE9", target); } else { peauDePierreMagValeur = peauDePierreMagValeur[0]; let rdPeauDePierreMax = parseInt(peauDePierreMagValeur.get('current')); let peauDePierreAbsorbe = parseInt(peauDePierreMagValeur.get('max')); if (isNaN(rdPeauDePierreMax) || isNaN(peauDePierreAbsorbe) || rdPeauDePierreMax < 1 || peauDePierreAbsorbe < 1) { - error("compteur de Peau de Pierre mal formé", peauDePierreMagValeur); + error("compteur de Peau de Pierre mal form\xE9", peauDePierreMagValeur); finDEffetDeNom(target, "peauDePierreMag", evt); } else { let rdPeauDePierreMag = rdPeauDePierreMax; @@ -21531,7 +21784,7 @@ var COFantasy = COFantasy || function() { }); } if (predicateAsBool(target, 'commandant')) { - //On cherche si il y a au moins 4 créatures sous ses ordres à moins de 10 m + //On cherche si il y a au moins 4 cr\xE9atures sous ses ordres \xE0 moins de 10 m let pageId = target.token.get('pageid'); let tokens = findObjs({ @@ -21588,7 +21841,7 @@ var COFantasy = COFantasy || function() { options.memePasMal += dmgTotal; dmgTotal = 0; } - expliquer("Même pas mal : ignore " + options.memePasMal + " PVs et peut enrager"); + expliquer("M\xEAme pas mal : ignore " + options.memePasMal + " PVs et peut enrager"); let mpm = attributeAsInt(target, 'memePasMalIgnore', 0); setTokenAttr(target, 'memePasMalIgnore', mpm + options.memePasMal, evt); setAttrDuree(target, 'memePasMalBonus', 3, evt); @@ -21606,7 +21859,7 @@ var COFantasy = COFantasy || function() { } let hasMana = (ficheAttributeAsInt(target, 'PM', 0) > 0); let tempDmg = 0; - const estMook = token.get("bar1_link") === ''; + const estMook = token.get('bar1_link') === ''; if (hasMana) { if (estMook) tempDmg = attributeAsInt(target, 'DMTEMP', 0); else tempDmg = ficheAttributeAsInt(target, 'DMTEMP', 0); @@ -21648,7 +21901,7 @@ var COFantasy = COFantasy || function() { showTotal = true; dmgTotal = 1; if (dmSuivis.drain && dmSuivis.drain > 0) dmSuivis.drain = 1; - expliquer("La nuée est constituée de très nombreuses cibles, l'attaque ne lui fait qu'1 DM"); + expliquer("La nu\xE9e est constitu\xE9e de tr\xE8s nombreuses cibles, l'attaque ne lui fait qu'1 DM"); } if (options.attaquant && options.arme && dmgTotal > 0 && predicateAsBool(options.attaquant, 'blessureSanglante') && @@ -21674,9 +21927,9 @@ var COFantasy = COFantasy || function() { }; let sujet = onGenre(target, 'il', 'elle'); let saveOpts = { - msgPour: " pour se libérer de la domination", - msgReussite: ", " + sujet + " se libère de la domination", - msgRate: ", " + sujet + " reste sous domination malgré les dégâts", + msgPour: " pour se lib\xE9rer de la domination", + msgReussite: ", " + sujet + " se lib\xE8re de la domination", + msgRate: ", " + sujet + " reste sous domination malgr\xE9 les d\xE9g\xE2ts", rolls: options.rolls, chanceRollId: options.chanceRollId }; @@ -21702,7 +21955,7 @@ var COFantasy = COFantasy || function() { } enlevePVStatueDeBois(target, pvPerdus, evt); } else { - //On enlève les points de vie + //On enl\xE8ve les points de vie let pvTemporaires = attributeAsInt(target, 'PVTemporaires', 0); if (bar1 > 0 && bar1 + pvTemporaires <= dmgTotal && predicateAsBool(target, 'instinctDeSurvieHumain')) { @@ -21717,7 +21970,7 @@ var COFantasy = COFantasy || function() { dmgDisplay += " / 2"; showTotal = true; } - expliquer("L'instinct de survie aide à réduire une attaque fatale"); + expliquer("L'instinct de survie aide \xE0 r\xE9duire une attaque fatale"); } pvPerdus = dmgTotal; if (pvTemporaires > 0) { @@ -21732,18 +21985,18 @@ var COFantasy = COFantasy || function() { } else { bar1 = bar1 - dmgTotal; } - if (crit) { //Vulnérabilité aux critiues + if (crit) { //Vuln\xE9rabilit\xE9 aux critiues let vulnerableCritique = predicateAsInt(target, 'vulnerableCritique', 0); if (vulnerableCritique > 0) { if (randomInteger(100) <= vulnerableCritique) { - expliquer("Le coup critique le fait voler en éclats"); + expliquer("Le coup critique le fait voler en \xE9clats"); if (bar1 > 0) { dmgTotal += bar1; pvPerdus += bar1; bar1 = 0; } } else { - expliquer("Le coup critique fait vibrer l'adversaire, mais il résiste."); + expliquer("Le coup critique fait vibrer l'adversaire, mais il r\xE9siste."); } } } @@ -21751,7 +22004,7 @@ var COFantasy = COFantasy || function() { predicateAsBool(target, 'peutEnrager') && !attributeAsBool(target, 'enrage')) { setTokenAttr(target, 'enrage', true, evt); - expliquer(nomPerso(target) + " devient enragé" + eForFemale(target) + "."); + expliquer(nomPerso(target) + " devient enrag\xE9" + eForFemale(target) + "."); finDEffetDeNom(target, 'apeureTemp', evt); finDEffetDeNom(target, 'peurEtourdi', evt); setState(target, 'apeure', false, evt); @@ -21796,7 +22049,7 @@ var COFantasy = COFantasy || function() { if (bar1 <= 0) { if (predicateAsBool(target, 'sergent') && !attributeAsBool(target, 'attributDeCombat_sergentUtilise')) { - expliquer(nomPerso(target) + " évite l'attaque in-extremis"); + expliquer(nomPerso(target) + " \xE9vite l'attaque in-extremis"); setTokenAttr(target, 'attributDeCombat_sergentUtilise', true, evt); pvPerdus = 0; } else if (target.attackRoll && @@ -21819,8 +22072,8 @@ var COFantasy = COFantasy || function() { } else { weaponStatsIncrevable = enMain; } - } else { //attaque à distance - weaponStatsIncrevable.name = "Attaque à distance"; + } else { //attaque \xE0 distance + weaponStatsIncrevable.name = "Attaque \xE0 distance"; weaponStatsIncrevable.attSkill = '@{ATKTIR}'; } let optionsIncrevable = {...options @@ -21839,7 +22092,7 @@ var COFantasy = COFantasy || function() { } } else if (getState(target, 'immobilise')) { dice = 12; - expliquer(nomPerso(target) + " immobilisé => D12 au lieu de D20 en Attaque"); + expliquer(nomPerso(target) + " immobilis\xE9 => D12 au lieu de D20 en Attaque"); } else if (attributeAsBool(target, 'mortMaisNAbandonnePas')) { dice = 12; expliquer(nomPerso(target) + " mort mais n'abandonne pas => D12 au lieu de D20 en Attaque"); @@ -21877,12 +22130,12 @@ var COFantasy = COFantasy || function() { let msgIncrevable = "Increvable : " + nomPerso(target) + " fait " + attRollValue; //TODO: afficher les explications de calcul des bonus d'attaque ? if (attackRollAttaquant < target.attackRoll) { - expliquer(msgIncrevable + " < " + target.attackRoll + " => échec "); + expliquer(msgIncrevable + " < " + target.attackRoll + " => \xE9chec "); prendreUnCoupMortel(target, dmgTotal, pvPerdus, bar1, pvmax, tempDmg, dmgDisplay, showTotal, dmSuivis.drain, displayRes, options, evt, expliquer); return; } - //L'attaque est évitée - expliquer(msgIncrevable + " > " + target.attackRoll + " => l'attaque est évitée ! "); + //L'attaque est \xE9vit\xE9e + expliquer(msgIncrevable + " > " + target.attackRoll + " => l'attaque est \xE9vit\xE9e ! "); postBarUpdateForDealDamage(target, dmgTotal, 0, bar1, tempDmg, dmgDisplay, showTotal, dmSuivis.drain, displayRes, evt, expliquer); }); @@ -21904,7 +22157,8 @@ var COFantasy = COFantasy || function() { } function postBarUpdateForDealDamage(target, dmgTotal, pvPerdus, bar1, tempDmg, dmgDisplay, showTotal, dmDrains, displayRes, evt, expliquer) { - if (bar1 > 0 && tempDmg >= bar1) { //assommé + target.pvPerdus = target.pvPerdus || pvPerdus; + if (bar1 > 0 && tempDmg >= bar1) { //assomm\xE9 setState(target, 'assomme', true, evt); } let attrsLienDeSang = tokenAttribute(target, "lienDeSangVers"); @@ -21918,7 +22172,7 @@ var COFantasy = COFantasy || function() { }; let personnageLie = persoOfId(attrsLienDeSang[0].get("current")); if (personnageLie) { - expliquer("Le lien de sang inflige " + lienDuSangDmg + " dégâts à " + personnageLie.token.get("name")); + expliquer("Le lien de sang inflige " + lienDuSangDmg + " d\xE9g\xE2ts \xE0 " + personnageLie.token.get("name")); dealDamage(personnageLie, r, [], evt, false); } } @@ -22118,8 +22372,8 @@ var COFantasy = COFantasy || function() { return toEvaluate.replace(/@{/g, "@{" + name + "|"); } - // Retourne le diamètre d'un disque inscrit dans un carré de surface - // équivalente à celle du token + // Retourne le diam\xE8tre d'un disque inscrit dans un carr\xE9 de surface + // \xE9quivalente \xE0 celle du token function tokenSizeAsCircle(token) { const surface = token.get('width') * token.get('height'); return Math.sqrt(surface); @@ -22150,6 +22404,8 @@ var COFantasy = COFantasy || function() { let mObstacle = 0; let dp = distancePixToken(tok1, tok2); let liste_obstacles = []; + let pt1 = pointOfToken(tok1); + let pt2 = pointOfToken(tok2); allToks.forEach(function(obj) { if (obj.id == tok1.id || obj.id == tok2.id) return; let objCharId = obj.get('represents'); @@ -22177,14 +22433,12 @@ var COFantasy = COFantasy || function() { if (obj_dist > dp) return; obj_dist = distancePixToken(tok2, obj); if (obj_dist > dp) return; - let pt1 = pointOfToken(tok1); - let pt2 = pointOfToken(tok2); let distToTrajectory = distancePixTokenSegment(obj, pt1, pt2); - // On modélise le token comme un disque + // On mod\xE9lise le token comme un disque let rayonObj = tokenSizeAsCircle(obj) / 2; if (distToTrajectory > rayonObj) return; liste_obstacles.push(obj.get("name")); - // On calcule un malus proportionnel à l'arc à traverser + // On calcule un malus proportionnel \xE0 l'arc \xE0 traverser // Pour l'instant, malus = 1 si distance = PIX_PER_UNIT let longueurArc = 2 * Math.sqrt(rayonObj * rayonObj - distToTrajectory * distToTrajectory); let mToken = longueurArc / PIX_PER_UNIT; @@ -22199,7 +22453,7 @@ var COFantasy = COFantasy || function() { else mObstacle = Math.round(mObstacle); let res = mPortee + mObstacle; if (mObstacle > 0) { - log("Obstacle" + ((liste_obstacles.length > 1) ? "s" : "") + " trouvé : " + liste_obstacles.join(', ')); + log("Obstacle" + ((liste_obstacles.length > 1) ? "s" : "") + " trouv\xE9 : " + liste_obstacles.join(', ')); let msgObstacles = 'Obstacle' + ((liste_obstacles.length > 1) ? 's' : '') + ' sur le trajet => -' + mObstacle + ' en Attaque
'; if (liste_obstacles.length > 0) msgObstacles += '' + liste_obstacles.join(', ') + ''; @@ -22229,12 +22483,12 @@ var COFantasy = COFantasy || function() { }); } - // Fait foo sur tous les tokens représentant charId, ayant l'effet donné, et correspondant au nom d'attribut. Pour le cas où le token doit être lié au personnage, on ne prend qu'un seul token, sauf si les options indiquent autrement (soit option.tousLesTokens, soit une fonction options.filterAffected) + // Fait foo sur tous les tokens repr\xE9sentant charId, ayant l'effet donn\xE9, et correspondant au nom d'attribut. Pour le cas o\xF9 le token doit \xEAtre li\xE9 au personnage, on ne prend qu'un seul token, sauf si les options indiquent autrement (soit option.tousLesTokens, soit une fonction options.filterAffected) // Ne fonctionne correctement que pour les attributs sans _ function iterTokensOfAttribute(charId, pageId, attrName, attrNameComplet, foo, options) { options = options || {}; - let total = 1; //Nombre de tokens affectés, pour gérer l'asynchronie si besoin - if (attrNameComplet == attrName) { //token lié au character + let total = 1; //Nombre de tokens affect\xE9s, pour g\xE9rer l'asynchronie si besoin + if (attrNameComplet == attrName) { //token li\xE9 au character let tokens; if (pageId) { tokens = @@ -22279,7 +22533,7 @@ var COFantasy = COFantasy || function() { if (options.filterAffected(tok)) foo(tok, total); }); } else foo(tokens[0], 1); - } else { //token non lié au character + } else { //token non li\xE9 au character let tokenName = attrNameComplet.substring(attrNameComplet.indexOf('_') + 1); let tNames; if (pageId) { @@ -22326,7 +22580,7 @@ var COFantasy = COFantasy || function() { let character = getObj('character', charId); let charName = "d'id " + charId; if (character) charName = character.get('name'); - error("Attention, il y a plusieurs tokens nommés " + tokenName, total); + error("Attention, il y a plusieurs tokens nomm\xE9s " + tokenName, total); log(" tokens instances du personnage " + charName, total); } } @@ -22357,7 +22611,7 @@ var COFantasy = COFantasy || function() { token.set('showplayers_aura2', true); } else { let status = ''; - // Cas des tokens personnalisés + // Cas des tokens personnalis\xE9s if (statusForInitEnemy && statusForInitAlly) { // ennemi => rouge status = statusForInitEnemy; @@ -22370,7 +22624,7 @@ var COFantasy = COFantasy || function() { } } - //Ne rajoute pas evt à l'historique + //Ne rajoute pas evt \xE0 l'historique function setActiveToken(combat, tokenId, evt) { let pageId; if (combat) pageId = combat.pageId; @@ -22415,10 +22669,10 @@ var COFantasy = COFantasy || function() { if (tokenId) { let perso = persoOfId(tokenId, tokenId); if (perso) { - //On remet à 0 la liste des cibles attaquées par le personnage + //On remet \xE0 0 la liste des cibles attaqu\xE9es par le personnage removeDernieresCiblesAttaquees(perso, evt); let token = perso.token; - // personnage lié au Token + // personnage li\xE9 au Token affectToken(token, 'statusmarkers', token.get('statusmarkers'), evt); affectToken(token, 'aura2_radius', token.get('aura2_radius'), evt); affectToken(token, 'aura2_color', token.get('aura2_color'), evt); @@ -22435,7 +22689,7 @@ var COFantasy = COFantasy || function() { onGenre(perso, 'Il', 'Elle') + " ne fait rien ce tour"); removeTokenFlagAura(token); } else { - //Trouver la créature la plus proche + //Trouver la cr\xE9ature la plus proche let closestToken; pageId = token.get('pageid'); let toksOnPage = findObjs({ @@ -22480,7 +22734,7 @@ var COFantasy = COFantasy || function() { } } } - //On enlève aussi les états qui ne durent qu'un tour + //On enl\xE8ve aussi les \xE9tats qui ne durent qu'un tour let defenseTotale = tokenAttribute(perso, 'defenseTotale'); if (defenseTotale.length > 0) { defenseTotale = defenseTotale[0]; @@ -22508,7 +22762,7 @@ var COFantasy = COFantasy || function() { const charId = a.get('characterid'); let m = parseInt(a.get('max')); if (isNaN(m) || m < 0) { - error("Erreur dans les quantités d'arme de jet", a); + error("Erreur dans les quantit\xE9s d'arme de jet", a); a.remove(); return; } @@ -22521,7 +22775,7 @@ var COFantasy = COFantasy || function() { }); if (!msgAffiche.has(charId)) { msgAffiche.add(charId); - whisperChar(charId, "récupère ses armes de jet"); + whisperChar(charId, "r\xE9cup\xE8re ses armes de jet"); } a.set('current', m); } @@ -22538,7 +22792,7 @@ var COFantasy = COFantasy || function() { const charId = a.get('characterid'); let m = parseInt(a.get('max')); if (isNaN(m) || m < 0) { - error("Erreur dans les quantités de munitions", a); + error("Erreur dans les quantit\xE9s de munitions", a); a.remove(); return; } @@ -22551,23 +22805,96 @@ var COFantasy = COFantasy || function() { }); if (!msgAffiche.has(charId)) { msgAffiche.add(charId); - whisperChar(charId, "récupère ses munitions"); + whisperChar(charId, "r\xE9cup\xE8re ses munitions"); } a.set('current', m); } }); } + function dmExplosion(id, effet) { + let action = "!cof-dmg " + effet.dm + " --disque " + id + " " + effet.portee; + if (effet.typeBombe == 'piege') action += " --psave DEX 15"; + log(action); + sendChat('', action); + } + + function getTokenTemp(tt) { + let token = getObj('graphic', tt.tid); + if (!token) { + if (!tt.name) return; + token = findObjs({ + _type: 'graphic', + name: tt.name + }); + if (token.length === 0) return; + token = token[0]; + } + return token; + } + + //Peut faire des effets asynchrones + function deleteTokenTemp(tt, evt) { + let token = getTokenTemp(tt); + if (!token) return; + if (!tt.pasDExplosion) { + let gmNotes = token.get('gmnotes'); + try { + if (gmNotes.startsWith('{')) { + let effet = JSON.parse(gmNotes); + //{typeBombe, portee, message, dm, tempsDePose, duree, intrusion} + if (effet && effet.typeBombe) { + let pageId = token.get('pageid'); + if (effet.message) sendChat('', effet.message); + let left = token.get('left'); + let top = token.get('top'); + spawnFx(left, top, 'explode-fire', pageId); + playSound('Explosion'); + if (effet.dm) { + let charCible = trouveOuCreeCible(); + if (charCible) { + charCible.get('_defaulttoken', function(normalToken) { + if (normalToken === '') { + dmExplosion(tt.id, effet); + return; + } + normalToken = JSON.parse(normalToken); + normalToken._pageid = pageId; + normalToken.left = left; + normalToken.top = top; + normalToken.imgsrc = normalizeTokenImg(normalToken.imgsrc); + let tokenCible = createObj('graphic', normalToken); + if (tokenCible) dmExplosion(tokenCible.id, effet); + else { + log("Impossible de cr\xE9er le token cible"); + log(normalToken); + dmExplosion(tt.id, effet); + } + }); + } else dmExplosion(tt.id, effet); + } + } + } + } catch (parseError) {} + } + let ett = {...tt + }; + ett.deletedToken = getTokenFields(token); + evt.deletedTokensTemps = evt.deletedTokensTemps || []; + evt.deletedTokensTemps.push(ett); + token.remove(); + } + function sortirDuCombat() { stateCOF.prescience = undefined; stateCOF.nextPrescience = undefined; let combat = stateCOF.combat; if (!combat) { log("Pas en combat"); - sendChat("GM", "/w GM Le combat est déjà terminé"); + sendChat('GM', "/w GM Le combat est d\xE9j\xE0 termin\xE9"); return; } - sendChat("GM", "Le combat est terminé"); + sendChat('GM', "Le combat est termin\xE9"); let evt = { type: 'fin_combat', initiativepage: Campaign().get('initiativepage'), @@ -22586,7 +22913,6 @@ var COFantasy = COFantasy || function() { }); // Fin des effets qui durent pour le combat attrs = removeAllAttributes('attributDeCombat', evt, attrs); - attrs = removeAllAttributes('protegerUnAllie', evt, attrs); attrs = removeAllAttributes('protegePar', evt, attrs); attrs = removeAllAttributes('interposer', evt, attrs); attrs = removeAllAttributes('defenseTotale', evt, attrs); @@ -22613,23 +22939,22 @@ var COFantasy = COFantasy || function() { attrs = removeAllAttributes('increvableHumainUtilise', evt, attrs); attrs = removeAllAttributes('resistanceRaillerie', evt, attrs); attrs = removeAllAttributes('defierLaMort', evt, attrs); - attrs = removeAllAttributes('traquenardImpossible', evt, attrs); attrs = removeAllAttributes('niveauDesObjetsAnimes', evt, attrs); attrs = removeAllAttributes('meneurDHommesCible', evt, attrs); attrs = removeAllAttributes('energieImpie', evt, attrs); // Autres attributs - // On récupère les munitions récupérables - resetAttr(attrs, 'munition', evt, "récupère ses munitions"); //obsolète depuis mars 2023. + // On r\xE9cup\xE8re les munitions r\xE9cup\xE9rables + resetAttr(attrs, 'munition', evt, "r\xE9cup\xE8re ses munitions"); //obsol\xE8te depuis mars 2023. recupererMunitions(attrs, evt); recupererArmesDeJet(attrs, evt); - //Utilisation automatique de second souffle, si pas utilisé + //Utilisation automatique de second souffle, si pas utilis\xE9 let tokens = findObjs({ // Les tokens sur la page du combat _type: 'graphic', _subtype: 'token', _pageid: combat.pageId, }); - let persosDuCombat = []; //peuplé la première fois qu'on regarde les tokens - let persoParCharId = {}; //Pour ne garder qu'un jeu de prédicat par charId + let persosDuCombat = []; //peupl\xE9 la premi\xE8re fois qu'on regarde les tokens + let persoParCharId = {}; //Pour ne garder qu'un jeu de pr\xE9dicat par charId tokens.forEach(function(token) { let charId = token.get('represents'); if (charId === '' || charId === undefined) return; @@ -22656,11 +22981,11 @@ var COFantasy = COFantasy || function() { let jetSoins = rollDePlus(10, { bonus: bonus }); - let msg = ' reprend son souffle et récupère '; + let msg = ' reprend son souffle et r\xE9cup\xE8re '; let soins = jetSoins.val; if (pv + soins > pvDebut) { soins = pvDebut - pv; - msg += soins + " PV (le jet était " + jetSoins.roll + ")"; + msg += soins + " PV (le jet \xE9tait " + jetSoins.roll + ")"; } else { msg += jetSoins.roll + " PVs"; } @@ -22671,11 +22996,11 @@ var COFantasy = COFantasy || function() { }); attrs = removeAllAttributes('secondSouffleUtilise', evt, attrs); attrs = removeAllAttributes('PVsDebutCombat', evt, attrs); - // On diminue l'ébriété des personnages sous vapeurs éthyliques + // On diminue l'\xE9bri\xE9t\xE9 des personnages sous vapeurs \xE9thyliques allAttributesNamed(attrs, 'vapeursEthyliques').forEach(function(attr) { let veCharId = attr.get('characterid'); if (veCharId === undefined || veCharId === '') { - error("Attribut sans personnage associé", attr); + error("Attribut sans personnage associ\xE9", attr); return; } iterTokensOfAttribute(veCharId, combat.pageId, @@ -22686,7 +23011,7 @@ var COFantasy = COFantasy || function() { token: tok }; removeTokenAttr(perso, 'niveauEbriete', evt, { - msg: "désaoûle" + msg: "d\xE9sao\xFBle" }); }); }); @@ -22698,7 +23023,7 @@ var COFantasy = COFantasy || function() { degainerArme(perso, '', evt); } }); - // On remet en main l'arme par défaut si elle est précisée + // On remet en main l'arme par d\xE9faut si elle est pr\xE9cis\xE9e persosDuCombat.forEach(function(perso) { if (!isActive(perso)) return; let persoTest = persoParCharId[perso.charId]; @@ -22716,8 +23041,9 @@ var COFantasy = COFantasy || function() { let attaques = listAllAttacks(perso); for (let label in attaques) { let att = attaques[label]; - if (att.armespec) { - let predicats = predicateOfRaw(att.armespec); + let rawArme = fieldAsString(att, 'armepredicats', ''); + if (rawArme) { + let predicats = predicateOfRaw(rawArme); if (predicats.charge) { let chargeMax = predicats.charge; if (chargeMax === true) chargeMax = 1; @@ -22736,7 +23062,7 @@ var COFantasy = COFantasy || function() { ilds.forEach(function(ild) { let douleur = parseInt(ild.get('current')); if (isNaN(douleur)) { - error("La douleur ignorée n'est pas un nombre", douleur); + error("La douleur ignor\xE9e n'est pas un nombre", douleur); return; } let charId = ild.get('characterid'); @@ -22760,7 +23086,7 @@ var COFantasy = COFantasy || function() { pvAttr = pvAttr[0]; let pv = parseInt(pvAttr.get('current')); if (isNaN(pv)) { - error("PV mal formés ", pvAttr); + error("PV mal form\xE9s ", pvAttr); return; } evt.attributes.push({ @@ -22771,13 +23097,13 @@ var COFantasy = COFantasy || function() { if (newPv < 0) newPv = 0; pvAttr.set('current', newPv); if (pv > 0 && newPv === 0) { - sendChar(charId, "s'écroule. Il semble sans vie. La douleur qu'il avait ignorée l'a finalement rattrapé...", true); + sendChar(charId, "s'\xE9croule. Il semble sans vie. La douleur qu'il avait ignor\xE9e l'a finalement rattrap\xE9...", true); } else { let tempDmg = ficheAttributeAsInt(charId, 'DMTEMP', 0); if (pv > tempDmg && newPv <= tempDmg) { - sendChar(charId, "s'écroule, assommé. La douleur qu'il avait ignorée l'a finalement rattrapé...", true); + sendChar(charId, "s'\xE9croule, assomm\xE9. La douleur qu'il avait ignor\xE9e l'a finalement rattrap\xE9...", true); } else { - sendChar(charId, "subit le contrecoup de la douleur qu'il avait ignorée", true); + sendChar(charId, "subit le contrecoup de la douleur qu'il avait ignor\xE9e", true); } } } else { // ignorer la douleur d'un token @@ -22789,11 +23115,11 @@ var COFantasy = COFantasy || function() { name: tokName }); if (tokensIld.length === 0) { - error("Pas de token nommé " + tokName + " qui aurait ignoré la douleur", ild); + error("Pas de token nomm\xE9 " + tokName + " qui aurait ignor\xE9 la douleur", ild); return; } if (tokensIld.length > 1) { - sendChar(charId, "a plusieurs tokens nommés " + tokName + ". Un seul d'entre eux subira l'effet d'ignorer la douleur", true); + sendChar(charId, "a plusieurs tokens nomm\xE9s " + tokName + ". Un seul d'entre eux subira l'effet d'ignorer la douleur", true); } let tokPv = parseInt(tokensIld[0].get('bar1_value')); let tokNewPv = tokPv - douleur; @@ -22820,7 +23146,7 @@ var COFantasy = COFantasy || function() { } //Attributs qu'on veut enlever en dernier let removedLaterAttrs = []; - // fin des effets temporaires (durée en tours, ou durée = combat) + // fin des effets temporaires (dur\xE9e en tours, ou dur\xE9e = combat) attrs.forEach(function(obj) { let attrName = obj.get('name'); let charId = obj.get('characterid'); @@ -22874,7 +23200,7 @@ var COFantasy = COFantasy || function() { }, { tousLesTokens: true }); - //Pas besoin de détruire l'attribut, ce sera fait plus loin + //Pas besoin de d\xE9truire l'attribut, ce sera fait plus loin } evt.deletedAttributes.push(obj); obj.remove(); @@ -22907,14 +23233,8 @@ var COFantasy = COFantasy || function() { if (stateCOF.tokensTemps) { evt.deletedTokensTemps = []; stateCOF.tokensTemps.forEach(function(tt) { - let token = getObj('graphic', tt.tid); - if (token) { - let ett = {...tt - }; - ett.deletedToken = getTokenFields(token); - evt.deletedTokensTemps.push(ett); - token.remove(); - } + if (tt.intrusion) tt.pasDExplosion = true; + deleteTokenTemp(tt, evt); }); delete stateCOF.tokensTemps; } @@ -22937,7 +23257,7 @@ var COFantasy = COFantasy || function() { } //Asynchrone - // ne rajoute pas evt à l'historique + // ne rajoute pas evt \xE0 l'historique function soinsEcuyers(ecuyers, manquePV, playerId, evt) { ecuyers.forEach(function(ec) { const ecuyer = ec.perso; @@ -22947,11 +23267,11 @@ var COFantasy = COFantasy || function() { name: ecuyerDe }); if (charChevalier.length === 0) { - error("Pas de chevalier " + ecuyerDe + " pour l'écuyer " + nomPerso(ecuyer), ec); + error("Pas de chevalier " + ecuyerDe + " pour l'\xE9cuyer " + nomPerso(ecuyer), ec); return; } if (charChevalier.length > 1) { - error("Plusieurs personnages nommés " + ecuyerDe + ". Attention aux ambiguités."); + error("Plusieurs personnages nomm\xE9s " + ecuyerDe + ". Attention aux ambiguit\xE9s."); } charChevalier = charChevalier[0].id; let maxASoigner = modCarac(charChevalier, 'charisme') + 1; @@ -22975,13 +23295,13 @@ var COFantasy = COFantasy || function() { } alliesASoigner.push(cible); } - }); //fin de détermination des cibles + }); //fin de d\xE9termination des cibles if (chevalier === undefined && monture === undefined && - (maxASoigner < 1 || alliesASoigner.length === 0)) { //Personne à soigner + (maxASoigner < 1 || alliesASoigner.length === 0)) { //Personne \xE0 soigner return; } - //TODO: utiliser l'id d'un player qui contrôle le chevalier - let display = startFramedDisplay(playerId, "Services d'écuyer", ecuyer); + //TODO: utiliser l'id d'un player qui contr\xF4le le chevalier + let display = startFramedDisplay(playerId, "Services d'\xE9cuyer", ecuyer); let finSoin = function() { nbCibles--; if (nbCibles === 0) { @@ -22997,17 +23317,17 @@ var COFantasy = COFantasy || function() { if (c.token.id == ecuyer.token.id) { msgSoin = 'se soigne de '; } else { - msgSoin = nomPerso(c) + " récupère "; + msgSoin = nomPerso(c) + " r\xE9cup\xE8re "; } if (s < soins) - msgSoin += s + " PV. (Le résultat du jet était " + soinTxt + ")"; + msgSoin += s + " PV. (Le r\xE9sultat du jet \xE9tait " + soinTxt + ")"; else msgSoin += soinTxt + " PV."; addLineToFramedDisplay(display, msgSoin); }; soigneToken(c, soins, evt, printTrue); finSoin(); }); //fin du sendChat - }; // fin de définition de soigneCible + }; // fin de d\xE9finition de soigneCible let peutToutSoigner = (alliesASoigner.length <= maxASoigner); if (peutToutSoigner) nbCibles += alliesASoigner.length; else if (maxASoigner > 0) nbCibles++; //pour ne pas finir avant d'imprimer les boutons @@ -23027,7 +23347,7 @@ var COFantasy = COFantasy || function() { }); finSoin(); } - }); //fin iteration sur les écuyers + }); //fin iteration sur les \xE9cuyers } function parseOptions(msg) { @@ -23035,7 +23355,7 @@ var COFantasy = COFantasy || function() { if (msg.selected && msg.selected.length > 0) { let firstSelected = getObj('graphic', msg.selected[0]._id); if (firstSelected === undefined) { - error("Un token sélectionné n'est pas trouvé en interne", msg.selected); + error("Un token s\xE9lectionn\xE9 n'est pas trouv\xE9 en interne", msg.selected); return; } pageId = firstSelected.get('pageid'); @@ -23069,7 +23389,7 @@ var COFantasy = COFantasy || function() { break; case 'lanceur': if (cmd.length < 2) { - error("Il faut préciser l'id ou le nom du lanceur", arg); + error("Il faut pr\xE9ciser l'id ou le nom du lanceur", arg); return; } options.lanceur = persoOfId(cmd[1], cmd[1], pageId); @@ -23117,7 +23437,7 @@ var COFantasy = COFantasy || function() { cout = parseInt(cmd[1]); } if (isNaN(cout) || cout < 0) { - error("Coût en mana incorrect", cmd); + error("Co\xFBt en mana incorrect", cmd); return; } options.mana = options.mana || 0; @@ -23132,7 +23452,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { cout = parseInt(cmd[1]); if (isNaN(cout) || cout < 0) { - error("Le coût de la magie rapide n'est pas un entier positif", cmd); + error("Le co\xFBt de la magie rapide n'est pas un entier positif", cmd); cout = 1; } } @@ -23151,47 +23471,39 @@ var COFantasy = COFantasy || function() { } let rang = parseInt(cmd[1]); if (isNaN(rang) || rang < 1) { - error("Le rang doit être un nombre positif"); + error("Le rang doit \xEAtre un nombre positif"); return; } options.rang = rang; break; case 'limiteParJour': if (cmd.length < 2) { - error("Il manque la limite journalière", cmd); + error("Il manque la limite journali\xE8re", cmd); return; } - let limiteParJour = parseInt(cmd[1]); - if (isNaN(limiteParJour) || limiteParJour < 1) { - error("La limite journalière doit être un nombre positif", cmd); - return; - } - options.limiteParJour = limiteParJour; - if (cmd.length > 2) { - cmd.splice(0, 2); - options.limiteParJourRessource = cmd.join('_'); - } + let limiteParJour = parseLimite(cmd, "journali\xE8re"); + if (limiteParJour) options.limiteParJour = limiteParJour; return; case 'depasseLimite': if (cmd.length < 2) { - error("Il manque le coût en mana pour depasser la limite", cmd); + error("Il manque le co\xFBt en mana pour depasser la limite", cmd); return; } let depasse = parseInt(cmd[1]); if (isNaN(depasse) || depasse < 1) { - error("Le coût de dépassement doit être un nombre positif", cmd); + error("Le co\xFBt de d\xE9passement doit \xEAtre un nombre positif", cmd); return; } options.depasseLimite = depasse; return; case 'limiteSoinsParJour': if (cmd.length < 2) { - error("Il manque la limite de soins journalière", cmd); + error("Il manque la limite de soins journali\xE8re", cmd); return; } let limiteSoinsParJour = parseInt(cmd[1]); if (isNaN(limiteSoinsParJour) || limiteSoinsParJour < 1) { - error("La limite de soins journalière doit être un nombre positif", cmd); + error("La limite de soins journali\xE8re doit \xEAtre un nombre positif", cmd); return; } options.limiteSoinsParJour = limiteSoinsParJour; @@ -23202,12 +23514,12 @@ var COFantasy = COFantasy || function() { return; case 'limiteCibleParJour': if (cmd.length < 2) { - error("Il manque la limite journalière", cmd); + error("Il manque la limite journali\xE8re", cmd); return; } let limiteCibleParJour = parseInt(cmd[1]); if (isNaN(limiteCibleParJour) || limiteCibleParJour < 1) { - error("La limite journalière doit être un nombre positif", cmd); + error("La limite journali\xE8re doit \xEAtre un nombre positif", cmd); return; } options.limiteCibleParJour = limiteCibleParJour; @@ -23221,29 +23533,21 @@ var COFantasy = COFantasy || function() { options.limiteParCombat = 1; return; } - let limiteParCombat = parseInt(cmd[1]); - if (isNaN(limiteParCombat) || limiteParCombat < 1) { - error("La limite par combat doit être un nombre positif", cmd); - return; - } - options.limiteParCombat = limiteParCombat; - if (cmd.length > 2) { - cmd.splice(0, 2); - options.limiteParCombatRessource = cmd.join('_'); - } + let limiteParCombat = parseLimite(cmd, "par combat"); + if (limiteParCombat) options.limiteParCombat = limiteParCombat; return; case 'tempsRecharge': if (cmd.length < 3) { - error("Il manque un argument à l'option --tempsRecharge", cmd); + error("Il manque un argument \xE0 l'option --tempsRecharge", cmd); return; } if (!estEffetTemp(cmd[1])) { - error("Le premier argument de l'option --tempsRecharge doit être un effet temporaire répertorié", cmd); + error("Le premier argument de l'option --tempsRecharge doit \xEAtre un effet temporaire r\xE9pertori\xE9", cmd); return; } let tr = parseInt(cmd[2]); if (isNaN(tr)) { - error("Le deuxième argument de l'option --tempsRecharge doit être un nombre", cmd); + error("Le deuxi\xE8me argument de l'option --tempsRecharge doit \xEAtre un nombre", cmd); return; } options.tempsRecharge = { @@ -23268,7 +23572,7 @@ var COFantasy = COFantasy || function() { portee = parseInt(cmd[1]); } if (isNaN(portee) || portee < 0) { - error("Portée incorrecte", cmd); + error("Port\xE9e incorrecte", cmd); return; } options.portee = portee; @@ -23291,21 +23595,21 @@ var COFantasy = COFantasy || function() { return; case 'decrAttribute': if (cmd.length < 2) { - error("Erreur interne d'une commande générée par bouton", opts); + error("Erreur interne d'une commande g\xE9n\xE9r\xE9e par bouton", opts); return; } let attr = getObj('attribute', cmd[1]); if (attr === undefined && options.lanceur) { attr = tokenAttribute(options.lanceur, cmd[1]); if (attr.length === 0) { - log("Attribut à changer perdu"); + log("Attribut \xE0 changer perdu"); log(cmd); return; } attr = attr[0]; } if (attr === undefined) { - log("Attribut à changer perdu"); + log("Attribut \xE0 changer perdu"); log(cmd); return; } @@ -23356,14 +23660,14 @@ var COFantasy = COFantasy || function() { break; case "classeEffet": if (cmd.length < 2) { - sendChat("COF", "Il manque un argument à l'option --classeEffet"); + sendChat("COF", "Il manque un argument \xE0 l'option --classeEffet"); return; } options.classeEffet = cmd[1]; return; case 'message': if (cmd.length < 2) { - error("Il manque le message après --message", cmd); + error("Il manque le message apr\xE8s --message", cmd); return; } options.messages = options.messages || []; @@ -23371,7 +23675,7 @@ var COFantasy = COFantasy || function() { return; case 'messageMJ': if (cmd.length < 2) { - error("Il manque le message après --messageMJ", cmd); + error("Il manque le message apr\xE8s --messageMJ", cmd); return; } options.messagesMJ = options.messagesMJ || []; @@ -23379,14 +23683,14 @@ var COFantasy = COFantasy || function() { return; case 'image': if (cmd.length < 2) { - error("Il manque le nom de l'imageaprès --image", cmd); + error("Il manque le nom de l'imageapr\xE8s --image", cmd); return; } options.image = cmd[1].replace(':', ':'); return; case 'son': if (cmd.length < 2) { - error("Il manque le nom du son après --son", cmd); + error("Il manque le nom du son apr\xE8s --son", cmd); return; } options.son = cmd.slice(1).join(' '); @@ -23412,7 +23716,7 @@ var COFantasy = COFantasy || function() { return; case 'etat': if (cmd.length < 2) { - error("Il manque le nom de l'état et sa valeur après --etat", cmd); + error("Il manque le nom de l'\xE9tat et sa valeur apr\xE8s --etat", cmd); return; } options.etats = options.etats || {}; @@ -23432,7 +23736,7 @@ var COFantasy = COFantasy || function() { case 'dm': let t = cmd[0]; if (options[t]) { - error(t + " déjà défini", opts); + error(t + " d\xE9j\xE0 d\xE9fini", opts); return; } if (cmd.length < 2) { @@ -23455,7 +23759,7 @@ var COFantasy = COFantasy || function() { } else { let base = parseInt(cmd[1]); if (isNaN(base)) { - error("L'argument de --magieEnArmure doit être un nombre ou mana", cmd); + error("L'argument de --magieEnArmure doit \xEAtre un nombre ou mana", cmd); return; } options.magieEnArmure = { @@ -23468,16 +23772,36 @@ var COFantasy = COFantasy || function() { return; case 'tokenSide': if (cmd.length < 2) { - error("Il faut préciser le coté de token à utiliser", cmd); + error("Il faut pr\xE9ciser le cot\xE9 de token \xE0 utiliser", cmd); return; } let side = parseInt(cmd[1]); if (isNaN(side) || side < 0) { - error("Le coté de token doit être un nombre positif", cmd); + error("Le cot\xE9 de token doit \xEAtre un nombre positif", cmd); return; } options.tokenSide = side; return; + case 'terrainDifficile': + { + let terrainDifficile = options.terrainDifficile || { + duree: 1, + imgsrc: IMG_INVISIBLE, + nom: "Terrain difficile" + }; + if (cmd.length > 1) { //le premier argument est la dur\xE9e de l'effet + terrainDifficile.duree = toInt(cmd[1], 1); + if (cmd.length > 2) { //le second argument est le nom du terrain + terrainDifficile.nom = cmd[2].replace(/_/g, ' '); + if (cmd.length > 3) { //le troisi\xE8me argument est l'url de l'image + let imgsrc = cmd[3].replace(':', ':'); + terrainDifficile.imgsrc = normalizeTokenImg(imgsrc); + } + } + } + options.terrainDifficile = terrainDifficile; + return; + } default: return; } @@ -23485,11 +23809,11 @@ var COFantasy = COFantasy || function() { return options; } - //Si il y a des effets à durée indéterminées, les rappeler au MJ, avec un bouton pour facilement y mettre fin si nécessaire + //Si il y a des effets \xE0 dur\xE9e ind\xE9termin\xE9es, les rappeler au MJ, avec un bouton pour facilement y mettre fin si n\xE9cessaire function proposerFinEffetsIndetermines() { - //On commence par les états globaux + //On commence par les \xE9tats globaux if (stateCOF.tenebresMagiques) { - sendPlayer('GM', boutonSimple("!cof-tenebres-magiques fin", "Mettre fin") + "aux ténèbres magiques ?"); + sendPlayer('GM', boutonSimple("!cof-tenebres-magiques fin", "Mettre fin") + "aux t\xE9n\xE8bres magiques ?"); } if (stateCOF.effetAuD20) { for (let ev in stateCOF.effetAuD20) { @@ -23505,7 +23829,7 @@ var COFantasy = COFantasy || function() { estEffetIndetermine(name); }); if (attrs.length === 0) return; - const display = startFramedDisplay(undefined, "Effets à durée indéterminée actifs", undefined, { + const display = startFramedDisplay(undefined, "Effets \xE0 dur\xE9e ind\xE9termin\xE9e actifs", undefined, { chuchote: 'gm' }); let attrsParPerso = {}; @@ -23569,7 +23893,7 @@ var COFantasy = COFantasy || function() { } attrsParPerso[charId].effets.push(ef); return; - } // on a un attribut de token non lié + } // on a un attribut de token non li\xE9 let pn = attrName.indexOf('_'); if (pn < 1) return; ef.nom = attrName.substring(0, pn - 1); @@ -23626,8 +23950,8 @@ var COFantasy = COFantasy || function() { sendFramedDisplay(display); } - // Remise à zéro de toutes les limites journalières - // N'ajoute pas evt à l'historique + // Remise \xE0 z\xE9ro de toutes les limites journali\xE8res + // N'ajoute pas evt \xE0 l'historique function jour(persos, evt, options) { let attrs; attrs = removeAllAttributes('pressionMortelle', evt); @@ -23641,14 +23965,14 @@ var COFantasy = COFantasy || function() { attrs = removeAllAttributes('immunise24HA', evt, attrs); attrs = removeAllAttributes('testsRatesDuTour', evt, attrs); attrs = removeAllAttributes('pointsDeViolence', evt, attrs); - //Les élixirs + //Les \xE9lixirs attrs = removeAllAttributes('elixirsACreer', evt, attrs); attrs = proposerRenouveauElixirs(evt, attrs, options); //Les runes attrs = proposerRenouveauRunes(evt, attrs, options); - //Les plantes médicinales - attrs = removeAllAttributes('dose_Plante médicinale', evt, attrs); - attrs = removeConsommables('Plante médicinale', evt, attrs); + //Les plantes m\xE9dicinales + attrs = removeAllAttributes('dose_Plante m\xE9dicinale', evt, attrs); + attrs = removeConsommables('Plante m\xE9dicinale', evt, attrs); //La perte de substance persos.forEach(function(perso) { if (predicateAsBool(perso, 'perteDeSubstance')) { @@ -23656,8 +23980,8 @@ var COFantasy = COFantasy || function() { let msg = nomPerso(perso) + " a maintenant " + perteDeSubstance; msg += " jour" + ((perteDeSubstance > 1) ? 's' : '') + " de perte de substance.
"; if (!predicateAsBool(perso, 'ancreInvincible')) { - msg += " Demander un jet de CHA difficulté " + perteDeSubstance; - msg += " ou " + onGenre(perso, 'il', 'elle') + " disparaît pendant "; + msg += " Demander un jet de CHA difficult\xE9 " + perteDeSubstance; + msg += " ou " + onGenre(perso, 'il', 'elle') + " dispara\xEEt pendant "; let nj = rollDePlus(6); msg += nj.roll + " heure" + ((nj.val > 1) ? 's' : '') + '.'; } @@ -23690,13 +24014,13 @@ var COFantasy = COFantasy || function() { let attrName = attr.get('name'); let carac = attr.get('current'); if (!isCarac(carac)) { - error("Save par jour " + attrName + " mal formé", carac); + error("Save par jour " + attrName + " mal form\xE9", carac); finalize(); return; } let seuil = parseInt(attr.get('max')); if (isNaN(seuil)) { - error("Save par jour " + attrName + " mal formé", seuil); + error("Save par jour " + attrName + " mal form\xE9", seuil); finalize(); return; } @@ -23728,7 +24052,7 @@ var COFantasy = COFantasy || function() { name: attrName }); if (attrEffet === undefined || attrEffet.length === 0) { - error("Save sans effet associé " + attrName, attr); + error("Save sans effet associ\xE9 " + attrName, attr); findObjs({ _type: 'attribute', _characterid: charId, @@ -23747,11 +24071,11 @@ var COFantasy = COFantasy || function() { let sujet = onGenre(perso, 'il', 'elle'); let met = messageEffetIndetermine[effetC]; if (met === undefined) met = { - fin: "résiste à l'effet", + fin: "r\xE9siste \xE0 l'effet", actf: "reste sous l'emprise de l'effet" }; let saveOpts = { - msgPour: " pour ne plus être sous l'effet " + effetC, + msgPour: " pour ne plus \xEAtre sous l'effet " + effetC, msgReussite: ", " + sujet + ' ' + messageFin(perso, met), msgRate: ", " + sujet + ' ' + messageActif(perso, met), rolls: options.rolls, @@ -23782,7 +24106,7 @@ var COFantasy = COFantasy || function() { }); //fin boucle attrSave } - //La caractéristique sans affaiblissement + //La caract\xE9ristique sans affaiblissement function caracNormale(perso, carac) { let res = ficheAttributeAsInt(perso, carac, 10); if (!persoEstPNJ(perso)) return res; @@ -23818,7 +24142,7 @@ var COFantasy = COFantasy || function() { attributeAsInt(perso, 'affaiblissementde' + carac, 0); } - //N'ajoute pas evt à l'historique + //N'ajoute pas evt \xE0 l'historique function diminueAffaiblissement(perso, carac, valeur, evt, malus) { if (valeur < 1) return; let nomAttr = 'affaiblissementde' + carac; @@ -23846,7 +24170,7 @@ var COFantasy = COFantasy || function() { } let pvMaxNormaux = attributeAsInt(perso, 'pvMaxNormaux', 0); if (pvMaxNormaux < pvmax) { - error("Les PV max sont inférieurs à la valeur normale", pvMaxNormaux); + error("Les PV max sont inf\xE9rieurs \xE0 la valeur normale", pvMaxNormaux); return; } if (valeur == malus || (valeur == malus - 1 && caracNormale(perso, 'consititution') % 2 == 1)) { @@ -23873,7 +24197,7 @@ var COFantasy = COFantasy || function() { } } } else if (valeur == malus) { - //Au cas où, on vérifie le pv max + //Au cas o\xF9, on v\xE9rifie le pv max let pvMaxNormaux = attributeAsInt(perso, 'pvMaxNormaux', 0); if (pvMaxNormaux > 0) { let pvmax = parseInt(perso.token.get("bar1_max")); @@ -23931,7 +24255,7 @@ var COFantasy = COFantasy || function() { let speaksAs = player.get('speakingas'); if (speaksAs !== '') fromMsg = speaksAs; } - sendChat(fromMsg, "Un nouveau jour se lève"); + sendChat(fromMsg, "Un nouveau jour se l\xE8ve"); if (stateCOF.combat) sortirDuCombat(); jour(persos, evt, options); if (options.repos) { @@ -23948,8 +24272,8 @@ var COFantasy = COFantasy || function() { if (msg.content.includes(' --reposLong')) reposLong = true; getSelected(msg, function(selection, playerId) { if (selection.length === 0) { - sendPlayer(msg, "!cof-recuperer sans sélection de tokens", playerId); - log("!cof-recuperer requiert des tokens sélectionnés"); + sendPlayer(msg, "!cof-recuperer sans s\xE9lection de tokens", playerId); + log("!cof-recuperer requiert des tokens s\xE9lectionn\xE9s"); return; } let persos = []; @@ -23977,8 +24301,8 @@ var COFantasy = COFantasy || function() { let allCaracs = ['force', 'dexterite', 'constitution', 'intelligence', 'sagesse', 'charisme']; - //Asynchrone (jets de dés) - // ne rajoute pas evt à l'historique + //Asynchrone (jets de d\xE9s) + // ne rajoute pas evt \xE0 l'historique function recuperation(persos, reposLong, playerId, evt, options) { options = options || {}; let manquePV = []; @@ -24025,7 +24349,7 @@ var COFantasy = COFantasy || function() { let hasMana = false; let dmTemp = bar2; let estMook = token.get('bar1_link') === ''; - if (manaAttr.length > 0) { // Récupération des points de mana + if (manaAttr.length > 0) { // R\xE9cup\xE9ration des points de mana let manaMax = parseInt(manaAttr[0].get('max')); hasMana = !isNaN(manaMax) && manaMax > 0; if (hasMana) { @@ -24036,7 +24360,7 @@ var COFantasy = COFantasy || function() { } } } - if (!isNaN(dmTemp) && dmTemp > 0) { // récupération de DM temp + if (!isNaN(dmTemp) && dmTemp > 0) { // r\xE9cup\xE9ration de DM temp if (reposLong) dmTemp = 0; else dmTemp = Math.max(0, dmTemp - 10); if (hasMana) { @@ -24052,18 +24376,18 @@ var COFantasy = COFantasy || function() { return; } if (bar1 >= pvmax && !reposLong) { - //Plus rien à faire si pas un repos long + //Plus rien \xE0 faire si pas un repos long sendPerso(perso, "n'a pas besoin de repos"); finalize(); return; } if (reposLong) { - //Récupération des affaiblissements de carac si repos long + //R\xE9cup\xE9ration des affaiblissements de carac si repos long allCaracs.forEach(function(carac) { let malus = attributeAsInt(perso, 'affaiblissementde' + carac, 0); if (malus > 0) { diminueAffaiblissement(perso, carac, 1, evt, malus); - sendPerso(perso, "récupère un point " + deCarac(carac)); + sendPerso(perso, "r\xE9cup\xE8re un point " + deCarac(carac)); } }); if (bar1 >= pvmax && (!pr || pr.current == pr.max)) { @@ -24071,19 +24395,19 @@ var COFantasy = COFantasy || function() { return; } if (bar1 < pvmax && predicateAsBool(perso, 'montureMagique')) { - //La monture magique récupère tous ses PV durant la nuit + //La monture magique r\xE9cup\xE8re tous ses PV durant la nuit updateCurrentBar(perso, 1, pvmax, evt); - sendPerso(perso, "récupère tous ses PV"); + sendPerso(perso, "r\xE9cup\xE8re tous ses PV"); finalize(); return; } } - //La récupération de PV ou de PR + //La r\xE9cup\xE9ration de PV ou de PR let dVie = ficheAttributeAsInt(perso, "DV", 0); if (dVie < 4) { if (bar1 < pvmax) manquePV.push(perso); finalize(); - return; //Si pas de dé de vie, alors pas de PR. + return; //Si pas de d\xE9 de vie, alors pas de PR. } if (limiteRessources(perso, options, 'repos', 'repos', evt)) { if (bar1 < pvmax) manquePV.push(perso); @@ -24091,18 +24415,18 @@ var COFantasy = COFantasy || function() { return; } let message; - if (reposLong && pr && pr.current < pr.max) { // on récupère un PR + if (reposLong && pr && pr.current < pr.max) { // on r\xE9cup\xE8re un PR //Sauf si on a une blessure gave if (getState(perso, 'blesse')) { - let testId = 'guérir_blessure_' + perso.token.id; + let testId = 'gu\xE9rir_blessure_' + perso.token.id; testCaracteristique(perso, 'CON', 8, testId, options, evt, function(tr) { - sendPerso(perso, "fait un jet de CON pour guérir de sa blessure"); + sendPerso(perso, "fait un jet de CON pour gu\xE9rir de sa blessure"); let m = "/direct " + onGenre(perso, 'Il', 'Elle') + " fait " + tr.texte; if (tr.reussite) { - sendChar(charId, m + "≥ 8, son état s'améliore nettement." + tr.modifiers, true); + sendChar(charId, m + "≥ 8, son \xE9tat s'am\xE9liore nettement." + tr.modifiers, true); setState(perso, 'blesse', false, evt); } else { - let msgRate = m + "< 8, son état reste préoccupant." + tr.rerolls + tr.modifiers; + let msgRate = m + "< 8, son \xE9tat reste pr\xE9occupant." + tr.rerolls + tr.modifiers; sendChar(charId, msgRate, true); } finalize(); @@ -24111,27 +24435,26 @@ var COFantasy = COFantasy || function() { } let affAttr = rajouterPointDeRecuperation(perso, evt, pr); if (affAttr === undefined) { - error("Pas de point de récupération à rajouter et pourtant pas au max", token); + error("Pas de point de r\xE9cup\xE9ration \xE0 rajouter et pourtant pas au max", token); finalize(); return; } message = - "Au cours de la nuit, les points de récupération de " + nomPerso(perso) + - " passent de " + (pr.current - 1) + " à " + pr.current; + "Au cours de la nuit, les points de r\xE9cup\xE9ration de " + nomPerso(perso) + + " passent de " + (pr.current - 1) + " \xE0 " + pr.current; sendChar(charId, message, true); if (bar1 < pvmax) manquePV.push(perso); finalize(); return; } if (!reposLong && pr) { - if (pr.current === 0) { //pas possible de récupérer - message = " a besoin d'une nuit complète pour récupérer"; + if (pr.current === 0) { //pas possible de r\xE9cup\xE9rer + message = " a besoin d'une nuit compl\xE8te pour r\xE9cup\xE9rer"; sendPerso(perso, message); finalize(); return; - } else { //dépense d'un PR + } else { //d\xE9pense d'un PR enleverPointDeRecuperation(perso, pr, evt); - pr.current--; } } let conMod = modCarac(perso, 'constitution'); @@ -24164,16 +24487,17 @@ var COFantasy = COFantasy || function() { if (reposLong) { message = "Au cours de la nuit, "; } else { - message = "Après 5 minutes de repos, "; + message = "Apr\xE8s 5 minutes de repos, "; } - message += "récupère " + buildinline(roll) + "+" + bonus + " PV."; - if (pr) message += " Il lui reste " + pr.current + " points de récupération"; + message += "r\xE9cup\xE8re " + buildinline(roll) + "+" + bonus + " PV."; + if (pr) message += " Il lui reste " + pr.current + " points de r\xE9cup\xE9ration"; sendPerso(perso, message); finalize(); }); }); } + //!cof-recharger label [--grenaille] function recharger(msg) { let cmd = msg.content.split(' '); if (cmd.length < 2) { @@ -24187,15 +24511,12 @@ var COFantasy = COFantasy || function() { }; let grenaille = false; if (msg.content.includes(' --grenaille')) grenaille = true; - let options = {}; - if (msg.content.includes(' --son')) { - options = parseOptions(msg); - options = options || {}; - } + let options = parseOptions(msg); + options = options || {}; getSelected(msg, function(selected, playerId) { if (selected === undefined) { - sendPlayer(msg, "!cof-recharger sans sélection de tokens", playerId); - log("!cof-recharger requiert des tokens sélectionnés"); + sendPlayer(msg, "!cof-recharger sans s\xE9lection de tokens", playerId); + log("!cof-recharger requiert des tokens s\xE9lectionn\xE9s"); return; } iterSelected(selected, function(perso) { @@ -24222,7 +24543,7 @@ var COFantasy = COFantasy || function() { attrs = attrs[0]; currentCharge = parseInt(attrs.get('current')); if (isNaN(currentCharge)) { - error("charge mal formée", attrs); + error("charge mal form\xE9e", attrs); currentCharge = 0; } } @@ -24244,10 +24565,11 @@ var COFantasy = COFantasy || function() { } else attrGrenaille = attrGrenaille[0]; currentChargeGrenaille = parseInt(attrGrenaille.get('current')); if (isNaN(currentChargeGrenaille)) { - error("charge de grenaille mal formée", attrGrenaille); + error("charge de grenaille mal form\xE9e", attrGrenaille); return; } - if (currentChargeGrenaille > currentCharge) currentChargeGrenaille = currentCharge; + if (currentChargeGrenaille > currentCharge) + currentChargeGrenaille = currentCharge; evt.attributes.push({ attribute: attrGrenaille, current: currentChargeGrenaille @@ -24277,7 +24599,7 @@ var COFantasy = COFantasy || function() { } else attrGrenaille = attrGrenaille[0]; currentChargeGrenaille = parseInt(attrGrenaille.get('current')); if (isNaN(currentChargeGrenaille)) { - error("charge de grenaille mal formée", attrGrenaille); + error("charge de grenaille mal form\xE9e", attrGrenaille); return; } if (currentChargeGrenaille < currentCharge) { @@ -24293,7 +24615,7 @@ var COFantasy = COFantasy || function() { attrGrenaille = attrGrenaille[0]; currentChargeGrenaille = parseInt(attrGrenaille.get('current')); if (isNaN(currentChargeGrenaille)) { - error("charge de grenaille mal formée", attrGrenaille); + error("charge de grenaille mal form\xE9e", attrGrenaille); return; } if (currentChargeGrenaille > 0) { @@ -24308,12 +24630,12 @@ var COFantasy = COFantasy || function() { } } if (maxCharge == 1) { - sendPerso(perso, arme.name + " est déjà chargé"); + sendPerso(perso, arme.name + " est d\xE9j\xE0 charg\xE9"); } else { - sendPerso(perso, "a déjà tous ses " + arme.name + " chargés"); + sendPerso(perso, "a d\xE9j\xE0 tous ses " + arme.name + " charg\xE9s"); } }); - }); + }, options); addEvent(evt); } @@ -24326,12 +24648,12 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let action = evt.action; if (!action) { - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); return; } let perso = evt.personnage; @@ -24339,7 +24661,7 @@ var COFantasy = COFantasy || function() { if (args.length > 2) { let roll = action.rolls[args[2]]; if (roll === undefined) { - error("Erreur interne du bouton de chance : roll non identifié", args); + error("Erreur interne du bouton de chance : roll non identifi\xE9", args); return; } if (roll.token === undefined) { @@ -24350,7 +24672,7 @@ var COFantasy = COFantasy || function() { rollId = args[2]; } if (perso === undefined) { - error("Erreur interne du bouton de chance : l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton de chance : l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24359,7 +24681,7 @@ var COFantasy = COFantasy || function() { } let chance = pointsDeChance(perso); if (chance <= 0) { - sendPerso(perso, "n'a plus de point de chance à dépenser..."); + sendPerso(perso, "n'a plus de point de chance \xE0 d\xE9penser..."); return; } let evtChance = { @@ -24369,7 +24691,7 @@ var COFantasy = COFantasy || function() { chance--; undoEvent(evt); setFicheAttr(perso, 'pc', chance, evtChance, { - msg: " a dépensé un point de chance. Il lui en reste " + chance + msg: " a d\xE9pens\xE9 un point de chance. Il lui en reste " + chance }); action.options = action.options || {}; if (rollId) { @@ -24379,7 +24701,7 @@ var COFantasy = COFantasy || function() { action.options.chance = (action.options.chance + 10) || 10; } if (!redoEvent(evt, action, perso)) - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); addEvent(evtChance); } @@ -24392,19 +24714,19 @@ var COFantasy = COFantasy || function() { } const evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let perso = evt.personnage; let rollId; if (args.length > 2) { if (!evt.action) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let roll = evt.action.rolls[args[2]]; if (roll === undefined) { - error("Erreur interne du bouton de chance : roll non identifié", args); + error("Erreur interne du bouton de chance : roll non identifi\xE9", args); return; } if (roll.token === undefined) { @@ -24415,7 +24737,7 @@ var COFantasy = COFantasy || function() { rollId = args[2]; } if (perso === undefined) { - error("Erreur interne du bouton de prouesse : l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton de prouesse : l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24451,7 +24773,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evtProuesse, false, {}, explications, function(dmgDisplay, dmg) { - sendPerso(perso, "réalise une prouesse et perd " + dmgDisplay + " PV"); + sendPerso(perso, "r\xE9alise une prouesse et perd " + dmgDisplay + " PV"); explications.forEach(function(expl) { sendPerso(perso, expl); }); @@ -24465,7 +24787,7 @@ var COFantasy = COFantasy || function() { } if (redoEvent(evt, action, perso)) return; } - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); } //!cof-pacte-sanglant [evt.id] [3|5] [rollId] @@ -24477,7 +24799,7 @@ var COFantasy = COFantasy || function() { } const evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let bonus = parseInt(args[2]); @@ -24489,12 +24811,12 @@ var COFantasy = COFantasy || function() { let rollId; if (args.length > 3) { if (!evt.action) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let roll = evt.action.rolls[args[3]]; if (roll === undefined) { - error("Erreur interne du bouton de pacte sanglant : roll non identifié", args); + error("Erreur interne du bouton de pacte sanglant : roll non identifi\xE9", args); return; } if (roll.token === undefined) { @@ -24505,7 +24827,7 @@ var COFantasy = COFantasy || function() { rollId = args[3]; } if (perso === undefined) { - error("Erreur interne du bouton de pacte sanglant : l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton de pacte sanglant : l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24514,7 +24836,7 @@ var COFantasy = COFantasy || function() { } let valPacteSanglant = predicateAsInt(perso, 'pacteSanglant', 0); if (valPacteSanglant < bonus) { - sendPerso(perso, "ne peut pas faire ça !"); + sendPerso(perso, "ne peut pas faire \xE7a !"); return; } let action = evt.action; @@ -24543,7 +24865,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evtPacteSanglant, false, {}, explications, function(dmgDisplay, dmg) { - sendPerso(perso, "réalise un Pacte sanglant et perd " + dmgDisplay + " PV"); + sendPerso(perso, "r\xE9alise un Pacte sanglant et perd " + dmgDisplay + " PV"); explications.forEach(function(expl) { sendPerso(perso, expl); }); @@ -24556,7 +24878,7 @@ var COFantasy = COFantasy || function() { } if (redoEvent(evt, action, perso)) return; } - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); } //!cof-pacte-sanglant [evt.id] [3|5] [targetId] @@ -24568,11 +24890,11 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } if (!evt.action) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let bonus = parseInt(args[2]); @@ -24582,7 +24904,7 @@ var COFantasy = COFantasy || function() { } let perso = persoOfId([args[3]]); if (perso === undefined) { - error("Erreur interne du bouton de pacte sanglant (DEF) : pas de cible trouvée", args); + error("Erreur interne du bouton de pacte sanglant (DEF) : pas de cible trouv\xE9e", args); return; } if (!peutController(msg, perso)) { @@ -24591,7 +24913,7 @@ var COFantasy = COFantasy || function() { } let valPacteSanglant = predicateAsInt(perso, 'pacteSanglant', 0); if (valPacteSanglant < bonus) { - sendPerso(perso, "ne peut pas faire ça !"); + sendPerso(perso, "ne peut pas faire \xE7a !"); return; } let action = evt.action; @@ -24619,7 +24941,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evtPacteSanglant, false, {}, explications, function(dmgDisplay, dmg) { - sendPerso(perso, "réalise un Pacte sanglant et perd " + dmgDisplay + " PV"); + sendPerso(perso, "r\xE9alise un Pacte sanglant et perd " + dmgDisplay + " PV"); explications.forEach(function(expl) { sendPerso(perso, expl); }); @@ -24628,7 +24950,7 @@ var COFantasy = COFantasy || function() { options.pacteSanglantDef[perso.token.id] = (options.pacteSanglantDef[perso.token.id] + bonus) || bonus; if (redoEvent(evt, action, perso)) return; } - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); } //!cof-tour-force [evt.id] [rollId] @@ -24640,19 +24962,19 @@ var COFantasy = COFantasy || function() { } const evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let perso = evt.personnage; let rollId; if (args.length > 2) { if (!evt.action) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let roll = evt.action.rolls[args[2]]; if (roll === undefined) { - error("Erreur interne du bouton de tour de force : roll non identifié", args); + error("Erreur interne du bouton de tour de force : roll non identifi\xE9", args); return; } if (roll.token === undefined) { @@ -24663,7 +24985,7 @@ var COFantasy = COFantasy || function() { rollId = args[2]; } if (perso === undefined) { - error("Erreur interne du bouton de tour de force : l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton de tour de force : l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24672,7 +24994,7 @@ var COFantasy = COFantasy || function() { } let attrTourDeForce = predicateAsBool(perso, 'tourDeForce'); if (!attrTourDeForce) { - sendPerso(perso, "ne peut pas faire ça !"); + sendPerso(perso, "ne peut pas faire \xE7a !"); return; } let action = evt.action; @@ -24699,7 +25021,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evtTourDeForce, false, {}, explications, function(dmgDisplay, dmg) { - sendPerso(perso, "réalise un Tour de force et perd " + dmgDisplay + " PV"); + sendPerso(perso, "r\xE9alise un Tour de force et perd " + dmgDisplay + " PV"); explications.forEach(function(expl) { sendPerso(perso, expl); }); @@ -24712,7 +25034,7 @@ var COFantasy = COFantasy || function() { } if (redoEvent(evt, action, perso)) return; } - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); } //Renvoie true si redo possible, false sinon @@ -24771,7 +25093,7 @@ var COFantasy = COFantasy || function() { action.testINT, action.infosAdditionelles, options); return true; case 'enveloppement': - case 'étreinte': + case '\xE9treinte': doEnveloppement(action.attaquant, action.cible, action.difficulte, action.type, action.exprDM, options); return true; case 'injonction': @@ -24863,12 +25185,12 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let perso = evt.personnage; if (perso === undefined) { - error("Erreur interne du bouton d'échec total: l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton d'\xE9chec total: l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24877,14 +25199,14 @@ var COFantasy = COFantasy || function() { } let action = evt.action; if (!action || evt.type != "Attaque") { - error("Erreur interne du bouton d'échec total: l'évènement n'est pas une attaque", evt); + error("Erreur interne du bouton d'\xE9chec total: l'\xE9v\xE8nement n'est pas une attaque", evt); return; } let evtEchecTotal = { type: 'echecTotal' }; addEvent(evtEchecTotal); - // Attaquer avec les mêmes options, vider redo et preDmg éventuels + // Attaquer avec les m\xEAmes options, vider redo et preDmg \xE9ventuels let options = action.options; options.auto = true; options.echecTotal = true; @@ -24904,13 +25226,17 @@ var COFantasy = COFantasy || function() { else if (rangExpertDuCombat > 2) limiteParTour = 2; else limiteParTour = 1; if (limiteRessources(perso, { - limiteParCombat: rangExpertDuCombat * 2, - limiteParTour: limiteParTour - }, "expertDuCombat", "a atteint sa limite de dé d'expert du combat", evt)) { + limiteParCombat: { + val: rangExpertDuCombat * 2 + }, + limiteParTour: { + val: limiteParTour + } + }, "expertDuCombat", "a atteint sa limite de d\xE9 d'expert du combat", evt)) { addEvent(evt); return false; } - sendPerso(perso, "utilise un dé d'expert du combat"); + sendPerso(perso, "utilise un d\xE9 d'expert du combat"); return true; } @@ -24919,19 +25245,19 @@ var COFantasy = COFantasy || function() { //!cof-expert-combat-dm function expertDuCombat(msg) { if (!stateCOF.combat) { - sendPlayer(msg, "On ne peut utiliser les dés d'expert du combat qu'en combat"); + sendPlayer(msg, "On ne peut utiliser les d\xE9s d'expert du combat qu'en combat"); return; } let cmd = msg.content.split(' '); let evtARefaire; const evt = { - type: "Dé d'expert du combat (touche)", + type: "D\xE9 d'expert du combat (touche)", attributes: [] }; - if (cmd.length > 1) { //On relance pour un événement particulier + if (cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; @@ -24941,7 +25267,7 @@ var COFantasy = COFantasy || function() { return; } if (perso === undefined) { - error("Erreur interne du bouton expert de combat : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton expert de combat : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -24957,11 +25283,11 @@ var COFantasy = COFantasy || function() { else if (cmd[0].includes("-dm")) action.options.expertDuCombatDM = action.options.expertDuCombatDM + 1 || 1; if (!redoEvent(evtARefaire, action, perso)) - error("Type d'évènement pas supporté par le bouton Rune d'Energie", evt); - } else { //Juste pour vérifier l'attribut et le diminuer + error("Type d'\xE9v\xE8nement pas support\xE9 par le bouton Rune d'Energie", evt); + } else { //Juste pour v\xE9rifier l'attribut et le diminuer getSelected(msg, function(selection) { if (selection.length === 0) { - sendPlayer(msg, 'Pas de token sélectionné pour !cof-bouton-expert-combat-touche'); + sendPlayer(msg, 'Pas de token s\xE9lectionn\xE9 pour !cof-bouton-expert-combat-touche'); return; } iterSelected(selection, function(perso) { @@ -24981,17 +25307,17 @@ var COFantasy = COFantasy || function() { } let evtARefaire = findEvent(args[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let action = evtARefaire.action; if (action === undefined) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let perso = persoOfId([args[2]]); if (perso === undefined) { - error("Erreur interne du bouton d'expert du combat (DEF) : pas de cible trouvée", args); + error("Erreur interne du bouton d'expert du combat (DEF) : pas de cible trouv\xE9e", args); return; } if (!peutController(msg, perso)) { @@ -25012,37 +25338,39 @@ var COFantasy = COFantasy || function() { } function persoUtiliseRuneEnergie(perso, evt) { - let attr = tokenAttribute(perso, 'runeForgesort_énergie'); + let attr = tokenAttribute(perso, 'runeForgesort_\xE9nergie'); if (attr.length < 1 || attr[0].get('current') < 1) { - sendPerso(perso, "n'a pas de rune d'énergie"); + sendPerso(perso, "n'a pas de rune d'\xE9nergie"); return false; } if (limiteRessources(perso, { - limiteParCombat: 1 - }, "runeForgesort_énergie", "a déjà utilisé sa rune d'énergie durant ce combat", evt)) { + limiteParCombat: { + val: 1 + } + }, "runeForgesort_\xE9nergie", "a d\xE9j\xE0 utilis\xE9 sa rune d'\xE9nergie durant ce combat", evt)) { addEvent(evt); return false; } - sendPerso(perso, "utilise sa rune d'énergie pour relancer un d20 sur un test d'attaque, de FOR, DEX ou CON"); + sendPerso(perso, "utilise sa rune d'\xE9nergie pour relancer un d20 sur un test d'attaque, de FOR, DEX ou CON"); return true; } //!cof-bouton-rune-energie function runeEnergie(msg) { if (!stateCOF.combat) { - sendPlayer(msg, "On ne peut utiliser les runes d'énergie qu'en combat"); + sendPlayer(msg, "On ne peut utiliser les runes d'\xE9nergie qu'en combat"); return; } let cmd = msg.content.split(' '); let evtARefaire; const evt = { - type: "Rune d'énergie", + type: "Rune d'\xE9nergie", attributes: [] }; - if (cmd.length > 1) { //On relance pour un événement particulier + if (cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; @@ -25055,7 +25383,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 2) { let roll = action.rolls[cmd[2]]; if (roll === undefined) { - error("Erreur interne du bouton de chance : roll non identifié", cmd); + error("Erreur interne du bouton de chance : roll non identifi\xE9", cmd); return; } if (roll.token === undefined) { @@ -25067,7 +25395,7 @@ var COFantasy = COFantasy || function() { evt.rollId = rollId; } if (perso === undefined) { - error("Erreur interne du bouton de rune d'énergie : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton de rune d'\xE9nergie : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -25076,7 +25404,7 @@ var COFantasy = COFantasy || function() { } let carac = action.caracteristque; if (carac == 'SAG' || carac == 'INT' || carac == 'CHA') { - sendPerso(perso, "ne peut pas utiliser la rune d'énergie pour un test " + deCarac(carac)); + sendPerso(perso, "ne peut pas utiliser la rune d'\xE9nergie pour un test " + deCarac(carac)); return; } if (!persoUtiliseRuneEnergie(perso, evt)) return; @@ -25085,11 +25413,11 @@ var COFantasy = COFantasy || function() { if (rollId) delete action.rolls[rollId]; else if (action.rolls && action.rolls.attack) delete action.rolls.attack; if (!redoEvent(evtARefaire, action, perso)) - error("Type d'évènement pas supporté par le bouton Rune d'Energie", evt); - } else { //Juste pour vérifier l'attribut et le diminuer + error("Type d'\xE9v\xE8nement pas support\xE9 par le bouton Rune d'Energie", evt); + } else { //Juste pour v\xE9rifier l'attribut et le diminuer getSelected(msg, function(selection) { if (selection.length === 0) { - sendPlayer(msg, 'Pas de token sélectionné pour !cof-rune-energie'); + sendPlayer(msg, 'Pas de token s\xE9lectionn\xE9 pour !cof-rune-energie'); return; } iterSelected(selection, function(perso) { @@ -25104,7 +25432,7 @@ var COFantasy = COFantasy || function() { let attrName = permanent ? 'runeDePuissance' + labelArme : "runeForgesort_puissance(" + labelArme + ")"; let arme = getAttackName(labelArme, perso); if (arme === undefined) { - error(perso.tokNname + " n'a pas d'arme associée au label " + labelArme, perso); + error(perso.tokNname + " n'a pas d'arme associ\xE9e au label " + labelArme, perso); return false; } if (!permanent && tokenAttribute(perso, attrName).length === 0) { @@ -25112,8 +25440,10 @@ var COFantasy = COFantasy || function() { return false; } if (limiteRessources(perso, { - limiteParCombat: 1 - }, attrName, "a déjà utilisé sa rune de puissance durant ce combat", evt)) { + limiteParCombat: { + val: 1 + } + }, attrName, "a d\xE9j\xE0 utilis\xE9 sa rune de puissance durant ce combat", evt)) { addEvent(evt); return false; } @@ -25130,7 +25460,7 @@ var COFantasy = COFantasy || function() { } let cmd = msg.content.split(' '); if (cmd.length < 2) { - error("Il faut spécifier le label de l'arme sur laquelle la rune de puissance est inscrite", cmd); + error("Il faut sp\xE9cifier le label de l'arme sur laquelle la rune de puissance est inscrite", cmd); return; } let labelArme = cmd[1]; @@ -25139,15 +25469,15 @@ var COFantasy = COFantasy || function() { type: "Rune de puissance", attributes: [] }; - if (cmd.length > 2) { //On relance pour un événement particulier + if (cmd.length > 2) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[2]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; if (perso === undefined) { - error("Erreur interne du bouton de rune de puissance : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton de rune de puissance : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -25180,10 +25510,10 @@ var COFantasy = COFantasy || function() { default: return; } - } else { //Juste pour vérifier l'attribut et le diminuer + } else { //Juste pour v\xE9rifier l'attribut et le diminuer getSelected(msg, function(selection, playerId) { if (selection.length === 0) { - sendPlayer(msg, 'Pas de token sélectionné pour !cof-rune-puissance', playerId); + sendPlayer(msg, 'Pas de token s\xE9lectionn\xE9 pour !cof-rune-puissance', playerId); return; } iterSelected(selection, function(perso) { @@ -25207,12 +25537,12 @@ var COFantasy = COFantasy || function() { } let evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; if (perso === undefined) { - error("Erreur interne du bouton de kiai : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton de kiai : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -25254,7 +25584,7 @@ var COFantasy = COFantasy || function() { } } - //Devrait être appelé seulement depuis un bouton + //Devrait \xEAtre appel\xE9 seulement depuis un bouton //!cof-esquive-fatale evtid target_id function doEsquiveFatale(msg) { let cmd = msg.content.split(' '); @@ -25264,12 +25594,12 @@ var COFantasy = COFantasy || function() { attributes: [] }; if (cmd.length < 3) { - error("Il manque des arguments à !cof-esquive-fatale", cmd); + error("Il manque des arguments \xE0 !cof-esquive-fatale", cmd); return; } evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'attaque est trop ancienne ou a été annulée", cmd); + error("L'attaque est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let action = evtARefaire.action; @@ -25279,7 +25609,7 @@ var COFantasy = COFantasy || function() { } let perso = action.cibles[0]; if (perso === undefined) { - error("Erreur interne du bouton de 'esquive fatale : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton de 'esquive fatale : l'\xE9venement n'a pas de personnage", evtARefaire); return; } let adversaire = persoOfId(cmd[2]); @@ -25298,7 +25628,7 @@ var COFantasy = COFantasy || function() { } let ennemisAuContact = perso.ennemisAuContact; if (ennemisAuContact === undefined) { - error("Ennemis au contact non définis", perso); + error("Ennemis au contact non d\xE9finis", perso); } else { let i = ennemisAuContact.find(function(tok) { return (tok.id == adversaire.token.id); @@ -25312,12 +25642,12 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "pas le droit d'utiliser ce bouton"); return; } - let testEsquiveFatale = testLimiteUtilisationsCapa(perso, 'esquiveFatale', 'combat', "a déjà fait une esquive fatale durant ce combat", "ne sait pas faire d'esquive fatale"); + let testEsquiveFatale = testLimiteUtilisationsCapa(perso, 'esquiveFatale', 'combat', "a d\xE9j\xE0 fait une esquive fatale durant ce combat", "ne sait pas faire d'esquive fatale"); if (testEsquiveFatale === undefined) { return; } utiliseCapacite(perso, testEsquiveFatale, evt); - //On va refaire complètement l'attaque + //On va refaire compl\xE8tement l'attaque undoEvent(evtARefaire); addEvent(evt); adversaire.msgEsquiveFatale = nomPerso(perso) + " esquive l'attaque qui touche " + nomPerso(adversaire); @@ -25327,21 +25657,21 @@ var COFantasy = COFantasy || function() { redoEvent(evtARefaire, action); } - //Soit juste !cof-intercepter (en sélectionnant le chevalier) + //Soit juste !cof-intercepter (en s\xE9lectionnant le chevalier) //Soit depuis un bouton !cof-intercepter evtid cibleid function intercepter(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } let fromEvtId; if (cmd.length > 1) { fromEvtId = cmd[1]; //Appel depuis le bouton if (cmd.length < 3) { - error("Bouton d'interception mal formé", cmd); + error("Bouton d'interception mal form\xE9", cmd); return; } } @@ -25349,10 +25679,10 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(chevalier) { let character = getObj('character', chevalier.charId); if (character === undefined) { - error("L'argument de !cof-intercepter n'est pas une id de token valide (personnage non défini)", msg.content); + error("L'argument de !cof-intercepter n'est pas une id de token valide (personnage non d\xE9fini)", msg.content); return; } - let test = testLimiteUtilisationsCapa(chevalier, 'intercepter', 'tour', "a déjà intercepté une attaque ce tour", "ne sait pas utiliser intercepter les attaques"); + let test = testLimiteUtilisationsCapa(chevalier, 'intercepter', 'tour', "a d\xE9j\xE0 intercept\xE9 une attaque ce tour", "ne sait pas utiliser intercepter les attaques"); if (test === undefined) { return; } @@ -25360,7 +25690,7 @@ var COFantasy = COFantasy || function() { let attaque; let originalTarget; let evtARefaire; - if (fromEvtId) { //On a utilisé un bouton + if (fromEvtId) { //On a utilis\xE9 un bouton if (!peutController(msg, chevalier)) { sendPlayer(msg, "pas le droit d'utiliser ce bouton"); return; @@ -25394,15 +25724,15 @@ var COFantasy = COFantasy || function() { attaque = evtARefaire.action; } if (attaque === undefined) { - sendPlayer(msg, "La dernière action trouvée n'est pas une attaque, impossible d'intercepter"); + sendPlayer(msg, "La derni\xE8re action trouv\xE9e n'est pas une attaque, impossible d'intercepter"); return; } if (attaque.cibles.length === 0) { - sendPlayer(msg, "la dernière attaque n'a touché aucune cible, impossible d'intercepter"); + sendPlayer(msg, "la derni\xE8re attaque n'a touch\xE9 aucune cible, impossible d'intercepter"); return; } if (attaque.cibles.length > 1) { - sendPlayer(msg, "la dernière attaque a touché plus d'une cible, impossible d'intercepter"); + sendPlayer(msg, "la derni\xE8re attaque a touch\xE9 plus d'une cible, impossible d'intercepter"); return; } originalTarget = attaque.cibles[0]; @@ -25426,22 +25756,22 @@ var COFantasy = COFantasy || function() { removePreDmg(attaque.options, originalTarget); redoEvent(evtARefaire, attaque); }); - }); + }, options); } - //simplement prendre les DM à la place d'un autre + //simplement prendre les DM \xE0 la place d'un autre function interposer(msg) { getSelected(msg, function(selected, playerId) { iterSelected(selected, function(cible) { let charId = cible.charId; let character = getObj('character', charId); if (character === undefined) { - error("L'argument de !cof-interposer n'est pas une id de token valide (personnage non défini)", msg.content); + error("L'argument de !cof-interposer n'est pas une id de token valide (personnage non d\xE9fini)", msg.content); return; } cible.name = character.get('name'); //TODO: utile ? if (attributeAsBool(cible, 'interposer')) { - sendPerso(cible, " a déjà intercepté une attaque ce tour"); + sendPerso(cible, " a d\xE9j\xE0 intercept\xE9 une attaque ce tour"); return; } let attaque; @@ -25450,20 +25780,20 @@ var COFantasy = COFantasy || function() { attaque = lastAct.action; } if (attaque === undefined) { - sendPlayer(msg, "la dernière action trouvée n'est pas une attaque, impossible d'intercepter"); + sendPlayer(msg, "la derni\xE8re action trouv\xE9e n'est pas une attaque, impossible d'intercepter"); return; } if (attaque.cibles.length === 0) { - sendPlayer(msg, "la dernière attaque n'a touché aucune cible, impossible de s'interposer"); + sendPlayer(msg, "la derni\xE8re attaque n'a touch\xE9 aucune cible, impossible de s'interposer"); return; } if (attaque.cibles.length > 1) { - sendPlayer(msg, "la dernière attaque a touché plus d'une cible, impossible de s'interposer en utilisant le script"); + sendPlayer(msg, "la derni\xE8re attaque a touch\xE9 plus d'une cible, impossible de s'interposer en utilisant le script"); return; } let target = attaque.cibles[0]; if (target === undefined) { - error("Le token de la dernière attaque est indéfini", attaque); + error("Le token de la derni\xE8re attaque est ind\xE9fini", attaque); return; } let targetName = nomPerso(target); @@ -25480,7 +25810,7 @@ var COFantasy = COFantasy || function() { let pvApres = target.token.get('bar1_value'); // On annule l'ancienne action undoEvent(); - // On calcule ensuite les pv perdus, et on les applique au défenseur + // On calcule ensuite les pv perdus, et on les applique au d\xE9fenseur let pvPerdus = target.token.get('bar1_value') - pvApres; // Puis on refait en changeant la cible let options = attaque.options; @@ -25498,7 +25828,7 @@ var COFantasy = COFantasy || function() { getSelected(msg, function(selected, playerId) { iterSelected(selected, function(cible) { if (attributeAsBool(cible, 'exemplaire')) { - sendPerso(cible, " a déjà montré l'exemple à ce tour"); + sendPerso(cible, " a d\xE9j\xE0 montr\xE9 l'exemple \xE0 ce tour"); return; } let attaque; @@ -25509,20 +25839,20 @@ var COFantasy = COFantasy || function() { } } if (attaque === undefined) { - sendPlayer(msg, "la dernière action trouvée n'est pas une attaque ratée, impossible de montrer l'exemple", + sendPlayer(msg, "la derni\xE8re action trouv\xE9e n'est pas une attaque rat\xE9e, impossible de montrer l'exemple", playerId); return; } let attackerName = nomPerso(attaque.attaquant); if (attackerName === undefined) { - error("Le token de la dernière attaque est indéfini", attaque); + error("Le token de la derni\xE8re attaque est ind\xE9fini", attaque); return; } const evt = { type: "Montrer l'exemple" }; setTokenAttr(cible, 'exemplaire', true, evt, { - msg: "montre l'exemple à " + attackerName + msg: "montre l'exemple \xE0 " + attackerName }); // On annule l'ancienne action undoEvent(); @@ -25545,16 +25875,16 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2 || (cmd[1] != "rate" && cmd[1] != "touche")) { - error("Il manque l'option rate ou touche à Intervention Divine", msg); + error("Il manque l'option rate ou touche \xE0 Intervention Divine", msg); return; } getSelected(msg, function(selected) { iterSelected(selected, function(pretre) { - let testIntervention = testLimiteUtilisationsCapa(pretre, 'interventionDivine', 'combat', "a déjà fait une intervention divine ce combat", "ne sait pas faire d'intervention divine"); + let testIntervention = testLimiteUtilisationsCapa(pretre, 'interventionDivine', 'combat', "a d\xE9j\xE0 fait une intervention divine ce combat", "ne sait pas faire d'intervention divine"); if (testIntervention === undefined) { return; } @@ -25589,12 +25919,12 @@ var COFantasy = COFantasy || function() { attack(action.playerName, action.playerId, action.attaquant, action.cibles, action.weaponStats, optionsRedo); return; }); - }); + }, options); } - //!cof-petit-veinard (avec un token sélectionné) + //!cof-petit-veinard (avec un token s\xE9lectionn\xE9) //!cof-bouton-petit-veinard evtid - //sans argument, diminue juste l'attribut, sinon relance l'événement + //sans argument, diminue juste l'attribut, sinon relance l'\xE9v\xE9nement function petitVeinard(msg) { if (!stateCOF.combat) { sendPlayer(msg, "On ne peut utiliser petit veinard qu'en combat"); @@ -25604,7 +25934,7 @@ var COFantasy = COFantasy || function() { if (msgOptions === undefined) return; let cmd = msgOptions.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } let evtARefaire; @@ -25612,22 +25942,22 @@ var COFantasy = COFantasy || function() { type: "Petit veinard", attributes: [] }; - if (cmd.length > 1) { //On relance pour un événement particulier + if (cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; let rollId; if (cmd.length > 2) { if (!evtARefaire.action) { - error("Le dernier évènement n'est pas une action", msg.content); + error("Le dernier \xE9v\xE8nement n'est pas une action", msg.content); return; } let roll = evtARefaire.action.rolls[cmd[2]]; if (roll === undefined) { - error("Erreur interne du bouton de chance : roll non identifié", msg.content); + error("Erreur interne du bouton de chance : roll non identifi\xE9", msg.content); return; } if (roll.token === undefined) { @@ -25638,7 +25968,7 @@ var COFantasy = COFantasy || function() { rollId = cmd[2]; } if (perso === undefined) { - error("Erreur interne du bouton petit veinard : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton petit veinard : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -25650,7 +25980,7 @@ var COFantasy = COFantasy || function() { error("Impossible de relancer l'action", evtARefaire); return; } - let testPetitVeinard = testLimiteUtilisationsCapa(perso, 'petitVeinard', 'combat', "a déjà tenté sa chance pour ce combat", "n'est pas un petit veinard"); + let testPetitVeinard = testLimiteUtilisationsCapa(perso, 'petitVeinard', 'combat', "a d\xE9j\xE0 tent\xE9 sa chance pour ce combat", "n'est pas un petit veinard"); if (testPetitVeinard === undefined) { return; } @@ -25660,19 +25990,19 @@ var COFantasy = COFantasy || function() { if (rollId) delete action.rolls[rollId]; else if (action.rolls && action.rolls.attack) delete action.rolls.attack; if (!redoEvent(evtARefaire, action, perso)) - error("Type d'évènement pas supporté par le bouton Petit Veinard", evt); - } else { //Juste pour vérifier l'attribut et le diminuer + error("Type d'\xE9v\xE8nement pas support\xE9 par le bouton Petit Veinard", evt); + } else { //Juste pour v\xE9rifier l'attribut et le diminuer getSelected(msg, function(selection, playerId) { if (selection.length === 0) { - sendPlayer(msg, 'Pas de token sélectionné pour !cof-petit-veinard', playerId); + sendPlayer(msg, 'Pas de token s\xE9lectionn\xE9 pour !cof-petit-veinard', playerId); return; } iterSelected(selection, function(perso) { - let testPetitVeinard = testLimiteUtilisationsCapa(perso, 'petitVeinard', 'combat', "a déjà tenté sa chance pour ce combat", "n'est pas un petit veinard"); + let testPetitVeinard = testLimiteUtilisationsCapa(perso, 'petitVeinard', 'combat', "a d\xE9j\xE0 tent\xE9 sa chance pour ce combat", "n'est pas un petit veinard"); if (testPetitVeinard === undefined) { return; } - sendPerso(perso, "peut relancer un dé"); + sendPerso(perso, "peut relancer un d\xE9"); utiliseCapacite(perso, testPetitVeinard, evt); }); //fin iterSelected addEvent(evt); @@ -25685,7 +26015,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } let testSurprise; @@ -25697,8 +26027,8 @@ var COFantasy = COFantasy || function() { let ciblesSelectionnees; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "!cof-surprise sans sélection de token", playerId); - log("!cof-surprise requiert de sélectionner des tokens"); + sendPlayer(msg, "!cof-surprise sans s\xE9lection de token", playerId); + log("!cof-surprise requiert de s\xE9lectionner des tokens"); return; } ciblesSelectionnees = selected; @@ -25708,11 +26038,11 @@ var COFantasy = COFantasy || function() { } cibles.push(perso); }); - }); + }, options); if (cibles.length > 0) { doSurprise(cibles, testSurprise, ciblesSelectionnees, options); } else { - error("Pas de cible valable sélectionnée pour la surprise", msg.content); + error("Pas de cible valable s\xE9lectionn\xE9e pour la surprise", msg.content); } } @@ -25735,7 +26065,7 @@ var COFantasy = COFantasy || function() { if (testSurprise === undefined) { display = startFramedDisplay(options.playerId, "Surprise !"); } else { - display = startFramedDisplay(options.playerId, "Test de surprise difficulté " + testSurprise); + display = startFramedDisplay(options.playerId, "Test de surprise difficult\xE9 " + testSurprise); } let tokensToProcess = cibles.length; let sendEvent = function() { @@ -25756,12 +26086,12 @@ var COFantasy = COFantasy || function() { if (compagnonPresent(perso, 'surveillance')) { bonusSurprise += 5; setTokenAttr(perso, 'bonusInitEmbuscade', 5, evt); - bonusMessages.push(name + " garde un temps d'avance grâce à son compagnon animal : +5"); + bonusMessages.push(name + " garde un temps d'avance gr\xE2ce \xE0 son compagnon animal : +5"); initPerso(perso, evt, true); } if (attributeAsBool(perso, 'sixiemeSens')) { bonusSurprise += 5; - bonusMessages.push(name + " a un sixième sens : +5"); + bonusMessages.push(name + " a un sixi\xE8me sens : +5"); } if (testSurprise !== undefined) { let testId = 'surprise_' + perso.token.id; @@ -25774,9 +26104,9 @@ var COFantasy = COFantasy || function() { testCaracteristique(perso, 'SAG', testSurprise, testId, optionsTest, evt, function(tr, explications) { let result; - if (tr.reussite) result = "réussi." + tr.modifiers; + if (tr.reussite) result = "r\xE9ussi." + tr.modifiers; else { - result = "raté, " + name + " est surpris"; + result = "rat\xE9, " + name + " est surpris"; result += eForFemale(perso); result += tr.rerolls + tr.modifiers; setState(perso, 'surpris', true, evt); @@ -25799,7 +26129,7 @@ var COFantasy = COFantasy || function() { }); } - function interchangeable(attackingToken, target, pageId) { //détermine si il y a assez de tokens + function interchangeable(attackingToken, target, pageId) { //d\xE9termine si il y a assez de tokens let token = target.token; let res = { result: false, @@ -25827,7 +26157,7 @@ var COFantasy = COFantasy || function() { let d = distanceCombat(attackingToken, tok); return (d === 0); }); - } else { // cible à distance, on garde celles au contact de la cible + } else { // cible \xE0 distance, on garde celles au contact de la cible res.targets = tokens.filter(function(tok) { let d = distanceCombat(token, tok); return (d === 0); @@ -25837,6 +26167,7 @@ var COFantasy = COFantasy || function() { } let alliesParPerso = {}; + let alliesDAttaqueEnMeute = new Set(); let listeCompetences = { FOR: { list: [], @@ -25864,21 +26195,26 @@ var COFantasy = COFantasy || function() { }, nombre: 0 }; - // Appelé uniquement après le "ready" et lorsqu'on modifie un handout (fonctionne après l'ajout et la destruction d'un handout) - // Du coup, alliesParPerso est toujours à jour + + function recomputeAllies() { + const handouts = findObjs({ + _type: 'handout' + }); + alliesParPerso = {}; + alliesDAttaqueEnMeute = new Set(); + handouts.forEach(parseHandout); + } + // Appel\xE9 uniquement apr\xE8s le "ready" et lorsqu'on modifie un handout (fonctionne apr\xE8s l'ajout et la destruction d'un handout) + // Du coup, alliesParPerso est toujours \xE0 jour function changeHandout(hand, prev) { if (prev && prev.name && prev.name.startsWith("Equipe ")) { - const handouts = findObjs({ - _type: 'handout' - }); - alliesParPerso = {}; - handouts.forEach(parseHandout); + recomputeAllies(); } else if (hand) { parseHandout(hand); } } - //pour se débarasser des balises html + //pour se d\xE9barasser des balises html // et avoir un tableau de lignes function linesOfNote(note) { note = note.trim(); @@ -25903,7 +26239,7 @@ var COFantasy = COFantasy || function() { return c.get('name').trim() == name; }); if (charsWithName.length === 0) { - log(name + " dans l'équipe " + nomEquipe + " est inconnu"); + log(name + " dans l'\xE9quipe " + nomEquipe + " est inconnu"); return; } if (charsWithName.length > 1) { @@ -25912,7 +26248,7 @@ var COFantasy = COFantasy || function() { }); if (nonArch.length > 0) charsWithName = nonArch; if (charsWithName.length > 1) { - log(name + " dans l'équipe " + nomEquipe + " est en double"); + log(name + " dans l'\xE9quipe " + nomEquipe + " est en double"); } } charsWithName.forEach(function(character) { @@ -25927,7 +26263,9 @@ var COFantasy = COFantasy || function() { if (handName.startsWith("Equipe ")) { hand.get('notes', function(note) { // asynchronous const persos = charactersInHandout(note, handName); + let attaqueEnMeute = false; persos.forEach(function(charId) { + attaqueEnMeute = attaqueEnMeute || charPredicateAsBool(charId, 'attaqueEnMeute'); let ancien = alliesParPerso[charId]; if (ancien === undefined) { ancien = new Set(); @@ -25939,8 +26277,13 @@ var COFantasy = COFantasy || function() { }); //On ajoute les familiers }); + if (attaqueEnMeute) { + persos.forEach(function(charId) { + alliesDAttaqueEnMeute.add(charId); + }); + } }); //end hand.get('notes') - } else if (handName == 'Compétences' || handName == 'Competences') { + } else if (handName == 'Comp\xE9tences' || handName == 'Competences') { listeCompetences = { FOR: { list: [], @@ -25969,7 +26312,7 @@ var COFantasy = COFantasy || function() { nombre: 0 }; hand.get('notes', function(note) { // asynchronous - let carac; //La carac dont on spécifie les compétences actuellement + let carac; //La carac dont on sp\xE9cifie les comp\xE9tences actuellement let lignes = linesOfNote(note); lignes.forEach(function(ligne) { ligne = ligne.trim(); @@ -25982,7 +26325,7 @@ var COFantasy = COFantasy || function() { } if (ligne.length === 0) return; if (carac === undefined) { - error("Compétences sans caractéristique associée", note); + error("Comp\xE9tences sans caract\xE9ristique associ\xE9e", note); return; } let comps = ligne.split(/, |\/| /); @@ -26018,7 +26361,7 @@ var COFantasy = COFantasy || function() { } //options peut contenir: - // - ligneOptions : une chaîne de caractères à ajouter aux attaques + // - ligneOptions : une cha\xEEne de caract\xE8res \xE0 ajouter aux attaques // - target : l'id de la cible des attaques // - nePasAfficherArmes : quand on affiche plus tard l'arme en main function listeAttaquesVisibles(perso, options) { @@ -26026,7 +26369,7 @@ var COFantasy = COFantasy || function() { let ligneOptions = options.ligneOptions || ''; let target = options.target || '@{target|token_id}'; let ligne = ''; - //Cherche toutes les attaques à afficher + //Cherche toutes les attaques \xE0 afficher let attaques = listAllAttacks(perso); let attaquesTriees = []; let attaquesNonTriees = {}; @@ -26034,7 +26377,7 @@ var COFantasy = COFantasy || function() { let att = attaques[attLabel]; if (fieldAsInt(att, 'armeactionvisible', 1) === 0) continue; if (options.nePasAfficherArmes && estArme(att)) continue; - //Vérification que des options n'empêchent pas l'utilisation de l'attaque + //V\xE9rification que des options n'emp\xEAchent pas l'utilisation de l'attaque let attackOptions = ' ' + fieldAsString(att, 'armeoptions', ''); if (actionImpossible(perso, attackOptions.split(' --'), attLabel)) continue; //On regarde aussi si c'est une arme de jet @@ -26053,14 +26396,14 @@ var COFantasy = COFantasy || function() { for (let label in attaquesNonTriees) { ligne += attaquesNonTriees[label] + '
'; } - //On ajoute aussi les lancers de feu grégeois, si il y en a - let attrFeuxGregeois = tokenAttribute(perso, 'elixir_feu_grégeois'); + //On ajoute aussi les lancers de feu gr\xE9geois, si il y en a + let attrFeuxGregeois = tokenAttribute(perso, 'elixir_feu_gr\xE9geois'); if (attrFeuxGregeois.length > 0) { attrFeuxGregeois = attrFeuxGregeois[0]; let feuxGregeois = parseInt(attrFeuxGregeois.get('current')); if (feuxGregeois > 0) { let command = attrFeuxGregeois.get('max').trim(); - ligne += bouton(command, 'Feu grégeois', perso, { + ligne += bouton(command, 'Feu gr\xE9geois', perso, { ressource: attrFeuxGregeois }); ligne += " (reste " + feuxGregeois + ")
"; @@ -26123,13 +26466,13 @@ var COFantasy = COFantasy || function() { return res; } - //Si listActions est fourni, ça peut faire référence à une ability + //Si listActions est fourni, \xE7a peut faire r\xE9f\xE9rence \xE0 une ability //dont le nom commence et termine par #, contenant une liste d'actions - //à afficher - //sinon, fait référence à une des listes d'action de la fiche + //\xE0 afficher + //sinon, fait r\xE9f\xE9rence \xE0 une des listes d'action de la fiche function turnAction(perso, playerId, listActions) { const pageId = perso.token.get('pageid'); - // Toutes les Abilities du personnage lié au Token + // Toutes les Abilities du personnage li\xE9 au Token const abilities = findObjs({ _type: 'ability', _characterid: perso.charId, @@ -26156,7 +26499,7 @@ var COFantasy = COFantasy || function() { if (actionsDuTour === 0) { if (!isActive(perso)) { if (!getState(perso, 'surpris') || !compagnonPresent(perso, 'surveillance')) { - sendPerso(perso, "ne peut pas agir à ce tour"); + sendPerso(perso, "ne peut pas agir \xE0 ce tour"); return true; } } @@ -26172,23 +26515,23 @@ var COFantasy = COFantasy || function() { } } } - //actionDuTour peut être undefined, pour la liste par défaut + //actionDuTour peut \xEAtre undefined, pour la liste par d\xE9faut let actionsAAfficher; let ligne = ''; let command = ''; if (actionsParDefaut && !stateCOF.chargeFantastique && attributeAsBool(perso, 'hate')) { - ligne += "Effet de hâte : une action d'attaque ou de mouvement en plus
"; + ligne += "Effet de h\xE2te : une action d'attaque ou de mouvement en plus
"; } if (actionsParDefaut && !stateCOF.chargeFantastique && attributeAsBool(perso, 'reactionViolente')) { - ligne += "Crise de folie : doit attaquer la personne qui l'a provoqué et ceux qui l'en empêchent.
"; + ligne += "Crise de folie : doit attaquer la personne qui l'a provoqu\xE9 et ceux qui l'en emp\xEAchent.
"; ligne += boutonSimple('!cof-fin-reaction-violente ' + perso.token.id, "Prendre sur soi"); } - //Les dégâts aux personnages enveloppés par perso + //Les d\xE9g\xE2ts aux personnages envelopp\xE9s par perso let attrs_enveloppe = tokenAttribute(perso, 'enveloppe'); attrs_enveloppe.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); if (cible === undefined) { - error("Attribut d'enveloppe mal formé ou obsolète", a.get('current')); + error("Attribut d'enveloppe mal form\xE9 ou obsol\xE8te", a.get('current')); a.remove(); return; } @@ -26202,23 +26545,23 @@ var COFantasy = COFantasy || function() { command = abEnveloppe.get('action').trim(); command = replaceAction(command, perso); command = command.replace(new RegExp(escapeRegExp('@{target|token_id}'), 'g'), cible.token.id); - ligne += bouton(command, "Infliger DMS à " + nomPerso(cible), perso) + '
'; + ligne += bouton(command, "Infliger DMS \xE0 " + nomPerso(cible), perso) + '
'; } } else if (enveloppeDM.startsWith('label ')) { actionsAAfficher = true; command = '!cof-attack ' + perso.token.id + ' ' + cible.token.id + ' ' + enveloppeDM.substring(6) + ' --auto --acide --effet paralyseTemp [[2d6]] --save CON 15'; - ligne += bouton(command, "Infliger DMs à " + nomPerso(cible), perso) + '
'; + ligne += bouton(command, "Infliger DMs \xE0 " + nomPerso(cible), perso) + '
'; } else if (enveloppeDM.startsWith('etreinte ')) { actionsAAfficher = true; enveloppeDM = enveloppeDM.substring(9); - command = '!cof-attack ' + perso.token.id + ' ' + cible.token.id + ' --dm ' + enveloppeDM + ' --auto --nom étreinte '; - ligne += bouton(command, "Infliger DMs à " + nomPerso(cible), perso) + '
'; + command = '!cof-attack ' + perso.token.id + ' ' + cible.token.id + ' --dm ' + enveloppeDM + ' --auto --nom \xE9treinte '; + ligne += bouton(command, "Infliger DMs \xE0 " + nomPerso(cible), perso) + '
'; } //else pas reconnu - //On ajoute aussi un bouton pour libérer + //On ajoute aussi un bouton pour lib\xE9rer command = '!cof-echapper-enveloppement libere --target ' + cible.token.id; - ligne += boutonSimple(command, "Libérer " + nomPerso(cible)) + '
'; + ligne += boutonSimple(command, "Lib\xE9rer " + nomPerso(cible)) + '
'; }); - //Bouton pour libérer une personne qu'on agrippe + //Bouton pour lib\xE9rer une personne qu'on agrippe let attrs_agrippe = tokenAttribute(perso, 'agrippe'); attrs_agrippe = attrs_agrippe.concat( @@ -26232,7 +26575,7 @@ var COFantasy = COFantasy || function() { return; } command = '!cof-liberer-agrippe ' + cible.token.id + ' libere'; - ligne += boutonSimple(command, "Libérer " + nomPerso(cible)) + '
'; + ligne += boutonSimple(command, "Lib\xE9rer " + nomPerso(cible)) + '
'; }); let gobePar; let attrGobePar = tokenAttribute(perso, 'estGobePar'); @@ -26245,18 +26588,18 @@ var COFantasy = COFantasy || function() { if (!gobePar && attributeAsBool(perso, 'enveloppePar')) { actionsAAfficher = true; command = '!cof-echapper-enveloppement --target ' + perso.token.id; - ligne += boutonSimple(command, 'Se libérer') + '
'; + ligne += boutonSimple(command, 'Se lib\xE9rer') + '
'; } else if (getState(perso, 'enseveli')) { actionsAAfficher = true; ligne += boutonSaveState(perso, 'enseveli') + '
'; } else if (!gobePar && attributeAsBool(perso, 'etreinteScorpionPar')) { actionsAAfficher = true; command = '!cof-liberer-agrippe ' + perso.token.id; - ligne += boutonSimple(command, 'Se libérer') + "de l'étreinte du scorpion
"; + ligne += boutonSimple(command, 'Se lib\xE9rer') + "de l'\xE9treinte du scorpion
"; } else if (!gobePar && attributeAsBool(perso, 'estEcrasePar')) { actionsAAfficher = true; command = '!cof-liberer-ecrase ' + perso.token.id; - ligne += boutonSimple(command, 'Se libérer') + "de l'étreinte
"; + ligne += boutonSimple(command, 'Se lib\xE9rer') + "de l'\xE9treinte
"; } else { //On affiche les actions normales if (stateCOF.combat && stateCOF.combat.armeesDesMorts && !gobePar) { let combattreArmee = false; @@ -26264,7 +26607,7 @@ var COFantasy = COFantasy || function() { if (aid == perso.token.id) continue; let persoArmee = stateCOF.combat.armeesDesMorts[aid]; if (!persoArmee || !persoArmee.token) { - error("Erreur dans l'armée des morts", stateCOF.combat.armeesDesMorts); + error("Erreur dans l'arm\xE9e des morts", stateCOF.combat.armeesDesMorts); delete stateCOF.combat.armeesDesMorts[aid]; continue; } @@ -26286,12 +26629,12 @@ var COFantasy = COFantasy || function() { if (!gobePar && (attributeAsBool(perso, 'estAgrippePar') || attributeAsBool(perso, 'estDevorePar'))) { actionsAAfficher = true; command = '!cof-liberer-agrippe ' + perso.token.id; - ligne += bouton(command, 'Se libérer', perso) + '(action de mvt)
'; + ligne += bouton(command, 'Se lib\xE9rer', perso) + '(action de mvt)
'; } if (!gobePar && attributeAsBool(perso, 'etreinteImmolePar')) { actionsAAfficher = true; command = '!cof-liberer-agrippe ' + perso.token.id; - ligne += bouton(command, 'Se libérer', perso) + ' (action limitée)
'; + ligne += bouton(command, 'Se lib\xE9rer', perso) + ' (action limit\xE9e)
'; } //Actions pour les saves actifs let attrs = findObjs({ @@ -26330,7 +26673,7 @@ var COFantasy = COFantasy || function() { let cible = persoOfIdName(a.get('current')); if (cible) { let commande = "!cof-attack " + perso.token.id + ' ' + cible.token.id + ' ' + ecraser; - ligne += boutonSimple(commande, 'Écraser') + ' ' + nomPerso(cible) + '
'; + ligne += boutonSimple(commande, '\xC9craser') + ' ' + nomPerso(cible) + '
'; } else { a.remove(); } @@ -26359,7 +26702,7 @@ var COFantasy = COFantasy || function() { c = command + " Morsure --toucher " + atk + " --dm 1d6+" + force; ligne += bouton(c, 'Morsure', perso) + '
'; } - //On cherche si il y a une armée conjurée à attaquer + //On cherche si il y a une arm\xE9e conjur\xE9e \xE0 attaquer let attrs_armee = findObjs({ _type: 'attribute', @@ -26394,42 +26737,42 @@ var COFantasy = COFantasy || function() { if (allies.has(perso.charId)) return; allTokens.forEach(function(t) { if (t.get('represents') == aacid) { - //teste si dans un carré de 20 m de coté autour de l'armée. + //teste si dans un carr\xE9 de 20 m de cot\xE9 autour de l'arm\xE9e. let tx = t.get('left'); let ty = t.get('top'); if (tx < pxp && tx > pxm && ty < pyp && ty > pym) { command = '!cof-attack ' + perso.token.id + ' ' + t.id + - " Attaque de l'armée --dm " + + " Attaque de l'arm\xE9e --dm " + (ficheAttributeAsInt(perso, 'niveau', 1) + 1) + " --auto --attaqueArmeeConjuree --allonge 20"; - ligne += bouton(command, "Attaque de l'armée", perso) + '
'; + ligne += bouton(command, "Attaque de l'arm\xE9e", perso) + '
'; } } }); }); } - //Les soins pour les élémentaires + //Les soins pour les \xE9l\xE9mentaires if (predicateAsBool(perso, 'corpsElementaire')) { command = '!cof-soin 5'; - ligne += bouton(command, "Régénération", perso) + " si source élémentaire proche
"; + ligne += bouton(command, "R\xE9g\xE9n\xE9ration", perso) + " si source \xE9l\xE9mentaire proche
"; } - //Regard pétrifiant + //Regard p\xE9trifiant let regardPetrifiant = predicateAsInt(perso, 'regardPetrifiant', 0, 16); if (regardPetrifiant) { let c = '!cof-effet petrifie --lanceur ' + perso.token.id + ' --target @{target|token_id} --regard --save CON '; - ligne += boutonSimple(c + (regardPetrifiant - 4), "Regard pétrifiant") + + ligne += boutonSimple(c + (regardPetrifiant - 4), "Regard p\xE9trifiant") + boutonSimple(c + regardPetrifiant, "(inconscient)") + '
'; } - //Violence ciblée + //Violence cibl\xE9e if (predicateAsBool(perso, 'violenceCiblee') && !attributeAsBool(perso, 'reactionViolente')) { let pointsDeViolence = attributeAsInt(perso, 'pointsDeViolence', 0); if (pointsDeViolence > 0) { let attr = tokenAttribute(perso, 'pointsDeViolence')[0]; command = "!cof-effet-temp reactionViolente [[1d4]] --decrAttribute " + attr.id + " --target " + perso.token.id; - ligne += boutonSimple(command, 'Violence ciblée') + '
'; + ligne += boutonSimple(command, 'Violence cibl\xE9e') + '
'; } } - //Les attaques de la fiche à afficher dans la liste d'actions + //Les attaques de la fiche \xE0 afficher dans la liste d'actions const montrerAttaques = ficheAttributeAsInt(perso, 'montrerattaques', 1); const afficherAttaquesFiche = actionsParDefaut || @@ -26442,7 +26785,7 @@ var COFantasy = COFantasy || function() { attackOptions.nePasAfficherArmes = true; ligne += listeAttaquesVisibles(perso, attackOptions); } - //L'arme en main et dégainer, si besoin + //L'arme en main et d\xE9gainer, si besoin if (montrerArmeEnMain && armesAutorisees) { let { listeAttaques, @@ -26473,7 +26816,7 @@ var COFantasy = COFantasy || function() { else nomCommande += ' (1M)'; } if (attributeAsBool(perso, 'paradeCroisee')) { - //On connaîtra vraiment l'arme au moment de faire l'attaque + //On conna\xEEtra vraiment l'arme au moment de faire l'attaque command += '-1'; if (labelArmeGauche && listeAttaques[labelArmeGauche]) { @@ -26482,6 +26825,7 @@ var COFantasy = COFantasy || function() { } } else { command += labelArmePrincipale; + if (armeDechargee(perso, armePrincipale)) nomCommande += ' (vide)'; } ligneArmePrincipale = bouton(command, nomCommande, perso); } else if (!possedeAttaqueNaturelle) { @@ -26493,13 +26837,15 @@ var COFantasy = COFantasy || function() { } } if (perso.armeGauche) { - ligneArmeGauche = bouton("!cof-attack @{selected|token_id} @{target|token_id} " + labelArmeGauche, perso.armeGauche.name, perso); + let nomCommande = perso.armeGauche.name; + if (armeDechargee(perso, perso.armeGauche)) nomCommande += ' (vide)'; + ligneArmeGauche = bouton("!cof-attack @{selected|token_id} @{target|token_id} " + labelArmeGauche, nomCommande, perso); } - //Maintenant on propose de dégainer + //Maintenant on propose de d\xE9gainer if (armeVisible) { let degainer = "!cof-degainer ?{Arme?|"; let armeADegainer; - //Prise en compte des prédicats pour ce qu'on veut voir en premier + //Prise en compte des pr\xE9dicats pour ce qu'on veut voir en premier let i = 1; let labelsVus = new Set(); while (true) { @@ -26513,12 +26859,12 @@ var COFantasy = COFantasy || function() { if (label == labelArmePrincipale || labelGauche == labelArmeGauche) continue; let arme = armes[label]; if (arme === undefined) { - error("Impossible de trouver l'arme de label " + label + " mentionnée dans le prédicat actionDegainer" + (i - 1), armes); + error("Impossible de trouver l'arme de label " + label + " mentionn\xE9e dans le pr\xE9dicat actionDegainer" + (i - 1), armes); continue; } let armeGauche = armes[labelGauche]; if (armeGauche === undefined) { - error("Impossible de trouver l'arme de label " + labelGauche + " mentionnée dans le prédicat actionDegainer" + (i - 1), armes); + error("Impossible de trouver l'arme de label " + labelGauche + " mentionn\xE9e dans le pr\xE9dicat actionDegainer" + (i - 1), armes); continue; } degainer += arme.armenom + " et " + armeGauche.armenom + "," + label + ' ' + labelGauche + "|"; @@ -26532,7 +26878,7 @@ var COFantasy = COFantasy || function() { if (labels == labelArmePrincipale || labels == labelArmeGauche) continue; let arme = armes[labels]; if (arme === undefined) { - error("Impossible de trouver l'arme de label " + labels + " mentionnée dans le prédicat actionDegainer" + (i - 1), armes); + error("Impossible de trouver l'arme de label " + labels + " mentionn\xE9e dans le pr\xE9dicat actionDegainer" + (i - 1), armes); continue; } labelsVus.add(labels); @@ -26562,9 +26908,13 @@ var COFantasy = COFantasy || function() { } else if (l != labelArmePrincipale && l != labelArmeGauche && !labelsVus.has(l)) { degainer += armes[l].armenom; let pred = armes[l].armepredicats; - if (pred && pred.includes('batarde')) { - degainer += " (2M)," + l + " 2mains|" + - armes[l].armenom + " (1M)"; + if (pred) { + if (pred.includes('batarde')) { + degainer += " (2M)," + l + " 2mains|" + + armes[l].armenom + " (1M)"; + } + if (pred.includes('charge') && attributeAsInt(perso, 'charge_' + l, 1) === 0) + degainer += ' (vide)'; } degainer += "," + l + "|"; if (armeADegainer) armeADegainer.unique = undefined; @@ -26584,7 +26934,7 @@ var COFantasy = COFantasy || function() { else degainer += "son arme"; degainer += ",&#32;}"; } else if (armeADegainer.unique) { - //Dans ce cas, pas de choix, juste une arme à dégainer + //Dans ce cas, pas de choix, juste une arme \xE0 d\xE9gainer degainer = '!cof-degainer ' + armeADegainer.label; } else { degainer = degainer.substr(0, degainer.length - 1) + '}'; @@ -26593,7 +26943,7 @@ var COFantasy = COFantasy || function() { if (ligneArmePrincipale) ligneArmePrincipale += bouton(degainer, ';', perso); else - ligneArmePrincipale = bouton(degainer, 'Dégainer', perso); + ligneArmePrincipale = bouton(degainer, 'D\xE9gainer', perso); if (armeADegainer.unique && !labelArmePrincipale && !labelArmeGauche) ligneArmePrincipale += armeADegainer.nom; } else { @@ -26602,6 +26952,13 @@ var COFantasy = COFantasy || function() { } if (ligneArmePrincipale) ligne += ligneArmePrincipale + '
'; if (ligneArmeGauche) ligne += ligneArmeGauche + '
'; + // Le tir de semonce, si disponible et qu'on tient une arme \xE0 distance + if (predicateAsBool(perso, 'tirDeSemonce') && armePrincipale && + armePrincipale.portee > 0 && + attributeAsInt(perso, 'attaqueADistanceRatee', 0) == 1) { + command = '!cof-attack ' + perso.token.id + ' @{target|token_id} -1 --semonce'; + ligne += bouton(command, "Tir de semonce (L)", perso) + '
'; + } } //L'action de traverser pour un cyclone if (attributeAsBool(perso, 'cyclone')) { @@ -26620,29 +26977,32 @@ var COFantasy = COFantasy || function() { ligne += bouton(command, 'Second souffle', perso) + '
'; } } - //Changement de phase pour intangibilité avec changement de phase + //Changement de phase pour intangibilit\xE9 avec changement de phase if (attributeAsBool(perso, 'intangiblePuissant')) { if (attributeAsInt(perso, 'intangibleValeur', 1)) { command = "!cof-set-attribute intangibleValeur 0 --target " + perso.token.id + " --message redevient tangible"; ligne += boutonSimple(command, "Redevenir tangible") + '
'; } else { - command = "!cof-set-attribute intangibleValeur 1 --target " + perso.token.id + " --message devient légèrement translucide"; + command = "!cof-set-attribute intangibleValeur 1 --target " + perso.token.id + " --message devient l\xE9g\xE8rement translucide"; ligne += boutonSimple(command, "Redevenir intangible") + '
'; } } if (attributeAsBool(perso, 'intangibleInvisiblePuissant')) { if (attributeAsInt(perso, 'intangibleInvisibleValeur', 1)) { - command = "!cof-set-attribute intangibleInvisibleValeur 0 --etat invisible false --target " + perso.token.id + " --message réapparaît"; + command = "!cof-set-attribute intangibleInvisibleValeur 0 --etat invisible false --target " + perso.token.id + " --message r\xE9appara\xEEt"; ligne += boutonSimple(command, "Redevenir tangible") + '
'; } else { - command = "!cof-set-attribute intangibleInvisibleValeur 1 --etat invisible true --target " + perso.token.id + " --message disparaît"; + command = "!cof-set-attribute intangibleInvisibleValeur 1 --etat invisible true --target " + perso.token.id + " --message dispara\xEEt"; ligne += boutonSimple(command, "Redevenir intangible") + '
'; } } //La liste d'action proprement dite actionsAAfficher = treatActions(perso, actionsDuTour, abilities, function(command, text, macros, attackStats) { if (command == 'liste des attaques') { - let attackOptions = {}; + //Dans ce cas, attackStats est une chaine d'options \xE0 ajouter + let attackOptions = { + ligneOptions: attackStats + }; if (gobePar) attackOptions.target = gobePar.token.id; ligne += listeAttaquesVisibles(perso, attackOptions); } else { @@ -26663,7 +27023,7 @@ var COFantasy = COFantasy || function() { if (caracDM > 0) command += '+' + caracDM; else if (caracDM < 0) command += caracDM; command += "--energie --magique --limiteParTour 1 runeIsulys --effet affaibli 1"; - ligne += bouton(command, "Rayon d'énergie", perso) + '
'; + ligne += bouton(command, "Rayon d'\xE9nergie", perso) + '
'; } command = "!cof-gerer-runes-mortes " + perso.token.id; ligne += boutonSimple(command, "Gestion des runes mortes") + '
'; @@ -26673,8 +27033,8 @@ var COFantasy = COFantasy || function() { command = "!cof-attendre ?{Nouvelle initiative}"; ligne += bouton(command, 'Attendre', perso) + '
'; if (!gobePar && !charAttributeAsBool(perso, 'armeeConjuree')) { - command = "!cof-action-defensive ?{Action défensive|simple|totale}"; - ligne += bouton(command, 'Se défendre', perso) + '
'; + command = "!cof-action-defensive ?{Action d\xE9fensive|simple|totale}"; + ligne += bouton(command, 'Se d\xE9fendre', perso) + '
'; let manoeuvreDuelliste = predicateAsBool(perso, 'manoeuvreDuelliste'); if (manoeuvreDuelliste) { command = "!cof-manoeuvre @{selected|token_id} @{target|token_id} ?{Manoeuvre?|bloquer|desarmer|renverser|tenirADistance|repousser}"; @@ -26700,9 +27060,9 @@ var COFantasy = COFantasy || function() { } } if (actionsAAfficher) { - // on envoie la liste aux joueurs qui gèrent le personnage dont le token est lié + // on envoie la liste aux joueurs qui g\xE8rent le personnage dont le token est li\xE9 let lastPlayerid; - // on récupère les players_ids qui controllent le Token + // on r\xE9cup\xE8re les players_ids qui controllent le Token let playerIds; if (playerId) playerIds = [playerId]; else playerIds = getPlayerIds(perso); @@ -26743,17 +27103,17 @@ var COFantasy = COFantasy || function() { let actions = turnAction(perso, playerId, liste); if (!actions) { let l = liste || ''; - sendPerso(perso, "n'a pas de liste d'actions " + l + " définie"); + sendPerso(perso, "n'a pas de liste d'actions " + l + " d\xE9finie"); } }); - }); + }, options); } function removeDernieresCiblesAttaquees(perso, evt) { let attrDernieresCibles = tokenAttribute(perso, 'dernieresCiblesAttaquees'); if (attrDernieresCibles.length > 0) { attrDernieresCibles = attrDernieresCibles[0]; - if (predicateAsBool(perso, 'attaqueEnMeute')) { + if (predicateAsBool(perso, 'attaqueEnMeute') || alliesDAttaqueEnMeute.has(perso.charId)) { let dernieresCibles = attrDernieresCibles.get('current'); let cibles = new Set(dernieresCibles.split(' ')); cibles.forEach(function(ci) { @@ -26832,7 +27192,7 @@ var COFantasy = COFantasy || function() { return res; } - //ne rajoute pas evt à l'historique + //ne rajoute pas evt \xE0 l'historique function setTurnOrder(to, evt) { if (to.pasAgi.length > 0) { to.pasAgi.sort(function(a, b) { @@ -26840,8 +27200,8 @@ var COFantasy = COFantasy || function() { if (b.id == "-1") return -1; if (a.pr < b.pr) return 1; if (b.pr < a.pr) return -1; - // Priorité aux joueurs - // Premier critère : la barre de PV des joueurs est liée + // Priorit\xE9 aux joueurs + // Premier crit\xE8re : la barre de PV des joueurs est li\xE9e let tokenA = getObj('graphic', a.id); if (tokenA === undefined) return 1; let tokenB = getObj('graphic', b.id); @@ -26851,7 +27211,7 @@ var COFantasy = COFantasy || function() { return 1; } if (tokenB.get('bar1_link') === '') return -1; - // Deuxième critère : les joueurs ont un DV + // Deuxi\xE8me crit\xE8re : les joueurs ont un DV let charIdA = tokenA.get('represents'); if (charIdA === '') return 1; let charIdB = tokenB.get('represents'); @@ -26871,7 +27231,7 @@ var COFantasy = COFantasy || function() { return 1; } if (dvB === 0) return -1; - //Entre joueurs, priorité à la plus grosse sagesse + //Entre joueurs, priorit\xE9 \xE0 la plus grosse sagesse let sagA = caracCourante(persoA, 'sagesse'); let sagB = caracCourante(persoB, 'sagesse'); if (sagA < sagB) return 1; @@ -26893,17 +27253,17 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected) { if (selected === undefined || selected.length === 0) { - error("La fonction !cof-attendre : rien à faire, pas de token selectionné", msg); + error("La fonction !cof-attendre : rien \xE0 faire, pas de token selectionn\xE9", msg); return; } let cmd = msg.content.split(' '); if (cmd.length < 2) { - error("Attendre jusqu'à quelle initiative ?", cmd); + error("Attendre jusqu'\xE0 quelle initiative ?", cmd); return; } let newInit = parseInt(cmd[1]); if (isNaN(newInit) || newInit < 1) { - error("On ne peut attendre que jusqu'à une initiative de 1", cmd); + error("On ne peut attendre que jusqu'\xE0 une initiative de 1", cmd); newInit = 1; } let evt = { @@ -26918,7 +27278,7 @@ var COFantasy = COFantasy || function() { return (elt.id == token.id); }); if (tokenPos == -1) { // token ne peut plus agir - sendPerso(perso, " a déjà agit ce tour"); + sendPerso(perso, " a d\xE9j\xE0 agit ce tour"); return; } if (newInit < to.pasAgi[tokenPos].pr) { @@ -26926,7 +27286,7 @@ var COFantasy = COFantasy || function() { sendPerso(perso, " attend un peu avant d'agir..."); updateNextInit(perso); } else { - sendPerso(perso, " a déjà une initiative inférieure à " + newInit); + sendPerso(perso, " a d\xE9j\xE0 une initiative inf\xE9rieure \xE0 " + newInit); } }); setTurnOrder(to, evt); @@ -26934,22 +27294,22 @@ var COFantasy = COFantasy || function() { }); } - // Affiche des informations sur le personnage sélectionné + // Affiche des informations sur le personnage s\xE9lectionn\xE9 function statut(msg) { getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Dans !cof-statut : rien à faire, pas de token selectionné", msg); + error("Dans !cof-statut : rien \xE0 faire, pas de token selectionn\xE9", msg); return; } iterSelected(selected, function(perso) { - //Au cas où + //Au cas o\xF9 unlockToken(perso); const token = perso.token; const charId = perso.charId; const name = nomPerso(perso); let lie = true; if (token.get('bar1_link') === '') lie = false; - const display = startFramedDisplay(playerId, "État de " + name, perso, { + const display = startFramedDisplay(playerId, "\xC9tat de " + name, perso, { chuchote: true }); const estPNJ = persoEstPNJ(perso); @@ -26969,7 +27329,7 @@ var COFantasy = COFantasy || function() { hasMana = !isNaN(manaMax) && manaMax > 0; } let dmTemp = parseInt(token.get('bar2_value')); - if (hasMana) { //ne peut pas être un PNJ + if (hasMana) { //ne peut pas \xEAtre un PNJ if (lie) { dmTemp = ficheAttributeAsInt(perso, 'DMTEMP', 0); } else { @@ -26988,7 +27348,7 @@ var COFantasy = COFantasy || function() { } let douleurIgnoree = attributeAsInt(perso, 'douleurIgnoree', 0); if (douleurIgnoree > 0) { - line = "a ignoré " + douleurIgnoree + " pv dans ce combat."; + line = "a ignor\xE9 " + douleurIgnoree + " pv dans ce combat."; addLineToFramedDisplay(display, line); } let aDV = ficheAttributeAsInt(perso, 'DV', 0); @@ -26996,7 +27356,7 @@ var COFantasy = COFantasy || function() { let pr = pointsDeRecuperation(perso); if (pr) { line = - "Points de récupération : " + pr.current + " / " + pr.max; + "Points de r\xE9cup\xE9ration : " + pr.current + " / " + pr.max; addLineToFramedDisplay(display, line); } if (ficheAttributeAsInt(perso, 'option_pc', 1)) { @@ -27042,7 +27402,7 @@ var COFantasy = COFantasy || function() { if (att.armespec && predicateOfRaw(att.armespec).charge) { let charge = attributeAsInt(perso, 'charge_' + armeLabel, 0); if (charge === 0) { - line = nomArme + " n'est pas chargé"; + line = nomArme + " n'est pas charg\xE9"; } else { let na = fullAttributeName(perso, 'chargeGrenaille_' + armeLabel); let grenaille = attrsChar.find(function(a) { @@ -27053,7 +27413,7 @@ var COFantasy = COFantasy || function() { if (isNaN(grenaille) || grenaille < 0) grenaille = 0; } else grenaille = 0; if (charge == 1) { - line = nomArme + " est chargé"; + line = nomArme + " est charg\xE9"; if (grenaille) line += " de grenaille"; } else if (charge > 1) { line = nomArme + " contient encore " + charge + " charges"; @@ -27068,7 +27428,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, line); } else if (armeEnMain == armeLabel) { if (armeEnMainGauche == armeLabel) { - addLineToFramedDisplay(display, "tient " + nomArme + " à 2 mains."); + addLineToFramedDisplay(display, "tient " + nomArme + " \xE0 2 mains."); } else { addLineToFramedDisplay(display, "tient " + nomArme + " en main."); } @@ -27086,8 +27446,8 @@ var COFantasy = COFantasy || function() { if (attrEnveloppe.length > 0) { let cube = persoOfIdName(attrEnveloppe[0].get('current')); if (cube) { - let actE = "est enveloppé dans "; - if ((attrEnveloppe[0].get('max') + '').startsWith('etreinte')) actE = "est prisonnier de l'étreinte de "; + let actE = "est envelopp\xE9 dans "; + if ((attrEnveloppe[0].get('max') + '').startsWith('etreinte')) actE = "est prisonnier de l'\xE9treinte de "; addLineToFramedDisplay(display, actE + cube.tokName); } } @@ -27098,7 +27458,7 @@ var COFantasy = COFantasy || function() { let defenseMontree; let bufDef = attributeAsInt(perso, 'bufDEF', 0); if (bufDef > 0) { - addLineToFramedDisplay(display, "Défense temporairement modifiée de " + bufDef + " (DEF " + defense + ")"); + addLineToFramedDisplay(display, "D\xE9fense temporairement modifi\xE9e de " + bufDef + " (DEF " + defense + ")"); defenseMontree = true; } for (let etat in cof_states) { @@ -27118,13 +27478,13 @@ var COFantasy = COFantasy || function() { let possedeArmure = ficheAttributeAsInt(perso, 'defarmure', 0) > 0; if (possedeArmure) addLineToFramedDisplay(display, "Ne porte pas son armure"); if (predicateAsInt(perso, 'vetementsSacres', 0) > 0) { - if (possedeArmure) addLineToFramedDisplay(display, " mais bénéficie de ses vêtements sacrés (DEF " + defense + ")"); - else addLineToFramedDisplay(display, "porte des vêtements sacrés (DEF " + defense + ")"); + if (possedeArmure) addLineToFramedDisplay(display, " mais b\xE9n\xE9ficie de ses v\xEAtements sacr\xE9s (DEF " + defense + ")"); + else addLineToFramedDisplay(display, "porte des v\xEAtements sacr\xE9s (DEF " + defense + ")"); defenseMontree = true; } if (predicateAsInt(perso, 'armureDeVent', 0) > 0) { - if (possedeArmure) addLineToFramedDisplay(display, " mais bénéficie de son armure de vent (DEF " + defense + ")"); - else addLineToFramedDisplay(display, "bénéficie de son armure de vent (DEF " + defense + ")"); + if (possedeArmure) addLineToFramedDisplay(display, " mais b\xE9n\xE9ficie de son armure de vent (DEF " + defense + ")"); + else addLineToFramedDisplay(display, "b\xE9n\xE9ficie de son armure de vent (DEF " + defense + ")"); defenseMontree = true; } } @@ -27133,7 +27493,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, "Ne porte pas son bouclier"); if (ficheAttributeAsInt(perso, 'casque_rd', 0)) { if (ficheAttributeAsBool(perso, 'casque_on', false)) { - let b = boutonSimple('!cof-set-attribute casque_on false --message enlève son casque --target ' + perso.token.id, "l'enlever"); + let b = boutonSimple('!cof-set-attribute casque_on false --message enl\xE8ve son casque --target ' + perso.token.id, "l'enlever"); addLineToFramedDisplay(display, "Porte son casque :" + b); } else { let b = boutonSimple('!cof-set-attribute casque_on true --message met son casque --target ' + perso.token.id, "le mettre"); @@ -27190,7 +27550,7 @@ var COFantasy = COFantasy || function() { } let perteDeSubstance = parseInt(attr.get('current')); if (isNaN(perteDeSubstance) || perteDeSubstance < 1) { - error("Attribut de perte de substance mal formé", attr); + error("Attribut de perte de substance mal form\xE9", attr); return; } if (playerIsGM(playerId)) { @@ -27199,21 +27559,21 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, m); } if (perteDeSubstance < 3) { - addLineToFramedDisplay(display, "Dans le noir, on peut distinguer les lumières vives au travers de son corps"); + addLineToFramedDisplay(display, "Dans le noir, on peut distinguer les lumi\xE8res vives au travers de son corps"); } else if (perteDeSubstance < 5) { - addLineToFramedDisplay(display, "Le soleil diffuse à travers le corps à contre-jour"); + addLineToFramedDisplay(display, "Le soleil diffuse \xE0 travers le corps \xE0 contre-jour"); } else if (perteDeSubstance < 7) { - addLineToFramedDisplay(display, "On peut distinguer les objets à travers ses mains, et sa couleur s'estompe"); + addLineToFramedDisplay(display, "On peut distinguer les objets \xE0 travers ses mains, et sa couleur s'estompe"); } else if (perteDeSubstance < 10) { addLineToFramedDisplay(display, "Est translucide comme une eau sale"); } else if (perteDeSubstance < 15) { addLineToFramedDisplay(display, "Est aussi transparent que de l'eau et n'a plus faim ni soif"); } else { - addLineToFramedDisplay(display, "A perdu sa substance : impossible de tenir un objet et possibilité de passer à travers des obstacles"); + addLineToFramedDisplay(display, "A perdu sa substance : impossible de tenir un objet et possibilit\xE9 de passer \xE0 travers des obstacles"); } } }); - //ancienne version de munitions, obsolète depuis mars 2023 + //ancienne version de munitions, obsol\xE8te depuis mars 2023 allAttributesNamed(attrsChar, 'munition').forEach(function(attr) { let attrName = attr.get('name'); let underscore = attrName.indexOf('_'); @@ -27228,7 +27588,7 @@ var COFantasy = COFantasy || function() { let postureMsg = "a une posture "; switch (posture.substr(-3, 3)) { case 'DEF': - postureMsg += "défensive"; + postureMsg += "d\xE9fensive"; break; case 'ATT': postureMsg += "offensive"; @@ -27241,10 +27601,10 @@ var COFantasy = COFantasy || function() { postureMsg += " mais "; switch (posture.substr(0, 3)) { case 'DEF': - postureMsg += "risquée"; + postureMsg += "risqu\xE9e"; break; case 'ATT': - postureMsg += "moins précise"; + postureMsg += "moins pr\xE9cise"; break; case 'DM_': postureMsg += "moins puissante"; @@ -27255,7 +27615,7 @@ var COFantasy = COFantasy || function() { } let attaqueAOutrance = attributeAsInt(perso, 'attaqueAOutrance', 0); if (attaqueAOutrance) { - let attaqueAOutranceMsg = "attaque à outrance "; + let attaqueAOutranceMsg = "attaque \xE0 outrance "; switch (attaqueAOutrance) { case 2: attaqueAOutranceMsg += "(-2 DEF, +1D6 DM)"; @@ -27276,10 +27636,10 @@ var COFantasy = COFantasy || function() { if (soinsLegers < rangSoin) { soinsRestants = rangSoin - soinsLegers; if (soinsRestants > 1) soins = 's'; - msgSoins = "peut encore faire " + soinsRestants + " soin" + soins + " léger" + soins; + msgSoins = "peut encore faire " + soinsRestants + " soin" + soins + " l\xE9ger" + soins; addLineToFramedDisplay(display, msgSoins); } else { - addLineToFramedDisplay(display, "ne peut plus faire de soin léger aujourd'hui"); + addLineToFramedDisplay(display, "ne peut plus faire de soin l\xE9ger aujourd'hui"); } if (rangSoin > 1) { let soinsModeres = attributeAsInt(perso, 'soinsModeres', 0); @@ -27287,18 +27647,18 @@ var COFantasy = COFantasy || function() { soinsRestants = rangSoin - soinsModeres; if (soinsRestants > 1) soins = 's'; else soins = ''; - msgSoins = "peut encore faire " + soinsRestants + " soin" + soins + " modéré" + soins; + msgSoins = "peut encore faire " + soinsRestants + " soin" + soins + " mod\xE9r\xE9" + soins; addLineToFramedDisplay(display, msgSoins); } else { - addLineToFramedDisplay(display, "ne peut plus faire de soin modéré aujourd'hui"); + addLineToFramedDisplay(display, "ne peut plus faire de soin mod\xE9r\xE9 aujourd'hui"); } } if (rangSoin > 3) { - let soinsGuerison = attributeAsInt(perso, 'limiteParJour_guérison', 1); + let soinsGuerison = attributeAsInt(perso, 'limiteParJour_gu\xE9rison', 1); if (soinsGuerison > 0) { - addLineToFramedDisplay(display, "peut encore faire " + soinsGuerison + " guérison" + (soinsGuerison > 1 ? 's' : '') + " aujourd'hui"); + addLineToFramedDisplay(display, "peut encore faire " + soinsGuerison + " gu\xE9rison" + (soinsGuerison > 1 ? 's' : '') + " aujourd'hui"); } else { - addLineToFramedDisplay(display, "ne peut plus faire de guérison aujourd'hui"); + addLineToFramedDisplay(display, "ne peut plus faire de gu\xE9rison aujourd'hui"); } } } @@ -27308,7 +27668,7 @@ var COFantasy = COFantasy || function() { } let bonusCouvert = attributeAsInt(perso, 'bonusCouvert'); if (bonusCouvert) { - addLineToFramedDisplay(display, "est à couvert (+" + bonusCouvert + " DEF)"); + addLineToFramedDisplay(display, "est \xE0 couvert (+" + bonusCouvert + " DEF)"); } if (!defenseMontree) { let defenseAffichee = 10; @@ -27321,7 +27681,7 @@ var COFantasy = COFantasy || function() { defenseAffichee += modCarac(perso, 'dexterite'); } if (defense != defenseAffichee) - addLineToFramedDisplay(display, "Défense actuelle : " + defense); + addLineToFramedDisplay(display, "D\xE9fense actuelle : " + defense); } let predicatExpertDuCombat = predicateAsInt(perso, "expertDuCombat", 0); if (stateCOF.combat && predicatExpertDuCombat > 0) { @@ -27333,11 +27693,11 @@ var COFantasy = COFantasy || function() { else nbDesExpertDuCombat_tour_max = 1; let nbDesExpertDuCombat_tour = Math.min(nbDesExpertDuCombat_combat, attributeAsInt(perso, "limiteParTour_expertDuCombat", nbDesExpertDuCombat_tour_max)); - addLineToFramedDisplay(display, "Dés d'expertise du combat :
" + + addLineToFramedDisplay(display, "D\xE9s d'expertise du combat :
" + "Tour : " + nbDesExpertDuCombat_tour + "/" + nbDesExpertDuCombat_tour_max + "
" + "Combat : " + nbDesExpertDuCombat_combat + "/" + nbDesExpertDuCombat_combat_max + "
"); } - //Affaiblissements de caractéristiques + //Affaiblissements de caract\xE9ristiques allCaracs.forEach(function(carac) { let malus = attributeAsInt(perso, 'affaiblissementde' + carac, 0); if (malus > 0) { @@ -27346,7 +27706,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, ligne); } }); - //Violence ciblée + //Violence cibl\xE9e if (predicateAsBool(perso, 'violenceCiblee')) { let pointsDeViolence = attributeAsInt(perso, 'pointsDeViolence', 0); if (pointsDeViolence > 0) { @@ -27354,7 +27714,7 @@ var COFantasy = COFantasy || function() { } } if (attributeAsBool(perso, 'lumiere')) { - addLineToFramedDisplay(display, "éclaire ou fait de la lumière"); + addLineToFramedDisplay(display, "\xE9claire ou fait de la lumi\xE8re"); } let autresAttributs = predicatesNamed(perso, 'attributsDeStatut'); autresAttributs.forEach(function(attr) { @@ -27376,7 +27736,7 @@ var COFantasy = COFantasy || function() { }); } - //retourne l'id du suivant si le token actuel était en tête de liste + //retourne l'id du suivant si le token actuel \xE9tait en t\xEAte de liste function removeFromTurnTracker(perso, evt) { removeDernieresCiblesAttaquees(perso, evt); let tokenId = perso.token.id; @@ -27460,14 +27820,14 @@ var COFantasy = COFantasy || function() { } if (buf === 0) return; let message = ""; - if (buf > 0) message = "voit sa défense augmenter"; - else message = "voit sa défense baisser"; + if (buf > 0) message = "voit sa d\xE9fense augmenter"; + else message = "voit sa d\xE9fense baisser"; let evt = { type: 'other' }; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour !cof--buf-def", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof--buf-def", playerId); } iterSelected(selected, function(perso) { setTokenAttr(perso, 'bufDEF', buf, evt, { @@ -27476,7 +27836,7 @@ var COFantasy = COFantasy || function() { setToken(perso.token, 'status_blue', buf, evt); }); if (evt.attributes.length === 0) { - error("Pas de cible valide sélectionnée pour !cod-buf-def", msg); + error("Pas de cible valide s\xE9lectionn\xE9e pour !cod-buf-def", msg); return; } addEvent(evt); @@ -27489,11 +27849,11 @@ var COFantasy = COFantasy || function() { }; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour !cof-remove-buf-def", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof-remove-buf-def", playerId); } iterSelected(selected, function(perso) { removeTokenAttr(perso, 'bufDEF', evt, { - msg: "retrouve sa défense normale" + msg: "retrouve sa d\xE9fense normale" }); setToken(perso.token, 'status_blue', false, evt); }); @@ -27565,7 +27925,7 @@ var COFantasy = COFantasy || function() { if (opt.length > 1) { vampirise = parseInt(opt[1]); if (isNaN(vampirise)) { - error("Il faut un pourcentage entier comme argument à --vampirise", opt); + error("Il faut un pourcentage entier comme argument \xE0 --vampirise", opt); vampirise = 100; } } @@ -27579,7 +27939,7 @@ var COFantasy = COFantasy || function() { } options.ignoreRD = parseInt(opt[1]); if (isNaN(options.ignoreRD) || options.ignoreRD < 1) { - log("Pas un nombre positif après --ignoreRD, interprété comme ignore toute la RD"); + log("Pas un nombre positif apr\xE8s --ignoreRD, interpr\xE9t\xE9 comme ignore toute la RD"); options.ignoreRD = undefined; options.ignoreTouteRD = true; } @@ -27587,7 +27947,7 @@ var COFantasy = COFantasy || function() { case 'attaquant': { if (opt.length < 2) { - error("Manque l'id de l'attaquant, option ignorée", optArgs); + error("Manque l'id de l'attaquant, option ignor\xE9e", optArgs); return; } const attaquant = persoOfId(opt[1]); @@ -27595,12 +27955,12 @@ var COFantasy = COFantasy || function() { options.attaquant = attaquant; return; } - error("Attaquant non trouvé", opt); + error("Attaquant non trouv\xE9", opt); return; } case 'titre': if (opt.length < 2) { - error("Il manque le message après --message", text); + error("Il manque le message apr\xE8s --message", text); return; } options.titre = opt.slice(1).join(' '); @@ -27615,13 +27975,13 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("cof-dmg prend les dégats en argument, avant les options", + error("cof-dmg prend les d\xE9gats en argument, avant les options", msg.content); return; } getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "pas de cible trouvée, action annulée", playerId); + sendPlayer(msg, "pas de cible trouv\xE9e, action annul\xE9e", playerId); return; } options.aoe = true; @@ -27632,7 +27992,7 @@ var COFantasy = COFantasy || function() { }); cibles = enleveDoublonsPartagePV(cibles); if (options.return) return; - //L'expression à lancer est tout ce qui est entre le premier blanc et le premier -- + //L'expression \xE0 lancer est tout ce qui est entre le premier blanc et le premier -- let debutDmgRollExpr = msg.content.indexOf(' ') + 1; let dmgRollExpr = msg.content.substring(debutDmgRollExpr); let finDmgRollExpr = msg.content.indexOf(' --'); @@ -27674,7 +28034,7 @@ var COFantasy = COFantasy || function() { addEvent(evt); } evt.action = { - titre: "Dégâts", + titre: "D\xE9g\xE2ts", playerId: playerId, playerName: playerName, cibles: cibles, @@ -27682,12 +28042,12 @@ var COFantasy = COFantasy || function() { options: options }; if (options.lanceur && limiteRessources(options.lanceur, options, 'dmg', 'dmg', evt)) return; - let action = "Dégâts. "; + let action = "D\xE9g\xE2ts. "; if (options.titre) action += options.titre + "
"; if (options.partialSave) { action += - " Jet de " + options.partialSave.carac + " difficulté " + options.partialSave.seuil + - " pour réduire les dégâts"; + " Jet de " + options.partialSave.carac + " difficult\xE9 " + options.partialSave.seuil + + " pour r\xE9duire les d\xE9g\xE2ts"; } let display = startFramedDisplay(playerId, action); let tokensToProcess = cibles.length; @@ -27697,45 +28057,47 @@ var COFantasy = COFantasy || function() { if (someDmgDone) { sendFramedDisplay(display); } else { - sendPlayer(playerName, "Aucune cible valide n'a été sélectionée"); + sendPlayer(playerName, "Aucune cible valide n'a \xE9t\xE9 s\xE9lection\xE9e"); } } tokensToProcess--; }; - try { - sendChat('', '[[' + dmg.value + ']]', function(resDmg) { - dmg.roll = dmg.roll || resDmg[0]; - let afterEvaluateDmg = dmg.roll.content.split(' '); - let dmgRollNumber = rollNumber(afterEvaluateDmg[0]); - dmg.total = dmg.roll.inlinerolls[dmgRollNumber].results.total; - dmg.display = buildinline(dmg.roll.inlinerolls[dmgRollNumber], dmg.type, options.magique); - cibles.forEach(function(perso) { - if (getState(perso, 'mort')) { //pas de dégâts aux morts - finalDisplay(); - return; - } - if (options.mortsVivants && !(estMortVivant(perso))) { - sendPlayer(playerName, nomPerso(perso) + " n'est pas un mort-vivant"); - finalDisplay(); - return; - } - let name = nomPerso(perso); - let explications = []; - copyDmgOptionsToTarget(perso, options); + dmg.rolls = dmg.rolls || []; + cibles.forEach(function(perso) { + if (getState(perso, 'mort')) { //pas de d\xE9g\xE2ts aux morts + finalDisplay(); + return; + } + if (options.mortsVivants && !(estMortVivant(perso))) { + sendPlayer(playerName, nomPerso(perso) + " n'est pas un mort-vivant"); + finalDisplay(); + return; + } + let name = nomPerso(perso); + let explications = []; + copyDmgOptionsToTarget(perso, options); + try { + sendChat('', '[[' + dmg.value + ']]', function(resDmg) { + dmg.rolls[perso.token.id] = dmg.rolls[perso.token.id] || resDmg[0]; + let roll = dmg.rolls[perso.token.id]; + let afterEvaluateDmg = roll.content.split(' '); + let dmgRollNumber = rollNumber(afterEvaluateDmg[0]); + dmg.total = roll.inlinerolls[dmgRollNumber].results.total; + dmg.display = buildinline(roll.inlinerolls[dmgRollNumber], dmg.type, options.magique); dealDamage(perso, dmg, [], evt, false, options, explications, function(dmgDisplay, dmgFinal) { someDmgDone = true; addLineToFramedDisplay(display, - name + " reçoit " + dmgDisplay + " DM"); + name + " re\xE7oit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); finalDisplay(); }); - }); //fin forEach - }); //fin du jet de dés - } catch (rollError) { - error("Jet " + dmg.value + " mal formé", dmg); - } + }); //fin du jet de d\xE9s + } catch (rollError) { + error("Jet " + dmg.value + " mal form\xE9", dmg); + } + }); //fin forEach } function estElementaire(t) { @@ -27756,12 +28118,12 @@ var COFantasy = COFantasy || function() { if (valeur == 'false' || valeur == '0' || valeur == 'non' || valeur == 'no') valeur = false; if (valeur == 'true' || valeur == 'oui' || valeur == 'yes') valeur = true; if (!_.has(cof_states, etat)) { - error("Le premier argument de !cof-set-state n'est pas un état valide", cmd); + error("Le premier argument de !cof-set-state n'est pas un \xE9tat valide", cmd); return; } if (isCarac(cmd[2])) { if (cmd.length < 4) { - error("Il manque la difficulté du jet de sauvegarde.", cmd); + error("Il manque la difficult\xE9 du jet de sauvegarde.", cmd); return; } valeur = true; @@ -27774,20 +28136,21 @@ var COFantasy = COFantasy || function() { } else { options.saveActifParTour.difficulte = parseInt(cmd[3]); if (isNaN(options.saveActifParTour.difficulte)) { - error("Difficulté du jet de sauvegarde incorrecte", cmd); + error("Difficult\xE9 du jet de sauvegarde incorrecte", cmd); return; } } } let cibles = []; - getSelected(msg, function(selected, playerId) { + getSelected(msg, function(selected, playerId, aoe) { if (selected === undefined || selected.length === 0) { - error("Pas de cible pour le changement d'état", msg); + error("Pas de cible pour le changement d'\xE9tat", msg); return; } + options.aoe = aoe; iterSelected(selected, function(perso) { if (options.seulementVivant && estNonVivant(perso)) { - sendPlayer(msg, "cet effet n'affecte que les créatures vivantes", playerId); + sendPlayer(msg, "cet effet n'affecte que les cr\xE9atures vivantes", playerId); return; } switch (etat) { @@ -27829,7 +28192,7 @@ var COFantasy = COFantasy || function() { } cibles.push(perso); }); - }); + }, options); doSetState(cibles, etat, valeur, options); } @@ -27845,6 +28208,9 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); + if (options.terrainDifficile && options.aoe && options.aoe.type == 'disque') { + ajouteTerrainDifficile(options, evt); + } let lanceur = options.lanceur; if (lanceur === undefined && cibles.length == 1) lanceur = persoOfId(cibles[0].token.id); if (limiteRessources(lanceur, options, etat, etat, evt)) return; @@ -27887,8 +28253,8 @@ var COFantasy = COFantasy || function() { }; if (options.save) { let saveOpts = { - msgPour: " pour résister à l'effet " + stringOfEtat(etat), - msgRate: ", raté.", + msgPour: " pour r\xE9sister \xE0 l'effet " + stringOfEtat(etat), + msgRate: ", rat\xE9.", rolls: options.rolls, chanceRollId: options.chanceRollId, type: options.type @@ -27911,7 +28277,7 @@ var COFantasy = COFantasy || function() { function textOfSaveState(etat, perso) { switch (etat) { case 'immobilise': - return "se libérer"; + return "se lib\xE9rer"; case 'aveugle': return "retrouver la vue"; case 'etourdi': @@ -27921,13 +28287,13 @@ var COFantasy = COFantasy || function() { case 'renverse': return "se relever"; case 'endormi': - return "se réveiller"; + return "se r\xE9veiller"; case 'apeure': return "retrouver du courage"; case 'enseveli': return "sortir de terre"; default: - return "ne plus être " + stringOfEtat(etat, perso); + return "ne plus \xEAtre " + stringOfEtat(etat, perso); } } @@ -27936,7 +28302,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 4 || !_.has(cof_states, cmd[1])) { - error("Paramètres de !cof-save-state incorrects", cmd); + error("Param\xE8tres de !cof-save-state incorrects", cmd); return; } let etat = cmd[1]; @@ -27947,17 +28313,17 @@ var COFantasy = COFantasy || function() { carac2 = carac.substring(3, 6); carac = carac.substring(0, 3); if (!isCarac(carac) || !isCarac(carac)) { - error("Paramètres de !cof-save-state incorrects", cmd); + error("Param\xE8tres de !cof-save-state incorrects", cmd); return; } } else { - error("Paramètres de !cof-save-state incorrects", cmd); + error("Param\xE8tres de !cof-save-state incorrects", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Pas de token sélectionné", msg.content); + error("Pas de token s\xE9lectionn\xE9", msg.content); return; } let pageId = options.pageId; @@ -27980,7 +28346,7 @@ var COFantasy = COFantasy || function() { } else { let seuil = parseInt(cmd[3]); if (isNaN(seuil)) { - error("La difficulté n'est pas un nombre", cmd); + error("La difficult\xE9 n'est pas un nombre", cmd); return; } iterSelected(selected, function(perso) { @@ -27992,7 +28358,7 @@ var COFantasy = COFantasy || function() { doSaveState(playerId, perso, etat, carac, options, undefined, seuil); }); } - }); + }, options); } function doSaveState(playerId, perso, etat, carac, options, opposant, seuil) { @@ -28058,13 +28424,13 @@ var COFantasy = COFantasy || function() { } //!cof-save-effet token_id attr_id - // où attr_id est l'id de l'attribut de save + // o\xF9 attr_id est l'id de l'attribut de save function parseSaveEffet(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 3) { - error("Paramètres de !cof-save-effet incorrects", cmd); + error("Param\xE8tres de !cof-save-effet incorrects", cmd); return; } let perso = persoOfId(cmd[1]); @@ -28082,7 +28448,7 @@ var COFantasy = COFantasy || function() { let effetC = attrName.substring(0, indexSave); let effetTemp = estEffetTemp(effetC); if (!effetTemp && !estEffetCombat(effetC)) { - error("Impossible de trouver l'effet correspondant à " + effetC, attrName); + error("Impossible de trouver l'effet correspondant \xE0 " + effetC, attrName); return; } attrName = effetC + attrName.substr(indexSave + 16); @@ -28092,19 +28458,19 @@ var COFantasy = COFantasy || function() { let msgPour = " pour "; if (met.msgSave) msgPour += met.msgSave; else { - msgPour += "ne plus être sous l'effet de "; + msgPour += "ne plus \xEAtre sous l'effet de "; if (effetC.startsWith('dotGen(')) msgPour += effetC.substring(7, effetC.indexOf(')')); else msgPour += effetC; } let carac = attr.get('current'); if (!isCarac(carac)) { - error("Save par tour " + attrName + " mal formé", carac); + error("Save par tour " + attrName + " mal form\xE9", carac); return; } let seuil = parseInt(attr.get('max')); if (isNaN(seuil)) { - error("Save par tour " + attrName + " mal formé", seuil); + error("Save par tour " + attrName + " mal form\xE9", seuil); return; } let attrEffet = findObjs({ @@ -28205,7 +28571,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("commande non formée", msg.content); + error("commande non form\xE9e", msg.content); return; } let armeLabel = ''; @@ -28218,13 +28584,13 @@ var COFantasy = COFantasy || function() { let personnages = []; getSelected(msg, function(selected) { if (selected === undefined || selected.length === 0) { - error("Qui doit dégainer ?", msg); + error("Qui doit d\xE9gainer ?", msg); return; } iterSelected(selected, function(perso) { personnages.push(perso); }); - }); + }, options); doDegainer(personnages, armeLabel, options); } @@ -28243,14 +28609,14 @@ var COFantasy = COFantasy || function() { persos.forEach(function(perso) { function afterSave() { let nomArme = degainerArme(perso, labelArme, evt, options); - if (nomArme) sendPerso(perso, "a déjà " + nomArme + " en main"); + if (nomArme) sendPerso(perso, "a d\xE9j\xE0 " + nomArme + " en main"); else if (options.montreActions && persos.length === 1) turnAction(perso); } if (options.save) { let saveOpts = { msgPour: " pour garder son arme en main", - msgRate: ", raté.", + msgRate: ", rat\xE9.", rolls: options.rolls, chanceRollId: options.chanceRollId }; @@ -28272,7 +28638,7 @@ var COFantasy = COFantasy || function() { function echangeInit(msg) { let combat = stateCOF.combat; if (!combat) { - error("Échange d'intiative en dehors du combat", msg); + error("\xC9change d'intiative en dehors du combat", msg); return; } let options = parseOptions(msg); @@ -28297,7 +28663,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3) { attackBonus = parseInt(cmd[3]); if (isNaN(attackBonus)) { - error("Le troisième argument n'est pas un nombre", cmd[3]); + error("Le troisi\xE8me argument n'est pas un nombre", cmd[3]); return; } } @@ -28312,23 +28678,23 @@ var COFantasy = COFantasy || function() { return (t.id == perso2.token.id); }); if (tourTok1 < 0) { - sendPerso(perso1, "a déjà agit, pas moyen d'échanger son initiative"); + sendPerso(perso1, "a d\xE9j\xE0 agit, pas moyen d'\xE9changer son initiative"); return; } if (tourTok2 < 0) { - sendPerso(perso2, "a déjà agit, pas moyen d'échanger son initiative"); + sendPerso(perso2, "a d\xE9j\xE0 agit, pas moyen d'\xE9changer son initiative"); return; } let pr1 = to.pasAgi[tourTok1].pr; let pr2 = to.pasAgi[tourTok2].pr; if (pr1 == pr2) { - sendPerso(perso1, "a la même initiative que " + nomPerso(perso2)); + sendPerso(perso1, "a la m\xEAme initiative que " + nomPerso(perso2)); return; } if (pr1 > pr2) { if (attackBonus) { setTokenAttr(perso1, 'actionConcertee', attackBonus, evt, { - msg: "gagne un bonus de " + attackBonus + " à ses attaques et en DEF pour ce tour" + msg: "gagne un bonus de " + attackBonus + " \xE0 ses attaques et en DEF pour ce tour" }); } setActiveToken(combat, perso2.token.id, evt); @@ -28367,7 +28733,7 @@ var COFantasy = COFantasy || function() { return arg == '--secret'; }); setTokenAttr(perso1, 'aCouvert', 1, evt, { - msg: "reste à couvert", + msg: "reste \xE0 couvert", maxVal: init, secret: secret }); @@ -28380,9 +28746,9 @@ var COFantasy = COFantasy || function() { } if (perso2.token.id == perso1.token.id) { if (secret) { - whisperChar(perso1.charId, "s'est ciblé " + onGenre(perso1, 'lui', 'elle') + "-même, il est donc le seul à couvert"); + whisperChar(perso1.charId, "s'est cibl\xE9 " + onGenre(perso1, 'lui', 'elle') + "-m\xEAme, il est donc le seul \xE0 couvert"); } else { - sendPerso(perso1, "s'est ciblé " + onGenre(perso1, 'lui', 'elle') + "-même, il est donc le seul à couvert"); + sendPerso(perso1, "s'est cibl\xE9 " + onGenre(perso1, 'lui', 'elle') + "-m\xEAme, il est donc le seul \xE0 couvert"); } addEvent(evt); return; @@ -28390,13 +28756,13 @@ var COFantasy = COFantasy || function() { let d = distanceCombat(perso1.token, perso2.token); if (d > 0) { if (secret) { - whisperChar(perso2.charId, "est trop éloigné de " + nomPerso(perso1) + " pour rester à couvert avec lui"); + whisperChar(perso2.charId, "est trop \xE9loign\xE9 de " + nomPerso(perso1) + " pour rester \xE0 couvert avec lui"); } else { - sendPerso(perso2, "est trop éloigné de " + nomPerso(perso1) + " pour rester à couvert avec lui"); + sendPerso(perso2, "est trop \xE9loign\xE9 de " + nomPerso(perso1) + " pour rester \xE0 couvert avec lui"); } } else { setTokenAttr(perso2, 'aCouvert', 1, evt, { - msg: "suit " + nomPerso(perso1) + " et reste à couvert", + msg: "suit " + nomPerso(perso1) + " et reste \xE0 couvert", maxVal: init, secret: secret }); @@ -28427,20 +28793,20 @@ var COFantasy = COFantasy || function() { effet += 'Temp'; } if (effet == 'forgeron' || effet == 'armeEnflammee' || effet == 'armeGlacee') { - //Compléter description de l'effet + //Compl\xE9ter description de l'effet if (!lanceur) { error("Pas de lanceur pour " + effet, msg.content); return; } let armeActuelle = tokenAttribute(lanceur, 'armeEnMain'); if (armeActuelle.length === 0) { - whisperChar(charId, "Pas d'arme en main, impossible de savoir à quoi appliquer " + effet); + whisperChar(charId, "Pas d'arme en main, impossible de savoir \xE0 quoi appliquer " + effet); return; } let labelArme = armeActuelle[0].get('current'); effet = effet + '(' + labelArme + ')'; } else if (!estEffetTemp(effet)) { - error(effet + " n'est pas un effet temporaire répertorié", msg.content); + error(effet + " n'est pas un effet temporaire r\xE9pertori\xE9", msg.content); return; } if (lanceur && options.mana !== undefined && attributeAsBool(lanceur, 'frappeDesArcanes')) { @@ -28461,7 +28827,7 @@ var COFantasy = COFantasy || function() { if (options.puissantDuree || options.tempeteDeManaDuree) duree = duree * 2; getSelected(msg, function(selected, playerId, aoe) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour l'effet", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour l'effet", playerId); return; } options.aoe = aoe; @@ -28480,7 +28846,7 @@ var COFantasy = COFantasy || function() { } if (lanceur && options.tempeteDeMana) { if (duree > 0 && options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, dm: mEffet.dm, @@ -28494,7 +28860,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPlayer(msg, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayer(msg, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } if (selected.length == 1 && options.tempeteDeMana.altruiste) { selected[0]._id = options.tempeteDeMana.altruiste.token.id; @@ -28514,7 +28880,7 @@ var COFantasy = COFantasy || function() { } if ((mEffet.seulementVivant || options.seulementVivant) && estNonVivant(perso)) { - sendPlayer(msg, "cet effet n'affecte que les créatures vivantes", playerId); + sendPlayer(msg, "cet effet n'affecte que les cr\xE9atures vivantes", playerId); return; } if (predicateAsBool(perso, 'liberteDAction') && @@ -28556,7 +28922,40 @@ var COFantasy = COFantasy || function() { }, options); } - //Si display est défini, l'envoie dans le chat à la fin de l'appel + //Si options.terrainDifficile, doit avoir des champs imgsrc, nom et duree + function ajouteTerrainDifficile(options, evt) { + if (!options.aoe || !options.aoe.rayon) return; + let terrainDifficile = options.terrainDifficile; + if (!terrainDifficile || terrainDifficile.done) return; + terrainDifficile.done = true; + let diametre = options.aoe.rayon * 2 * PIX_PER_UNIT / computeScale(options.pageId); + let t = createObj('graphic', { + _pageid: options.pageId, + imgsrc: terrainDifficile.imgsrc, + represents: '', + left: options.aoe.centre.left, + top: options.aoe.centre.top, + width: diametre, + height: diametre, + layer: 'map', + isDrawing: true, + name: terrainDifficile.nom, + gmnotes: 'terrainDifficile:disque ' + Math.floor(diametre) + }); + if (t) { + toFront(t); + evt.tokens = evt.tokens || []; + evt.tokens.push(t); + stateCOF.tokensTemps = stateCOF.tokensTemps || []; + stateCOF.tokensTemps.push({ + tid: t.id, + duree: terrainDifficile.duree, + init: getInit() + }); + } + } + + //Si display est d\xE9fini, l'envoie dans le chat \xE0 la fin de l'appel function activerEffetTemporaire(lanceur, cibles, effet, mEffet, duree, options, evt, whisper, explications, display) { let ef = { effet: effet, @@ -28612,7 +29011,7 @@ var COFantasy = COFantasy || function() { ressource = "limiteParJour_" + ressource; let utilisations = attributeAsInt(perso, ressource, options.limiteCibleParJour); if (utilisations === 0) { - expliquer("ne peut plus bénéficier de " + effet + " aujourd'hui"); + expliquer("ne peut plus b\xE9n\xE9ficier de " + effet + " aujourd'hui"); return; } setTokenAttr(perso, ressource, utilisations - 1, evt); @@ -28626,37 +29025,18 @@ var COFantasy = COFantasy || function() { combat = entrerEnCombat(undefined, ini, explications, evt); } if (options.aoe && options.pageId && effet == 'prisonVegetale' && options.aoe.type == 'disque') { - let diametre = options.aoe.rayon * 2 * PIX_PER_UNIT / computeScale(options.pageId); - let t = createObj('graphic', { - _pageid: options.pageId, - imgsrc: stateCOF.options.images.val.prison_vegetale.val, - represents: '', - left: options.aoe.centre.get('left'), - top: options.aoe.centre.get('top'), - width: diametre, - height: diametre, - layer: 'map', - isDrawing: true, - name: 'Prison végétale', - gmnotes: 'terrainDifficile:disque ' + Math.floor(diametre) - }); - if (t) { - toFront(t); - evt.tokens = evt.tokens || []; - evt.tokens.push(t); - stateCOF.tokensTemps = stateCOF.tokensTemps || []; - stateCOF.tokensTemps.push({ - tid: t.id, - duree, - init: getInit() - }); - } + options.terrainDifficile = options.terrainDifficile || { + duree, + nom: "Prison v\xE9g\xE9tale", + imgsrc: stateCOF.options.images.val.prison_vegetale.val + }; + ajouteTerrainDifficile(options, evt); } let renew = attributeAsBool(perso, effet); setEffetTemporaire(perso, ef, d, evt, options); if (!renew) { if (effet.startsWith('forgeron(')) { - //Il faut dégainer l'arme si elle n'est pas en main, et ajouter une lumière + //Il faut d\xE9gainer l'arme si elle n'est pas en main, et ajouter une lumi\xE8re let labelArmeForgeron = effet.substring(9, effet.indexOf(')')); degainerArme(perso, labelArmeForgeron, evt); let feu = getIntValeurOfEffet(perso, effet, 1, 'voieDuMetal'); @@ -28714,15 +29094,15 @@ var COFantasy = COFantasy || function() { if (display) perso.messages.push(s); else sendPerso(perso, s); }; - if (options.type && immuniseAuType(perso, options.type, lanceur)) { - expliquer("ne semble pas affecté par " + stringOfType(options.type)); + if (options.type && immuniseAuType(perso, options.type, lanceur, options)) { + expliquer("ne semble pas affect\xE9 par " + stringOfType(options.type)); finalize(); return; } if (options.save) { let saveOpts = { - msgPour: options.save.msgPour || " pour résister à l'effet " + effet, - msgRate: ", raté.", + msgPour: options.save.msgPour || " pour r\xE9sister \xE0 l'effet " + effet, + msgRate: ", rat\xE9.", attaquant: lanceur, rolls: options.rolls, chanceRollId: options.chanceRollId, @@ -28739,7 +29119,7 @@ var COFantasy = COFantasy || function() { } if (reussite) { if (effet == 'reactionViolente' && predicateAsBool(perso, 'violenceCiblee')) { - expliquer("résiste à la provocation, mais emmagasine de la violence"); + expliquer("r\xE9siste \xE0 la provocation, mais emmagasine de la violence"); addToAttributeAsInt(perso, 'pointsDeViolence', 0, 1, evt); } finalize(); @@ -28761,7 +29141,7 @@ var COFantasy = COFantasy || function() { return (2 * magieEnArmure < defa + ma); } - //options doit être défini + //options doit \xEAtre d\xE9fini function effetTemporaire(playerId, cibles, effet, mEffet, duree, options) { const evt = { type: 'effetTemp', @@ -28808,7 +29188,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, line); activerEffetTemporaire(lanceur, cibles, effet, mEffet, duree, options, evt, whisper, explications, display); } else { - line += '< ' + difficulte + ", le sort est raté"; + line += '< ' + difficulte + ", le sort est rat\xE9"; addLineToFramedDisplay(display, line); sendFramedDisplay(display); } @@ -28816,7 +29196,7 @@ var COFantasy = COFantasy || function() { } else { activerEffetTemporaire(lanceur, cibles, effet, mEffet, duree, options, evt, whisper, explications); } - } else { //On met fin à l'effet + } else { //On met fin \xE0 l'effet explications.forEach(function(e) { sendChat('', e); }); @@ -28855,7 +29235,7 @@ var COFantasy = COFantasy || function() { case 'oui': case 'Oui': case 'true': - case 'début': + case 'd\xE9but': case 'debut': valeur = true; activer = true; @@ -28894,7 +29274,7 @@ var COFantasy = COFantasy || function() { } let effet = cmd[1]; if (!estEffetCombat(effet)) { - error(effet + " n'est pas un effet de combat répertorié", msg.content); + error(effet + " n'est pas un effet de combat r\xE9pertori\xE9", msg.content); return; } const evt = { @@ -28920,7 +29300,7 @@ var COFantasy = COFantasy || function() { } } if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour l'effet", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour l'effet", playerId); return; } if (lanceur === undefined) { @@ -28935,7 +29315,7 @@ var COFantasy = COFantasy || function() { } if (lanceur && options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, dm: messageEffetCombat[effet].dm, @@ -28948,7 +29328,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(lanceur, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort", options.secret); + sendPerso(lanceur, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort", options.secret); } if (selected.length == 1 && options.tempeteDeMana.altruiste) { selected[0]._id = options.tempeteDeMana.altruiste.token.id; @@ -29020,7 +29400,7 @@ var COFantasy = COFantasy || function() { setTokenAttr(perso, effet + 'TokenSide', oldSide, evt); } }); - } else { //on désactive + } else { //on d\xE9sactive iterSelected(selected, function(perso) { let actMsg = messageFin(perso, mEffet) + extraImg; removeTokenAttr(perso, effet, evt, { @@ -29081,7 +29461,7 @@ var COFantasy = COFantasy || function() { }); } } - }); + }, options); } function parseEffetIndetermine(msg) { @@ -29102,7 +29482,7 @@ var COFantasy = COFantasy || function() { effetCombat(msg); return; } - error(effet + " n'est pas un effet répertorié", msg.content); + error(effet + " n'est pas un effet r\xE9pertori\xE9", msg.content); return; } let av = activeOuValeur(cmd, options); @@ -29116,7 +29496,7 @@ var COFantasy = COFantasy || function() { if (lanceur) charId = lanceur.charId; getSelected(msg, function(selected, playerId, aoe) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour l'effet", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour l'effet", playerId); return; } if (lanceur === undefined) { @@ -29134,7 +29514,7 @@ var COFantasy = COFantasy || function() { } if (lanceur && options.tempeteDeMana) { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPlayer(msg, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayer(msg, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } if (selected.length == 1 && options.tempeteDeMana.altruiste) { selected[0]._id = options.tempeteDeMana.altruiste.token.id; @@ -29163,12 +29543,12 @@ var COFantasy = COFantasy || function() { } if (activer === undefined) { if (cibles.length > 1) { - sendPlayer(msg, "On ne peut sélectionner qu'un token si on ne précise pas si il faut activer ou désactiver l'effet"); + sendPlayer(msg, "On ne peut s\xE9lectionner qu'un token si on ne pr\xE9cise pas si il faut activer ou d\xE9sactiver l'effet"); return; } let perso = persoOfId(selected[0]._id); if (!perso) { - error("Token sélectionné non valide", selected); + error("Token s\xE9lectionn\xE9 non valide", selected); return; } activer = !attributeAsBool(perso, effet); @@ -29192,7 +29572,7 @@ var COFantasy = COFantasy || function() { normalToken = JSON.parse(normalToken); let nw = normalToken.width; let nh = normalToken.height; - //Rien à faire si le token occupe déjà une case + //Rien \xE0 faire si le token occupe d\xE9j\xE0 une case if (nw >= PIX_PER_UNIT || nh >= PIX_PER_UNIT) return; setTokenAttr(perso, 'tailleDeTokenNormale', nw, evt, { maxVal: nh @@ -29226,7 +29606,7 @@ var COFantasy = COFantasy || function() { let nw = parseInt(attr.get('current')); let nh = parseInt(attr.get('max')); if (isNaN(nw) || isNaN(nh)) { - error("La taille de token sauvegardée n'est pas correcte", attr); + error("La taille de token sauvegard\xE9e n'est pas correcte", attr); attr.remove(); } let character = getObj('character', perso.charId); @@ -29371,11 +29751,11 @@ var COFantasy = COFantasy || function() { if (!msgPour) { msgPour = " pour "; if (mEffet.msgSave) msgPour += mEffet.msgSave; - else msgPour += "résister à l'effet " + effet; + else msgPour += "r\xE9sister \xE0 l'effet " + effet; } let saveOpts = { msgPour, - msgRate: ", raté.", + msgRate: ", rat\xE9.", silencieuxSiPasAffecte: options.silencieuxSiPasAffecte, attaquant: lanceur, rolls: options.rolls, @@ -29453,7 +29833,7 @@ var COFantasy = COFantasy || function() { let classeEffet = cmd[1]; getSelected(msg, function(selected) { if (selected === undefined || selected.length === 0) { - error("Pas de cible sélectionnée pour la fin d'une classe d'effets", msg); + error("Pas de cible s\xE9lectionn\xE9e pour la fin d'une classe d'effets", msg); return; } const evt = { @@ -29491,16 +29871,16 @@ var COFantasy = COFantasy || function() { predicateAsBool(target, 'sansEsprit') || attributeAsBool(target, 'enrage') || predicateAsBool(target, 'liberteDAction')) { - messages.push(targetName + " est insensible à la peur !"); + messages.push(targetName + " est insensible \xE0 la peur !"); callback(); return; } if (options.immuniseSiResiste && attributeAsBool(target, options.immuniseSiResiste)) { - messages.push(targetName + " a déjà résisté à cet effet, " + onGenre(target, 'il', 'elle') + " n'y est plus sensible"); + messages.push(targetName + " a d\xE9j\xE0 r\xE9sist\xE9 \xE0 cet effet, " + onGenre(target, 'il', 'elle') + " n'y est plus sensible"); callback(); return; } - let carac = 'SAG'; //carac pour résister + let carac = 'SAG'; //carac pour r\xE9sister if (options.resisteAvecForce) carac = meilleureCarac('SAG', 'FOR', target, difficulte); //chercher si un partenaire a sansPeur pour appliquer le bonus @@ -29512,7 +29892,7 @@ var COFantasy = COFantasy || function() { let allTokens; allies.forEach(function(cid) { if (charPredicateAsBool(cid, 'sansPeur')) { - //On cherche si l'allié est présent sur la même page + //On cherche si l'alli\xE9 est pr\xE9sent sur la m\xEAme page allTokens = allTokens || findObjs({ _type: "graphic", @@ -29531,7 +29911,7 @@ var COFantasy = COFantasy || function() { charId: cid, token: alliePresent }; - msgAllieSansPeur = nomPerso(allie) + " a donné +" + bonusAllie + " au jet"; + msgAllieSansPeur = nomPerso(allie) + " a donn\xE9 +" + bonusAllie + " au jet"; } } } @@ -29547,7 +29927,7 @@ var COFantasy = COFantasy || function() { let line = targetName + " fait " + tr.texte; let sujet = onGenre(target, 'il', 'elle'); if (tr.reussite) { - line += ", " + sujet + " résiste à la peur." + tr.modifiers; + line += ", " + sujet + " r\xE9siste \xE0 la peur." + tr.modifiers; if (options.immuniseSiResiste) setTokenAttr(target, options.immuniseSiResiste, true, evt); } else { @@ -29555,18 +29935,18 @@ var COFantasy = COFantasy || function() { let effet = 'apeureTemp'; let etat = 'apeure'; if (options.etourdi) { - line += "s'enfuit ou reste recroquevillé" + eForFemale(target) + " sur place"; + line += "s'enfuit ou reste recroquevill\xE9" + eForFemale(target) + " sur place"; effet = 'peurEtourdi'; } else if (options.ralenti) { line += "est ralenti" + eForFemale(target); effet = 'ralentiTemp'; etat = 'ralenti'; } else if (options.paralyse) { - line += "est paralysé" + eForFemale(target); + line += "est paralys\xE9" + eForFemale(target); effet = 'paralyseTemp'; etat = 'paralyse'; } else if (options.secoue && !attributeAsBool(target, 'secoue')) { - line += "est secoué" + eForFemale(target); + line += "est secou\xE9" + eForFemale(target); effet = 'secoue'; etat = false; } else { @@ -29596,12 +29976,12 @@ var COFantasy = COFantasy || function() { let pageId = getPageId(playerId); let difficulte = parseInt(cmd[1]); if (isNaN(difficulte)) { - error("Le premier argument de !cof-peur, la difficulté du test de résistance, n'est pas un nombre", cmd); + error("Le premier argument de !cof-peur, la difficult\xE9 du test de r\xE9sistance, n'est pas un nombre", cmd); return; } - let duree = parseDice(cmd[2], "durée de peur"); + let duree = parseDice(cmd[2], "dur\xE9e de peur"); if (!dePositif(duree)) { - error("Le second argument de !cof-peur, la durée, n'est pas un nombre positif", cmd); + error("Le second argument de !cof-peur, la dur\xE9e, n'est pas un nombre positif", cmd); return; } let options = {}; @@ -29621,12 +30001,12 @@ var COFantasy = COFantasy || function() { return; case 'portee': if (optCmd.length < 2) { - error("Il manque l'argument de portée", optArgs); + error("Il manque l'argument de port\xE9e", optArgs); return; } options.portee = parseInt(optCmd[1]); if (isNaN(options.portee) || options.portee < 0) { - error("La portée n'est pas un nombre positif", optCmd); + error("La port\xE9e n'est pas un nombre positif", optCmd); delete options.portee; } return; @@ -29659,7 +30039,7 @@ var COFantasy = COFantasy || function() { let cibles = []; getSelected(msg, function(selected) { if (selected === undefined || selected.length === 0) { - error("Pas de cible sélectionnée pour la peur", msg); + error("Pas de cible s\xE9lectionn\xE9e pour la peur", msg); return; } iterSelected(selected, function(perso) { @@ -29672,11 +30052,11 @@ var COFantasy = COFantasy || function() { perso.duree = rollDePlus(duree).val; cibles.push(perso); }); - }); + }, options); if (cibles.length > 0) { doPeur(cibles, difficulte, options); } else { - error("Aucune cible valable à portée de l'effet de Peur", msg); + error("Aucune cible valable \xE0 port\xE9e de l'effet de Peur", msg); } } @@ -29696,14 +30076,14 @@ var COFantasy = COFantasy || function() { if (options.titre) action += options.titre; else if (options.effroi) action += "est vraiment effrayant" + eForFemale(options.lanceur); - else action = "Capacité : Effet de peur"; + else action = "Capacit\xE9 : Effet de peur"; } else if (options.titre) action = options.titre; let messages = []; entrerEnCombat(options.lanceur, cibles, messages, evt); let display = startFramedDisplay(options.playerId, action, options.lanceur); let jet = " Jet de SAG "; if (options.resisteAvecForce) jet += "ou FOR "; - jet += "difficulté " + difficulte; + jet += "difficult\xE9 " + difficulte; addLineToFramedDisplay(display, jet, 80); let counter = cibles.length; let finalDisplay = function() { @@ -29730,7 +30110,7 @@ var COFantasy = COFantasy || function() { if (options === undefined || options.cmd === undefined) return; let cmd = options.cmd; if (cmd.length < 3) { - error("Il faut au moins 2 arguments à !cof-attaque-magique", cmd); + error("Il faut au moins 2 arguments \xE0 !cof-attaque-magique", cmd); return; } let attaquant = persoOfId(cmd[1], cmd[1]); @@ -29764,13 +30144,13 @@ var COFantasy = COFantasy || function() { } } - // callback est seulement appelé si on fait le test - // evt est facultatif ; si absent, en crée un nouveau générique et l'ajoute à l'historique + // callback est seulement appel\xE9 si on fait le test + // evt est facultatif ; si absent, en cr\xE9e un nouveau g\xE9n\xE9rique et l'ajoute \xE0 l'historique function attaqueMagiqueOpposee(playerId, attaquant, cible, options, callback, evt) { if (options.attaqueMentale) { if (predicateAsBool(cible, 'sansEsprit') || predicateAsBool(cible, 'vegetatif')) { sendPerso(attaquant, " est sans esprit, " + onGenre(cible, 'il', 'elle') + - " est immunisé" + onGenre(cible, '', 'e') + " aux attaques mentales."); + " est immunis\xE9" + onGenre(cible, '', 'e') + " aux attaques mentales."); return; } else if (predicateAsBool(cible, 'liberteDAction')) { sendPerso(cible, "reste libre de ses actions !"); @@ -29850,7 +30230,7 @@ var COFantasy = COFantasy || function() { let attackRoll2 = d20roll2 + att2Skill; if (options.chanceRollId && options.chanceRollId.roll2) attackRoll2 += options.chanceRollId.roll2; - let action = "Attaque magique opposée"; + let action = "Attaque magique oppos\xE9e"; let reussi; if (d20roll1 == 1) { if (d20roll2 == 1) reussi = (attackRoll1 >= attackRoll2); @@ -29903,10 +30283,10 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, line); if (reussi) { diminueMalediction(cible, evt); - addLineToFramedDisplay(display, "Attaque réussie !"); + addLineToFramedDisplay(display, "Attaque r\xE9ussie !"); } else { diminueMalediction(attaquant, evt); - addLineToFramedDisplay(display, "L'attaque échoue."); + addLineToFramedDisplay(display, "L'attaque \xE9choue."); } explications.forEach(explication => addLineToFramedDisplay(display, explication, 80)); if (callback) callback(display, reussi); @@ -29932,16 +30312,16 @@ var COFantasy = COFantasy || function() { function(display, reussi) { if (reussi) { if (attributeAsBool(cible, 'immunise24HA_injonction')) { - addLineToFramedDisplay(display, nomPerso(cible) + " a déjà résisté à une injonction aujourd'hui, c'est sans effet"); + addLineToFramedDisplay(display, nomPerso(cible) + " a d\xE9j\xE0 r\xE9sist\xE9 \xE0 une injonction aujourd'hui, c'est sans effet"); } else if (predicateAsBool(cible, 'liberteDAction')) { addLineToFramedDisplay(display, nomPerso(cible) + " reste libre de ses actions !"); } else { - addLineToFramedDisplay(display, nomPerso(cible) + " obéit à l'injonction"); + addLineToFramedDisplay(display, nomPerso(cible) + " ob\xE9it \xE0 l'injonction"); } sendFramedDisplay(display); } else { setTokenAttr(cible, 'immunise24HA_injonction', true, evt); - addLineToFramedDisplay(display, nomPerso(cible) + " n'obéit pas à l'injonction"); + addLineToFramedDisplay(display, nomPerso(cible) + " n'ob\xE9it pas \xE0 l'injonction"); sendFramedDisplay(display); } }, evt); @@ -29962,12 +30342,12 @@ var COFantasy = COFantasy || function() { function(display, reussi) { if (reussi) { if (estNonVivant(cible)) { - addLineToFramedDisplay(display, nomPerso(cible) + " n'est pas une créature vivante, il ne peut croire à sa mort"); + addLineToFramedDisplay(display, nomPerso(cible) + " n'est pas une cr\xE9ature vivante, il ne peut croire \xE0 sa mort"); sendFramedDisplay(display); return; } if (attributeAsBool(cible, 'limiteParJour_tueurFantasmagorique')) { - addLineToFramedDisplay(display, nomPerso(cible) + " a déjà été victime d'un tueur fantasmagorique aujourd'hui, c'est sans effet"); + addLineToFramedDisplay(display, nomPerso(cible) + " a d\xE9j\xE0 \xE9t\xE9 victime d'un tueur fantasmagorique aujourd'hui, c'est sans effet"); sendFramedDisplay(display); return; } @@ -29986,7 +30366,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, message, 80); }; const saveOpts = { - msgPour: " pour résister au tueur fantasmagorique", + msgPour: " pour r\xE9sister au tueur fantasmagorique", attaquant: attaquant, rolls: options.rolls, chanceRollId: options.chanceRollId, @@ -29996,10 +30376,10 @@ var COFantasy = COFantasy || function() { save(s, cible, saveId, expliquer, saveOpts, evt, function(reussiteSave, texte) { if (reussiteSave) { - addLineToFramedDisplay(display, nomPerso(cible) + " perd l'équilibre et tombe par terre"); + addLineToFramedDisplay(display, nomPerso(cible) + " perd l'\xE9quilibre et tombe par terre"); setState(cible, 'renverse', true, evt); - } else { //save raté - addLineToFramedDisplay(display, nomPerso(cible) + " succombe à ses pires terreurs"); + } else { //save rat\xE9 + addLineToFramedDisplay(display, nomPerso(cible) + " succombe \xE0 ses pires terreurs"); updateCurrentBar(cible, 1, 0, evt); setState(cible, 'mort', true, evt); } @@ -30027,7 +30407,7 @@ var COFantasy = COFantasy || function() { function(display, reussi) { if (reussi) { if (attributeAsBool(cible, 'limiteParJour_enkystementLointain')) { - addLineToFramedDisplay(display, nomPerso(cible) + " a déjà été victime d'un enkystement lointain aujourd'hui, c'est sans effet"); + addLineToFramedDisplay(display, nomPerso(cible) + " a d\xE9j\xE0 \xE9t\xE9 victime d'un enkystement lointain aujourd'hui, c'est sans effet"); sendFramedDisplay(display); return; } @@ -30038,13 +30418,13 @@ var COFantasy = COFantasy || function() { val, roll } = rollDePlus(20); - let message = nomPerso(cible) + " est téléporté" + eForFemale(cible) + " à une distance de "; + let message = nomPerso(cible) + " est t\xE9l\xE9port\xE9" + eForFemale(cible) + " \xE0 une distance de "; if (niveauCible < niveauAttaquant / 2) { - message += (val * 100) + " kilomètres."; + message += (val * 100) + " kilom\xE8tres."; } else if (niveauCible < niveauAttaquant) { - message += roll + " kilomètre" + (val > 1) ? 's' : ''; + message += roll + " kilom\xE8tre" + (val > 1) ? 's' : ''; } else { - message += (val * 10) + " mètres."; + message += (val * 10) + " m\xE8tres."; } addLineToFramedDisplay(display, message); sendFramedDisplay(display); @@ -30060,7 +30440,7 @@ var COFantasy = COFantasy || function() { if (options === undefined || options.cmd === undefined) return; const cmd = options.cmd; if (cmd.length < 3) { - error("Il faut au moins 2 arguments à !cof-injonction-mortelle", cmd); + error("Il faut au moins 2 arguments \xE0 !cof-injonction-mortelle", cmd); return; } let attaquant = persoOfId(cmd[1], cmd[1]); @@ -30097,7 +30477,7 @@ var COFantasy = COFantasy || function() { }); explications.forEach(msg => addLineToFramedDisplay(display, msg, 80)); if (attributeAsBool(cible, 'injonctionMortelle')) { - addLineToFramedDisplay(display, nomPerso(cible) + " a déjà été victime d'une injonction mortelle ce combat, c'est sans effet"); + addLineToFramedDisplay(display, nomPerso(cible) + " a d\xE9j\xE0 \xE9t\xE9 victime d'une injonction mortelle ce combat, c'est sans effet"); sendFramedDisplay(display); return; } @@ -30108,8 +30488,8 @@ var COFantasy = COFantasy || function() { } setTokenAttr(cible, 'injonctionMortelle', true, evt); let saveOpts = { - msgPour: " pour résister à l'injonction mortelle", - msgRate: ", raté.", + msgPour: " pour r\xE9sister \xE0 l'injonction mortelle", + msgRate: ", rat\xE9.", attaquant: attaquant, rolls: options.rolls, chanceRollId: options.chanceRollId, @@ -30142,7 +30522,7 @@ var COFantasy = COFantasy || function() { cible.attaquant = attaquant; dealDamage(cible, dmg, [], evt, false, options, explicationsDmg, function(dmgDisplay, dmgFinal) { addLineToFramedDisplay(display, - name + " reçoit " + dmgDisplay + " DM"); + name + " re\xE7oit " + dmgDisplay + " DM"); explicationsDmg.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); @@ -30168,7 +30548,7 @@ var COFantasy = COFantasy || function() { } const lanceur = persoOfId(args[1], args[1]); if (lanceur === undefined) { - error("Aucun personnage nommé " + args[1], args); + error("Aucun personnage nomm\xE9 " + args[1], args); return; } const casterCharId = lanceur.charId; @@ -30179,7 +30559,7 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionnée pour le sort de sommeil", playerId); + sendPlayer(msg, "Pas de cible s\xE9lectionn\xE9e pour le sort de sommeil", playerId); return; } let cibles = []; @@ -30188,7 +30568,7 @@ var COFantasy = COFantasy || function() { }); doSommeil(lanceur, cibles, options); }, { - lanceur: lanceur + lanceur }); } @@ -30219,14 +30599,14 @@ var COFantasy = COFantasy || function() { let rollD6 = evt.action.rolls[rollD6Id] || rolls.inlinerolls[d6RollNumber]; evt.action.rolls[rollD6Id] = rollD6; let nbTargetsMax = rollD6.results.total + cha; - let action = "Capacité : Sort de sommeil (max " + nbTargetsMax + " cibles)"; + let action = "Capacit\xE9 : Sort de sommeil (max " + nbTargetsMax + " cibles)"; let display = startFramedDisplay(options.playerId, action, lanceur); let attMag = rolls.inlinerolls[attMagRollNumber].results.total; let targetsWithSave = []; let targetsWithoutSave = []; cibles.forEach(function(perso) { - if (estNonVivant(perso) || predicateAsBool(perso, 'immunite_endormi')) { //le sort de sommeil n'affecte que les créatures vivantes - addLineToFramedDisplay(display, nomPerso(perso) + " n'est pas affecté par le sommeil"); + if (estNonVivant(perso) || predicateAsBool(perso, 'immunite_endormi')) { //le sort de sommeil n'affecte que les cr\xE9atures vivantes + addLineToFramedDisplay(display, nomPerso(perso) + " n'est pas affect\xE9 par le sommeil"); return; } if (predicateAsBool(perso, "liberteDAction")) { @@ -30235,7 +30615,7 @@ var COFantasy = COFantasy || function() { } let pv = perso.token.get('bar1_max'); if (pv > 2 * attMag) { - let line = nomPerso(perso) + " a trop de PV pour être affecté par le sort"; + let line = nomPerso(perso) + " a trop de PV pour \xEAtre affect\xE9 par le sort"; addLineToFramedDisplay(display, line); } else if (pv > attMag) { targetsWithSave.push(perso); @@ -30303,7 +30683,7 @@ var COFantasy = COFantasy || function() { let testId = 'resisteSommeil_' + perso.token.id; testCaracteristique(perso, 'SAG', seuil, testId, options, evt, function(tr) { - let line = "Jet de résistance de " + nomPerso(perso) + ": " + tr.texte; + let line = "Jet de r\xE9sistance de " + nomPerso(perso) + ": " + tr.texte; let sujet = onGenre(perso, 'il', 'elle'); if (tr.reussite) { line += ">=" + seuil + ", " + sujet + " ne s'endort pas." + tr.modifiers; @@ -30328,7 +30708,7 @@ var COFantasy = COFantasy || function() { if (options === undefined || options.cmd === undefined) return; let cmd = options.cmd; if (cmd.length < 3) { - error("Il faut au moins 2 arguments à !cof-attaque-magique-contre-pv", cmd); + error("Il faut au moins 2 arguments \xE0 !cof-attaque-magique-contre-pv", cmd); return; } let attaquant = persoOfId(cmd[1], cmd[1]); @@ -30393,41 +30773,41 @@ var COFantasy = COFantasy || function() { else if (d20roll == 20) reussi = true; else reussi = (attackRoll >= pvMax); if (reussi) { - addLineToFramedDisplay(display, "Attaque réussi !"); + addLineToFramedDisplay(display, "Attaque r\xE9ussi !"); } else { diminueMalediction(attaquant, evt); - addLineToFramedDisplay(display, "L'attaque échoue."); + addLineToFramedDisplay(display, "L'attaque \xE9choue."); } sendFramedDisplay(display); - }); //Fin du jet de dés pour l'attaque + }); //Fin du jet de d\xE9s pour l'attaque } function transeGuerison(msg) { if (stateCOF.combat) { - sendPlayer(msg, "Pas possible de méditer en combat"); + sendPlayer(msg, "Pas possible de m\xE9diter en combat"); return; } const options = parseOptions(msg); if (options === undefined) return; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionnée pour la transe de guérison", playerId); + sendPlayer(msg, "Pas de cible s\xE9lectionn\xE9e pour la transe de gu\xE9rison", playerId); return; } const evt = { - type: "Transe de guérison", + type: "Transe de gu\xE9rison", }; iterSelected(selected, function(perso) { let token = perso.token; - if (attributeAsBool(perso, 'transeDeGuérison')) { - sendPerso(perso, "a déjà médité depuis le dernier combat"); + if (attributeAsBool(perso, 'transeDeGu\xE9rison')) { + sendPerso(perso, "a d\xE9j\xE0 m\xE9dit\xE9 depuis le dernier combat"); return; } let bar1 = parseInt(token.get("bar1_value")); let pvmax = parseInt(token.get("bar1_max")); if (isNaN(bar1) || isNaN(pvmax)) return; if (bar1 >= pvmax) { - sendPerso(perso, "n'a pas besoin de méditer"); + sendPerso(perso, "n'a pas besoin de m\xE9diter"); return; } let sagMod = modCarac(perso, 'sagesse'); @@ -30447,11 +30827,11 @@ var COFantasy = COFantasy || function() { bar1 = pvmax; } updateCurrentBar(perso, 1, bar1, evt); - setTokenAttr(perso, 'transeDeGuérison', true, evt); - sendPerso(perso, "entre en méditation pendant 10 minutes et récupère " + soin + " points de vie."); + setTokenAttr(perso, 'transeDeGu\xE9rison', true, evt); + sendPerso(perso, "entre en m\xE9ditation pendant 10 minutes et r\xE9cup\xE8re " + soin + " points de vie."); }); addEvent(evt); - }); + }, options); } function raceIs(perso, race) { @@ -30463,7 +30843,7 @@ var COFantasy = COFantasy || function() { } function estFee(perso) { - if (predicateAsBool(perso, 'fée')) return true; + if (predicateAsBool(perso, 'f\xE9e')) return true; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.toLowerCase(); @@ -30473,7 +30853,7 @@ var COFantasy = COFantasy || function() { case 'licorne': case 'farfadet': case 'fee': - case 'fée': + case 'f\xE9e': case 'pixie': case 'lutin': return true; @@ -30483,14 +30863,14 @@ var COFantasy = COFantasy || function() { } function estDemon(perso) { - if (predicateAsBool(perso, 'démon')) return true; + if (predicateAsBool(perso, 'd\xE9mon')) return true; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.toLowerCase(); } if (perso.race === '') return false; switch (perso.race) { - case 'démon': + case 'd\xE9mon': case 'demon': case 'balor': case 'marilith': @@ -30542,14 +30922,14 @@ var COFantasy = COFantasy || function() { } function estGeant(perso) { - if (predicateAsBool(perso, 'géant')) return true; + if (predicateAsBool(perso, 'g\xE9ant')) return true; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.toLowerCase(); } if (perso.race === '') return false; switch (perso.race) { - case 'géant': + case 'g\xE9ant': case 'geant': case 'ogre': case 'troll': @@ -30615,7 +30995,7 @@ var COFantasy = COFantasy || function() { return false; } - //Vrai pour les insectes et araignées + //Vrai pour les insectes et araign\xE9es function estInsecte(perso) { if (predicateAsBool(perso, 'insecte')) return true; if (perso.profil === undefined) { @@ -30623,7 +31003,7 @@ var COFantasy = COFantasy || function() { perso.profil = perso.profil.toLowerCase(); } if (perso.profil == 'insecte') return true; - if (perso.profil == 'araignée') return true; + if (perso.profil == 'araign\xE9e') return true; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.toLowerCase(); @@ -30632,7 +31012,7 @@ var COFantasy = COFantasy || function() { if (perso.race.includes('elf') && perso.race.includes('noir')) return true; switch (perso.race) { case 'ankheg': - case 'araignée': + case 'araign\xE9e': case 'araignee': case 'insecte': return true; @@ -30657,18 +31037,18 @@ var COFantasy = COFantasy || function() { case 'drow': case 'haut elfe': case 'halfelin': - case 'géant': + case 'g\xE9ant': case 'geant': case 'ange': case 'barghest': - case 'démon': + case 'd\xE9mon': case 'doppleganger': case 'dryade': case 'gnoll': case 'gobelin': case 'gobelours': case 'hobegobelin': - case 'homme-lézard': + case 'homme-l\xE9zard': case 'kobold': case 'nymphe': case 'ogre': @@ -30690,25 +31070,25 @@ var COFantasy = COFantasy || function() { if (perso.race === '') return false; switch (perso.race) { case 'ankheg': - case 'araignée': + case 'araign\xE9e': case 'araignee': case 'basilic': - case 'béhir': + case 'b\xE9hir': case 'behir': case 'bulette': case 'bison': case 'centaure': case 'cheval': case 'chien': - case 'chimère': + case 'chim\xE8re': case 'chimere': case 'cockatrice': case 'crocodile': case 'dragon': case 'drider': - case 'eléphant': + case 'el\xE9phant': case 'elephant': - case 'éléphant': + case '\xE9l\xE9phant': case 'mammouth': case 'griffon': case 'hipogriffe': @@ -30721,13 +31101,13 @@ var COFantasy = COFantasy || function() { case 'manticore': case 'ours': case 'panthere': - case 'panthère': + case 'panth\xE8re': case 'pegase': - case 'pégase': + case 'p\xE9gase': case 'pieuvre': case 'rat': case 'rhinoceros': - case 'rhinocéros': + case 'rhinoc\xE9ros': case 'sanglier': case 'taureau': case 'tigre': @@ -30759,7 +31139,7 @@ var COFantasy = COFantasy || function() { case 'animal': case 'aigle': case 'araignee': - case 'araignée': + case 'araign\xE9e': case 'basilic': case 'bulette': case 'bison': @@ -30769,8 +31149,8 @@ var COFantasy = COFantasy || function() { case 'chien': case 'crocodile': case 'dinosaure': - case 'éléphant': - case 'eléphant': + case '\xE9l\xE9phant': + case 'el\xE9phant': case 'elephant': case 'gorille': case 'griffon': @@ -30783,11 +31163,11 @@ var COFantasy = COFantasy || function() { case 'manticore': case 'ours': case 'ours-hibou': - case 'panthère': + case 'panth\xE8re': case 'pegase': - case 'pégase': + case 'p\xE9gase': case 'pieuvre': - case 'rhinocéros': + case 'rhinoc\xE9ros': case 'roc': case 'sanglier': case 'serpent': @@ -30807,7 +31187,7 @@ var COFantasy = COFantasy || function() { switch (perso.race) { case 'squelette': case 'zombie': - case 'élémentaire': + case '\xE9l\xE9mentaire': case 'momie': return true; default: @@ -30828,7 +31208,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd.length < 2) { - error("Il faut au moins un argument à !cof-soin", cmd); + error("Il faut au moins un argument \xE0 !cof-soin", cmd); return; } let soigneur = options.lanceur; @@ -30836,7 +31216,7 @@ var COFantasy = COFantasy || function() { let cible; let argSoin; if (cmd.length > 4) { - error("Trop d'arguments à !cof-soin", cmd); + error("Trop d'arguments \xE0 !cof-soin", cmd); } if (cmd.length > 2) { //cof-soin lanceur [cible] montant if (soigneur === undefined) { @@ -30850,7 +31230,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3) { // on a la cible en argument cible = persoOfId(cmd[2], cmd[2], pageId); if (cible === undefined) { - error("Le deuxième argument n'est pas un token valide: " + msg.content, cmd[2]); + error("Le deuxi\xE8me argument n'est pas un token valide: " + msg.content, cmd[2]); return; } argSoin = cmd[3]; @@ -30861,7 +31241,7 @@ var COFantasy = COFantasy || function() { argSoin = cmd[1]; } if (soigneur === undefined && (options.mana || (options.portee !== undefined) || options.limiteParJour || options.limiteParCombat || options.dose || options.limiteSoinsParJour)) { - error("Il faut préciser un soigneur pour ces options d'effet", options); + error("Il faut pr\xE9ciser un soigneur pour ces options d'effet", options); return; } let charId; @@ -30879,11 +31259,11 @@ var COFantasy = COFantasy || function() { if (options.tempeteDeManaIntense) nbDes += options.tempeteDeManaIntense; switch (argSoin) { case 'leger': - effet += ' légers'; + effet += ' l\xE9gers'; if (options.dose === undefined && options.limiteParJour === undefined) options.limiteAttribut = { nom: 'soinsLegers', - message: "ne peut plus lancer de sort de soins légers aujourd'hui", + message: "ne peut plus lancer de sort de soins l\xE9gers aujourd'hui", limite: rangSoin }; let bonusLeger = niveau + predicateAsInt(soigneur, 'voieDuGuerisseur', 0); @@ -30895,11 +31275,11 @@ var COFantasy = COFantasy || function() { if (options.portee === undefined) options.portee = 0; break; case 'modere': - effet += ' modérés'; + effet += ' mod\xE9r\xE9s'; if (options.dose === undefined && options.limiteParJour === undefined) options.limiteAttribut = { nom: 'soinsModeres', - message: "ne peut plus lancer de sort de soins modéréss aujourd'hui", + message: "ne peut plus lancer de sort de soins mod\xE9r\xE9ss aujourd'hui", limite: rangSoin }; if (options.portee === undefined) options.portee = 0; @@ -30953,7 +31333,7 @@ var COFantasy = COFantasy || function() { if (options.dose === undefined && options.limiteParJour === undefined) options.limiteAttribut = { nom: 'attributDeCombat_soinsDeGroupe', - message: " a déjà fait un soin de groupe durant ce combat", + message: " a d\xE9j\xE0 fait un soin de groupe durant ce combat", limite: 1 }; if (options.puissant) soins = "[[1d10"; @@ -30972,14 +31352,14 @@ var COFantasy = COFantasy || function() { case 'secondSouffle': { if (!stateCOF.combat) { - whisperChar(charId, " ne peut pas utiliser la capacité second souffle en dehors des combats"); + whisperChar(charId, " ne peut pas utiliser la capacit\xE9 second souffle en dehors des combats"); return; } effet = "second souffle"; if (options.dose === undefined && options.limiteParJour === undefined) options.limiteAttribut = { nom: 'secondSouffleUtilise', - message: " a déjà repris son souffle durant ce combat", + message: " a d\xE9j\xE0 repris son souffle durant ce combat", limite: 1 }; soins = "[[1d10+"; @@ -30989,8 +31369,8 @@ var COFantasy = COFantasy || function() { soins += "]]"; cible = soigneur; options.recuperation = true; - if (bonus == -1 || bonus > 0) { //Il y a un prédicat second souffle - //On limite les soins à ce qui a été perdu dans ce combat + if (bonus == -1 || bonus > 0) { //Il y a un pr\xE9dicat second souffle + //On limite les soins \xE0 ce qui a \xE9t\xE9 perdu dans ce combat const pvDebut = attributeAsInt(soigneur, 'PVsDebutCombat', 0); let pv = parseInt(soigneur.token.get('bar1_value')); if (isNaN(pv)) return; @@ -31039,7 +31419,7 @@ var COFantasy = COFantasy || function() { const playerId = getPlayerIdFromMsg(msg); if (options.tempeteDeMana && soigneur) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options const optMana = { mana: options.mana, rang: options.rang, @@ -31051,7 +31431,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(soigneur, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPerso(soigneur, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -31060,7 +31440,7 @@ var COFantasy = COFantasy || function() { soins = res[0].inlinerolls[0].results.total; let soinTxt = buildinline(res[0].inlinerolls[0], 'normal', true); if (soins <= 0) { - sendChar(charId, "ne réussit pas à soigner (total de soins " + soinTxt + ")", true); + sendChar(charId, "ne r\xE9ussit pas \xE0 soigner (total de soins " + soinTxt + ")", true); return; } const evt = { @@ -31093,7 +31473,7 @@ var COFantasy = COFantasy || function() { if (nbCibles > 1) { display = startFramedDisplay(playerId, effet, soigneur); } else if (nbCibles === 0) { - sendChar(charId, "personne à soigner", true); + sendChar(charId, "personne \xE0 soigner", true); return; } iterSelected(selected, callback); @@ -31139,7 +31519,7 @@ var COFantasy = COFantasy || function() { let utilisations = attributeAsInt(cible, ressourceLimiteCibleParJour, options.limiteCibleParJour); if (utilisations === 0) { - sendPerso(cible, "ne peut plus bénéficier de " + effet + " aujourd'hui"); + sendPerso(cible, "ne peut plus b\xE9n\xE9ficier de " + effet + " aujourd'hui"); finSoin(); return; } @@ -31175,11 +31555,11 @@ var COFantasy = COFantasy || function() { return; } if (display) { - addLineToFramedDisplay(display, "Résultat des dés : " + soinTxt); + addLineToFramedDisplay(display, "R\xE9sultat des d\xE9s : " + soinTxt); } if (msg.content.includes(' --sacrifierPV')) { //paie autant de PV que soins if (soigneur === undefined) { - error("Il faut préciser qui est le soigneur pour utiliser l'option --sacrifierPV", msg.content); + error("Il faut pr\xE9ciser qui est le soigneur pour utiliser l'option --sacrifierPV", msg.content); soinImpossible = true; display = undefined; finSoin(); @@ -31214,7 +31594,7 @@ var COFantasy = COFantasy || function() { let pv = parseInt(cible.token.get('bar1_value')); if (isNaN(pv) || pv > 0) { let sort = (souffleDeVie > 0) ? "souffle de vie" : "premiers soins"; - let m = nomPerso(cible) + " n'est pas à 0 PV, impossible d'utiliser " + sort + " pour " + onGenre(cible, 'lui', 'elle'); + let m = nomPerso(cible) + " n'est pas \xE0 0 PV, impossible d'utiliser " + sort + " pour " + onGenre(cible, 'lui', 'elle'); if (display) addLineToFramedDisplay(display, m); else sendChar(charId, m, true); finSoin(); @@ -31234,7 +31614,7 @@ var COFantasy = COFantasy || function() { } } if (tropTard) { - let m = nomPerso(cible) + " est à 0 PV depuis plus de 2 tours, impossible d'utiliser le souffle de vie pour " + onGenre(cible, 'lui', 'elle'); + let m = nomPerso(cible) + " est \xE0 0 PV depuis plus de 2 tours, impossible d'utiliser le souffle de vie pour " + onGenre(cible, 'lui', 'elle'); if (display) addLineToFramedDisplay(display, m); else sendChar(charId, m, true); finSoin(); @@ -31268,7 +31648,7 @@ var COFantasy = COFantasy || function() { } else { maxMsg += "soigner " + nomCible; } - sendChar(charId, maxMsg + ". " + Sujet + " est déjà au maximum de PV", true); + sendChar(charId, maxMsg + ". " + Sujet + " est d\xE9j\xE0 au maximum de PV", true); } }; let extraImg = afficheOptionImage(options); @@ -31288,9 +31668,9 @@ var COFantasy = COFantasy || function() { msgSoin = 'soigne ' + nomCible; } msgSoin += " de "; - if (options.recuperation) msgSoin = "récupère "; + if (options.recuperation) msgSoin = "r\xE9cup\xE8re "; if (limiteSoinsAtteinte || s != soins) - msgSoin += s + " PV. (Le résultat du jet était " + soinTxt + ")"; + msgSoin += s + " PV. (Le r\xE9sultat du jet \xE9tait " + soinTxt + ")"; else msgSoin += soinTxt + " PV."; msgSoin += extraImg; sendChar(charId, msgSoin, true); @@ -31299,7 +31679,7 @@ var COFantasy = COFantasy || function() { let callTrueFinal = printTrue; if (msg.content.includes(' --transfer')) { //paie avec ses PV if (soigneur === undefined) { - error("Il faut préciser qui est le soigneur pour utiliser l'option --transfer", msg.content); + error("Il faut pr\xE9ciser qui est le soigneur pour utiliser l'option --transfer", msg.content); soinImpossible = true; finSoin(); return; @@ -31342,15 +31722,15 @@ var COFantasy = COFantasy || function() { soigneToken(cible, soins, evt, callTrueFinal, callMax, options); finSoin(); }); //fin de iterCibles - }); //fin du sendChat du jet de dés + }); //fin du sendChat du jet de d\xE9s } catch (e) { if (soins) { log(msg.content); - log("L'expression des soins était " + soins + ", et il y a eu une erreur durant son évaluation"); + log("L'expression des soins \xE9tait " + soins + ", et il y a eu une erreur durant son \xE9valuation"); if (argSoin) { - error("L'expression des soins (" + argSoin + ") n'est pas bien formée", msg.content); + error("L'expression des soins (" + argSoin + ") n'est pas bien form\xE9e", msg.content); } else { - error("Erreur pendant l'évaluation de l'expression des soins. Plus d'informations dans le log", msg); + error("Erreur pendant l'\xE9valuation de l'expression des soins. Plus d'informations dans le log", msg); } } else { error("Erreur pendant les soins ", msg.content); @@ -31394,7 +31774,7 @@ var COFantasy = COFantasy || function() { } function ajouterConsommable(perso, nom, nb, action, evt) { - if (perso.token.get('bar1_link') === '') { //Perso non lié, on utilise un attribut + if (perso.token.get('bar1_link') === '') { //Perso non li\xE9, on utilise un attribut let attrName = 'dose_' + nom; let attr = tokenAttribute(perso, attrName); if (attr.length > 0) { @@ -31416,7 +31796,7 @@ var COFantasy = COFantasy || function() { maxVal: action }); } - } else { //On va mettre les consommables dans l'équipement + } else { //On va mettre les consommables dans l'\xE9quipement let attributes = findObjs({ _type: 'attribute', _characterid: perso.charId @@ -31466,7 +31846,7 @@ var COFantasy = COFantasy || function() { }); return true; }); - // si le consommable n'a pas été trouvé, on le crée avec une valeur de nb + // si le consommable n'a pas \xE9t\xE9 trouv\xE9, on le cr\xE9e avec une valeur de nb if (!found) { let pref = 'repeating_equipement_' + generateRowID() + '_'; let attre = createObj("attribute", { @@ -31506,11 +31886,11 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(lanceur) { let voieDeLaSurvie = predicateAsInt(lanceur, 'voieDeLaSurvie', 0); if (voieDeLaSurvie < 1) { - sendPerso(lanceur, " ne connaît pas la Voie de la Survie ?"); + sendPerso(lanceur, " ne conna\xEEt pas la Voie de la Survie ?"); } doNatureNourriciere(lanceur, options); }); - }); + }, options); } function doNatureNourriciere(perso, options) { @@ -31532,7 +31912,7 @@ var COFantasy = COFantasy || function() { } let output = "cherche des herbes. "; if (trouveBaies) output = "cherche des baies. "; - output += "Après " + evt.action.rolls.duree.roll + " heure"; + output += "Apr\xE8s " + evt.action.rolls.duree.roll + " heure"; if (evt.action.rolls.duree.val > 1) output += "s"; output += ", " + onGenre(perso, "il", "elle"); const testId = 'natureNourriciere'; @@ -31541,11 +31921,11 @@ var COFantasy = COFantasy || function() { let post = ""; if ((tr.reussite && !trouveBaies) || (trouveBaies && !tr.reussite && tr.valeur > 7)) { if (voieDeLaSurvie > 0) { - output += " revient avec " + voieDeLaSurvie + " plantes médicinales." + tr.modifiers; + output += " revient avec " + voieDeLaSurvie + " plantes m\xE9dicinales." + tr.modifiers; let actionHerbes = "!cof-soin @{selected|token_id} @{selected|token_id} 1d6"; - ajouterConsommable(perso, 'Plante médicinale', voieDeLaSurvie, actionHerbes, evt); + ajouterConsommable(perso, 'Plante m\xE9dicinale', voieDeLaSurvie, actionHerbes, evt); } else { - output += " revient avec de quoi soigner les blessés." + tr.modifiers; + output += " revient avec de quoi soigner les bless\xE9s." + tr.modifiers; } } else if (tr.reussite && trouveBaies) { let niveau = ficheAttributeAsInt(perso, 'niveau', 1); @@ -31568,10 +31948,10 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; let evtARefaire = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } @@ -31579,11 +31959,11 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(chevalier) { let token = chevalier.token; if (attributeAsInt(chevalier, 'douleurIgnoree', 0) > 0) { - sendPerso(chevalier, "a déjà ignoré la doubleur une fois pendant ce combat"); + sendPerso(chevalier, "a d\xE9j\xE0 ignor\xE9 la doubleur une fois pendant ce combat"); return; } if (evtARefaire === undefined || evtARefaire.type === undefined || !evtARefaire.type.startsWith('Attaque')) { - sendPerso(chevalier, "s'y prend trop tard pour ignorer la douleur : la dernière action n'était pas une attaque"); + sendPerso(chevalier, "s'y prend trop tard pour ignorer la douleur : la derni\xE8re action n'\xE9tait pas une attaque"); return; } let aIgnore; @@ -31591,18 +31971,18 @@ var COFantasy = COFantasy || function() { type: 'ignorer la douleur' }; let PVid = token.get('bar1_link'); - if (PVid === '') { //token non lié, effets seulement sur le token. + if (PVid === '') { //token non li\xE9, effets seulement sur le token. if (evtARefaire.affecte) { let affecte = evtARefaire.affectes[token.id]; if (affecte && affecte.prev) { let lastBar1 = affecte.prev.bar1_value; let bar1 = parseInt(token.get('bar1_value')); if (isNaN(lastBar1) || isNaN(bar1) || lastBar1 <= bar1) { - //On regarde la barre 2, peut-être qu'il s'agit de DM temporaires + //On regarde la barre 2, peut-\xEAtre qu'il s'agit de DM temporaires let lastBar2 = affecte.prev.bar2_value; let bar2 = parseInt(token.get('bar2_value')); if (isNaN(lastBar2) || isNaN(bar2) || bar2 <= lastBar2) { - sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la dernière attaque ne lui ait pas enlevé de PV"); + sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la derni\xE8re attaque ne lui ait pas enlev\xE9 de PV"); return; } updateCurrentBar(chevalier, 2, lastBar2, evt); @@ -31615,7 +31995,7 @@ var COFantasy = COFantasy || function() { } } } - } else { // token lié, il faut regarder l'attribut + } else { // token li\xE9, il faut regarder l'attribut let attrPV = evtARefaire.attributes.find(function(attr) { return (attr.attribute.id == PVid); }); @@ -31623,13 +32003,13 @@ var COFantasy = COFantasy || function() { let lastPV = attrPV.current; let newPV = attrPV.attribute.get('current'); if (isNaN(lastPV) || isNaN(newPV) || lastPV <= newPV) { - sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la dernière attaque ne lui ait pas enlevé de PV"); + sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la derni\xE8re attaque ne lui ait pas enlev\xE9 de PV"); return; } updateCurrentBar(chevalier, 1, lastPV, evt); setTokenAttr(chevalier, 'douleurIgnoree', lastPV - newPV, evt); aIgnore = true; - } else { //peut-être qu'il s'agit de DM temporaires + } else { //peut-\xEAtre qu'il s'agit de DM temporaires PVid = token.get('bar2_link'); attrPV = evtARefaire.attributes.find(function(attr) { return (attr.attribute.id == PVid); @@ -31638,7 +32018,7 @@ var COFantasy = COFantasy || function() { let lastDmTemp = attrPV.current; let newDmTemp = attrPV.attribute.get('current'); if (isNaN(lastDmTemp) || isNaN(newDmTemp) || newDmTemp <= lastDmTemp) { - sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la dernière attaque ne lui ait pas augmenté les DM temporaires"); + sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la derni\xE8re attaque ne lui ait pas augment\xE9 les DM temporaires"); return; } updateCurrentBar(chevalier, 2, lastDmTemp, evt); @@ -31648,13 +32028,13 @@ var COFantasy = COFantasy || function() { } } if (aIgnore) { - sendPerso(chevalier, " ignore la douleur de la dernière attaque"); + sendPerso(chevalier, " ignore la douleur de la derni\xE8re attaque"); addEvent(evt); } else { - sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la dernière attaque ne l'ait pas affecté"); + sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la derni\xE8re attaque ne l'ait pas affect\xE9"); } }); - }); + }, options); } function fortifiant(msg) { @@ -31662,7 +32042,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("La fonction !cof-fortifiant attend en argument le rang dans la Voie des élixirs du créateur", cmd); + error("La fonction !cof-fortifiant attend en argument le rang dans la Voie des \xE9lixirs du cr\xE9ateur", cmd); return; } const rang = parseInt(cmd[1]); @@ -31683,19 +32063,19 @@ var COFantasy = COFantasy || function() { }); sendPerso(beneficiaire, " boit un fortifiant"); soigneToken(beneficiaire, soins.val, evt, function(soinsEffectifs) { - let msgSoins = "et est soigné de "; + let msgSoins = "et est soign\xE9 de "; if (soinsEffectifs == soins.val) msgSoins += soins.roll + " PV"; - else msgSoins += soinsEffectifs + " PV (le jet était " + soins.roll + ")"; + else msgSoins += soinsEffectifs + " PV (le jet \xE9tait " + soins.roll + ")"; sendPerso(beneficiaire, msgSoins); }); // Finalement on met l'effet fortifie setTokenAttr(beneficiaire, 'fortifie', rang + 1, evt); }); - }); + }, options); } //Appliquer une huile instable sur l'arme de la cible - // Par défaut, c'est l'arme en main de la cible + // Par d\xE9faut, c'est l'arme en main de la cible // TODO: le faire pour les projectiles // !cof-huile-instable @{target|token_id} function huileInstable(msg) { @@ -31744,7 +32124,7 @@ var COFantasy = COFantasy || function() { _id: options.lanceur.token.id }]; } else { - error("Pas de token sélectionée pour !cof-lancer-sort", cmd); + error("Pas de token s\xE9lection\xE9e pour !cof-lancer-sort", cmd); return; } } @@ -31756,7 +32136,7 @@ var COFantasy = COFantasy || function() { let lanceur = options.lanceur; if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, dm: false, @@ -31769,7 +32149,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(lanceur, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPerso(lanceur, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -31782,7 +32162,7 @@ var COFantasy = COFantasy || function() { if (!options.lanceur) { if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options const optMana = { mana: options.mana, dm: false, @@ -31795,7 +32175,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(cible, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPerso(cible, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -31845,11 +32225,11 @@ var COFantasy = COFantasy || function() { sendChat(nomPerso, cmd.join(' ')); } - // Renvoie la durée mise à jour ou undefined si l'action n'est pas possible + // Renvoie la dur\xE9e mise \xE0 jour ou undefined si l'action n'est pas possible function lancerMurDeForce(lanceur, playerId, duree, msg, typeMur, evt, options) { if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, dm: false, @@ -31862,7 +32242,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(lanceur, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPerso(lanceur, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -31885,7 +32265,7 @@ var COFantasy = COFantasy || function() { } //!cof-mur-de-force [opt] [duree] - // opt peut être mur, noImage ou vent + // opt peut \xEAtre mur, noImage ou vent // On peut changer la taille du mur avec l'option --portee. function murDeForce(msg) { let options = parseOptions(msg); @@ -31915,13 +32295,13 @@ var COFantasy = COFantasy || function() { if (cmd.length > 2) { duree = parseInt(cmd[2]); if (isNaN(duree) || duree < 1) { - error("Le deuxième argument de !cof-mur-de-force doit être une durée", cmd); + error("Le deuxi\xE8me argument de !cof-mur-de-force doit \xEAtre une dur\xE9e", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Aucun personnage sélectionné pour lancer le mur de " + typeMur, playerId); + sendPlayer(msg, "Aucun personnage s\xE9lectionn\xE9 pour lancer le mur de " + typeMur, playerId); return; } const evt = { @@ -31974,7 +32354,7 @@ var COFantasy = COFantasy || function() { if (options.puissantDuree || options.tempeteDeManaDuree) duree += duree; setAttrDuree(cible, 'murDeForce', duree, evt); } else { - error("Impossible de créer l'image " + options.image, imageFields); + error("Impossible de cr\xE9er l'image " + options.image, imageFields); } } else { sendPlayerAndGM(msg, playerId, "placer l'image du mur sur la carte"); @@ -32021,7 +32401,7 @@ var COFantasy = COFantasy || function() { } else { capitaine = persoOfId(cmd[1], cmd[1]); if (capitaine === undefined) { - error("Le premier argument de !cof-capitaine doit être un token", cmd[1]); + error("Le premier argument de !cof-capitaine doit \xEAtre un token", cmd[1]); return; } setState(capitaine, 'chef', true, evt); @@ -32029,7 +32409,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 2 && !cmd[2].startsWith('--')) { bonus = parseInt(cmd[2]); if (isNaN(bonus) || bonus < 0) { - error("Le bonus de capitaine (second argument) doit être un nombre positif", cmd); + error("Le bonus de capitaine (second argument) doit \xEAtre un nombre positif", cmd); return; } if (bonus === 0) remove = true; @@ -32038,7 +32418,7 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected) { if (selected.length === 0) { - error("Pas de token sélectionné pour !cof-capitaine"); + error("Pas de token s\xE9lectionn\xE9 pour !cof-capitaine"); return; } iterSelected(selected, function(perso) { @@ -32063,12 +32443,12 @@ var COFantasy = COFantasy || function() { function distribuerBaies(msg) { if (msg.selected === undefined || msg.selected.length != 1) { - error("Pour utiliser !cof-distribuer-baies, il faut sélectionner un token", msg); + error("Pour utiliser !cof-distribuer-baies, il faut s\xE9lectionner un token", msg); return; } let druide = persoOfId(msg.selected[0]._id); if (druide === undefined) { - error("Erreur de sélection dans !cof-distribuer-baies", msg.selected); + error("Erreur de s\xE9lection dans !cof-distribuer-baies", msg.selected); return; } let niveau = ficheAttributeAsInt(druide, 'niveau', 1); @@ -32082,7 +32462,7 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(perso) { let nom = nomPerso(perso); ajouterConsommable(perso, 'Baie magique', 1, mangerBaie, evt); - let line = nom + " reçoit une baie"; + let line = nom + " re\xE7oit une baie"; if (perso.token.id == druide.token.id) line = nom + " en garde une pour " + onGenre(druide, "lui", "elle"); addLineToFramedDisplay(display, line); @@ -32100,17 +32480,17 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd.length < 2) { - error("Il faut un argument à !cof-consommer-baie", cmd); + error("Il faut un argument \xE0 !cof-consommer-baie", cmd); return; } let baie = parseInt(cmd[1]); if (isNaN(baie) || baie < 0) { - error("L'argument de !cof-consommer-baie doit être un nombre positif", cmd); + error("L'argument de !cof-consommer-baie doit \xEAtre un nombre positif", cmd); return; } getSelected(msg, function(selected, playerId) { if (selected === undefined) { - sendPlayer(msg, "Pas de token sélectionné pour !cof-consommer-baie", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof-consommer-baie", playerId); return; } const evt = { @@ -32118,21 +32498,21 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); iterSelected(selected, function(perso) { - if (limiteRessources(perso, options, 'baieMagique', "a déjà mangé une baie aujourd'hui. Pas d'effet.", evt)) return; + if (limiteRessources(perso, options, 'baieMagique', "a d\xE9j\xE0 mang\xE9 une baie aujourd'hui. Pas d'effet.", evt)) return; let soins = rollDePlus(6, { bonus: baie }); soigneToken(perso, soins.val, evt, function(soinsEffectifs) { let msgSoins = "mange une baie magique. " + - onGenre(perso, "Il est rassasié", "Elle est rassasiée") + - " et récupère "; + onGenre(perso, "Il est rassasi\xE9", "Elle est rassasi\xE9e") + + " et r\xE9cup\xE8re "; if (soinsEffectifs == soins.val) msgSoins += soins.roll + " points de vie"; - else msgSoins += soinsEffectifs + " PV (le jet était " + soins.roll + ")"; + else msgSoins += soinsEffectifs + " PV (le jet \xE9tait " + soins.roll + ")"; sendPerso(perso, msgSoins); }, function() { - sendPerso(perso, "mange une baie magique. " + onGenre(perso, "Il", "Elle") + " se sent rassasié" + onGenre(perso, '', 'e') + '.'); + sendPerso(perso, "mange une baie magique. " + onGenre(perso, "Il", "Elle") + " se sent rassasi\xE9" + onGenre(perso, '', 'e') + '.'); }); }); }); //fin de getSelected @@ -32152,9 +32532,9 @@ var COFantasy = COFantasy || function() { } } - /* Quand on protège un allié, on stocke l'idName dans un attribut 'protegerUnAllie', et pour ce token, on met un - * attribut 'protegePar_nom' où nom est le nom du token protecteur, et qui contient l'idName du protecteur - * Ces attributs disparaissent à la fin des combats */ + /* Quand on prot\xE8ge un alli\xE9, on stocke l'idName dans un attribut 'attributDeComat_protegerUnAllie', et pour ce token, on met un + * attribut 'protegePar_nom' o\xF9 nom est le nom du token protecteur, et qui contient l'idName du protecteur + * Ces attributs disparaissent \xE0 la fin des combats */ function protegerUnAllie(msg) { let args = msg.content.split(' '); if (args.length < 3) { @@ -32171,53 +32551,53 @@ var COFantasy = COFantasy || function() { let pageId = tokenProtecteur.get('pageid'); let target = persoOfId(args[2], args[2], pageId); if (target === undefined) { - error("Le deuxième argument n'est pas un token valide: " + msg.content, args[2]); + error("Le deuxi\xE8me argument n'est pas un token valide: " + msg.content, args[2]); return; } let tokenTarget = target.token; if (tokenTarget.id == tokenProtecteur.id) { - sendPerso(protecteur, "ne peut pas se protéger i" + onGenre(protecteur, 'lui', 'elle') + "-même"); + sendPerso(protecteur, "ne peut pas se prot\xE9ger i" + onGenre(protecteur, 'lui', 'elle') + "-m\xEAme"); return; } const nameTarget = nomPerso(target); const evt = { - type: "Protéger un allié" + type: "Prot\xE9ger un alli\xE9" }; - let attrsProtecteur = tokenAttribute(protecteur, 'protegerUnAllie'); + let attrsProtecteur = tokenAttribute(protecteur, 'attributDeCombat_protegerUnAllie'); let protegePar = 'protegePar_' + nameProtecteur; let other; - if (attrsProtecteur.length > 0) { //On protège déjà quelqu'un + if (attrsProtecteur.length > 0) { //On prot\xE8ge d\xE9j\xE0 quelqu'un let previousTarget = persoOfIdName(attrsProtecteur[0].get('current'), pageId); if (previousTarget) { if (previousTarget.token.id == tokenTarget.id) { - sendPerso(protecteur, "protège déjà " + nameTarget); + sendPerso(protecteur, "prot\xE8ge d\xE9j\xE0 " + nameTarget); return; } - if (predicateAsBool(protecteur, 'protegerUnAllieAvance')) { + if (predicateAsBool(protecteur, 'attributDeCombat_protegerUnAllieAvance')) { let previousTarget2 = persoOfIdName(attrsProtecteur[0].get('max'), pageId); if (previousTarget2) { if (previousTarget2.token.id == tokenTarget.id) { - sendPerso(protecteur, "protège déjà " + nameTarget); + sendPerso(protecteur, "prot\xE8ge d\xE9j\xE0 " + nameTarget); return; } removeTokenAttr(previousTarget2, protegePar, evt, { - msg: "n'est plus protégé par " + nameProtecteur + msg: "n'est plus prot\xE9g\xE9 par " + nameProtecteur }); } else { other = attrsProtecteur[0].get('current'); } } removeTokenAttr(previousTarget, protegePar, evt, { - msg: "n'est plus protégé par " + nameProtecteur + msg: "n'est plus prot\xE9g\xE9 par " + nameProtecteur }); } } let distTargetProtecteur = distanceCombat(target.token, protecteur.token, pageId); if (distTargetProtecteur > 0) { sendPerso(protecteur, "est trop loin de " + - nameTarget + " pour le protéger"); + nameTarget + " pour le prot\xE9ger"); return; } if (ficheAttributeAsInt(protecteur, 'defbouclieron', 0) === 0) { @@ -32230,30 +32610,30 @@ var COFantasy = COFantasy || function() { maxVal: '' }; if (other === undefined) { - setTokenAttr(protecteur, 'protegerUnAllie', idName(target), evt, opt); + setTokenAttr(protecteur, 'attributDeCombat_protegerUnAllie', idName(target), evt, opt); } else { opt.maxVal = idName(target); - setTokenAttr(protecteur, 'protegerUnAllie', other, evt, opt); + setTokenAttr(protecteur, 'attributDeCombat_protegerUnAllie', other, evt, opt); } setTokenAttr(target, protegePar, idName(protecteur), evt); - sendPerso(protecteur, "protège " + nameTarget); + sendPerso(protecteur, "prot\xE8ge " + nameTarget); addEvent(evt); } function actionDefensive(msg) { let combat = stateCOF.combat; if (!combat) { - sendPlayer(msg, "Il faut entrer en combat pour se défendre"); + sendPlayer(msg, "Il faut entrer en combat pour se d\xE9fendre"); return; } let cmd = msg.content.split(' '); - let def = 2; //pour une défense simple - let defMsg = "préfère se défendre pendant ce tour"; + let def = 2; //pour une d\xE9fense simple + let defMsg = "pr\xE9f\xE8re se d\xE9fendre pendant ce tour"; if (cmd.length > 1) { switch (cmd[1]) { case 'totale': def = 4; - defMsg = "se consacre entièrement à sa défense pendant ce tour"; + defMsg = "se consacre enti\xE8rement \xE0 sa d\xE9fense pendant ce tour"; break; case 'simple': def = 2; @@ -32263,7 +32643,7 @@ var COFantasy = COFantasy || function() { } } const evt = { - type: "action défensive" + type: "action d\xE9fensive" }; getSelected(msg, function(selected) { initiative(selected, evt); @@ -32278,20 +32658,20 @@ var COFantasy = COFantasy || function() { } function strangulation(msg) { - var args = msg.content.split(' '); + const args = msg.content.split(' '); if (args.length < 3) { error("Pas assez d'arguments pour !cof-strangulation: " + msg.content, args); return; } - var necromancien = persoOfId(args[1], args[1]); + const necromancien = persoOfId(args[1], args[1]); if (necromancien === undefined) { error("Le premier argument n'est pas un token", args[1]); return; } - var pageId = necromancien.token.get('pageid'); - var target = persoOfId(args[2], args[2], pageId); + let pageId = necromancien.token.get('pageid'); + const target = persoOfId(args[2], args[2], pageId); if (target === undefined) { - error("Le deuxième argument n'est pas un token valide: " + msg.content, args[2]); + error("Le deuxi\xE8me argument n'est pas un token valide: " + msg.content, args[2]); return; } let name2 = nomPerso(target); @@ -32299,15 +32679,15 @@ var COFantasy = COFantasy || function() { sendPerso(necromancien, "ne peut pas maintenir la strangulation. Il faut (re)lancer le sort"); return; } - var evt = { + const evt = { type: "Strangulation" }; - var dureeStrang = tokenAttribute(target, 'dureeStrangulation'); - var nouvelleDuree = 1; + let dureeStrang = tokenAttribute(target, 'dureeStrangulation'); + let nouvelleDuree = 1; if (dureeStrang.length > 0) { nouvelleDuree = parseInt(dureeStrang[0].get('current')); if (isNaN(nouvelleDuree)) { - log("Durée de strangulation n'est pas un nombre"); + log("Dur\xE9e de strangulation n'est pas un nombre"); log(dureeStrang); nouvelleDuree = 1; } else nouvelleDuree++; @@ -32323,7 +32703,7 @@ var COFantasy = COFantasy || function() { else if (modInt < 0) dmgExpr += modInt; dmgExpr += "]]"; sendChat('', dmgExpr, function(res) { - var dmg = { + const dmg = { type: 'magique', total: res[0].inlinerolls[0].results.total, display: buildinline(res[0].inlinerolls[0], 'normal', true), @@ -32340,27 +32720,27 @@ var COFantasy = COFantasy || function() { function ombreMortelle(msg) { - var options = parseOptions(msg); + const options = parseOptions(msg); if (options === undefined) return; - var cmd = options.cmd; + const cmd = options.cmd; if (cmd === undefined || cmd.length < 4) { error("Pas assez d'arguments pour " + cmd[0], cmd); return; } - var lanceur = persoOfId(cmd[1], cmd[1]); + const lanceur = persoOfId(cmd[1], cmd[1]); if (lanceur === undefined) { error("Le premier argument n'est pas un token valide", cmd[1]); return; } - var pageId = options.pageId || lanceur.token.get('pageid'); - var cible = persoOfId(cmd[2], cmd[2], pageId); + const pageId = options.pageId || lanceur.token.get('pageid'); + const cible = persoOfId(cmd[2], cmd[2], pageId); if (cible === undefined) { error("La cible n'est pas un token valide", cmd[2]); return; } let duree = parseInt(cmd[3]); if (isNaN(duree) || duree <= 0) { - error("La durée doit être un nombre positif", cmd); + error("La dur\xE9e doit \xEAtre un nombre positif", cmd); return; } let image = options.image || stateCOF.options.images.val.image_ombre.val; @@ -32378,13 +32758,13 @@ var COFantasy = COFantasy || function() { let msgRes = "invoquer une ombre mortelle"; if (limiteRessources(lanceur, options, "Ombre_mortelle", msgRes, evt)) return; copieToken(cible, image, stateCOF.options.images.val.image_ombre.val, "Ombre de " + nomPerso(cible), 'ombreMortelle', duree, pageId, evt); - let msgOmbre = "anime l'ombre de " + cible.tokName + ". Celle-ci commence à attaquer " + cible.tokName + " !"; + let msgOmbre = "anime l'ombre de " + cible.tokName + ". Celle-ci commence \xE0 attaquer " + cible.tokName + " !"; if (options.secret) whisperChar(lanceur.charId, msgOmbre); else sendPerso(lanceur, msgOmbre); addEvent(evt); } - //renvoie l'attribut de l'effet temporaire créé + //renvoie l'attribut de l'effet temporaire cr\xE9\xE9 function copieToken(cible, image1, image2, nom, effet, duree, pageId, evt) { let pv = parseInt(cible.token.get('bar1_value')); if (isNaN(pv)) { @@ -32431,7 +32811,7 @@ var COFantasy = COFantasy || function() { newToken = createObj('graphic', tokenFields); } if (newToken === undefined) { - error("L'image du token sélectionné n'a pas été uploadé, et l'image par défaut n'est pas correcte. Impossible de créer un token.", tokenFields); + error("L'image du token s\xE9lectionn\xE9 n'a pas \xE9t\xE9 upload\xE9, et l'image par d\xE9faut n'est pas correcte. Impossible de cr\xE9er un token.", tokenFields); return; } } @@ -32447,12 +32827,12 @@ var COFantasy = COFantasy || function() { return attr; } - //retourne true si le joueur est effectivement déplacé + //retourne true si le joueur est effectivement d\xE9plac\xE9 function movePlayerToPage(pid, oldPageId, newPageId) { if (getObj('player', pid) === undefined) return; - var c = Campaign(); - var playerPages = c.get('playerspecificpages'); - var playersMainPage = c.get('playerpageid'); + const c = Campaign(); + let playerPages = c.get('playerspecificpages'); + const playersMainPage = c.get('playerpageid'); if (!playerPages) playerPages = {}; if ((playerPages[pid] && playerPages[pid] == oldPageId)) { if (playersMainPage == newPageId) { @@ -32468,10 +32848,10 @@ var COFantasy = COFantasy || function() { } } else if ((!playerPages[pid] && playersMainPage == oldPageId)) { playerPages[pid] = newPageId; - var allPlayers = findObjs({ + let allPlayers = findObjs({ _type: 'player' }); - var allOnNewPage = allPlayers.every(function(p) { + let allOnNewPage = allPlayers.every(function(p) { if (playerIsGM(p.id)) return true; return playerPages[p.id] == newPageId; }); @@ -32485,8 +32865,8 @@ var COFantasy = COFantasy || function() { } function findEsc(escaliers, escName, i) { - var fullEscName = escName + labelsEscalier[i]; - var sortieEscalier = escaliers.find(function(esc) { + let fullEscName = escName + labelsEscalier[i]; + let sortieEscalier = escaliers.find(function(esc) { return esc.get('name') == fullEscName; }); if (sortieEscalier === undefined && i > 0) return findEsc(escName, i - 1); @@ -32500,17 +32880,17 @@ var COFantasy = COFantasy || function() { return ((pos2 + size2 / 2) >= pos1 - size1 / 2); } - var labelsEscalier = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]; + const labelsEscalier = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]; function escalier(msg) { getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de sélection de token pour !cof-escalier", playerId); - log("!cof-escalier requiert de sélectionner des tokens"); + sendPlayer(msg, "Pas de s\xE9lection de token pour !cof-escalier", playerId); + log("!cof-escalier requiert de s\xE9lectionner des tokens"); return; } let pageId = getObj('graphic', selected[0]._id).get('pageid'); - var escaliers = findObjs({ + let escaliers = findObjs({ _type: 'graphic', _pageid: pageId, layer: 'gmlayer' @@ -32519,9 +32899,9 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "Pas de token dans le layer GM", playerId); return; } - var tmaps; //Les passages entre les maps. - var versLeHaut = true; - var loop = true; + let tmaps; //Les passages entre les maps. + let versLeHaut = true; + let loop = true; if (msg.content) { if (msg.content.includes(' bas')) { versLeHaut = false; @@ -32532,22 +32912,22 @@ var COFantasy = COFantasy || function() { } } iterSelected(selected, function(perso) { - var token = perso.token; - var posX = token.get('left'); - var sizeX = token.get('width'); - var posY = token.get('top'); - var sizeY = token.get('height'); - var sortieEscalier; + let token = perso.token; + let posX = token.get('left'); + let sizeX = token.get('width'); + let posY = token.get('top'); + let sizeY = token.get('height'); + let sortieEscalier; escaliers.forEach(function(esc) { if (sortieEscalier) return; if (intersection(posX, sizeX, esc.get('left'), esc.get('width')) && intersection(posY, sizeY, esc.get('top'), esc.get('height'))) { - var escName = esc.get('name'); - var l = escName.length; + let escName = esc.get('name'); + let l = escName.length; if (l > 1) { - var label = escName.substr(l - 1, 1); + let label = escName.substr(l - 1, 1); escName = escName.substr(0, l - 1); - var i = labelsEscalier.indexOf(label); + let i = labelsEscalier.indexOf(label); if (versLeHaut) { if (i == 11) { if (loop) escName += labelsEscalier[0]; @@ -32557,7 +32937,7 @@ var COFantasy = COFantasy || function() { if (loop) escName += labelsEscalier[11]; } else escName += labelsEscalier[i - 1]; } - var escs = escaliers; + let escs = escaliers; if (escName.startsWith('tmap_')) { if (!tmaps) { tmaps = findObjs({ @@ -32590,16 +32970,16 @@ var COFantasy = COFantasy || function() { let left = sortieEscalier.get('left'); let top = sortieEscalier.get('top'); let newPageId = sortieEscalier.get('pageid'); - //Déplacement du token + //D\xE9placement du token if (newPageId == pageId) { token.set('left', left); token.set('top', top); } else { //On change de carte, il faut donc copier le token - var tokenObj = JSON.parse(JSON.stringify(token)); + let tokenObj = JSON.parse(JSON.stringify(token)); tokenObj._pageid = newPageId; - //On met la taille du token à jour en fonction des échelles des cartes. - var ratio = computeScale(pageId) / computeScale(newPageId); + //On met la taille du token \xE0 jour en fonction des \xE9chelles des cartes. + let ratio = computeScale(pageId) / computeScale(newPageId); if (ratio < 0.9 || ratio > 1.1) { if (ratio < 0.25) ratio = 0.25; else if (ratio > 4) ratio = 4; @@ -32615,12 +32995,12 @@ var COFantasy = COFantasy || function() { return; } } - //On déplace ensuite le joueur. + //On d\xE9place ensuite le joueur. let character = getObj('character', perso.charId); if (character === undefined) return; let charControlledby = character.get('controlledby'); if (charControlledby === '') { - //Seul le MJ contrôle le personnage + //Seul le MJ contr\xF4le le personnage let players = findObjs({ _type: 'player', online: true @@ -32638,7 +33018,7 @@ var COFantasy = COFantasy || function() { sendPing(left, top, newPageId, pid, true, pid); }); } - //Enfin, on efface le token de départ si on a changé de page + //Enfin, on efface le token de d\xE9part si on a chang\xE9 de page if (newPageId != pageId) token.remove(); return; } @@ -32653,45 +33033,45 @@ var COFantasy = COFantasy || function() { } function defautDansLaCuirasse(msg) { - var args = msg.content.split(' '); + let args = msg.content.split(' '); if (args.length < 3) { error("Pas assez d'arguments pour !cof-defaut-dans-la-cuirasse", args); return; } - var tireur = persoOfId(args[1], args[1]); + let tireur = persoOfId(args[1], args[1]); if (tireur === undefined) { error("Le premier argument n'est pas un token valide", args[1]); return; } - var pageId = tireur.token.get('pageid'); - var cible = persoOfId(args[2], args[2], pageId); + let pageId = tireur.token.get('pageid'); + let cible = persoOfId(args[2], args[2], pageId); if (cible === undefined) { error("La cible n'est pas un token valide", args[2]); return; } - var evt = { - type: "Défaut dans la cuirasse" + const evt = { + type: "D\xE9faut dans la cuirasse" }; setTokenAttr(cible, 'defautDansLaCuirasse_' + nomPerso(tireur), 2, evt); - sendPerso(tireur, "passe le tour à analyser les points faibles de " + nomPerso(cible)); + sendPerso(tireur, "passe le tour \xE0 analyser les points faibles de " + nomPerso(cible)); addEvent(evt); } function postureDeCombat(msg) { - var args = msg.content.split(' '); + let args = msg.content.split(' '); if (args.length < 4) { error("Pas assez d'arguments pour !cof-posture-de-combat", args); return; } - var bonus = parseInt(args[1]); - var attrDebuf = args[2]; + let bonus = parseInt(args[1]); + let attrDebuf = args[2]; if (attrDebuf != 'DEF' && attrDebuf != 'ATT' && attrDebuf != 'DM') { - error("L'attribut à débuffer pour la posture de combat est incorrect", args); + error("L'attribut \xE0 d\xE9buffer pour la posture de combat est incorrect", args); return; } - var attrBuf = args[3]; + let attrBuf = args[3]; if (attrBuf != 'DEF' && attrBuf != 'ATT' && attrBuf != 'DM') { - error("L'attribut à augmenter pour la posture de combat est incorrect", args); + error("L'attribut \xE0 augmenter pour la posture de combat est incorrect", args); return; } getSelected(msg, function(selected, playerId) { @@ -32700,12 +33080,12 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "choisir un bonus positif (pas " + args[1] + ") pour sa posture de combat", playerId); return; } - var rang = predicateAsInt(guerrier, "voieDuSoldat", 0); + let rang = predicateAsInt(guerrier, "voieDuSoldat", 0); if (rang > 0 && rang < bonus) { - sendPerso(guerrier, "ne peut choisir qu'un bonus inférieur à " + rang + " pour sa posture de combat"); + sendPerso(guerrier, "ne peut choisir qu'un bonus inf\xE9rieur \xE0 " + rang + " pour sa posture de combat"); return; } - var evt = { + const evt = { type: "Posture de combat" }; if (attrBuf == attrDebuf) { @@ -32717,7 +33097,7 @@ var COFantasy = COFantasy || function() { msg = "prend une posture "; switch (attrBuf) { case 'DEF': - msg += "défensive"; + msg += "d\xE9fensive"; break; case 'ATT': msg += "offensive"; @@ -32730,10 +33110,10 @@ var COFantasy = COFantasy || function() { msg += " mais "; switch (attrDebuf) { case 'DEF': - msg += "risquée"; + msg += "risqu\xE9e"; break; case 'ATT': - msg += "moins précise"; + msg += "moins pr\xE9cise"; break; case 'DM': msg += "moins puissante"; @@ -32757,21 +33137,21 @@ var COFantasy = COFantasy || function() { } let bonus = parseInt(args[1]); if (bonus != 0 && bonus != 2 && bonus != 5) { - error("Le malus de DEF ne peut être que 0, 2 ou 5", args); + error("Le malus de DEF ne peut \xEAtre que 0, 2 ou 5", args); return; } getSelected(msg, function(selected) { iterSelected(selected, function(guerrier) { const evt = { - type: "Attaque à outrance" + type: "Attaque \xE0 outrance" }; if (bonus === 0) { - sendPerso(guerrier, "n'attaque plus à outrance"); + sendPerso(guerrier, "n'attaque plus \xE0 outrance"); removeTokenAttr(guerrier, 'attaqueAOutrance', evt); addEvent(evt); return; } - msg = "attaque à outrance "; + msg = "attaque \xE0 outrance "; switch (bonus) { case 2: msg += "(-2 DEF, +1D6 DM)"; @@ -32793,14 +33173,14 @@ var COFantasy = COFantasy || function() { var options = parseOptions(msg); var cmd = options.cmd; if (cmd < 2) { - error("Il manque un argument à !cof-tour-de-force", cmd); + error("Il manque un argument \xE0 !cof-tour-de-force", cmd); return; } var seuil = parseInt(cmd[1]); getSelected(msg, function(selected, playerId) { iterSelected(selected, function(barbare) { if (isNaN(seuil)) { - sendPlayer(msg, "le seuil de difficulté du tour de force doit être un nombre", playerId); + sendPlayer(msg, "le seuil de difficult\xE9 du tour de force doit \xEAtre un nombre", playerId); return; } doTourDeForce(barbare, seuil, options); @@ -32818,18 +33198,18 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - let action = "Capacité : Tour de force"; + let action = "Capacit\xE9 : Tour de force"; let display = startFramedDisplay(options.playerId, action, perso); let testId = 'tourDeForce'; options.bonus = 10; testCaracteristique(perso, 'FOR', seuil, testId, options, evt, function(tr) { - addLineToFramedDisplay(display, " Jet de force difficulté " + seuil); + addLineToFramedDisplay(display, " Jet de force difficult\xE9 " + seuil); let smsg = nomPerso(perso) + " fait " + tr.texte; if (tr.reussite) { - smsg += " => réussite"; + smsg += " => r\xE9ussite"; } else { - smsg += " => échec" + tr.rerolls; + smsg += " => \xE9chec" + tr.rerolls; } addLineToFramedDisplay(display, smsg); let d4 = options.rolls.tourDeForceDmg || rollDePlus(4); @@ -32843,7 +33223,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evt, false, {}, explications, function(dmgDisplay, dmg) { - let dmgMsg = "mais cela lui coûte " + dmgDisplay + " PV"; + let dmgMsg = "mais cela lui co\xFBte " + dmgDisplay + " PV"; addLineToFramedDisplay(display, dmgMsg); explications.forEach(function(expl) { addLineToFramedDisplay(display, expl, 80); @@ -32867,41 +33247,41 @@ var COFantasy = COFantasy || function() { } } - //!cof-encaisser-un-coup, avec la personne qui encaisse sélectionnée + //!cof-encaisser-un-coup, avec la personne qui encaisse s\xE9lectionn\xE9e function doEncaisserUnCoup(msg) { var optionsEncaisser = parseOptions(msg); if (optionsEncaisser === undefined) return; var cmd = optionsEncaisser.cmd; var evt = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Personne n'est sélectionné pour encaisser un coup", msg); + error("Personne n'est s\xE9lectionn\xE9 pour encaisser un coup", msg); return; } if (evt === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour encaisser un coup"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour encaisser un coup"); return; } if (evt.type != 'Attaque' || evt.succes === false) { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour encaisser le coup d'une action précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour encaisser le coup d'une action pr\xE9c\xE9dente"); return; } var action = evt.action; if (action.options.distance) { - sendChat('', "Impossible d'encaisser le dernier coup, ce n'était pas une attaque au contact"); + sendChat('', "Impossible d'encaisser le dernier coup, ce n'\xE9tait pas une attaque au contact"); return; } var toProceed; iterSelected(selected, function(chevalier) { if (!attributeAsBool(chevalier, 'encaisserUnCoup')) { - sendPerso(chevalier, "n'est pas placé pour encaisser un coup"); + sendPerso(chevalier, "n'est pas plac\xE9 pour encaisser un coup"); return; } if (!peutController(msg, chevalier)) { @@ -32912,7 +33292,7 @@ var COFantasy = COFantasy || function() { return (target.token.id === chevalier.token.id); }); if (cible === undefined) { - sendPerso(chevalier, "n'est pas la cible de la dernière attaque"); + sendPerso(chevalier, "n'est pas la cible de la derni\xE8re attaque"); return; } action.choices = action.choices || {}; @@ -32935,40 +33315,40 @@ var COFantasy = COFantasy || function() { removePreDmg(options, cible, "encaisserUnCoup"); } - //!cof-devier-les-coups, avec la personne qui encaisse sélectionnée + //!cof-devier-les-coups, avec la personne qui encaisse s\xE9lectionn\xE9e function doDevierLesCoups(msg) { let optionsDevier = parseOptions(msg); if (optionsDevier === undefined) return; let cmd = optionsDevier.cmd; let evt = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Personne n'est sélectionné pour dévier les coups", msg); + error("Personne n'est s\xE9lectionn\xE9 pour d\xE9vier les coups", msg); return; } if (evt === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour dévier les coups"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour d\xE9vier les coups"); return; } if (evt.type != 'Attaque' || evt.succes === false) { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour dévier les coups d'une action précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour d\xE9vier les coups d'une action pr\xE9c\xE9dente"); return; } var action = evt.action; if (action.options.distance) { - sendChat('', "Impossible d'encaisser le dernier coup, ce n'était pas une attaque au contact"); + sendChat('', "Impossible d'encaisser le dernier coup, ce n'\xE9tait pas une attaque au contact"); return; } let toProceed; iterSelected(selected, function(perso) { - let testDevierCoups = testLimiteUtilisationsCapa(perso, 'devierLesCoups', 'tour', "ne peut plus dévier les coups à ce tour-ci"); + let testDevierCoups = testLimiteUtilisationsCapa(perso, 'devierLesCoups', 'tour', "ne peut plus d\xE9vier les coups \xE0 ce tour-ci"); if (testDevierCoups === undefined) return; if (!peutController(msg, perso)) { sendPlayer(msg, "pas le droit d'utiliser ce bouton", playerId); @@ -32978,7 +33358,7 @@ var COFantasy = COFantasy || function() { return (target.token.id === perso.token.id); }); if (cible === undefined) { - sendPerso(perso, "n'est pas la cible de la dernière attaque"); + sendPerso(perso, "n'est pas la cible de la derni\xE8re attaque"); return; } action.choices = action.choices || {}; @@ -33007,33 +33387,33 @@ var COFantasy = COFantasy || function() { if (optionsParade === undefined) return; var cmd = optionsParade.cmd; var evt = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Personne n'est sélectionné pour parer le projectile", msg); + error("Personne n'est s\xE9lectionn\xE9 pour parer le projectile", msg); return; } if (evt === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour parer le projectile"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour parer le projectile"); return; } if (evt.type != 'Attaque' || evt.succes === false) { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour parer le projectile d'une action précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour parer le projectile d'une action pr\xE9c\xE9dente"); return; } var action = evt.action; if (!action.options.distance) { - sendChat('', "Impossible de parer le projectile, ce n'était pas une attaque à distance"); + sendChat('', "Impossible de parer le projectile, ce n'\xE9tait pas une attaque \xE0 distance"); return; } if (action.options.poudre) { - sendChat('', "Impossible de parer le projectile, il s'agit d'une arme à poudre"); + sendChat('', "Impossible de parer le projectile, il s'agit d'une arme \xE0 poudre"); return; } if (action.cibles.length > 1) { @@ -33054,7 +33434,7 @@ var COFantasy = COFantasy || function() { return (target.token.id === moine.token.id); }); if (cible === undefined) { - sendPerso(moine, "n'est pas la cible de la dernière attaque"); + sendPerso(moine, "n'est pas la cible de la derni\xE8re attaque"); return; } action.choices = action.choices || {}; @@ -33079,8 +33459,8 @@ var COFantasy = COFantasy || function() { // asynchrone : on fait les jets du personnage en opposition // options : - // predicat : on utilise un prédicat et non un attribut. Peut être 'tour' ou 'combat' - // protecteur: c'est un protecteur qui protège la cible (pas compatible avec predicate + // predicat : on utilise un pr\xE9dicat et non un attribut. Peut \xEAtre 'tour' ou 'combat' + // protecteur: c'est un protecteur qui prot\xE8ge la cible (pas compatible avec predicate function evitementGenerique(msg, verbe, attributeName, actionName, tente, msgDejaFait, carac, typeAttaque, msgReussite, opt) { let options = parseOptions(msg); if (options === undefined) return; @@ -33095,10 +33475,10 @@ var COFantasy = COFantasy || function() { } let evt; let chance; - if (cmd.length > 2) { //On relance pour un événement particulier + if (cmd.length > 2) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[2]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } chance = cmd.length > 3 && cmd[3] == 'chance'; @@ -33106,11 +33486,11 @@ var COFantasy = COFantasy || function() { evt = lastEvent(); } if (evt === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour esquiver"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour esquiver"); return; } if (evt.type != 'Attaque') { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour " + verbe + " l'attaque précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour " + verbe + " l'attaque pr\xE9c\xE9dente"); return; } const perso = persoOfId(cmd[1]); @@ -33125,12 +33505,12 @@ var COFantasy = COFantasy || function() { return (target.token.id === perso.token.id); }); if (cible === undefined) { - sendPerso(perso, "n'est pas la cible de la dernière attaque"); + sendPerso(perso, "n'est pas la cible de la derni\xE8re attaque"); return; } let attributAVerifier = attributeName; let persoAttribut = perso; - if (opt.protecteur) { // c'est un personnage tiers qui protège la cible + if (opt.protecteur) { // c'est un personnage tiers qui prot\xE8ge la cible let protecteurAttrs = tokenAttribute(perso, attributeName + 'Valeur'); if (protecteurAttrs.length < 1) { error("Erreur interne dans le bouton de protection, protecteur introuvable", cmd); @@ -33177,7 +33557,7 @@ var COFantasy = COFantasy || function() { } else { let curAttribut = parseInt(attribut.get('current')); if (isNaN(curAttribut)) { - error("Resource pour " + actionName + " mal formée", attribut); + error("Resource pour " + actionName + " mal form\xE9e", attribut); return; } if (curAttribut < 1) { @@ -33240,8 +33620,8 @@ var COFantasy = COFantasy || function() { } } else if (testPredicat) { utiliseCapacite(testPredicat.perso, testPredicat, evt); - } else if (attributeName !== undefined) { //ni attribut ni prédicat - error("On n'a ni attribut ni prédicat pour un évitement générique", evitementGen); + } else if (attributeName !== undefined) { //ni attribut ni pr\xE9dicat + error("On n'a ni attribut ni pr\xE9dicat pour un \xE9vitement g\xE9n\xE9rique", evitementGen); return; } let optDice; @@ -33320,20 +33700,20 @@ var COFantasy = COFantasy || function() { if (attEvBonus > 0) msg += "+" + attEvBonus; else if (attEvBonus < 0) msg += attEvBonus; msg = nomPerso(lanceur) + " tente " + tente + ". " + - onGenre(lanceur, "Il", "elle") + " fait " + msg; - var generalMsg = ''; + onGenre(lanceur, "Il", "Elle") + " fait " + msg; + let generalMsg = ''; if (totalEvitement < jetAdversaire) { - msg += " => Raté"; - var pc = pointsDeChance(lanceur); + msg += " => Rat\xE9"; + let pc = pointsDeChance(lanceur); if (attackRoll.results.total != 1 && pc > 0) { generalMsg += '
' + boutonSimple("!cof-bouton-chance " + evt.id + " " + testId, "Chance") + " (reste " + pc + " PC)"; } - if (stateCOF.combat && attributeAsBool(lanceur, 'runeForgesort_énergie') && - attributeAsInt(lanceur, 'limiteParCombat_runeForgesort_énergie', 1) > 0 && + if (stateCOF.combat && attributeAsBool(lanceur, 'runeForgesort_\xE9nergie') && + attributeAsInt(lanceur, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0 && (carac == 'force' || carac == 'constitution' || carac == 'dexterite')) { - generalMsg += '
' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'énergie"); + generalMsg += '
' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'\xE9nergie"); } if (stateCOF.combat && capaciteDisponible(lanceur, 'petitVeinard', 'combat')) { generalMsg += '
' + boutonSimple("!cof-bouton-petit-veinard " + evt.id + " " + testId, "Petit veinard"); @@ -33343,23 +33723,23 @@ var COFantasy = COFantasy || function() { } else { //Sinon cacher le bouton mais laisser l'option reroll removePreDmg(options, cible, attributeName, 'reroll'); } - } else { //Évitement réussi + } else { //\xC9vitement r\xE9ussi if (opt && cible.critique && (opt.critiqueDevientNormal || (opt.critiqueAnnuleCritique && d20roll != 20))) { cible.critique = false; - msg += " => Réussi, l'attaque fait des dégâts normaux"; + msg += " => R\xE9ussi, l'attaque fait des d\xE9g\xE2ts normaux"; removePreDmg(options, cible, attributeName); } else { cible.touche = false; if (opt.annule) { delete options.preDmg; options.preDmgAnnule = true; - generalMsg += " => Réussi, " + msgReussite; + generalMsg += " => R\xE9ussi, " + msgReussite; } else { action.ciblesTouchees = action.ciblesTouchees.filter(function(c) { return c.token.id != cible.token.id; }); removePreDmg(options, cible); - msg += " => Réussi, " + msgReussite; + msg += " => R\xE9ussi, " + msgReussite; } } } @@ -33378,7 +33758,7 @@ var COFantasy = COFantasy || function() { }; evitementGenerique(msg, "absorber un coup au bouclier", 'absorberUnCoup', "d'absorption de coup au bouclier", "d'absorber un coup au bouclier", - " a déjà essayé d'absorber un coup au bouclier ce tour", 'force', 'contact', "le coup est absorbé !", { + " a d\xE9j\xE0 essay\xE9 d'absorber un coup au bouclier ce tour", 'force', 'contact', "le coup est absorb\xE9 !", { attrAsBool: true, condition, }); @@ -33395,7 +33775,7 @@ var COFantasy = COFantasy || function() { }; evitementGenerique(msg, "absorber un sort au bouclier", 'absorberUnSort', "d'absorption de sort au bouclier", "d'absorber un sort au bouclier", - " a déjà essayé d'absorber un sort au bouclier ce tour", 'sagesse', 'magique', "le sort est absorbé !", { + " a d\xE9j\xE0 essay\xE9 d'absorber un sort au bouclier ce tour", 'sagesse', 'magique', "le sort est absorb\xE9 !", { attrAsBool: true, condition: condition }); @@ -33404,10 +33784,10 @@ var COFantasy = COFantasy || function() { // asynchrone : on fait les jets du barbare en opposition //!cof-resister-a-la-magie id [evtid] [chance] function resisterALaMagie(msg) { - evitementGenerique(msg, 'résister à la magie', 'resistanceALaMagieBarbare', - 'résistance à la magie', "de résister à la magie", - " a déjà essayé de résister à la magie ce tour", - 'sagesse', 'magique', "il résiste à la magie !", { + evitementGenerique(msg, 'r\xE9sister \xE0 la magie', 'resistanceALaMagieBarbare', + 'r\xE9sistance \xE0 la magie', "de r\xE9sister \xE0 la magie", + " a d\xE9j\xE0 essay\xE9 de r\xE9sister \xE0 la magie ce tour", + 'sagesse', 'magique', "il r\xE9siste \xE0 la magie !", { predicat: 'tour' }); } @@ -33417,8 +33797,8 @@ var COFantasy = COFantasy || function() { function cercleDeProtection(msg) { evitementGenerique(msg, 'activer le cercle de protection', 'cercleDeProtection', 'activation du cercle de protection', "de bloquer le sort avec le Cercle de Protection", - " a déjà active le Cercle de Protection ce tour", - 'intelligence', 'magique', "le sort est annulé !", { + " a d\xE9j\xE0 active le Cercle de Protection ce tour", + 'intelligence', 'magique', "le sort est annul\xE9 !", { protecteur: true, annule: true }); @@ -33428,7 +33808,7 @@ var COFantasy = COFantasy || function() { //!cof-esquive-acrobatique id [evtid] [chance] function doEsquiveAcrobatique(msg) { evitementGenerique(msg, 'esquiver', 'esquiveAcrobatique', - 'esquive acrobatique', "une esquive acrobatique", " a déjà fait une esquive acrobatique ce tour", 'dexterite', 'distance', "l'attaque est esquivée !", { + 'esquive acrobatique', "une esquive acrobatique", " a d\xE9j\xE0 fait une esquive acrobatique ce tour", 'dexterite', 'distance', "l'attaque est esquiv\xE9e !", { critiqueDevientNormal: true, predicat: 'tour' }); @@ -33436,12 +33816,12 @@ var COFantasy = COFantasy || function() { function doEsquiveDeLaMagie(msg) { evitementGenerique(msg, 'esquiver', undefined, - "esquive de la magie", "d'esquiver la magie", " a déjà fait esquivé la magie", 'dexterite', 'esquive', "l'attaque est esquivée !", {}); + "esquive de la magie", "d'esquiver la magie", " a d\xE9j\xE0 fait esquiv\xE9 la magie", 'dexterite', 'esquive', "l'attaque est esquiv\xE9e !", {}); } function doEsquiveMagistrale(msg) { evitementGenerique(msg, 'esquiver', 'paradeMagistrale', - 'esquive acrobatique', "une esquive acrobatique", " a déjà fait une parade magistrale ce tour", 'dexterite', 'distance', "l'attaque est esquivée !", { + 'esquive acrobatique', "une esquive acrobatique", " a d\xE9j\xE0 fait une parade magistrale ce tour", 'dexterite', 'distance', "l'attaque est esquiv\xE9e !", { bonusAttaque: -5, critiqueDevientNormal: true, predicat: 'tour' @@ -33450,7 +33830,7 @@ var COFantasy = COFantasy || function() { function doParadeMagistrale(msg) { evitementGenerique(msg, 'parer', 'paradeMagistrale', - 'parade magistrale', "une parade magistrale", " a déjà fait une parade magistrale ce tour", 'dexterite', 'distance', "l'attaque est parée !", { + 'parade magistrale', "une parade magistrale", " a d\xE9j\xE0 fait une parade magistrale ce tour", 'dexterite', 'distance', "l'attaque est par\xE9e !", { arme: true, critiqueDevientNormal: true, predicat: 'tour' @@ -33460,7 +33840,7 @@ var COFantasy = COFantasy || function() { //!cof-parade-au-bouclier function doParadeAuBouclier(msg) { evitementGenerique(msg, 'parer', 'paradeAuBouclier', - 'parade au bouclier', "une parade au bouclier", " a déjà fait une parade au bouclier ce tour", 'force', 'contact', "l'attaque est parée !", { + 'parade au bouclier', "une parade au bouclier", " a d\xE9j\xE0 fait une parade au bouclier ce tour", 'force', 'contact', "l'attaque est par\xE9e !", { armeGauche: true, critiqueAnnuleCritique: true, predicat: 'tour' @@ -33468,7 +33848,7 @@ var COFantasy = COFantasy || function() { } //!cof-chair-a-canon id1 id2 [evt_id] - // id1 est l'id du pnj récurrent + // id1 est l'id du pnj r\xE9current // id2 est l'id du token qui se met devant l'attaque function doChairACanon(msg) { let options = parseOptions(msg); @@ -33479,13 +33859,13 @@ var COFantasy = COFantasy || function() { return; } let evtARefaire; - if (cmd.length > 3) { //On relance pour un événement particulier + if (cmd.length > 3) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[3]); } else { evtARefaire = lastEvent(); } if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let pnjRec = persoOfId(cmd[1]); @@ -33497,7 +33877,7 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "pas le droit d'utiliser ce bouton"); return; } - let testChairACanon = testLimiteUtilisationsCapa(pnjRec, 'chairACanon', 'tour', "a déjà utilisé un sous-fifre ce tour", "ne sait pas utiliser ses sous-fifres pour se défendre"); + let testChairACanon = testLimiteUtilisationsCapa(pnjRec, 'chairACanon', 'tour', "a d\xE9j\xE0 utilis\xE9 un sous-fifre ce tour", "ne sait pas utiliser ses sous-fifres pour se d\xE9fendre"); if (testChairACanon === undefined) { return; } @@ -33507,11 +33887,11 @@ var COFantasy = COFantasy || function() { return; } if (evtARefaire === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour la chair à canon"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour la chair \xE0 canon"); return; } if (evtARefaire.type != 'Attaque') { - sendChat('', "la dernière action n'est pas une attaque"); + sendChat('', "la derni\xE8re action n'est pas une attaque"); return; } let attaque = evtARefaire.action; @@ -33536,7 +33916,7 @@ var COFantasy = COFantasy || function() { let optionsRedo = attaque.options; optionsRedo.rolls = attaque.rolls; let evt = { - type: "chair à canon" + type: "chair \xE0 canon" }; utiliseCapacite(pnjRec, testChairACanon, evt); undoEvent(evtARefaire); @@ -33545,7 +33925,7 @@ var COFantasy = COFantasy || function() { redoEvent(evtARefaire, attaque); } - // modifie res et le retourne (au cas où il ne serait pas donné) + // modifie res et le retourne (au cas o\xF9 il ne serait pas donn\xE9) function listRollResults(roll, res) { res = res || []; switch (roll.type) { @@ -33560,7 +33940,7 @@ var COFantasy = COFantasy || function() { roll.results.forEach(function(r) { if (r.v) res.push(r.v); else if (r.d) res.push(r.d); - else log("Type de résultat de dé inconnu " + r); + else log("Type de r\xE9sultat de d\xE9 inconnu " + r); }); return res; case 'M': @@ -33581,9 +33961,9 @@ var COFantasy = COFantasy || function() { return res; } - //category est un tableau de string, le premier élément étant la catégorie - //principale, le suivant la sous-catégorie, etc - //value peut être un nombre, un tableau de nombres, ou un inline roll + //category est un tableau de string, le premier \xE9l\xE9ment \xE9tant la cat\xE9gorie + //principale, le suivant la sous-cat\xE9gorie, etc + //value peut \xEAtre un nombre, un tableau de nombres, ou un inline roll function addStatistics(playerId, category, value) { if (stateCOF.statistiques === undefined) return; var stat = stateCOF.statistiques; @@ -33624,7 +34004,7 @@ var COFantasy = COFantasy || function() { nombre: 0, total: 0, }; - if (stats.nombre) { //on peut afficher des résultats + if (stats.nombre) { //on peut afficher des r\xE9sultats res.nombre = stats.nombre; res.total = stats.total; } @@ -33636,7 +34016,7 @@ var COFantasy = COFantasy || function() { res.nombre += catRes.nombre; res.total += catRes.total; } - var msg = "aucun jet cellecté"; + var msg = "aucun jet cellect\xE9"; if (res.nombre > 0) { var moyenne = res.total / res.nombre; msg = res.nombre + " jet" + ((res.nombre > 1) ? "s" : "") + ", moyenne " + moyenne; @@ -33658,7 +34038,7 @@ var COFantasy = COFantasy || function() { if (stats) addLineToFramedDisplay(display, "Statistiques en pause"); else { - addLineToFramedDisplay(display, "Aucune statistique collectée"); + addLineToFramedDisplay(display, "Aucune statistique collect\xE9e"); sendFramedDisplay(display); return; } @@ -33700,7 +34080,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let args = options.cmd; if (args === undefined || args.length < 2) { - error("Il faut au moins un argument à !cof-destruction-des-morts-vivants", args); + error("Il faut au moins un argument \xE0 !cof-destruction-des-morts-vivants", args); return; } args.shift(); @@ -33713,11 +34093,11 @@ var COFantasy = COFantasy || function() { dm = dm.replace(/\]/g, ']'); getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Il faut sélectionner le lanceur de la destruction des morts-vivants", playerId); + sendPlayer(msg, "Il faut s\xE9lectionner le lanceur de la destruction des morts-vivants", playerId); return; } if (selected.length > 1) { - sendPlayer(msg, "Ne sélectionner qu'un token à la fois pour lancer la destruction des mort-vivants.", playerId); + sendPlayer(msg, "Ne s\xE9lectionner qu'un token \xE0 la fois pour lancer la destruction des mort-vivants.", playerId); return; } let playerName = msg.who; @@ -33725,7 +34105,7 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(lanceur) { if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options var optMana = { mana: options.mana, dm: true, @@ -33737,7 +34117,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -33747,7 +34127,7 @@ var COFantasy = COFantasy || function() { let nbDes = parseInt(findNbDes[1]); dm = dm.replace(findNbDes[0], (nbDes + options.tempeteDeManaIntense) + 'd'); } else { - log("Pas réussi à trouver le nombre de dés dans " + dm); + log("Pas r\xE9ussi \xE0 trouver le nombre de d\xE9s dans " + dm); } } else if (options.puissant) { let findValDes = dm.match(/^([0-9]+d)([0-9]+)/); @@ -33755,7 +34135,7 @@ var COFantasy = COFantasy || function() { let valDes = parseInt(findValDes[2]) + 2; dm = dm.replace(findValDes[0], findValDes[1] + valDes); } else { - log("Pas réussi à trouver le nombre de faces des dés dans " + dm); + log("Pas r\xE9ussi \xE0 trouver le nombre de faces des d\xE9s dans " + dm); } } doDestructionDesMortsVivants(lanceur, playerName, dm, options); @@ -33827,7 +34207,7 @@ var COFantasy = COFantasy || function() { if (!estMortVivant(cible)) return; if (getState(cible, 'mort')) return; if (predicateAsBool(cible, 'immunite_destruction')) { - addLineToFramedDisplay(display, nomPerso(cible) + " ne semble pas affecté par la destruction des morts-vivants"); + addLineToFramedDisplay(display, nomPerso(cible) + " ne semble pas affect\xE9 par la destruction des morts-vivants"); return; } cibles.push(cible); @@ -33874,21 +34254,21 @@ var COFantasy = COFantasy || function() { dmg.display = buildinline(dmg.roll.inlinerolls[dmgRollNumber], dmg.type, optionsDM.magique); dealDamage(perso, dmg, [], evt, false, optionsDM, explications, function(dmgDisplay, dmgFinal) { addLineToFramedDisplay(display, - name + " reçoit " + dmgDisplay + " DM"); + name + " re\xE7oit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); finalDisplay(); }); - }); //fin du jet de dés + }); //fin du jet de d\xE9s } catch (rollError) { - error("Jet " + dm + " mal formé", dm); + error("Jet " + dm + " mal form\xE9", dm); } }); //fin forEach } else { addLineToFramedDisplay(display, msgJet + " < " + difficulte); - let msgRate = nomPerso(lanceur) + " ne réussit pas à invoquer son dieu." + testRes.rerolls + testRes.modifiers; + let msgRate = nomPerso(lanceur) + " ne r\xE9ussit pas \xE0 invoquer son dieu." + testRes.rerolls + testRes.modifiers; addLineToFramedDisplay(display, msgRate); sendFramedDisplay(display); } @@ -33909,7 +34289,7 @@ var COFantasy = COFantasy || function() { let label = cmd[1]; let typePoison = cmd[2]; if (typePoison != 'rapide' && typePoison != 'affaiblissant') { - error("Les seuls type de poison gérés sont rapide et affaiblissant, mais pas encore " + typePoison, cmd); + error("Les seuls type de poison g\xE9r\xE9s sont rapide et affaiblissant, mais pas encore " + typePoison, cmd); } let nomMunition; let estMunition = label.startsWith('munition_'); @@ -33917,7 +34297,7 @@ var COFantasy = COFantasy || function() { let forcePoison = cmd[3]; let savePoison = parseInt(cmd[4]); if (isNaN(savePoison)) { - error("Le dernier argument non optionnel doit être la difficulté du test de CON", cmd); + error("Le dernier argument non optionnel doit \xEAtre la difficult\xE9 du test de CON", cmd); return; } let testINT = 14; @@ -33926,7 +34306,7 @@ var COFantasy = COFantasy || function() { switch (cmd[0]) { case 'testINT': if (cmd.length < 2) { - error("Il faut un argument à --testINT", cmd); + error("Il faut un argument \xE0 --testINT", cmd); return; } testINT = parseInt(cmd[1]); @@ -33974,11 +34354,11 @@ var COFantasy = COFantasy || function() { return; } if (arme.sortilege) { - sendPerso(perso, "imossible d'enduire un sortilège de poison", true); + sendPerso(perso, "imossible d'enduire un sortil\xE8ge de poison", true); return; } if (arme.typeDegats == 'contondant') { - sendPerso(perso, arme.name + " fait des dégâts contondants. Est-il vraiment possible de l'empoisonner ?", true); + sendPerso(perso, arme.name + " fait des d\xE9g\xE2ts contondants. Est-il vraiment possible de l'empoisonner ?", true); } if (arme.armeDeJet) estMunition = true; } @@ -33993,22 +34373,22 @@ var COFantasy = COFantasy || function() { let munitions = listAllMunitions(perso); let m = munitions[nomMunition]; if (m) { - let typeMunition = fieldAsString(m, 'typemunition', 'Flèche'); + let typeMunition = fieldAsString(m, 'typemunition', 'Fl\xE8che'); armeEnduite = fieldAsString(m, 'nommunition', typeMunition); munitionsCourantes = fieldAsInt(m, 'qtemunition', 1); maxMunitions = fieldAsInt(m, 'qtemunition_max', 1); - } else { //ancienne variante, obsolète depuis mars 2023 + } else { //ancienne variante, obsol\xE8te depuis mars 2023 armeEnduite = nomMunition.replace(/_/g, ' '); let attrQte = tokenAttribute(perso, labelArme); if (attrQte.length === 0) { - sendPerso(perso, "n'a pas de munition nommée " + nomMunition); + sendPerso(perso, "n'a pas de munition nomm\xE9e " + nomMunition); return; } attrQte = attrQte[0]; munitionsCourantes = parseInt(attrQte.get('current')); maxMunitions = parseInt(attrQte.get('max')); if (isNaN(munitionsCourantes) || isNaN(maxMunitions)) { - error("Attribut de munitions mal formé", attrQte); + error("Attribut de munitions mal form\xE9", attrQte); return; } } @@ -34022,7 +34402,7 @@ var COFantasy = COFantasy || function() { let infos = attr[0].get('max'); let indexInfos = infos.indexOf(' '); if (indexInfos < 1) { - error("Attribut de poison rapide de munition mal formé (il faudrait la difficulté du save + le nombre de munitions empoisonnées)", infos); + error("Attribut de poison rapide de munition mal form\xE9 (il faudrait la difficult\xE9 du save + le nombre de munitions empoisonn\xE9es)", infos); return; } let oldSave = parseInt(infos.substring(0, indexInfos)); @@ -34031,23 +34411,23 @@ var COFantasy = COFantasy || function() { if (dejaEnduits > 0 && (attr[0].get('current') != typePoison + ' ' + forcePoison || oldSave != savePoison)) { - sendPlayer(msg, "Il y a déjà du poison de type " + attr[0].get('current') + "et de save " + oldSave + " sur les munitions " + armeEnduite + ". Le script ne sait pas gérer différents poisons sur les mêmes munitions.", playerId); + sendPlayer(msg, "Il y a d\xE9j\xE0 du poison de type " + attr[0].get('current') + "et de save " + oldSave + " sur les munitions " + armeEnduite + ". Le script ne sait pas g\xE9rer diff\xE9rents poisons sur les m\xEAmes munitions.", playerId); return; } } infosAdditionelles = savePoison + ' ' + (dejaEnduits + 1); if (dejaEnduits >= maxMunitions) { - sendPlayer(msg, "Toutes les munitions " + armeEnduite + " sont déjà enduites de poison", playerId); + sendPlayer(msg, "Toutes les munitions " + armeEnduite + " sont d\xE9j\xE0 enduites de poison", playerId); return; } } else { armeEnduite = getAttackName(labelArme, perso); if (armeEnduite === undefined) { - error(perso.tokNname + " n'a pas d'arme associée au label " + labelArme, cmd); + error(perso.tokNname + " n'a pas d'arme associ\xE9e au label " + labelArme, cmd); return; } if (attributeAsBool(perso, attribut)) { - sendPlayer(msg, armeEnduite + " est déjà enduit de poison.", playerId); + sendPlayer(msg, armeEnduite + " est d\xE9j\xE0 enduit de poison.", playerId); return; } } @@ -34087,13 +34467,13 @@ var COFantasy = COFantasy || function() { addEvent(evt); if (limiteRessources(perso, options, 'enduirePoison', 'enduire de poison', evt)) return; const display = startFramedDisplay(options.playerId, "Essaie d'enduire " + armeEnduite + " de poison", perso); - //Test d'INT pour savoir si l'action réussit. + //Test d'INT pour savoir si l'action r\xE9ussit. let testId = 'enduireDePoison'; testCaracteristique(perso, 'INT', testINT, testId, options, evt, function(tr) { let jet = "Jet d'INT : " + tr.texte; - if (tr.echecCritique) { //échec critique - jet += " Échec critique !" + tr.rerolls + tr.modifiers; + if (tr.echecCritique) { //\xE9chec critique + jet += " \xC9chec critique !" + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, jet); addLineToFramedDisplay(display, nomPerso(perso) + " s'empoisonne."); sendChat('', "[[" + forcePoison + "]]", function(res) { @@ -34122,7 +34502,7 @@ var COFantasy = COFantasy || function() { }); addLineToFramedDisplay(display, nomPerso(perso) + " subit " + dmgDisplay + " DM"); sendFramedDisplay(display); - }); //fin de dmg dus à l'échec critique + }); //fin de dmg dus \xE0 l'\xE9chec critique } }); //fin du jet de dmg } else if (tr.reussite) { @@ -34134,7 +34514,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, armeEnduite + " est maintenant enduit de poison"); sendFramedDisplay(display); } else { //echec normal au jet d'INT - jet += " < " + testINT + " : échec" + tr.rerolls + tr.modifiers; + jet += " < " + testINT + " : \xE9chec" + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, jet); sendFramedDisplay(display); } @@ -34142,72 +34522,72 @@ var COFantasy = COFantasy || function() { } const listeElixirs = [{ - nom: 'Élixir fortifiant', + nom: '\xC9lixir fortifiant', attrName: 'fortifiant', action: "!cof-fortifiant $rang", rang: 1 }, { - nom: 'Élixir de feu grégeois', - attrName: 'feu_grégeois', - action: "!cof-attack @{selected|token_id} @{target|token_id} Feu Grégeois --auto --dm $rangd6 --feu --psave DEX [[$base_save+@{selected|INT}]] --disque 3 --portee 10 --targetFx burst-fire", + nom: '\xC9lixir de feu gr\xE9geois', + attrName: 'feu_gr\xE9geois', + action: "!cof-attack @{selected|token_id} @{target|token_id} Feu Gr\xE9geois --auto --dm $rangd6 --feu --psave DEX [[$base_save+@{selected|INT}]] --disque 3 --portee 10 --targetFx burst-fire", rang: 2 }, { - nom: 'Élixir de guérison', - attrName: 'élixir_de_guérison', + nom: '\xC9lixir de gu\xE9rison', + attrName: '\xE9lixir_de_gu\xE9rison', action: "!cof-soin 3d6+$INT", rang: 3 }, { - nom: "Élixir d'agrandissement", + nom: "\xC9lixir d'agrandissement", attrName: "potion_d_agrandissement", action: "!cof-effet-temp agrandissement [[5+$INT]]", rang: 4 }, { - nom: "Élixir de forme gazeuse", + nom: "\xC9lixir de forme gazeuse", attrName: "potion_de_forme_gazeuse", action: "!cof-effet-temp formeGazeuse [[1d4+$INT]]", rang: 4 }, { - nom: "Élixir de protection contre les éléments", - attrName: "potion_de_protection_contre_les_éléments", + nom: "\xC9lixir de protection contre les \xE9l\xE9ments", + attrName: "potion_de_protection_contre_les_\xE9l\xE9ments", action: "!cof-effet-temp protectionContreLesElements [[5+$INT]] --valeur $rang", rang: 4 }, { - nom: "Élixir d'armure de mage", + nom: "\xC9lixir d'armure de mage", attrName: "potion_d_armure_de_mage", action: "!cof-effet-combat armureDuMage", rang: 4 }, { - nom: "Élixir de chute ralentie", + nom: "\xC9lixir de chute ralentie", attrName: "potion_de_chute_ralentie", - action: "est léger comme une plume.", + action: "est l\xE9ger comme une plume.", rang: 4 }, { - nom: "Élixir d'invisibilité", - attrName: "potion_d_invisibilité", + nom: "\xC9lixir d'invisibilit\xE9", + attrName: "potion_d_invisibilit\xE9", action: "!cof-set-state invisible true --message se rend invisible ([[1d6+$INT]] minutes)", rang: 5 }, { - nom: "Élixir de vol", + nom: "\xC9lixir de vol", attrName: "potion_de_vol", - action: "se met à voler", + action: "se met \xE0 voler", rang: 5 }, { - nom: "Élixir de respiration aquatique", + nom: "\xC9lixir de respiration aquatique", attrName: "potion_de_respiration_aquatique", action: "peut respirer sous l'eau", rang: 5 }, { - nom: "Élixir de flou", + nom: "\xC9lixir de flou", attrName: "potion_de_flou", action: "!cof-effet-temp flou [[1d4+$INT]]", rang: 5 }, { - nom: "Élixir de hâte", - attrName: "potion_de_hâte", + nom: "\xC9lixir de h\xE2te", + attrName: "potion_de_h\xE2te", action: "!cof-effet-temp hate [[1d6+$INT]]", rang: 5 }, - //Le élixirs pour les terres d'Arran + //Le \xE9lixirs pour les terres d'Arran { nom: 'Huile instable', attrName: 'huileInstable', @@ -34215,25 +34595,25 @@ var COFantasy = COFantasy || function() { rang: 3, arran: true }, { - nom: 'Élixir de guérison', - attrName: 'élixirGuérison', + nom: '\xC9lixir de gu\xE9rison', + attrName: '\xE9lixirGu\xE9rison', action: "!cof-soin 3d6+$INT", rang: 4, arran: true }, { - nom: "Élixir de peau d'écorce", + nom: "\xC9lixir de peau d'\xE9corce", attrName: 'peauEcorce', action: "!cof-effet-temp peauDEcorce [[5+$SAG]] --valeur 4", rang: 5, arran: true }, { - nom: "Élixir d'image décalée", + nom: "\xC9lixir d'image d\xE9cal\xE9e", attrName: 'imageDecalee', action: "!cof-effet-temp imageDecalee [[5+$SAG]]", rang: 5, arran: true }, { - nom: "Élixir de protection contre les éléments", + nom: "\xC9lixir de protection contre les \xE9l\xE9ments", attrName: 'protectionContreElements', action: "!cof-effet-temp protectionContreLesElements [[5+$SAG]] --valeur 5", rang: 5, @@ -34257,7 +34637,7 @@ var COFantasy = COFantasy || function() { getSelected(msg, function(selected, playerId) { iterSelected(selected, function(perso) { if (perso.token.get('bar1_link') === '') { - error("La liste de consommables n'est pas au point pour les tokens non liés", perso); + error("La liste de consommables n'est pas au point pour les tokens non li\xE9s", perso); return; } let display = startFramedDisplay(playerId, 'Liste de vos consommables :', perso, { @@ -34323,7 +34703,7 @@ var COFantasy = COFantasy || function() { var aConsommable; _.each(consommables, function(c, prefix) { if (c.effet === undefined || c.effet === '' || c.nom === undefined || c.nom === '') return; - //La quantité est de 1 par défaut sur la fiche + //La quantit\xE9 est de 1 par d\xE9faut sur la fiche if (c.quantite === undefined) { c.quantite = 1; c.attr = createObj('attribute', { @@ -34340,12 +34720,12 @@ var COFantasy = COFantasy || function() { ressource: c.attr }); // Pictos : https://wiki.roll20.net/CSS_Wizardry#Pictos - var overlay = ' title="Cliquez pour échanger"'; + var overlay = ' title="Cliquez pour \xE9changer"'; ligne += boutonSimple('!cof-echange-consommable ' + perso.token.id + ' @{target|token_id} ' + c.attr.id, 'r', overlay); addLineToFramedDisplay(display, ligne); }); //fin de la boucle sur les onsommables if (aConsommable) - addLineToFramedDisplay(display, 'Cliquez sur le consommable pour l\'utiliser ou sur r pour l\'échanger avec un autre personnage.'); + addLineToFramedDisplay(display, 'Cliquez sur le consommable pour l\'utiliser ou sur r pour l\'\xE9changer avec un autre personnage.'); else addLineToFramedDisplay(display, "Vous n'avez aucun consommable"); sendFramedDisplay(display); @@ -34364,15 +34744,15 @@ var COFantasy = COFantasy || function() { cmd.shift(); var perso = persoOfId(cmd[0]); if (perso === undefined) { - log("Propriétaire perdu"); - sendChat('COF', "Plus possible d'utiliser cette action. Réafficher les consommables."); + log("Propri\xE9taire perdu"); + sendChat('COF', "Plus possible d'utiliser cette action. R\xE9afficher les consommables."); return; } - // Vérifie les droits d'utiliser le consommable + // V\xE9rifie les droits d'utiliser le consommable if (msg.selected && msg.selected.length == 1) { var utilisateur = persoOfId(msg.selected[0]._id); if (utilisateur === undefined) { - sendChat('COF', "Le token sélectionné n'est pas valide"); + sendChat('COF', "Le token s\xE9lectionn\xE9 n'est pas valide"); return; } var d = distanceCombat(perso.token, utilisateur.token); @@ -34382,19 +34762,19 @@ var COFantasy = COFantasy || function() { } perso = utilisateur; } else { - //On regarde si le joueur contrôle le token + //On regarde si le joueur contr\xF4le le token if (!peutController(msg, perso)) { - sendPlayer(msg, "Pas les droits pour ça"); + sendPlayer(msg, "Pas les droits pour \xE7a"); return; } } - //on récupère l'attribut à utiliser + //on r\xE9cup\xE8re l'attribut \xE0 utiliser cmd.shift(); var attr = getObj('attribute', cmd[0]); if (attr === undefined) { - log("Attribut a changé/perdu"); + log("Attribut a chang\xE9/perdu"); log(msg.content); - sendChat('COF', "Plus possible d'utiliser cette action. Veuillez réafficher les consommables."); + sendChat('COF', "Plus possible d'utiliser cette action. Veuillez r\xE9afficher les consommables."); return; } //Nom du consommable (pour affichage) @@ -34443,40 +34823,40 @@ var COFantasy = COFantasy || function() { return; } if (cmd[1] == cmd[2]) { - sendChat('COF', "Échange avec soi-même, sans effet"); + sendChat('COF', "\xC9change avec soi-m\xEAme, sans effet"); return; } - //perso1 = token avec qui va échanger le consommable + //perso1 = token avec qui va \xE9changer le consommable var perso1 = persoOfId(cmd[1]); if (perso1 === undefined) { - log("Propriétaire perdu"); - sendChat('COF', "Plus possible d'utiliser cette action. Réafficher les consommables."); + log("Propri\xE9taire perdu"); + sendChat('COF', "Plus possible d'utiliser cette action. R\xE9afficher les consommables."); return; } - //perso2 = token avec lequel on va faire l'échange + //perso2 = token avec lequel on va faire l'\xE9change let perso2 = persoOfId(cmd[2]); if (perso2 === undefined) { log("Destinataire perdu"); - sendChat('COF', "Erreur concernant le destinataire. Veuillez réessayer."); + sendChat('COF', "Erreur concernant le destinataire. Veuillez r\xE9essayer."); return; } - //On regarde si le joueur contrôle le token + //On regarde si le joueur contr\xF4le le token if (!peutController(msg, perso1)) { - sendPlayer(msg, "Pas les droits pour ça"); + sendPlayer(msg, "Pas les droits pour \xE7a"); return; } - //on récupère l'attribut à échanger de perso1 + //on r\xE9cup\xE8re l'attribut \xE0 \xE9changer de perso1 var attr1 = getObj('attribute', cmd[3]); if (attr1 === undefined) { - log("Attribut a changé/perdu"); + log("Attribut a chang\xE9/perdu"); log(cmd); - sendChat('COF', "Plus possible d'utiliser cette action. Veuillez réafficher les consommables."); + sendChat('COF', "Plus possible d'utiliser cette action. Veuillez r\xE9afficher les consommables."); return; } var consName; var quantite1 = parseInt(attr1.get('current')); var evt = { - type: "Échange de consommable", + type: "\xC9change de consommable", attributes: [{ attribute: attr1, current: quantite1, @@ -34506,7 +34886,7 @@ var COFantasy = COFantasy || function() { whisperChar(perso1.charId, "Vous ne disposez plus de " + consName); return; } - // on baisse la valeur de 1 du consommable qu'on s'apprête à échanger + // on baisse la valeur de 1 du consommable qu'on s'appr\xEAte \xE0 \xE9changer quantite1--; attr1.set('current', quantite1); // ajout du consommable dans perso2 : @@ -34533,7 +34913,7 @@ var COFantasy = COFantasy || function() { attribute: attrEffet2, }); } else if (attrEffet2[0].get('current').trim() != effet) { - error("Échange dangereux : pas le même effet pour le consommable selon le personnage \n" + + error("\xC9change dangereux : pas le m\xEAme effet pour le consommable selon le personnage \n" + "Effet chez " + nomPerso(perso1) + " : " + effet + "\n" + "Effet chez " + nomPerso(perso2) + " : " + attrEffet2[0].get('current'), attr2.get('name')); return false; @@ -34562,7 +34942,7 @@ var COFantasy = COFantasy || function() { return true; } else if (!m1 && attrName == attrName2.trim()) { if (attr2.get('max').trim() != effet) { - error("Échange dangereux : pas le même effet pour le consommable selon le personnage \n" + + error("\xC9change dangereux : pas le m\xEAme effet pour le consommable selon le personnage \n" + "Effet chez " + nomPerso(perso1) + " : " + effet + "\n" + "Effet chez " + nomPerso(perso2) + " : " + attr2.get('max'), attr2); return false; @@ -34579,7 +34959,7 @@ var COFantasy = COFantasy || function() { } return false; }); - // si le consommable n'a pas été trouvé, on le crée avec une valeur de 1. + // si le consommable n'a pas \xE9t\xE9 trouv\xE9, on le cr\xE9e avec une valeur de 1. if (!found) { if (m1) { var pref = 'repeating_equipement_' + generateRowID() + '_'; @@ -34612,12 +34992,12 @@ var COFantasy = COFantasy || function() { } } quantite2++; - // on envoie un petit message précisant la résultante de l'action. - sendChat('COF', "Echange entre " + nomPerso(perso1) + " et " + nomPerso(perso2) + " terminée."); + // on envoie un petit message pr\xE9cisant la r\xE9sultante de l'action. + sendChat('COF', "Echange entre " + nomPerso(perso1) + " et " + nomPerso(perso2) + " termin\xE9e."); whisperChar(perso1.charId, " Il vous reste " + quantite1 + " " + consName + "."); - whisperChar(perso2.charId, " Vous possédez désormais " + quantite2 + " " + consName + "."); - // le MJ est notifié : - sendChat('COF', "/w GM " + nomPerso(perso1) + " vient de donner 1 " + consName + " à " + nomPerso(perso2) + "."); + whisperChar(perso2.charId, " Vous poss\xE9dez d\xE9sormais " + quantite2 + " " + consName + "."); + // le MJ est notifi\xE9 : + sendChat('COF', "/w GM " + nomPerso(perso1) + " vient de donner 1 " + consName + " \xE0 " + nomPerso(perso2) + "."); addEvent(evt); } @@ -34626,7 +35006,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -34640,7 +35020,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-provocation n'est pas un token valide"); + error("Le deuxi\xE8me argument de !cof-provocation n'est pas un token valide"); return; } if (cmd.length > 3 && cmd[3] == 'raillerie') { @@ -34689,16 +35069,16 @@ var COFantasy = COFantasy || function() { }); let reussite; switch (res) { - case 0: //en cas d'égalité, on considère que la provocation est réussie + case 0: //en cas d'\xE9galit\xE9, on consid\xE8re que la provocation est r\xE9ussie diminueMalediction(cible, evt); switch (crit) { case -1: - reussite = "Sur un malentendu, la " + action + " réussit..."; + reussite = "Sur un malentendu, la " + action + " r\xE9ussit..."; if (options.raillerie) setAttrDuree(cible, 'enerve', 1, evt); break; case 0: case 1: - reussite = "La " + action + " réussit tout juste."; + reussite = "La " + action + " r\xE9ussit tout juste."; if (options.raillerie) { setAttrDuree(cible, 'enerve', 1, evt); setTokenAttr(cible, 'resistanceRaillerie', @@ -34709,7 +35089,7 @@ var COFantasy = COFantasy || function() { case 1: switch (crit) { case -1: - reussite = nomCible + " marche complètement, il attaque " + nomVoleur; + reussite = nomCible + " marche compl\xE8tement, il attaque " + nomVoleur; if (options.raillerie) { setAttrDuree(cible, 'enerve', 1, evt); removeTokenAttr(cible, 'resistanceRaillerie', evt); @@ -34718,13 +35098,13 @@ var COFantasy = COFantasy || function() { case 0: if (options.raillerie) { setAttrDuree(cible, 'enerve', 1, evt); - reussite = nomVoleur + " a réussi à bien énerver " + nomCible; + reussite = nomVoleur + " a r\xE9ussi \xE0 bien \xE9nerver " + nomCible; setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) + 1, evt); - } else reussite = "La provocation réussit."; + } else reussite = "La provocation r\xE9ussit."; break; case 1: - reussite = "La provocation est une réussite critique !"; + reussite = "La provocation est une r\xE9ussite critique !"; setAttrDuree(cible, 'enerve', 1, evt); setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) - 1, evt); @@ -34733,7 +35113,7 @@ var COFantasy = COFantasy || function() { case 2: switch (crit) { case -1: - reussite = "Échec critique de la " + action + " !"; + reussite = "\xC9chec critique de la " + action + " !"; if (options.raillerie) { setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) + 5, evt); @@ -34744,19 +35124,19 @@ var COFantasy = COFantasy || function() { setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) + 1, evt); } - reussite = "La provocation échoue"; + reussite = "La provocation \xE9choue"; break; case 1: if (options.raillerie) { setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) + 10, evt); } - reussite = nomCible + " voit clair dans le jeu de " + nomVoleur + ". La provocation échoue."; + reussite = nomCible + " voit clair dans le jeu de " + nomVoleur + ". La provocation \xE9choue."; } } addLineToFramedDisplay(display, reussite); sendFramedDisplay(display); - }); //Fin du test opposé + }); //Fin du test oppos\xE9 } function enSelle(msg) { @@ -34800,14 +35180,14 @@ var COFantasy = COFantasy || function() { let nomMonture = cmd.join(' '); let monture = persoOfId(nomMonture, nomMonture, pageId); if (monture === undefined || !predicateAsBool(monture, 'monture')) { - sendPerso(cavalier, "ne peut pas monter là-dessus"); + sendPerso(cavalier, "ne peut pas monter l\xE0-dessus"); log(nomMonture); return; } const tokenM = monture.token; nomMonture = tokenM.get('name'); if (attributeAsBool(monture, 'estMontePar')) { - //Vérifie si le cavalier existe bien sur cette page. + //V\xE9rifie si le cavalier existe bien sur cette page. let cavalierBis; let estMontePar = tokenAttribute(monture, 'estMontePar'); estMontePar.forEach(function(emp) { @@ -34816,7 +35196,7 @@ var COFantasy = COFantasy || function() { if (cavalierBis === undefined) emp.remove(); }); if (cavalierBis) { - sendPerso(cavalier, "ne peut monter sur " + nomMonture + " car " + onGenre(monture, 'il', 'elle') + " a déjà un cavalier, " + nomPerso(cavalierBis)); + sendPerso(cavalier, "ne peut monter sur " + nomMonture + " car " + onGenre(monture, 'il', 'elle') + " a d\xE9j\xE0 un cavalier, " + nomPerso(cavalierBis)); return; } } @@ -34850,9 +35230,9 @@ var COFantasy = COFantasy || function() { } else voieDesElixirs = predicateAsInt(perso, 'voieDesElixirs', 0); if (voieDesElixirs < 1 && !noMsg) { if (arran) - sendPerso(perso, "ne connaît pas la Voie de l'Alchimie"); + sendPerso(perso, "ne conna\xEEt pas la Voie de l'Alchimie"); else - sendPerso(perso, "ne connaît pas la Voie des Élixirs"); + sendPerso(perso, "ne conna\xEEt pas la Voie des \xC9lixirs"); return; } return voieDesElixirs; @@ -34876,7 +35256,7 @@ var COFantasy = COFantasy || function() { if (forgesort === undefined) { let c = getObj('character', cmd[1]); if (c === undefined) { - error("Impossible de savoir qui crée l'élixir", cmd); + error("Impossible de savoir qui cr\xE9e l'\xE9lixir", cmd); return; } forgesort = { @@ -34890,7 +35270,7 @@ var COFantasy = COFantasy || function() { if (exilirInconnu(i, forgesort, voieDesElixirs)) return false; return i.attrName == cmd[2]; }); - if (elixir === undefined) { //Version perso des élixirs + if (elixir === undefined) { //Version perso des \xE9lixirs let altElixirs = findObjs({ _type: 'attribute', _characterid: forgesort.charId @@ -34911,16 +35291,16 @@ var COFantasy = COFantasy || function() { return true; }); if (elixir === undefined) { - error(nomPerso(forgesort) + " est incapable de créer " + cmd[2], cmd); + error(nomPerso(forgesort) + " est incapable de cr\xE9er " + cmd[2], cmd); return; } } const evt = { - type: "Création d'élixir" + type: "Cr\xE9ation d'\xE9lixir" }; addEvent(evt); let arran = persoArran(forgesort); - //Dépense de mana + //D\xE9pense de mana if (!arran && reglesOptionelles.mana.val.elixirs_sorts.val && ficheAttributeAsBool(forgesort, 'option_pm', true)) { if (reglesOptionelles.mana.val.mana_totale.val) { switch (elixir.rang) { @@ -34946,14 +35326,14 @@ var COFantasy = COFantasy || function() { } let elixirsACreer = tokenAttribute(forgesort, 'elixirsACreer'); if (elixirsACreer.length === 0) { - error(nomPerso(forgesort) + " ne peut créer d'élixirs " + cmd[2], cmd); + error(nomPerso(forgesort) + " ne peut cr\xE9er d'\xE9lixirs " + cmd[2], cmd); return; } elixirsACreer = elixirsACreer[0]; let extraFortifiants = toInt(elixirsACreer.get('max'), 0); let extra = extraFortifiants > 0 && elixir.rang == 1; if (!extra) options.decrAttribute = elixirsACreer.id; - if (limiteRessources(forgesort, options, 'elixirsACreer', 'élixirs à créer', evt)) return; + if (limiteRessources(forgesort, options, 'elixirsACreer', '\xE9lixirs \xE0 cr\xE9er', evt)) return; if (extra) { evt.attributes = evt.attributes || []; evt.attributes.push({ @@ -34964,7 +35344,7 @@ var COFantasy = COFantasy || function() { elixirsACreer.set('max', extraFortifiants - 1); } let attrName = 'elixir_' + elixir.attrName; - let message = "crée un " + elixir.nom; + let message = "cr\xE9e un " + elixir.nom; let attr = tokenAttribute(forgesort, attrName); if (attr.length === 0) { let rang = voieDesElixirs; @@ -35015,20 +35395,20 @@ var COFantasy = COFantasy || function() { let titre; if (elixirsACreer < 1) { if (fortifiantExtra < 1) - titre = "Impossible de créer un autre élixir aujourd'hui"; + titre = "Impossible de cr\xE9er un autre \xE9lixir aujourd'hui"; else { titre = "Encore " + fortifiantExtra + " fortifiant"; if (fortifiantExtra > 1) titre += 's'; - titre += "à créer"; + titre += "\xE0 cr\xE9er"; } } else { - titre = "Encore " + elixirsACreer + " élixir"; + titre = "Encore " + elixirsACreer + " \xE9lixir"; if (elixirsACreer > 1) titre += 's'; if (fortifiantExtra > 0) { titre += " et " + fortifiantExtra + " fortifiant"; if (fortifiantExtra > 1) titre += 's'; } - titre += " à créer"; + titre += " \xE0 cr\xE9er"; } let display = startFramedDisplay(playerId, titre, forgesort, { chuchote: true @@ -35036,7 +35416,7 @@ var COFantasy = COFantasy || function() { listeElixirs.forEach(function(elixir) { if (exilirInconnu(elixir, forgesort, voieDesElixirs)) return; if (elixir.rang < 4) { - //Il est possible de changer l'élixir par défaut + //Il est possible de changer l'\xE9lixir par d\xE9faut let altElixir = charAttribute(forgesort.charId, 'Elixir ' + elixir.rang); if (altElixir.length > 0) { elixir.nom = altElixir[0].get('current'); @@ -35128,17 +35508,17 @@ var COFantasy = COFantasy || function() { function proposerRenouveauElixirs(evt, attrs, options) { let attrsNamed = allAttributesNamed(attrs, 'elixir'); if (attrsNamed.length === 0) return attrs; - // Trouver les forgesorts avec des élixirs sur eux + // Trouver les forgesorts avec des \xE9lixirs sur eux let forgesorts = {}; attrsNamed.forEach(function(attr) { - // Check de l'existence d'un créateur + // Check de l'existence d'un cr\xE9ateur let charId = attr.get('characterid'); - let personnage = persoOfCharId(charId, options.pageId, "avec un élixir"); + let personnage = persoOfCharId(charId, options.pageId, "avec un \xE9lixir"); if (personnage === undefined) personnage = { charId }; let voieDesElixirs = rangVoieDesElixirs(personnage, true); - //TODO: réfléchir à une solution pour le renouveau des élixirs échangés + //TODO: r\xE9fl\xE9chir \xE0 une solution pour le renouveau des \xE9lixirs \xE9chang\xE9s if (voieDesElixirs > 0) { let elixirsDuForgesort = forgesorts[charId]; if (elixirsDuForgesort === undefined) { @@ -35148,24 +35528,24 @@ var COFantasy = COFantasy || function() { elixirsParRang: {} }; } - // Check de l'élixir à renouveler + // Check de l'\xE9lixir \xE0 renouveler let nomElixir = attr.get('name'); let typeElixir = listeElixirs.find(function(i) { if (i.rang > voieDesElixirs) return false; return "elixir_" + i.attrName == nomElixir; }); if (typeElixir === undefined) { - error("Impossible de trouver l'élixir à renouveler"); + error("Impossible de trouver l'\xE9lixir \xE0 renouveler"); return; } // Check des doses let doses = attr.get("current"); if (isNaN(doses)) { - error("Erreur interne : élixir mal formé"); + error("Erreur interne : \xE9lixir mal form\xE9"); return; } if (doses > 0) { - // Tout est ok, création de l'item + // Tout est ok, cr\xE9ation de l'item let elixirArenouveler = { typeElixir: typeElixir, doses: doses @@ -35199,7 +35579,7 @@ var COFantasy = COFantasy || function() { opt.maxVal = 2; } setTokenAttr(forgesort, 'elixirsACreer', elixirsDuForgesort.voieDesElixirs * 2, evt, opt); - let display = startFramedDisplay(allPlayers[0], "Renouveler les élixirs", forgesort, displayOpt); + let display = startFramedDisplay(allPlayers[0], "Renouveler les \xE9lixirs", forgesort, displayOpt); let actionToutRenouveler = ""; // Boucle par rang de rune for (const rang in elixirsDuForgesort.elixirsParRang) { @@ -35208,7 +35588,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, "Elixirs de rang " + rang, undefined, true); let actionTout = ''; let ligneBoutons = ''; - // Boucle par élixir de ce rang à renouveler + // Boucle par \xE9lixir de ce rang \xE0 renouveler for (const i in elixirsDeRang) { let elixir = elixirsDeRang[i]; // Boucle par dose @@ -35242,9 +35622,9 @@ var COFantasy = COFantasy || function() { var liste = []; if (rang < 2) return liste; liste.push({ - nom: "Rune d'énergie", + nom: "Rune d'\xE9nergie", action: "!cof-rune-energie", - attrName: "runeForgesort_énergie", + attrName: "runeForgesort_\xE9nergie", rang: 2 }); if (rang < 3) return liste; @@ -35274,19 +35654,19 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(forgesort) { let voieDesRunes = predicateAsInt(forgesort, 'voieDesRunes', 0); if (voieDesRunes < 1) { - sendPerso(forgesort, "ne connaît pas la Voie des Runes."); + sendPerso(forgesort, "ne conna\xEEt pas la Voie des Runes."); return; } else if (voieDesRunes < 2) { - sendPerso(forgesort, "ne peut écrire que des Runes de défense."); + sendPerso(forgesort, "ne peut \xE9crire que des Runes de d\xE9fense."); return; } - let titre = "Création de runes"; + let titre = "Cr\xE9ation de runes"; let display = startFramedDisplay(playerId, titre, forgesort, { chuchote: true }); listeRunes(voieDesRunes).forEach(function(rune) { var action = "!cof-creer-rune " + forgesort.token.id + " @{target|token_id} " + rune.rang; - if (rune.rang === 4) action += " ?{Numéro de l'arme de la cible?}"; + if (rune.rang === 4) action += " ?{Num\xE9ro de l'arme de la cible?}"; var options = bouton(action, rune.nom, forgesort); addLineToFramedDisplay(display, options); }); @@ -35310,40 +35690,40 @@ var COFantasy = COFantasy || function() { forgesort = persoOfId(msg.selected[0]._id); } if (forgesort === undefined) { - error("Impossible de savoir qui crée la rune", cmd); + error("Impossible de savoir qui cr\xE9e la rune", cmd); return; } } var target = persoOfId(cmd[2], cmd[2], options.pageId); if (target === undefined) { - error("Impossible de savoir à qui octroyer la rune", cmd); + error("Impossible de savoir \xE0 qui octroyer la rune", cmd); return; } var voieDesRunes = predicateAsInt(forgesort, 'voieDesRunes', 0); if (voieDesRunes < 1) { - sendPerso(forgesort, "ne connaît pas la Voie des Runes"); + sendPerso(forgesort, "ne conna\xEEt pas la Voie des Runes"); return; } else if (voieDesRunes < 2) { - sendPerso(forgesort, "ne peut écrire que des Runes de défense."); + sendPerso(forgesort, "ne peut \xE9crire que des Runes de d\xE9fense."); return; } var rune = listeRunes(voieDesRunes).find(function(i) { return i.rang == cmd[3]; }); if (rune === undefined) { - error(nomPerso(forgesort) + " est incapable de créer " + cmd[3], cmd); + error(nomPerso(forgesort) + " est incapable de cr\xE9er " + cmd[3], cmd); return; } var labelArme; if (rune.rang == 4) { if (cmd.length < 5) { - error("La rune de puissance nécessite de choisir un label d'arme."); + error("La rune de puissance n\xE9cessite de choisir un label d'arme."); return; } labelArme = parseInt(cmd[4]); } var evt = { - type: "Création de rune" + type: "Cr\xE9ation de rune" }; addEvent(evt); if (ficheAttributeAsBool(forgesort, 'option_pm', true)) { @@ -35364,11 +35744,11 @@ var COFantasy = COFantasy || function() { } } let attrName = rune.attrName; - let message = "reçoit "; + let message = "re\xE7oit "; let typeRune; switch (rune.rang) { case 2: - typeRune = "une rune d'énergie"; + typeRune = "une rune d'\xE9nergie"; break; case 3: typeRune = "une rune de protection"; @@ -35383,10 +35763,10 @@ var COFantasy = COFantasy || function() { } message += typeRune; if (attributeAsInt(target, attrName, 0) > 0) { - error("La cible possède déjà une rune " + typeRune, cmd); + error("La cible poss\xE8de d\xE9j\xE0 une rune " + typeRune, cmd); return; } - if (options.mana !== undefined && limiteRessources(forgesort, options, undefined, "créer " + typeRune, evt)) return; + if (options.mana !== undefined && limiteRessources(forgesort, options, undefined, "cr\xE9er " + typeRune, evt)) return; setTokenAttr(target, attrName, 1, evt, { msg: message, maxVal: forgesort.charId @@ -35402,19 +35782,19 @@ var COFantasy = COFantasy || function() { function proposerRenouveauRunes(evt, attrs, options) { let attrsNamed = allAttributesNamed(attrs, 'runeForgesort'); if (attrsNamed.length === 0) return attrs; - // Filtrer par Forgesort, dans l'éventualité qu'il y en ait plusieurs actifs + // Filtrer par Forgesort, dans l'\xE9ventualit\xE9 qu'il y en ait plusieurs actifs let forgesorts = {}; attrsNamed.forEach(function(attr) { - // Check de l'existence d'un créateur + // Check de l'existence d'un cr\xE9ateur let forgesortId = attr.get('max'); if (forgesortId === undefined) { - error("Impossible de retrouver le créateur de la rune : " + attr); + error("Impossible de retrouver le cr\xE9ateur de la rune : " + attr); return; } let runesDuForgesort = forgesorts[forgesortId]; if (runesDuForgesort === undefined) { - // Check de l'existence d'un token présent pour le créateur - let forgesort = persoOfCharId(forgesortId, options.pageId, "ayant créé une rune"); + // Check de l'existence d'un token pr\xE9sent pour le cr\xE9ateur + let forgesort = persoOfCharId(forgesortId, options.pageId, "ayant cr\xE9\xE9 une rune"); if (forgesort === undefined) { attr.remove(); return; @@ -35422,10 +35802,10 @@ var COFantasy = COFantasy || function() { // Check du perso voie des Runes let voieDesRunes = predicateAsInt(forgesort, 'voieDesRunes', 0); if (voieDesRunes < 1) { - sendPerso(forgesort, "ne connaît pas la Voie des Runes"); + sendPerso(forgesort, "ne conna\xEEt pas la Voie des Runes"); return; } else if (voieDesRunes < 2) { - sendPerso(forgesort, "ne peut écrire que des Runes de défense."); + sendPerso(forgesort, "ne peut \xE9crire que des Runes de d\xE9fense."); return; } runesDuForgesort = { @@ -35434,21 +35814,21 @@ var COFantasy = COFantasy || function() { runesParRang: {} }; } - // Check de la présence d'un token pour la cible + // Check de la pr\xE9sence d'un token pour la cible let targetCharId = attr.get('characterid'); let target = persoOfCharId(targetCharId, options.pageId, "ayant une rune"); if (target === undefined) return; - // Check de la rune à renouveler + // Check de la rune \xE0 renouveler let runeName = attr.get('name'); let typeRune = listeRunes(runesDuForgesort.voieDesRunes).find(function(i) { return i.attrName == runeName.split("(")[0]; }); if (typeRune === undefined) { - error("Impossible de trouver la rune à renouveler"); + error("Impossible de trouver la rune \xE0 renouveler"); return; } - // Tout est ok, création de l'item + // Tout est ok, cr\xE9ation de l'item let runeARenouveler = { target: target, typeRune: typeRune, @@ -35485,7 +35865,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, runesDeRang[0].typeRune.nom, undefined, true); let actionTout = ""; let ligneBoutons = ""; - // Boucle par rune de ce rang à renouveler + // Boucle par rune de ce rang \xE0 renouveler for (const i in runesDeRang) { let rune = runesDeRang[i]; let action = @@ -35518,7 +35898,7 @@ var COFantasy = COFantasy || function() { if (msg.content.includes(' --furie')) typeRage = 'furie'; getSelected(msg, function(selection, playerId) { if (selection.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour la rage", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour la rage", playerId); return; } const options = parseOptions(msg); @@ -35549,17 +35929,17 @@ var COFantasy = COFantasy || function() { typeRage = attrRage.get('current'); let difficulte = 13; if (typeRage == 'furie') difficulte = 16; - //Jet de sagesse difficulté 13 pou 16 pour sortir de cet état + //Jet de sagesse difficult\xE9 13 pou 16 pour sortir de cet \xE9tat let display = startFramedDisplay(options.playerId, "Essaie de calmer sa " + typeRage, perso); let testId = 'rageDuBerserk_' + perso.token.id; testCaracteristique(perso, 'SAG', difficulte, testId, options, evt, function(tr) { - addLineToFramedDisplay(display, "Résultat du jet de SAG : " + tr.texte); + addLineToFramedDisplay(display, "R\xE9sultat du jet de SAG : " + tr.texte); if (tr.reussite) { - addLineToFramedDisplay(display, "C'est réussi, " + nomPerso(perso) + " se calme." + tr.modifiers); + addLineToFramedDisplay(display, "C'est r\xE9ussi, " + nomPerso(perso) + " se calme." + tr.modifiers); removeTokenAttr(perso, 'rageDuBerserk', evt); } else { - let msgRate = "C'est raté, " + nomPerso(perso) + " reste enragé" + tr.rerolls + tr.modifiers; + let msgRate = "C'est rat\xE9, " + nomPerso(perso) + " reste enrag\xE9" + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, msgRate); } sendFramedDisplay(display); @@ -35586,17 +35966,17 @@ var COFantasy = COFantasy || function() { var options = parseOptions(msg); var cmd = msg.content.split(' '); if (cmd.length < 3) { - error("Il faut deux arguments à !cof-arme-secrete", cmd); + error("Il faut deux arguments \xE0 !cof-arme-secrete", cmd); return; } var barde = persoOfId(cmd[1]); var cible = persoOfId(cmd[2]); if (barde === undefined || cible === undefined) { - error("Token non valide pour l'arme secrète", cmd); + error("Token non valide pour l'arme secr\xE8te", cmd); return; } if (attributeAsInt(barde, 'armeSecreteBardeUtilisee')) { - sendPerso(barde, "a déjà utilisé son arme secrète durant ce combat"); + sendPerso(barde, "a d\xE9j\xE0 utilis\xE9 son arme secr\xE8te durant ce combat"); return; } doArmeSecrete(barde, cible, options); @@ -35624,14 +36004,14 @@ var COFantasy = COFantasy || function() { var testId = 'armeSecreteBarde'; testCaracteristique(perso, 'CHA', intCible, testId, options, evt, function(tr) { var display = startFramedDisplay(options.playerId, - "Arme secrète", perso, { + "Arme secr\xE8te", perso, { perso2: cible }); var line = "Jet de CHA : " + tr.texte; if (tr.reussite) { line += " ≥ " + intCible + tr.modifiers; addLineToFramedDisplay(display, line); - addLineToFramedDisplay(display, nomPerso(cible) + " est complètement déstabilisé"); + addLineToFramedDisplay(display, nomPerso(cible) + " est compl\xE8tement d\xE9stabilis\xE9"); setAttrDuree(cible, 'armeSecreteBarde', 1, evt); } else { line += " < " + intCible + tr.rerolls + tr.modifiers; @@ -35660,15 +36040,15 @@ var COFantasy = COFantasy || function() { } } - //Crée un nouveau personnage (de type PNJ par défaut) - //spec contient les charactéristiques, attributs et abilities - // - attributesFiche contient les attributs définis dans la fiche + //Cr\xE9e un nouveau personnage (de type PNJ par d\xE9faut) + //spec contient les charact\xE9ristiques, attributs et abilities + // - attributesFiche contient les attributs d\xE9finis dans la fiche // nom_attribut: valeur - // - pv (permet d'être indépendant de PJ ou PNJ) + // - pv (permet d'\xEAtre ind\xE9pendant de PJ ou PNJ) // - attaques, liste d'attaques, chacune avec (nom, atk, dmnbde, dmde, dm,...) // - attributes autres attributs (name, current, max) - // - abilities (name, action), toujours rajoutées à la liste d'actions - // - actions (titre, code), ajoutées aux listes d'actions + // - abilities (name, action), toujours rajout\xE9es \xE0 la liste d'actions + // - actions (titre, code), ajout\xE9es aux listes d'actions function createCharacter(nom, playerId, avatar, token, spec, evt, createur) { let res = createObj('character', { name: nom, @@ -35885,7 +36265,7 @@ var COFantasy = COFantasy || function() { } let tokenArbre = getObj('graphic', cmd[2]); if (tokenArbre === undefined) { - error("Le deuxième argument de !cof-animer-arbre n'est pas un token", cmd); + error("Le deuxi\xE8me argument de !cof-animer-arbre n'est pas un token", cmd); return; } if (tokenArbre.get('represents') !== '') { @@ -35900,10 +36280,10 @@ var COFantasy = COFantasy || function() { } } let rang = predicateAsInt(druide, 'voieDesVegetaux', 3); - if (cmd.length > 3) { //Le rang est spécifié en argument optionnel + if (cmd.length > 3) { //Le rang est sp\xE9cifi\xE9 en argument optionnel let cmd3 = parseInt(cmd[3]); if (isNaN(cmd3) || cmd3 < 1) { - error("Le rang n'est pas un nombre valie. On utilise " + rang + " à la place", cmd); + error("Le rang n'est pas un nombre valie. On utilise " + rang + " \xE0 la place", cmd); } else rang = cmd3; } const evt = { @@ -35915,7 +36295,7 @@ var COFantasy = COFantasy || function() { initPerso(druide, evt); } let niveau = ficheAttributeAsInt(druide, 'niveau', 1); - let nomArbre = nouveauNomDePerso('Arbre animé'); + let nomArbre = nouveauNomDePerso('Arbre anim\xE9'); let avatar = "https://s3.amazonaws.com/files.d20.io/images/42323556/6qxlm965aFhBXGoYFy5fqg/thumb.png?1510582137"; let specArbre = { pv: rang * 10, @@ -35958,11 +36338,11 @@ var COFantasy = COFantasy || function() { }; let charArbre = createCharacter(nomArbre, options.playerId, avatar, tokenArbre, specArbre, evt, druide); evt.characters = [charArbre]; - sendChar(charArbre.id, "commence à s'animer", true); + sendChar(charArbre.id, "commence \xE0 s'animer", true); initiative([{ _id: tokenArbre.id }], evt); - // Ajout de l'arbre animé aux alliés du Druide + // Ajout de l'arbre anim\xE9 aux alli\xE9s du Druide let alliesDruide = alliesParPerso[druide.charId] || new Set(); alliesDruide.add(charArbre.id); alliesParPerso[druide.charId] = alliesDruide; @@ -35978,20 +36358,20 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; var cmd = options.cmd; var evt = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } if (evt.type != 'Attaque') { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour absorber l'attaque précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour absorber l'attaque pr\xE9c\xE9dente"); return; } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Personne n'est sélectionné pour utiliser une rune", msg); + error("Personne n'est s\xE9lectionn\xE9 pour utiliser une rune", msg); return; } var action = evt.action; @@ -36004,7 +36384,7 @@ var COFantasy = COFantasy || function() { return (target.token.id === perso.token.id); }); if (cible === undefined) { - sendPerso(perso, "n'est pas la cible de la dernière attaque"); + sendPerso(perso, "n'est pas la cible de la derni\xE8re attaque"); return; } if (!attributeAsBool(perso, 'runeForgesort_protection')) { @@ -36012,7 +36392,7 @@ var COFantasy = COFantasy || function() { return; } if (attributeAsInt(perso, 'limiteParCombat_runeForgesort_protection', 1) < 1) { - sendPerso(perso, "a déjà utilisé sa rune de protection durant ce combat"); + sendPerso(perso, "a d\xE9j\xE0 utilis\xE9 sa rune de protection durant ce combat"); return; } action.choices = action.choices || {}; @@ -36040,8 +36420,8 @@ var COFantasy = COFantasy || function() { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; - if (cmd === undefined || cmd.length < 3) { - error("cof-delivrance attend 2 arguments", msg.content); + if (cmd === undefined || cmd.length < 2) { + error("cof-delivrance attend un argument", msg.content); return; } let pretre = persoOfId(cmd[1], cmd[1], options.pageId); @@ -36049,127 +36429,143 @@ var COFantasy = COFantasy || function() { error("Le premier argument de !cof-delivrance n'est pas un token valide", msg.content); return; } - let cible = persoOfId(cmd[2], cmd[2], options.pageId); - if (cible === undefined) { - error("Le deuxième argument de !cof-delivrance n'est pas un token valide", msg.content); - return; - } - if (options.portee !== undefined) { - let dist = distanceCombat(pretre.token, cible.token, options.pageId); - if (dist > options.portee) { - sendPerso(pretre, "est trop loin de " + nomPerso(cible)); + let c; + if (cmd.length > 2) c = persoOfId(cmd[2], cmd[2], options.pageId); + let cibles = [c]; + if (c === undefined) { + cibles = []; + getSelected(msg, function(selected, playerId) { + iterSelected(selected, function(cible) { + cibles.push(cible); + }); + }); + if (cibles.length < 1) { + error("Le deuxi\xE8me argument de !cof-delivrance n'est pas un token valide", msg.content); return; } } + if (options.portee !== undefined) { + cibles = cibles.filter(function(cible) { + let dist = distanceCombat(pretre.token, cible.token, options.pageId); + if (dist > options.portee) { + sendPerso(pretre, "est trop loin de " + nomPerso(cible)); + return false; + } + return true; + }); + } + if (cibles.length < 1) return; const evt = { - type: "Délivrance", + type: "D\xE9livrance", deletedAttributes: [] }; addEvent(evt); - if (limiteRessources(pretre, options, 'délivrance', 'délivrance', evt)) return; - let display = startFramedDisplay(getPlayerIdFromMsg(msg), 'Délivrance', pretre, { - perso2: cible - }); - let printEffet = function(message) { - addLineToFramedDisplay(display, nomPerso(cible) + ' ' + message); - }; - let optFin = { - print: printEffet, - pageId: options.pageId - }; - _.each(messageEffetTemp, function(effet, nomEffet) { - if (effet.prejudiciable) { - //Attention, ne fonctionne pas avec les effets génériques - let attr = tokenAttribute(cible, nomEffet); - if (attr.length > 0) - finDEffet(attr[0], nomEffet, attr[0].get('name'), cible.charId, evt, optFin); - } - }); - _.each(messageEffetCombat, function(effet, nomEffet) { - if (effet.prejudiciable) { - let attr = tokenAttribute(cible, nomEffet); - if (attr.length > 0) { - printEffet(messageFin(cible, effet)); - evt.deletedAttributes.push(attr[0]); - attr[0].remove(); + if (limiteRessources(pretre, options, 'd\xE9livrance', 'd\xE9livrance', evt)) return; + cibles.forEach(function(cible) { + let display = startFramedDisplay(getPlayerIdFromMsg(msg), 'D\xE9livrance', pretre, { + perso2: cible + }); + let printEffet = function(message) { + addLineToFramedDisplay(display, nomPerso(cible) + ' ' + message); + }; + let optFin = { + print: printEffet, + pageId: options.pageId + }; + _.each(messageEffetTemp, function(effet, nomEffet) { + if (effet.prejudiciable) { + //Attention, ne fonctionne pas avec les effets g\xE9n\xE9riques + let attr = tokenAttribute(cible, nomEffet); + if (attr.length > 0) + finDEffet(attr[0], nomEffet, attr[0].get('name'), cible.charId, evt, optFin); } - } - }); - _.each(messageEffetIndetermine, function(effet, nomEffet) { - if (effet.prejudiciable) { - let attr = tokenAttribute(cible, nomEffet); - if (attr.length > 0) { - printEffet(messageFin(cible, effet)); - evt.deletedAttributes.push(attr[0]); - attr[0].remove(); + }); + _.each(messageEffetCombat, function(effet, nomEffet) { + if (effet.prejudiciable) { + let attr = tokenAttribute(cible, nomEffet); + if (attr.length > 0) { + printEffet(messageFin(cible, effet)); + evt.deletedAttributes.push(attr[0]); + attr[0].remove(); + } } + }); + _.each(messageEffetIndetermine, function(effet, nomEffet) { + if (effet.prejudiciable) { + let attr = tokenAttribute(cible, nomEffet); + if (attr.length > 0) { + printEffet(messageFin(cible, effet)); + evt.deletedAttributes.push(attr[0]); + attr[0].remove(); + } + } + }); + if (attributeAsBool(cible, 'malediction')) { + printEffet("n'est plus maudite"); + removeTokenAttr(cible, 'malediction', evt); + } + if (attributeAsBool(cible, 'pointsDeSang')) { + printEffet("n'a plus de point de sang."); + removeTokenAttr(cible, 'pointsDeSang', evt); + } + //On enl\xE8ve les \xE9tats pr\xE9judiciables + if (getState(cible, 'aveugle')) { + printEffet("retrouve la vue"); + setState(cible, 'aveugle', false, evt); + } + if (getState(cible, 'affaibli')) { + printEffet("retrouve des forces"); + setState(cible, 'affaibli', false, evt); + } + if (getState(cible, 'etourdi')) { + printEffet("retrouve ses esprits"); + setState(cible, 'etourdi', false, evt); + } + if (getState(cible, 'paralyse')) { + printEffet("peut \xE0 nouveau bouger"); + setState(cible, 'paralyse', false, evt); + } + if (getState(cible, 'ralenti')) { + printEffet("retrouve une vitesse normale"); + setState(cible, 'ralenti', false, evt); + } + if (getState(cible, 'endormi')) { + printEffet("se r\xE9veille"); + setState(cible, 'endormi', false, evt); + } + if (getState(cible, 'apeure')) { + printEffet("reprend courage"); + setState(cible, 'apeure', false, evt); + } + //R\xE9g\xE9n\xE9ration d'une carac affaiblie de 1d4, si il y en a. + if (attributeAsInt(cible, 'affaiblissementdesagesse', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'sagesse', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de sagesse"); + } else if (attributeAsInt(cible, 'affaiblissementdecharisme', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'charisme', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de charisme"); + } else if (attributeAsInt(cible, 'affaiblissementdeintelligence', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'intelligence', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points d'intelligence"); + } + if (attributeAsInt(cible, 'affaiblissementdeconstitution', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'constitution', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de constitution"); + } else if (attributeAsInt(cible, 'affaiblissementdeforce', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'force', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de force"); + } else if (attributeAsInt(cible, 'affaiblissementdedexterite', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'dexterite', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de dext\xE9rit\xE9"); } + sendFramedDisplay(display); }); - if (attributeAsBool(cible, 'malediction')) { - printEffet("n'est plus maudite"); - removeTokenAttr(cible, 'malediction', evt); - } - if (attributeAsBool(cible, 'pointsDeSang')) { - printEffet("n'a plus de point de sang."); - removeTokenAttr(cible, 'pointsDeSang', evt); - } - //On enlève les états préjudiciables - if (getState(cible, 'aveugle')) { - printEffet("retrouve la vue"); - setState(cible, 'aveugle', false, evt); - } - if (getState(cible, 'affaibli')) { - printEffet("retrouve des forces"); - setState(cible, 'affaibli', false, evt); - } - if (getState(cible, 'etourdi')) { - printEffet("retrouve ses esprits"); - setState(cible, 'etourdi', false, evt); - } - if (getState(cible, 'paralyse')) { - printEffet("peut à nouveau bouger"); - setState(cible, 'paralyse', false, evt); - } - if (getState(cible, 'ralenti')) { - printEffet("retrouve une vitesse normale"); - setState(cible, 'ralenti', false, evt); - } - if (getState(cible, 'endormi')) { - printEffet("se réveille"); - setState(cible, 'endormi', false, evt); - } - if (getState(cible, 'apeure')) { - printEffet("reprend courage"); - setState(cible, 'apeure', false, evt); - } - //Régénération d'une carac affaiblie de 1d4, si il y en a. - if (attributeAsInt(cible, 'affaiblissementdesagesse', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'sagesse', d4.val, evt); - printEffet("récupère " + d4.roll + " points de sagesse"); - } else if (attributeAsInt(cible, 'affaiblissementdecharisme', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'charisme', d4.val, evt); - printEffet("récupère " + d4.roll + " points de charisme"); - } else if (attributeAsInt(cible, 'affaiblissementdeintelligence', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'intelligence', d4.val, evt); - printEffet("récupère " + d4.roll + " points d'intelligence"); - } - if (attributeAsInt(cible, 'affaiblissementdeconstitution', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'constitution', d4.val, evt); - printEffet("récupère " + d4.roll + " points de constitution"); - } else if (attributeAsInt(cible, 'affaiblissementdeforce', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'force', d4.val, evt); - printEffet("récupère " + d4.roll + " points de force"); - } else if (attributeAsInt(cible, 'affaiblissementdedexterite', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'dexterite', d4.val, evt); - printEffet("récupère " + d4.roll + " points de dextérité"); - } - sendFramedDisplay(display); } function guerisonPerso(perso, evt, lanceur) { @@ -36181,36 +36577,36 @@ var COFantasy = COFantasy || function() { msgSoin = 'soigne ' + nomPerso(perso); } } else { - msgSoin = 'récupère'; + msgSoin = 'r\xE9cup\xE8re'; } msgSoin += ' de toutes les blessures subies'; if (lanceur) sendPerso(lanceur, msgSoin); else sendPerso(perso, msgSoin); if (getState(perso, 'blesse')) { setState(perso, 'blesse', false, evt); - } else { //On peut bien faire récupérer un PR + } else { //On peut bien faire r\xE9cup\xE9rer un PR let d = rajouterPointDeRecuperation(perso, evt); - if (d) sendPerso(perso, "récupère un point de récupération"); + if (d) sendPerso(perso, "r\xE9cup\xE8re un point de r\xE9cup\xE9ration"); } let soins = perso.token.get('bar1_max') - perso.token.get('bar1_value'); if (isNaN(soins)) { updateCurrentBar(perso, 1, perso.token.get('bar1_max'), evt); return; } - //Les affaiblissements de caractéristiques + //Les affaiblissements de caract\xE9ristiques allCaracs.forEach(function(carac) { let malus = attributeAsInt(perso, 'affaiblissementde' + carac, 0); if (malus > 0) { diminueAffaiblissement(perso, carac, malus, evt, malus); - sendPerso(perso, "récupère " + malus + " points " + deCarac(carac)); + sendPerso(perso, "r\xE9cup\xE8re " + malus + " points " + deCarac(carac)); } }); - //La putréfaction des momies + //La putr\xE9faction des momies if (attributeAsBool(perso, 'putrefaction')) { finDEffetDeNom(perso, 'putrefaction', evt); } if (soins <= 0) { - //Rien d'autre à faire (le script ne gère pas encore le reste) + //Rien d'autre \xE0 faire (le script ne g\xE8re pas encore le reste) return; } soigneToken(perso, soins, evt); @@ -36221,8 +36617,8 @@ var COFantasy = COFantasy || function() { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; - if (cmd === undefined || cmd.length < 3) { - error("cof-guerison attend le lanceur et la cible en argument", msg.content); + if (cmd === undefined || cmd.length < 2) { + error("cof-guerison attend le lanceur en argument", msg.content); return; } let lanceur = persoOfId(cmd[1], cmd[1], options.pageId); @@ -36230,27 +36626,49 @@ var COFantasy = COFantasy || function() { error("Le premier argument de !cof-guerison n'est pas un token valide", msg.content); return; } - let cible = persoOfId(cmd[2], cmd[2], options.pageId); - if (cible === undefined) { - error("Le deuxième argument de !cof-guerison n'est pas un token valide", msg.content); - return; + let c; + if (cmd.length > 2) c = persoOfId(cmd[2], cmd[2], options.pageId); + let cibles = [c]; + if (c === undefined) { + cibles = []; + getSelected(msg, function(selected, playerId) { + iterSelected(selected, function(cible) { + cibles.push(cible); + }); + }); + if (cibles.length < 1) { + if (cmd.length < 3) { + error("cof-guerison attend le lanceur et la cible en argument", msg.content); + } else { + error("Le deuxi\xE8me argument de !cof-guerison n'est pas un token valide", msg.content); + } + return; + } } if (options.dose === undefined && options.decrAttribute === undefined) { - options.limiteParJour = 1; + options.limiteParJour = { + val: 1 + }; } if (options.portee !== undefined) { - const dist = distanceCombat(lanceur.token, cible.token, options.pageId); - if (dist > options.portee) { - sendPerso(lanceur, "est trop loin de " + nomPerso(cible)); - return; - } + cibles = cibles.filter(function(cible) { + const dist = distanceCombat(lanceur.token, cible.token, options.pageId); + if (dist > options.portee) { + sendPerso(lanceur, "est trop loin de " + nomPerso(cible)); + return false; + } + return true; + }); } + if (cibles.length < 1) return; const evt = { - type: "Guérison", + type: "Gu\xE9rison", }; addEvent(evt); - if (limiteRessources(lanceur, options, 'guérison', 'guérison', evt)) return; - guerisonPerso(cible, evt, lanceur); + if (limiteRessources(lanceur, options, 'gu\xE9rison', 'gu\xE9rison', evt)) return; + cibles.forEach(function(cible) { + guerisonPerso(cible, evt, lanceur); + }); if (options.messages) { options.messages.forEach(function(m) { sendChat('', m); @@ -36263,16 +36681,16 @@ var COFantasy = COFantasy || function() { arme = armesEnMain(perso); if (arme === undefined && labelArmeDefaut) arme = getWeaponStats(perso, labelArmeDefaut); - //L'arme doit être une arme de contact ? + //L'arme doit \xEAtre une arme de contact ? if (armeContact && arme && arme.portee) { - sendPerso(perso, armeContact + " " + arme.name + " est une arme à distance."); + sendPerso(perso, armeContact + " " + arme.name + " est une arme \xE0 distance."); return; } if (arme) { return arme; } arme = { - name: 'Attaque par défaut', + name: 'Attaque par d\xE9faut', attSkillDiv: 0, attSkill: "@{ATKCAC}", crit: 20, @@ -36288,12 +36706,12 @@ var COFantasy = COFantasy || function() { }; options.contact = true; entrerEnCombat(attaquant, [defenseur], explications, evt); - //Recherche des armes utilisées + //Recherche des armes utilis\xE9es let armeAttaquant = armeDeContact(attaquant, options.armeAttaquant, options.labelArmeAttaquant, options.armeAttaquantContact); let armeDefenseur = armeDeContact(defenseur, options.armeDefenseur, options.labelArmeDefenseur, options.armeDefenseurContact); - let action = options.action || "Attaque opposée"; + let action = options.action || "Attaque oppos\xE9e"; if (!armeAttaquant.parDefaut) { action += " (" + armeAttaquant.name + ")"; } @@ -36313,7 +36731,7 @@ var COFantasy = COFantasy || function() { } } else if (getState(attaquant, 'immobilise')) { dice = 12; - explications.push("Attaquant immobilisé => D12 au lieu de D20 en Attaque"); + explications.push("Attaquant immobilis\xE9 => D12 au lieu de D20 en Attaque"); } let toEvaluateAttack = attackExpression(attaquant, 1, dice, critAttaquant, true, armeAttaquant); @@ -36352,14 +36770,14 @@ var COFantasy = COFantasy || function() { if (estAffaibli(defenseur)) { if (predicateAsBool(defenseur, 'insensibleAffaibli')) { malusAttaque = -2; - explications.push("Défenseur affaibli, mais insensible => -2 en Attaque"); + explications.push("D\xE9fenseur affaibli, mais insensible => -2 en Attaque"); } else { dice = 12; - explications.push("Défenseur affaibli => D12 au lieu de D20 en Attaque"); + explications.push("D\xE9fenseur affaibli => D12 au lieu de D20 en Attaque"); } } else if (getState(defenseur, 'immobilise')) { dice = 12; - explications.push("Défenseur immobilisé => D12 au lieu de D20 en Attaque"); + explications.push("D\xE9fenseur immobilis\xE9 => D12 au lieu de D20 en Attaque"); } toEvaluateAttack = attackExpression(defenseur, 1, dice, critDefenseur, true, armeDefenseur); sendChat('', toEvaluateAttack, function(resAttack) { @@ -36417,11 +36835,11 @@ var COFantasy = COFantasy || function() { resultat.succes = true; diminueMalediction(defenseur, evt); } - callback(resultat, display, explications); //evt est mis à jour - }); //fin du sendchat pour jet du défenseur + callback(resultat, display, explications); //evt est mis \xE0 jour + }); //fin du sendchat pour jet du d\xE9fenseur }); //Fin du sendChat pour jet de l'attaquant } catch (rollError) { - error("Erreur pendant le jet " + toEvaluateAttack + " dans attaqueContactOpposé", options); + error("Erreur pendant le jet " + toEvaluateAttack + " dans attaqueContactOppos\xE9", options); } } @@ -36434,15 +36852,15 @@ var COFantasy = COFantasy || function() { const attaquant = persoOfId(cmd[1], cmd[1]); const defenseur = persoOfId(cmd[2], cmd[2]); if (attaquant === undefined) { - error("Le premier argument de !cof-test-attaque-opposee doit être un token valide", cmd[1]); + error("Le premier argument de !cof-test-attaque-opposee doit \xEAtre un token valide", cmd[1]); return; } if (defenseur === undefined) { - error("Le deuxième argument de !cof-test-attaque-opposee doit être un token valide", cmd[2]); + error("Le deuxi\xE8me argument de !cof-test-attaque-opposee doit \xEAtre un token valide", cmd[2]); return; } const evt = { - type: "Test d'attaque opposée" + type: "Test d'attaque oppos\xE9e" }; const options = { pasDeDmg: true @@ -36467,7 +36885,7 @@ var COFantasy = COFantasy || function() { function desarmer(msg) { let cmd = msg.content.split(' '); if (cmd.length < 3) { - error("Il manque des arguments à !cof-desarmer", msg.content); + error("Il manque des arguments \xE0 !cof-desarmer", msg.content); return; } const guerrier = persoOfId(cmd[1], cmd[1]); @@ -36477,21 +36895,21 @@ var COFantasy = COFantasy || function() { } const cible = persoOfId(cmd[2], cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-desarmer n'est pas un token valide", cmd); + error("Le deuxi\xE8me argument de !cof-desarmer n'est pas un token valide", cmd); return; } let pageId = guerrier.token.get('pageid'); if (distanceCombat(guerrier.token, cible.token, pageId)) { - sendPerso(guerrier, "est trop loin de " + nomPerso(cible) + " pour le désarmer."); + sendPerso(guerrier, "est trop loin de " + nomPerso(cible) + " pour le d\xE9sarmer."); return; } - var options = { - action: "Désarmement", - armeContact: "doit porter une arme de contact pour désarmer son adversaire.", + const options = { + action: "D\xE9sarmement", + armeContact: "doit porter une arme de contact pour d\xE9sarmer son adversaire.", pasDeDmg: true, pageId: pageId, }; - //On cherche l'arme de la cible. On en aura besoin pour désarmer + //On cherche l'arme de la cible. On en aura besoin pour d\xE9sarmer let armeCible = armesEnMain(cible); let attrArmeCible = cible.attrArmeEnMain; if (armeCible) { @@ -36499,7 +36917,7 @@ var COFantasy = COFantasy || function() { if (armeCible.deuxMains) { options.bonusAttaqueDefenseur = [{ val: 5, - explication: nomPerso(cible) + " porte une arme à 2 mains => +5 à son jet" + explication: nomPerso(cible) + " porte une arme \xE0 2 mains => +5 \xE0 son jet" }]; } } @@ -36512,7 +36930,7 @@ var COFantasy = COFantasy || function() { } }; const evt = { - type: 'Désarmer' + type: 'D\xE9sarmer' }; if (cmd.length > 3) options.labelArmeAttaquant = cmd[3]; const playerId = getPlayerIdFromMsg(msg); @@ -36520,23 +36938,23 @@ var COFantasy = COFantasy || function() { function(res, display, explications) { let resultat; if (res.echecCritique) { - resultat = "échec critique"; + resultat = "\xE9chec critique"; } else if (res.echecCritiqueDefenseur) { - resultat = "succès, " + nomPerso(cible) + " laisse tomber son arme, difficile de la récupérer..."; + resultat = "succ\xE8s, " + nomPerso(cible) + " laisse tomber son arme, difficile de la r\xE9cup\xE9rer..."; enleverArmeCible(); } else if (res.critique) { - resultat = "réussite critique : " + nomPerso(cible) + " est désarmé, et " + nomPerso(guerrier) + " empêche de reprendre l'arme"; + resultat = "r\xE9ussite critique : " + nomPerso(cible) + " est d\xE9sarm\xE9, et " + nomPerso(guerrier) + " emp\xEAche de reprendre l'arme"; enleverArmeCible(); } else if (res.critiqueDefenseur) { - resultat = "échec, " + nomPerso(cible) + " garde son arme bien en main"; + resultat = "\xE9chec, " + nomPerso(cible) + " garde son arme bien en main"; } else if (res.echec) { - resultat = "échec, " + nomPerso(guerrier) + " n'a pas réussi à désarmer son adversaire"; - } else { //succès + resultat = "\xE9chec, " + nomPerso(guerrier) + " n'a pas r\xE9ussi \xE0 d\xE9sarmer son adversaire"; + } else { //succ\xE8s enleverArmeCible(); if (res.rollAttaquant > res.rollDefenseur + 9) { - resultat = "succès, " + nomPerso(guerrier) + " désarme son adversaire et l'empêche de récupérer son arme"; + resultat = "succ\xE8s, " + nomPerso(guerrier) + " d\xE9sarme son adversaire et l'emp\xEAche de r\xE9cup\xE9rer son arme"; } else { - resultat = "succès, " + nomPerso(guerrier) + " désarme son adversaire."; + resultat = "succ\xE8s, " + nomPerso(guerrier) + " d\xE9sarme son adversaire."; } } addLineToFramedDisplay(display, resultat); @@ -36550,7 +36968,7 @@ var COFantasy = COFantasy || function() { function appliquerBloquer(attaquant, cible, critique, evt, envoyerMessage) { let msg; - if (envoyerMessage) msg = "est bloqué par son adversaire"; + if (envoyerMessage) msg = "est bloqu\xE9 par son adversaire"; setAttrDuree(cible, 'bloqueManoeuvre', 1, evt, msg); if (critique) appliquerTenirADistance(attaquant, cible, false, evt, envoyerMessage); @@ -36558,7 +36976,7 @@ var COFantasy = COFantasy || function() { function appliquerTenirADistance(attaquant, cible, critique, evt, envoyerMessage) { let msg; - if (envoyerMessage) msg = "est tenu à distance par son adversaire"; + if (envoyerMessage) msg = "est tenu \xE0 distance par son adversaire"; setAttrDuree( cible, 'tenuADistanceManoeuvre(' + attaquant.token.id + ')', 1, evt, msg); if (critique) appliquerBloquer(attaquant, cible, false, evt, envoyerMessage); @@ -36570,7 +36988,7 @@ var COFantasy = COFantasy || function() { let duree = 1; if (critique) duree = randomInteger(6); let msg; - if (envoyerMessage) msg = "est aveuglé par son adversaire"; + if (envoyerMessage) msg = "est aveugl\xE9 par son adversaire"; setAttrDuree( cible, 'aveugleManoeuvre', duree, evt, msg); return critique; //Pour les DMs en plus @@ -36594,19 +37012,19 @@ var COFantasy = COFantasy || function() { attrArmeCible.remove(); } if (envoyerMessage) { - let msgDesarme = "est désarmé" + onGenre(cible, '', 'e'); + let msgDesarme = "est d\xE9sarm\xE9" + onGenre(cible, '', 'e'); if (critique) msgDesarme += ", son adversaire lui a pris son arme."; else msgDesarme += "."; sendPerso(cible, msgDesarme); } }, - verbe: 'désarmer', + verbe: 'd\xE9sarmer', duelliste: true }, faireDiversion: { appliquer: function(attaquant, cible, critique, evt, envoyerMessage) { var msg; - if (envoyerMessage) msg = "a son attention attirée ailleurs"; + if (envoyerMessage) msg = "a son attention attir\xE9e ailleurs"; var malus = -5; if (critique) malus = -10; setAttrDuree(cible, 'diversionManoeuvre', 1, evt, msg); @@ -36642,7 +37060,7 @@ var COFantasy = COFantasy || function() { var distance = rollDePlus(6); if (critique && distance < 3) distance = 3; if (envoyerMessage) - sendPerso(cible, "est repoussé" + onGenre(cible, '', 'e') + " et doit reculer de " + distance.roll + "m."); + sendPerso(cible, "est repouss\xE9" + onGenre(cible, '', 'e') + " et doit reculer de " + distance.roll + "m."); if (critique) setState(cible, 'renverse', true, evt); }, penalitePlusPetit: true, @@ -36651,13 +37069,13 @@ var COFantasy = COFantasy || function() { }, tenirADistance: { appliquer: appliquerTenirADistance, - verbe: 'tenir à distance', + verbe: 'tenir \xE0 distance', duelliste: true } }; //!cof-appliquer-manoeuvre id1 id2 effet attrId - //attrId est utilisé pour limiter le nombre d'utilisations + //attrId est utilis\xE9 pour limiter le nombre d'utilisations function appliquerManoeuvre(msg) { var cmd = msg.content.split(' '); if (cmd.length < 5) { @@ -36670,7 +37088,7 @@ var COFantasy = COFantasy || function() { } var limiteAttr = getObj('attribute', cmd[4]); if (limiteAttr === undefined) { - sendPlayer(msg, "La manoeuvre a déjà été choisie"); + sendPlayer(msg, "La manoeuvre a d\xE9j\xE0 \xE9t\xE9 choisie"); return; } var attaquant = persoOfId(cmd[1], cmd[1]); @@ -36680,7 +37098,7 @@ var COFantasy = COFantasy || function() { } var cible = persoOfId(cmd[2], cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-appliquer-manoeuvre n'est pas un token valide", cmd); + error("Le deuxi\xE8me argument de !cof-appliquer-manoeuvre n'est pas un token valide", cmd); return; } var effet = listeManoeuvres[cmd[3]]; @@ -36715,7 +37133,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2], cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-manoeuvre n'est pas un token valide", cmd); + error("Le deuxi\xE8me argument de !cof-manoeuvre n'est pas un token valide", cmd); return; } const evt = { @@ -36738,7 +37156,7 @@ var COFantasy = COFantasy || function() { function(res, display, explications) { let dmSupp; if (res.succes) { - addLineToFramedDisplay(display, nomPerso(attaquant) + " réussit à " + effet.verbe + " " + nomPerso(cible)); + addLineToFramedDisplay(display, nomPerso(attaquant) + " r\xE9ussit \xE0 " + effet.verbe + " " + nomPerso(cible)); dmSupp = effet.appliquer(attaquant, cible, res.critique, evt); if (manoeuvreDuelliste && !dmSupp) { let pageId = cible.token.get('pageid'); @@ -36746,8 +37164,8 @@ var COFantasy = COFantasy || function() { dmSupp = res.rollAttaquant >= defense + 10; } } else { - addLineToFramedDisplay(display, nomPerso(attaquant) + " ne réussit pas à " + effet.verbe + " " + nomPerso(cible)); - //Envoyer à la cible la possibilité d'appliquer un effet de son choix + addLineToFramedDisplay(display, nomPerso(attaquant) + " ne r\xE9ussit pas \xE0 " + effet.verbe + " " + nomPerso(cible)); + //Envoyer \xE0 la cible la possibilit\xE9 d'appliquer un effet de son choix } explications.forEach(function(expl) { addLineToFramedDisplay(display, expl, 80); @@ -36755,7 +37173,7 @@ var COFantasy = COFantasy || function() { if (dmSupp) { let actionGratuite = "!cof-attack " + attaquant.token.id + " " + cible.token.id + " -1 --auto"; - addLineToFramedDisplay(display, nomPerso(attaquant) + " fait en plus des dégâts à " + nomPerso(cible) + boutonSimple(actionGratuite, "lancer une attaque pour déterminer le montant"), 80); + addLineToFramedDisplay(display, nomPerso(attaquant) + " fait en plus des d\xE9g\xE2ts \xE0 " + nomPerso(cible) + boutonSimple(actionGratuite, "lancer une attaque pour d\xE9terminer le montant"), 80); } sendFramedDisplay(display); addEvent(evt); @@ -36765,11 +37183,11 @@ var COFantasy = COFantasy || function() { if (!res.succes && !manoeuvreDuelliste) { let charCible = getObj('character', cible.charId); if (charCible === undefined) { - error("Cible sans personnage associé", cible); + error("Cible sans personnage associ\xE9", cible); return; } let titre = "Choisir un effet contre " + nomPerso(attaquant); - //On crée un display sans le header + //On cr\xE9e un display sans le header display = startFramedDisplay(undefined, titre, cible, { retarde: true }); @@ -36784,7 +37202,7 @@ var COFantasy = COFantasy || function() { let ligneManoeuvre = boutonSimple(appliquerManoeuvre, man); addLineToFramedDisplay(display, ligneManoeuvre, 90); } - // on envoie la liste aux joueurs qui gèrent le voleur + // on envoie la liste aux joueurs qui g\xE8rent le voleur let playerIds = getPlayerIds(cible); playerIds.forEach(function(playerid) { addFramedHeader(display, playerid, true); @@ -36806,7 +37224,7 @@ var COFantasy = COFantasy || function() { return; } if (cmd.length < 3) { - error("Il manque des arguments à !cof-expert-combat-bousculer", msg.content); + error("Il manque des arguments \xE0 !cof-expert-combat-bousculer", msg.content); return; } let expert = persoOfId(cmd[1], cmd[1]); @@ -36816,7 +37234,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2], cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-expert-combat-bousculer n'est pas un token valide", cmd); + error("Le deuxi\xE8me argument de !cof-expert-combat-bousculer n'est pas un token valide", cmd); return; } if (!predicateAsBool(expert, 'expertDuCombat')) { @@ -36842,14 +37260,14 @@ var COFantasy = COFantasy || function() { var display = startFramedDisplay(playerId, "Bousculer", expert, { perso2: cible }); - explications.push("Dé d'expertise : " + deExpertise.roll); + explications.push("D\xE9 d'expertise : " + deExpertise.roll); if (resultat === 1) { - addLineToFramedDisplay(display, nomPerso(cible) + " est repoussé de " + - Math.ceil(deExpertise.val / 2) + " mètre" + (deExpertise.val > 1 ? "s" : "") + "
S'il est acculé : " + + addLineToFramedDisplay(display, nomPerso(cible) + " est repouss\xE9 de " + + Math.ceil(deExpertise.val / 2) + " m\xE8tre" + (deExpertise.val > 1 ? "s" : "") + "
S'il est accul\xE9 : " + boutonSimple("!cof-dmg " + deExpertise.val + " --target " + cmd[2], "Appliquer " + deExpertise.val + " DM")); setState(cible, "renverse", "true", evt); } else { - addLineToFramedDisplay(display, nomPerso(cible) + " n'est pas renversé"); + addLineToFramedDisplay(display, nomPerso(cible) + " n'est pas renvers\xE9"); } explications.forEach(function(expl) { addLineToFramedDisplay(display, expl, 80); @@ -36960,7 +37378,7 @@ var COFantasy = COFantasy || function() { dm: 3, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }], abilities: [{ @@ -37011,7 +37429,7 @@ var COFantasy = COFantasy || function() { dm: 5, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }], abilities: [{ @@ -37062,7 +37480,7 @@ var COFantasy = COFantasy || function() { dm: 5, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }, { name: 'predicats_script', @@ -37076,7 +37494,7 @@ var COFantasy = COFantasy || function() { titre: 'Attaque en embuscade', code: '!cof-attack @{selected|token_id} @{target|token_id} 1 --sournoise 1 --if moins FOR --etat renverse --endif' }, { - titre: 'Dévorer', + titre: 'D\xE9vorer', code: '!cof-attack @{selected|token_id} @{target|token_id} 1' }] }, @@ -37118,7 +37536,7 @@ var COFantasy = COFantasy || function() { dm: 7, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }, { name: 'predicats_script', @@ -37132,7 +37550,7 @@ var COFantasy = COFantasy || function() { titre: 'Attaque en embuscade', code: '!cof-attack @{selected|token_id} @{target|token_id} 1 --sournoise 1 --if moins FOR --etat renverse --endif' }, { - titre: 'Dévorer', + titre: 'D\xE9vorer', code: '!cof-attack @{selected|token_id} @{target|token_id} 1' }] }, @@ -37183,7 +37601,7 @@ var COFantasy = COFantasy || function() { }, ] }, tigreDentsDeSabre: { - nom: 'Tigre à dents de sabre', + nom: 'Tigre \xE0 dents de sabre', avatar: "https://s3.amazonaws.com/files.d20.io/images/59486272/f5lUcN3Y9H0thmJPrqa6FQ/max.png?1533041702", token: "https://s3.amazonaws.com/files.d20.io/images/60186469/ShcrgpvgXKiQsLVOyg4SZQ/thumb.png?1533903741", attributesFiche: { @@ -37222,7 +37640,7 @@ var COFantasy = COFantasy || function() { dm: 12, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }, { name: 'predicats_script', @@ -37236,12 +37654,12 @@ var COFantasy = COFantasy || function() { titre: 'Attaque en embuscade', code: '!cof-attack @{selected|token_id} @{target|token_id} 1 --sournoise 1 --if moins FOR --etat renverse --endif' }, { - titre: 'Dévorer', + titre: 'D\xE9vorer', ccode: '!cof-attack @{selected|token_id} @{target|token_id} 1' }] }, oursPrehistorique: { - nom: 'Ours préhistorique', + nom: 'Ours pr\xE9historique', avatar: "https://s3.amazonaws.com/files.d20.io/images/59486323/V6RVSlBbeRJi_aIaIuGGBw/max.png?1533041814", token: "https://s3.amazonaws.com/files.d20.io/images/60186633/lNHXvCOsvfPMZDQnqJKQVw/thumb.png?1533904189", attributesFiche: { @@ -37266,7 +37684,7 @@ var COFantasy = COFantasy || function() { pnj_init: 10, RDS: 2, race: 'ours', - taille: 'énorme' + taille: '\xE9norme' }, pv: 110, attaques: [{ @@ -37305,11 +37723,11 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - error("pas de lanceur pour la conjuration de prédateurs", msg); + error("pas de lanceur pour la conjuration de pr\xE9dateurs", msg); return; } let evt = { - type: 'conjuration de prédateurs' + type: 'conjuration de pr\xE9dateurs' }; let combat = initiative(selected, evt); let abort; @@ -37317,12 +37735,12 @@ var COFantasy = COFantasy || function() { if (abort) return; if (options.tempeteDeMana) { if (selected.length > 1) { - sendPlayerAndGM(msg, playerId, "Il faut sélectionner un seul token pour les options de tempête de mana"); + sendPlayerAndGM(msg, playerId, "Il faut s\xE9lectionner un seul token pour les options de temp\xEAte de mana"); abort = true; return; } if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, portee: false, @@ -37336,11 +37754,11 @@ var COFantasy = COFantasy || function() { return; } else { if (options.tempeteDeMana.cout > 1) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } - if (limiteRessources(invocateur, options, 'invocationPredateur', 'lancer une invocation de prédateur', evt)) return; + if (limiteRessources(invocateur, options, 'invocationPredateur', 'lancer une invocation de pr\xE9dateur', evt)) return; let pageId = invocateur.token.get('pageid'); let niveau = ficheAttributeAsInt(invocateur, 'niveau', 1); if (!renforce) { @@ -37392,13 +37810,13 @@ var COFantasy = COFantasy || function() { toFront(token); let charPredateur = createCharacter(nomPredateur, playerId, predateur.avatar, token, predateur, evt); - //Tous les prédateurs sont des quadrupèdes + //Tous les pr\xE9dateurs sont des quadrup\xE8des let persoPredateur = { token: token, charId: charPredateur.id }; setPredicate(persoPredateur, 'quadrupede', evt); - //Attribut de predateur conjuré pour la disparition automatique + //Attribut de predateur conjur\xE9 pour la disparition automatique let attr = createObj('attribute', { name: 'predateurConjure', _characterid: charPredateur.id, @@ -37420,7 +37838,7 @@ var COFantasy = COFantasy || function() { initiative([{ _id: token.id }], evt); - // Ajout du Prédateur aux alliés de l'invocateur + // Ajout du Pr\xE9dateur aux alli\xE9s de l'invocateur let alliesInvocateur = alliesParPerso[invocateur.charId] || new Set(); alliesInvocateur.add(charPredateur.id); alliesParPerso[invocateur.charId] = alliesInvocateur; @@ -37444,11 +37862,11 @@ var COFantasy = COFantasy || function() { return; } let evt = { - type: "invocation d'une sphère de feu", + type: "invocation d'une sph\xE8re de feu", }; let combat = initiative(selected, evt); iterSelected(selected, function(invocateur) { - if (limiteRessources(invocateur, options, 'sphereDeFeu', 'lancer un sort de sphère de feu', evt)) return; + if (limiteRessources(invocateur, options, 'sphereDeFeu', 'lancer un sort de sph\xE8re de feu', evt)) return; let character = getObj('character', invocateur.charId); if (character === undefined) { error("Impossible de trouver le personnage de " + nomPerso(invocateur), invocateur); @@ -37457,7 +37875,7 @@ var COFantasy = COFantasy || function() { let pageId = invocateur.token.get('pageid'); let niveau = ficheAttributeAsInt(invocateur, 'niveau', 1); let sphere = { - nom: 'Sphère de feu', + nom: 'Sph\xE8re de feu', avatar: "https://s3.amazonaws.com/files.d20.io/images/260057530/nL8O6US3f1BpeTJkodWNCg/max.png?16394116785", token: "https://s3.amazonaws.com/files.d20.io/images/260057530/nL8O6US3f1BpeTJkodWNCg/thumb.png?16394116785", attributesFiche: { @@ -37466,7 +37884,7 @@ var COFantasy = COFantasy || function() { }, pv: 1, attaques: [{ - nom: 'Brûlure', + nom: 'Br\xFBlure', atk: 0, dmnbde: 3, dmde: 6, @@ -37479,7 +37897,7 @@ var COFantasy = COFantasy || function() { name: 'predicats_script', current: 'nonVivant immunite_feu sansEsprit initiativeDeriveeDe::' + character.get('name') + '\n', }, { - name: 'predateurConjure', //Pas exactement ça, mais ça fait ce qu'il faut + name: 'predateurConjure', //Pas exactement \xE7a, mais \xE7a fait ce qu'il faut current: niveau, max: combat.init, lie: options.mana !== undefined @@ -37504,7 +37922,7 @@ var COFantasy = COFantasy || function() { has_limit_field_of_vision: true, }); if (token === undefined) { - error("Impossible de créer le token de la sphère de feu ", sphere); + error("Impossible de cr\xE9er le token de la sph\xE8re de feu ", sphere); return; } toFront(token); @@ -37515,7 +37933,7 @@ var COFantasy = COFantasy || function() { initiative([{ _id: token.id }], evt); - // Ajout du Prédateur aux alliés de l'invocateur + // Ajout du Pr\xE9dateur aux alli\xE9s de l'invocateur let alliesInvocateur = alliesParPerso[invocateur.charId] || new Set(); alliesInvocateur.add(charSphere.id); alliesParPerso[invocateur.charId] = alliesInvocateur; @@ -37524,18 +37942,18 @@ var COFantasy = COFantasy || function() { }); //end getSelected } - //!cof-conjuration-armee [dé de DM] --limiteParJour... + //!cof-conjuration-armee [d\xE9 de DM] --limiteParJour... function conjurationArmee(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Il faut sélectionner le lanceur de la conjuration d'arméé", playerId); + sendPlayer(msg, "Il faut s\xE9lectionner le lanceur de la conjuration d'arm\xE9\xE9", playerId); return; } let abort; @@ -37543,12 +37961,12 @@ var COFantasy = COFantasy || function() { if (abort) return; if (options.tempeteDeMana) { if (selected.length > 1) { - sendPlayerAndGM(msg, playerId, "Il faut sélectionner un seul token pour les options de tempête de mana"); + sendPlayerAndGM(msg, playerId, "Il faut s\xE9lectionner un seul token pour les options de temp\xEAte de mana"); abort = true; return; } if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, portee: false, @@ -37562,16 +37980,16 @@ var COFantasy = COFantasy || function() { return; } else { if (options.tempeteDeMana.cout > 1) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } let pageId = invocateur.token.get('pageid'); let niveau = ficheAttributeAsInt(invocateur, 'niveau', 1); const evt = { - type: "Conjuration d'armée" + type: "Conjuration d'arm\xE9e" }; - if (limiteRessources(invocateur, options, 'conjurationArmee', "conjurer une armée", evt)) { + if (limiteRessources(invocateur, options, 'conjurationArmee', "conjurer une arm\xE9e", evt)) { addEvent(evt); return; } @@ -37592,7 +38010,7 @@ var COFantasy = COFantasy || function() { dm.nbDe = 2; } } - let nomArmee = "Armée de " + nomPerso(invocateur); + let nomArmee = "Arm\xE9e de " + nomPerso(invocateur); let token = createObj('graphic', { name: nomArmee, subtype: 'token', @@ -37652,13 +38070,13 @@ var COFantasy = COFantasy || function() { } //!cof-tenebres token-lanceur token-cible - // possibilité de --brumes pour un effet de brumes + // possibilit\xE9 de --brumes pour un effet de brumes function tenebres(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("!cof-tenebres mal formé, il faut un token comme premier argument", msg.content); + error("!cof-tenebres mal form\xE9, il faut un token comme premier argument", msg.content); return; } let necromant = persoOfId(cmd[1], cmd[1], options.pageId); @@ -37675,7 +38093,7 @@ var COFantasy = COFantasy || function() { const playerId = getPlayerIdFromMsg(msg); if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, portee: true, @@ -37687,7 +38105,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.tempeteDeMana.cout > 1) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -37703,7 +38121,7 @@ var COFantasy = COFantasy || function() { if (distanceCombat(necromant.token, target.token, options.pageId, { strict2: true }) > portee) { - sendPlayer(msg, "Le point visé est trop loin (portée " + portee + ")", playerId); + sendPlayer(msg, "Le point vis\xE9 est trop loin (port\xE9e " + portee + ")", playerId); return; } let duree = 5; @@ -37719,7 +38137,7 @@ var COFantasy = COFantasy || function() { if (options.brumes) { if (limiteRessources(necromant, options, 'brumes', 'lancer un sort de brumes', evt)) return; } else { - if (limiteRessources(necromant, options, 'tenebres', 'lancer un sort de ténèbres', evt)) return; + if (limiteRessources(necromant, options, 'tenebres', 'lancer un sort de t\xE9n\xE8bres', evt)) return; } if (!stateCOF.combat) { initPerso(necromant, evt); @@ -37739,7 +38157,7 @@ var COFantasy = COFantasy || function() { tokSpec.height = rayonUnite * PIX_PER_UNIT; tokSpec.layer = 'map'; } else { - tokSpec.name = "Ténèbres de " + nomPerso(necromant); + tokSpec.name = "T\xE9n\xE8bres de " + nomPerso(necromant); tokSpec.imgsrc = 'https://s3.amazonaws.com/files.d20.io/images/192072874/eJXFx20fD931DuBDvzAnQQ/thumb.png?1610469273'; tokSpec.width = 70; tokSpec.height = 70; @@ -37759,9 +38177,9 @@ var COFantasy = COFantasy || function() { if (options.brumes) sendPerso(necromant, "lance un sort de brumes pour " + duree + " tours"); else - sendPerso(necromant, "lance un sort de ténèbres pour " + duree + " tours"); + sendPerso(necromant, "lance un sort de t\xE9n\xE8bres pour " + duree + " tours"); } - // Calcul des cibles à aveugler + // Calcul des cibles \xE0 aveugler let cibles = []; let allToksDisque = findObjs({ @@ -37811,8 +38229,8 @@ var COFantasy = COFantasy || function() { if (options.brumes) effetTenebres.effet = 'brumes'; setEffetTemporaire(necromant, effetTenebres, duree, evt, options); if (target.token.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir le disque - target.token.remove(); //On l'enlève, normalement plus besoin + //C'est juste un token utilis\xE9 pour d\xE9finir le disque + target.token.remove(); //On l'enl\xE8ve, normalement plus besoin } if (options.messages) { options.messages.forEach(function(m) { @@ -37822,7 +38240,7 @@ var COFantasy = COFantasy || function() { } const demonInvoque = { - nom: 'Démon', + nom: 'D\xE9mon', avatar: "https://s3.amazonaws.com/files.d20.io/images/183633585/DWpHYp4SLPCDCMHdmTyKOw/thumb.png?1607339938", token: "https://s3.amazonaws.com/files.d20.io/images/183633585/DWpHYp4SLPCDCMHdmTyKOw/thumb.png?1607339938", attributesFiche: { @@ -37847,7 +38265,7 @@ var COFantasy = COFantasy || function() { DEFDIV: 3, pnj_def: 17, pnj_init: 16, - race: 'démon', + race: 'd\xE9mon', taille: 'moyen' }, attaques: [{ @@ -37859,7 +38277,7 @@ var COFantasy = COFantasy || function() { }], attributes: [{ name: 'predicats_script', - current: 'démon' + current: 'd\xE9mon' }], abilities: [] }; @@ -37869,7 +38287,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("!cof-invoquer-demon mal formé, il faut un token comme premier argument", msg.content); + error("!cof-invoquer-demon mal form\xE9, il faut un token comme premier argument", msg.content); return; } let necromant = persoOfId(cmd[1], cmd[1], options.pageId); @@ -37886,7 +38304,7 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - if (limiteRessources(necromant, options, 'invoquerDemon', 'lance une invocation de démon', evt)) return; + if (limiteRessources(necromant, options, 'invoquerDemon', 'lance une invocation de d\xE9mon', evt)) return; let d6 = rollDePlus(6); evt.action.rolls.invocationDemonDmg = d6; let r = { @@ -37901,7 +38319,7 @@ var COFantasy = COFantasy || function() { if (!stateCOF.combat) { initPerso(necromant, evt); } - let tokenDemon = "Démon de " + nomPerso(necromant); + let tokenDemon = "D\xE9mon de " + nomPerso(necromant); let token = createObj('graphic', { name: tokenDemon, showname: 'true', @@ -37929,7 +38347,7 @@ var COFantasy = COFantasy || function() { evt.characters = [charDemon]; evt.tokens = [token]; let duree = 5 + modCarac(necromant, 'intelligence'); - //Attribut de démon invoqué pour la disparition automatique + //Attribut de d\xE9mon invoqu\xE9 pour la disparition automatique createObj('attribute', { name: 'demonInvoque', _characterid: charDemon.id, @@ -37944,13 +38362,13 @@ var COFantasy = COFantasy || function() { initiative([{ _id: token.id }], evt); - // Ajout du Démon aux alliés du Nécromant + // Ajout du D\xE9mon aux alli\xE9s du N\xE9cromant var alliesNecromant = alliesParPerso[necromant.charId] || new Set(); alliesNecromant.add(charDemon.id); alliesParPerso[necromant.charId] = alliesNecromant; - var msg = "invoque un démon"; + var msg = "invoque un d\xE9mon"; if (stateCOF.options.affichage.val.duree_effets.val) msg += " pour " + duree + " tours"; - msg += " mais cela lui coûte " + dmgDisplay + " PV"; + msg += " mais cela lui co\xFBte " + dmgDisplay + " PV"; sendPerso(necromant, msg); }); }, options); @@ -37997,7 +38415,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("!cof-animer-mort mal formé, il faut un token comme premier argument", msg.content); + error("!cof-animer-mort mal form\xE9, il faut un token comme premier argument", msg.content); return; } const necromant = persoOfId(cmd[1], cmd[1], options.pageId); @@ -38008,7 +38426,7 @@ var COFantasy = COFantasy || function() { let zombiesControles = attributeAsInt(necromant, 'zombiesControles', 0); let rangVoie = predicateAsInt(necromant, 'voieOutreTombe', 1); if (zombiesControles >= rangVoie) { - sendPerso(necromant, "ne peut plus animer de Zombie car il en contrôle déjà assez."); + sendPerso(necromant, "ne peut plus animer de Zombie car il en contr\xF4le d\xE9j\xE0 assez."); return; } options.lanceur = necromant; @@ -38052,7 +38470,7 @@ var COFantasy = COFantasy || function() { let charZombie = createCharacter(nomToken, playerId, zombieAnime.avatar, token, zombie, evt); evt.characters.push(charZombie); evt.tokens.push(token); - // Dégradation du Zombie + // D\xE9gradation du Zombie createObj('attribute', { name: 'degradationZombie', _characterid: charZombie.id, @@ -38068,7 +38486,7 @@ var COFantasy = COFantasy || function() { initiative([{ _id: token.id }], evt); - // Ajout du Zombie aux alliés du Nécromant + // Ajout du Zombie aux alli\xE9s du N\xE9cromant let alliesNecromant = alliesParPerso[necromant.charId] || new Set(); alliesNecromant.add(charZombie.id); alliesParPerso[necromant.charId] = alliesNecromant; @@ -38086,7 +38504,7 @@ var COFantasy = COFantasy || function() { const MONTER = String.fromCharCode(0x2197); const DESCENDRE = String.fromCharCode(0x2198); - //Crée les macros utiles au jeu + //Cr\xE9e les macros utiles au jeu const gameMacros = [{ name: 'Actions', action: "!cof-liste-actions", @@ -38164,7 +38582,7 @@ var COFantasy = COFantasy || function() { istokenaction: true }, { name: 'Surprise', - action: "!cof-surprise ?{difficulté}", + action: "!cof-surprise ?{difficult\xE9}", visibleto: '', istokenaction: false, inBar: true @@ -38174,20 +38592,20 @@ var COFantasy = COFantasy || function() { visibleto: 'all', istokenaction: true, }, { - name: 'Éteindre', - action: "!cof-eteindre-lumiere ?{Quelle lumière?|Tout}", + name: '\xC9teindre', + action: "!cof-eteindre-lumiere ?{Quelle lumi\xE8re?|Tout}", visibleto: '', istokenaction: false, inBar: true }, { name: 'devient', - action: "!cof-set-state ?{État|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blesse|encombre} true", + action: "!cof-set-state ?{\xC9tat|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blesse|encombre} true", visibleto: '', istokenaction: false, inBar: true }, { - name: 'enlève', - action: "!cof-set-state ?{État|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blesse|encombre} false", + name: 'enl\xE8ve', + action: "!cof-set-state ?{\xC9tat|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blesse|encombre} false", visibleto: '', istokenaction: false, inBar: true @@ -38225,20 +38643,20 @@ var COFantasy = COFantasy || function() { if (prev === undefined) { m.playerid = playerId; createObj('macro', m); - sendPlayer(msg, "Macro " + m.name + " créée."); + sendPlayer(msg, "Macro " + m.name + " cr\xE9\xE9e."); if (m.inBar) inBar.push(m.name); } else if (force) { prev.set('action', m.action); prev.set('visibleto', m.visibleto); prev.set('istokenaction', m.istokenaction); - sendPlayer(msg, "Macro " + m.name + " réécrite."); + sendPlayer(msg, "Macro " + m.name + " r\xE9\xE9crite."); if (m.inBar) inBar.push(m.name); } else { - sendPlayer(msg, "Macro " + m.name + " déjà présente (utiliser --force pour réécrire)."); + sendPlayer(msg, "Macro " + m.name + " d\xE9j\xE0 pr\xE9sente (utiliser --force pour r\xE9\xE9crire)."); } }); if (inBar.length > 0) { - sendPlayer(msg, "Macros à mettre dans la barre d'action du MJ : " + inBar.join(', ')); + sendPlayer(msg, "Macros \xE0 mettre dans la barre d'action du MJ : " + inBar.join(', ')); } stateCOF.gameMacros = gameMacros; } @@ -38248,24 +38666,24 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd === undefined || cmd.length < 3) { - error("Il faut au moins 2 arguments à !cof-lumiere", cmd); + error("Il faut au moins 2 arguments \xE0 !cof-lumiere", cmd); return; } const cible = persoOfId(cmd[1]); if (cible === undefined) { - error("le premier argument de !cof-lumière doit être un token", cmd); + error("le premier argument de !cof-lumi\xE8re doit \xEAtre un token", cmd); return; } const radius = parseInt(cmd[2]); if (isNaN(radius) || radius <= 0) { - error("La distance de vue de la lumière doit être positive", cmd[2]); + error("La distance de vue de la lumi\xE8re doit \xEAtre positive", cmd[2]); return; } let dimRadius = ''; if (cmd.length > 3) { dimRadius = parseInt(cmd[3]); if (isNaN(dimRadius)) { - error("La distance de vue de la lumière assombrie doit être un nombre", cmd[3]); + error("La distance de vue de la lumi\xE8re assombrie doit \xEAtre un nombre", cmd[3]); dimRadius = ''; } } @@ -38278,7 +38696,7 @@ var COFantasy = COFantasy || function() { type: 'lumiere', }; addEvent(evt); - if (limiteRessources(options.lanceur, options, 'lumière', "lumière", evt)) return; + if (limiteRessources(options.lanceur, options, 'lumi\xE8re', "lumi\xE8re", evt)) return; ajouteUneLumiere(cible, nomToken, radius, dimRadius, evt); } @@ -38292,7 +38710,7 @@ var COFantasy = COFantasy || function() { } let lumId = al.get('max'); if (lumId == 'surToken') { - //Il faut enlever la lumière sur tous les tokens + //Il faut enlever la lumi\xE8re sur tous les tokens let allTokens = [perso.token]; if (perso.token.get('bar1_value') !== '') { allTokens = findObjs({ @@ -38320,7 +38738,7 @@ var COFantasy = COFantasy || function() { name: lumName }); if (tokensLumiere.length === 0) { - log("Pas de token pour la lumière " + lumName); + log("Pas de token pour la lumi\xE8re " + lumName); al.remove(); return; } @@ -38352,7 +38770,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionnée pour !cof-eteindre-lumiere", playerId); + sendPlayer(msg, "Pas de cible s\xE9lectionn\xE9e pour !cof-eteindre-lumiere", playerId); return; } const cmd = options.cmd; @@ -38361,7 +38779,7 @@ var COFantasy = COFantasy || function() { if (groupe && groupe.toLowerCase() == 'tout') groupe = ''; let pageId = options.pageId; const evt = { - type: "Eteindre la lumière" + type: "Eteindre la lumi\xE8re" }; iterSelected(selected, function(perso) { pageId = pageId || perso.token.get('pageid'); @@ -38380,7 +38798,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd.length < 2) { - error("Il faut préciser le token en argument de !cof-torche"); + error("Il faut pr\xE9ciser le token en argument de !cof-torche"); return; } let pageId = options.pageId; @@ -38392,15 +38810,15 @@ var COFantasy = COFantasy || function() { pageId = pageId || perso.token.get('pageid'); var diminueDuree = 0; if (cmd.length > 2) { - //Dans ce cas, c'est pour diminuer la durée de vie de la torche + //Dans ce cas, c'est pour diminuer la dur\xE9e de vie de la torche diminueDuree = parseInt(cmd[2]); if (isNaN(diminueDuree) || diminueDuree <= 0) { - sendPlayer(msg, "Le deuxième argument de !cof-torche doit être un nombre strictement positif " + msg.content); + sendPlayer(msg, "Le deuxi\xE8me argument de !cof-torche doit \xEAtre un nombre strictement positif " + msg.content); return; } } var evt; - //On commence par chercher si une torche est allumée + //On commence par chercher si une torche est allum\xE9e var torcheAllumee = false; var attrLumiere = tokenAttribute(perso, 'lumiere').filter(function(a) { return a.get('current').startsWith('torche'); @@ -38408,7 +38826,7 @@ var COFantasy = COFantasy || function() { if (!diminueDuree && attrLumiere.length > 0) { torcheAllumee = true; evt = { - type: "Éteindre les torches" + type: "\xC9teindre les torches" }; attrLumiere.forEach(function(al) { let lumName = al.get('current'); @@ -38436,8 +38854,8 @@ var COFantasy = COFantasy || function() { return; } if (tempsTorche === 0) { - if (nbTorches === 0) { //Donc forcément torcheAllumee - //On remet l'attribut dans un état convenable + if (nbTorches === 0) { //Donc forc\xE9ment torcheAllumee + //On remet l'attribut dans un \xE9tat convenable setTokenAttr(perso, 'torches', 0, evt, { maxVal: 60 }); @@ -38457,7 +38875,7 @@ var COFantasy = COFantasy || function() { nbTorches--; temps += tempsTorche; tempsTorche = 60; - var msgDiminue = "torche épuisée."; + var msgDiminue = "torche \xE9puis\xE9e."; if (nbTorches === 0) { msgDiminue += " Plus de torche !"; } else if (nbTorches == 1) { @@ -38470,23 +38888,23 @@ var COFantasy = COFantasy || function() { setTokenAttr(perso, 'torches', nbTorches, evt, { maxVal: tempsTorche }); - sendChar(perso.charId, '/w gm temps de torche diminué de ' + temps + ' minutes'); + sendChar(perso.charId, '/w gm temps de torche diminu\xE9 de ' + temps + ' minutes'); addEvent(evt); return; } if (torcheAllumee) { - var msgTorche = "/w gm torche éteinte. "; + var msgTorche = "/w gm torche \xE9teinte. "; if (nbTorches > 1) { msgTorche += "Reste " + (nbTorches - 1) + " torche"; if (nbTorches > 2) msgTorche += "s neuves"; else msgTorche += " neuve"; - msgTorche += ", et une torche pouvant encore éclairer " + tempsTorche + " minutes."; + msgTorche += ", et une torche pouvant encore \xE9clairer " + tempsTorche + " minutes."; } else { - msgTorche += "Elle peut encore éclairer " + tempsTorche + " minutes."; + msgTorche += "Elle peut encore \xE9clairer " + tempsTorche + " minutes."; } sendChar(perso.charId, msgTorche + - boutonSimple("!cof-torche " + perso.token.id + " ?{Durée?}", "Temps depuis allumage")); + boutonSimple("!cof-torche " + perso.token.id + " ?{Dur\xE9e?}", "Temps depuis allumage")); addEvent(evt); return; } @@ -38495,7 +38913,7 @@ var COFantasy = COFantasy || function() { }; ajouteUneLumiere(perso, 'torche', 13, 7, evt); var msgAllume = - "allume une torche, qui peut encore éclairer pendant " + tempsTorche + + "allume une torche, qui peut encore \xE9clairer pendant " + tempsTorche + " minute"; if (tempsTorche > 1) msgAllume += 's'; msgAllume += '.'; @@ -38508,9 +38926,9 @@ var COFantasy = COFantasy || function() { addEvent(evt); return; } - //On ne tient pas le compte précis des torches + //On ne tient pas le compte pr\xE9cis des torches if (torcheAllumee) { - whisperChar(perso.charId, "éteint sa torche"); + whisperChar(perso.charId, "\xE9teint sa torche"); } else { evt = { type: "Allumer une torche" @@ -38522,9 +38940,9 @@ var COFantasy = COFantasy || function() { } //!cof-options - //!cof-options opt1 [... optn] val, met l'option à val - //!cof-options [opt0 ... optk] reset remet toutes les options à leur valeur patr défaut - //Dans tous les cas, affiche les options du niveau demandé + //!cof-options opt1 [... optn] val, met l'option \xE0 val + //!cof-options [opt0 ... optk] reset remet toutes les options \xE0 leur valeur patr d\xE9faut + //Dans tous les cas, affiche les options du niveau demand\xE9 function setCofOptions(msg) { const playerId = getPlayerIdFromMsg(msg); if (!playerIsGM(playerId)) { @@ -38547,7 +38965,7 @@ var COFantasy = COFantasy || function() { cmd.shift(); cmd.forEach(function(c) { if (fini) { - sendPlayer(msg, "Option " + c + " ignorée", playerId); + sendPlayer(msg, "Option " + c + " ignor\xE9e", playerId); return; } if (c == 'reset') { @@ -38557,7 +38975,7 @@ var COFantasy = COFantasy || function() { } else if (cofOptions[c]) { if (cofOptions[c].type == 'options') { if (defOpt[c] === undefined) { - sendPlayer(msg, "Option " + c + " inconnue dans les options par défaut", playerId); + sendPlayer(msg, "Option " + c + " inconnue dans les options par d\xE9faut", playerId); fini = true; return; } @@ -38569,7 +38987,7 @@ var COFantasy = COFantasy || function() { newOption = cofOptions[c]; } } else { - if (newOption) { //on met newOption à c + if (newOption) { //on met newOption \xE0 c let val = c; switch (newOption.type) { case 'bool': @@ -38585,7 +39003,7 @@ var COFantasy = COFantasy || function() { val = false; break; default: - sendPlayer(msg, "L'option " + lastCmd + " ne peut être que true ou false", playerId); + sendPlayer(msg, "L'option " + lastCmd + " ne peut \xEAtre que true ou false", playerId); val = newOption.val; } fini = true; @@ -38593,7 +39011,7 @@ var COFantasy = COFantasy || function() { case 'int': val = parseInt(c); if (isNaN(val)) { - sendPlayer(msg, "L'option " + lastCmd + " est une valeur entière", playerId); + sendPlayer(msg, "L'option " + lastCmd + " est une valeur enti\xE8re", playerId); val = newOption.val; } fini = true; @@ -38634,7 +39052,7 @@ var COFantasy = COFantasy || function() { case 'bool': action += ' ?{Nouvelle valeur de ' + optVu + '|actif,true|inactif,false}'; if (displayedVal) - // Bizarrement, le caractère '*' modifie la suite du tableau + // Bizarrement, le caract\xE8re '*' modifie la suite du tableau displayedVal = '3'; else displayedVal = '*'; @@ -38664,7 +39082,7 @@ var COFantasy = COFantasy || function() { line += boutonSimple(action, displayedVal) + after; addLineToFramedDisplay(display, line); } - addLineToFramedDisplay(display, boutonSimple('!cof-options' + prefix + ' reset', 'Valeurs par défaut'), 70); + addLineToFramedDisplay(display, boutonSimple('!cof-options' + prefix + ' reset', 'Valeurs par d\xE9faut'), 70); sendFramedDisplay(display); } @@ -38680,20 +39098,20 @@ var COFantasy = COFantasy || function() { let pageId = options.pageId; let samourai = persoOfId(cmd[1], cmd[1], pageId); if (samourai === undefined) { - error("Le token sélectionné n'est pas valide", msg.content); + error("Le token s\xE9lectionn\xE9 n'est pas valide", msg.content); return; } if (attributeAsBool(samourai, 'defiSamourai')) { - sendPlayer(msg, nomPerso(samourai) + " a déjà lancé un défi durant ce combat."); + sendPlayer(msg, nomPerso(samourai) + " a d\xE9j\xE0 lanc\xE9 un d\xE9fi durant ce combat."); return; } let cible = persoOfId(cmd[2], cmd[2], pageId); if (cible === undefined) { - error("Le deuxième token sélectionné n'est pas valide", msg.content); + error("Le deuxi\xE8me token s\xE9lectionn\xE9 n'est pas valide", msg.content); return; } const evt = { - type: 'Défi samouraï' + type: 'D\xE9fi samoura\xEF' }; let explications = []; entrerEnCombat(samourai, [cible], explications, evt); @@ -38704,14 +39122,14 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3) { bonus = parseInt(cmd[3]); if (isNaN(bonus) || bonus < 1) { - error("Bonus de défi de samouraï incorrect", cmd[3]); + error("Bonus de d\xE9fi de samoura\xEF incorrect", cmd[3]); bonus = undefined; } } if (bonus === undefined) bonus = predicateAsInt(samourai, 'voieDeLHonneur', 2); setTokenAttr(samourai, 'defiSamourai', bonus, evt, { - msg: nomPerso(samourai) + " lance un défi à " + nomPerso(cible), + msg: nomPerso(samourai) + " lance un d\xE9fi \xE0 " + nomPerso(cible), maxVal: idName(cible) }); } @@ -38721,16 +39139,16 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 6) { - error("Il manque des arguments à !cof-enveloppement", cmd); + error("Il manque des arguments \xE0 !cof-enveloppement", cmd); return; } let cube = persoOfId(cmd[1]); if (cube === undefined) { - error("Token non défini", cmd[1]); + error("Token non d\xE9fini", cmd[1]); return; } if (!peutController(msg, cube)) { @@ -38739,12 +39157,12 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2]); if (cible === undefined) { - error("Token non défini", cmd[2]); + error("Token non d\xE9fini", cmd[2]); return; } let difficulte = parseInt(cmd[3]); if (isNaN(difficulte)) { - error("Difficulté n'est pas un nombre, on prend 15 par défaut", cmd[3]); + error("Difficult\xE9 n'est pas un nombre, on prend 15 par d\xE9faut", cmd[3]); difficulte = 15; } let exprDM; @@ -38756,18 +39174,18 @@ var COFantasy = COFantasy || function() { exprDM = cmd[4] + ' ' + cmd[5]; break; case 'etreinte': - type = 'étreinte'; + type = '\xE9treinte'; exprDM = cmd[4] + ' ' + cmd[5]; break; default: - error("Impossible de déterminer les dégâts quand enveloppé", cmd[4]); + error("Impossible de d\xE9terminer les d\xE9g\xE2ts quand envelopp\xE9", cmd[4]); return; } doEnveloppement(cube, cible, difficulte, type, exprDM, options); } //!cof-enveloppement cubeId targetId Difficulte Attaque - //Attaque peut être soit label l, soit ability a, soit etreinte expr + //Attaque peut \xEAtre soit label l, soit ability a, soit etreinte expr function doEnveloppement(attaquant, cible, difficulte, type, exprDM, options) { const evt = { type: type, @@ -38782,9 +39200,9 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - //Choix de la caractéristique pour résister : FOR ou DEX + //Choix de la caract\xE9ristique pour r\xE9sister : FOR ou DEX let caracRes = meilleureCarac('FOR', 'DEX', cible, 10 + modCarac(attaquant, 'force')); - let titre = (type == 'étreinte') ? 'Étreinte' : 'Enveloppement'; + let titre = (type == '\xE9treinte') ? '\xC9treinte' : 'Enveloppement'; let display = startFramedDisplay(options.playerId, titre, attaquant, { perso2: cible }); @@ -38793,14 +39211,14 @@ var COFantasy = COFantasy || function() { testOppose(rollId, attaquant, 'FOR', options, cible, caracRes, options, explications, evt, function(res, crit, rt1, rt2) { - let act = " a absorbé "; + let act = " a absorb\xE9 "; switch (res) { case 1: - if (type == 'étreinte') act = " s'est enroulé autour de "; + if (type == '\xE9treinte') act = " s'est enroul\xE9 autour de "; explications.push(nomPerso(attaquant) + act + nomPerso(cible)); let attaquantId = idName(attaquant); let maxval = difficulte; - if (type == 'étreinte') maxval = 'etreinte ' + difficulte; + if (type == '\xE9treinte') maxval = 'etreinte ' + difficulte; setTokenAttr(cible, 'enveloppePar', attaquantId, evt, { maxVal: maxval }); @@ -38810,23 +39228,23 @@ var COFantasy = COFantasy || function() { setTokenAttr(attaquant, 'enveloppe', cibleId, evt, { maxVal: exprDM }); - if (type == 'étreinte') setState(cible, 'immobilise', true, evt); + if (type == '\xE9treinte') setState(cible, 'immobilise', true, evt); break; case 2: if (caracRes == 'FOR') { - if (type == 'étreinte') act = 'étreindre'; + if (type == '\xE9treinte') act = '\xE9treindre'; else act = 'absorber'; - explications.push(nomPerso(cible) + " résiste et ne se laisse pas " + act); + explications.push(nomPerso(cible) + " r\xE9siste et ne se laisse pas " + act); } else { - if (type == 'étreinte') act = "l'étreinte"; + if (type == '\xE9treinte') act = "l'\xE9treinte"; else act = "l'absorption"; - explications.push(nomPerso(cible) + " évite " + act); + explications.push(nomPerso(cible) + " \xE9vite " + act); } break; default: //match null, la cible s'en sort - if (type == 'étreinte') act = "l'étreinte"; + if (type == '\xE9treinte') act = "l'\xE9treinte"; else act = "l'enveloppement"; - explications.push(nomPerso(cible) + " échappe de justesse à " + act); + explications.push(nomPerso(cible) + " \xE9chappe de justesse \xE0 " + act); } explications.forEach(function(e) { addLineToFramedDisplay(display, e); @@ -38843,8 +39261,8 @@ var COFantasy = COFantasy || function() { options.cmd && options.cmd.length > 1 && options.cmd[1] == 'libere'; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "!cof-echapper-enveloppement sans sélection de token", playerId); - log("!cof-echapper-enveloppement requiert de sélectionner des tokens"); + sendPlayer(msg, "!cof-echapper-enveloppement sans s\xE9lection de token", playerId); + log("!cof-echapper-enveloppement requiert de s\xE9lectionner des tokens"); return; } iterSelected(selected, function(perso) { @@ -38856,7 +39274,7 @@ var COFantasy = COFantasy || function() { attr = attr[0]; let cube = persoOfIdName(attr.get('current'), options.pageId); if (cube === undefined) { - error("Attribut enveloppePar mal formé, on le supprime", attr.get('current')); + error("Attribut enveloppePar mal form\xE9, on le supprime", attr.get('current')); attr.remove(); unlockToken(perso); return; @@ -38869,7 +39287,7 @@ var COFantasy = COFantasy || function() { } if (libere) { let evt = { - type: 'Libération', + type: 'Lib\xE9ration', deletedAttributes: [attr] }; addEvent(evt); @@ -38884,12 +39302,12 @@ var COFantasy = COFantasy || function() { a.remove(); } }); - sendChar(cube.charId, "libère " + nomPerso(perso)); + sendChar(cube.charId, "lib\xE8re " + nomPerso(perso)); return; } let difficulte = parseInt(maxAttr); if (isNaN(difficulte)) { - error("Difficulté mal formée", attr.get('max')); + error("Difficult\xE9 mal form\xE9e", attr.get('max')); difficulte = 15; } doEchapperEnveloppement(perso, etreinte, cube, difficulte, options); @@ -38912,16 +39330,16 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); let titre = "Tentative de sortir de " + nomPerso(cube); - if (etreinte) titre = "Tentative de se libérer de l'etreinte de " + cube.tokName; + if (etreinte) titre = "Tentative de se lib\xE9rer de l'etreinte de " + cube.tokName; const display = startFramedDisplay(options.playerId, titre, perso, { chuchote: options.secret }); const testId = 'enveloppement_' + perso.token.id; testCaracteristique(perso, 'FOR', difficulte, testId, options, evt, function(tr) { - addLineToFramedDisplay(display, "Résultat : " + tr.texte); + addLineToFramedDisplay(display, "R\xE9sultat : " + tr.texte); if (tr.reussite) { - addLineToFramedDisplay(display, "C'est réussi, " + nomPerso(perso) + " s'extirpe de " + cube.tokName + tr.modifiers); + addLineToFramedDisplay(display, "C'est r\xE9ussi, " + nomPerso(perso) + " s'extirpe de " + cube.tokName + tr.modifiers); toFront(perso.token); evt.deletedAttributes = evt.deletedAttributes || []; let attr = tokenAttribute(perso, 'enveloppePar')[0]; @@ -38938,7 +39356,7 @@ var COFantasy = COFantasy || function() { } }); } else { - let msgRate = "C'est raté." + tr.rerolls + tr.modifiers; + let msgRate = "C'est rat\xE9." + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, msgRate); } sendFramedDisplay(display); @@ -38950,7 +39368,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { @@ -38974,7 +39392,7 @@ var COFantasy = COFantasy || function() { attr = tokenAttribute(perso, 'estDevorePar'); attrName = 'estDevorePar'; if (attr.length === 0) { - sendPlayer(msg, nomPerso(perso) + " n'est pas agrippé."); + sendPlayer(msg, nomPerso(perso) + " n'est pas agripp\xE9."); return; } } @@ -38983,13 +39401,17 @@ var COFantasy = COFantasy || function() { attr = attr[0]; let agrippant = persoOfIdName(attr.get('current'), options.pageId); if (agrippant === undefined) { - error("Attribut " + attrName + " mal formé, on le supprime", attr.get('current')); + error("Attribut " + attrName + " mal form\xE9, on le supprime", attr.get('current')); attr.remove(); unlockToken(perso); return; } if (cmd.length > 2 && cmd[2] == 'libere') { - finAgripper(perso, agrippant, attrName); + const evt = { + type: "Lib\xE8re une cible agripp\xE9e" + }; + finAgripper(perso, agrippant, attrName, evt); + sendPerso(agrippant, "rel\xE2che " + nomPerso(perso)); return; } doLibererAgrippe(perso, agrippant, attrName, options); @@ -39031,7 +39453,7 @@ var COFantasy = COFantasy || function() { const evt = { type: 'libererAgrippe', action: { - titre: "Se libérer", + titre: "Se lib\xE9rer", perso, agrippant, attrName, @@ -39039,7 +39461,7 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - let titre = "Tentative de se libérer de " + nomPerso(agrippant); + let titre = "Tentative de se lib\xE9rer de " + nomPerso(agrippant); let playerId = options.playerId; let display = startFramedDisplay(playerId, titre, perso, { chuchote: options.secret @@ -39056,14 +39478,14 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, e); }); if (tr == 2) { - let msgRate = "C'est raté, " + nomPerso(perso) + " est toujours "; + let msgRate = "C'est rat\xE9, " + nomPerso(perso) + " est toujours "; if (attrName == 'etreinteImmolePar' || attrName == 'etreinteScorpionPar') - msgRate += "prisonnier de l'étreinte de " + nomPerso(agrippant); + msgRate += "prisonnier de l'\xE9treinte de " + nomPerso(agrippant); else if (attrName == 'estDevorePar') msgRate += 'saisi' + eForFemale(perso) + '.'; - else msgRate += "agrippé" + eForFemale(perso) + "."; + else msgRate += "agripp\xE9" + eForFemale(perso) + "."; addLineToFramedDisplay(display, msgRate); - if (attrName == 'etreinteScorpionPar') { // Cas d'étreinte de scorpion avec dommages automatiques + if (attrName == 'etreinteScorpionPar') { // Cas d'\xE9treinte de scorpion avec dommages automatiques let d6 = evt.action.rolls.etreinteDmg || rollDePlus(6, { bonus: 3 }); @@ -39076,7 +39498,7 @@ var COFantasy = COFantasy || function() { let explications2 = []; perso.ignoreTouteRD = true; dealDamage(perso, r, [], evt, false, {}, explications2, function(dmgDisplay) { - let dmgMsg = "L'étreinte du scorpion inflige " + dmgDisplay + " dégâts."; + let dmgMsg = "L'\xE9treinte du scorpion inflige " + dmgDisplay + " d\xE9g\xE2ts."; setTokenAttr(perso, "etreinteScorpionRatee", true, evt); addLineToFramedDisplay(display, dmgMsg); explications2.forEach(function(expl) { @@ -39089,9 +39511,9 @@ var COFantasy = COFantasy || function() { } } else { if (tr === 0) - addLineToFramedDisplay(display, "Réussi de justesse, " + nomPerso(perso) + " se libère."); + addLineToFramedDisplay(display, "R\xE9ussi de justesse, " + nomPerso(perso) + " se lib\xE8re."); else //tr == 1 - addLineToFramedDisplay(display, "Réussi, " + nomPerso(perso) + " se libère."); + addLineToFramedDisplay(display, "R\xE9ussi, " + nomPerso(perso) + " se lib\xE8re."); toFront(perso.token); finAgripper(perso, agrippant, attrName, evt); sendFramedDisplay(display); @@ -39107,7 +39529,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { @@ -39118,13 +39540,13 @@ var COFantasy = COFantasy || function() { let attrName = 'estEcrasePar'; let attr = tokenAttribute(perso, attrName); if (attr.length === 0) { - sendPlayer(msg, nomPerso(perso) + " n'est pas écrasé."); + sendPlayer(msg, nomPerso(perso) + " n'est pas \xE9cras\xE9."); return; } attr = attr[0]; let agrippant = persoOfIdName(attr.get('current'), options.pageId); if (agrippant === undefined) { - error("Attribut " + attrName + " mal formé, on le supprime", attr.get('current')); + error("Attribut " + attrName + " mal form\xE9, on le supprime", attr.get('current')); attr.remove(); unlockToken(perso); return; @@ -39137,15 +39559,15 @@ var COFantasy = COFantasy || function() { estMauvais(agrippant)) { let bonusProtectionContreLeMal = getIntValeurOfEffet(perso, 'protectionContreLeMal', 2); bonus += bonusProtectionContreLeMal; - explications.push("Protection contre le mal => +" + bonusProtectionContreLeMal + " au jet pour se libérer"); + explications.push("Protection contre le mal => +" + bonusProtectionContreLeMal + " au jet pour se lib\xE9rer"); } if (predicateAsBool(perso, 'actionLibre')) { bonus += 5; - explications.push("Action libre => +5 pour résister aux entraves"); + explications.push("Action libre => +5 pour r\xE9sister aux entraves"); } let carac = meilleureCarac('FOR', 'DEX', perso, difficulte - bonus); if (bonus) options.bonus = bonus; - let titre = "Tentative de se libérer de " + nomPerso(agrippant); + let titre = "Tentative de se lib\xE9rer de " + nomPerso(agrippant); doLibererEcrase(perso, agrippant, titre, carac, difficulte, explications, options); } @@ -39184,7 +39606,7 @@ var COFantasy = COFantasy || function() { smsg += '">' + tr.texte + ''; } if (tr.reussite) { - smsg += " => réussi, " + nomPerso(perso) + " se libère."; + smsg += " => r\xE9ussi, " + nomPerso(perso) + " se lib\xE8re."; smsg += tr.modifiers; addLineToFramedDisplay(display, smsg); toFront(perso.token); @@ -39203,7 +39625,7 @@ var COFantasy = COFantasy || function() { } }); } else { - smsg += " => échec, " + nomPerso(perso) + " est toujours saisi dans les bras de " + nomPerso(agrippant); + smsg += " => \xE9chec, " + nomPerso(perso) + " est toujours saisi dans les bras de " + nomPerso(agrippant); smsg += tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, smsg); } @@ -39228,7 +39650,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2], cmd[2], options.pageId); if (cible === undefined) { - error("Le deuxième argument de !cof-animer-cadavre n'est pas un token valide", msg.content); + error("Le deuxi\xE8me argument de !cof-animer-cadavre n'est pas un token valide", msg.content); return; } if (!getState(cible, 'mort')) { @@ -39236,13 +39658,13 @@ var COFantasy = COFantasy || function() { return; } if (attributeAsBool(cible, 'cadavreAnime')) { - sendPlayer(msg, nomPerso(cible) + " a déjà été animé" + eForFemale(cible) + "."); + sendPlayer(msg, nomPerso(cible) + " a d\xE9j\xE0 \xE9t\xE9 anim\xE9" + eForFemale(cible) + "."); return; } var niveauLanceur = ficheAttributeAsInt(lanceur, 'niveau', 1); var niveauCible = ficheAttributeAsInt(cible, 'niveau', 1); if (niveauCible > niveauLanceur) { - sendPlayer(msg, nomPerso(cible) + " est de NC " + niveauCible + ", supérieur à celui de " + nomPerso(lanceur) + " (" + niveauLanceur + ")"); + sendPlayer(msg, nomPerso(cible) + " est de NC " + niveauCible + ", sup\xE9rieur \xE0 celui de " + nomPerso(lanceur) + " (" + niveauLanceur + ")"); return; } var evt = { @@ -39250,27 +39672,27 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); if (limiteRessources(lanceur, options, 'animerUnCadavre', "animer un cadavre", evt)) return; - sendPerso(lanceur, 'réanime ' + nomPerso(cible)); + sendPerso(lanceur, 'r\xE9anime ' + nomPerso(cible)); setState(cible, 'mort', false, evt); var pvmax = parseInt(cible.token.get("bar1_max")); updateCurrentBar(cible, 1, pvmax, evt); setTokenAttr(cible, 'cadavreAnime', true, evt, { - msg: 'se relève' + msg: 'se rel\xE8ve' }); } var niveauxEbriete = [ "sobre", "pompette", - "bourré", + "bourr\xE9", "ivre-mort", - "en coma éthylique" + "en coma \xE9thylique" ]; function augmenteEbriete(personnage, evt, expliquer) { let n = attributeAsInt(personnage, 'niveauEbriete', 0) + 1; if (n >= niveauxEbriete.length) { - expliquer(nomPerso(personnage) + " est déjà en coma éthylique."); + expliquer(nomPerso(personnage) + " est d\xE9j\xE0 en coma \xE9thylique."); return; } expliquer(nomPerso(personnage) + " devient " + niveauxEbriete[n]); @@ -39292,7 +39714,7 @@ var COFantasy = COFantasy || function() { var cibles = []; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "pas de cible trouvée, action annulée", playerId); + sendPlayer(msg, "pas de cible trouv\xE9e, action annul\xE9e", playerId); return; } iterSelected(selected, function(perso) { @@ -39312,17 +39734,17 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - if (limiteRessources(options.lanceur, options, 'vapeursEthyliques', "lancer une fiole de vapeurs éthyliques", evt)) { + if (limiteRessources(options.lanceur, options, 'vapeursEthyliques', "lancer une fiole de vapeurs \xE9thyliques", evt)) { addEvent(evt); return; } - let display = startFramedDisplay(playerId, 'Vapeurs éthyliques'); + let display = startFramedDisplay(playerId, 'Vapeurs \xE9thyliques'); let expliquer = function(m) { addLineToFramedDisplay(display, m); }; const explications = []; if (options.save) { - explications.push(" Jet de " + options.save.carac + " " + options.save.seuil + " pour résister à l'alcool"); + explications.push(" Jet de " + options.save.carac + " " + options.save.seuil + " pour r\xE9sister \xE0 l'alcool"); } entrerEnCombat(options.lanceur, persos, explications, evt); explications.forEach(explication => expliquer(explications)); @@ -39361,11 +39783,11 @@ var COFantasy = COFantasy || function() { function desaouler(msg) { getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Aucune sélection pour !cof-desaouler", playerId); + sendPlayer(msg, "Aucune s\xE9lection pour !cof-desaouler", playerId); return; } var evt = { - type: 'desaoûler' + type: 'desao\xFBler' }; var expliquer = function(s) { sendChat('', s); @@ -39399,7 +39821,7 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - if (limiteRessources(options.lanceur, options, 'boireAlcool', "est affecté par l'alcool", evt)) { + if (limiteRessources(options.lanceur, options, 'boireAlcool', "est affect\xE9 par l'alcool", evt)) { return; } var display = startFramedDisplay(playerId, 'Alcool'); @@ -39407,7 +39829,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, m); }; if (options.save) { - expliquer("Jet de " + options.save.carac + " " + options.save.seuil + " pour résister à l'alcool"); + expliquer("Jet de " + options.save.carac + " " + options.save.seuil + " pour r\xE9sister \xE0 l'alcool"); } var count = persos.length; var finalize = function() { @@ -39443,7 +39865,7 @@ var COFantasy = COFantasy || function() { //On joue un son let son = msg.content.substring(sonIndex + 1); playSound(son); - } else { //On arrête tous les sons + } else { //On arr\xEAte tous les sons let AMdeclared; try { AMdeclared = Roll20AM; @@ -39480,7 +39902,7 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error('pas de token sélectionné pour !cof-bonus-couvert'); + error('pas de token s\xE9lectionn\xE9 pour !cof-bonus-couvert'); return; } var evt = { @@ -39491,12 +39913,12 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(perso) { if (nouveauBonus) { setTokenAttr(perso, 'bonusCouvert', nouveauBonus, evt, { - msg: "se met à couvert", + msg: "se met \xE0 couvert", secret: options.secret }); } else { removeTokenAttr(perso, 'bonusCouvert', evt, { - msg: "n'est plus à couvert", + msg: "n'est plus \xE0 couvert", secret: options.secret }); } @@ -39528,7 +39950,7 @@ var COFantasy = COFantasy || function() { return; }*/ if (selected.length === 0) { - error('pas de token sélectionné pour !cof-set-attribute'); + error('pas de token s\xE9lectionn\xE9 pour !cof-set-attribute'); return; } const evt = { @@ -39581,7 +40003,7 @@ var COFantasy = COFantasy || function() { let predicats = state.COFantasy.predicats; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error('pas de token sélectionné pour !cof-set-predicate'); + error('pas de token s\xE9lectionn\xE9 pour !cof-set-predicate'); return; } const evt = { @@ -39596,14 +40018,14 @@ var COFantasy = COFantasy || function() { case 'vrai': case 'oui': if (pred.includes(predicat)) { - sendPlayer(msg, 'Prédicat ' + predicat + ' déjà présent', playerId); + sendPlayer(msg, 'Pr\xE9dicat ' + predicat + ' d\xE9j\xE0 pr\xE9sent', playerId); return; } if (pred === '') pred = predicat; else pred = pred + ' ' + predicat; setFicheAttr(perso, 'predicats_script', pred, evt); if (predicats) predicats[perso.charId] = undefined; - sendPlayer(msg, 'Prédicat ' + predicat + ' ajouté', playerId); + sendPlayer(msg, 'Pr\xE9dicat ' + predicat + ' ajout\xE9', playerId); break; case 'false': case 'faux': @@ -39611,11 +40033,11 @@ var COFantasy = COFantasy || function() { let regPred = new RegExp('(^| |,|\n)' + predicat + '($| |,|\n)'); let newPred = pred.replace(regPred, ' '); if (newPred == pred) { - sendPlayer(msg, 'Prédicat ' + predicat + ' non trouvé', playerId); + sendPlayer(msg, 'Pr\xE9dicat ' + predicat + ' non trouv\xE9', playerId); } else { setFicheAttr(perso, 'predicats_script', newPred, evt); if (predicats) predicats[perso.charId] = undefined; - sendPlayer(msg, 'Prédicat ' + predicat + ' enlevé', playerId); + sendPlayer(msg, 'Pr\xE9dicat ' + predicat + ' enlev\xE9', playerId); } break; default: @@ -39643,11 +40065,11 @@ var COFantasy = COFantasy || function() { } var perso = persoOfId(cmd[1]); if (perso === undefined) { - error("Le token renseigné pour !cof-defense-armee-des-morts est inconnu", cmd); + error("Le token renseign\xE9 pour !cof-defense-armee-des-morts est inconnu", cmd); return; } if (!peutController(msg, perso)) { - sendPlayer(msg, "ne peut pas faire ça."); + sendPlayer(msg, "ne peut pas faire \xE7a."); return; } var evt = { @@ -39655,7 +40077,7 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); var opt = { - msg: "se défend contre les morts" + msg: "se d\xE9fend contre les morts" }; setTokenAttr(perso, "defenseArmeeDesMorts", true, evt, opt); } @@ -39675,8 +40097,8 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, ligne); } - //!cof-options-d-attaque, affiche les options d'attaque du token sélectionné - // si on donne reset en argument, remet tout à zéro + //!cof-options-d-attaque, affiche les options d'attaque du token s\xE9lectionn\xE9 + // si on donne reset en argument, remet tout \xE0 z\xE9ro // si on donne en argument option valeur, change la valeur de l'option function optionsDAttaque(msg) { const options = parseOptions(msg); @@ -39806,7 +40228,7 @@ var COFantasy = COFantasy || function() { break; default: error("Argument de !cof-options-d-attaque non reconnu", cmd); - //Mais on peut quand même afficher les options + //Mais on peut quand m\xEAme afficher les options } turnAction(perso, playerId); return; @@ -39818,7 +40240,7 @@ var COFantasy = COFantasy || function() { }; if (aepc || arc || aac || adtc || (persoEstPNJ(perso) && adg > 1)) { action = "!cof-options-d-attaque reset --target " + perso.token.id; - opt_display.action_right = boutonSimple(action, 'réinit.'); + opt_display.action_right = boutonSimple(action, 'r\xE9init.'); } var display = startFramedDisplay(playerId, title, perso, opt_display); var ligne = ''; @@ -39827,7 +40249,7 @@ var COFantasy = COFantasy || function() { ligne = "Attaque de groupe : "; action = "!cof-options-d-attaque attaque_de_groupe ?{Combien d'adversaires par jet?}"; action += " --target " + perso.token.id; - overlay = 'title="+2 Att. par créature, si Att > DEF + 5, DM x2, si critique DM x3"'; + overlay = 'title="+2 Att. par cr\xE9ature, si Att > DEF + 5, DM x2, si critique DM x3"'; ligne += boutonSimple(action, adg, overlay); if (adg < 2) { ligne += "attaquant"; @@ -39847,7 +40269,7 @@ var COFantasy = COFantasy || function() { } action += " --target " + perso.token.id; ligne = boutonSimple(action, text) + "Attaque en puissance"; - action = "!cof-options-d-attaque attaque_en_puissance ?{nombre de dés de bonus (-5 att par dé)?}"; + action = "!cof-options-d-attaque attaque_en_puissance ?{nombre de d\xE9s de bonus (-5 att par d\xE9)?}"; action += " --target " + perso.token.id; ligne += "(+" + boutonSimple(action, aep) + "d"; if (predicateAsBool(perso, 'tropPetit') && !attributeAsBool(perso, 'grandeTaille')) { @@ -39856,8 +40278,8 @@ var COFantasy = COFantasy || function() { ligne += "6 DM)"; } addLineToFramedDisplay(display, ligne); - addLigneOptionAttaque(display, perso, arc, "Attaque risquée", 'attaque_risquee'); - addLigneOptionAttaque(display, perso, aac, "Attaque assurée", 'attaque_assuree'); + addLigneOptionAttaque(display, perso, arc, "Attaque risqu\xE9e", 'attaque_risquee'); + addLigneOptionAttaque(display, perso, aac, "Attaque assur\xE9e", 'attaque_assuree'); addLigneOptionAttaque(display, perso, adtc, "Attaque pour assommer", 'attaque_dm_temp'); sendFramedDisplay(display); }); @@ -39865,7 +40287,7 @@ var COFantasy = COFantasy || function() { if (evt.attributes) addEvent(evt); } - //si evt est défini, on ajoute les actions à evt + //si evt est d\xE9fini, on ajoute les actions \xE0 evt function nePlusSuivre(perso, pageId, evt, reutilise) { let attrSuit = tokenAttribute(perso, 'suit'); if (attrSuit.length > 0) { @@ -39938,7 +40360,7 @@ var COFantasy = COFantasy || function() { } let perso = persoOfId(cmd[1], cmd[1], options.pageId); if (perso === undefined) { - error("Token sélectionne incorrect pour !cof-suivre", cmd); + error("Token s\xE9lectionne incorrect pour !cof-suivre", cmd); return; } let pageId = perso.token.get('pageid'); @@ -39951,7 +40373,7 @@ var COFantasy = COFantasy || function() { type: 'Suivre', attributes: [] }; - //D'abord on arrête de suivre si on suivait quelqu'un + //D'abord on arr\xEAte de suivre si on suivait quelqu'un let attrSuit = nePlusSuivre(perso, pageId, evt, true); let cibleId = idName(cible); let attr = tokenAttribute(cible, 'estSuiviPar'); @@ -39974,7 +40396,7 @@ var COFantasy = COFantasy || function() { let yc = cible.token.get('top'); let distance = Math.floor(Math.sqrt((xc - xt) * (xc - xt) + (yc - yt) * (yc - yt))); if (attrSuit) { - //alors evt contient déjà attrSuit + //alors evt contient d\xE9j\xE0 attrSuit attrSuit.set('current', cibleId); attrSuit.set('max', distance); } else { @@ -39994,7 +40416,7 @@ var COFantasy = COFantasy || function() { return c !== ''; }); if (cmd.length < 2) { - error("Il faut préciser un token sur lequel se centrer", cmd); + error("Il faut pr\xE9ciser un token sur lequel se centrer", cmd); return; } let playerId = getPlayerIdFromMsg(msg); @@ -40002,7 +40424,7 @@ var COFantasy = COFantasy || function() { if (playerIsGM(playerId)) { let p = getObj('player', playerId); if (p === undefined) { - error("Impossible de trouver le joueur qui a lancé la commande", msg); + error("Impossible de trouver le joueur qui a lanc\xE9 la commande", msg); return; } pageId = p.get('_lastpage'); @@ -40049,7 +40471,7 @@ var COFantasy = COFantasy || function() { else possede = true; msg += pc + " PC"; } - if (possede) msg = 'possède ' + msg; + if (possede) msg = 'poss\xE8de ' + msg; else msg = "n'a pas d'argent"; if (dest) sendPlayer(dest, nomPerso(perso) + ' ' + msg); else whisperChar(perso.charId, msg); @@ -40071,19 +40493,19 @@ var COFantasy = COFantasy || function() { let val = ficheAttributeAsInt(perso, 'bourse_' + unite, 0); let line = '
'; let action = - "!cof-bourse fixer ?{Nouveau montant de pièces " + piece + " ?} " + finAction; + "!cof-bourse fixer ?{Nouveau montant de pi\xE8ces " + piece + " ?} " + finAction; line += boutonSimple(action, val) + '' + nom + ''; line += ''; - action = "!cof-bourse depenser ?{Pièces " + piece + " à dépenser ?} " + finAction; - line += boutonSimple(action, 'Dépenser'); - action = "!cof-bourse gagner ?{Pièces " + piece + " ?} " + finAction; + action = "!cof-bourse depenser ?{Pi\xE8ces " + piece + " \xE0 d\xE9penser ?} " + finAction; + line += boutonSimple(action, 'D\xE9penser'); + action = "!cof-bourse gagner ?{Pi\xE8ces " + piece + " ?} " + finAction; line += boutonSimple(action, 'Gagner'); line += '
'; addLineToFramedDisplay(display, line); } //!cof-bourse [action] - //Les actions peuvent être depenser val [unite], fixer val unite ou gagner val [unite] + //Les actions peuvent \xEAtre depenser val [unite], fixer val unite ou gagner val [unite] function gestionBourse(msg) { var cmd = msg.content.split(' ').filter(function(c) { return c.trim() !== ''; @@ -40100,11 +40522,11 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { switch (cmd[1]) { case 'depenser': - case 'dépenser': + case 'd\xE9penser': case 'gagner': case 'fixer': if (cmd.length < 3) { - error("Il faut spécifier un montant à " + cmd[1], msg.content); + error("Il faut sp\xE9cifier un montant \xE0 " + cmd[1], msg.content); return; } montant = parseInt(cmd[2]); @@ -40117,7 +40539,7 @@ var COFantasy = COFantasy || function() { action = 'depenser'; } else if (cmd[1] == 'fixer') { if (montant < 0) { - error("On ne peut avoir qu'un nombre positif de pièces", cmd); + error("On ne peut avoir qu'un nombre positif de pi\xE8ces", cmd); return; } action = 'fixer'; @@ -40125,12 +40547,12 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3 && !cmd[3].startsWith('--')) { unite = cmd[3].toLowerCase().trim(); if (unite != 'pp' && unite != 'po' && unite != 'pa' && unite != 'pc') { - error("Pièces non reconnues : " + cmd[3], cmd); + error("Pi\xE8ces non reconnues : " + cmd[3], cmd); return; } depense[unite] = montant; } else if (action == 'fixer') { - error("Il faut préciser les unités pour !cof-bourse fixer", msg.content); + error("Il faut pr\xE9ciser les unit\xE9s pour !cof-bourse fixer", msg.content); return; } depense.total = depense.pc + 10 * (depense.pa + 10 * (depense.po + 10 * depense.pp)); @@ -40138,7 +40560,7 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de personnage sélectionné pour !cof-bourse", playerId); + sendPlayer(msg, "Pas de personnage s\xE9lectionn\xE9 pour !cof-bourse", playerId); return; } var evt = { @@ -40182,7 +40604,7 @@ var COFantasy = COFantasy || function() { } var montantPossede = pc + 10 * (pa + 10 * (po + 10 * pp)); if (montantPossede < depense.total) { - sendPerso(perso, "ne possède pas assez d'argent pour cette dépense"); + sendPerso(perso, "ne poss\xE8de pas assez d'argent pour cette d\xE9pense"); afficherRichesse(perso, msg); return; } @@ -40192,7 +40614,7 @@ var COFantasy = COFantasy || function() { po: po, pp: pp }; - // On privilégie les dépenses directes + // On privil\xE9gie les d\xE9penses directes var dpp = depense.pp; if (dpp <= bourse.pp) { bourse.pp -= dpp; @@ -40225,14 +40647,14 @@ var COFantasy = COFantasy || function() { dpc -= bourse.pc; bourse.pc = 0; } - // Puis on dépense d'abord la petite monnaie + // Puis on d\xE9pense d'abord la petite monnaie var v = dpc + 10 * (dpa + 10 * (dpo + 10 * dpp)); v = depenserSous(perso, 'pc', bourse, v); v = depenserSous(perso, 'pa', bourse, v); v = depenserSous(perso, 'po', bourse, v); v = depenserSous(perso, 'pp', bourse, v); if (v > 0) { - error("Erreur interne de calcul, il reste " + v + " PP à dépenser ??", bourse); + error("Erreur interne de calcul, il reste " + v + " PP \xE0 d\xE9penser ??", bourse); return; } if (bourse.pc != pc) @@ -40291,7 +40713,7 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); if (options.lanceur) { - sendPerso(options.lanceur, "prononce un mot avec la Voix d'une puissance supérieure. Tous ses ennemis sont immobilisés et ses alliés sont galvanisés."); + sendPerso(options.lanceur, "prononce un mot avec la Voix d'une puissance sup\xE9rieure. Tous ses ennemis sont immobilis\xE9s et ses alli\xE9s sont galvanis\xE9s."); let allies = alliesParPerso[options.lanceur.charId]; if (allies) { let tokens = findObjs({ @@ -40327,8 +40749,8 @@ var COFantasy = COFantasy || function() { }, options); } - // Ajoute evt à l'historique si présent - // msg n'est pas forcément présent + // Ajoute evt \xE0 l'historique si pr\xE9sent + // msg n'est pas forc\xE9ment pr\xE9sent function nextTurnChargeFantastique(msg, oldTurnOrder) { if (oldTurnOrder) Campaign().set('turnorder', oldTurnOrder); let cf = stateCOF.chargeFantastique; @@ -40367,7 +40789,7 @@ var COFantasy = COFantasy || function() { stateCOF.chargeFantastique.activeTokenId = perso.token.id; setTokenInitAura(perso); let display = startFramedDisplay(playerId, "Charge fantastique", perso, optionsDisplay); - addLineToFramedDisplay(display, "Phase de mouvement : déplacez votre token en ligne droite"); + addLineToFramedDisplay(display, "Phase de mouvement : d\xE9placez votre token en ligne droite"); addLineToFramedDisplay(display, "puis " + boutonSimple("!cof-next-charge-fantastique", "cliquez ici")); sendFramedDisplay(display); return; @@ -40401,12 +40823,12 @@ var COFantasy = COFantasy || function() { } const chevalier = persoOfId(cmd[1], cmd[1], options.pageId); if (chevalier === undefined) { - error("Le token sélectionné ne représente pas un personnage", cmd); + error("Le token s\xE9lectionn\xE9 ne repr\xE9sente pas un personnage", cmd); return; } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error('pas de token sélectionné pour !cof-charge-fantastique', msg.content); + error('pas de token s\xE9lectionn\xE9 pour !cof-charge-fantastique', msg.content); return; } const evt = { @@ -40414,7 +40836,7 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); if (limiteRessources(chevalier, options, 'chargeFantastique', 'charge fantastique', evt)) return; - sendPerso(chevalier, "mène une charge fantastique !"); + sendPerso(chevalier, "m\xE8ne une charge fantastique !"); initiative(selected, evt); stateCOF.chargeFantastique = {}; let ordreActions = []; @@ -40432,14 +40854,14 @@ var COFantasy = COFantasy || function() { ordreActions.sort(function(p1, p2) { if (p1.init < p2.init) return 1; if (p1.init > p2.init) return -1; - // Priorité aux joueurs - // Premier critère : la barre de PV des joueurs est liée + // Priorit\xE9 aux joueurs + // Premier crit\xE8re : la barre de PV des joueurs est li\xE9e if (p1.perso.token.get('bar1_link') === '') { if (p2.perso.token.get('bar1_link') === '') return 0; return 1; } if (p2.perso.token.get('bar1_link') === '') return -1; - // Deuxième critère : les joueurs ont un DV + // Deuxi\xE8me crit\xE8re : les joueurs ont un DV let dvA = ficheAttributeAsInt(p1.perso, "DV", 0); let dvB = ficheAttributeAsInt(p2.perso, "DV", 0); if (dvA === 0) { @@ -40447,7 +40869,7 @@ var COFantasy = COFantasy || function() { return 1; } if (dvB === 0) return -1; - //Entre joueurs, priorité à la plus grosse sagesse + //Entre joueurs, priorit\xE9 \xE0 la plus grosse sagesse let sagA = ficheAttributeAsInt(p1.perso, 'sagesse', 10); let sagB = ficheAttributeAsInt(p2.perso, 'sagesse', 10); if (sagA < sagB) return 1; @@ -40501,9 +40923,9 @@ var COFantasy = COFantasy || function() { error("Impossible d'utiliser la prescience car l'historique est vide", cmd); return; } - //Au cas où, on vérifie que l'événement de début de tour est bien présent + //Au cas o\xF9, on v\xE9rifie que l'\xE9v\xE9nement de d\xE9but de tour est bien pr\xE9sent if (!findEvent(stateCOF.prescience.evt.id)) { - error("Impossible de trouver le début du tour dans l'historique.", stateCOF.prescience); + error("Impossible de trouver le d\xE9but du tour dans l'historique.", stateCOF.prescience); return; } while (evt && evt.id != stateCOF.prescience.evt.id) { @@ -40543,7 +40965,7 @@ var COFantasy = COFantasy || function() { updateNextInit(ensorceleur); } - //Synchronise les tokens de même nom entre les cartes + //Synchronise les tokens de m\xEAme nom entre les cartes function multiCartes(msg) { let options = parseOptions(msg); let enlever = options && options.cmd && options.cmd.length > 1 && @@ -40558,13 +40980,13 @@ var COFantasy = COFantasy || function() { addEvent(evt); return; } - sendPlayer(msg, "Aucun token selectionné pour !cof-multi-cartes", playerId); + sendPlayer(msg, "Aucun token selectionn\xE9 pour !cof-multi-cartes", playerId); return; } addEvent(evt); if (enlever) { iterSelected(selected, function(perso) { - sendPlayer(msg, nomPerso(perso) + " n'est plus synchronisé", playerId); + sendPlayer(msg, nomPerso(perso) + " n'est plus synchronis\xE9", playerId); removeTokenAttr(perso, 'tokensSynchronises', evt); }); return; @@ -40579,7 +41001,7 @@ var COFantasy = COFantasy || function() { let left = perso.token.get('left'); let top = perso.token.get('top'); let listTokens = [perso.token.id]; - //On cherche les tokens de même nom et on les met en même position + //On cherche les tokens de m\xEAme nom et on les met en m\xEAme position allTokens.forEach(function(tok) { if (tok.get('represents') != perso.charId) return; if (tok.get('name') != name) return; @@ -40602,7 +41024,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour !cof-ombre-mouvante", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof-ombre-mouvante", playerId); return; } iterSelected(selected, function(perso) { @@ -40621,16 +41043,16 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - if (limiteRessources(voleur, options, 'ombreMouvante', 'disparaître dans les ombres', evt)) return; + if (limiteRessources(voleur, options, 'ombreMouvante', 'dispara\xEEtre dans les ombres', evt)) return; let optionsDisplay = { secret: options.secret }; let display = startFramedDisplay(playerId, 'Ombre mouvante', voleur, optionsDisplay); testCaracteristique(voleur, 'DEX', 10, 'ombreMouvante', options, evt, function(tr, explications) { - let msgRes = "Résultat : " + tr.texte; + let msgRes = "R\xE9sultat : " + tr.texte; if (tr.reussite) { - msgRes += ", " + nomPerso(voleur) + " disparaît dans les ombres"; + msgRes += ", " + nomPerso(voleur) + " dispara\xEEt dans les ombres"; addLineToFramedDisplay(display, msgRes + tr.modifiers); let ef = { effet: 'invisibleTemp', @@ -40641,7 +41063,7 @@ var COFantasy = COFantasy || function() { if (options.fx) spawnFx(voleur.token.get('left'), voleur.token.get('top'), options.fx, voleur.token.get('pageid')); } else { - msgRes += ", " + nomPerso(voleur) + " ne réussit pas à se fondre dans les ombres."; + msgRes += ", " + nomPerso(voleur) + " ne r\xE9ussit pas \xE0 se fondre dans les ombres."; addLineToFramedDisplay(display, msgRes + tr.rerolls + tr.modifiers); } explications.forEach(function(m) { @@ -40669,22 +41091,22 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour !cof-reveler-nom", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof-reveler-nom", playerId); return; } let nouveauNomToken; if (cmd.length > 1) nouveauNomToken = cmd.slice(1).join(' '); if (selected.length > 1 && nouveauNomToken) { - sendPlayer(msg, "Attention, on ne peut sélectionner qu'un seul token quand on précise le nouveau nom des tokens", playerId); + sendPlayer(msg, "Attention, on ne peut s\xE9lectionner qu'un seul token quand on pr\xE9cise le nouveau nom des tokens", playerId); return; } const evt = { - type: "Révélation de nom", + type: "R\xE9v\xE9lation de nom", characterNames: [], defaultTokens: [], attributes: [] @@ -40715,24 +41137,24 @@ var COFantasy = COFantasy || function() { }); ancienNom = ficheAttribute(perso, 'alias', ''); nouveauNom = character.get('name'); - sendChat('', ancienNom + " était en réalité " + nouveauNom + " !"); + sendChat('', ancienNom + " \xE9tait en r\xE9alit\xE9 " + nouveauNom + " !"); } else { nouveauNom = ficheAttribute(perso, 'alias', ''); ancienNom = character.get('name'); if (nouveauNom === '') { - sendPlayer(msg, ancienNom + " n'a pas d'alias, rien à révéler."); + sendPlayer(msg, ancienNom + " n'a pas d'alias, rien \xE0 r\xE9v\xE9ler."); return; } setFicheAttr(perso, 'alias', '', evt, { default: '' }); - sendChar(perso.charId, "était en réalité " + nouveauNom + " !"); + sendChar(perso.charId, "\xE9tait en r\xE9alit\xE9 " + nouveauNom + " !"); evt.characterNames.push({ character: character, name: ancienNom }); character.set('name', nouveauNom); - //On change aussi les prédicats qui stoquent le nom du personnage + //On change aussi les pr\xE9dicats qui stoquent le nom du personnage if (attrsWithCharNames === undefined) { attrsWithCharNames = allAttrs.filter(function(attr) { return attr.get('name') == 'predicats_script'; @@ -40825,7 +41247,7 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "Pas de renommage de " + tokName, playerId); } } else { - sendPlayer(msg, "Pas de token par défaut pour " + tokName + ", ce n'est pas encore géré dans !cof-reveler-nom", playerId); + sendPlayer(msg, "Pas de token par d\xE9faut pour " + tokName + ", ce n'est pas encore g\xE9r\xE9 dans !cof-reveler-nom", playerId); } } else { if (defaultTokenName && tokName == defaultTokenName) { @@ -40880,14 +41302,14 @@ var COFantasy = COFantasy || function() { } if (b) { if (stateCOF.tenebresMagiques) { - sendPlayer('GM', "Les personnages sont déjà dans des ténèbres magiques"); + sendPlayer('GM', "Les personnages sont d\xE9j\xE0 dans des t\xE9n\xE8bres magiques"); return; } - sendPlayer('GM', "Les personnages entrent dans des ténèbres magiques"); + sendPlayer('GM', "Les personnages entrent dans des t\xE9n\xE8bres magiques"); stateCOF.tenebresMagiques = {}; } else { stateCOF.tenebresMagiques = undefined; - sendPlayer('GM', "Les personnages sortent des ténèbres magiques"); + sendPlayer('GM', "Les personnages sortent des t\xE9n\xE8bres magiques"); } } @@ -40895,24 +41317,24 @@ var COFantasy = COFantasy || function() { let cmd = msg.content.split(' '); let tm = stateCOF.tenebresMagiques; if (tm === undefined) { - sendPlayer(msg, "Pas de ténèbres magiques, pas d'effet de fiole"); + sendPlayer(msg, "Pas de t\xE9n\xE8bres magiques, pas d'effet de fiole"); return; } cmd = cmd.filter(function(c) { return c.trim() !== ''; }); if (cmd.length < 2) { - error("Il faut un argument à !cof-fiole-de-lumiere", cmd); + error("Il faut un argument \xE0 !cof-fiole-de-lumiere", cmd); return; } var distance = parseInt(cmd[1]); getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Aucun personnage sélectionné", cmd); + error("Aucun personnage s\xE9lectionn\xE9", cmd); return; } if (selected.length > 1) { - error("Il n'y a qu'une seule fiole de lumière", cmd); + error("Il n'y a qu'une seule fiole de lumi\xE8re", cmd); return; } var evt = { @@ -40933,7 +41355,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3) { dimRadius = parseInt(cmd[3]); if (isNaN(dimRadius)) { - error("La distance de vue de la lumière assombrie doit être un nombre", cmd[3]); + error("La distance de vue de la lumi\xE8re assombrie doit \xEAtre un nombre", cmd[3]); dimRadius = ''; } } @@ -40950,25 +41372,25 @@ var COFantasy = COFantasy || function() { return c !== ''; }); if (cmd.length < 3) { - error("Il faut spécifier un attaquant et un défenseur pour !cof-agripper-de-demon", cmd); + error("Il faut sp\xE9cifier un attaquant et un d\xE9fenseur pour !cof-agripper-de-demon", cmd); return; } let attaquant = persoOfId(cmd[1], cmd[1]); let defenseur = persoOfId(cmd[2], cmd[2]); if (attaquant === undefined) { - error("Le premier argument de !cof-agripper-de-demon doit être un token valide", cmd[1]); + error("Le premier argument de !cof-agripper-de-demon doit \xEAtre un token valide", cmd[1]); return; } if (defenseur === undefined) { - error("Le deuxième argument de !cof-agripper-de-demon doit être un token valide", cmd[2]); + error("Le deuxi\xE8me argument de !cof-agripper-de-demon doit \xEAtre un token valide", cmd[2]); return; } if (attributeAsBool(defenseur, 'armureDEau')) { - sendChat("L'armure d'eau empêche " + nomPerso(defenseur) + " d'être aggripé"); + sendChat("L'armure d'eau emp\xEAche " + nomPerso(defenseur) + " d'\xEAtre aggrip\xE9"); return; } const evt = { - type: "Agripper (démon)" + type: "Agripper (d\xE9mon)" }; let options = { pasDeDmg: true @@ -40983,7 +41405,7 @@ var COFantasy = COFantasy || function() { setTokenAttr(defenseur, 'estAgrippePar', idName(attaquant), evt); setTokenAttr(defenseur, 'agrippeParUnDemon', true, evt); } else { - addLineToFramedDisplay(display, nomPerso(defenseur) + " échappe à la tentative de saisie."); + addLineToFramedDisplay(display, nomPerso(defenseur) + " \xE9chappe \xE0 la tentative de saisie."); } explications.forEach(function(expl) { addLineToFramedDisplay(display, expl, 80); @@ -41034,7 +41456,7 @@ var COFantasy = COFantasy || function() { evt.attributes.push({ attribute: attr }); - if ((carac == 'DEX' && comp != 'crochetage' && comp != 'désamorçage') || + if ((carac == 'DEX' && comp != 'crochetage' && comp != 'd\xE9samor\xE7age') || (carac == 'CON' && comp == 'survie') || comp == 'natation' || comp == 'escalade') { attrSpec.name = prefix + 'malus'; @@ -41080,7 +41502,7 @@ var COFantasy = COFantasy || function() { if (treatedChars.has(perso.charId)) return; treatedChars.add(perso.charId); if (!charAttributeAsBool(perso, 'ac')) { - sendPlayer(msg, nomPerso(perso) + " déjà converti (pas d'attribut ac)"); + sendPlayer(msg, nomPerso(perso) + " d\xE9j\xE0 converti (pas d'attribut ac)"); return; } let attributes = findObjs({ @@ -41165,7 +41587,7 @@ var COFantasy = COFantasy || function() { if (d.startsWith('channel resistance ')) { let resChannel = parseInt(d.substring(19)); if (isNaN(resChannel)) { - log("Capacité défensive " + d + " non connue"); + log("Capacit\xE9 d\xE9fensive " + d + " non connue"); } else { predicats += 'bonusSaveContre_positif:' + resChannel + ' '; return; @@ -41173,16 +41595,16 @@ var COFantasy = COFantasy || function() { } else if (d.startsWith('bravery ')) { let courage = parseInt(d.substring(8)); if (isNaN(courage)) { - log("Capacité défensive " + d + " non connue"); + log("Capacit\xE9 d\xE9fensive " + d + " non connue"); } else { predicats += 'courage:' + courage + ' '; return; } } else { - log("Capacité défensive " + d + " non connue"); + log("Capacit\xE9 d\xE9fensive " + d + " non connue"); } if (nonPrisEnCompte === '') - nonPrisEnCompte = 'Capacités défensives : ' + d; + nonPrisEnCompte = 'Capacit\xE9s d\xE9fensives : ' + d; else nonPrisEnCompte += ', ' + d; } }); @@ -41198,7 +41620,7 @@ var COFantasy = COFantasy || function() { if (w === '') return; switch (w) { case 'resurrection vulnerability': - notes += "Détruit par un sort de résurection \n"; + notes += "D\xE9truit par un sort de r\xE9surection \n"; return; case 'vulnerable to acid': case 'vulnerability to acid': @@ -41307,12 +41729,12 @@ var COFantasy = COFantasy || function() { case 'and': return; default: - log("Immunité à " + i + " non traitée"); + log("Immunit\xE9 \xE0 " + i + " non trait\xE9e"); immunitesNonTraitees += i + ' '; } }); if (immunitesNonTraitees !== '') { - log("Immunités non traitées : " + immunitesNonTraitees); + log("Immunit\xE9s non trait\xE9es : " + immunitesNonTraitees); attributsIgnores += 'immune : ' + immunitesNonTraitees + '.\n'; } deleteAttribute(attr, evt); @@ -41363,12 +41785,12 @@ var COFantasy = COFantasy || function() { else rd += ', sonique:' + resVal; return; default: - log("Résistance à " + res[0] + " non traitée"); + log("R\xE9sistance \xE0 " + res[0] + " non trait\xE9e"); resistancesNonTraitees += r + ', '; } }); if (resistancesNonTraitees !== '') { - log("Resistances non traitées : " + resistancesNonTraitees); + log("Resistances non trait\xE9es : " + resistancesNonTraitees); attributsIgnores += 'resist : ' + resistancesNonTraitees + '.\n'; } deleteAttribute(attr, evt); @@ -41418,10 +41840,10 @@ var COFantasy = COFantasy || function() { predicats += 'dragon '; break; case 'fey': - predicats += 'fée '; + predicats += 'f\xE9e '; break; case 'outsider': - predicats += 'extérieur '; + predicats += 'ext\xE9rieur '; break; case 'undead': predicats += 'nonVivant mortVivant '; @@ -41451,7 +41873,7 @@ var COFantasy = COFantasy || function() { taille = 'minuscule'; break; case 'tiny': - taille = 'très petit'; + taille = 'tr\xE8s petit'; break; case 'small': taille = 'petite'; @@ -41462,7 +41884,7 @@ var COFantasy = COFantasy || function() { taille = 'grand'; break; case 'huge': - taille = 'énorme'; + taille = '\xE9norme'; break; case 'gargantuan': case 'colossal': @@ -41551,15 +41973,15 @@ var COFantasy = COFantasy || function() { deleteAttribute(attr, evt); return; case 'disable_device': - ajouteCompetence(perso, 'désamorçage', 'DEX', attr.get('current'), evt); + ajouteCompetence(perso, 'd\xE9samor\xE7age', 'DEX', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'disguise': - ajouteCompetence(perso, 'déguisement', 'CHA', attr.get('current'), evt); + ajouteCompetence(perso, 'd\xE9guisement', 'CHA', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'escape_artist': - ajouteCompetence(perso, 'évasion', 'DEX', attr.get('current'), evt); + ajouteCompetence(perso, '\xE9vasion', 'DEX', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'fly': @@ -41587,11 +42009,11 @@ var COFantasy = COFantasy || function() { deleteAttribute(attr, evt); return; case 'knowledge_engineering': - ajouteCompetence(perso, 'connaissance (ingéniérie)', 'INT', attr.get('current'), evt); + ajouteCompetence(perso, 'connaissance (ing\xE9ni\xE9rie)', 'INT', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'knowledge_geography': - ajouteCompetence(perso, 'connaissance (géographie)', 'INT', attr.get('current'), evt); + ajouteCompetence(perso, 'connaissance (g\xE9ographie)', 'INT', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'knowledge_history': @@ -41635,7 +42057,7 @@ var COFantasy = COFantasy || function() { deleteAttribute(attr, evt); return; case 'ride': - ajouteCompetence(perso, 'Équitation', 'DEX', attr.get('current'), evt); + ajouteCompetence(perso, '\xC9quitation', 'DEX', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'sense_motive': @@ -41647,11 +42069,11 @@ var COFantasy = COFantasy || function() { deleteAttribute(attr, evt); return; case 'spellcraft': - ajouteCompetence(perso, 'sortilèges', 'INT', attr.get('current'), evt); + ajouteCompetence(perso, 'sortil\xE8ges', 'INT', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'stealth': - ajouteCompetence(perso, 'discrétion', 'DEX', attr.get('current'), evt); + ajouteCompetence(perso, 'discr\xE9tion', 'DEX', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'survival': @@ -41662,7 +42084,7 @@ var COFantasy = COFantasy || function() { ajouteCompetence(perso, 'natation', 'FOR', attr.get('current'), evt); deleteAttribute(attr, evt); return; - //Attributs de toutes facons modifiés: + //Attributs de toutes facons modifi\xE9s: case 'tab': case 'type_personnage': return; @@ -41690,7 +42112,7 @@ var COFantasy = COFantasy || function() { case 'skills_racial_modifiers': case 'fortitude': case 'reflex': - case 'will': //On n'y touche pas pour l'instant. À voir plus tard + case 'will': //On n'y touche pas pour l'instant. \xC0 voir plus tard let x = attr.get('current'); if (x === undefined || x === '') deleteAttribute(attr, evt); return; @@ -41749,7 +42171,7 @@ var COFantasy = COFantasy || function() { case 'spellabilities_flag': case 'sq': case 'xp': - case 'l1mancer_status': //Attributs ignorés + case 'l1mancer_status': //Attributs ignor\xE9s deleteAttribute(attr, evt); return; default: @@ -41887,7 +42309,7 @@ var COFantasy = COFantasy || function() { break; default: if (!e.startsWith('+')) { - log("Ennemi juré non reconnu : " + e); + log("Ennemi jur\xE9 non reconnu : " + e); } } } @@ -41925,7 +42347,7 @@ var COFantasy = COFantasy || function() { }); break; case 'dmgbase': - let dm = parseDice(attaque.dmgbase, 'dégâts'); + let dm = parseDice(attaque.dmgbase, 'd\xE9g\xE2ts'); if (dm) { if (dm.nbDe) createObj('attribute', { @@ -41996,7 +42418,7 @@ var COFantasy = COFantasy || function() { options += '--incrCritCoef ' + (cm - 2) + ' '; } break; - case 'atkname': //déjà traité plus haut + case 'atkname': //d\xE9j\xE0 trait\xE9 plus haut case 'options-flag': case 'dmgflag': case 'dmg2type': @@ -42039,7 +42461,7 @@ var COFantasy = COFantasy || function() { if (ab.description) notes += ab.description + '\n'; } if (maxAttackLabel > 0) setAttr('max_attack_label', maxAttackLabel); - //Puis on met les attributs nécessaires + //Puis on met les attributs n\xE9cessaires if (attributsIgnores !== '') setAttr('Attributs Pathfinder', attributsIgnores); if (predicats !== '') setAttr('predicats_script', predicats); @@ -42055,10 +42477,10 @@ var COFantasy = COFantasy || function() { let initiative = dexterite + init - mod_dex; if (isNaN(initiative)) initiative = 10 + 2 * init; setAttr('pnj_init', initiative); - // Nécessaire pour éviter que les sheetworkers re-calculent init et def + // N\xE9cessaire pour \xE9viter que les sheetworkers re-calculent init et def if (initiative != dexterite) setAttr('INIT_DIV', initiative - dexterite); if (def != 10 + mod_dex) setAttr('DEFDIV', def - 10 - mod_dex); - //Finalement, on change le token par défaut + //Finalement, on change le token par d\xE9faut let acAttr = perso.token.get('bar2_link'); affectToken(perso.token, 'bar2_link', acAttr, evt); perso.token.set('bar2_link', ''); @@ -42125,7 +42547,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { @@ -42133,15 +42555,15 @@ var COFantasy = COFantasy || function() { return; } let positif = true; - if (cmd[1] === 'false' || cmd[1] === 'negatif' || cmd[1] === 'négatif') + if (cmd[1] === 'false' || cmd[1] === 'negatif' || cmd[1] === 'n\xE9gatif') positif = false; if (options.soin === undefined && options.dm === undefined) { - sendPlayer(msg, "Rien à canaliser. Il faut préciser un montant de soins ou de dégâts"); + sendPlayer(msg, "Rien \xE0 canaliser. Il faut pr\xE9ciser un montant de soins ou de d\xE9g\xE2ts"); return; } getSelected(msg, function(selected, playerId) { if (selected.length != 1) { - sendPlayer(msg, "Il faut sélectionner un personnage", playerId); + sendPlayer(msg, "Il faut s\xE9lectionner un personnage", playerId); return; } let token = getObj('graphic', selected[0]._id); @@ -42151,7 +42573,7 @@ var COFantasy = COFantasy || function() { } let charId = token.get('represents'); if (charId === undefined || charId === '') { - error("Le token ne représente pas un personnage", token); + error("Le token ne repr\xE9sente pas un personnage", token); return; } let pretre = { @@ -42246,11 +42668,11 @@ var COFantasy = COFantasy || function() { let soins = res[0].inlinerolls[0].results.total; let soinTxt = buildinline(res[0].inlinerolls[0], 'normal', true); if (soins <= 0) { - sendPerso(pretre, "ne réussit pas à soigner (total de soins " + soinTxt + ")", true); + sendPerso(pretre, "ne r\xE9ussit pas \xE0 soigner (total de soins " + soinTxt + ")", true); sync(); return; } - //TODO: tenir compte des PV partagés + //TODO: tenir compte des PV partag\xE9s soigneToken(target, soins, evt, function(soinsEffectifs) { let line = "" + nomPerso(target) + " : + "; @@ -42268,7 +42690,7 @@ var COFantasy = COFantasy || function() { }, options); }); } catch (rollError) { - error("Jet " + options.soin + " mal formé", options); + error("Jet " + options.soin + " mal form\xE9", options); } }); } @@ -42302,7 +42724,7 @@ var COFantasy = COFantasy || function() { copyDmgOptionsToTarget(target, options); dealDamage(target, dmg, [], evt, false, options, explications, function(dmgDisplay, dmgFinal) { addLineToFramedDisplay(display, - nomPerso(target) + " reçoit " + dmgDisplay + " DM"); + nomPerso(target) + " re\xE7oit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); @@ -42310,7 +42732,7 @@ var COFantasy = COFantasy || function() { }); }); } catch (rollError) { - error("Jet " + options.dm + " mal formé", dm); + error("Jet " + options.dm + " mal form\xE9", dm); } }); } @@ -42321,7 +42743,7 @@ var COFantasy = COFantasy || function() { 1: { token: "https://s3.amazonaws.com/files.d20.io/images/250177368/mJsYWMFqDeEmJDJy8tJKWA/thumb.png?1634130296", avatar: "https://s3.amazonaws.com/files.d20.io/images/250177753/IMzDqEpNpuznVnAMYRil8A/max.jpg?1634130507", - taille: 'très petite', + taille: 'tr\xE8s petite', force: 4, pnj_for: -3, constitution: 4, @@ -42391,13 +42813,13 @@ var COFantasy = COFantasy || function() { }; //!cof-animation-des-objets lid niveau [tid] - // la cible optionelle correspond à un token existant non associé à un personnage + // la cible optionelle correspond \xE0 un token existant non associ\xE9 \xE0 un personnage function animationDesObjets(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -42411,7 +42833,7 @@ var COFantasy = COFantasy || function() { } let niveauObjet = parseInt(cmd[2]); if (isNaN(niveauObjet) || niveauObjet < 1) { - error("Le niveau de l'objet animé doit être un nombre positif", cmd); + error("Le niveau de l'objet anim\xE9 doit \xEAtre un nombre positif", cmd); return; } if (niveauObjet > 10) niveauObjet = 10; @@ -42424,7 +42846,7 @@ var COFantasy = COFantasy || function() { let dejaAnime = attributeAsInt(lanceur, 'niveauDesObjetsAnimes', 0); let playerId = getPlayerIdFromMsg(msg); if (dejaAnime + niveauObjet > niveau) { - sendPlayer(msg, "Impossible d'animer plus d'objets pour le moment : somme des niveau animés = " + dejaAnime, playerId); + sendPlayer(msg, "Impossible d'animer plus d'objets pour le moment : somme des niveau anim\xE9s = " + dejaAnime, playerId); return; } let evt = { @@ -42434,7 +42856,7 @@ var COFantasy = COFantasy || function() { if (limiteRessources(lanceur, options, 'animationObjet', "animation d'un objet", evt)) return; let tokenSize = 70; switch (stats.taille) { - case 'très petite': + case 'tr\xE8s petite': tokenSize = 35; break; case 'petite': @@ -42453,7 +42875,7 @@ var COFantasy = COFantasy || function() { let pageId = lanceur.token.get('pageid'); tokenObjet = tokenObjet || createObj('graphic', { - name: 'Objet animé', + name: 'Objet anim\xE9', subtype: 'token', pageid: pageId, imgsrc: stats.token, @@ -42471,12 +42893,12 @@ var COFantasy = COFantasy || function() { limit_field_of_vision_total: 0, }); if (tokenObjet === undefined) { - error("Impossible de créer le token", stats); + error("Impossible de cr\xE9er le token", stats); return; } toFront(tokenObjet); let persoObjet = { - nom: 'Objet animé par ' + nomPerso(lanceur), + nom: 'Objet anim\xE9 par ' + nomPerso(lanceur), attributesFiche: { type_personnage: 'PNJ', niveau: niveauObjet, @@ -42543,7 +42965,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -42558,9 +42980,9 @@ var COFantasy = COFantasy || function() { break; case 'DEX': case 'dexterite': - case 'dexterité': - case 'dextérité': - case 'dextérite': + case 'dexterit\xE9': + case 'dext\xE9rit\xE9': + case 'dext\xE9rite': carac = 'dexterite'; break; case 'CON': @@ -42580,18 +43002,18 @@ var COFantasy = COFantasy || function() { carac = 'charisme'; break; default: - error("Caractéristique " + carac + " non reconnue", cmd); + error("Caract\xE9ristique " + carac + " non reconnue", cmd); return; } let valeur = parseInt(cmd[2]); if (isNaN(valeur) || valeur < 1) { - error("La valeur de soin d'affaiblissement doit être un nombre positif", cmd); + error("La valeur de soin d'affaiblissement doit \xEAtre un nombre positif", cmd); return; } let lanceur = options.lanceur; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour le soin d'affaiblissement", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour le soin d'affaiblissement", playerId); return; } if (lanceur === undefined) { @@ -42636,7 +43058,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -42651,9 +43073,9 @@ var COFantasy = COFantasy || function() { break; case 'DEX': case 'dexterite': - case 'dexterité': - case 'dextérité': - case 'dextérite': + case 'dexterit\xE9': + case 'dext\xE9rit\xE9': + case 'dext\xE9rite': carac = 'dexterite'; break; case 'CON': @@ -42678,18 +43100,18 @@ var COFantasy = COFantasy || function() { carac = 'random'; break; default: - error("Caractéristique " + carac + " non reconnue", cmd); + error("Caract\xE9ristique " + carac + " non reconnue", cmd); return; } let valeur = parseDice(cmd[2]); if (!valeur || !dePositif(valeur)) { - error("La valeur d'affaiblissement doit être un nombre positif", cmd); + error("La valeur d'affaiblissement doit \xEAtre un nombre positif", cmd); return; } let lanceur = options.lanceur; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour l'affaiblissement", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour l'affaiblissement", playerId); return; } if (lanceur === undefined) { @@ -42714,8 +43136,8 @@ var COFantasy = COFantasy || function() { return; } } - if (options.type && immuniseAuType(perso, options.type, lanceur)) { - sendPerso(perso, "ne semble pas affecté par " + stringOfType(options.type)); + if (options.type && immuniseAuType(perso, options.type, lanceur, options)) { + sendPerso(perso, "ne semble pas affect\xE9 par " + stringOfType(options.type)); return; } cibles.push(perso); @@ -42756,15 +43178,15 @@ var COFantasy = COFantasy || function() { return carac; } - //carac est une caractéristique entière - //valeur est soit un nombre, soit le résultat de parseDice + //carac est une caract\xE9ristique enti\xE8re + //valeur est soit un nombre, soit le r\xE9sultat de parseDice function affaiblirCaracPerso(perso, carac, valeur, expliquer, evt) { let nomAttr = 'affaiblissementde' + carac; let valeurText = valeur; if (isNaN(valeur)) { let rid = valeur.id; if (rid === undefined) { - error("Résultat de parseDice sans id", valeur); + error("R\xE9sultat de parseDice sans id", valeur); return; } if (perso.affaiblirCaracRoll && perso.affaiblirCaracRoll[rid]) { @@ -42820,7 +43242,7 @@ var COFantasy = COFantasy || function() { updateCurrentBar(perso, 1, bar1, evt, pvmax); if (bar1 === 0) mort(perso, expliquer, evt); } - } else { //autre caractéristiques + } else { //autre caract\xE9ristiques if (malus >= cn) { setState(perso, 'renverse', true, evt); setState(perso, 'assomme', true, evt); @@ -42828,7 +43250,7 @@ var COFantasy = COFantasy || function() { } } - // valeur peut être un nombre ou le résultat de parseDice + // valeur peut \xEAtre un nombre ou le r\xE9sultat de parseDice function affaiblirCarac(playerId, cibles, carac, valeur, options) { const evt = { type: 'affaiblissement', @@ -42864,8 +43286,8 @@ var COFantasy = COFantasy || function() { }; if (options.save) { let saveOpts = { - msgPour: " pour résister à un affaiblissement de " + car, - msgRate: ", raté.", + msgPour: " pour r\xE9sister \xE0 un affaiblissement de " + car, + msgRate: ", rat\xE9.", attaquant: lanceur, rolls: options.rolls, chanceRollId: options.chanceRollId, @@ -42890,7 +43312,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { @@ -42905,19 +43327,19 @@ var COFantasy = COFantasy || function() { let playerId = getPlayerIdFromMsg(msg); let attr = tokenAttribute(perso, 'reactionViolente'); if (attr.length === 0) { - sendPlayer(msg, "Action inutile, " + perso.token.ge('name') + " n'est pas sous l'effet d'une réaction violente", playerId); + sendPlayer(msg, "Action inutile, " + perso.token.ge('name') + " n'est pas sous l'effet d'une r\xE9action violente", playerId); return; } attr = attr[0]; let duree = parseInt(attr.get('current')); if (isNaN(duree) || duree < 1) duree = 1; let evt = { - type: "Fin de réaction violente", + type: "Fin de r\xE9action violente", deletedAttributes: [attr] }; addEvent(evt); attr.remove(); - sendPerso(perso, "prend sur " + onGenre(perso, 'lui', 'elle') + " pour contenir sa réaction violente"); + sendPerso(perso, "prend sur " + onGenre(perso, 'lui', 'elle') + " pour contenir sa r\xE9action violente"); options.ignoreRD = true; let de = 6; if (predicateAsBool(perso, 'sangFroid')) de = 4; @@ -42935,16 +43357,16 @@ var COFantasy = COFantasy || function() { }); } - //!cof-explosion correspond à !cof-attack token token --explosion pour chaque token sélectionné + //!cof-explosion correspond \xE0 !cof-attack token token --explosion pour chaque token s\xE9lectionn\xE9 function attaqueExplosion(msg) { if (!msg.content) return; let index = msg.content.indexOf(' '); if (index < 1) { - error("Il manque le label de l'attaque à utiliser pour !cof-explosion", msg.content); + error("Il manque le label de l'attaque \xE0 utiliser pour !cof-explosion", msg.content); return; } let args_msg = msg.content.substring(index); - //On va ensuite enlever tout ce qui vient après --target + //On va ensuite enlever tout ce qui vient apr\xE8s --target index = args_msg.indexOf(' --target '); if (index > 0) args_msg = args_msg.substring(0, index); args_msg += ' --explosion'; @@ -42959,7 +43381,7 @@ var COFantasy = COFantasy || function() { }, { ignoreAllies: true, ignoreDisque: true - }); //On ignore les options d'alliés dans le getSelected + }); //On ignore les options d'alli\xE9s dans le getSelected } const listeEffetsAuD20 = { @@ -42985,7 +43407,7 @@ var COFantasy = COFantasy || function() { function setEffetChaqueD20(msg) { let playerId = getPlayerIdFromMsg(msg); if (!playerIsGM(playerId)) { - sendPlayer(msg, "Commande réservée au MJ", playerId); + sendPlayer(msg, "Commande r\xE9serv\xE9e au MJ", playerId); return; } let cmd = msg.content.split(' '); @@ -43079,7 +43501,7 @@ var COFantasy = COFantasy || function() { } let playerId = getPlayerIdFromMsg(msg); if (!playerIsGM(playerId)) { - sendPlayer(msg, "Commande réservée aux MJs", playerId); + sendPlayer(msg, "Commande r\xE9serv\xE9e aux MJs", playerId); return; } let pageId = getPageId(playerId); @@ -43089,7 +43511,7 @@ var COFantasy = COFantasy || function() { } let page = getObj('page', pageId); if (page === undefined) { - error("Impossible de trouver la page correspondant à l'id", pageId); + error("Impossible de trouver la page correspondant \xE0 l'id", pageId); return; } let agrandir = function(o, field) { @@ -43128,31 +43550,31 @@ var COFantasy = COFantasy || function() { texts.forEach(function(t) { move(t); }); - sendPlayer('GM', "Agrandissement terminé"); + sendPlayer('GM', "Agrandissement termin\xE9"); } function decoincer(msg) { getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9", playerId); return; } if (!playerIsGM(playerId)) { - sendPlayer(msg, "Action réservée au MJ", playerId); + sendPlayer(msg, "Action r\xE9serv\xE9e au MJ", playerId); return; } const evt = { - type: "Décoincer", + type: "D\xE9coincer", tokens: [] }; let pageId; iterSelected(selected, function(perso) { if (attributeAsBool(perso, 'decoince')) { - sendPlayer(msg, nomPerso(perso) + " peut déjà être déplacé", playerId); + sendPlayer(msg, nomPerso(perso) + " peut d\xE9j\xE0 \xEAtre d\xE9plac\xE9", playerId); return; } if (!perso.token.get('lockMovement')) { - sendPlayer(msg, nomPerso(perso) + "n'est pas bloqué", playerId); + sendPlayer(msg, nomPerso(perso) + "n'est pas bloqu\xE9", playerId); return; } let nom = 'decoince ' + perso.token.get('name'); @@ -43206,14 +43628,14 @@ var COFantasy = COFantasy || function() { }; let tokenBouge = createObj('graphic', tokenFields); if (!tokenBouge) { - error("Impossible de créer de token pour décoincer " + nomPerso(perso), tokenFields); + error("Impossible de cr\xE9er de token pour d\xE9coincer " + nomPerso(perso), tokenFields); return; } evt.tokens.push(tokenBouge); toFront(tokenBouge); setTokenAttr(perso, 'bougeGraceA', tokenBouge.id, evt); }); - if (pageId) sendPlayer(msg, "Penser à supprimer le token invisible quand vous aurez terminé le déplacement", playerId); + if (pageId) sendPlayer(msg, "Penser \xE0 supprimer le token invisible quand vous aurez termin\xE9 le d\xE9placement", playerId); }); } @@ -43282,7 +43704,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -43296,7 +43718,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-sentir-la-corruption n'est pas un token valide", msg.content); + error("Le deuxi\xE8me argument de !cof-sentir-la-corruption n'est pas un token valide", msg.content); return; } let portee = 30; @@ -43350,7 +43772,7 @@ var COFantasy = COFantasy || function() { testCaracteristique(cible, 'INT', 15, 'sentirLaCorruptionCible', options, evt, function(tr, explications) { let msgRes = "Jet d'INT de " + nomPerso(cible) + " : " + tr.texte; - //On n'affiche pas les possibilités de rerolls, sinon il faudrait un bouton pour "continuer" afin de ne pas afficher le résultat. + //On n'affiche pas les possibilit\xE9s de rerolls, sinon il faudrait un bouton pour "continuer" afin de ne pas afficher le r\xE9sultat. addLineToFramedDisplay(display, msgRes + tr.modifiers); explications.forEach(function(m) { addLineToFramedDisplay(display, m, 80); @@ -43379,7 +43801,7 @@ var COFantasy = COFantasy || function() { } } else { addLineToFramedDisplay(display, msgRes + tr.rerolls + tr.modifiers); - addLineToFramedDisplay(display, nomPerso(chasseur) + " ne réussit pas à sentir la corruption."); + addLineToFramedDisplay(display, nomPerso(chasseur) + " ne r\xE9ussit pas \xE0 sentir la corruption."); endDisplay(); } }); @@ -43391,28 +43813,28 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } let nbBaies; if (cmd.length > 1) { nbBaies = parseInt(cmd[1]); if (isNaN(nbBaies) || nbBaies < 1) { - sendPlayer(msg, "Aucune baie créée. la commnde en demandait " + cmd[1]); + sendPlayer(msg, "Aucune baie cr\xE9\xE9e. la commnde en demandait " + cmd[1]); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Utilisation de !cof-creer-baies sans sélection de token", playerId); + sendPlayer(msg, "Utilisation de !cof-creer-baies sans s\xE9lection de token", playerId); return; } const evt = { - type: "Création de baies" + type: "Cr\xE9ation de baies" }; addEvent(evt); iterSelected(selected, function(druide) { - if (limiteRessources(druide, options, 'creationDeBaies', "créer des baies", evt)) return; + if (limiteRessources(druide, options, 'creationDeBaies', "cr\xE9er des baies", evt)) return; let niveau = ficheAttributeAsInt(druide, 'niveau', 1); let mangerBaie = "!cof-consommer-baie " + niveau + " --limiteParJour 1 baieMagique"; let nb; @@ -43427,7 +43849,7 @@ var COFantasy = COFantasy || function() { }); } ajouterConsommable(druide, 'Baie magique', nb.val, mangerBaie, evt); - sendPerso(druide, "crée " + nb.roll + " baies magiques"); + sendPerso(druide, "cr\xE9e " + nb.roll + " baies magiques"); }); }); } @@ -43455,12 +43877,12 @@ var COFantasy = COFantasy || function() { if (attr.length > 0) { attr = attr[0]; if (attr.length > 1) { - error("Plus d'un attribut pour la quantité d'armes de jet", attr); + error("Plus d'un attribut pour la quantit\xE9 d'armes de jet", attr); attr[1].remove(); } max = parseInt(attr.get('max')); if (isNaN(max) || max < 1) { - error("Maximum de " + weaponStats.name + " mal formé, vérifier sur la fiche", attr); + error("Maximum de " + weaponStats.name + " mal form\xE9, v\xE9rifier sur la fiche", attr); max = 1; } evt.attributes.push({ @@ -43480,7 +43902,7 @@ var COFantasy = COFantasy || function() { }); } if (weaponStats.nbArmesDeJet >= max) { - error(nomPerso(lanceur) + " a déjà toutes ses armes de jet (" + max + ")", weaponStats); + error(nomPerso(lanceur) + " a d\xE9j\xE0 toutes ses armes de jet (" + max + ")", weaponStats); return; } attr.set('current', weaponStats.nbArmesDeJet + 1); @@ -43493,16 +43915,16 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { - error("Il manque des arguments à !cof-retour-boomerang", cmd); + error("Il manque des arguments \xE0 !cof-retour-boomerang", cmd); return; } let lanceur = persoOfId(cmd[1]); if (!lanceur) { - error("L'id du token ayan lancé les armes est incorrecte", cmd); + error("L'id du token ayan lanc\xE9 les armes est incorrecte", cmd); return; } let evt = { @@ -43519,11 +43941,11 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { - error("Il manque un argument à !cof-open-door", cmd); + error("Il manque un argument \xE0 !cof-open-door", cmd); return; } let door = getObj('door', cmd[1]); @@ -43534,7 +43956,7 @@ var COFantasy = COFantasy || function() { door.set('isOpen', true); } - //Demande de bouger son token jusqu'à destination + //Demande de bouger son token jusqu'\xE0 destination function attaqueLigneBouger(msg) { const playerId = getPlayerIdFromMsg(msg); if (stateCOF.pause && !playerIsGM(playerId)) { @@ -43543,7 +43965,7 @@ var COFantasy = COFantasy || function() { } let args = msg.content.split(' '); if (args.length < 2) { - error("Il manque un argument à !cof-attack-line", args); + error("Il manque un argument \xE0 !cof-attack-line", args); return; } const attaquant = persoOfId(args[1]); @@ -43554,12 +43976,12 @@ var COFantasy = COFantasy || function() { let token = attaquant.token; let restArgs = args.slice(2).join(' '); let command = '!cof-attack-line-from ' + token.get('left') + ' ' + token.get('top') + ' ' + token.id + ' ' + restArgs; - sendPlayer(msg, "Déplacer votre token jusqu'au bout de la ligne (l'emplacement doit être libre), et " + boutonSimple(command, "cliquer ici"), playerId); + sendPlayer(msg, "D\xE9placer votre token jusqu'au bout de la ligne (l'emplacement doit \xEAtre libre), et " + boutonSimple(command, "cliquer ici"), playerId); return; } - //En partant de from, retourne la première position sur le segment [from, to] - // à distance dist de pt. S'il n'y en a pas, retourne la projection de pt sur le segment + //En partant de from, retourne la premi\xE8re position sur le segment [from, to] + // \xE0 distance dist de pt. S'il n'y en a pas, retourne la projection de pt sur le segment function positionLigne(from, to, token, dist) { let fx = from.x; let fy = from.y; @@ -43605,7 +44027,7 @@ var COFantasy = COFantasy || function() { let originLeft = parseInt(args[1]); let originTop = parseInt(args[2]); if (isNaN(originLeft) || isNaN(originTop)) { - error("Coordonnées non numériques dans !co-attack-line", args); + error("Coordonn\xE9es non num\xE9riques dans !co-attack-line", args); return; } const attaquant = persoOfId(args[3]); @@ -43615,7 +44037,7 @@ var COFantasy = COFantasy || function() { } let destLeft = attaquant.token.get('left'); let destTop = attaquant.token.get('top'); - //On remet l'attaquant à sa place + //On remet l'attaquant \xE0 sa place attaquant.token.set('left', originLeft); attaquant.token.set('top', originTop); let combat = stateCOF.combat; @@ -43642,12 +44064,12 @@ var COFantasy = COFantasy || function() { y: originTop }; let tropLoin = false; - //On cherche si argument --distanceMax, pas utilisé par cof-attack + //On cherche si argument --distanceMax, pas utilis\xE9 par cof-attack optArgs = optArgs.filter(function(cmd) { if (!cmd.startsWith('distanceMax')) return true; let a = cmd.split(' '); if (a.length < 2) { - error("Il manque un argument à --distanceMax", cmd); + error("Il manque un argument \xE0 --distanceMax", cmd); return false; } let distanceMax = parseInt(a[1]); @@ -43700,14 +44122,14 @@ var COFantasy = COFantasy || function() { return; } } - //On détermine les cibles sur le trajet + //On d\xE9termine les cibles sur le trajet let cibles = []; tokens.forEach(function(tok) { let cible = { token: tok, charId: tok.get('represents') }; - if (nePeutPlusPrendreDM(cible, {})) return; //pas de dégâts aux morts + if (nePeutPlusPrendreDM(cible, {})) return; //pas de d\xE9g\xE2ts aux morts let distToTrajectory = distancePixTokenSegment(tok, ptOrigin, ptDest); if (distToTrajectory > attRayon + tokenSize(tok, 0)) return; @@ -43734,7 +44156,7 @@ var COFantasy = COFantasy || function() { }); combat.attackId = combat.attackId || 0; combat.attackCallbacks = combat.attackCallBacks || {}; - //On trie les cibles selon leur distance à l'origine. + //On trie les cibles selon leur distance \xE0 l'origine. cibles.sort(function(c1, c2) { return c1.distanceOrigine - c2.distanceOrigine; }); @@ -43783,11 +44205,11 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { - error("Il manque un argument à !cof-vision-nocturne", cmd); + error("Il manque un argument \xE0 !cof-vision-nocturne", cmd); return; } let distance = parseInt(cmd[1]); @@ -43798,7 +44220,7 @@ var COFantasy = COFantasy || function() { let pageId = options.pageId; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Utilisation de !cof-vision-nocturne sans sélection de token", playerId); + sendPlayer(msg, "Utilisation de !cof-vision-nocturne sans s\xE9lection de token", playerId); return; } const evt = { @@ -43818,27 +44240,27 @@ var COFantasy = COFantasy || function() { const listeDesRunesMortes = { Melianil: { - description: "+2 en attaque et +1d6 aux DM (à tous les sorts ou aux attaques au contact avec le bâton)", + description: "+2 en attaque et +1d6 aux DM (\xE0 tous les sorts ou aux attaques au contact avec le b\xE2ton)", }, Isulys: { - description: "une fois par tour, par une action d'attaque, peut produire un rayon d’énergie négative d’une portée de 40 mètres. Sur test d’attaque magique réussit, la victime subit [2d6 + Mod. %SAGINT] DM et doit utiliser un d12 à tous ses tests au lieu d’un d20 pendant un tour.", + description: "une fois par tour, par une action d'attaque, peut produire un rayon d\x2019\xE9nergie n\xE9gative d\x2019une port\xE9e de 40 m\xE8tres. Sur test d\x2019attaque magique r\xE9ussit, la victime subit [2d6 + Mod. %SAGINT] DM et doit utiliser un d12 \xE0 tous ses tests au lieu d\x2019un d20 pendant un tour.", }, Bryniza: { - description: "permet de voir parfaitement dans le noir à une portée de 30 m, et comme dans la pénombre jusqu'à 50 m. Au prix d'une action limitée, le porteur peut utiliser le sort Détection de la magie 3 fois par jour.", + description: "permet de voir parfaitement dans le noir \xE0 une port\xE9e de 30 m, et comme dans la p\xE9nombre jusqu'\xE0 50 m. Au prix d'une action limit\xE9e, le porteur peut utiliser le sort D\xE9tection de la magie 3 fois par jour.", activation: "Les yeux de %NOM deviennent d'un noir d'encre.", fin: "Les yeux de %NOM redeviennent normaux.", }, Lizura: { - description: "immunité au souffle de Swarathnak, à l'acide et au poison.", - activation: "La boue noire du bâton s'écoule le long du bras de %NOM et recouvre tout son corps à l'exception des yeux.", - fin: "La boue se retire dans le bâton, %NOM retrouve une apparence normale.", + description: "immunit\xE9 au souffle de Swarathnak, \xE0 l'acide et au poison.", + activation: "La boue noire du b\xE2ton s'\xE9coule le long du bras de %NOM et recouvre tout son corps \xE0 l'exception des yeux.", + fin: "La boue se retire dans le b\xE2ton, %NOM retrouve une apparence normale.", memeEffetQue: 'Mitrah', }, Mitrah: { - description: "RD 5 à tous les DM.", - activation: "La boue noire du bâton s'écoule le long du bras de %NOM et recouvre tout son corps à l'exception des yeux.", - fin: "La boue se retire dans le bâton, %NOM retrouve une apparence normale.", + description: "RD 5 \xE0 tous les DM.", + activation: "La boue noire du b\xE2ton s'\xE9coule le long du bras de %NOM et recouvre tout son corps \xE0 l'exception des yeux.", + fin: "La boue se retire dans le b\xE2ton, %NOM retrouve une apparence normale.", memeEffetQue: 'Lizura', }, }; @@ -43850,13 +44272,13 @@ var COFantasy = COFantasy || function() { function gererRunesMortes(msg) { let cmd = msg.content.split(' '); if (cmd.length < 2) { - error("il manque l'id du personnage qui gère ses runes mortes", cmd); + error("il manque l'id du personnage qui g\xE8re ses runes mortes", cmd); return; } let perso = persoOfId(cmd[1]); if (perso === undefined) return; if (!predicateAsBool(perso, 'batonDesRunesMortes')) { - sendPerso(perso, "ne porte pas le bâton des runes mortes"); + sendPerso(perso, "ne porte pas le b\xE2ton des runes mortes"); return; } let niveau = ficheAttributeAsInt(perso, 'niveau', 1); @@ -43880,7 +44302,7 @@ var COFantasy = COFantasy || function() { error("Rune " + cmd[3] + " non reconnue", cmd); break; } - //Vérification qu'on n'a pas déjà le max de runes + //V\xE9rification qu'on n'a pas d\xE9j\xE0 le max de runes let runesLibres = Math.ceil(niveau / 4); for (let rune in listeDesRunesMortes) { if (attributeAsBool(perso, 'rune' + rune)) runesLibres--; @@ -43894,11 +44316,11 @@ var COFantasy = COFantasy || function() { if (attr[0].get('current') == 'false') { let donne = attr[0].get('max'); if (donne) { - sendPerso(perso, "a donné " + cmd[3] + " à " + donne + ". Impossible de l'activer.", true); + sendPerso(perso, "a donn\xE9 " + cmd[3] + " \xE0 " + donne + ". Impossible de l'activer.", true); break; } } else { - sendPerso(perso, cmd[3] + " est déjà active", true); + sendPerso(perso, cmd[3] + " est d\xE9j\xE0 active", true); break; } } @@ -43938,7 +44360,7 @@ var COFantasy = COFantasy || function() { break; } if (!attributeAsBool(perso, 'rune' + cmd[3])) { - sendPerso(perso, cmd[3] + " n'est pas activée.", true); + sendPerso(perso, cmd[3] + " n'est pas activ\xE9e.", true); break; } let msg; @@ -43950,7 +44372,7 @@ var COFantasy = COFantasy || function() { msg }); if (cmd[3] == 'Bryniza') { - //On enlève la vision dans le noir + //On enl\xE8ve la vision dans le noir let token = perso.token; let pageId = token.get('pageid'); let visionNoir = predicateAsInt(perso, 'visionDansLeNoir', 0); @@ -43973,12 +44395,12 @@ var COFantasy = COFantasy || function() { case 'donner': { if (cmd.length < 4) { - error("Il faut préciser le token à qui donner la rune", cmd); + error("Il faut pr\xE9ciser le token \xE0 qui donner la rune", cmd); break; } let cible = persoOfId(cmd[4]); if (!cible) { - error("Impossible de trouver à qui donner la rune", cmd); + error("Impossible de trouver \xE0 qui donner la rune", cmd); break; } let attr = tokenAttribute(perso, 'rune' + cmd[3]); @@ -43986,11 +44408,11 @@ var COFantasy = COFantasy || function() { if (attr[0].get('current') == 'false') { let donne = attr[0].get('max'); if (donne) { - sendPerso(perso, "a déjà donné " + cmd[3] + " à " + donne + ".", true); + sendPerso(perso, "a d\xE9j\xE0 donn\xE9 " + cmd[3] + " \xE0 " + donne + ".", true); break; } } else { - sendPerso(perso, "Il faut d'abord désactiver " + cmd[3] + " avant de la donner", true); + sendPerso(perso, "Il faut d'abord d\xE9sactiver " + cmd[3] + " avant de la donner", true); break; } } @@ -43999,14 +44421,14 @@ var COFantasy = COFantasy || function() { error("Rune " + cmd[3] + " non reconnue", cmd); break; } - let msg = nomPerso(perso) + " donne une rune à " + nomPerso(cible); + let msg = nomPerso(perso) + " donne une rune \xE0 " + nomPerso(cible); let maxVal = nomPerso(cible); setTokenAttr(perso, 'rune' + cmd[3], 'false', evt, { msg, maxVal }); - sendPerso(perso, "peut maintenant communiquer par télépathie avec " + nomPerso(cible), true); - sendPerso(cible, "peut maintenant communiquer par télépathie avec " + nomPerso(perso), true); + sendPerso(perso, "peut maintenant communiquer par t\xE9l\xE9pathie avec " + nomPerso(cible), true); + sendPerso(cible, "peut maintenant communiquer par t\xE9l\xE9pathie avec " + nomPerso(perso), true); break; } case 'recuperer': @@ -44018,23 +44440,23 @@ var COFantasy = COFantasy || function() { } let attr = tokenAttribute(perso, 'rune' + cmd[3]); if (attr.length === 0) { - sendPerso(perso, "a déjà " + cmd[3], true); + sendPerso(perso, "a d\xE9j\xE0 " + cmd[3], true); break; } if (attr[0].get('current') != 'false') { - sendPerso(perso, "a déjà " + cmd[3], true); + sendPerso(perso, "a d\xE9j\xE0 " + cmd[3], true); break; } let donne = attr[0].get('max'); if (!donne) { - sendPerso(perso, "a déjà " + cmd[3], true); + sendPerso(perso, "a d\xE9j\xE0 " + cmd[3], true); break; } - let msg = nomPerso(perso) + " rappelle une rune sur le bâton"; + let msg = nomPerso(perso) + " rappelle une rune sur le b\xE2ton"; removeTokenAttr(perso, 'rune' + cmd[3], evt, { msg }); - sendPerso(perso, "ne peut plus communiquer par télépathie avec " + donne, true); + sendPerso(perso, "ne peut plus communiquer par t\xE9l\xE9pathie avec " + donne, true); break; } default: @@ -44071,13 +44493,13 @@ var COFantasy = COFantasy || function() { if (er.actif) { ligne = ' 3) { + rang = parseInt(cmd[3]); + if (isNaN(rang)) + rang = predicateAsInt(arquebusier, cmd[3], 0, 2); + if (rang < 1) { + error("Rang de d\xE9molition " + cmd[3] + " incorrect", cmd); + return; + } + } else rang = predicateAsInt(arquebusier, 'voieDesExplosifs', 2, 2); + portee = 6; + dm = rang + 'd6'; + let dmStruct = rollDePlus(6, { + nbDes: 2 * rang + }); + message += " et inflige " + dmStruct.roll + " DM \xE0 la structure (ignore la moiti\xE9 de la RD)"; + tempsDePose = 3; + break; + } + case 'piege': + case 'pi\xE8ge': + { + typeBombe = 'piege'; + if (cmd.length < 5) { + error("Il manque des arguments pour !cof-poser-bombe", cmd); + return; + } + dm = cmd[3]; + portee = 3; + switch (cmd[4]) { + case 'retard': + case 'retard\xE9': + tempsDePose = 1; + if (cmd.length > 5) { + duree = parseInt(cmd[5]); + if (isNaN(duree) || duree < 1) { + error("Dur\xE9e de retardement " + cmd[5] + " incorrecte"); + return; + } + } + break; + case 'intrusion': + case 'detection': + case 'd\xE9tection': + tempsDePose = 2; + intrusion = 1; + duree = 100; + if (cmd.length > 5) { + intrusion = parseInt(cmd[5]); + if (isNaN(intrusion) || intrusion < 1) { + error("Distance de d\xE9tection " + cmd[5] + " incorrecte"); + return; + } + } + //On converti la distance d'intrusion en pixels + let scale = computeScale(pageId); + intrusion = (intrusion / scale) * PIX_PER_UNIT; + break; + default: + error("Type de pi\xE8ge explosif " + cmd[4] + " non reconnu", cmd); + return; + } + break; + } + default: + error("Type de bombe " + cmd[2] + " non reconnu", cmd); + return; + } + let gmnotes = JSON.stringify({ + typeBombe, + portee, + message, + dm, + tempsDePose, + duree, + intrusion + }); + let name = "Bombe " + generateUUID(); + const evt = { + type: "Pose de bombe" + }; + addEvent(evt); + if (limiteRessources(arquebusier, options, 'poseBombe', "poser un explosif", evt)) return; + //create the token + let t = createObj('graphic', { + _pageid: pageId, + imgsrc: IMG_BOMB, + represents: '', + left: arquebusier.token.get('left'), + top: arquebusier.token.get('top'), + width: PIX_PER_UNIT, + height: PIX_PER_UNIT * 0.8, + layer: 'map', + isDrawing: true, + name, + gmnotes + }); + if (!t) { + error("Impossible de cr\xE9er le token de la bombe", IMG_BOMB); + return; + } + toFront(t); + evt.tokens = evt.tokens || []; + evt.tokens.push(t); + stateCOF.tokensTemps = stateCOF.tokensTemps || []; + stateCOF.tokensTemps.push({ + tid: t.id, + duree: duree + tempsDePose, + name, + init: getInit(), + intrusion + }); + //TODO: ajouter un effet temporaire "occup\xE9" + let msgPose = "pose un explosif. "; + if (tempsDePose < 2) msgPose += "Cela lui prend tout le tour"; + else { + msgPose += onGenre(arquebusier, 'Il', 'Elle') + " y passe le tour et encore le"; + if (tempsDePose < 3) msgPose += " suivant."; + else msgPose += "s " + (tempsDePose - 1) + " suivants."; + } + sendPerso(arquebusier, msgPose); } function apiCommand(msg) { @@ -44279,7 +44856,7 @@ var COFantasy = COFantasy || function() { case '!cof-attack-line': attaqueLigneBouger(msg); return; - case '!cof-attack-line-from': //seulement utilisé en interne + case '!cof-attack-line-from': //seulement utilis\xE9 en interne attaqueLigne(msg); return; case '!cof-attendre': @@ -44329,14 +44906,14 @@ var COFantasy = COFantasy || function() { case '!cof-explosion': attaqueExplosion(msg); return; - case '!cof-hors-combat': //ancienne syntaxe, plus documentée + case '!cof-hors-combat': //ancienne syntaxe, plus document\xE9e case '!cof-fin-combat': sortirDuCombat(); return; case '!cof-fin-reaction-violente': finReactionViolente(msg); return; - case '!cof-foudre-du-temps': //ancienne syntaxe, plus documentée + case '!cof-foudre-du-temps': //ancienne syntaxe, plus document\xE9e if (!msg.content) return; let i = msg.content.indexOf(' '); if (i < 0) return; @@ -44385,6 +44962,9 @@ var COFantasy = COFantasy || function() { case '!cof-pause': pauseGame(); return; + case '!cof-poser-bombe': + poserBombe(msg); + return; case '!cof-recharger': recharger(msg); return; @@ -44426,7 +45006,10 @@ var COFantasy = COFantasy || function() { case '!cof-sphere-de-feu': sphereDeFeu(msg); return; - case "!cof-save-state": + case '!cof-save-effet': + parseSaveEffet(msg); + return; + case '!cof-save-state': parseSaveState(msg); return; case '!cof-statut': @@ -44447,9 +45030,6 @@ var COFantasy = COFantasy || function() { case '!cof-zone-de-vie': lancerZoneDeVie(msg); return; - case "!cof-save-effet": - parseSaveEffet(msg); - return; case "!cof-degainer": parseDegainer(msg); return; @@ -44474,7 +45054,7 @@ var COFantasy = COFantasy || function() { case "!cof-fin-classe-effet": finClasseDEffet(msg); return; - case "!cof-attaque-magique": + case '!cof-attaque-magique': parseAttaqueMagique(msg); return; case "!cof-injonction": @@ -44631,7 +45211,7 @@ var COFantasy = COFantasy || function() { stateCOF.statistiques = stateCOF.statistiquesEnPause; delete stateCOF.statistiquesEnPause; } else { - stateCOF.statistiques = {}; //remet aussi les statistiques à 0 + stateCOF.statistiques = {}; //remet aussi les statistiques \xE0 0 } return; case "!cof-arreter-statistiques": @@ -44641,7 +45221,7 @@ var COFantasy = COFantasy || function() { if (stateCOF.statistiques) { stateCOF.statistiquesEnPause = stateCOF.statistiques; delete stateCOF.statistiques; - } // sinon, ne pas écraser les statistiques déjà en pause + } // sinon, ne pas \xE9craser les statistiques d\xE9j\xE0 en pause return; case '!cof-statistiques': displayStatistics(msg); @@ -44850,57 +45430,63 @@ var COFantasy = COFantasy || function() { } //Attributs possibles : - // activation : message à l'activation - // activationF : message à l'activation si la cible est féminine + // activation : message \xE0 l'activation + // activationF : message \xE0 l'activation si la cible est f\xE9minine // actif : message de statut - // actifF : message de statut si la cible est féminine - // fin : message à la fin de l'effet + // actifF : message de statut si la cible est f\xE9minine + // fin : message \xE0 la fin de l'effet // dm : permet d'infliger des dm // soins : soigne - // prejudiciable: est un effet préjudiciable, qui peut être enlevé par délivrance - // generic: admet un argument entre parenthèses - // seulementVivant: ne peut s'appliquer qu'aux créatures vivantes + // prejudiciable: est un effet pr\xE9judiciable, qui peut \xEAtre enlev\xE9 par d\xE9livrance + // generic: admet un argument entre parenth\xE8ses + // seulementVivant: ne peut s'appliquer qu'aux cr\xE9atures vivantes // visible : l'effet est visible - // msgSave: message à afficher quand on résiste à l'effet. Sera précédé de "pour " + // msgSave: message \xE0 afficher quand on r\xE9siste \xE0 l'effet. Sera pr\xE9c\xE9d\xE9 de "pour " // entrave: effet qui immobilise, paralyse ou ralentit - // statusMarker: marker par défaut pour l'effet + // statusMarker: marker par d\xE9faut pour l'effet const messageEffetTemp = { aCouvert: { - activation: "reste à couvert", - actif: "est à couvert", - fin: "n'est pas à couvert" + activation: "reste \xE0 couvert", + actif: "est \xE0 couvert", + fin: "n'est pas \xE0 couvert" }, affecteParAura: { activation: "entre dans une aura", - actif: "est entré dans une aura ce tour", - actifF: "est entrée dans une aura ce tour", + actif: "est entr\xE9 dans une aura ce tour", + actifF: "est entr\xE9e dans une aura ce tour", fin: "fin d'aura", generic: true, }, apeureTemp: { activation: "prend peur", - actif: "est dominé par sa peur", - actifF: "est dominée par sa peur", + actif: "est domin\xE9 par sa peur", + actifF: "est domin\xE9e par sa peur", fin: "retrouve du courage", msgSave: "retrouver du courage", prejudiciable: true, visible: true }, + attaqueADistanceRatee: { + activation: "rate une attaque \xE0 distance", + actif: "a rat\xE9 une attaque \xE0 distance", + fin: '', + visible: false + }, aveugleTemp: { activation: "n'y voit plus rien !", - actif: "est aveuglé", - actifF: "est aveuglée", + actif: "est aveugl\xE9", + actifF: "est aveugl\xE9e", fin: "retrouve la vue", msgSave: "retrouver la vue", prejudiciable: true, visible: true }, benediction: { - activation: "est touché par la bénédiction", - activationF: "est touchée par la bénédiction", - actif: "est béni", - actifF: "est bénie", - fin: "l'effet de la bénédiction s'estompe" + activation: "est touch\xE9 par la b\xE9n\xE9diction", + activationF: "est touch\xE9e par la b\xE9n\xE9diction", + actif: "est b\xE9ni", + actifF: "est b\xE9nie", + fin: "l'effet de la b\xE9n\xE9diction s'estompe" }, blessureSanglante: { activation: "saigne abondamment", @@ -44913,43 +45499,43 @@ var COFantasy = COFantasy || function() { }, carquoisMagique: { activation: "enchante son carquois", - actif: "a un carquois enchannté", + actif: "a un carquois enchannt\xE9", fin: "le carquois redevient normal", visible: true, }, chantDesHeros: { - activation: "écoute le chant du barde", - actif: "est inspiré par le Chant des Héros", - actifF: "est inspirée par le Chant des Héros", - fin: "n'est plus inspiré par le Chant des Héros", - finF: "n'est plus inspirée par le Chant des Héros" + activation: "\xE9coute le chant du barde", + actif: "est inspir\xE9 par le Chant des H\xE9ros", + actifF: "est inspir\xE9e par le Chant des H\xE9ros", + fin: "n'est plus inspir\xE9 par le Chant des H\xE9ros", + finF: "n'est plus inspir\xE9e par le Chant des H\xE9ros" }, drainDeForce: { - activation: "se sent drainé de sa force", - activationF: "se sent drainée de sa force", + activation: "se sent drain\xE9 de sa force", + activationF: "se sent drain\xE9e de sa force", actif: "est sous l'effet d'un drain de force", - msgSave: "ne plus être affaibli", + msgSave: "ne plus \xEAtre affaibli", fin: "n'est plus affaibli", finF: "n'est plus affaiblie", prejudiciable: true, seulementVivant: true, }, etourdiTemp: { - activation: "est étourdi : aucune action et -5 en DEF", - activationF: "est étourdie : aucune action et -5 en DEF", - actif: "est étourdi", - actifF: "est étourdie", - fin: "n'est plus étourdi", - finF: "n'est plus étourdie", + activation: "est \xE9tourdi : aucune action et -5 en DEF", + activationF: "est \xE9tourdie : aucune action et -5 en DEF", + actif: "est \xE9tourdi", + actifF: "est \xE9tourdie", + fin: "n'est plus \xE9tourdi", + finF: "n'est plus \xE9tourdie", msgSave: "se reprendre", prejudiciable: true, visible: true }, formeDAnge: { - activation: "prend la forme d'un ange ailé", + activation: "prend la forme d'un ange ail\xE9", actif: "est en forme d'ange et peut jeter des sorts en vol stationnaire", - fin: "retrouve sa forme normale. Espérons qu'il était au sol...", - finF: "retrouve sa forme normale. Espérons qu'elle était au sol...", + fin: "retrouve sa forme normale. Esp\xE9rons qu'il \xE9tait au sol...", + finF: "retrouve sa forme normale. Esp\xE9rons qu'elle \xE9tait au sol...", visible: true, }, frappeDesArcanes: { @@ -44958,50 +45544,50 @@ var COFantasy = COFantasy || function() { fin: "retrouve assez de puissance magique pour lancer des sorts", }, frenesieMinotaure: { - activation: "entre en frénésie", - actif: "est en frénésie", + activation: "entre en fr\xE9n\xE9sie", + actif: "est en fr\xE9n\xE9sie", fin: "retrouve son calme", msgSave: "retrouver son calme", }, inspiration: { - activation: "est inspiré", - activationF: "est inspirée", + activation: "est inspir\xE9", + activationF: "est inspir\xE9e", actif: "est sous l'effet d'une inspiration", - fin: "n'est plus inspiré", - finF: "n'est plus inspirée" + fin: "n'est plus inspir\xE9", + finF: "n'est plus inspir\xE9e" }, imageDecalee: { - activation: "décale légèrement son image", - actif: "a décalé son image", - fin: "apparaît à nouveau là où il se trouve", - finF: "apparaît à nouveau là où elle se trouve", + activation: "d\xE9cale l\xE9g\xE8rement son image", + actif: "a d\xE9cal\xE9 son image", + fin: "appara\xEEt \xE0 nouveau l\xE0 o\xF9 il se trouve", + finF: "appara\xEEt \xE0 nouveau l\xE0 o\xF9 elle se trouve", visible: false }, immobiliseTemp: { - activation: "est immobilisé : aucun déplacement possible", - activationF: "est immobilisée : aucun déplacement possible", - actif: "est immobilisé", - actifF: "est immobilisée", - fin: "n'est plus immobilisé", - finF: "n'est plus immobilisée", + activation: "est immobilis\xE9 : aucun d\xE9placement possible", + activationF: "est immobilis\xE9e : aucun d\xE9placement possible", + actif: "est immobilis\xE9", + actifF: "est immobilis\xE9e", + fin: "n'est plus immobilis\xE9", + finF: "n'est plus immobilis\xE9e", msgSave: "pouvoir bouger", prejudiciable: true, visible: true, entrave: true }, immuniteAmaladie: { - activation: "devient immunisé aux maladies", - activationF: "devient immunisée aux maladies", - actif: "est temporairement immunisé aux maladies", - actifF: "est temporairement immunisée aux maladies", + activation: "devient immunis\xE9 aux maladies", + activationF: "devient immunis\xE9e aux maladies", + actif: "est temporairement immunis\xE9 aux maladies", + actifF: "est temporairement immunis\xE9e aux maladies", fin: "redevient sensible aux maladies", visible: false }, immuniteApoison: { - activation: "devient immunisé au poison", - activationF: "devient immunisée au poison", - actif: "est temporairement immunisé au poison", - actifF: "est temporairement immunisée au poison", + activation: "devient immunis\xE9 au poison", + activationF: "devient immunis\xE9e au poison", + actif: "est temporairement immunis\xE9 au poison", + actifF: "est temporairement immunis\xE9e au poison", fin: "redevient sensible au poison", visible: false }, @@ -45014,36 +45600,36 @@ var COFantasy = COFantasy || function() { }, paradeCroisee: { activation: "se met en position pour parer des deux armes", - actif: "est en position de parade croisée", - fin: "ne bénéficie plus de sa parade croisée", + actif: "est en position de parade crois\xE9e", + fin: "ne b\xE9n\xE9ficie plus de sa parade crois\xE9e", visible: true, }, paralyseTemp: { - activation: "est paralysé : aucune action ni déplacement possible", - activationF: "est paralysée : aucune action ni déplacement possible", - actif: "est paralysé", - actifF: "est paralysée", - fin: "n'est plus paralysé", - finF: "n'est plus paralysée", - msgSave: "ne plus être paralysé", + activation: "est paralys\xE9 : aucune action ni d\xE9placement possible", + activationF: "est paralys\xE9e : aucune action ni d\xE9placement possible", + actif: "est paralys\xE9", + actifF: "est paralys\xE9e", + fin: "n'est plus paralys\xE9", + finF: "n'est plus paralys\xE9e", + msgSave: "ne plus \xEAtre paralys\xE9", prejudiciable: true, visible: true, entrave: true }, paralyseGoule: { - activation: "est paralysé : aucune action ni déplacement possible", - activationF: "est paralysée : aucune action ni déplacement possible", - actif: "est paralysé", - actifF: "est paralysée", - fin: "n'est plus paralysé", - finF: "n'est plus paralysée", - msgSave: "ne plus être paralysé", + activation: "est paralys\xE9 : aucune action ni d\xE9placement possible", + activationF: "est paralys\xE9e : aucune action ni d\xE9placement possible", + actif: "est paralys\xE9", + actifF: "est paralys\xE9e", + fin: "n'est plus paralys\xE9", + finF: "n'est plus paralys\xE9e", + msgSave: "ne plus \xEAtre paralys\xE9", prejudiciable: true, visible: true }, peauDEcorce: { - activation: "donne à sa peau la consistance de l'écorce", - actif: "a la peau dure comme l'écorce", + activation: "donne \xE0 sa peau la consistance de l'\xE9corce", + actif: "a la peau dure comme l'\xE9corce", fin: "retrouve une peau normale", visible: true }, @@ -45054,36 +45640,36 @@ var COFantasy = COFantasy || function() { visible: true }, penombreTemp: { - activation: "ne voit plus très loin", - actif: "est dans la pénombre", + activation: "ne voit plus tr\xE8s loin", + actif: "est dans la p\xE9nombre", fin: "retrouve une vue normale", msgSave: "retrouver la vue", prejudiciable: true, }, peurEtourdi: { - activation: "prend peur: il peut fuir ou rester recroquevillé", - activationF: "prend peur: elle peut fuir ou rester recroquevillé", - actif: "est paralysé par la peur", - actifF: "est paralysée par la peur", - fin: "retrouve du courage et peut à nouveau agir", + activation: "prend peur: il peut fuir ou rester recroquevill\xE9", + activationF: "prend peur: elle peut fuir ou rester recroquevill\xE9", + actif: "est paralys\xE9 par la peur", + actifF: "est paralys\xE9e par la peur", + fin: "retrouve du courage et peut \xE0 nouveau agir", msgSave: "retrouver du courage", prejudiciable: true, visible: true }, protectionContreLesProjectiles: { activation: "gagne une protection contre les projectiles", - actif: "est protégé contre les projectiles", - actifF: "est protégée contre les projectiles", - fin: "n'est plus protégé contre les projectiles", - finF: "n'est plus protégée contre les projectiles", + actif: "est prot\xE9g\xE9 contre les projectiles", + actifF: "est prot\xE9g\xE9e contre les projectiles", + fin: "n'est plus prot\xE9g\xE9 contre les projectiles", + finF: "n'est plus prot\xE9g\xE9e contre les projectiles", visible: false, }, ralentiTemp: { - activation: "est ralenti : une seule action, pas d'action limitée", - activationF: "est ralentie : une seule action, pas d'action limitée", + activation: "est ralenti : une seule action, pas d'action limit\xE9e", + activationF: "est ralentie : une seule action, pas d'action limit\xE9e", actif: "est ralenti", actifF: "est ralentie", - msgSave: "ne plus être ralenti", + msgSave: "ne plus \xEAtre ralenti", fin: "n'est plus ralenti", finF: "n'est plus ralentie", prejudiciable: true, @@ -45091,23 +45677,23 @@ var COFantasy = COFantasy || function() { entrave: true }, rayonAffaiblissant: { - activation: "est touché par un rayon affaiblissant", - activationF: "est touchée par un rayon affaiblissant", + activation: "est touch\xE9 par un rayon affaiblissant", + activationF: "est touch\xE9e par un rayon affaiblissant", actif: "est sous l'effet d'un rayon affaiblissant", - msgSave: "ne plus être affaibli", + msgSave: "ne plus \xEAtre affaibli", fin: "n'est plus affaibli", finF: "n'est plus affaiblie", prejudiciable: true }, rituelAssure: { - activation: "passe un tour complet à préparer un sort", - actif: "a préparé un rituel assuré", + activation: "passe un tour complet \xE0 pr\xE9parer un sort", + actif: "a pr\xE9par\xE9 un rituel assur\xE9", fin: "", visible: false }, secoue: { - activation: "hésite un peu, il est secoué", - activationF: "hésite un peu, elle est secouée", + activation: "h\xE9site un peu, il est secou\xE9", + activationF: "h\xE9site un peu, elle est secou\xE9e", actif: "a un peu peur", fin: "retrouve du courage", msgSave: "retrouver du courage", @@ -45116,29 +45702,29 @@ var COFantasy = COFantasy || function() { }, secretsDeLAuDela: { activation: "contacte des esprits", - actif: "des esprits lui murmurent des secrets oubliés", + actif: "des esprits lui murmurent des secrets oubli\xE9s", fin: "les esprits repartent" }, souffleDeMort: { - activation: "est terrifié par la mort de son allié", - activationF: "est terrifiée par la mort de son allié", + activation: "est terrifi\xE9 par la mort de son alli\xE9", + activationF: "est terrifi\xE9e par la mort de son alli\xE9", actif: "ne peut agir suite au souffle de mort", fin: "retrouve ses esprits", - msgSave: "pouvoir agir malgré la mort de son allié", + msgSave: "pouvoir agir malgr\xE9 la mort de son alli\xE9", prejudiciable: true, visible: true, }, tremblementMineur: { activation: "Tremblement mineur", - actif: "est déséquilibré par le tremblement", - actifF: "est déséquilibrée par le tremblement", + actif: "est d\xE9s\xE9quilibr\xE9 par le tremblement", + actifF: "est d\xE9s\xE9quilibr\xE9e par le tremblement", fin: '', visible: false }, zoneDeVie: { activation: "enchante une zone autour de lui", activationF: "enchante une zone autour d'elle", - actif: "a créé une zone de vie", + actif: "a cr\xE9\xE9 une zone de vie", fin: "la zone de vie se termine", visible: true, generic: true, //pour pouvoir avoir plusieurs zones de vie @@ -45152,10 +45738,10 @@ var COFantasy = COFantasy || function() { prejudiciable: true }, assommeTemp: { - activation: "est assommé", - activationF: "est assommée", - actif: "est assommé", - actifF: "est assommée", + activation: "est assomm\xE9", + activationF: "est assomm\xE9e", + actif: "est assomm\xE9", + actifF: "est assomm\xE9e", fin: "reprend conscience", msgSave: "reprendre conscience", prejudiciable: true, @@ -45163,90 +45749,90 @@ var COFantasy = COFantasy || function() { }, nauseeuxTemp: { activation: "souffre de violentes douleurs au ventre", - actif: "est nauséeux, seul le mouvement est possible", - actifF: "est nauséeuse, seul le mouvement est possible", + actif: "est naus\xE9eux, seul le mouvement est possible", + actifF: "est naus\xE9euse, seul le mouvement est possible", fin: "se sent mieux", - msgSave: "ne plus être nauséeux", + msgSave: "ne plus \xEAtre naus\xE9eux", prejudiciable: true, visible: true }, invisibleTemp: { - activation: "disparaît", + activation: "dispara\xEEt", actif: "est invisible", - fin: "réapparaît", + fin: "r\xE9appara\xEEt", msgSave: "ne pas devenir invisible", visible: true }, aveugleManoeuvre: { - activation: "est aveuglé par la manoeuvre", - activationF: "est aveuglée par la manoeuvre", - actif: "a du mal à voir où sont ses adversaires", + activation: "est aveugl\xE9 par la manoeuvre", + activationF: "est aveugl\xE9e par la manoeuvre", + actif: "a du mal \xE0 voir o\xF9 sont ses adversaires", fin: "retrouve une vision normale", - msgSave: "voir à nouveau", + msgSave: "voir \xE0 nouveau", prejudiciable: true, visible: true }, bloqueManoeuvre: { - activation: "est bloqué par la manoeuvre", - activationF: "est bloquée par la manoeuvre", - actif: "est bloqué et ne peut pas se déplacer", - actifF: "est bloquée et ne peut pas se déplacer", - fin: "peut à nouveau se déplacer", - msgSave: "pouvoir se déplacer", + activation: "est bloqu\xE9 par la manoeuvre", + activationF: "est bloqu\xE9e par la manoeuvre", + actif: "est bloqu\xE9 et ne peut pas se d\xE9placer", + actifF: "est bloqu\xE9e et ne peut pas se d\xE9placer", + fin: "peut \xE0 nouveau se d\xE9placer", + msgSave: "pouvoir se d\xE9placer", prejudiciable: true, entrave: true }, diversionManoeuvre: { - activation: "est déconcentré", - activationF: "est déconcentrée", - actif: "a été perturbé par une diversion", - actifF: "a été perturbée par une diversion", + activation: "est d\xE9concentr\xE9", + activationF: "est d\xE9concentr\xE9e", + actif: "a \xE9t\xE9 perturb\xE9 par une diversion", + actifF: "a \xE9t\xE9 perturb\xE9e par une diversion", fin: "se reconcentre sur le combat", msgSave: "se reconcentrer sur le combat", prejudiciable: true, visible: true }, menaceManoeuvre: { - activation: "est menacé", - activationF: "est menacée", - actif: "a été menacé, risque de plus de DM", - actifF: "a été menacée, risque de plus de DM", + activation: "est menac\xE9", + activationF: "est menac\xE9e", + actif: "a \xE9t\xE9 menac\xE9, risque de plus de DM", + actifF: "a \xE9t\xE9 menac\xE9e, risque de plus de DM", fin: "n'est plus sous la menace", - msgSave: "ne plus être sous la menace", + msgSave: "ne plus \xEAtre sous la menace", prejudiciable: true, generic: true }, tenuADistanceManoeuvre: { - activation: "est tenu à distance", - activationF: "est tenue à distance", - actif: "est tenu à distance de son adversaire, il ne peut pas l'attaquer", - actifF: "est tenue à distance de son adversaire, elle ne peut pas l'attaquer", - fin: "peut à nouveau attaquer son adversaire", - msgSave: "pouvoir à nouveau attaquer son adversaire", + activation: "est tenu \xE0 distance", + activationF: "est tenue \xE0 distance", + actif: "est tenu \xE0 distance de son adversaire, il ne peut pas l'attaquer", + actifF: "est tenue \xE0 distance de son adversaire, elle ne peut pas l'attaquer", + fin: "peut \xE0 nouveau attaquer son adversaire", + msgSave: "pouvoir \xE0 nouveau attaquer son adversaire", prejudiciable: true, generic: true, visible: true, entrave: true }, epeeDansante: { - activation: "fait apparaître une lame d'énergie lumineuse", - actif: "contrôle une lame d'énergie lumineuse", - fin: "La lame d'énergie lumineuse disparaît", + activation: "fait appara\xEEtre une lame d'\xE9nergie lumineuse", + actif: "contr\xF4le une lame d'\xE9nergie lumineuse", + fin: "La lame d'\xE9nergie lumineuse dispara\xEEt", dm: true, visible: true }, rapiereDansante: { - activation: "fait apparaître une rapière d'énergie lumineuse", - actif: "contrôle une rapière d'énergie lumineuse", - fin: "La rapière d'énergie lumineuse disparaît", + activation: "fait appara\xEEtre une rapi\xE8re d'\xE9nergie lumineuse", + actif: "contr\xF4le une rapi\xE8re d'\xE9nergie lumineuse", + fin: "La rapi\xE8re d'\xE9nergie lumineuse dispara\xEEt", dm: true, visible: true }, putrefaction: { - activation: "vient de contracter une sorte de lèpre fulgurante", - actif: "est en pleine putréfaction", - fin: "La putréfaction s'arrête.", - msgSave: "résister à la putréfaction", + activation: "vient de contracter une sorte de l\xE8pre fulgurante", + actif: "est en pleine putr\xE9faction", + fin: "La putr\xE9faction s'arr\xEAte.", + msgSave: "r\xE9sister \xE0 la putr\xE9faction", prejudiciable: true, dm: true, visible: true @@ -45254,38 +45840,38 @@ var COFantasy = COFantasy || function() { forgeron: { activation: "enflamme son arme", actif: "a une arme en feu", - fin: "L'arme n'est plus enflammée.", + fin: "L'arme n'est plus enflamm\xE9e.", dm: true, generic: true, visible: true }, armeEnflammee: { activation: "voit son arme prendre feu", - actif: "a une arme enflammée", - fin: "L'arme n'est plus enflammée.", + actif: "a une arme enflamm\xE9e", + fin: "L'arme n'est plus enflamm\xE9e.", dm: true, generic: true, visible: true }, armeGlacee: { activation: "voit son arme se couvrir de givre", - actif: "a une arme glacée", - fin: "L'arme n'est plus gelée.", + actif: "a une arme glac\xE9e", + fin: "L'arme n'est plus gel\xE9e.", dm: true, generic: true, visible: true }, armesEnflammees: { activation: "voit ses armes prendre feu", - actif: "a des armes enflammées", - fin: "Les armes ne sont plus enflammées.", + actif: "a des armes enflamm\xE9es", + fin: "Les armes ne sont plus enflamm\xE9es.", dm: true, visible: true }, dotGen: { activation: "subit un effet", - actif: "subit régulièrement des dégâts", - fin: "ne subit plus ces effets de dégâts", + actif: "subit r\xE9guli\xE8rement des d\xE9g\xE2ts", + fin: "ne subit plus ces effets de d\xE9g\xE2ts", dm: true, prejudiciable: true, generic: true @@ -45293,7 +45879,7 @@ var COFantasy = COFantasy || function() { rechargeGen: { activation: "doit maintenant attendre un peu avant de pouvoir le refaire", actif: "attend avant de pouvoir refaire une action", - fin: "a récupéré", + fin: "a r\xE9cup\xE9r\xE9", generic: true }, dmgArme: { @@ -45306,15 +45892,15 @@ var COFantasy = COFantasy || function() { flou: { activation: "devient flou", activationF: "devient floue", - actif: "apparaît flou", - actifF: "apparaît floue", + actif: "appara\xEEt flou", + actifF: "appara\xEEt floue", fin: "redevient net", visible: true }, agrandissement: { - activation: "se met à grandir", - actif: "est vraiment très grand", - actifF: "est vraiment très grande", + activation: "se met \xE0 grandir", + actif: "est vraiment tr\xE8s grand", + actifF: "est vraiment tr\xE8s grande", fin: "retrouve sa taille normale", visible: true }, @@ -45331,24 +45917,24 @@ var COFantasy = COFantasy || function() { visible: true }, intangibleInvisible: { - activation: "disparaît", + activation: "dispara\xEEt", actif: "est intangible et invisible", - fin: "réapparaît", + fin: "r\xE9appara\xEEt", visible: true }, sousTension: { - activation: "se charge d'énergie électrique", - actif: "est chargé d'énergie électrique", - actifF: "est chargée d'énergie électrique", - fin: "n'est plus chargé d'énergie électrique", - finF: "n'est plus chargée d'énergie électrique", + activation: "se charge d'\xE9nergie \xE9lectrique", + actif: "est charg\xE9 d'\xE9nergie \xE9lectrique", + actifF: "est charg\xE9e d'\xE9nergie \xE9lectrique", + fin: "n'est plus charg\xE9 d'\xE9nergie \xE9lectrique", + finF: "n'est plus charg\xE9e d'\xE9nergie \xE9lectrique", dm: true, visible: false }, strangulation: { - activation: "commence à étouffer", - actif: "est étranglé", - actifF: "est étranglée", + activation: "commence \xE0 \xE9touffer", + actif: "est \xE9trangl\xE9", + actifF: "est \xE9trangl\xE9e", fin: "respire enfin", msgSave: "pouvoir respirer", prejudiciable: true, @@ -45358,7 +45944,7 @@ var COFantasy = COFantasy || function() { }, ombreMortelle: { activation: "voit son ombre s'animer et l'attaquer !", - actif: "est une ombre animée", + actif: "est une ombre anim\xE9e", fin: "retrouve une ombre normale", dm: true, visible: true @@ -45367,7 +45953,7 @@ var COFantasy = COFantasy || function() { activation: "voit un double translucide sortir de lui", activationF: "voit un double translucide sortir d'elle", actif: "est un double translucide", - fin: "le double disparaît", + fin: "le double dispara\xEEt", dm: true, visible: true }, @@ -45375,20 +45961,20 @@ var COFantasy = COFantasy || function() { activation: "n'entend plus rien", actif: "est totalement sourd", actifF: "est totalement sourde", - fin: "peut à nouveau entendre" + fin: "peut \xE0 nouveau entendre" }, danseIrresistible: { - activation: "se met à danser", - actif: "danse malgré lui", - actifF: "danse malgré elle", - fin: "s'arrête de danser", - msgSave: "s'arrêter de danser", + activation: "se met \xE0 danser", + actif: "danse malgr\xE9 lui", + actifF: "danse malgr\xE9 elle", + fin: "s'arr\xEAte de danser", + msgSave: "s'arr\xEAter de danser", prejudiciable: true, visible: true }, confusion: { - activation: "ne sait plus très bien ce qu'il fait là", - activationF: "ne sait plus très bien ce qu'elle fait là", + activation: "ne sait plus tr\xE8s bien ce qu'il fait l\xE0", + activationF: "ne sait plus tr\xE8s bien ce qu'elle fait l\xE0", actif: "est en pleine confusion", fin: "retrouve ses esprits", msgSave: "retrouver ses esprits", @@ -45396,16 +45982,16 @@ var COFantasy = COFantasy || function() { visible: true }, murDeForce: { - activation: "fait apparaître un mur de force", - actif: "en entouré d'un mur de force", - actifF: "en entourée d'un mur de force", - fin: "voit son mur de force disparaître", + activation: "fait appara\xEEtre un mur de force", + actif: "en entour\xE9 d'un mur de force", + actifF: "en entour\xE9e d'un mur de force", + fin: "voit son mur de force dispara\xEEtre", visible: true }, asphyxie: { - activation: "commence à manquer d'air", - actif: "étouffe", - fin: "peut à nouveau respirer", + activation: "commence \xE0 manquer d'air", + actif: "\xE9touffe", + fin: "peut \xE0 nouveau respirer", msgSave: "pouvoir respirer normalement", prejudiciable: true, seulementVivant: true, @@ -45416,11 +46002,11 @@ var COFantasy = COFantasy || function() { forceDeGeant: { activation: "devient plus fort", activationE: "devient plus forte", - actif: "a une force de géant", + actif: "a une force de g\xE9ant", fin: "retrouve sa force normale" }, saignementsSang: { - activation: "commence à saigner du nez, des oreilles et des yeux", + activation: "commence \xE0 saigner du nez, des oreilles et des yeux", actif: "saigne de tous les orifices du visage", fin: "ne saigne plus", msgSave: "ne plus saigner", @@ -45430,70 +46016,70 @@ var COFantasy = COFantasy || function() { visible: true }, encaisserUnCoup: { - activation: "se place de façon à dévier un coup sur son armure", - actif: "est placé de façon à dévier un coup", - actifF: "est placée de façon à dévier un coup", + activation: "se place de fa\xE7on \xE0 d\xE9vier un coup sur son armure", + actif: "est plac\xE9 de fa\xE7on \xE0 d\xE9vier un coup", + actifF: "est plac\xE9e de fa\xE7on \xE0 d\xE9vier un coup", fin: "n'est plus en position pour encaisser un coup" }, seulContreTous: { - activation: "se place de façon à faire face à tous ses adversaires", + activation: "se place de fa\xE7on \xE0 faire face \xE0 tous ses adversaires", actif: "riposte", - fin: "ne fait plus face à tous ses adversaires" + fin: "ne fait plus face \xE0 tous ses adversaires" }, absorberUnCoup: { - activation: "se prépare à absorber un coup avec son bouclier", - actif: "est prêt à absorber un coup avec son bouclier", - actifF: "est prête à absorber un coup avec son bouclier", + activation: "se pr\xE9pare \xE0 absorber un coup avec son bouclier", + actif: "est pr\xEAt \xE0 absorber un coup avec son bouclier", + actifF: "est pr\xEAte \xE0 absorber un coup avec son bouclier", fin: "n'est plus en position de prendre le prochain coup sur son bouclier" }, absorberUnSort: { - activation: "se prépare à absorber un sort avec son bouclier", - actif: "est prêt à absorber un sort avec son bouclier", - actifF: "est prête à absorber un sort avec son bouclier", - fin: "n'est plus en position de se protéger d'un sort avec son bouclier" + activation: "se pr\xE9pare \xE0 absorber un sort avec son bouclier", + actif: "est pr\xEAt \xE0 absorber un sort avec son bouclier", + actifF: "est pr\xEAte \xE0 absorber un sort avec son bouclier", + fin: "n'est plus en position de se prot\xE9ger d'un sort avec son bouclier" }, nueeDInsectes: { - activation: "est attaqué par une nuée d'insectes", - activationF: "est attaquée par une nuée d'insectes", - actif: "est entouré d'une nuée d'insectes", - actifF: "est entourée d'une nuée d'insectes", - fin: "est enfin débarassé des insectes", - finF: "est enfin débarassée des insectes", - msgSave: "se débarasser des insectes", + activation: "est attaqu\xE9 par une nu\xE9e d'insectes", + activationF: "est attaqu\xE9e par une nu\xE9e d'insectes", + actif: "est entour\xE9 d'une nu\xE9e d'insectes", + actifF: "est entour\xE9e d'une nu\xE9e d'insectes", + fin: "est enfin d\xE9barass\xE9 des insectes", + finF: "est enfin d\xE9barass\xE9e des insectes", + msgSave: "se d\xE9barasser des insectes", prejudiciable: true, dm: true, visible: true }, nueeDeCriquets: { - activation: "est attaqué par une nuée de criquets", - activationF: "est attaquée par une nuée de criquets", - actif: "est entouré d'une nuée de criquets", - actifF: "est entourée d'une nuée de criquets", - fin: "est enfin débarassé des criquets", - finF: "est enfin débarassée des criquets", - msgSave: "se débarasser des criquets", + activation: "est attaqu\xE9 par une nu\xE9e de criquets", + activationF: "est attaqu\xE9e par une nu\xE9e de criquets", + actif: "est entour\xE9 d'une nu\xE9e de criquets", + actifF: "est entour\xE9e d'une nu\xE9e de criquets", + fin: "est enfin d\xE9barass\xE9 des criquets", + finF: "est enfin d\xE9barass\xE9e des criquets", + msgSave: "se d\xE9barasser des criquets", prejudiciable: true, dm: true, visible: true }, nueeDeScorpions: { - activation: "est attaqué par une nuée de scorpions", - activationF: "est attaquée par une nuée de scorpions", - actif: "est entouré d'une nuée de scorpions", - actifF: "est entourée d'une nuée de scorpions", - fin: "est enfin débarassé des scorpions", - finF: "est enfin débarassée des scorpions", - msgSave: "se débarasser des scorpions", + activation: "est attaqu\xE9 par une nu\xE9e de scorpions", + activationF: "est attaqu\xE9e par une nu\xE9e de scorpions", + actif: "est entour\xE9 d'une nu\xE9e de scorpions", + actifF: "est entour\xE9e d'une nu\xE9e de scorpions", + fin: "est enfin d\xE9barass\xE9 des scorpions", + finF: "est enfin d\xE9barass\xE9e des scorpions", + msgSave: "se d\xE9barasser des scorpions", prejudiciable: true, dm: true, visible: true }, toiles: { - activation: "voit des toiles d'araignées apparaître tout autour", - actif: "est bloqué par des toiles d'araignées", - actifF: "est bloquée par des toiles d'araignées", - fin: "se libère des toiles", - msgSave: "se libérer des toiles", + activation: "voit des toiles d'araign\xE9es appara\xEEtre tout autour", + actif: "est bloqu\xE9 par des toiles d'araign\xE9es", + actifF: "est bloqu\xE9e par des toiles d'araign\xE9es", + fin: "se lib\xE8re des toiles", + msgSave: "se lib\xE9rer des toiles", prejudiciable: true, statusMarker: 'cobweb', visible: true, @@ -45501,70 +46087,70 @@ var COFantasy = COFantasy || function() { }, prisonVegetale: { activation: "voit des plantes pousser et s'enrouler autour de ses jambes", - actif: "est bloqué par des plantes", - actifF: "est bloquée par des plantes", - fin: "se libère des plantes", - msgSave: "se libérer des plantes", + actif: "est bloqu\xE9 par des plantes", + actifF: "est bloqu\xE9e par des plantes", + fin: "se lib\xE8re des plantes", + msgSave: "se lib\xE9rer des plantes", prejudiciable: true, statusMarker: 'green', visible: true, entrave: true }, protectionContreLesElements: { - activation: "lance un sort de protection contre les éléments", - actif: "est protégé contre les éléments", - actifF: "est protégée contre les éléments", - fin: "n'est plus protégé contre les éléments", - finF: "n'est plus protégée contre les éléments" + activation: "lance un sort de protection contre les \xE9l\xE9ments", + actif: "est prot\xE9g\xE9 contre les \xE9l\xE9ments", + actifF: "est prot\xE9g\xE9e contre les \xE9l\xE9ments", + fin: "n'est plus prot\xE9g\xE9 contre les \xE9l\xE9ments", + finF: "n'est plus prot\xE9g\xE9e contre les \xE9l\xE9ments" }, masqueMortuaire: { activation: "prend l'apparence de la mort", - actif: "semble mort et animé", - actifF: "semble morte et animée", + actif: "semble mort et anim\xE9", + actifF: "semble morte et anim\xE9e", fin: "retrouve une apparence de vivant", visible: true }, masqueMortuaireAmeLiee: { - activation: "est lié à une apparence de la mort", - activationF: "est liée à une apparence de la mort", + activation: "est li\xE9 \xE0 une apparence de la mort", + activationF: "est li\xE9e \xE0 une apparence de la mort", actif: "semble en lien avec la mort", fin: "n'est plus en lien avec la mort" }, armeBrulante: { activation: "sent son arme lui chauffer la main", - actif: "se brûle la main sur son arme", + actif: "se br\xFBle la main sur son arme", fin: "sent son arme refroidir", dm: true }, armureBrulante: { activation: "sent son armure chauffer", - actif: "brûle dans son armure", + actif: "br\xFBle dans son armure", fin: "sent son armure refroidir", dm: true }, masqueDuPredateur: { - activation: "prend les traits d'un prédateur", - actif: "a les traits d'un prédateur", + activation: "prend les traits d'un pr\xE9dateur", + actif: "a les traits d'un pr\xE9dateur", fin: "redevient normal", finF: "redevient normale", visible: true }, masqueDuPredateurAmeLiee: { - activation: "est lié à une âme de prédateur", - activationF: "est liée à une âme de prédateur", - actif: "bénéficie d'un lien avec un prédateur", - fin: "le lien disparaît", + activation: "est li\xE9 \xE0 une \xE2me de pr\xE9dateur", + activationF: "est li\xE9e \xE0 une \xE2me de pr\xE9dateur", + actif: "b\xE9n\xE9ficie d'un lien avec un pr\xE9dateur", + fin: "le lien dispara\xEEt", visible: false }, aspectDeLaSuccube: { - activation: "acquiert une beauté fascinante", - actif: "est d'une beauté fascinante", - fin: "retrouve sa beauté habituelle", + activation: "acquiert une beaut\xE9 fascinante", + actif: "est d'une beaut\xE9 fascinante", + fin: "retrouve sa beaut\xE9 habituelle", visible: true }, aspectDuDemon: { - activation: "prend l’apparence d’un démon", - actif: "a l’apparence d’un démon", + activation: "prend l\x2019apparence d\x2019un d\xE9mon", + actif: "a l\x2019apparence d\x2019un d\xE9mon", fin: "retrouve son apparence habituelle", visible: true }, @@ -45574,124 +46160,125 @@ var COFantasy = COFantasy || function() { fin: "retrouve un sang normal" }, armeSecreteBarde: { - activation: "est déstabilisé", - activationF: "est déstabilisée", - actif: "est déstabilisé par une action de charme", - actifF: "est déstabilisée par une action de charme", + activation: "est d\xE9stabilis\xE9", + activationF: "est d\xE9stabilis\xE9e", + actif: "est d\xE9stabilis\xE9 par une action de charme", + actifF: "est d\xE9stabilis\xE9e par une action de charme", fin: "retrouve ses esprits", msgSave: "retrouver ses esprits", prejudiciable: true, visible: true }, regeneration: { - activation: "commence à se régénérer", - actif: "se régénère", - fin: "a fini de se régénérer", + activation: "commence \xE0 se r\xE9g\xE9n\xE9rer", + actif: "se r\xE9g\xE9n\xE8re", + fin: "a fini de se r\xE9g\xE9n\xE9rer", soins: true, visible: true }, arbreAnime: { - activation: "commence à bouger", - actif: "est un arbre animé", + activation: "commence \xE0 bouger", + actif: "est un arbre anim\xE9", fin: "redevient un arbre ordinaire", visible: true }, objetAnime: { - activation: "commence à bouger", - actif: "est un objet animé", + activation: "commence \xE0 bouger", + actif: "est un objet anim\xE9", fin: "redevient un objet ordinaire", visible: true }, magnetisme: { - activation: "contrôle le magnétisme", - actif: "contrôle le magnétisme", - fin: "relache son contrôle du magnétisme" + activation: "contr\xF4le le magn\xE9tisme", + actif: "contr\xF4le le magn\xE9tisme", + fin: "relache son contr\xF4le du magn\xE9tisme" }, hate: { - activation: "voit son métabolisme s'accélérer", + activation: "voit son m\xE9tabolisme s'acc\xE9l\xE9rer", actif: "peut faire une action de plus par tour", - fin: "retrouve un métabolisme normal (plus d'action supplémentaire)" + fin: "retrouve un m\xE9tabolisme normal (plus d'action suppl\xE9mentaire)" }, ailesCelestes: { - activation: "sent des ailes célestes lui pousser dans le dos", - actif: "possède des ailes célestes", - fin: "n'a plus d'aile céleste. Espérons qu'il était au sol...", - finF: "n'a plus d'aile céleste. Espérons qu'elle était au sol...", + activation: "sent des ailes c\xE9lestes lui pousser dans le dos", + actif: "poss\xE8de des ailes c\xE9lestes", + fin: "n'a plus d'aile c\xE9leste. Esp\xE9rons qu'il \xE9tait au sol...", + finF: "n'a plus d'aile c\xE9leste. Esp\xE9rons qu'elle \xE9tait au sol...", visible: true }, sanctuaire: { - activation: "lance un sort de sanctuaire", - actif: "est protégé par un sanctuaire", - actifF: "est protégée par un sanctuaire", - fin: "n'est plus protégé par le sanctuaire", - finF: "n'est plus protégée par le sanctuaire" + activation: "est prot\xE9g\xE9 par un sanctuaire", + activationF: "est prot\xE9g\xE9e par un sanctuaire", + actif: "est prot\xE9g\xE9 par un sanctuaire", + actifF: "est prot\xE9g\xE9e par un sanctuaire", + fin: "n'est plus prot\xE9g\xE9 par le sanctuaire", + finF: "n'est plus prot\xE9g\xE9e par le sanctuaire" }, rechargeSouffle: { activation: "doit maintenant attendre un peu avant de pouvoir le refaire", actif: "attend avant de pouvoir refaire un souffle", - fin: "a récupéré" + fin: "a r\xE9cup\xE9r\xE9" }, paralysieRoublard: { - activation: "est paralysé par la douleur", - activationF: "est paralysée par la douleur", - actif: "ne peut pas attaquer ni se déplacer", - fin: "peut à nouveau attaquer et se déplacer", - msgSave: "résister à la douleur", + activation: "est paralys\xE9 par la douleur", + activationF: "est paralys\xE9e par la douleur", + actif: "ne peut pas attaquer ni se d\xE9placer", + fin: "peut \xE0 nouveau attaquer et se d\xE9placer", + msgSave: "r\xE9sister \xE0 la douleur", prejudiciable: true, seulementVivant: true, visible: true, entrave: true }, mutationOffensive: { - activation: "échange une partie de son corps avec celle d'une créature monstrueuse", - actif: "possède un appendice monstrueux", + activation: "\xE9change une partie de son corps avec celle d'une cr\xE9ature monstrueuse", + actif: "poss\xE8de un appendice monstrueux", fin: "retrouve un corps normal", visible: true }, formeDArbre: { activation: "se transorme en arbre", - actif: "est transformé en arbre", - actifF: "est transformée en arbre", + actif: "est transform\xE9 en arbre", + actifF: "est transform\xE9e en arbre", fin: "retrouve sa forme normale", visible: true }, statueDeBois: { activation: "se transforme en statue de bois", - actif: "est transformé en statue de bois", - actifF: "est transformée en statue de bois", + actif: "est transform\xE9 en statue de bois", + actifF: "est transform\xE9e en statue de bois", fin: "retrouve sa forme normale", - msgSave: "ne plus être une statue de bois", + msgSave: "ne plus \xEAtre une statue de bois", prejudiciable: true, visible: true }, clignotement: { - activation: "disparaît, puis réapparaît", + activation: "dispara\xEEt, puis r\xE9appara\xEEt", actif: "clignote", - fin: "ne disparaît plus", + fin: "ne dispara\xEEt plus", visible: true }, agitAZeroPV: { - activation: "continue à agir malgré les blessures", - actif: "devrait être à terre", + activation: "continue \xE0 agir malgr\xE9 les blessures", + actif: "devrait \xEAtre \xE0 terre", fin: "subit l'effet de ses blessures", visible: true }, predateurConjure: { - activation: "apparaît depuis un autre plan", - actif: "est un prédateur conjuré", - fin: "disparaît", + activation: "appara\xEEt depuis un autre plan", + actif: "est un pr\xE9dateur conjur\xE9", + fin: "dispara\xEEt", dm: true }, champDeProtection: { - activation: "devient protégé par un champ télékinétique", - actif: "est protégé par un champ télékinétique", - actifF: "est protégée par un champ télékinétique", + activation: "devient prot\xE9g\xE9 par un champ t\xE9l\xE9kin\xE9tique", + actif: "est prot\xE9g\xE9 par un champ t\xE9l\xE9kin\xE9tique", + actifF: "est prot\xE9g\xE9e par un champ t\xE9l\xE9kin\xE9tique", fin: "n'est plus sous l'effet d'un champ de protection", }, attaqueArmeeConjuree: { - activation: "se bat contre une armée conjurée", - actif: "se bat contre une armée conjurée", - fin: "ne se bat plus contre l'armée conjurée" + activation: "se bat contre une arm\xE9e conjur\xE9e", + actif: "se bat contre une arm\xE9e conjur\xE9e", + fin: "ne se bat plus contre l'arm\xE9e conjur\xE9e" }, rechargeDuKiai: { activation: "pousse un kiai", @@ -45701,71 +46288,71 @@ var COFantasy = COFantasy || function() { memePasMalBonus: { activation: "enrage suite au coup critique", actif: "a subit un coup critique", - fin: "ne bénéficie plus des effets de même pas mal" + fin: "ne b\xE9n\xE9ficie plus des effets de m\xEAme pas mal" }, attaqueRisquee: { - activation: "fait une attaque risquée", - actif: "s'est mis en danger par une attaque risquée", - fin: "retrouve une position moins risquée", + activation: "fait une attaque risqu\xE9e", + actif: "s'est mis en danger par une attaque risqu\xE9e", + fin: "retrouve une position moins risqu\xE9e", }, peauDePierreMag: { activation: "transforme sa peau en pierre", - actif: "voit ses dégâts réduits par sa Peau de pierre", + actif: "voit ses d\xE9g\xE2ts r\xE9duits par sa Peau de pierre", fin: "retrouve sa peau normale", visible: true }, expose: { activation: "s'expose aux attaques de sa cible", - actif: "est exposé aux attaques de son adversaire", - actifF: "est exposée aux attaques de son adversaire", - fin: "n'est plus exposé", - finF: "n'est plus exposée", + actif: "est expos\xE9 aux attaques de son adversaire", + actifF: "est expos\xE9e aux attaques de son adversaire", + fin: "n'est plus expos\xE9", + finF: "n'est plus expos\xE9e", msgSave: "ne plus s'exposer", prejudiciable: true }, effetRetarde: { - activation: "il va bientôt se produire quelque chose", - actif: "s'attend à un effet", - fin: "effet retardé activé", + activation: "il va bient\xF4t se produire quelque chose", + actif: "s'attend \xE0 un effet", + fin: "effet retard\xE9 activ\xE9", generic: true, prejudiciable: true }, messageRetarde: { - activation: "il va bientôt se produire quelque chose", - actif: "s'attend à un effet", - fin: "effet activé", + activation: "il va bient\xF4t se produire quelque chose", + actif: "s'attend \xE0 un effet", + fin: "effet activ\xE9", generic: true }, detectionDeLInvisible: { - activation: "voit les choses invibles et cachées", - actif: "détecte l'invisible", + activation: "voit les choses invibles et cach\xE9es", + actif: "d\xE9tecte l'invisible", fin: "ne voit plus les choses invisibles", }, bonusAttaqueTemp: { activation: "affecte son attaque", - actif: "a son attaque affectée", + actif: "a son attaque affect\xE9e", fin: "retrouve son attaque normale", }, enerve: { - activation: "est énervé par ces railleries", - activationF: "est énervée par ces railleries", - actif: "est énervé", - actifF: "est énervée", + activation: "est \xE9nerv\xE9 par ces railleries", + activationF: "est \xE9nerv\xE9e par ces railleries", + actif: "est \xE9nerv\xE9", + actifF: "est \xE9nerv\xE9e", fin: "retrouve son calme", msgSave: "retrouver son calme", prejudiciable: true, visible: true }, cercleDeProtection: { - activation: "est protégé par le Cercle de protection", - activationF: "est protégée par le Cercle de protection", + activation: "est prot\xE9g\xE9 par le Cercle de protection", + activationF: "est prot\xE9g\xE9e par le Cercle de protection", actif: "est dans le Cercle de protection", fin: "sort du Cercle de protection", }, tenebres: { - activation: "lance un sort de Ténèbres", - actif: "maintient un sort de Ténèbres", - fin: "les ténèbres se dissipent", + activation: "lance un sort de T\xE9n\xE8bres", + actif: "maintient un sort de T\xE9n\xE8bres", + fin: "les t\xE9n\xE8bres se dissipent", visible: true }, brumes: { @@ -45775,12 +46362,12 @@ var COFantasy = COFantasy || function() { visible: true }, progresserACouvert: { - activation: "est à couvert de bouclier", - actif: "est à couvert de bouclier", - fin: "n'est plus à couvert de bouclier" + activation: "est \xE0 couvert de bouclier", + actif: "est \xE0 couvert de bouclier", + fin: "n'est plus \xE0 couvert de bouclier" }, cyclone: { - activation: "se transforme en tourbillon de matière élémentaire", + activation: "se transforme en tourbillon de mati\xE8re \xE9l\xE9mentaire", actif: "est en cyclone", fin: "retrouve sa forme habituelle", visible: true @@ -45791,57 +46378,57 @@ var COFantasy = COFantasy || function() { fin: "voit le temps reprendre son cours normal", }, armeeDesMorts: { - activation: "invoque d'innombrables squelettes émergeant du sol", + activation: "invoque d'innombrables squelettes \xE9mergeant du sol", actif: "invoque d'innombrables squelettes", fin: "laisse les morts en paix", visible: true }, demonInvoque: { - activation: "apparaît depuis un autre plan", - actif: "est un démon invoqué", - fin: "disparaît", + activation: "appara\xEEt depuis un autre plan", + actif: "est un d\xE9mon invoqu\xE9", + fin: "dispara\xEEt", dm: true }, degradationZombie: { - activation: "se relève d'entre les morts", - actif: "est un zombie animé", - fin: "tombe en poussière", + activation: "se rel\xE8ve d'entre les morts", + actif: "est un zombie anim\xE9", + fin: "tombe en poussi\xE8re", dm: true }, hemorragie: { - activation: "saigne à la moindre blessure", - actif: "saigne à la moindre blessure", - fin: "soigne son hémorragie", - msgSave: "guérir de son hémorragie", + activation: "saigne \xE0 la moindre blessure", + actif: "saigne \xE0 la moindre blessure", + fin: "soigne son h\xE9morragie", + msgSave: "gu\xE9rir de son h\xE9morragie", prejudiciable: true }, lienDeSang: { - activation: "est lié par le sang", - activationF: "est liée par le sang", + activation: "est li\xE9 par le sang", + activationF: "est li\xE9e par le sang", actif: "a un lien de sang", fin: "perd son lien de sang", - msgSave: "ne plus être lié par le sang", + msgSave: "ne plus \xEAtre li\xE9 par le sang", prejudiciable: true }, tenirADistance: { - activation: "utilise son allonge pour tenir ses ennemis à distance", - actif: "utilise son allonge pour tenir ses ennemis à distance", - fin: "ne tient plus ses ennemis à distance" + activation: "utilise son allonge pour tenir ses ennemis \xE0 distance", + actif: "utilise son allonge pour tenir ses ennemis \xE0 distance", + fin: "ne tient plus ses ennemis \xE0 distance" }, reactionViolente: { - activation: "est pris de folie et attaque la personne qui s'est moquée de lui", - activationF: "est prise de folie et attaque la personne qui s'est moquée d'elle", - actif: "a une réaction violente et doit attaquer", + activation: "est pris de folie et attaque la personne qui s'est moqu\xE9e de lui", + activationF: "est prise de folie et attaque la personne qui s'est moqu\xE9e d'elle", + actif: "a une r\xE9action violente et doit attaquer", fin: "reprend son calme", - msgSave: "résister à la provocation", + msgSave: "r\xE9sister \xE0 la provocation", prejudiciable: true, }, poisonAffaiblissantLatent: { - activation: "sent qu'un poison commence à se répandre dans ses veines", - actif: "est empoisonné, mais l'effet du poison ne se fait pas encore sentir", - actifF: "est empoisonnée, mais l'effet du poison ne se fait pas encore sentir", + 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ésister au poison", + msgSave: "r\xE9sister au poison", prejudiciable: true, seulementVivant: true, }, @@ -45882,23 +46469,23 @@ var COFantasy = COFantasy || function() { return (patternAttributEffetsTemp.test(name)); } - //On sait déjà que le nom a passé le test estEffetTemp + //On sait d\xE9j\xE0 que le nom a pass\xE9 le test estEffetTemp function effetTempOfAttribute(attr) { let ef = attr.get('name'); if (ef === undefined || messageEffetTemp[ef]) return ef; - //D'abord on enlève le nom du token + //D'abord on enl\xE8ve le nom du token let pu = ef.indexOf('_'); if (pu > 0) { ef = ef.substring(0, pu); if (messageEffetTemp[ef]) return ef; } - //Ensuite on enlève les parties entre parenthèse pour les effets génériques + //Ensuite on enl\xE8ve les parties entre parenth\xE8se pour les effets g\xE9n\xE9riques pu = ef.indexOf('('); if (pu > 0) { ef = ef.substring(0, pu); if (messageEffetTemp[ef]) return ef; } - error("Impossible de déterminer l'effet correspondant à " + ef, attr); + error("Impossible de d\xE9terminer l'effet correspondant \xE0 " + ef, attr); } function messageOfEffetTemp(effetC) { @@ -45910,61 +46497,61 @@ var COFantasy = COFantasy || function() { res = messageEffetTemp[ef]; return res; } - error("Effet temporaire non trouvé", effetC); + error("Effet temporaire non trouv\xE9", effetC); } const messageEffetCombat = { a0PVDepuis: { - activation: "est à 0 PV", - actif: "est à 0 PV", + activation: "est \xE0 0 PV", + actif: "est \xE0 0 PV", fin: "" }, armureMagique: { - activation: "est entouré d'un halo magique", - activationF: "est entourée d'un halo magique", - actif: "est protégé par une armure magique", - actifF: "est protégée par une armure magique", - fin: "n'est plus entouré d'un halo magique", - finF: "n'est plus entourée d'un halo magique" + activation: "est entour\xE9 d'un halo magique", + activationF: "est entour\xE9e d'un halo magique", + actif: "est prot\xE9g\xE9 par une armure magique", + actifF: "est prot\xE9g\xE9e par une armure magique", + fin: "n'est plus entour\xE9 d'un halo magique", + finF: "n'est plus entour\xE9e d'un halo magique" }, armureDuMage: { - activation: "fait apparaître un nuage magique argenté qui le protège", - activationF: "fait apparaître un nuage magique argenté qui la protège", - actif: "est entouré d'une armure du mage", - actifF: "est entourée d'une armure du mage", + activation: "fait appara\xEEtre un nuage magique argent\xE9 qui le prot\xE8ge", + activationF: "fait appara\xEEtre un nuage magique argent\xE9 qui la prot\xE8ge", + actif: "est entour\xE9 d'une armure du mage", + actifF: "est entour\xE9e d'une armure du mage", fin: "n'a plus son armure du mage" }, armureDEau: { - activation: "fait apparaître une couche d'eau de quelques centimètres qui le protège", - activationF: "fait apparaître une couche d'eau de quelques centimètres qui la protège", - actif: "est entouré d'une armure d'eau'", - actifF: "est entourée d'une armure d'eau'", + activation: "fait appara\xEEtre une couche d'eau de quelques centim\xE8tres qui le prot\xE8ge", + activationF: "fait appara\xEEtre une couche d'eau de quelques centim\xE8tres qui la prot\xE8ge", + actif: "est entour\xE9 d'une armure d'eau'", + actifF: "est entour\xE9e d'une armure d'eau'", fin: "n'a plus son armure d'eau'" }, armeDArgent: { - activation: "crée une arme d'argent et de lumière", - actif: "possède une arme d'argent et de lumière", - fin: "ne possède plus d'arme d'argent et de lumière", + activation: "cr\xE9e une arme d'argent et de lumi\xE8re", + actif: "poss\xE8de une arme d'argent et de lumi\xE8re", + fin: "ne poss\xE8de plus d'arme d'argent et de lumi\xE8re", dm: true }, attaqueAOutrance: { - activation: "attaque à outrance", - actif: "attaque à outrance", + activation: "attaque \xE0 outrance", + actif: "attaque \xE0 outrance", fin: "attaque normalement", }, - bonusInitEmbuscade: { //Effet interne pour la capacité Surveillance + 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: "" }, criDeGuerre: { activation: "pousse son cri de guerre", - actif: "a effrayé ses adversaires", + actif: "a effray\xE9 ses adversaires", fin: "" }, criDuPredateur: { activation: "pousse un hurlement effrayant", - actif: "a libéré son âme de prédateur", + actif: "a lib\xE9r\xE9 son \xE2me de pr\xE9dateur", fin: "" }, danseDesLames: { @@ -45973,22 +46560,22 @@ var COFantasy = COFantasy || function() { fin: "termine sa danse des lames" }, detournerLeRegard: { - activation: "détourne le regard", - actif: "détourne le regard", + activation: "d\xE9tourne le regard", + actif: "d\xE9tourne le regard", fin: "regarde normalement", }, enflamme: { activation: "prend feu !", actif: "est en feu", - fin: "les flammes s'éteignent", + fin: "les flammes s'\xE9teignent", dm: true, statusMarker: 'red', }, enrage: { - activation: "devient enragé", - activationF: "devient enragée", - actif: "est enragé", - actifF: "est enragée", + activation: "devient enrag\xE9", + activationF: "devient enrag\xE9e", + actif: "est enrag\xE9", + actifF: "est enrag\xE9e", fin: "retrouve son calme", msgSave: "retrouver son calme", }, @@ -45999,17 +46586,17 @@ var COFantasy = COFantasy || function() { fin: "retrouve son calme" }, protectionContreLeMal: { - activation: "reçoit une bénédiction de protection contre le mal", - actif: "est protégé contre le mal", - actifF: "est protégée contre le mal", - fin: "n'est plus protégé contre le mal", - finF: "n'est plus protégée contre le mal", + activation: "re\xE7oit une b\xE9n\xE9diction de protection contre le mal", + actif: "est prot\xE9g\xE9 contre le mal", + actifF: "est prot\xE9g\xE9e contre le mal", + fin: "n'est plus prot\xE9g\xE9 contre le mal", + finF: "n'est plus prot\xE9g\xE9e contre le mal", }, putrefactionOutreTombe: { activation: "sent ses chairs pourrir", - actif: "subit le contrecoup d'une putréfaction", - fin: "se remet de la putréfaction", - msgSave: "ne plus être putréfié", + actif: "subit le contrecoup d'une putr\xE9faction", + fin: "se remet de la putr\xE9faction", + msgSave: "ne plus \xEAtre putr\xE9fi\xE9", prejudiciable: true, dm: true }, @@ -46031,8 +46618,8 @@ var COFantasy = COFantasy || function() { fin: '' }, defiSamourai: { - activation: "lance un défi", - actif: "a lancé un défi", + activation: "lance un d\xE9fi", + actif: "a lanc\xE9 un d\xE9fi", fin: '' }, agrippe: { @@ -46041,12 +46628,12 @@ var COFantasy = COFantasy || function() { fin: "lache sa cible" }, estAgrippePar: { - activation: "est agrippé", - activationF: "est agrippée", - actif: "est agrippé", - actifF: "est agrippée", - fin: "se libère", - msgSave: "se libérer", + activation: "est agripp\xE9", + activationF: "est agripp\xE9e", + actif: "est agripp\xE9", + actifF: "est agripp\xE9e", + fin: "se lib\xE8re", + msgSave: "se lib\xE9rer", entrave: true }, devore: { @@ -46059,8 +46646,8 @@ var COFantasy = COFantasy || function() { activationF: "est saisie", actif: "est saisi", actifF: "est saisie", - fin: "se libère", - msgSave: "se libérer", + fin: "se lib\xE8re", + msgSave: "se lib\xE9rer", entrave: true }, ecrase: { @@ -46073,34 +46660,34 @@ var COFantasy = COFantasy || function() { activationF: "est saisie", actif: "est saisi", actifF: "est saisie", - fin: "se libère", - msgSave: "se libérer", + fin: "se lib\xE8re", + msgSave: "se lib\xE9rer", entrave: true }, aGobe: { activation: "avale sa cible", - actif: "a avalé une créature vivante", - fin: "digère sa cible" + actif: "a aval\xE9 une cr\xE9ature vivante", + fin: "dig\xE8re sa cible" }, estGobePar: { - activation: "est avalé", - activationF: "est avalée", - actif: "est dans le ventre d'une créature", + activation: "est aval\xE9", + activationF: "est aval\xE9e", + actif: "est dans le ventre d'une cr\xE9ature", fin: "fin de la digestion, sort du ventre", msgSave: "sortir du ventre", entrave: true }, inconfort: { - activation: "commence à être gêné par son armure", - activationF: "commence à être gênée par son armure", - actif: "est gêné par son armure", - actifF: "est gênée par son armure", - fin: "réajuste son armure", + activation: "commence \xE0 \xEAtre g\xEAn\xE9 par son armure", + activationF: "commence \xE0 \xEAtre g\xEAn\xE9e par son armure", + actif: "est g\xEAn\xE9 par son armure", + actifF: "est g\xEAn\xE9e par son armure", + fin: "r\xE9ajuste son armure", }, noyade: { - activation: "commence à se noyer", + activation: "commence \xE0 se noyer", actif: "se noie", - fin: "peut à nouveau respirer", + fin: "peut \xE0 nouveau respirer", msgSave: "surnager", prejudiciable: true, seulementVivant: true, @@ -46108,8 +46695,8 @@ var COFantasy = COFantasy || function() { visible: true }, blessureQuiSaigne: { - activation: "reçoit une blessure qui saigne", - actif: "saigne à cause d'une blessure", + activation: "re\xE7oit une blessure qui saigne", + actif: "saigne \xE0 cause d'une blessure", fin: "saigne beaucoup moins", msgSave: "ne plus saigner", prejudiciable: true, @@ -46117,10 +46704,10 @@ var COFantasy = COFantasy || function() { }, poisonAffaiblissant: { activation: "sent le poison ralentir ses mouvements", - actif: "est empoisonné", - actifF: "est empoisonnée", + actif: "est empoisonn\xE9", + actifF: "est empoisonn\xE9e", fin: "le poison n'agit plus", - msgSave: "résister au poison", + msgSave: "r\xE9sister au poison", prejudiciable: true, seulementVivant: true, }, @@ -46142,16 +46729,16 @@ var COFantasy = COFantasy || function() { function effetCombatOfAttribute(attr) { let ef = attr.get('name'); if (ef === undefined || messageEffetCombat[ef]) return ef; - //D'abord on enlève le nom du token + //D'abord on enl\xE8ve le nom du token let pu = ef.indexOf('_'); if (pu > 0) { ef = ef.substring(0, pu); if (messageEffetCombat[ef]) return ef; } - error("Impossible de déterminer l'effet correspondant à " + ef, attr); + error("Impossible de d\xE9terminer l'effet correspondant \xE0 " + ef, attr); } - // Si un effet est prejudiciable, enlevé par délivrance + // Si un effet est prejudiciable, enlev\xE9 par d\xE9livrance const messageEffetIndetermine = { armesNaturelles: { activation: "se fait pousser griffes et crocs", @@ -46172,29 +46759,29 @@ var COFantasy = COFantasy || function() { }, constructionTailleHumaine: { activation: "rentre dans une construction de taille humaine.", - actif: "est un peu à l'étroit, le bâtiment est trop petit", + actif: "est un peu \xE0 l'\xE9troit, le b\xE2timent est trop petit", fin: "sort de la construction de taille humains." }, dominationPsy: { - activation: "est maintenant sous le contrôle de quelqu'un", + activation: "est maintenant sous le contr\xF4le de quelqu'un", actif: "est sous l'effet d'une domination psy", - fin: "retrouve le contrôle de son corps", + fin: "retrouve le contr\xF4le de son corps", prejudiciable: true, }, fievreux: { - activation: "se sent fiévreux", - activationF: "se sent fiévreuse", - actif: "est fiévreux", - actifF: "est fiévreuse", + activation: "se sent fi\xE9vreux", + activationF: "se sent fi\xE9vreuse", + actif: "est fi\xE9vreux", + actifF: "est fi\xE9vreuse", fin: "se sent mieux", prejudiciable: true }, foretVivanteEnnemie: { - activation: "est gêné par la forêt", - activationF: "est gênée par la forêt", - actif: "est désorienté par la forêt", - actifF: "est désorientée par la forêt", - fin: "se retrouve dans une forêt normale", + activation: "est g\xEAn\xE9 par la for\xEAt", + activationF: "est g\xEAn\xE9e par la for\xEAt", + actif: "est d\xE9sorient\xE9 par la for\xEAt", + actifF: "est d\xE9sorient\xE9e par la for\xEAt", + fin: "se retrouve dans une for\xEAt normale", entrave: true }, grandeTaille: { @@ -46205,9 +46792,9 @@ var COFantasy = COFantasy || function() { fin: "retrouve sa taille normale" }, lameDeLigneePerdue: { - activation: "perd sa lame de lignée", - actif: "a perdu sa lame de lignée", - fin: "retrouve sa lame de lignée", + activation: "perd sa lame de lign\xE9e", + actif: "a perdu sa lame de lign\xE9e", + fin: "retrouve sa lame de lign\xE9e", }, marcheSylvestre: { activation: "se deplace maintenant en terrain difficile", @@ -46220,8 +46807,8 @@ var COFantasy = COFantasy || function() { fin: "retrouve une peau normale" }, mutationEcaillesRouges: { - activation: "recouvre sa peau d'écailles rouges", - actif: "a la peau recouverte d'écailles rouges", + activation: "recouvre sa peau d'\xE9cailles rouges", + actif: "a la peau recouverte d'\xE9cailles rouges", fin: "retrouve une peau normale" }, mutationFourrureViolette: { @@ -46230,15 +46817,15 @@ var COFantasy = COFantasy || function() { fin: "retrouve une peau normale" }, mutationMusclesHypertrophies: { - activation: "devient plus musclé", - activationF: "devient plus musclée", - actif: "a les muscles hypertrophiés", + activation: "devient plus muscl\xE9", + activationF: "devient plus muscl\xE9e", + actif: "a les muscles hypertrophi\xE9s", fin: "retrouve des muscles normaux", }, mutationOuies: { - activation: "se fait pousser des ouïes", - actif: "possède des ouïes", - fin: "n'a plus d'ouïes" + activation: "se fait pousser des ou\xEFes", + actif: "poss\xE8de des ou\xEFes", + fin: "n'a plus d'ou\xEFes" }, mutationSangNoir: { activation: "prend un teint plus sombre", @@ -46259,8 +46846,8 @@ var COFantasy = COFantasy || function() { }, presenceGlaciale: { activation: "transforme son corps en glace vivante", - actif: "est formé de glace", - actifF: "est formée de glace", + actif: "est form\xE9 de glace", + actifF: "est form\xE9e de glace", fin: "retrouve un corps normal", }, sensDuDevoir: { @@ -46270,12 +46857,12 @@ var COFantasy = COFantasy || function() { }, sixiemeSens: { activation: "fait un rituel de divination", - actif: "sait un peu à l'avance ce qu'il va se passer", + actif: "sait un peu \xE0 l'avance ce qu'il va se passer", fin: "l'effet du rituel de divination prend fin", }, espaceExigu: { activation: "entre dans un espace exigu.", - actif: "est à l'étroit.", + actif: "est \xE0 l'\xE9troit.", fin: "sort de l'espace exigu." }, sangDeLArbreCoeur: { @@ -46283,36 +46870,36 @@ var COFantasy = COFantasy || function() { actif: "a bu une potion de Sang de l'Arbre-Coeur", fin: "les effets de la potion de Sang de l'Arbre-Coeur diminuent un peu" }, - ondesCorruptrices: { //nombre, à mettre avec !cof-effet ondesCorruptrices 2 - activation: "se sent nauséeux", - activationF: "se sent nauséeuse", - actif: "se sent nauséeux", - actifF: "se sent nauséeuse", + ondesCorruptrices: { //nombre, \xE0 mettre avec !cof-effet ondesCorruptrices 2 + activation: "se sent naus\xE9eux", + activationF: "se sent naus\xE9euse", + actif: "se sent naus\xE9eux", + actifF: "se sent naus\xE9euse", fin: "se sent un peu mieux", prejudiciable: true }, petrifie: { activation: "se change en pierre", - actif: "est transformé en pierre", - actifF: "est transformée en pierre", - fin: "n'est plus pétrifié", - finF: "n'est plus pétrifiée", + actif: "est transform\xE9 en pierre", + actifF: "est transform\xE9e en pierre", + fin: "n'est plus p\xE9trifi\xE9", + finF: "n'est plus p\xE9trifi\xE9e", prejudiciable: true, - msgSave: "résister à la pétrification", + msgSave: "r\xE9sister \xE0 la p\xE9trification", }, poisonAffaiblissantLong: { activation: "sent le poison ralentir ses mouvements", - actif: "est empoisonné", - actifF: "est empoisonnée", + actif: "est empoisonn\xE9", + actifF: "est empoisonn\xE9e", fin: "le poison n'agit plus", - msgSave: "résister au poison", + msgSave: "r\xE9sister au poison", prejudiciable: true, seulementVivant: true, }, reactionAllergique: { - activation: "ressent de fortes démangeaisons", - actif: "est victime d'une réaction allergique", - fin: "les démangeaisons cessent", + activation: "ressent de fortes d\xE9mangeaisons", + actif: "est victime d'une r\xE9action allergique", + fin: "les d\xE9mangeaisons cessent", prejudiciable: true }, }; @@ -46326,13 +46913,13 @@ var COFantasy = COFantasy || function() { function effetIndetermineOfAttribute(attr) { let ef = attr.get('name'); if (ef === undefined || messageEffetIndetermine[ef]) return ef; - //D'abord on enlève le nom du token + //D'abord on enl\xE8ve le nom du token let pu = ef.indexOf('_'); if (pu > 0) { ef = ef.substring(0, pu); if (messageEffetIndetermine[ef]) return ef; } - error("Impossible de déterminer l'effet correspondant à " + ef, attr); + error("Impossible de d\xE9terminer l'effet correspondant \xE0 " + ef, attr); } function attributeExtending(charId, attrName, effetC, extension) { @@ -46344,10 +46931,10 @@ var COFantasy = COFantasy || function() { }); } - //Nom de l'effet, avec la partie générique, mais sans le nom de token + //Nom de l'effet, avec la partie g\xE9n\xE9rique, mais sans le nom de token function effetComplet(effet, attrName) { if (effet == attrName) return effet; - //On a un effet lié à un token ou bien un effet générique + //On a un effet li\xE9 \xE0 un token ou bien un effet g\xE9n\xE9rique if (attrName.charAt(effet.length) == '(') { let p = attrName.indexOf(')', effet.length); if (p > 0) return attrName.substring(0, p + 1); @@ -46388,7 +46975,7 @@ var COFantasy = COFantasy || function() { //alors dmg = '' et type = '' let valAttr = tokenAttribute(perso, effet + 'Valeur'); if (valAttr.length === 0) { - //Par défaut, 1d6 DM normaux + //Par d\xE9faut, 1d6 DM normaux dmgExpr = "1d6"; type = 'normal'; } else { @@ -46434,7 +47021,7 @@ var COFantasy = COFantasy || function() { count.v--; if (count.v === 0) callback(); }); - }); //fin sendChat du jet de dé + }); //fin sendChat du jet de d\xE9 } //asynchrone @@ -46465,7 +47052,7 @@ var COFantasy = COFantasy || function() { let expliquer = function(m) { addLineToFramedDisplay(display, m); }; - let msgPour = " pour ne pas prendre de dégâts de " + nameEffet; + let msgPour = " pour ne pas prendre de d\xE9g\xE2ts de " + nameEffet; let sujet = onGenre(perso, 'il', 'elle'); let msgReussite = ", " + sujet + " ne perd pas de PV ce tour"; let saveOpts = { @@ -46517,8 +47104,8 @@ var COFantasy = COFantasy || function() { let displaySoins = buildinline(soinRoll, 'normal', true); soigneToken(perso, soins, evt, function(s) { - if (s < soins) sendPerso(perso, "récupère tous ses PV."); - else sendPerso(perso, "récupère " + displaySoins + " PV."); + if (s < soins) sendPerso(perso, "r\xE9cup\xE8re tous ses PV."); + else sendPerso(perso, "r\xE9cup\xE8re " + displaySoins + " PV."); count--; if (count === 0) callback(); }, @@ -46526,7 +47113,7 @@ var COFantasy = COFantasy || function() { count--; if (count === 0) callback(); }); - }); //fin sendChat du jet de dé + }); //fin sendChat du jet de d\xE9 }); //fin iterTokensOfAttribute } @@ -46540,9 +47127,9 @@ var COFantasy = COFantasy || function() { return options; } - // gestion des effets qui se déclenchent à la fin de chaque tour - // N'ajoute pas evt à l'historique - // Asynchrone (à cause des saves par tour) + // 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) function changementDeTour(tour, attrs, evt, combat, pageId, options) { // Enlever les bonus d'un tour attrs = removeAllAttributes('limiteParTour', evt, attrs); @@ -46553,7 +47140,7 @@ var COFantasy = COFantasy || function() { attrs = removeAllAttributes('prescienceUtilisee', evt, attrs); attrs = removeAllAttributes('increvableHumainUtilise', evt, attrs); resetAttr(attrs, 'cercleDeProtectionActif', evt); - // Pour défaut dans la cuirasse, on diminue si la valeur est 2, et on supprime si c'est 1 + // Pour d\xE9faut dans la cuirasse, on diminue si la valeur est 2, et on supprime si c'est 1 let defautsDansLaCuirasse = allAttributesNamed(attrs, 'defautDansLaCuirasse'); defautsDansLaCuirasse.forEach(function(attr) { if (attr.get('current') < 2) { @@ -46585,7 +47172,7 @@ var COFantasy = COFantasy || function() { attr.set('current', 1); } }); - //Les tests ratés + //Les tests rat\xE9s let trTour = allAttributesNamed(attrs, 'testsRatesDuTour'); trTour.forEach(function(tr) { let curTr = tr.get('current'); @@ -46614,7 +47201,7 @@ var COFantasy = COFantasy || function() { attr.set('current', ve + 1); let veCharId = attr.get('characterid'); if (veCharId === undefined || veCharId === '') { - error("Attribut sans personnage associé", attr); + error("Attribut sans personnage associ\xE9", attr); return; } let veSeuil = parseInt(attr.get('max')); @@ -46629,9 +47216,9 @@ var COFantasy = COFantasy || function() { }; let testId = 'vapeursEthyliques_' + perso.token.id; testCaracteristique(perso, 'CON', veSeuil, testId, options, evt, function(testRes) { - let res = "tente un jet de CON " + veSeuil + " pour combattre les vapeurs éthyliques " + testRes.texte; + let res = "tente un jet de CON " + veSeuil + " pour combattre les vapeurs \xE9thyliques " + testRes.texte; if (testRes.reussite) { - res += " => réussi." + testRes.modifiers; + res += " => r\xE9ussi." + testRes.modifiers; let expliquer; if (attr.get('name') == 'vapeursEthyliques') { expliquer = function(s) { @@ -46645,14 +47232,14 @@ var COFantasy = COFantasy || function() { expliquer(res); diminueEbriete(perso, evt, expliquer); } else { - res += " => raté" + testRes.rerolls + testRes.modifiers; + res += " => rat\xE9" + testRes.rerolls + testRes.modifiers; sendPerso(perso, res); } }); }); }); // nouveau tour : enlever le statut surpris - // et faire les actions de début de tour + // et faire les actions de d\xE9but de tour let selected = []; updateNextInitSet.forEach(function(id) { selected.push({ @@ -46697,14 +47284,14 @@ var COFantasy = COFantasy || function() { }; dealDamage(perso, dmg, [], evt, false, {}, undefined, function(dmgDisplay, dmgFinal) { - sendPerso(perso, " est écrasé ! " + + sendPerso(perso, " est \xE9cras\xE9 ! " + onGenre(perso, 'Il', 'Elle') + " subit " + dmgDisplay + " DM"); }); } let enflammeAttr = tokenAttribute(perso, 'enflamme'); if (enflammeAttr.length > 0) { let enflamme = parseInt(enflammeAttr[0].get('current')); - // Pour ne pas faire les dégâts plusieurs fois (plusieurs tokens pour un même personnage), on utilise la valeur max de l'attribut + // Pour ne pas faire les d\xE9g\xE2ts plusieurs fois (plusieurs tokens pour un m\xEAme personnage), on utilise la valeur max de l'attribut let dernierTourEnflamme = parseInt(enflammeAttr[0].get('max')); if ((isNaN(dernierTourEnflamme) || dernierTourEnflamme < tour) && !isNaN(enflamme) && enflamme > 0) { @@ -46723,7 +47310,7 @@ var COFantasy = COFantasy || function() { display: roll }; if (getState(perso, 'mort')) { - sendChat('', "Le cadavre de " + nomPerso(perso) + " continue de brûler"); + sendChat('', "Le cadavre de " + nomPerso(perso) + " continue de br\xFBler"); } else { dealDamage(perso, dmgEnflamme, [], evt, false, {}, undefined, function(dmgDisplay, dmgFinal) { @@ -46732,7 +47319,7 @@ var COFantasy = COFantasy || function() { }); } if (d6Enflamme < 3) { - sendPerso(perso, ": les flammes s'éteignent"); + sendPerso(perso, ": les flammes s'\xE9teignent"); removeTokenAttr(perso, 'enflamme', evt); let ms = messageEffetCombat.enflamme.statusMarker; if (ms) { @@ -46749,14 +47336,14 @@ var COFantasy = COFantasy || function() { nbDes: 3 }); let dmg = { - type: 'normal', //correspond à de l'asphyxie + type: 'normal', //correspond \xE0 de l'asphyxie total: jet.val, display: jet.roll }; if (immuniseAsphyxie(perso)) dmg.type = 'acide'; dealDamage(perso, dmg, [], evt, false, {}, undefined, function(dmgDisplay, dmgFinal) { - sendPerso(perso, "est en train d'être digéré. " + onGenre(perso, 'Il', 'Elle') + " perd " + dmgDisplay + " PVs"); + sendPerso(perso, "est en train d'\xEAtre dig\xE9r\xE9. " + onGenre(perso, 'Il', 'Elle') + " perd " + dmgDisplay + " PVs"); }); } if (attributeAsBool(perso, 'blessureQuiSaigne') && @@ -46782,7 +47369,7 @@ var COFantasy = COFantasy || function() { let expliquer = function(m) { addLineToFramedDisplay(display, m); }; - let msgPour = " pour ne pas prendre de dégâts de noyade"; + let msgPour = " pour ne pas prendre de d\xE9g\xE2ts de noyade"; let sujet = onGenre(perso, 'il', 'elle'); let msgReussite = ", " + sujet + " ne perd pas de PV ce tour"; let saveOpts = { @@ -46838,7 +47425,7 @@ var COFantasy = COFantasy || function() { saufDMType = vitaliteSurnaturelle.substring(indexType + 1).split(','); soigneToken(perso, vitaliteSurnat, evt, function(s) { - whisperChar(perso.charId, 'récupère ' + s + ' PVs.'); + whisperChar(perso.charId, 'r\xE9cup\xE8re ' + s + ' PVs.'); }, function() {}, { saufDMType @@ -46850,7 +47437,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(perso, 'sangDeLArbreCoeur') && !getState(perso, 'mort')) { soigneToken(perso, 5, evt, function(s) { - whisperChar(perso.charId, "régénère " + s + " PVs. (grâce à la potion de sang de l'Arbre Coeur)"); + whisperChar(perso.charId, "r\xE9g\xE9n\xE8re " + s + " PVs. (gr\xE2ce \xE0 la potion de sang de l'Arbre Coeur)"); }, function() {} ); @@ -46860,9 +47447,9 @@ var COFantasy = COFantasy || function() { increvableActif[0].remove(); let soins = randomInteger(6) + randomInteger(6) + randomInteger(6) + modCarac(perso, 'constitution'); soigneToken(perso, soins, evt, function(soinsEffectifs) { - let msgSoins = "est increvable et récupère "; + let msgSoins = "est increvable et r\xE9cup\xE8re "; if (soinsEffectifs == soins) msgSoins += soins + " points de vie"; - else msgSoins += soinsEffectifs + " PV (le jet était " + soins + ")"; + else msgSoins += soinsEffectifs + " PV (le jet \xE9tait " + soins + ")"; whisperChar(perso.charId, msgSoins); }); } @@ -46875,16 +47462,16 @@ var COFantasy = COFantasy || function() { }; perso.ignoreTouteRD = true; dealDamage(perso, r, [], evt, false, {}, [], function() { - // Vérification si le Zombie est toujours vivant + // V\xE9rification si le Zombie est toujours vivant let token = getObj('graphic', perso.token.id); - if (token) whisperChar(perso.charId, "se dégrade et perd 1 PV"); + if (token) whisperChar(perso.charId, "se d\xE9grade et perd 1 PV"); }); } }); setActiveToken(combat, undefined, evt); - initiative(selected, evt, true); // met Tour à la fin et retrie + initiative(selected, evt, true); // met Tour \xE0 la fin et retrie updateNextInitSet = new Set(); - // Saves à faire à la fin de chaque tour. Asynchrone, mais pas grave ? + // Saves \xE0 faire \xE0 la fin de chaque tour. Asynchrone, mais pas grave ? attrs.forEach(function(attr) { let attrName = attr.get('name'); let indexSave = attrName.indexOf('SaveParTour'); @@ -46896,12 +47483,12 @@ var COFantasy = COFantasy || function() { if (!cof_states[effetC] && !effetTemp && !estEffetCombat(effetC)) return; let carac = attr.get('current'); if (!isCarac(carac)) { - error("Save par tour " + attrName + " mal formé", carac); + error("Save par tour " + attrName + " mal form\xE9", carac); return; } let seuil = parseInt(attr.get('max')); if (isNaN(seuil)) { - error("Save par tour " + attrName + " mal formé", seuil); + error("Save par tour " + attrName + " mal form\xE9", seuil); return; } let charId = attr.get('characterid'); @@ -46930,7 +47517,7 @@ var COFantasy = COFantasy || function() { let se = stringOfEtat(effetC, perso); met = { etat: true, - msgSave: "ne plus être " + se, + msgSave: "ne plus \xEAtre " + se, fin: "n'est plus " + se, actif: "est toujours " + se }; @@ -46938,7 +47525,7 @@ var COFantasy = COFantasy || function() { let msgPour = " pour "; if (met.msgSave) msgPour += met.msgSave; else { - msgPour += "ne plus être sous l'effet de "; + msgPour += "ne plus \xEAtre sous l'effet de "; if (effetC.startsWith('dotGen(')) msgPour += effetC.substring(7, effetC.indexOf(')')); else msgPour += effetC; @@ -47024,7 +47611,7 @@ var COFantasy = COFantasy || function() { //Pour chaque token representant ce perso allPersos.forEach(function(perso) { if (perso.charId != charId) return; - //On cherche ensuite les tokens à portee + //On cherche ensuite les tokens \xE0 portee allPersos.forEach(function(target) { if (target.token.id == perso.token.id) return; let tokRepresents = target.charId; @@ -47053,19 +47640,19 @@ var COFantasy = COFantasy || function() { targetLine += " --target " + tokId; }); if (targetLine != "") - sendChat('player|' + gmId, "!cof-dmg 3d6" + targetLine + " --titre Dégâts des morts-vivants animés"); + sendChat('player|' + gmId, "!cof-dmg 3d6" + targetLine + " --titre D\xE9g\xE2ts des morts-vivants anim\xE9s"); targetLine = ""; Object.keys(degatsArmeeDefense).forEach(function(tokId) { targetLine += " --target " + tokId; }); if (targetLine != "") - sendChat('player|' + gmId, "!cof-dmg 1d6" + targetLine + " --titre Dégâts des morts-vivants animés sur les cibles qui les combattent"); + sendChat('player|' + gmId, "!cof-dmg 1d6" + targetLine + " --titre D\xE9g\xE2ts des morts-vivants anim\xE9s sur les cibles qui les combattent"); removeAllAttributes("defenseArmeeDesMorts", evt, attrs); if (stateCOF.prescience) { - //On affiche la prescience aux joueurs concernés + //On affiche la prescience aux joueurs concern\xE9s allPersos.forEach(function(perso) { if (capaciteDisponible(perso, 'prescience', 'combat')) { - whisperChar(perso.charId, "Possibilité d'utiliser la " + boutonSimple('!cof-prescience ' + perso.token.id + ' --mana 2', "Prescience")); + whisperChar(perso.charId, "Possibilit\xE9 d'utiliser la " + boutonSimple('!cof-prescience ' + perso.token.id + ' --mana 2', "Prescience")); } }); stateCOF.nextPrescience = { @@ -47086,7 +47673,7 @@ var COFantasy = COFantasy || function() { } //evt a un champ attributes et un champ deletedAttributes - //evt n'est pas ajouté à l'historique dans cette fonction + //evt n'est pas ajout\xE9 \xE0 l'historique dans cette fonction function nextTurnOfActive(active, attrs, evt, combat, pageId, options) { if (active === undefined) return; if (active.id == "-1" && active.custom == "Tour") { //Nouveau tour @@ -47099,8 +47686,8 @@ var COFantasy = COFantasy || function() { }; evt.combat.tour = tour - 1; evt.updateNextInitSet = updateNextInitSet; - active.pr = tour - 1; // préparation au calcul de l'undo - sendChat("GM", "Début du tour " + tour); + active.pr = tour - 1; // pr\xE9paration au calcul de l'undo + sendChat("GM", "D\xE9but du tour " + tour); combat.tour = tour; combat.init = 1000; changementDeTour(tour, attrs, evt, combat, pageId, options); @@ -47163,7 +47750,7 @@ var COFantasy = COFantasy || function() { nbDe: 1, de: 4 }, 'feu', - "brûle dans son armure", evt, { + "br\xFBle dans son armure", evt, { valeur: 'armureBrulanteValeur' }, callBack); return; @@ -47171,7 +47758,7 @@ var COFantasy = COFantasy || function() { degatsParTour(charId, pageId, effet, attrName, { cst: 1 }, 'normal', - "est piqué par les insectes", evt, { + "est piqu\xE9 par les insectes", evt, { valeur: 'nueeDInsectesValeur' }, callBack); return; @@ -47179,31 +47766,31 @@ var COFantasy = COFantasy || function() { degatsParTour(charId, pageId, effet, attrName, { cst: 2 }, 'normal', - "est piqué par les criquets", evt, {}, callBack); + "est piqu\xE9 par les criquets", evt, {}, callBack); return; case 'nueeDeScorpions': //prend 1D6 DM degatsParTour(charId, pageId, effet, attrName, { nbDe: 1, de: 6 }, 'normal', - "est piqué par les scorpions", evt, {}, callBack); + "est piqu\xE9 par les scorpions", evt, {}, callBack); return; case 'armeBrulante': //prend 1 DM degatsParTour(charId, pageId, effet, attrName, { cst: 1 }, 'feu', - "se brûle avec son arme", evt, { + "se br\xFBle avec son arme", evt, { valeur: 'armeBrulanteValeur' }, callBack); return; case 'regeneration': //soigne - soigneParTour(charId, pageId, effet, attrName, 3, "régénère", evt, { + soigneParTour(charId, pageId, effet, attrName, 3, "r\xE9g\xE9n\xE8re", evt, { valeur: 'regenerationValeur' }, callBack); return; case 'strangulation': let nameDureeStrang = 'dureeStrangulation'; - if (effet != attrName) { //concerne un token non lié + if (effet != attrName) { //concerne un token non li\xE9 nameDureeStrang += attrName.substring(attrName.indexOf('_')); } let dureeStrang = findObjs({ @@ -47223,18 +47810,18 @@ var COFantasy = COFantasy || function() { }); } else { let strangUpdate = dureeStrang[0].get('max'); - if (strangUpdate) { //a été mis à jour il y a au plus 1 tour + if (strangUpdate) { //a \xE9t\xE9 mis \xE0 jour il y a au plus 1 tour evt.attributes.push({ attribute: dureeStrang[0], current: dureeStrang[0].get('current'), max: strangUpdate }); dureeStrang[0].set('max', false); - } else { //Ça fait trop longtemps, on arrête tout + } else { //Ça fait trop longtemps, on arr\xEAte tout sendChar(charId, messageFin({ charId }, messageEffetTemp[effet]), true); - evt.attributes.pop(); //On enlève des attributs modifiés pour mettre dans les attribute supprimés. + evt.attributes.pop(); //On enl\xE8ve des attributs modifi\xE9s pour mettre dans les attribute supprim\xE9s. evt.deletedAttributes.push(attr); attr.remove(); evt.deletedAttributes.push(dureeStrang[0]); @@ -47322,14 +47909,14 @@ var COFantasy = COFantasy || function() { let displaySoins = buildinline(soinRoll, 'normal', true); soigneToken(cible, soins, evt, function(s) { - if (s < soins) sendPerso(cible, "récupère tous ses PV."); + if (s < soins) sendPerso(cible, "r\xE9cup\xE8re tous ses PV."); else if (s == soins) - sendPerso(cible, "récupère " + displaySoins + " PV."); + sendPerso(cible, "r\xE9cup\xE8re " + displaySoins + " PV."); else - sendPerso(cible, "récupère " + s + " PV. (Le jet était " + displaySoins + ")"); + sendPerso(cible, "r\xE9cup\xE8re " + s + " PV. (Le jet \xE9tait " + displaySoins + ")"); fin(); }, fin); - }); //fin sendChat du jet de dé + }); //fin sendChat du jet de d\xE9 }); }); return; @@ -47340,13 +47927,14 @@ var COFantasy = COFantasy || function() { } } - //Appelé si le turn order change, mais aussi en interne - //si evt est déjà défini, ne l'ajoute pas au turn order + //Appel\xE9 si le turn order change, mais aussi en interne + //si evt est d\xE9j\xE0 d\xE9fini, ne l'ajoute pas au turn order function nextTurn(cmp, options, evt) { if (!cmp.get('initiativepage')) return; let combat = stateCOF.combat; if (!combat) { error("Le script n'est pas en mode combat", cmp); + return; } let turnOrder = cmp.get('turnorder'); let pageId = combat.pageId; @@ -47400,7 +47988,7 @@ var COFantasy = COFantasy || function() { let attrs = findObjs({ _type: 'attribute' }); - // Si on a changé d'initiative, alors diminue les effets temporaires + // Si on a chang\xE9 d'initiative, alors diminue les effets temporaires if (combat.init > init) { if (stateCOF.tokensTemps && stateCOF.tokensTemps.length > 0) { stateCOF.tokensTemps = stateCOF.tokensTemps.filter(function(tt) { @@ -47414,15 +48002,8 @@ var COFantasy = COFantasy || function() { tt.duree--; return true; } else { - let token = getObj('graphic', tt.tid); - if (token) { - let ett = {...tt - }; - ett.deletedToken = getTokenFields(token); - evt.deletedTokensTemps = evt.deletedTokensTemps || []; - evt.deletedTokensTemps.push(ett); - token.remove(); - } + if (tt.intrusion) tt.pasDExplosion = true; + deleteTokenTemp(tt, evt); return false; } } else { @@ -47430,7 +48011,7 @@ var COFantasy = COFantasy || function() { } }); } - //attrsTemp ne contient que les attributs dont la durée doit baisser + //attrsTemp ne contient que les attributs dont la dur\xE9e doit baisser let attrsTemp = attrs.filter(function(obj) { if (!estEffetTemp(obj.get('name'))) return false; let obji = obj.get('max'); @@ -47439,7 +48020,7 @@ var COFantasy = COFantasy || function() { if (!evt.combat) evt.combat = {...stateCOF.combat }; combat.init = init; - // Boucle sur les effets temps peut être asynchrone à cause des DM + // Boucle sur les effets temps peut \xEAtre asynchrone \xE0 cause des DM let count = attrsTemp.length; if (count === 0) { nextTurnOfActive(active, attrs, evt, combat, pageId, options); @@ -47462,8 +48043,8 @@ var COFantasy = COFantasy || function() { let effetC = effetComplet(effet, attrName); let v = parseInt(attr.get('current')); if (isNaN(v)) v = 1; - if (v <= 1) { //L'effet arrive en fin de vie, doit être supprimé - //Sauf si on a accumulé plusieurs fois l'effet + if (v <= 1) { //L'effet arrive en fin de vie, doit \xEAtre supprim\xE9 + //Sauf si on a accumul\xE9 plusieurs fois l'effet let accumuleAttr = attributeExtending(charId, attrName, effetC, 'DureeAccumulee'); if (accumuleAttr.length > 0) { accumuleAttr = accumuleAttr[0]; @@ -47514,16 +48095,16 @@ var COFantasy = COFantasy || function() { if (v > 1) attr.set('current', v - 1); actionEffet(attr, effet, attrName, charId, pageId, evt, fin); }); //fin de la boucle sur tous les attributs d'effets temporaires - } else { //L'initiative n'a pas bougée + } else { //L'initiative n'a pas boug\xE9e nextTurnOfActive(active, attrs, evt, combat, pageId, options); } } - //Fonction appelée par !cof-tour-suivant + //Fonction appel\xE9e par !cof-tour-suivant function tourSuivant(msg) { let combat = stateCOF.combat; if (!combat) { - sendPlayer(msg, "Vous n'êtes pas en combat"); + sendPlayer(msg, "Vous n'\xEAtes pas en combat"); return; } let cmp = Campaign(); @@ -47561,10 +48142,10 @@ var COFantasy = COFantasy || function() { nextTurn(cmp); } - //nb à 11 pour ne pas retenter de lire les attributs + //nb \xE0 11 pour ne pas retenter de lire les attributs function scriptVersionToCharacter(character, nb) { let charId = character.id; - //On vérifie que les attributs sont peuplés + //On v\xE9rifie que les attributs sont peupl\xE9s let attrs = findObjs({ _type: 'attribute', _characterid: charId, @@ -47630,7 +48211,7 @@ var COFantasy = COFantasy || function() { removeTokenAttr(perso, 'bougeGraceA'); return; } - //On regarde si il existe une copie de ce token, par exemple à cause de l'invisibilité + //On regarde si il existe une copie de ce token, par exemple \xE0 cause de l'invisibilit\xE9 let otherTokens = findObjs({ _type: 'graphic', _pageid: pageId, @@ -47742,7 +48323,7 @@ var COFantasy = COFantasy || function() { activerEffetTemporaire(origine, cibles, 'drainDeForce', mEffet, 1, options, evtEffet, '', [], display); } - //retourne le nombre de cibles affectées + //retourne le nombre de cibles affect\xE9es function appliquerAura(origine, cibles, pageId, aura, evt, renew) { let effet; cibles = cibles.filter(function(perso) { @@ -47763,7 +48344,7 @@ var COFantasy = COFantasy || function() { save: { carac: 'CON', seuil: 12, - msgPour: ' pour ne pas être affaibli' + eForFemale(cibles[0]) + msgPour: ' pour ne pas \xEAtre affaibli' + eForFemale(cibles[0]) } }; let mEffet = messageEffetTemp.drainDeForce; @@ -47795,8 +48376,8 @@ var COFantasy = COFantasy || function() { return cibles.length; } - //Réagit au déplacement manuel d'un token. - // suivis est l'ensemble des tokens qui a déjà été bougé suite à ce déplacement + //R\xE9agit au d\xE9placement manuel d'un token. + // suivis est l'ensemble des tokens qui a d\xE9j\xE0 \xE9t\xE9 boug\xE9 suite \xE0 ce d\xE9placement function moveToken(token, prev, synchronisation, suivis) { let charId = token.get('represents'); if (charId === '') return; @@ -47809,6 +48390,57 @@ var COFantasy = COFantasy || function() { let y = token.get('top'); let deplacement = prev && (prev.left != x || prev.top != y); if (!deplacement) return; + //Effet des bombes \xE0 intrusion + if (stateCOF.tokensTemps) { + let collisions = []; + let pt_arrivee = { + x, + y + }; + let pt_depart = { + x: prev.left, + y: prev.top + }; + let rayon = tokenSizeAsCircle(token) / 2; + stateCOF.tokensTemps.forEach(function(tt) { + if (!tt.intrusion) return; + //tt.intrusion est exprim\xE9 en pixels + let bombe = getTokenTemp(tt); + if (!bombe) return; + let pb = pointOfToken(bombe); + let distance = distancePoints(pt_depart, pb); + if (distance < tt.intrusion) return; //On est parti de la zone de d\xE9part + let distToTrajectory = + distancePixTokenSegment(bombe, pt_depart, pt_arrivee); + if (distToTrajectory > tt.intrusion + rayon) return; + collisions.push({ + bombe, + tt, + distance + }); + }); + if (collisions.length > 0) { + collisions.sort(function(b1, b2) { + let d1 = b1.distance; + let d2 = b2.distance; + if (d1 < d2) return -1; + if (d2 < d1) return 1; + return 0; + }); + let bombe = collisions[0].bombe; + x = bombe.get('left'); + y = bombe.get('top'); + token.set('left', x); + token.set('top', y); + const evt = { + type: "Explosion de bombe" + }; + deleteTokenTemp(collisions[0].tt, evt); + stateCOF.tokensTemps = stateCOF.tokensTemps.filter(function(tt) { + return tt.id == collisions[0].tt.id; + }); + } + } //Effets des auras, asynchrone if (stateCOF.combat && stateCOF.combat.auras) { const evt = { @@ -47849,7 +48481,7 @@ var COFantasy = COFantasy || function() { if (tid == token.id) return; let tok = getObj('graphic', tid); if (tok === undefined) { - error("Impossible de trouver le token d'id " + tid + " synchronisé avec " + token.get('name'), attr); + error("Impossible de trouver le token d'id " + tid + " synchronis\xE9 avec " + token.get('name'), attr); return; } tok.set('left', x); @@ -47916,7 +48548,7 @@ var COFantasy = COFantasy || function() { type: "initiative" }; updateInit(monture.token, evt); - // Réadapter l'init_dynamique au token du perso + // R\xE9adapter l'init_dynamique au token du perso if (stateCOF.options.affichage.val.init_dynamique.val) { setTokenInitAura(perso); } @@ -47998,7 +48630,7 @@ var COFantasy = COFantasy || function() { autreInvisible.set('top', y); } } - //si non, perso est peut-être une monture + //si non, perso est peut-\xEAtre une monture let attrMontePar = tokenAttribute(perso, 'estMontePar'); attrMontePar.forEach(function(a) { let cavalier = persoOfIdName(a.get('current'), pageId); @@ -48024,7 +48656,7 @@ var COFantasy = COFantasy || function() { //Si le token suivait quelqu'un, ce n'est plus le cas if (prev.suit === undefined) nePlusSuivre(perso, pageId); //On bouge tous les tokens qui suivent le personnage - //sauf si on a déjà été bougé. + //sauf si on a d\xE9j\xE0 \xE9t\xE9 boug\xE9. if (!suivis.has(token.id)) { suivis.add(token.id); let attrSuivi = tokenAttribute(perso, 'estSuiviPar'); @@ -48058,7 +48690,7 @@ var COFantasy = COFantasy || function() { if (sh > width) return false; let sx = suivant.token.get('left'); let sy = suivant.token.get('top'); - //On essaie de garder la même position par rapport au token, en supposant qu'on était derrière lui + //On essaie de garder la m\xEAme position par rapport au token, en supposant qu'on \xE9tait derri\xE8re lui let attrSuit = tokenAttribute(suivant, 'suit'); let dp; if (attrSuit.length > 0) { @@ -48073,10 +48705,10 @@ var COFantasy = COFantasy || function() { if (nsy < 0) nsy = 0; if (nsx + sw / 2 > width) nsx = Math.floor(width - sw / 2); if (nsy + sh / 2 > height) nsy = Math.floor(height - sh / 2); - //vérifie si de la nouvelle position on peut voir le suivi + //v\xE9rifie si de la nouvelle position on peut voir le suivi if (obstaclePresent(nsx, nsy, pt, murs)) { - //On essaie de suivre le chemin du token, à la place - //D'abord se déplacer vers l'ancienne position de perso, au maximum de distance pixels + //On essaie de suivre le chemin du token, \xE0 la place + //D'abord se d\xE9placer vers l'ancienne position de perso, au maximum de distance pixels let distLoc = distance; if (distLoc - dp < 5) { nsx = prev.left; @@ -48133,7 +48765,7 @@ var COFantasy = COFantasy || function() { roundMarker.set('left', x); roundMarker.set('top', y); } else { - // Cas spéciaux du cavaliers : au tour du cavalier, l'init_dynamique suit la monture + // Cas sp\xE9ciaux du cavaliers : au tour du cavalier, l'init_dynamique suit la monture let estMontePar = tokenAttribute(perso, 'estMontePar'); if (estMontePar.length > 0) { let sp = splitIdName(estMontePar[0].get('current')); @@ -48145,7 +48777,7 @@ var COFantasy = COFantasy || function() { } } } - //On déplace les tokens de lumière, si il y en a + //On d\xE9place les tokens de lumi\xE8re, si il y en a let attrLumiere = tokenAttribute(perso, 'lumiere'); attrLumiere.forEach(function(al) { let lumId = al.get('max'); @@ -48165,13 +48797,13 @@ var COFantasy = COFantasy || function() { }); if (tokensLumiere.length === 0) { if (lumiereExiste) return; - log("Pas de token pour la lumière " + al.get('current')); + log("Pas de token pour la lumi\xE8re " + al.get('current')); al.remove(); return; } lumiere = tokensLumiere.shift(); if (tokensLumiere.length > 0) { - //On cherche le token le plus proche de la position précédente + //On cherche le token le plus proche de la position pr\xE9c\xE9dente let d = distanceTokenPrev(lumiere, prev); tokensLumiere.forEach(function(tl) { let d2 = distanceTokenPrev(tl, prev); @@ -48184,7 +48816,7 @@ var COFantasy = COFantasy || function() { } if (lumiere === undefined) { if (lumiereExiste) return; - log("Pas de token pour la lumière " + al.get('current')); + log("Pas de token pour la lumi\xE8re " + al.get('current')); al.remove(); return; } @@ -48207,7 +48839,7 @@ var COFantasy = COFantasy || function() { function synchronisationDesEtats(perso) { for (let etat in cof_states) { - // Récupère la valeur de l'état sur la fiche + // R\xE9cup\xE8re la valeur de l'\xE9tat sur la fiche let valEtat; if (etat == 'affaibli') { // Cas particulier affaibli sur la fiche perso valEtat = (ficheAttributeAsInt(perso, 'affaibli', 20) == 12); @@ -48219,10 +48851,10 @@ var COFantasy = COFantasy || function() { } } - //Opérations diverses au moment où on pose un token. - //Si le token représente un personnage et avec la barre de vie non liée, - // assure un nom unique en ajoutant un numéro - // On en profite aussi pour mettre certaines valeurs par défaut + //Op\xE9rations diverses au moment o\xF9 on pose un token. + //Si le token repr\xE9sente un personnage et avec la barre de vie non li\xE9e, + // assure un nom unique en ajoutant un num\xE9ro + // On en profite aussi pour mettre certaines valeurs par d\xE9faut // retourne un perso si c'est un token de personnage function renameToken(token, tokenName) { let charId = token.get('represents'); @@ -48285,11 +48917,11 @@ var COFantasy = COFantasy || function() { } return perso; } - //cas des mooks : numérotation + //cas des mooks : num\xE9rotation let copyOf = 0; let tokenBaseName = tokenName; if (tokenBaseName.includes('%%NUMBERED%%')) { - if (typeof TokenNameNumber !== 'undefined') return perso; //On laisse tokenNameNumber gérer ça + if (typeof TokenNameNumber !== 'undefined') return perso; //On laisse tokenNameNumber g\xE9rer \xE7a tokenBaseName = tokenBaseName.replace('%%NUMBERED%%', ''); } else { // On regarde si le nom se termine par un entier @@ -48341,7 +48973,7 @@ var COFantasy = COFantasy || function() { function addToken(token, nb) { let tokenName = token.get('name'); - //La plupart du temps, il faut attendre un peu que le nom soit affecté + //La plupart du temps, il faut attendre un peu que le nom soit affect\xE9 if (tokenName !== '') { let perso = renameToken(token, tokenName); if (perso === undefined) return; @@ -48355,16 +48987,16 @@ var COFantasy = COFantasy || function() { return; } nb = nb || 1; - if (nb > 10) return; //Tant pis, peut-être que le nom est vide + if (nb > 10) return; //Tant pis, peut-\xEAtre que le nom est vide _.delay(function() { addToken(token, nb + 1); }, 50); } - // Surveillance sur le changement d'état du token + // Surveillance sur le changement d'\xE9tat du token function changeMarker(token, prev) { const charId = token.get('represents'); - if (charId === undefined || charId === '') return; // Uniquement si token lié à un perso + if (charId === undefined || charId === '') return; // Uniquement si token li\xE9 \xE0 un perso const perso = { token, charId @@ -48430,7 +49062,7 @@ var COFantasy = COFantasy || function() { let lumId = al.get('max'); if (lumId == 'surToken') { if (!token.get('emits_bright_light') && !token.get('emits_low_light')) { - //On cherche un token qui représente le même personnage et émet de la lumière + //On cherche un token qui repr\xE9sente le m\xEAme personnage et \xE9met de la lumi\xE8re let allTokens = findObjs({ type: 'graphic', represents: perso.charId @@ -48449,7 +49081,7 @@ var COFantasy = COFantasy || function() { } return; } - //Lumière sur un token qui suit le perso. + //Lumi\xE8re sur un token qui suit le perso. let lumiere = getObj('graphic', lumId); if (lumiere && lumiere.get('pageid') != pageId) { let copyLum = createObj('graphic', { @@ -48475,7 +49107,7 @@ var COFantasy = COFantasy || function() { } } - //Actions à faire pour maintenir la cohérence des tokens qui représentent le même personnage. + //Actions \xE0 faire pour maintenir la coh\xE9rence des tokens qui repr\xE9sentent le m\xEAme personnage. function changePlayerPage(campaign) { let currentMap = getObj('page', campaign.get('playerpageid')); let tokens = findObjs({ @@ -48485,7 +49117,7 @@ var COFantasy = COFantasy || function() { }); tokens.forEach(function(token) { let charId = token.get('represents'); - if (charId === undefined || charId === '') return; // Si token lié à un perso + if (charId === undefined || charId === '') return; // Si token li\xE9 \xE0 un perso if (token.get('bar1_link') === '') return; // Si unique let perso = { token, @@ -48527,8 +49159,8 @@ var COFantasy = COFantasy || function() { function changeTokenLock(token, prev) { const charId = token.get('represents'); - if (charId === undefined || charId === '') return; // Uniquement si token lié à un perso - if (token.get('lockMovement')) return; //Rien de spécial à faire + if (charId === undefined || charId === '') return; // Uniquement si token li\xE9 \xE0 un perso + if (token.get('lockMovement')) return; //Rien de sp\xE9cial \xE0 faire const perso = { token, charId @@ -48557,8 +49189,8 @@ var COFantasy = COFantasy || function() { state.COFantasy.eventId = 0; } if (version < 1.0) { - log("Mise à jour des attributs et macros vers la version 1.0"); - //Mise à jour des effets temporaires avec _ + log("Mise \xE0 jour des attributs et macros vers la version 1.0"); + //Mise \xE0 jour des effets temporaires avec _ let strReg = "(rayon_affaiblissant|peau_d_ecorce|chant_des_heros|image_decalee|a_couvert|sous_tension|forgeron_|armeEnflammee)"; let regName = new RegExp("^" + strReg); let regText = new RegExp(strReg); @@ -48611,10 +49243,10 @@ var COFantasy = COFantasy || function() { m.set('action', action); } }); - log("Mise à jour effectuée."); + log("Mise \xE0 jour effectu\xE9e."); } if (version < 2.0) { - log("Mise à jour des attributs et macros vers la version 2.0"); + log("Mise \xE0 jour des attributs et macros vers la version 2.0"); let strReg = "(--argent)"; let regName = new RegExp("^" + strReg); let regText = new RegExp(strReg); @@ -48646,7 +49278,7 @@ var COFantasy = COFantasy || function() { m.set('action', action); } }); - log("Mise à jour effectuée."); + log("Mise \xE0 jour effectu\xE9e."); } if (version < 2.02) { let attrs = findObjs({ @@ -48656,7 +49288,7 @@ var COFantasy = COFantasy || function() { let attrName = attr.get('name'); if (attrName == 'mort-vivant') attr.set('name', 'mortVivant'); }); - log("Mise à jour effectuée."); + log("Mise \xE0 jour effectu\xE9e."); } if (version < 2.03) { let attrs = findObjs({ @@ -48664,13 +49296,13 @@ var COFantasy = COFantasy || function() { }); attrs.forEach(function(attr) { let attrName = attr.get('name'); - if (attrName == 'runeDEnergie') attr.set('name', 'runeForgesort_énergie'); + if (attrName == 'runeDEnergie') attr.set('name', 'runeForgesort_\xE9nergie'); if (attrName == 'runeDeProtection') attr.set('name', 'runeForgesort_protection'); if (attrName.includes('runeDePuissance')) { attr.set('name', 'runeForgesort_puissance(' + attrName.substring(attrName.indexOf("(") + 1, attrName.indexOf(")")) + ')'); } }); - log("Mise à jour des runes effectuée."); + log("Mise \xE0 jour des runes effectu\xE9e."); } if (version < 2.04) { let attrs = findObjs({ @@ -48718,7 +49350,7 @@ var COFantasy = COFantasy || function() { attrRDS.set('current', rdPerso); a.remove(); }); - log("Mise à jour de la RD effectuée"); + log("Mise \xE0 jour de la RD effectu\xE9e"); } if (version < 2.05) { let attrs = findObjs({ @@ -48733,7 +49365,7 @@ var COFantasy = COFantasy || function() { let message = action.substring(19); a.set("max", "!cof-lancer-sort --message " + message + " --mana " + mana); }); - log("Mise à jour des consommables !cof-lancer-sort effectuée"); + log("Mise \xE0 jour des consommables !cof-lancer-sort effectu\xE9e"); let macros = findObjs({ _type: 'macro' }).concat(findObjs({ @@ -48746,7 +49378,7 @@ var COFantasy = COFantasy || function() { let message = macro.substring(19); m.set("action", "!cof-lancer-sort --message " + message + " --mana " + mana); }); - log("Mise à jour des ability & macros !cof-lancer-sort effectuée"); + log("Mise \xE0 jour des ability & macros !cof-lancer-sort effectu\xE9e"); } if (version < 2.10) { let tokens = findObjs({ @@ -48775,7 +49407,7 @@ var COFantasy = COFantasy || function() { let removeAttrs = function() { charsToTreat--; if (charsToTreat > 0) return; - log("Supression des attributs obsolètes"); + log("Supression des attributs obsol\xE8tes"); let attrs = findObjs({ _type: 'attribute', }); @@ -48840,13 +49472,13 @@ var COFantasy = COFantasy || function() { setDefaultTokenForCharacter(character, newToken); newToken.remove(); } else { - log('Impossible de créer un token pour ' + token.name); + log('Impossible de cr\xE9er un token pour ' + token.name); log(token); } removeAttrs(); }); }); - log("Mise à jour des attributs et tokens effectuée"); + log("Mise \xE0 jour des attributs et tokens effectu\xE9e"); } if (version < 2.11) { let attrs = findObjs({ @@ -48862,7 +49494,7 @@ var COFantasy = COFantasy || function() { }; a.set(na); }); - log("Mise à jour des attributs de capitaine effectuée"); + log("Mise \xE0 jour des attributs de capitaine effectu\xE9e"); } if (version < 2.12) { let attrs = findObjs({ @@ -48931,10 +49563,10 @@ var COFantasy = COFantasy || function() { } a.remove(); }); - log("Déplacement des attributs de consommables vers la fiche"); + log("D\xE9placement des attributs de consommables vers la fiche"); } if (version < 2.13) { - //On enlève les attributs obsolètes de la verison 4.00 de la fiche + //On enl\xE8ve les attributs obsol\xE8tes de la verison 4.00 de la fiche let attrs = findObjs({ _type: 'attribute', }); @@ -48974,7 +49606,7 @@ var COFantasy = COFantasy || function() { }); } if (version < 2.14) { - //Migration des éléments de règles optionnels + //Migration des \xE9l\xE9ments de r\xE8gles optionnels //Divers if (state.COFantasy.options.regles.val.poudre_explosif) { state.COFantasy.options.regles.val.divers.val.poudre_explosif.val = state.COFantasy.options.regles.val.poudre_explosif.val; @@ -49007,13 +49639,13 @@ var COFantasy = COFantasy || function() { delete state.COFantasy.options.regles.val.usure_DEF; } if (state.COFantasy.options.regles.val.generer_options_attaques) { - log("Options d'attaques supprimées ; veuiller utiliser le bouton 'Options' de la liste d'Actions à la place"); - sendChat('COFantasy', "Options d'attaques supprimées ; veuiller utiliser le bouton 'Options' de la liste d'Actions à la place"); + log("Options d'attaques supprim\xE9es ; veuiller utiliser le bouton 'Options' de la liste d'Actions \xE0 la place"); + sendChat('COFantasy', "Options d'attaques supprim\xE9es ; veuiller utiliser le bouton 'Options' de la liste d'Actions \xE0 la place"); delete state.COFantasy.options.regles.val.generer_options_attaques; } if (state.COFantasy.options.regles.val.generer_attaque_groupe) { - log("Attaques de groupe supprimées ; veuiller utiliser le bouton 'Options' de la liste d'Actions à la place"); - sendChat('COFantasy', "Options d'attaques supprimées ; veuiller utiliser le bouton 'Options' de la liste d'Actions à la place"); + log("Attaques de groupe supprim\xE9es ; veuiller utiliser le bouton 'Options' de la liste d'Actions \xE0 la place"); + sendChat('COFantasy', "Options d'attaques supprim\xE9es ; veuiller utiliser le bouton 'Options' de la liste d'Actions \xE0 la place"); delete state.COFantasy.options.regles.val.generer_attaque_groupe; } if (state.COFantasy.options.regles.val.bonus_attaque_groupe) { @@ -49042,7 +49674,7 @@ var COFantasy = COFantasy || function() { state.COFantasy.options.regles.val.mana.val.elixirs_sorts.val = state.COFantasy.options.regles.val.elixirs_sorts.val; delete state.COFantasy.options.regles.val.elixirs_sorts; } - log("Règles optionelles mises à jour"); + log("R\xE8gles optionelles mises \xE0 jour"); } if (version < 2.15) { let attrs = findObjs({ @@ -49084,7 +49716,7 @@ var COFantasy = COFantasy || function() { }); a.remove(); }); - log("Déplacement des attributs de consommables de PNJs vers la fiche"); + log("D\xE9placement des attributs de consommables de PNJs vers la fiche"); } if (version < 2.16) { let attrs = findObjs({ @@ -49095,7 +49727,7 @@ var COFantasy = COFantasy || function() { }); let handhoutComp = handouts.find(function(h) { let handName = h.get('name'); - return (handName == 'Compétences' || handName == 'Competences'); + return (handName == 'Comp\xE9tences' || handName == 'Competences'); }); if (handhoutComp) { let listeCompetences = { @@ -49108,7 +49740,7 @@ var COFantasy = COFantasy || function() { nombre: 0 }; handhoutComp.get('notes', function(note) { // asynchronous - let carac; //La carac dont on spécifie les compétences actuellement + let carac; //La carac dont on sp\xE9cifie les comp\xE9tences actuellement note = note.trim(); if (note.startsWith('

')) note = note.substring(3); note = note.trim().replace(/]*>|<\/span>/g, ''); @@ -49126,7 +49758,7 @@ var COFantasy = COFantasy || function() { } if (ligne.length === 0) return; if (carac === undefined) { - log("Compétences sans caractéristique associée"); + log("Comp\xE9tences sans caract\xE9ristique associ\xE9e"); return; } let comps = ligne.split(/, |\/| /); @@ -49204,9 +49836,9 @@ var COFantasy = COFantasy || function() { a.set('name', 'charisme'); return; } - //Les compétences + //Les comp\xE9tences let charId = a.get('characterid'); - //On ne bouge les compétences que pour les persos de type PJ + //On ne bouge les comp\xE9tences que pour les persos de type PJ let typePerso = findObjs({ _type: 'attribute', _characterid: charId, @@ -49232,7 +49864,7 @@ var COFantasy = COFantasy || function() { attrSpec.current = compToCarac[attrName]; createObj('attribute', attrSpec); let attrMalus; - if ((attrSpec.current == 'DEX' && attrName != 'crochetage' && attrName != 'désamorçage') || + if ((attrSpec.current == 'DEX' && attrName != 'crochetage' && attrName != 'd\xE9samor\xE7age') || (attrSpec.current == 'CON' && attrName == 'survie') || attrName == 'natation' || attrName == 'escalade') { attrSpec.name = prefix + 'malus'; @@ -49296,7 +49928,7 @@ var COFantasy = COFantasy || function() { } }); } - log("Mise à jour des attributs de compétence effectué"); + log("Mise \xE0 jour des attributs de comp\xE9tence effectu\xE9"); } if (version < 2.17) { let macros = findObjs({ @@ -49311,7 +49943,7 @@ var COFantasy = COFantasy || function() { if (macro !== newMacro) m.set("action", newMacro); }); - log("Mise à jour des ability Ténèbres effectuée"); + log("Mise \xE0 jour des ability T\xE9n\xE8bres effectu\xE9e"); } let updateReset = function(a, nom, typ) { let c = parseInt(a.get('current')); @@ -49353,7 +49985,7 @@ var COFantasy = COFantasy || function() { } }); } - log("Mise à jour des attributs effectuée"); + log("Mise \xE0 jour des attributs effectu\xE9e"); } if (version < 3.00) { let macros = findObjs({ @@ -49601,7 +50233,7 @@ var COFantasy = COFantasy || function() { characterid: cid, }); if (abilitiesInList.has(actionCmd) || abilitie.get('istokenaction')) { - //On garde le texte partagé de l'ability. + //On garde le texte partag\xE9 de l'ability. createObj('attribute', { name: pref + 'actiontitre', current: action, @@ -49648,7 +50280,7 @@ var COFantasy = COFantasy || function() { characterid: cid, }); // Macro - //D'abord le cas de #Attaque, car le nom affiché est celui de l'arme + //D'abord le cas de #Attaque, car le nom affich\xE9 est celui de l'arme if (actionCmd == '#Attaque' && actionCommands.length > 1) { createObj('attribute', { name: pref + 'actiontitre', @@ -49711,7 +50343,7 @@ var COFantasy = COFantasy || function() { state.COFantasy.options.affichage && state.COFantasy.options.affichage.val && state.COFantasy.options.affichage.val.actions_par_defaut.val) { - //Par défaut, on montrait la liste de toutes les abilities + //Par d\xE9faut, on montrait la liste de toutes les abilities abilities.forEach(function(a) { n++; let pref = 'repeating_actions_' + generateRowID() + '_'; @@ -49762,17 +50394,17 @@ var COFantasy = COFantasy || function() { } if (n > 0) attrRang.set('current', n); }); - log("Mise à jour des listes d'action effectuée"); - //Ensuite les prédicats booléens + log("Mise \xE0 jour des listes d'action effectu\xE9e"); + //Ensuite les pr\xE9dicats bool\xE9ens let predicates = '^(' + 'actionLibre|agripper|ambidextreDuelliste|animal|argumentDeTaille' + '|armureProtection|aucuneActionCombat|baroudHonneur' + '|botteMortelle|bouclierPsi|briseurDOs|bucheron|champion' + '|chasseurEmerite|chatimentDuMale|chimiste|ciblesMultiples' + '|combatEnPhalange|combatKinetique|commandant|controleDuMetabolisme' + - '|creatureArtificielle|crocEnJambe|defenseIntuitive|démon|devorer' + + '|creatureArtificielle|crocEnJambe|defenseIntuitive|d\xE9mon|devorer' + '|durACuire|ecuyer|elfeNoir|enchainement|energieDeLaMort' + - '|estUneIllusion|exsangue|fée|fievreChene|frappeChirurgicale|gober' + + '|estUneIllusion|exsangue|f\xE9e|fievreChene|frappeChirurgicale|gober' + '|graceFeline|graceFelineVoleur|grosMonstreGrosseArme|grosseTete' + '|hachesEtMarteaux|hausserLeTon|horsDePortee|humanoide' + '|ignorerLaDouleur|immuniteAuxArmes|immuniteAuxSournoises' + @@ -49823,7 +50455,7 @@ var COFantasy = COFantasy || function() { { let charId = attribute.get('characterid'); parChar[charId] = parChar[charId] || new Set(); - parChar[charId].add('géant'); + parChar[charId].add('g\xE9ant'); attribute.remove(); } break; @@ -49854,7 +50486,7 @@ var COFantasy = COFantasy || function() { attr.set('current', predText + attr.get('current')); } } - log("Transformation des attributs booléens en prédicats"); + log("Transformation des attributs bool\xE9ens en pr\xE9dicats"); } let getPredicateAttr = function(charId) { let attr = findObjs({ @@ -49922,7 +50554,7 @@ var COFantasy = COFantasy || function() { } attr.set('current', predText); } - log("Transformation des attributs numériques en prédicats"); + log("Transformation des attributs num\xE9riques en pr\xE9dicats"); } if (version < 3.02) { const regPJ = new RegExp("^(repeating_armes_[^_]*_)(.*)$"); @@ -49991,7 +50623,7 @@ var COFantasy = COFantasy || function() { taux = parseInt(cmd[2]); if (isNaN(taux) || taux < 0 || taux > 100) taux = 0; } else { - taux = 100; //La valeur par défaut en option. + taux = 100; //La valeur par d\xE9faut en option. } return false; }); @@ -50038,7 +50670,7 @@ var COFantasy = COFantasy || function() { } }); }); - log("Mise à jour des armes de jet effectuée"); + log("Mise \xE0 jour des armes de jet effectu\xE9e"); } if (version < 3.03) { findObjs({ @@ -50057,7 +50689,7 @@ var COFantasy = COFantasy || function() { if (arme.trim() !== '') predText += ':' + arme; attr.set('current', predText); }); - log("Mise à jour de prédicats effectuée"); + log("Mise \xE0 jour de pr\xE9dicats effectu\xE9e"); } if (version < 3.04) { let attrs = findObjs({ @@ -50138,7 +50770,7 @@ var COFantasy = COFantasy || function() { } attr.set('current', predText); } - log("Transformation d'attributs de combat en prédicats"); + log("Transformation d'attributs de combat en pr\xE9dicats"); } if (version < 3.05) { let attrs = findObjs({ @@ -50151,7 +50783,7 @@ var COFantasy = COFantasy || function() { log("Suppression des attributs pnj d'armure et de bouclier"); } if (version < 3.07) { - //Collecte des persos ayant un prédicat charge_ ou eclaire_ + //Collecte des persos ayant un pr\xE9dicat charge_ ou eclaire_ let charIds = {}; let attrs = findObjs({ _type: 'attribute', @@ -50244,7 +50876,7 @@ var COFantasy = COFantasy || function() { } } } - log("Copie des prédicats de charge et éclairage vers les attaques des armes"); + log("Copie des pr\xE9dicats de charge et \xE9clairage vers les attaques des armes"); } if (version < 3.08) { let attrs = findObjs({ @@ -50285,10 +50917,10 @@ var COFantasy = COFantasy || function() { a.set('current', preds); } }); - log("Changement du prédicat laissez-le-moi"); + log("Changement du pr\xE9dicat laissez-le-moi"); } if (version < 3.11) { - //aura sera passé en actions plus tard + //aura sera pass\xE9 en actions plus tard let predicates = '^(' + 'attributsDeStatut|chairACanonDe|defDeriveeDe|dmSiToucheContact' + '|ecuyerDe|ennemiJure|entrerEnCombatAvec|familier|guetteur' + @@ -50327,7 +50959,7 @@ var COFantasy = COFantasy || function() { for (let charId in parChar) { parChar[charId].attr.set('current', parChar[charId].predText); } - log("Transformation des attributs complexes en prédicats"); + log("Transformation des attributs complexes en pr\xE9dicats"); } if (version < 3.12) { if (state.COFantasy.foudresDuTemps) { @@ -50351,7 +50983,15 @@ var COFantasy = COFantasy || function() { charAttr: true }); }); - log("Mise à jour effectuée"); + log("Mise \xE0 jour effectu\xE9e"); + } + } + + function changePredicats(attr, prev) { + let curPred = attr.get('current'); + let prevPred = prev.current; + if (curPred.includes('attaqueEnMeute') != prevPred.includes('attaqueEnMeute')) { + recomputeAllies(); } } @@ -50371,7 +51011,8 @@ var COFantasy = COFantasy || function() { predicateOfRaw, listAllAttacks, getWeaponStats, - updateVersion + updateVersion, + changePredicats, }; }(); @@ -50397,7 +51038,7 @@ on('ready', function() { handout.forEach(function(hand) { COFantasy.changeHandout(hand); }); - //Vérification de la version sur les fiches + //V\xE9rification de la version sur les fiches characters.forEach(function(c) { COFantasy.scriptVersionToCharacter(c, 11); }); @@ -50416,8 +51057,8 @@ on("chat:message", function(msg) { try { COFantasy.apiCommand(msg); } catch (e) { - sendChat('COF', "Erreur durant l'exécution de " + msg.content); - log("Erreur durant l'exécution de " + msg.content); + sendChat('COF', "Erreur durant l'ex\xE9cution de " + msg.content); + log("Erreur durant l'ex\xE9cution de " + msg.content); log(msg); let errMsg = e.name; if (e.lineNumber) errMsg += " at " + e.lineNumber; @@ -50450,6 +51091,8 @@ on("change:attribute", function(attr, prev) { let predicats = state.COFantasy.predicats; if (!predicats) return; let n = attr.get("name"); - if (n == "predicats_script" || n.includes('armepredicats')) + if (n == "predicats_script" || n.includes('armepredicats')) { predicats[attr.get('characterid')] = undefined; + COFantasy.changePredicats(attr, prev); + } }); diff --git a/COFantasy/3.13/doc.html b/COFantasy/3.13/doc.html index c71932c9e..e9f19a181 100644 --- a/COFantasy/3.13/doc.html +++ b/COFantasy/3.13/doc.html @@ -4,7 +4,7 @@ - Scripts pour Chroniques Oubli\xE9es Fantasy sous Roll20 + Scripts pour Chroniques Oubliées Fantasy sous Roll20 @@ -57,26 +57,26 @@

Sommaire

  • Actions principales
  • -
  • Capacit\xE9s par Classe
  • +
  • Capacités par Classe
  • -
  • Autres capacit\xE9s
  • +
  • Autres capacités
  • Terres d'Arran
  • -
  • Markers personnalis\xE9s
  • +
  • Markers personnalisés
  • Console API
  • Conversion depuis Pathfinder
  • @@ -136,129 +136,129 @@

    1. Comment utiliser Le scr

    1.1 Tokens et personnages

    -

    Ces scripts ont \xE9t\xE9 \xE9crits pour fonctionner avec les fiches de personnages d\xE9velopp\xE9es par Natha.

    +

    Ces scripts ont été écrits pour fonctionner avec les fiches de personnages développées par Natha.

    -
    A choisir pendant la cr\xE9ation de la partie sur Roll20.
    +
    A choisir pendant la création de la partie sur Roll20.
    -

    Chaque token avec lequel vous souhaitez interagir doit repr\xE9senter un personnage.

    -

    La barre 1 repr\xE9sente toujours les points de vie du token.
    - La barre 2 est soit la mana, pour les personnages qui ont des points de mana, soit les d\xE9g\xE2ts temporaires pour les personnages qui n\x2019ont pas de points de mana
    - La barre 3 est utilis\xE9e pour donner un modificateur temporaire \xE0 l\x2019attaque du token. +

    Chaque token avec lequel vous souhaitez interagir doit représenter un personnage.

    +

    La barre 1 représente toujours les points de vie du token.
    + La barre 2 est soit la mana, pour les personnages qui ont des points de mana, soit les dégâts temporaires pour les personnages qui n’ont pas de points de mana
    + La barre 3 est utilisée pour donner un modificateur temporaire à l’attaque du token.

    -

    Les statuts des tokens sont en partie utilis\xE9s pour repr\xE9senter des \xE9tats. Voir plus loin pour la liste des statuts utilis\xE9s par les scripts.
    - Pour tenir compte d'autre \xE9tats non visibles sur les tokens, les scripts utilisent des attributs suppl\xE9mentaires (hors fiche). Parfois, le MJ devra cr\xE9er et remplir lui-m\xEAme certains attributs, d'autres fois cela sera g\xE9r\xE9 par les scripts. +

    Les statuts des tokens sont en partie utilisés pour représenter des états. Voir plus loin pour la liste des statuts utilisés par les scripts.
    + Pour tenir compte d'autre états non visibles sur les tokens, les scripts utilisent des attributs supplémentaires (hors fiche). Parfois, le MJ devra créer et remplir lui-même certains attributs, d'autres fois cela sera géré par les scripts.

    -

    Il est important de noter la diff\xE9rence entre les tokens li\xE9s \xE0 un personnage (la barre 1 est li\xE9e aux points de vie du personnage, tout changement sur la fiche se r\xE9percute sur le token), et les tokens non li\xE9s (dans ce cas, la fiche de personnage est g\xE9n\xE9rique, et chaque token est une instance diff\xE9rente, avec des PV ind\xE9pendants).

    -

    Pour g\xE9rer les \xE9tats sp\xE9cifiques \xE0 un token non li\xE9, les scripts utilisent des conventions de nom d'attribut utilisant le nom du token. Pour que cela fonctionne correctement, il est important que deux tokens ind\xE9pendants ne portent pas le m\xEAme nom, m\xEAme si ils repr\xE9sentent le m\xEAme personnage. Pour cette raison, le script va automatiquement renommer les tokens ind\xE9pendants, en leur associant un num\xE9ro. Il est toujours possible de remodifier le nom apr\xE8s la cr\xE9ation du token, mais dans ce cas, c'est vous qui g\xE9rez...

    -

    Certains messages tiennent compte du genre (masculin ou f\xE9minin) des personnages. Ils utilisent le champ Sexe de la fiche de personnage. Un personnage est reconnu comme f\xE9minin si ce champ commence par la lettre F. +

    Il est important de noter la différence entre les tokens liés à un personnage (la barre 1 est liée aux points de vie du personnage, tout changement sur la fiche se répercute sur le token), et les tokens non liés (dans ce cas, la fiche de personnage est générique, et chaque token est une instance différente, avec des PV indépendants).

    +

    Pour gérer les états spécifiques à un token non lié, les scripts utilisent des conventions de nom d'attribut utilisant le nom du token. Pour que cela fonctionne correctement, il est important que deux tokens indépendants ne portent pas le même nom, même si ils représentent le même personnage. Pour cette raison, le script va automatiquement renommer les tokens indépendants, en leur associant un numéro. Il est toujours possible de remodifier le nom après la création du token, mais dans ce cas, c'est vous qui gérez...

    +

    Certains messages tiennent compte du genre (masculin ou féminin) des personnages. Ils utilisent le champ Sexe de la fiche de personnage. Un personnage est reconnu comme féminin si ce champ commence par la lettre F.

    1.2 Macros et Abilities

    -

    Comme tous les scripts, ces scripts sont utilisables tels quels dans le chat, mais ils sont pens\xE9s pour \xEAtre utilis\xE9s par des macros qui permettent un autre niveau d'automatisation parfois difficile d'acc\xE8s au sein des scripts. le script g\xE9n\xE8re d'ailleurs la plupart des macros utiles \xE0 la premi\xE8re utilisation, et il met automatiquement les macros \xE0 jour \xE0 chaque changement de version. Il est possible de demander des les re-cr\xE9er en tapant la commande !cof-set-macros dans le chat.

    +

    Comme tous les scripts, ces scripts sont utilisables tels quels dans le chat, mais ils sont pensés pour être utilisés par des macros qui permettent un autre niveau d'automatisation parfois difficile d'accès au sein des scripts. le script génère d'ailleurs la plupart des macros utiles à la première utilisation, et il met automatiquement les macros à jour à chaque changement de version. Il est possible de demander des les re-créer en tapant la commande !cof-set-macros dans le chat.

    - Le script ne peut pas mettre les macros dans la barre de raccourci. Je recommande que chaque joueur se cr\xE9e sa macro Centrer, contenant le code !cof-centrer-sur-token nom_de_leur_token_principal, qui leur permettra en un click de centrer la vue de la carte sur leur token. Pour le MJ, le script sugg\xE8re de mettre un certain nombre des macros qu'il cr\xE9e, au moment de la premi\xE8re utilisation.

    -

    Une partie des capacit\xE9s et attaques des personnages devraient \xEAtre utilis\xE9es au sein d'abilities de personnages, accessibles comme "Token action". Si ces abilities utilisent des macros, ne pas oublier de rendre ces macros accessibles aux joueurs.

    + Le script ne peut pas mettre les macros dans la barre de raccourci. Je recommande que chaque joueur se crée sa macro Centrer, contenant le code !cof-centrer-sur-token nom_de_leur_token_principal, qui leur permettra en un click de centrer la vue de la carte sur leur token. Pour le MJ, le script suggère de mettre un certain nombre des macros qu'il crée, au moment de la première utilisation.

    +

    Une partie des capacités et attaques des personnages devraient être utilisées au sein d'abilities de personnages, accessibles comme "Token action". Si ces abilities utilisent des macros, ne pas oublier de rendre ces macros accessibles aux joueurs.

    -

    1.3 Pr\xE9dicats

    +

    1.3 Prédicats

    -

    Une fa\xE7on courante d'informer le script qu'un personnage dispose d'une capacit\xE9 particuli\xE8re (que ce soit d\xFB \xE0 son entra\xEEnement ou \xE0 un objet port\xE9) consiste \xE0 utiliser des pr\xE9dicats. Il s'agit de mots cl\xE9s \xE0 rentrer dans la zone de texte Pr\xE9dicats, visible depuis l'onglet Script de la fiche. Ces mots cl\xE9s peuvent \xEAtre s\xE9par\xE9s de blancs ou de retours \xE0 la ligne.

    -

    On peut associer une valeur \xE0 un pr\xE9dicat (le plus souvent un nombre, mais en fait n'importe quel mot qui ne contienne ni virgule, ni blanc, ni :). Pour cela, faire suivre le pr\xE9dicat de : puis de la valeur.

    -

    Dans chaque ligne de la zone de pr\xE9dicats, tout ce qui vient apr\xE8s // est consid\xE9r\xE9 comme du commentaire et ignor\xE9 (exception: les valeurs complexes, si le // vient apr\xE8s ::, voir plus bas).

    +

    Une façon courante d'informer le script qu'un personnage dispose d'une capacité particulière (que ce soit dû à son entraînement ou à un objet porté) consiste à utiliser des prédicats. Il s'agit de mots clés à rentrer dans la zone de texte Prédicats, visible depuis l'onglet Script de la fiche. Ces mots clés peuvent être séparés de blancs ou de retours à la ligne.

    +

    On peut associer une valeur à un prédicat (le plus souvent un nombre, mais en fait n'importe quel mot qui ne contienne ni virgule, ni blanc, ni :). Pour cela, faire suivre le prédicat de : puis de la valeur.

    +

    Dans chaque ligne de la zone de prédicats, tout ce qui vient après // est considéré comme du commentaire et ignoré (exception: les valeurs complexes, si le // vient après ::, voir plus bas).

    -
    Exemple de pr\xE9dicats.
    -

    Certains pr\xE9dicats ont des valeurs complexes, qui peuvent contenir des blancs, des virgules, des guillements, ou m\xEAme des : ou //. Afin de pouvoir utliser ces valeurs, vous pouvez faire suivre le nom du pr\xE9dicat de ::. Tout ce qui viendra apr\xE8s jusqu'\xE0 la fin de la ligne sera consid\xE9r\xE9 comme \xE9tant la valeur associ\xE9e \xE0 ce pr\xE9dicat. Un exemple typique d'utilisation : quand la valeur est un nom de personnage.

    -

    Il est aussi possible d'associer des pr\xE9dicats \xE0 des attaques. Ces pr\xE9dicats sont pris en compte quand ses attaques sont des armes, et ce que ces armes sont tenues en main. Cela permet de coder une grande vari\xE9t\xE9 d'effets magiques des armes. Attention, cela ne fonctionne pas pour les mooks avec les pr\xE9dicats animeAPartirDExistant, intercepter, lienEpique, attaqueEnTraitre, sansPeur, immuniteSaignement, et controleSanguin.

    +
    Exemple de prédicats.
    +

    Certains prédicats ont des valeurs complexes, qui peuvent contenir des blancs, des virgules, des guillements, ou même des : ou //. Afin de pouvoir utliser ces valeurs, vous pouvez faire suivre le nom du prédicat de ::. Tout ce qui viendra après jusqu'à la fin de la ligne sera considéré comme étant la valeur associée à ce prédicat. Un exemple typique d'utilisation : quand la valeur est un nom de personnage.

    +

    Il est aussi possible d'associer des prédicats à des attaques. Ces prédicats sont pris en compte quand ses attaques sont des armes, et ce que ces armes sont tenues en main. Cela permet de coder une grande variété d'effets magiques des armes. Attention, cela ne fonctionne pas pour les mooks avec les prédicats animeAPartirDExistant, intercepter, lienEpique, attaqueEnTraitre, sansPeur, immuniteSaignement, et controleSanguin.

    -
    Une \xE9p\xE9e +1 aff\xFBt\xE9e avec le pr\xE9dicat enchainement (actif pour toute attaque, tant que cette \xE9p\xE9e est en main).
    +
    Une épée +1 affûtée avec le prédicat enchainement (actif pour toute attaque, tant que cette épée est en main).
    -

    1.4 M\xE9thodes de s\xE9lection de groupes

    +

    1.4 Méthodes de sélection de groupes

    -

    Comme les joueurs ne peuvent pas s\xE9lectionner un nombre arbitraire d'ennemis, 7 m\xE9thodes sont disponibles :

    +

    Comme les joueurs ne peuvent pas sélectionner un nombre arbitraire d'ennemis, 7 méthodes sont disponibles :

      -
    • Le MJ lance la macro en s\xE9lectionnant les cibles
    • -
    • option --allies : cela fait chercher tous les handout dont le nom est Equipe suivi d'un nom, et tels que le handout contienne une liste de noms (un par ligne), parmis lesquels, celui du personnage qui agit. Le personnage qui agit est celui qui est s\xE9lectionn\xE9. Les cibles sont tous les alli\xE9s du personnage s\xE9lectionn\xE9, mais pas le personnage lui-m\xEAme. Attention, les noms de personnages ne doivent pas contenir de balise XML (texte encadr\xE9 par des < et >). Optionellement, on peut pr\xE9ciser une distance maximale entre le personnage s\xE9lectionn\xE9 et ses allies.
    • -
    • option --alliesEnVue : comme --allies, mais ne garde que les alli\xE9s en vue (en fonction des murs sur le layer lumi\xE8re).
    • -
    • option --equipe nom : agit sur tous les personnages mentionn\xE9s dans le handout s'appelant Equipe nom.
    • -
    • option --self : pour rajouter le personnage s\xE9lectionn\xE9. Utile si on veut le personnage et ses alli\xE9s, par exemple.
    • -
    • option --target : pour ajouter une seule cible, avec une id de token. Le personnage qui agit est celui qui est s\xE9lectionn\xE9.
    • -
    • option --disque : le premier argument, optionnel, est l'id ou le nom d'un token qui repr\xE9sente un personnage, le deuxi\xE8me argument un rayon. Cela s\xE9lectionne tous les tokens \xE0 une distance de moins que le rayon du premier argument (ou du personnage \xE0 l'origine de l'effet, si le premier argument est absent). Si un troisi\xE8me argument est donn\xE9, il est interpr\xE9t\xE9 comme la port\xE9e maximum entre le centre du disque et le token du personnage \xE0 l'origine de l'effet. Si le premier argument repr\xE9sente un personnage avec un max de PV \xE0 0, il est compris comme un personnage fictif cr\xE9\xE9 juste pour d\xE9finir le disque, et il sera supprim\xE9 apr\xE8s la s\xE9lection. \xC0 noter que le script cr\xE9e par d\xE9faut un tel personnage, utilisable par tous, et appel\xE9 Cible.
    • +
    • Le MJ lance la macro en sélectionnant les cibles
    • +
    • option --allies : cela fait chercher tous les handout dont le nom est Equipe suivi d'un nom, et tels que le handout contienne une liste de noms (un par ligne), parmis lesquels, celui du personnage qui agit. Le personnage qui agit est celui qui est sélectionné. Les cibles sont tous les alliés du personnage sélectionné, mais pas le personnage lui-même. Attention, les noms de personnages ne doivent pas contenir de balise XML (texte encadré par des < et >). Optionellement, on peut préciser une distance maximale entre le personnage sélectionné et ses allies.
    • +
    • option --alliesEnVue : comme --allies, mais ne garde que les alliés en vue (en fonction des murs sur le layer lumière).
    • +
    • option --equipe nom : agit sur tous les personnages mentionnés dans le handout s'appelant Equipe nom.
    • +
    • option --self : pour rajouter le personnage sélectionné. Utile si on veut le personnage et ses alliés, par exemple.
    • +
    • option --target : pour ajouter une seule cible, avec une id de token. Le personnage qui agit est celui qui est sélectionné.
    • +
    • option --disque : le premier argument, optionnel, est l'id ou le nom d'un token qui représente un personnage, le deuxième argument un rayon. Cela sélectionne tous les tokens à une distance de moins que le rayon du premier argument (ou du personnage à l'origine de l'effet, si le premier argument est absent). Si un troisième argument est donné, il est interprété comme la portée maximum entre le centre du disque et le token du personnage à l'origine de l'effet. Si le premier argument représente un personnage avec un max de PV à 0, il est compris comme un personnage fictif créé juste pour définir le disque, et il sera supprimé après la sélection. À noter que le script crée par défaut un tel personnage, utilisable par tous, et appelé Cible.
    • option --disquePasseMur : comme --disque, mais l'effet traverse les murs.
    • -
    • option --enVue : s\xE9lectionne tous les tokens en vue du personnage qui lance l'effet. Accepte aussi un argument d'id de token, dans ce cas on garde les token en vue de celui avec cette id.
    • -
    • option --saufAllies permet d'exclure les alli\xE9s de la s\xE9lection (voir plus haut pour la d\xE9finition des alli\xE9s).
    • +
    • option --enVue : sélectionne tous les tokens en vue du personnage qui lance l'effet. Accepte aussi un argument d'id de token, dans ce cas on garde les token en vue de celui avec cette id.
    • +
    • option --saufAllies permet d'exclure les alliés de la sélection (voir plus haut pour la définition des alliés).

    -
    Exemple d'handout avec diff\xE9rentes \xE9quipes.
    +
    Exemple d'handout avec différentes équipes.

    1.5 Options de mana

    -

    COF sous ses diff\xE9rentes formes est une bo\xEEte \xE0 outils et nombreuses sont les variantes de syst\xE8me de magie qui peuvent \xEAtre utilis\xE9es. Le script propose un support pour les plus populaires d'entre elles. Voici quelques consignes pour les impl\xE9menter.

    -

    Sp\xE9cifier un co\xFBt en mana

    +

    COF sous ses différentes formes est une boîte à outils et nombreuses sont les variantes de système de magie qui peuvent être utilisées. Le script propose un support pour les plus populaires d'entre elles. Voici quelques consignes pour les implémenter.

    +

    Spécifier un coût en mana

      -
    • Les points de mana sont d\xE9pens\xE9s en ajoutant l'option --mana X \xE0 une action ou dans les options d'une attaque. Toutes les capacit\xE9s impl\xE9ment\xE9es dans la documentation donnent par d\xE9faut le co\xFBt en mana selon les r\xE8gles de base.
    • -
    • M\xEAme un sort qui ne co\xFBte pas de mana devrait utiliser --mana 0. Cela permet au script de dissiper automatiquement un effet g\xE9n\xE9r\xE9 par un lanceur de sort mis hors de combat.
    • -
    • Une option d'affichage disponible via !cof-options permet de demander au script d'afficher explicitement dans le chat toute d\xE9pense de PM effectu\xE9e par un personnage.
    • +
    • Les points de mana sont dépensés en ajoutant l'option --mana X à une action ou dans les options d'une attaque. Toutes les capacités implémentées dans la documentation donnent par défaut le coût en mana selon les règles de base.
    • +
    • Même un sort qui ne coûte pas de mana devrait utiliser --mana 0. Cela permet au script de dissiper automatiquement un effet généré par un lanceur de sort mis hors de combat.
    • +
    • Une option d'affichage disponible via !cof-options permet de demander au script d'afficher explicitement dans le chat toute dépense de PM effectuée par un personnage.
    -

    Syst\xE8me de base (COF p. 79)

    -

    Le support des effets suppl\xE9mentaires \xE0 disposition du lanceur de sort sont g\xE9r\xE9es via l'utilisation d'options sur les commandes utilis\xE9es.

    +

    Système de base (COF p. 79)

    +

    Le support des effets supplémentaires à disposition du lanceur de sort sont gérées via l'utilisation d'options sur les commandes utilisées.

    • Magie rapide : pas de support particulier
    • -
    • Magie puissante (d\xE9s) : utiliser l'option --puissant dans vos abilities ou attaques
    • -
    • Magie puissante (port\xE9e) : utiliser l'option --puissant portee dans vos abilities ou attaques
    • -
    • Magie puissante (dur\xE9e) : utiliser l'option --puissant duree dans vos abilities ou attaques
    • +
    • Magie puissante (dés) : utiliser l'option --puissant dans vos abilities ou attaques
    • +
    • Magie puissante (portée) : utiliser l'option --puissant portee dans vos abilities ou attaques
    • +
    • Magie puissante (durée) : utiliser l'option --puissant duree dans vos abilities ou attaques
    -

    On peut facilement combiner ces options avec un input de choix roll20 qui permettra au joueur de choisir le type d'incantation lorsqu'il lance le sort, tout en sp\xE9cifiant la d\xE9pense de Mana.

    -

    --mana X ?{Incantation ?|Rapide,&#32;|Puissante (L),--puissant|Port\xE9e \xE9tendue (L),--puissant portee|Dur\xE9e \xE9tendue (L),--puissant duree}

    +

    On peut facilement combiner ces options avec un input de choix roll20 qui permettra au joueur de choisir le type d'incantation lorsqu'il lance le sort, tout en spécifiant la dépense de Mana.

    +

    --mana X ?{Incantation ?|Rapide,&#32;|Puissante (L),--puissant|Portée étendue (L),--puissant portee|Durée étendue (L),--puissant duree}

    Mana Totale (COF p. 180)

    -

    La premi\xE8re chose \xE0 faire est d'activer l'option Mana totale via !cof-options. Pour le reste, vous pouvez r\xE9utiliser le principe du syst\xE8me de base ci-dessus.

    -
    Co\xFBt al\xE9atoire
    -

    Vous pouvez utiliser des lancers de d\xE9s dans vos options --mana. Par exemple pour un sort de rang 1, on peut renseigner --mana [[1d3]]. L'option d'affichage de la d\xE9pense de mana prend ici tout son sens, activable via !cof-options.

    +

    La première chose à faire est d'activer l'option Mana totale via !cof-options. Pour le reste, vous pouvez réutiliser le principe du système de base ci-dessus.

    +
    Coût aléatoire
    +

    Vous pouvez utiliser des lancers de dés dans vos options --mana. Par exemple pour un sort de rang 1, on peut renseigner --mana [[1d3]]. L'option d'affichage de la dépense de mana prend ici tout son sens, activable via !cof-options.

    Contrecoup
    -

    Vous pouvez activer la r\xE8gle sp\xE9cifique de Contrecoup via !cof-options.

    -

    Temp\xEAte de Mana (COF Compagnon p. 105)

    -

    Le script impl\xE9mente un support complet des r\xE8gles de Temp\xEAte de Mana. Pour ce faire, il faut ajouter les options --tempeteDeMana --rang X sur les sorts combinables avec Temp\xEAte de Mana. L'option rang permet d'indiquer le rang du sort afin que le script puisse calculer le maximum de PM qu'on peut d\xE9penser lors du lancement du sort. Pour mettre \xE7a de mani\xE8re g\xE9n\xE9rique sur une action ou une attaque et permettre au joueur de choisir de faire appel \xE0 Temp\xEAte de Mana ou pas, on peut utiliser :

    -

    --mana X --rang Y ?{Temp\xEAte de Mana ?|Non,&#32;|Oui,--tempeteDeMana}

    -

    Temp\xEAte de Mana est compatible avec Mana Totale et Br\xFBlure de Magie.

    +

    Vous pouvez activer la règle spécifique de Contrecoup via !cof-options.

    +

    Tempête de Mana (COF Compagnon p. 105)

    +

    Le script implémente un support complet des règles de Tempête de Mana. Pour ce faire, il faut ajouter les options --tempeteDeMana --rang X sur les sorts combinables avec Tempête de Mana. L'option rang permet d'indiquer le rang du sort afin que le script puisse calculer le maximum de PM qu'on peut dépenser lors du lancement du sort. Pour mettre ça de manière générique sur une action ou une attaque et permettre au joueur de choisir de faire appel à Tempête de Mana ou pas, on peut utiliser :

    +

    --mana X --rang Y ?{Tempête de Mana ?|Non,&#32;|Oui,--tempeteDeMana}

    +

    Tempête de Mana est compatible avec Mana Totale et Brûlure de Magie.

    Option altruiste
    -

    Si vous d\xE9sirez jouer avec l'option de Magie altruiste, il suffit de changer l'option en --tempeteDeMana altruiste sur les sorts o\xF9 c'est utile.

    +

    Si vous désirez jouer avec l'option de Magie altruiste, il suffit de changer l'option en --tempeteDeMana altruiste sur les sorts où c'est utile.

    Terres d'Arran (COTA p. 112)

    -

    Premi\xE8re chose \xE0 faire, activer l'option Br\xFBlure de Magie via !cof-options. Note : si vous utilisez l'option de Br\xFBlure de Magie avec l'option Mana Totale, vous pouvez utiliser un pr\xE9dicat coefPVMana qui va diviser le nombre de PVs d\xE9pens\xE9 par point de mana.

    -

    Vous pouvez ensuite r\xE9utiliser le m\xEAme principe que le syst\xE8me de base en combinant d\xE9pense de Mana et effets suppl\xE9mentaires. Voici un exemple pour une Boule de Feu (Voie de l'\xE9l\xE9mentaliste, rang 4) :

    -

    --mana 2 ?{Incantation ?|Normale,--mana 2|\xC9conome (L),&#32;|Puissante (L),--mana 2 --puissant|Port\xE9e \xE9tendue (L),--mana 2 --puissant portee} (notez que les co\xFBt total pour une incantation normale sera de 4 points de mana)

    +

    Première chose à faire, activer l'option Brûlure de Magie via !cof-options. Note : si vous utilisez l'option de Brûlure de Magie avec l'option Mana Totale, vous pouvez utiliser un prédicat coefPVMana qui va diviser le nombre de PVs dépensé par point de mana.

    +

    Vous pouvez ensuite réutiliser le même principe que le système de base en combinant dépense de Mana et effets supplémentaires. Voici un exemple pour une Boule de Feu (Voie de l'élémentaliste, rang 4) :

    +

    --mana 2 ?{Incantation ?|Normale,--mana 2|Économe (L),&#32;|Puissante (L),--mana 2 --puissant|Portée étendue (L),--mana 2 --puissant portee} (notez que les coût total pour une incantation normale sera de 4 points de mana)

    -

    1.6 R\xE8gles optionnelles utilis\xE9es

    +

    1.6 Règles optionnelles utilisées

    -

    Le script supporte l'utilisation de la r\xE8gle des points de chance et des points de r\xE9cup\xE9ration.

    -

    J'ai aussi choisi, comme propos\xE9 par Kegron, de diminuer la DEF de tous les protagonistes apr\xE8s un certain nombre de tours de combat (-2 tous les 5 tours, peut \xEAtre d\xE9sactiv\xE9 pendant un combat par la commande !cof-usure-off, ou bien dans les options de jeu).

    -

    Le script utilise aussi par d\xE9faut une r\xE8gle de blessure grave : chaque fois qu'un personnage tombe \xE0 0 PV, il encaisse une perte d'un point de r\xE9cup\xE9ration. S'il \xE9tait \xE0 0 points de r\xE9cup\xE9ration, il devient gravement bless\xE9, ce qui le rend affaibli. Si le personnage \xE9tait d\xE9j\xE0 gravement bless\xE9, il meurt. Pour r\xE9cup\xE9rer d'une blessure grave, le personnage doit se reposer une nuit, et r\xE9ussir un test de CON difficult\xE9 8 (avec le d12). Il est impossible de r\xE9g\xE9n\xE9rer les points de r\xE9cup\xE9ration quand on est gravement bless\xE9.

    -

    Le script utilise \xE9galement une r\xE8gle de dommages importants : chaque fois qu'un PJ re\xE7oit plus de dommages en une fois que la somme de sa valeur de constitution et de son niveau, il perd 1PR et la r\xE8gle de blessure grave s'applique. S'il \xE9tait d\xE9j\xE0 bless\xE9 mais qu'il lui reste des PV, il tombe inconscient. Les deux r\xE8gles sont d\xE9sactivables s\xE9par\xE9ment via !cof-options, dans la section dommages.

    -

    Le script propose \xE9galement quelques autres options qui sont activables et/ou modifiables via la commande !cof-options. Quelques exemples :

    +

    Le script supporte l'utilisation de la règle des points de chance et des points de récupération.

    +

    J'ai aussi choisi, comme proposé par Kegron, de diminuer la DEF de tous les protagonistes après un certain nombre de tours de combat (-2 tous les 5 tours, peut être désactivé pendant un combat par la commande !cof-usure-off, ou bien dans les options de jeu).

    +

    Le script utilise aussi par défaut une règle de blessure grave : chaque fois qu'un personnage tombe à 0 PV, il encaisse une perte d'un point de récupération. S'il était à 0 points de récupération, il devient gravement blessé, ce qui le rend affaibli. Si le personnage était déjà gravement blessé, il meurt. Pour récupérer d'une blessure grave, le personnage doit se reposer une nuit, et réussir un test de CON difficulté 8 (avec le d12). Il est impossible de régénérer les points de récupération quand on est gravement blessé.

    +

    Le script utilise également une règle de dommages importants : chaque fois qu'un PJ reçoit plus de dommages en une fois que la somme de sa valeur de constitution et de son niveau, il perd 1PR et la règle de blessure grave s'applique. S'il était déjà blessé mais qu'il lui reste des PV, il tombe inconscient. Les deux règles sont désactivables séparément via !cof-options, dans la section dommages.

    +

    Le script propose également quelques autres options qui sont activables et/ou modifiables via la commande !cof-options. Quelques exemples :

    • Initiative variable (individuelle / de groupe)
    • -
    • Versions alternatives de capacit\xE9s (interchangeable, forme d'arbre, rune de protection)
    • -
    • Critiques \xE9tendus
    • +
    • Versions alternatives de capacités (interchangeable, forme d'arbre, rune de protection)
    • +
    • Critiques étendus
    • Dommages minimums
    • Attaques de groupe

    2. Actions principales

    -

    Pour la plupart des actions ci-dessous, il est g\xE9n\xE9ralement utile de cr\xE9er des macros facilitant leur utilisation. Pour mettre en place un jeu de macros par d\xE9faut, vous pouvez taper !cof-set-macros dans le chat. Si vous souhaitez red\xE9finir des macros existantes, vous pouvez taper !cof-set-macros --force.

    +

    Pour la plupart des actions ci-dessous, il est généralement utile de créer des macros facilitant leur utilisation. Pour mettre en place un jeu de macros par défaut, vous pouvez taper !cof-set-macros dans le chat. Si vous souhaitez redéfinir des macros existantes, vous pouvez taper !cof-set-macros --force.

    2.1 Le combat

    Initiative : !cof-init

    -

    Les tokens s\xE9lectionn\xE9s sont ajout\xE9 au tracker de tour. Si celui-ci n'existe pas, un nouveau est cr\xE9\xE9, avec compteur de tour \xE0 1, et on rentre en combat. Les tokens ayant un pr\xE9dicat aucuneActionCombat ne sont jamais ajout\xE9s au turn tracker.

    -

    Une option du script (ajustable en utilisant !cof-options) permet d'utiliser la r\xE8gle de l'initiative variable (ajout d'un d6 explosif \xE0 l'initiative). Il est alors possible de faire lancer les d\xE9s d'initiative par les joueurs.

    -

    Les r\xE8gles de tri suivent ce qui est donn\xE9 p 70 : priorit\xE9 aux PJs. Pour l'instant, on distingue un PJ d'un PNJ au d\xE9 de vie : si le personnage d'a pas de d\xE9 de vie, c'est un PNJ. Ensuite, entre PJs, priorit\xE9 \xE0 la plus haute sagesse. Pour les PNJ, c'est al\xE9atoire.

    -

    \xC0 chaque instant, le token dont c'est le tour d'agir est signal\xE9 par une aura qui bouge lentement. L'image de cette aura peut \xEAtre modifi\xE9e dans les options (!cof-options images), et il est possible de sp\xE9cifier une aura pour chaque token, en ajoutant une ligne dans le champ GM Notes du token (en bas de la partie basique de l'\xE9dition du token). Cette ligne doit commencer par init_aura:, et contenir une url valide pour un token. N'oubliez pas de sauvegarder le token comme token par d\xE9faut our un personnage si vous voulez que ce personnage ait toujours cette aura.

    +

    Les tokens sélectionnés sont ajouté au tracker de tour. Si celui-ci n'existe pas, un nouveau est créé, avec compteur de tour à 1, et on rentre en combat. Les tokens ayant un prédicat aucuneActionCombat ne sont jamais ajoutés au turn tracker.

    +

    Une option du script (ajustable en utilisant !cof-options) permet d'utiliser la règle de l'initiative variable (ajout d'un d6 explosif à l'initiative). Il est alors possible de faire lancer les dés d'initiative par les joueurs.

    +

    Les règles de tri suivent ce qui est donné p 70 : priorité aux PJs. Pour l'instant, on distingue un PJ d'un PNJ au dé de vie : si le personnage d'a pas de dé de vie, c'est un PNJ. Ensuite, entre PJs, priorité à la plus haute sagesse. Pour les PNJ, c'est aléatoire.

    +

    À chaque instant, le token dont c'est le tour d'agir est signalé par une aura qui bouge lentement. L'image de cette aura peut être modifiée dans les options (!cof-options images), et il est possible de spécifier une aura pour chaque token, en ajoutant une ligne dans le champ GM Notes du token (en bas de la partie basique de l'édition du token). Cette ligne doit commencer par init_aura:, et contenir une url valide pour un token. N'oubliez pas de sauvegarder le token comme token par défaut our un personnage si vous voulez que ce personnage ait toujours cette aura.

    Il est possible de laisser les joueurs passer leur tour, en utilisant la commande !cof-tour-suivant. Une utilisation possible est de le mettre en macro dans les actions du tour (voir Actions du tour ci-dessous).

    Astuces :
      -
    • !cof-attendre ?{Nouvelle initiative} : Permet d'attendre avant d'agir en r\xE9duisant temporairement son initiative.

    • -
    • Il est possible de se passer de l'aura qui bouge, et d'utiliser \xE0 la place une ic\xF4ne de drapeau ou avec la syntaxe - !cof-init --aura une aura autour du Token de couleur verte (ou rouge si le personnage n'est pas contr\xF4l\xE9 par un joueur ou dans une \xE9quipe contenant un personnage contr\xF4l\xE9 par un joueur). Pour cela, d\xE9sactiver l'initiative dynamique dans les options d'affichage (!cof-options affichage). +
    • !cof-attendre ?{Nouvelle initiative} : Permet d'attendre avant d'agir en réduisant temporairement son initiative.

    • +
    • Il est possible de se passer de l'aura qui bouge, et d'utiliser à la place une icône de drapeau ou avec la syntaxe + !cof-init --aura une aura autour du Token de couleur verte (ou rouge si le personnage n'est pas contrôlé par un joueur ou dans une équipe contenant un personnage contrôlé par un joueur). Pour cela, désactiver l'initiative dynamique dans les options d'affichage (!cof-options affichage).
    @@ -266,349 +266,353 @@
    Astuces :

    Liste d'actions pour le personnage dont c'est le tour

    -

    Le script affiche, pour le personnage dont c'est le tour, une liste d'actions. Cette liste est chuchot\xE9e au joueur qui contr\xF4le le personnage, ou si aucun joueur le contr\xF4lant n'est connect\xE9, au MJ. Elle se compose par d\xE9faut des attaques du personnage et des actions d'attendre, se d\xE9fendre et faire une manoeuvre. - Pour voir ce message en dehors du changement d'initiative, ou pour le MJ, on peut utiliser !cof-liste-actions en s\xE9lectionnant le token (un bon candidat pour une macro de type token action, d'ailleurs g\xE9n\xE9r\xE9 par la commande !cof-set-macros). - Pour contr\xF4ler ce qui est affich\xE9 dans cette liste, vous pouvez principalement utiliser la liste des attaques du personnage et surtout la partie script de la fiche.

    -
    Les attaques affich\xE9es
    -

    Il est possible de ne pas afficher une attaque en d\xE9cochant la case sous le d\xE9 dans les options d'attaque. Les attaques sont affich\xE9es dans l'ordre des labels d'attaques. les attaques avec des conditions impossibles (du genre limite par jour \xE9puis\xE9e, etc.) ne sont pas affich\xE9es.

    -

    \xC0 cela se rajoute \xE9ventuellement l'attaque avec l'arme en main. \xC0 c\xF4t\xE9 de cette attaque, le script propose un bouton pour rengainer l'arme ou en d\xE9gainer une autre (parmis les armes de la fiche coch\xE9es). On peut modifier cette liste des armes \xE0 d\xE9gainer en utilisant des pr\xE9dicats actionDegainern, de valeur le label de l'arme \xE0 afficher en position n dans la liste (seulement pour les premi\xE8res armes, il n'est pas possible de ne sp\xE9cifier que la 2nde arme ou la 1\xE8re et le 3\xE8me). On peut ainsi faire afficher 2 armes \xE0 d\xE9gainer en m\xEAme temps en s\xE9parant les labels d'un - (par exemple pour faire d\xE9gainer l'arme 1 en main droite et l'arme 4 en main gauche, en premi\xE8re position dans la liste, on \xE9crira actionDegainer1:1-4). \xC0 noter que si aucune arme n'est en main, et qu'aucune attaque naturelle n'est coch\xE9e, le script va tout de m\xEAme afficher une des attaques naturelles non coch\xE9es \xE0 la place de l'arme en main. Cela permet d'avoir une attaque que l'on n'affiche que quand on n'a pas d'arme en main.

    -

    Notez qu'il est possible d'avoir une arme par d\xE9faut en main, en ajoutant un pr\xE9dicat armeParDefaut, de valeur le label de l'attaque correspondante. C'est parfois bien pratique pour ne pas avoir \xE0 d\xE9gainer les armes de chacun des orques en embuscade, par exemple.

    -
    Choisir les actions \xE0 afficher
    -

    Pour changer les attaques affich\xE9es par d\xE9faut, rajouter des actions \xE0 la liste d'actions du tour, ou utiliser de nouvelles listes, il faut aller dans l'onglet Script de la fiche de personnage.

    +

    Le script affiche, pour le personnage dont c'est le tour, une liste d'actions. Cette liste est chuchotée au joueur qui contrôle le personnage, ou si aucun joueur le contrôlant n'est connecté, au MJ. Elle se compose par défaut des attaques du personnage et des actions d'attendre, se défendre et faire une manoeuvre. + Pour voir ce message en dehors du changement d'initiative, ou pour le MJ, on peut utiliser !cof-liste-actions en sélectionnant le token (un bon candidat pour une macro de type token action, d'ailleurs généré par la commande !cof-set-macros). + Pour contrôler ce qui est affiché dans cette liste, vous pouvez principalement utiliser la liste des attaques du personnage et surtout la partie script de la fiche.

    +
    Les attaques affichées
    +

    Il est possible de ne pas afficher une attaque en décochant la case sous le dé dans les options d'attaque. Les attaques sont affichées dans l'ordre des labels d'attaques. les attaques avec des conditions impossibles (du genre limite par jour épuisée, etc.) ne sont pas affichées.

    +

    À cela se rajoute éventuellement l'attaque avec l'arme en main. À côté de cette attaque, le script propose un bouton pour rengainer l'arme ou en dégainer une autre (parmis les armes de la fiche cochées). On peut modifier cette liste des armes à dégainer en utilisant des prédicats actionDegainern, de valeur le label de l'arme à afficher en position n dans la liste (seulement pour les premières armes, il n'est pas possible de ne spécifier que la 2nde arme ou la 1ère et le 3ème). On peut ainsi faire afficher 2 armes à dégainer en même temps en séparant les labels d'un - (par exemple pour faire dégainer l'arme 1 en main droite et l'arme 4 en main gauche, en première position dans la liste, on écrira actionDegainer1:1-4). À noter que si aucune arme n'est en main, et qu'aucune attaque naturelle n'est cochée, le script va tout de même afficher une des attaques naturelles non cochées à la place de l'arme en main. Cela permet d'avoir une attaque que l'on n'affiche que quand on n'a pas d'arme en main.

    +

    Notez qu'il est possible d'avoir une arme par défaut en main, en ajoutant un prédicat armeParDefaut, de valeur le label de l'attaque correspondante. C'est parfois bien pratique pour ne pas avoir à dégainer les armes de chacun des orques en embuscade, par exemple.

    +
    Choisir les actions à afficher
    +

    Pour changer les attaques affichées par défaut, rajouter des actions à la liste d'actions du tour, ou utiliser de nouvelles listes, il faut aller dans l'onglet Script de la fiche de personnage.

    Exemple d'une liste d'actions pour un magicien
    -

    Pour rajouter des actions \xE0 montrer, il faut ajouter des lignes en-dessous de Montrer l'arme en main et d\xE9gainer. La case coch\xE9e devant chaque action peut \xEAtre d\xE9coch\xE9e pour ne pas afficher l'action. Les actions seront affich\xE9e dans l'ordre des num\xE9ros d'action. Attention, si deux actions ont le m\xEAme num\xE9ro, une des deux ne sera pas affich\xE9e. Le titre de l'action peut soit \xEAtre directement une commande (commen\xE7ant par %, # ou !), et dans ce cas l'action affich\xE9e sera d\xE9termin\xE9e par le script, soit du texte qui sera affich\xE9 tel quel. Dans ce cas, il sera souvent n\xE9cessaire de pr\xE9ciser le code de l'action : cliquer sur la roue au bout \xE0 droite de la ligne de l'action pour faire appara\xEEtre les lignes de condition et de code. La ligne de conditions n'est pas encore utilis\xE9e par le script.

    -

    Il existe un certain nombre de commandes sp\xE9ciales, qui peuvent \xEAtre rentr\xE9e dans le titre ou le code : +

    Pour rajouter des actions à montrer, il faut ajouter des lignes en-dessous de Montrer l'arme en main et dégainer. La case cochée devant chaque action peut être décochée pour ne pas afficher l'action. Les actions seront affichée dans l'ordre des numéros d'action. Attention, si deux actions ont le même numéro, une des deux ne sera pas affichée. Le titre de l'action peut soit être directement une commande (commençant par %, # ou !), et dans ce cas l'action affichée sera déterminée par le script, soit du texte qui sera affiché tel quel. Dans ce cas, il sera souvent nécessaire de préciser le code de l'action : cliquer sur la roue au bout à droite de la ligne de l'action pour faire apparaître les lignes de condition et de code. La ligne de conditions n'est pas encore utilisée par le script.

    +

    Il existe un certain nombre de commandes spéciales, qui peuvent être rentrée dans le titre ou le code :

      -
    • !attaques fera afficher toutes les attaques coch\xE9es de la fiche
    • -
    • !arme-en-main affichera l'attaque correspondant \xE0 l'arme en main, ou si aucune arme n'est en main, une attaque naturelle non coch\xE9e, et si il n'y en a pas non plus, une attaque \xE0 mains nues. Vous pouvez faire suivre cette commandes d'options d'attaque, comme --m2d20.
    • -
    • !options passera en option \xE0 toutes les actions suivantes tout ce que vous \xE9crirez dans la m\xEAme ligne (par exemple !options --traquenard passe l'option --traquenard \xE0 toutes les actions suivantes).
    • +
    • !attaques fera afficher toutes les attaques cochées de la fiche
    • +
    • !arme-en-main affichera l'attaque correspondant à l'arme en main, ou si aucune arme n'est en main, une attaque naturelle non cochée, et si il n'y en a pas non plus, une attaque à mains nues. Vous pouvez faire suivre cette commandes d'options d'attaque, comme --m2d20.
    • +
    • !options passera en option à toutes les actions suivantes tout ce que vous écrirez dans la même ligne (par exemple !options --traquenard passe l'option --traquenard à toutes les actions suivantes).

    Autres listes d'action
    -

    Il est possible d'ouvrir d'autre listes d'actions, \xE0 partir des commandes ou m\xEAme d'une liste d'actions. La fiche propose 4 emplacements pour ces listes d'action, mais si cela ne suffit pas, vous pouvez utiliser des abilities dont le nom commence et termine par #. Pour faire r\xE9f\xE9rence \xE0 une liste dans une action, inscrivez simplement le nom de la liste dans le titre de l'action et s\xE9lectionnez Liste d'actions dans le menu d\xE9roulant \xE0 c\xF4t\xE9. Les listes d'action sur la fiche fonctionnent de la m\xEAme fa\xE7on que la liste des actions du tour, sauf qu'il n'y a pas d'affichage par d\xE9faut des attaques ou de l'arme en main (pour cela, une simple ligne avec en titre #Attaque -1 permet d'y rem\xE9dier), et que la liste peut avoir une liste d'options globales (cliquer sur la roue \xE0 droite du nom de la liste).

    -

    Pour les listes d'actions suppl\xE9mentaires, dans les abilities, il faut respecter la syntaxe suivante : +

    Il est possible d'ouvrir d'autre listes d'actions, à partir des commandes ou même d'une liste d'actions. La fiche propose 4 emplacements pour ces listes d'action, mais si cela ne suffit pas, vous pouvez utiliser des abilities dont le nom commence et termine par #. Pour faire référence à une liste dans une action, inscrivez simplement le nom de la liste dans le titre de l'action et sélectionnez Liste d'actions dans le menu déroulant à côté. Les listes d'action sur la fiche fonctionnent de la même façon que la liste des actions du tour, sauf qu'il n'y a pas d'affichage par défaut des attaques ou de l'arme en main (pour cela, une simple ligne avec en titre #Attaque -1 permet d'y remédier), et que la liste peut avoir une liste d'options globales (cliquer sur la roue à droite du nom de la liste).

    +

    Pour les listes d'actions supplémentaires, dans les abilities, il faut respecter la syntaxe suivante :

    • une action par ligne
    • chaque ligne est donc soit un commentaire, soit une macro (qui commence par #), soit une ability (qui commence par %), soit une commande qui commence par !
    • -
    • l'action affich\xE9e sera le nom de la macro ou de l'ability (sauf pour les attaques, pour lesquelles le nom de l'arme sera affich\xE9e)
    • +
    • l'action affichée sera le nom de la macro ou de l'ability (sauf pour les attaques, pour lesquelles le nom de l'arme sera affichée)
    • les commandes disponibles sont !options et !attaques.
    • -
    • pour les listes d'actions, il suffit de mettre %# suivi du nom de la liste et termin\xE9 par #.
    • +
    • pour les listes d'actions, il suffit de mettre %# suivi du nom de la liste et terminé par #.
    -

    Il est aussi possible de faire afficher une liste quelconque avec une commande, avec !cof-liste-actions nom (o\xF9 le nom est celui de la liste, ou bien de l'ability sans les #). Par exemple, si on ne souhaite pas afficher la liste compl\xE8te des sorts d'un personnage \xE0 son tour, on peut faire une liste Sorts, puis faire une macro qui lance !cof-liste-actions Sorts pour que le joueur puisse afficher la liste quand il le souhaite.

    +

    Il est aussi possible de faire afficher une liste quelconque avec une commande, avec !cof-liste-actions nom (où le nom est celui de la liste, ou bien de l'ability sans les #). Par exemple, si on ne souhaite pas afficher la liste complète des sorts d'un personnage à son tour, on peut faire une liste Sorts, puis faire une macro qui lance !cof-liste-actions Sorts pour que le joueur puisse afficher la liste quand il le souhaite.

    Attaquer une (ou plusieurs) cible : !cof-attack @{selected|token_id} @{target|token_id} n

    -

    o\xF9 n est un argument optionnel qui peut soit correspondre au label de l'attaque sur la fiche du personnage (ce label est automatiquement g\xE9n\xE9r\xE9 par la fiche et affich\xE9 juste devant le nom), soit \xEAtre le nom de l'attaque. Si cet argument est -1, le script cherchera si le personnage a une arme en main et utilisera cette arme. Si c'est -2, il va chercher l'arme en main gauche. Si cet argument est absent ou qu'il ne correspond pas \xE0 un label de la fiche du personnage, l'attaque aura les valeurs par d\xE9faut d'une attaque au contact infligeant 1d4 DM. Pour plus de facilit\xE9, vous pouvez utiliser la macro Attaque qui fait !cof-attack @{selected|token_id} @{target|token_id}

    +

    n est un argument optionnel qui peut soit correspondre au label de l'attaque sur la fiche du personnage (ce label est automatiquement généré par la fiche et affiché juste devant le nom), soit être le nom de l'attaque. Si cet argument est -1, le script cherchera si le personnage a une arme en main et utilisera cette arme. Si c'est -2, il va chercher l'arme en main gauche. Si cet argument est absent ou qu'il ne correspond pas à un label de la fiche du personnage, l'attaque aura les valeurs par défaut d'une attaque au contact infligeant 1d4 DM. Pour plus de facilité, vous pouvez utiliser la macro Attaque qui fait !cof-attack @{selected|token_id} @{target|token_id}

    -

    L'attaque tient alors compte de toutes les informations de l'attaque, y compris chances de critique, port\xE9e, type d'attaque, type de d\xE9g\xE2s et autres options sp\xE9cifi\xE9es sur la fiche. Par d\xE9faut, l'attaque montre le label, le nom de l'attaque, le calcul du bonus d'attaque, le calcul des d\xE9g\xE2ts, la port\xE9e et un champ SP\xC9CIAL (ou encore appel\xE9 divers). En cliquant sur la roue au bout \xE0 droite de cette ligne, on affiche une deuxi\xE8me ligne, avec un case \xE0 d\xE9cocher pour ne pas faire appara\xEEtre l'attaque \xE0 chaque tour, un choix de type d'attaque, des modificateurs, un choix de type de deg\xE2ts et un champ d'options. Les modificateurs sont constitu\xE9s d'options sans argument, s\xE9par\xE9e par une espace. Les options sont reprises telles quels comme un argument \xE0 l'attaque (voir plus bas pour le liste de ces options). Attention, pour l'instant ne traite correctment les jets (parties entre crochets) et les demandes au joueur (de type ?{question?}) que si on passe par une liste d'actions (donc pas directement en faisant #Attaque 1 dans le chat). Une troisi\xE8me ligne peut aussi s'afficher, pour g\xE9rer le nombre d'armes de jet, ou pour les armes port\xE9es, pour indiquer des pr\xE9dicats actifs seulement quand on porte l'arme. Il est possible de sp\xE9cifier une arme batarde (pouvant se porter \xE0 une ou deux mains) en renseignant un pr\xE9dicat batarde de valeur le d\xE9 de DM \xE0 utiliser quand on porte l'arme \xE0 deux mains.

    +

    L'attaque tient alors compte de toutes les informations de l'attaque, y compris chances de critique, portée, type d'attaque, type de dégâs et autres options spécifiées sur la fiche. Par défaut, l'attaque montre le label, le nom de l'attaque, le calcul du bonus d'attaque, le calcul des dégâts, la portée et un champ SPÉCIAL (ou encore appelé divers). En cliquant sur la roue au bout à droite de cette ligne, on affiche une deuxième ligne, avec un case à décocher pour ne pas faire apparaître l'attaque à chaque tour, un choix de type d'attaque, des modificateurs, un choix de type de degâts et un champ d'options. Les modificateurs sont constitués d'options sans argument, séparée par une espace. Les options sont reprises telles quels comme un argument à l'attaque (voir plus bas pour le liste de ces options). Attention, pour l'instant ne traite correctment les jets (parties entre crochets) et les demandes au joueur (de type ?{question?}) que si on passe par une liste d'actions (donc pas directement en faisant #Attaque 1 dans le chat). Une troisième ligne peut aussi s'afficher, pour gérer le nombre d'armes de jet, ou pour les armes portées, pour indiquer des prédicats actifs seulement quand on porte l'arme. Il est possible de spécifier une arme batarde (pouvant se porter à une ou deux mains) en renseignant un prédicat batarde de valeur le dé de DM à utiliser quand on porte l'arme à deux mains.

    Exemple d'attaques.
    -

    En l'absence de label, on peut sp\xE9cifier ces informations sous forme d'options d'attaque

    +

    En l'absence de label, on peut spécifier ces informations sous forme d'options d'attaque

    -

    Malus ou bonus temporaire \xE0 une attaque : utiliser la barre 3.

    -

    Toutes les attaques ayant une port\xE9e non nulles sont consid\xE9r\xE9es par le script comme des attaques \xE0 distance.

    -

    Le test d'attaque \xE0 distance tient compte de la port\xE9e (malus de -1 \xE0 -5 si distance entre port\xE9e et deux fois cette valeur), ainsi que des tokens sur le trajet de l'attaque. Une attaque de trop loin ne porte jamais.

    +

    Malus ou bonus temporaire à une attaque : utiliser la barre 3.

    +

    Toutes les attaques ayant une portée non nulles sont considérées par le script comme des attaques à distance.

    +

    Le test d'attaque à distance tient compte de la portée (malus de -1 à -5 si distance entre portée et deux fois cette valeur), ainsi que des tokens sur le trajet de l'attaque. Une attaque de trop loin ne porte jamais.

    Utiliser une attaque fait rentrer l'attaquant en combat (et le rajoute au turn tracker).

    -

    Il existe une version sp\xE9cialis\xE9e permettant de faire des d\xE9g\xE2ts dans un disque centr\xE9 sur un token, !cof-explosion, dont le premier argument doit \xEAtre le label d'une attaque.

    +

    Il existe une version spécialisée permettant de faire des dégâts dans un disque centré sur un token, !cof-explosion, dont le premier argument doit être le label d'une attaque.

    Options pour l'attaque :

    - Toutes les options sans arguments peuvent \xEAtre directement utilis\xE9es comme modificateurs dans le liste des modifcateurs d'une attaque. + Toutes les options sans arguments peuvent être directement utilisées comme modificateurs dans le liste des modifcateurs d'une attaque.
      -
    • --nom txt : nom de l'attaque \xE0 afficher. Remplace le nom dans la ligne d'attaque si on a donn\xE9 un label en argument. Le nom ne doit pas comporte de blanc usivi de 2 tirets ( --).
    • -
    • --toucher n : bonus de base de l'attaque. Remplace les valeurs dans la ligne d'attaque si on a donn\xE9 un label en argument. Pour r\xE9f\xE9rence, sur les fiches de PJ, l'attaque au contact est [[@{selected|ATKCAC}]], l'attaque \xE0 distance [[@{selected|ATKTIR}]], et l'attaque magique [[@{selected|ATKMAG}]].
    • -
    • --crit n : valeur \xE0 partir de laquelle le jet de d\xE9 est un critique. Remplace les valeurs dans la ligne d'attaque si on a donn\xE9 un label en argument.
    • -
    • --dm expr : D\xE9g\xE2ts de base de l'attaque. Remplace les valeurs dans la ligne d'attaque si on a donn\xE9 un label en argument. expr peut \xEAtre un entier ou bien une expression du type adb+c. La partie constante de cette expression est optionnelle et peut \xEAtre n\xE9gative.
    • -
    • --portee n : la port\xE9e de l'attaque exprim\xE9e en m\xE8tres. Remplace les valeurs dans la ligne d'attaque si on a donn\xE9 un label en argument.
    • -
    • --special txt : remplace le champ sp\xE9cial de l'attaque sur la fiche.
    • -
    • --tempDmg : l'attaque fait des d\xE9g\xE2ts temporaires (tient compte de la force de l'adversaire, utilise la barre 2 pour les dmg temp, sauf si le token a des PM, auquel cas on utilisera un attribut temporaire).
    • +
    • --nom txt : nom de l'attaque à afficher. Remplace le nom dans la ligne d'attaque si on a donné un label en argument. Le nom ne doit pas comporte de blanc usivi de 2 tirets ( --).
    • +
    • --toucher n : bonus de base de l'attaque. Remplace les valeurs dans la ligne d'attaque si on a donné un label en argument. Pour référence, sur les fiches de PJ, l'attaque au contact est [[@{selected|ATKCAC}]], l'attaque à distance [[@{selected|ATKTIR}]], et l'attaque magique [[@{selected|ATKMAG}]].
    • +
    • --crit n : valeur à partir de laquelle le jet de dé est un critique. Remplace les valeurs dans la ligne d'attaque si on a donné un label en argument.
    • +
    • --dm expr : Dégâts de base de l'attaque. Remplace les valeurs dans la ligne d'attaque si on a donné un label en argument. expr peut être un entier ou bien une expression du type adb+c. La partie constante de cette expression est optionnelle et peut être négative.
    • +
    • --portee n : la portée de l'attaque exprimée en mètres. Remplace les valeurs dans la ligne d'attaque si on a donné un label en argument.
    • +
    • --special txt : remplace le champ spécial de l'attaque sur la fiche.
    • +
    • --tempDmg : l'attaque fait des dégâts temporaires (tient compte de la force de l'adversaire, utilise la barre 2 pour les dmg temp, sauf si le token a des PM, auquel cas on utilisera un attribut temporaire).
    • --pasDeDmg : l'attaque ne fait pas de DM.
    • -
    • --poudre : l'arme est une arme \xE0 poudre, utilisation d'un d\xE9 de poudre. Une arme est aussi consid\xE9r\xE9e comme une arme \xE0 poudre si elle contient poudre dans le nom de l'arme ou dans le champ modifcateur ou de pr\xE9dicats.
    • -
    • --epieu : l'arme est un \xE9pieu. \xC0 noter que l'arme est aussi consid\xE9r\xE9e comme un \xE9pieu si elle contient \xE9pieu dans son nom ou epieu dans son champs modificateurs ou pr\xE9dicats. Cette option augmente de 1 le nombre de d\xE9s contre un adversaire sans armure.
    • -
    • --hache : l'arme est une hache. \xC0 noter que l'arme est aussi consid\xE9r\xE9e comme une hache si elle contient hache dans son nom ou dans son champs modificateurs ou pr\xE9dicats. Cette option permet de passer la RD/hache (pour les sylvaniens, par exemple).
    • -
    • --marteau : l'arme est un marteau. \xC0 noter que l'arme est aussi consid\xE9r\xE9e comme un marteau si elle contient marteau dans son nom ou dans son champs modificateurs ou pr\xE9dicats.
    • -
    • --auto : l'attaque r\xE9ussit automatiquement
    • +
    • --poudre : l'arme est une arme à poudre, utilisation d'un dé de poudre. Une arme est aussi considérée comme une arme à poudre si elle contient poudre dans le nom de l'arme ou dans le champ modifcateur ou de prédicats.
    • +
    • --epieu : l'arme est un épieu. À noter que l'arme est aussi considérée comme un épieu si elle contient épieu dans son nom ou epieu dans son champs modificateurs ou prédicats. Cette option augmente de 1 le nombre de dés contre un adversaire sans armure.
    • +
    • --hache : l'arme est une hache. À noter que l'arme est aussi considérée comme une hache si elle contient hache dans son nom ou dans son champs modificateurs ou prédicats. Cette option permet de passer la RD/hache (pour les sylvaniens, par exemple).
    • +
    • --marteau : l'arme est un marteau. À noter que l'arme est aussi considérée comme un marteau si elle contient marteau dans son nom ou dans son champs modificateurs ou prédicats.
    • +
    • --auto : l'attaque réussit automatiquement
    • --bonusAttaque n : ajoute n au jet d'attaque
    • -
    • --bonusCritique n : augmente n \xE0 la plage de coups critiques
    • -
    • --modifiePortee n : ajoute n \xE0 la port\xE9e de l'attaque.
    • -
    • --divisePortee n : divise la port\xE9e de base par n. C'est appliqu\xE9 avant toute modification de port\xE9e.
    • -
    • --bonusContreBouclier n : ajoute n au jet d'attaque si le d\xE9fenseur porte un bouclier. Utile par exemple pour le fl\xE9au d'arme.
    • -
    • --bonusContreArmure n : ajoute n au jet d'attaque si le d\xE9fenseur porte une armure.
    • -
    • --psave carac seuil : jet de carac, si le jet est sup\xE9rieur \xE0 seuil, les d\xE9g\xE2ts sont divis\xE9s par 2. carac est l'abbr\xE9viation de caract\xE9ristiques de 3 lettres standard (FOR, DEX, ...). Il est possible de prendre la meilleure de 2 caract\xE9ristiques pour le save : pour cela indiquer les 2 caract\xE9ristiques coll\xE9es (donc 6 caract\xE8res, par exemple FORDEX, pour le meilleur de FOR et de DEX). Le script choisira automatiquement la caract\xE9ristique qui donne les meilleures chances de r\xE9ussite (en tenant compte de la difficult\xE9 et des caract\xE9ristiques sup\xE9rieures).
    • Enfin on peut encore ajouter un ou des arguments optionnels. Si vous avez besoin de plus d'un argument optionnel, s\xE9parez-les par +: +
    • --bonusCritique n : augmente n à la plage de coups critiques
    • +
    • --modifiePortee n : ajoute n à la portée de l'attaque.
    • +
    • --divisePortee n : divise la portée de base par n. C'est appliqué avant toute modification de portée.
    • +
    • --bonusContreBouclier n : ajoute n au jet d'attaque si le défenseur porte un bouclier. Utile par exemple pour le fléau d'arme.
    • +
    • --bonusContreArmure n : ajoute n au jet d'attaque si le défenseur porte une armure.
    • +
    • --psave carac seuil : jet de carac, si le jet est supérieur à seuil, les dégâts sont divisés par 2. carac est l'abbréviation de caractéristiques de 3 lettres standard (FOR, DEX, ...). Il est possible de prendre la meilleure de 2 caractéristiques pour le save : pour cela indiquer les 2 caractéristiques collées (donc 6 caractères, par exemple FORDEX, pour le meilleur de FOR et de DEX). Le script choisira automatiquement la caractéristique qui donne les meilleures chances de réussite (en tenant compte de la difficulté et des caractéristiques supérieures).
    • Enfin on peut encore ajouter un ou des arguments optionnels. Si vous avez besoin de plus d'un argument optionnel, séparez-les par +:
        -
      • Si on souhaite que le jet ne permette de r\xE9duire qu'une partie des dommages (la derni\xE8re ajout\xE9e avec --plus), on peut ajouter local. La syntaxe compl\xE8te est alors --psave carac seuil local.
      • -
      • Si on souhaite que la difficult\xE9 soit augment\xE9e en cas de temp\xEAte de mana, on peut utiliser le mot cl\xE9 tempete suivi si besoin de l'incr\xE9ment en fonction de la mana (par defaut 1 mana augmente de 1 la difficult\xE9).
      • -
      • Si on souhaite indiquer une difficult\xE9 alternative pour les cibles au contact, ajouter contact n, o\xF9 n est la difficult\xE9 en question.
      • +
      • Si on souhaite que le jet ne permette de réduire qu'une partie des dommages (la dernière ajoutée avec --plus), on peut ajouter local. La syntaxe complète est alors --psave carac seuil local.
      • +
      • Si on souhaite que la difficulté soit augmentée en cas de tempête de mana, on peut utiliser le mot clé tempete suivi si besoin de l'incrément en fonction de la mana (par defaut 1 mana augmente de 1 la difficulté).
      • +
      • Si on souhaite indiquer une difficulté alternative pour les cibles au contact, ajouter contact n, où n est la difficulté en question.
      • +
      • Si on souhaite augmenter la difficulté du save en fonction de la marge de réussite du jet d'attaque, ajouter augmenteAvecMargeDeToucher.
      -
    • --demiAuto : si l'attaque rate, on consid\xE8re juste que les saves partiels sont automatiquemet r\xE9ussi. Ça signifie en g\xE9n\xE9ral que la cible prend au moins la moiti\xE9 des d\xE9g\xE2ts.
    • -
    • --dmSiRate dmg : si l'attaque rate, la cible est quand m\xEAme touch\xE9e et se voit infliger dmg d\xE9g\xE2ts.
    • -
    • --toucheDoubleDmg : si l'attaque rate, elle inflige les d\xE9g\xE2ts normaux, et si elle touche, elle double les d\xE9g\xE2ts de base. Pas cumulable avec dmSiRate ou demiAuto.
    • -
    • --save carac seuil : m\xEAme effet que --psave, mais pour annuler le dernier --effet ou etat (aucun effet sur les DM). Si on rajoute un argument demiDuree au save, alors la r\xE9ussite du save ne fait que diviser par 2 sa dur\xE9e.
    • -
    • --saveDM carac seuil : m\xEAme effet que --psave, mais pour annuler l'ensemble des d\xE9g\xE2ts.
    • -
    • --saveParTour carac seuil : m\xEAme effet que --save, mais donne droit \xE0 un jet \xE0 la fin de chaque tour au lieu d'un jet au moment de l'attaque.
    • -
    • --saveActifParTour carac seuil : m\xEAme effet que --save, mais affiche un bouton pour faire le save dans la liste d'actions \xE0 chaque tour. Utile si les joueurs pr\xE9f\xE8rent jeter "eux-m\xEAmes" le d\xE9, ou si le save est sens\xE9 arriver au tour du joueur.
    • -
    • --saveParJour carac seuil : m\xEAme effet que --save, mais donne droit \xE0 un jet \xE0 la fin de chaque jour au lieu d'un jet au moment de l'attaque.
    • -
    • --fx effet : ajoute un effet qui part de l'attaquant \xE0 la cible. Si l'attaque rate, l'effet rate aussi, d'autant plus que le jet d'attaque est loin de la d\xE9fense. Il est possible d'utiliser un effet que vous avez d\xE9fini vous-m\xEAme en utilisant l'option --fx custom nom, o\xF9 nom est le nom de votre effet.
    • -
    • --targetFx effet : ajoute un effet au niveau de la cible (l'effet ne doit pas \xEAtre directionnel). Comme avec --fx, on peut utiliser un effet qu'on a cr\xE9\xE9.
    • +
    • --demiAuto : si l'attaque rate, on considère juste que les saves partiels sont automatiquemet réussi. Ça signifie en général que la cible prend au moins la moitié des dégâts.
    • +
    • --dmSiRate dmg : si l'attaque rate, la cible est quand même touchée et se voit infliger dmg dégâts.
    • +
    • --toucheDoubleDmg : si l'attaque rate, elle inflige les dégâts normaux, et si elle touche, elle double les dégâts de base. Pas cumulable avec dmSiRate ou demiAuto.
    • +
    • --save carac seuil : même effet que --psave, mais pour annuler le dernier --effet ou etat (aucun effet sur les DM). Si on rajoute un argument demiDuree au save, alors la réussite du save ne fait que diviser par 2 sa durée.
    • +
    • --saveDM carac seuil : même effet que --psave, mais pour annuler l'ensemble des dégâts.
    • +
    • --saveParTour carac seuil : même effet que --save, mais donne droit à un jet à la fin de chaque tour au lieu d'un jet au moment de l'attaque.
    • +
    • --saveActifParTour carac seuil : même effet que --save, mais affiche un bouton pour faire le save dans la liste d'actions à chaque tour. Utile si les joueurs préfèrent jeter "eux-mêmes" le dé, ou si le save est sensé arriver au tour du joueur.
    • +
    • --saveParJour carac seuil : même effet que --save, mais donne droit à un jet à la fin de chaque jour au lieu d'un jet au moment de l'attaque.
    • +
    • --fx effet : ajoute un effet qui part de l'attaquant à la cible. Si l'attaque rate, l'effet rate aussi, d'autant plus que le jet d'attaque est loin de la défense. Il est possible d'utiliser un effet que vous avez défini vous-même en utilisant l'option --fx custom nom, où nom est le nom de votre effet.
    • +
    • --targetFx effet : ajoute un effet au niveau de la cible (l'effet ne doit pas être directionnel). Comme avec --fx, on peut utiliser un effet qu'on a créé.
    • - --si condition : l'attaque n'est possible que si condition est valid\xE9e. Une condition peut \xEAtre + --si condition : l'attaque n'est possible que si condition est validée. Une condition peut être
      • moins attribut : vrai si l'attribut attribut de la cible est moins haute que celle de l'attaquant
      • -
      • etat e : vrai si l'\xE9tat e est actif sur l'attaquant. Cet \xE9tat peut \xEAtre un des \xE9tats d\xE9finis plus bas, ou un attribut quelconque.
      • -
      • attribut attr val: vrai si l'attaquant poss\xE8de un attribut attr, de valeur val, aux majuscules pr\xE8s. On peut optionnellement pr\xE9ciser qu'il s'agit d'un attribut par token en rajoutant le mot cl\xE9 local, ou encore qu'il sagit d'un attribut de la fiche, avec \xE9ventuellement sa valeur par d\xE9faut, en ajoutant le mot cl\xE9 fiche defaut.
      • -
      • etatCible e : vrai si l'\xE9tat e est actif sur toutes la cible. Cet \xE9tat peut \xEAtre un des \xE9tats d\xE9finis plus bas, ou un attribut quelconque.
      • -
      • attributCible attr val: vrai si la cible poss\xE8de un attribut attr, de valeur val, aux majuscules pr\xE8s. On peut optionnellement pr\xE9ciser qu'il s'agit d'un attribut par token en rajoutant le mot cl\xE9 local, ou encore qu'il sagit d'un attribut de la fiche, avec \xE9ventuellement sa valeur par d\xE9faut, en ajoutant le mot cl\xE9 fiche defaut.
      • -
      • predicatCible predicat: vrai si la cible poss\xE8de un pr\xE9dicat predicat. On peut aussi sp\xE9cifier une valeur auquel le pr\xE9dicat doit \xEAtre \xE9gal.
      • -
      • typeCible type: vrai si la cible est du type sp\xE9cifi\xE9. Les types reconnus sont animal, d\xE9mon, dragon, f\xE9e, insecte, mauvais, mort-vivant, g\xE9ant, gobelin, et si le type n'est pas reconnu, va chercher si la race ou un pr\xE9dicat correspondant.
      • -
      • deAttaque n : vrai si le jet de d\xE9 d'attaque est sup\xE9rieur ou \xE9gal \xE0 n.
      • +
      • etat e : vrai si l'état e est actif sur l'attaquant. Cet état peut être un des états définis plus bas, ou un attribut quelconque.
      • +
      • attribut attr val: vrai si l'attaquant possède un attribut attr, de valeur val, aux majuscules près. On peut optionnellement préciser qu'il s'agit d'un attribut par token en rajoutant le mot clé local, ou encore qu'il sagit d'un attribut de la fiche, avec éventuellement sa valeur par défaut, en ajoutant le mot clé fiche defaut.
      • +
      • etatCible e : vrai si l'état e est actif sur toutes la cible. Cet état peut être un des états définis plus bas, ou un attribut quelconque.
      • +
      • attributCible attr val: vrai si la cible possède un attribut attr, de valeur val, aux majuscules près. On peut optionnellement préciser qu'il s'agit d'un attribut par token en rajoutant le mot clé local, ou encore qu'il sagit d'un attribut de la fiche, avec éventuellement sa valeur par défaut, en ajoutant le mot clé fiche defaut.
      • +
      • predicatCible predicat: vrai si la cible possède un prédicat predicat. On peut aussi spécifier une valeur auquel le prédicat doit être égal.
      • +
      • typeCible type: vrai si la cible est du type spécifié. Les types reconnus sont animal, démon, dragon, fée, insecte, mauvais, mort-vivant, géant, gobelin, et si le type n'est pas reconnu, va chercher si la race ou un prédicat correspondant.
      • +
      • deAttaque n : vrai si le jet de dé d'attaque est supérieur ou égal à n.
      • touche : vrai si l'attaque touche.
      • critique : vrai si l'attaque est un critique.
      • -
      • echecCritique : vrai si l'attaque est un \xE9chec critique.
      • +
      • echecCritique : vrai si l'attaque est un échec critique.
      • +
      • premiereAttaque : vrai si c'est la première attaque du combat.
    • -
    • --if condition options --endif: permet de ne prendre en compte des options que si certaines conditions sont r\xE9alis\xE9es. Il est possible d'utiliser un --else pour activer des options quand les conditions ne sont pas r\xE9alis\xE9es. Attention, les options qui modifient une option pr\xE9c\xE9dente (comme --valeur) doivent appara\xEEtre au m\xEAme niveau que l'option qu'elles modifient. Comme les conditions peuvent d\xE9pendre du d\xE9 d'attaque, un certain nombre d'options ne sont pas affect\xE9es par cette conditionnelle : tempeteDeMana, les options d'aoe (ligne, cone, disque, target), avecd12, avantage, auto, demiAuto, test, pointsVitaux, tempsRecharge, sortilege, bonusCritique, disparition, affute, munition, tirDouble, semonce, tirDeBarrage, poudre, traquenard, feinte, asDeLaGachette, magique, tranchant, percant, contondant, pasDeDmg. Ne pas h\xE9siter \xE0 me demander si vous aviez besoin que l'une de ces options puissent \xEAtre conditionnelle.
    • -
    • --ifSaveFails carac seuil options --endif : comme --if, mais fait r\xE9aliser une jet de sauvegarde \xE0 la cible (comme avec --save), et si le test est rat\xE9, applique les options qui suivent. Un --else permet de choisir des options \xE0 appliquer quand le test est r\xE9ussi. \xC0 utiliser seulement si on ne peut pas se contenter d'un --save, car \xE7a marche moins bien.
    • -
    • --decrAttribute nom : l'attaque n'est possible que si l'attribut existe et si sa valeur est strictement positive. L'attaque diminue cette valeur de 1. Si cette option est utilis\xE9e \xE0 l'int\xE9rieur d'un --if, alors l'option se contente de diminuer l'attribut (on peut savoir si la valeur est positive gr\xE2ce \xE0 --if etat nom).
    • -
    • --decrLimitePredicatParTour nom : l'attaque n'est possible que si un pr\xE9dicat nom existe et si elle n'a pas \xE9t\xE9 utilis\xE9e plus de fois dans le tour que la valeur de ce pr\xE9dicat. L'attaque augmente ce nombre de 1.
    • -
    • --tempsRecharge effet duree : l'attaque n'est possible que si l'effet est inactif sur l'attaquant, et de plus active l'effet sur l'attaquant pour la dur\xE9e indiqu\xE9e si l'attaque est possible. Il existe un effet temporaire g\xE9n\xE9rique, rechargeGen(desc) que vous pouvez utiliser si aucun effet existant ne correspond pour votre attaque.
    • -
    • --etat e: si l'attaque touche, la cible passe dans l'\xE9tat e. Il est aussi possible de sp\xE9cifier une caract\xE9ristique et un seuil (comme pour !cof-set-state) pour faire afficher \xE0 chaque tour une action permettant de se lib\xE9rer de l'\xE9tat.
    • -
    • --effet e duree : ajoute \xE0 la cible l'effet temporaire e pour la duree sp\xE9cifi\xE9e. Pour que cela soit automatiquement mis \xE0 jour, il faut utiliser le turn tracker. Noter que l'argument de dur\xE9e peut \xEAtre omis pour certains effets, comme ceux qui par d\xE9finition durent tout le combat.
    • -
    • --valeur v : sp\xE9cifie une valeur au dernier effet mentionn\xE9.
    • -
    • --optionEffet opt arg1 arg2 ... : sp\xE9cifie une option au dernier effet mentionn\xE9. L'option opt doit \xEAtre donn\xE9e sans le -- et sera pass\xE9e telle quelle \xE0 l'effet, par exemple pour les d\xE9g\xE2ts p\xE9riodiques, si on ne veut pas que la RD s'applique, on pourra ajouter --optionEffet ignoreRD.
    • -
    • --peur seuil duree : fait un effet de peur si l'attaque touche. Le seuil sert pour le test de sagesse de r\xE9sistance \xE0 la peur (tient compte de la capacit\xE9 sans peur du chevalier).
    • -
    • --affaiblirCarac carac n : l'attaque diminue la caract\xE9ristique carac de n. Si carac est random, le script tire une caract\xE9ristique au hasard.
    • -
    • --plus dmg : ajoute dmg d\xE9g\xE2ts. Attention, si dmg est un simple nombre, ces d\xE9g\xE2ts sont multipli\xE9s par les critiques (sauf si de type diff\xE9rent de l'attaque principale). Ainsi, --plus [[1d6]] donnera des d\xE9g\xE2ts multipli\xE9s par les critiques (car la fonction ne voit que le r\xE9sultat du jet), alors que --plus 1d6 ne le sera pas.
    • -
    • --plusCrit dmg : ajoute dmg d\xE9g\xE2ts en cas de r\xE9ussite critique
    • -
    • --test pour voir le r\xE9sultat du jet d'attaque. On n'applique pas les r\xE9sultats d'un touch\xE9.
    • -
    • --sournoise n : ajoute nd6 de d\xE9g\xE2ts d'attaque sournoise ou par surprise. Si l'option n'a pas d'argument, le nombre de d\xE9s rajout\xE9s sera celui associ\xE9 \xE0 un pr\xE9dicat attaqueSournoise, et si l'attaquant n'a pas de pr\xE9dicat attaqueSournoise, l'attaque ajoute juste 1d6. Le script limite le nombre d'attaque sournoise par personnage \xE0 1 par tour. On peut augmenter ce nombre en utilisant un pr\xE9dicat sournoisesParTour, de valeur la limite au nombre de sournoises pour ce personnage.
    • -
    • --magique : les d\xE9g\xE2ts sont magiques. On peut passer en argument le niveau de magie. Il est utilis\xE9 contre les cr\xE9atures immunis\xE9es aux armes. Le niveau par d\xE9faut est 1.
    • -
    • --+k : l'attaque utilise une arme magique +k. Pratique \xE0 mettre dans les modificateurs de l'attaque (dans ce cas, on n'a pas les --), cela rajoute les bonus au toucher et aux d\xE9g\xE2ts, et indique que les d\xE9g\xE2ts sont magiques. Si un niveau de magie est sp\xE9cifi\xE9, rajoute k \xE0 ce niveau.
    • -
    • --feu, --acide, --electrique, --froid, --sonique, --poison, --maladie, --argent, --drain, --energie : les d\xE9g\xE2ts sont de type feu, acide, \xE9lectrique, froid, sonique, poison, maladie, argent, drain ou \xE9nergie. Le type sp\xE9cifie uniquement le dernier --plus pr\xE9c\xE9dent cette option, ou si il n'y en a pas, celui des d\xE9g\xE2ts principaux. Seul le dernier type sp\xE9cifi\xE9 est pris en compte (pas de type multiple pour l'instant). Le type affecte diff\xE9rents attributs, et aussi la couleur d'affichage des d\xE9g\xE2ts.
    • -
    • --beni : les d\xE9g\xE2ts sont d'une source sainte ou b\xE9nie. Sert principalement \xE0 signaler pour les r\xE9sistances aux d\xE9g\xE2ts qui peuvent d\xE9pendre de cela (genre RD 5/beni).
    • -
    • --spectral : L'attaque peut toucher les cr\xE9atures intangibles.
    • -
    • --tranchant, --percant, --contondant : pr\xE9cise le type d'arme (si pertinent), pour pouvoir utiliser les RD sp\xE9cifiques \xE0 un type d'arme.
    • -
    • --ignoreRD : l'attaque ignore les RD et division de DMs. Il est possible de donner en argument une valeur de RD ignor\xE9e, de sorte que l'attaque ignore les RD jusqu'\xE0 cette valeur. Par exemple on pourra \xE9crire --ignoreRD 5.
    • -
    • --ignoreMoitieRD : l'attaque ignore la moiti\xE9 de la RD.
    • -
    • --sortilege pour indiquer qu'il s'agit d'un sortil\xE8ge, de fa\xE7ons \xE0 pouvoir appliquer tous les effets sp\xE9cifiques aux sorts. Cette options devrait \xEAtre pass\xE9es pour toutes les capacit\xE9s suivies d'une \xE9toile dans le livre des r\xE8gles. En particulier, tout sortilege ignore les malus d'obstacles.
    • -
    • --reroll1 : relance les 1 aux d\xE9s de d\xE9gats. \xC0 noter que cela ne concerne que les d\xE9s de base de l'attaque, pas les DM suppl\xE9mentaire.
    • -
    • --explodeMax : relance les valeurs maximum aux d\xE9s de DM de base, et rajoute le nouveau r\xE9sultat (qui lui-m\xEAme explose).
    • -
    • --mana n : l'attaque co\xFBte n points de mana. Si l'attaque provoque un effet temporaire, le script essaiera de le supprimer \xE0 la mort du lanceur (m\xEAme avec un co\xFBt nul).
    • -
    • --magieRapide : augmente le co\xFBt en mana (1 avec la mana normale, 3 avec la mana totale) et affiche un petit message indiquant que le lancement est rapide. Il est possible de pr\xE9ciser un co\xFBt en mana diff\xE9rent.
    • -
    • --rang n : indique le rang de la capacit\xE9 utilis\xE9e, si besoin. Utilis\xE9 par l'option --tempeteDeMana.
    • -
    • --tempeteDeMana liste : indique des effets de temp\xEAte de mana. La liste peut contenir un nombre (pour l'effet intense), duree, rapide, portee et altruiste id. Si le rang du sort est sp\xE9cifi\xE9 (par l'option --rang, un message est affich\xE9e si le co\xFBt en mana est sup\xE9rieur au rang. Si la liste d'options est vide ou ne contient que altruiste, le script affiche un menu dans le chat pour sp\xE9cifier les options de temp\xEAte de mana. Il est possible d'utiliser les r\xE8gles de mana totale pour les co\xFBts de temp\xEAte de mana (\xE0 activer avec !cof-options).
    • -
    • --magieEnArmure : applique un malus \xE0 l'attaque \xE9gale au rang du sort + le malus d'armure de l'attaquant. On peut ajouter un argument optionnel : soit un nombre qui va remplacer le rang dans cette formule, soit mana qui va augmenter le co\xFBt en mana de l'attaque en fonction de l'armure port\xE9e.
    • -
    • --frappeDesArcanes n : ajoute +5 \xE0 l'attaque et +nd6 aux DM, mais emp\xEAche de lancer des sorts pendant 1d6 tours si l'attaque touche. Si le nombre n n'est pas pr\xE9sent, le bonus est de 2d6.
    • -
    • --limiteParJour l : limite le nombre d'utilisations de cette attaque \xE0 l fois par jour. On peut pr\xE9ciser un nom apr\xE8s l, qui va correspondre \xE0 une ressource pouvant \xEAtre partag\xE9e avec d'autres attaques ou d'autres effets (voir !cof-effet-temp). Par d\xE9faut, le nom de cette ressource est le label de l'attaque.
    • -
    • --limiteParCombat : m\xEAme effet que la limite par jour. Si aucun argument n'est donn\xE9, la limite est de une fois par combat.
    • -
    • --limiteParTour : m\xEAme effet que la limite par jour. Si aucun argument n'est donn\xE9, la limite est de une fois par tour.
    • -
    • --munition label : l'attaque utilise les munitions de label label (not\xE9es dans l'onglet \xE9quipement de la fiche). \xC0 chaque attaque port\xE9e, une munition est utilis\xE9e, et le script teste si elle sera r\xE9cup\xE9rable (en fonction du taux de pertes not\xE9e sur la fiche). En fin de combat, on consid\xE8re que le personnage r\xE9cup\xE8re toutes les munitions r\xE9cup\xE9rables. Si une arme est reconnue comme \xE9tant un arc,une arbal\xE8te ou une arme \xE0 poudre, et que les options de l'attaque ne contiennent pas l'option --munition, alors le script propose automatiquement de choisir parmis les munitions normales (suppos\xE9es illimit\xE9es) et celles encores pr\xE9sentes du bon type. \xC0 noter que cette option devrait \xEAtre inutile pour les armes de jet qui ont d\xE9j\xE0 leur propre case associ\xE9e \xE0 l'attaque.
    • -
    • --aussiArmeDeJet L : permet d'indiquer que l'arme peut aussi \xEAtre employ\xE9e comme arme de jet. L doit \xEAtre le label de l'attaque avec cette arme en tant qu'arme de jet. Cela permet de tenir compte des cas o\xF9 l'arme a \xE9t\xE9 lanc\xE9e et ne peut donc plus \xEAtre utilis\xE9e au corps \xE0 corps. Si l'arme est utilis\xE9e \xE0 distance, le script va automatiquement utiliser l'attaque L.
    • -
    • --arcComposite n : augmente les DM du modificateur de force, (qui peut \xEAtre n\xE9gatif), mais sans d\xE9passer n. Si le modificateur est strictement inf\xE9rieur \xE0 n, l'attaque se fait avec un malus de -2.
    • -
    • --seulementDistance : l'attaque ne peut \xEAtre r\xE9alis\xE9e que contre un adversaire \xE0 distance.
    • -
    • --vampirise : soigne de tous les DM inflig\xE9s, quel que soit leur type. Il est possible de soigner un pourcentage des d\xE9g\xE2ts : pour cela, pr\xE9ciser le pourcentage entier apr\xE8s l'option. Par exemple, pour une attaque qui soigne de la moiti\xE9 des d\xE9g\xE2ts inflig\xE9s, on pourra mettre --vampirise 50. \xC0 noter que les soins se cumulent avec les d\xE9g\xE2ts de type drain.
    • +
    • --if condition options --endif: permet de ne prendre en compte des options que si certaines conditions sont réalisées. Il est possible d'utiliser un --else pour activer des options quand les conditions ne sont pas réalisées. Attention, les options qui modifient une option précédente (comme --valeur) doivent apparaître au même niveau que l'option qu'elles modifient. Comme les conditions peuvent dépendre du dé d'attaque, un certain nombre d'options ne sont pas affectées par cette conditionnelle : tempeteDeMana, les options d'aoe (ligne, cone, disque, target), avecd12, avantage, auto, demiAuto, test, pointsVitaux, tempsRecharge, sortilege, bonusCritique, disparition, affute, munition, tirDouble, semonce, tirDeBarrage, poudre, traquenard, feinte, asDeLaGachette, magique, tranchant, percant, contondant, pasDeDmg. Ne pas hésiter à me demander si vous aviez besoin que l'une de ces options puissent être conditionnelle.
    • +
    • --ifSaveFails carac seuil options --endif : comme --if, mais fait réaliser une jet de sauvegarde à la cible (comme avec --save), et si le test est raté, applique les options qui suivent. Un --else permet de choisir des options à appliquer quand le test est réussi. À utiliser seulement si on ne peut pas se contenter d'un --save, car ça marche moins bien.
    • +
    • --decrAttribute nom : l'attaque n'est possible que si l'attribut existe et si sa valeur est strictement positive. L'attaque diminue cette valeur de 1. Si cette option est utilisée à l'intérieur d'un --if, alors l'option se contente de diminuer l'attribut (on peut savoir si la valeur est positive grâce à --if etat nom).
    • +
    • --decrLimitePredicatParTour nom : l'attaque n'est possible que si un prédicat nom existe et si elle n'a pas été utilisée plus de fois dans le tour que la valeur de ce prédicat. L'attaque augmente ce nombre de 1.
    • +
    • --tempsRecharge effet duree : l'attaque n'est possible que si l'effet est inactif sur l'attaquant, et de plus active l'effet sur l'attaquant pour la durée indiquée si l'attaque est possible. Il existe un effet temporaire générique, rechargeGen(desc) que vous pouvez utiliser si aucun effet existant ne correspond pour votre attaque.
    • +
    • --etat e: si l'attaque touche, la cible passe dans l'état e. Il est aussi possible de spécifier une caractéristique et un seuil (comme pour !cof-set-state) pour faire afficher à chaque tour une action permettant de se libérer de l'état.
    • +
    • --effet e duree : ajoute à la cible l'effet temporaire e pour la duree spécifiée. Pour que cela soit automatiquement mis à jour, il faut utiliser le turn tracker. Noter que l'argument de durée peut être omis pour certains effets, comme ceux qui par définition durent tout le combat.
    • +
    • --valeur v : spécifie une valeur au dernier effet mentionné.
    • +
    • --optionEffet opt arg1 arg2 ... : spécifie une option au dernier effet mentionné. L'option opt doit être donnée sans le -- et sera passée telle quelle à l'effet, par exemple pour les dégâts périodiques, si on ne veut pas que la RD s'applique, on pourra ajouter --optionEffet ignoreRD.
    • +
    • --peur seuil duree : fait un effet de peur si l'attaque touche. Le seuil sert pour le test de sagesse de résistance à la peur (tient compte de la capacité sans peur du chevalier).
    • +
    • --affaiblirCarac carac n : l'attaque diminue la caractéristique carac de n. Si carac est random, le script tire une caractéristique au hasard.
    • +
    • --plus dmg : ajoute dmg dégâts. Attention, si dmg est un simple nombre, ces dégâts sont multipliés par les critiques (sauf si de type différent de l'attaque principale). Ainsi, --plus [[1d6]] donnera des dégâts multipliés par les critiques (car la fonction ne voit que le résultat du jet), alors que --plus 1d6 ne le sera pas.
    • +
    • --plusCrit dmg : ajoute dmg dégâts en cas de réussite critique
    • +
    • --test pour voir le résultat du jet d'attaque. On n'applique pas les résultats d'un touché.
    • +
    • --sournoise n : ajoute nd6 de dégâts d'attaque sournoise ou par surprise. Si l'option n'a pas d'argument, le nombre de dés rajoutés sera celui associé à un prédicat attaqueSournoise, et si l'attaquant n'a pas de prédicat attaqueSournoise, l'attaque ajoute juste 1d6. Le script limite le nombre d'attaque sournoise par personnage à 1 par tour. On peut augmenter ce nombre en utilisant un prédicat sournoisesParTour, de valeur la limite au nombre de sournoises pour ce personnage.
    • +
    • --magique : les dégâts sont magiques. On peut passer en argument le niveau de magie. Il est utilisé contre les créatures immunisées aux armes. Le niveau par défaut est 1.
    • +
    • --+k : l'attaque utilise une arme magique +k. Pratique à mettre dans les modificateurs de l'attaque (dans ce cas, on n'a pas les --), cela rajoute les bonus au toucher et aux dégâts, et indique que les dégâts sont magiques. Si un niveau de magie est spécifié, rajoute k à ce niveau.
    • +
    • --feu, --acide, --electrique, --froid, --sonique, --poison, --maladie, --argent, --drain, --energie : les dégâts sont de type feu, acide, électrique, froid, sonique, poison, maladie, argent, drain ou énergie. Le type spécifie uniquement le dernier --plus précédent cette option, ou si il n'y en a pas, celui des dégâts principaux. Seul le dernier type spécifié est pris en compte (pas de type multiple pour l'instant). Le type affecte différents attributs, et aussi la couleur d'affichage des dégâts.
    • +
    • --beni : les dégâts sont d'une source sainte ou bénie. Sert principalement à signaler pour les résistances aux dégâts qui peuvent dépendre de cela (genre RD 5/beni).
    • +
    • --spectral : L'attaque peut toucher les créatures intangibles.
    • +
    • --tranchant, --percant, --contondant : précise le type d'arme (si pertinent), pour pouvoir utiliser les RD spécifiques à un type d'arme.
    • +
    • --ignoreRD : l'attaque ignore les RD et division de DMs. Il est possible de donner en argument une valeur de RD ignorée, de sorte que l'attaque ignore les RD jusqu'à cette valeur. Par exemple on pourra écrire --ignoreRD 5.
    • +
    • --ignoreMoitieRD : l'attaque ignore la moitié de la RD.
    • +
    • --sortilege pour indiquer qu'il s'agit d'un sortilège, de façons à pouvoir appliquer tous les effets spécifiques aux sorts. Cette options devrait être passées pour toutes les capacités suivies d'une étoile dans le livre des règles. En particulier, tout sortilege ignore les malus d'obstacles.
    • +
    • --reroll1 : relance les 1 aux dés de dégats. À noter que cela ne concerne que les dés de base de l'attaque, pas les DM supplémentaire.
    • +
    • --explodeMax : relance les valeurs maximum aux dés de DM de base, et rajoute le nouveau résultat (qui lui-même explose).
    • +
    • --mana n : l'attaque coûte n points de mana. Si l'attaque provoque un effet temporaire, le script essaiera de le supprimer à la mort du lanceur (même avec un coût nul).
    • +
    • --magieRapide : augmente le coût en mana (1 avec la mana normale, 3 avec la mana totale) et affiche un petit message indiquant que le lancement est rapide. Il est possible de préciser un coût en mana différent.
    • +
    • --rang n : indique le rang de la capacité utilisée, si besoin. Utilisé par l'option --tempeteDeMana.
    • +
    • --tempeteDeMana liste : indique des effets de tempête de mana. La liste peut contenir un nombre (pour l'effet intense), duree, rapide, portee et altruiste id. Si le rang du sort est spécifié (par l'option --rang, un message est affichée si le coût en mana est supérieur au rang. Si la liste d'options est vide ou ne contient que altruiste, le script affiche un menu dans le chat pour spécifier les options de tempête de mana. Il est possible d'utiliser les règles de mana totale pour les coûts de tempête de mana (à activer avec !cof-options).
    • +
    • --magieEnArmure : applique un malus à l'attaque égale au rang du sort + le malus d'armure de l'attaquant. On peut ajouter un argument optionnel : soit un nombre qui va remplacer le rang dans cette formule, soit mana qui va augmenter le coût en mana de l'attaque en fonction de l'armure portée.
    • +
    • --frappeDesArcanes n : ajoute +5 à l'attaque et +nd6 aux DM, mais empêche de lancer des sorts pendant 1d6 tours si l'attaque touche. Si le nombre n n'est pas présent, le bonus est de 2d6.
    • +
    • --limiteParJour l : limite le nombre d'utilisations de cette attaque à l fois par jour. On peut préciser un nom après l, qui va correspondre à une ressource pouvant être partagée avec d'autres attaques ou d'autres effets (voir !cof-effet-temp). Par défaut, le nom de cette ressource est le label de l'attaque. On peut remplacer le nombre n par le nom d'un prédicat dont la valeur sera utilisée.
    • +
    • --limiteParCombat : même effet que la limite par jour. Si aucun argument n'est donné, la limite est de une fois par combat.
    • +
    • --limiteParTour : même effet que la limite par jour. Si aucun argument n'est donné, la limite est de une fois par tour.
    • +
    • --munition label : l'attaque utilise les munitions de label label (notées dans l'onglet équipement de la fiche). À chaque attaque portée, une munition est utilisée, et le script teste si elle sera récupérable (en fonction du taux de pertes notée sur la fiche). En fin de combat, on considère que le personnage récupère toutes les munitions récupérables. Si une arme est reconnue comme étant un arc,une arbalète ou une arme à poudre, et que les options de l'attaque ne contiennent pas l'option --munition, alors le script propose automatiquement de choisir parmis les munitions normales (supposées illimitées) et celles encores présentes du bon type. À noter que cette option devrait être inutile pour les armes de jet qui ont déjà leur propre case associée à l'attaque.
    • +
    • --aussiArmeDeJet L : permet d'indiquer que l'arme peut aussi être employée comme arme de jet. L doit être le label de l'attaque avec cette arme en tant qu'arme de jet. Cela permet de tenir compte des cas où l'arme a été lancée et ne peut donc plus être utilisée au corps à corps. Si l'arme est utilisée à distance, le script va automatiquement utiliser l'attaque L.
    • +
    • --arcComposite n : augmente les DM du modificateur de force, (qui peut être négatif), mais sans dépasser n. Si le modificateur est strictement inférieur à n, l'attaque se fait avec un malus de -2.
    • +
    • --seulementDistance : l'attaque ne peut être réalisée que contre un adversaire à distance.
    • +
    • --vampirise : soigne de tous les DM infligés, quel que soit leur type. Il est possible de soigner un pourcentage des dégâts : pour cela, préciser le pourcentage entier après l'option. Par exemple, pour une attaque qui soigne de la moitié des dégâts infligés, on pourra mettre --vampirise 50. À noter que les soins se cumulent avec les dégâts de type drain.
    • --seulementVivant : n'affecte que les cibles vivantes
    • --forceMinimum n : l'attaque n'est possible que si l'attaquant a au moins n en force.
    • -
    • --necromancie : l'attaque est de la n\xE9cromancie
    • -
    • --ferFroid : multiplie par 2 les d\xE9g\xE2ts contre les f\xE9es et les d\xE9mons (le script reconna\xEEt certaines races et les pr\xE9dicats d\xE9mon et f\xE9e).
    • -
    • --adamantium : l'arme utilis\xE9e est en adamantium. Reconnu pour la RD.
    • -
    • --tueurDe categorie : bonus de +2 en attaque et +2d6 DM contre les esp\xE8ces appartenant \xE0 la cat\xE9gorie (voir la condition typeCible.
    • -
    • --tueurDeGrands : bonus de +1d6 DM contre les cr\xE9atures de taille grande et +2d6 DM contre les cr\xE9atures de taille \xE9norme ou plus.
    • -
    • --ignoreObstacles : ignore les tokens sur le trajet. Ça semble n\xE9cessaire pour les attaques magiques d'apr\xE8s Kegron.
    • -
    • --retourneEnMain : L'arme de jet revient en main apr\xE8s l'attaque.
    • -
    • --puissant : augmente la valeur max des d\xE9s de d\xE9g\xE2ts de 2. Si --puissant est suivi d'un argument effet, on teste la pr\xE9sence d'un attribut effetPuissant pour d\xE9cider si l'attaque est puissante ou non. Il est aussi possible de donner oui ou non en argument (ce n'est alors pas consid\xE9r\xE9 comme un effet). --puissant portee permet de doubler la port\xE9e de l'attaque (utile pour l'option de Magie Puissante)
    • -
    • --attaqueAssuree : impl\xE9mente une attaque assur\xE9e (+5 \xE0 l'attaque, d\xE9g\xE2ts divis\xE9s par 2, critique impossible).
    • -
    • --attaqueRisquee : impl\xE9mente une attaque risqu\xE9e (+2 \xE0 l'attaque au contact, -4 en DEF pendant un tour).
    • -
    • --attaqueDeGroupe n : n est le nombre de cr\xE9atures qui attaquent ; impl\xE9mente une attaque de groupe (+2 \xE0 l'attaque par attaquant au-del\xE0 du premier, x2 DMG si l'attaque d\xE9passe la DEF de 5 ou plus, x3 DMG si critique).
    • -
    • --attaqueAcrobatique : l'attaquant effectue un test d'acrobatie difficult\xE9 15, et s'il r\xE9ussit, l'attaque b\xE9n\xE9ficie des effets d'une sournoise. On peut en option pr\xE9ciser le nombre de d\xE9s de cette attaque sournoise.
    • -
    • --strigeSuce : option sp\xE9cifique aux striges. Donne le malus de -3 en DEF et compte la quantite suc\xE9e. Quand cette quantit\xE9 arrive \xE0 6, enl\xE8ve le malus de DEF et rend la cible affaiblie.
    • -
    • --mainsDEnergie : +2 \xE0 +5 \xE0 l'attaque, selon l'armure de la cible
    • -
    • --semonce : +5 au touch\xE9 et +1d6 aux DM (ne change pas les charges de l'arme).
    • -
    • --avantage : lance un d\xE9 de plus en attaque et garde le meilleur. plusieurs arguments avantage se cumulent et sont annul\xE9s par les d\xE9savantages (syntaxe alertnative: (--m2d20)
    • -
    • --desavantage : lance un d\xE9 de plus en attaque et garde le moins bon. plusieurs arguments d\xE9savantage se cumulent et sont annul\xE9s par les avantages.
    • -
    • --avecd12 : lance un d12 au lieu du d20 pour le jet d'attaque. L'attaque est impossible si l'attaquant est d\xE9j\xE0 affaibli.
    • -
    • --avecd12crit : comme --avecd12, mais le jet peut faire un critique. La plage de critique est divis\xE9e par 2, arrondie \xE0 l'inf\xE9rieur. Ainsi si le d20 sevait critiquer sur un 20 seulement, le d12 ne fait pas de critique. Il fait un critique sur un 12 si le d20 devait faire un critique sur un 19 ou un 18, et ainsi de suite.
    • -
    • --incrDmgCoef n : augmente le coefficient des d\xE9g\xE2ts de base de 1. Les d\xE9g\xE2ts de base comprennent les d\xE9s de dommage de l'arme (ou du sort), plus tous les bonus constants. Le coefficient par d\xE9faut est de 1, et une r\xE9ussite critique augmente ce coefficient de 1.
    • -
    • --incrCritCoef n : augmente le coefficient des d\xE9g\xE2ts critiques de n (1 si on ne donne pas d'argument).
    • -
    • --diviseDmg n : divise les d\xE9g\xE2ts de base par n.
    • -
    • --maxDmg : l'attaque inflige le maximum de DM permis par les d\xE9s de base.
    • -
    • --runeDePuissance : l'arme est enchant\xE9e avec une rune de puissance permanente.
    • -
    • --difficultePVmax : la difficult\xE9 du jet d'attaque est le maximum de PVs au lieu de la d\xE9fense.
    • -
    • --difficultePV : la difficult\xE9 du jet d'attaque est la valeur courante des PVs au lieu de la d\xE9fense.
    • -
    • --difficulteCarac carac : la difficult\xE9 du jet d'attaque est une des caract\xE9ristiques de la cible (sous forme de code \xE0 3 lettres, FOR, DEX, etc). Il est possible de prendre le meilleur de 2 caract\xE9ristiques en \xE9crivant les 2 noms coll\xE9s. Par exemple, pour viser le meilleur de l'intelligence et du charisme, on \xE9crira --difficuletCarac INTCHA.
    • +
    • --necromancie : l'attaque est de la nécromancie
    • +
    • --ferFroid : multiplie par 2 les dégâts contre les fées et les démons (le script reconnaît certaines races et les prédicats démon et fée).
    • +
    • --adamantium : l'arme utilisée est en adamantium. Reconnu pour la RD.
    • +
    • --tueurDe categorie : bonus de +2 en attaque et +2d6 DM contre les espèces appartenant à la catégorie (voir la condition typeCible.
    • +
    • --tueurDeGrands : bonus de +1d6 DM contre les créatures de taille grande et +2d6 DM contre les créatures de taille énorme ou plus.
    • +
    • --ignoreObstacles : ignore les tokens sur le trajet. Ça semble nécessaire pour les attaques magiques d'après Kegron.
    • +
    • --retourneEnMain : L'arme de jet revient en main après l'attaque.
    • +
    • --puissant : augmente la valeur max des dés de dégâts de 2. Si --puissant est suivi d'un argument effet, on teste la présence d'un attribut effetPuissant pour décider si l'attaque est puissante ou non. Il est aussi possible de donner oui ou non en argument (ce n'est alors pas considéré comme un effet). --puissant portee permet de doubler la portée de l'attaque (utile pour l'option de Magie Puissante)
    • +
    • --attaqueAssuree : implémente une attaque assurée (+5 à l'attaque, dégâts divisés par 2, critique impossible).
    • +
    • --attaqueRisquee : implémente une attaque risquée (+2 à l'attaque au contact, -4 en DEF pendant un tour).
    • +
    • --attaqueDeGroupe n : n est le nombre de créatures qui attaquent ; implémente une attaque de groupe (+2 à l'attaque par attaquant au-delà du premier, x2 DMG si l'attaque dépasse la DEF de 5 ou plus, x3 DMG si critique).
    • +
    • --attaqueAcrobatique : l'attaquant effectue un test d'acrobatie difficulté 15, et s'il réussit, l'attaque bénéficie des effets d'une sournoise. On peut en option préciser le nombre de dés de cette attaque sournoise.
    • +
    • --strigeSuce : option spécifique aux striges. Donne le malus de -3 en DEF et compte la quantite sucée. Quand cette quantité arrive à 6, enlève le malus de DEF et rend la cible affaiblie.
    • +
    • --mainsDEnergie : +2 à +5 à l'attaque, selon l'armure de la cible
    • +
    • --semonce : +5 au touché et +1d6 aux DM (ne change pas les charges de l'arme).
    • +
    • --avantage : lance un dé de plus en attaque et garde le meilleur. plusieurs arguments avantage se cumulent et sont annulés par les désavantages (syntaxe alertnative: (--m2d20)
    • +
    • --desavantage : lance un dé de plus en attaque et garde le moins bon. plusieurs arguments désavantage se cumulent et sont annulés par les avantages.
    • +
    • --avecd12 : lance un d12 au lieu du d20 pour le jet d'attaque. L'attaque est impossible si l'attaquant est déjà affaibli.
    • +
    • --avecd12crit : comme --avecd12, mais le jet peut faire un critique. La plage de critique est divisée par 2, arrondie à l'inférieur. Ainsi si le d20 sevait critiquer sur un 20 seulement, le d12 ne fait pas de critique. Il fait un critique sur un 12 si le d20 devait faire un critique sur un 19 ou un 18, et ainsi de suite.
    • +
    • --incrDmgCoef n : augmente le coefficient des dégâts de base de 1. Les dégâts de base comprennent les dés de dommage de l'arme (ou du sort), plus tous les bonus constants. Le coefficient par défaut est de 1, et une réussite critique augmente ce coefficient de 1.
    • +
    • --incrCritCoef n : augmente le coefficient des dégâts critiques de n (1 si on ne donne pas d'argument).
    • +
    • --diviseDmg n : divise les dégâts de base par n.
    • +
    • --maxDmg : l'attaque inflige le maximum de DM permis par les dés de base.
    • +
    • --runeDePuissance : l'arme est enchantée avec une rune de puissance permanente.
    • +
    • --difficultePVmax : la difficulté du jet d'attaque est le maximum de PVs au lieu de la défense.
    • +
    • --difficultePV : la difficulté du jet d'attaque est la valeur courante des PVs au lieu de la défense.
    • +
    • --difficulteCarac carac : la difficulté du jet d'attaque est une des caractéristiques de la cible (sous forme de code à 3 lettres, FOR, DEX, etc). Il est possible de prendre le meilleur de 2 caractéristiques en écrivant les 2 noms collés. Par exemple, pour viser le meilleur de l'intelligence et du charisme, on écrira --difficuletCarac INTCHA.
    • --affute : augmente de 1 les chances de crit et +1d6 aux DM des crit.
    • --tirDeBarrage : ignore la charge, multiplie les DM par 2 et message pour undo si la cible bouge.
    • --tirAveugle : ignore le malus de tir sur une cible invisible.
    • -
    • --vicieux : ajoute 2d6 DM mais inflige 1d6 DM \xE0 l'attaquant.
    • -
    • --enflamme : enflamme la cible, lui infligeant 1d6 DM par tour. Les flammes s'\xE9teindent sur un 1 ou 2. Si l'option --puissant est donn\xE9e en conjonction, les DM augmentent de 1.
    • +
    • --vicieux : ajoute 2d6 DM mais inflige 1d6 DM à l'attaquant.
    • +
    • --enflamme : enflamme la cible, lui infligeant 1d6 DM par tour. Les flammes s'éteindent sur un 1 ou 2. Si l'option --puissant est donnée en conjonction, les DM augmentent de 1.
    • --malediction : maudit la cible pour 3 jets.
    • -
    • --asDeLaGachette : ajoute 1d6 DM si le jet d'attaque d\xE9passe une DEF de 25.
    • -
    • --armeDArgent : bonus de +2 en attaque et 1d6 aux DM si la cible est un mort-vivant ou un d\xE9mon (utilise le champ Race de la fiche ou si pr\xE9sent un pr\xE9dicat mortVivant).
    • -
    • --pietine : si l'attaquant est de taille au moins \xE9gale \xE0 celle de la cible (ou si la taille de l'un des deux n'est pas connue), fait un test oppos\xE9 de FOR. En cas d'\xE9chec de la cible, elle est renvers\xE9e et les DM sont doubl\xE9s.
    • -
    • --percute : comme --pietine, mais la cible est en plus projet\xE9e \xE0 1d6+1 m\xE8tres et \xE9tourdie si elle rate un test de CON difficult\xE9 15, renouvelable chaque tour.
    • -
    • --feinte : L'attaque ne fait pas de d\xE9g\xE2t, mais un bonus de +5 en attaque est donn\xE9 sur les attaques du tour suivant sur cette cible (par celui qui a fait la feinte), et +2d6 DM si l'attaque fictive \xE9tait un succ\xE8s. Si l'attaquant poss\xE8de un pr\xE9dicat bonusFeinte, c'est la valeur de ce pr\xE9dicat qui est donn\xE9 en bonus aux attaques, \xE0 la place de +5.
    • -
    • --enveloppe difficulte type expr : si l'attaque touche, elle a une chance d'envelopper la cible. Dans ce cas, un bouton appara\xEEt qui lance un test en opposition. Si celui-ci est remport\xE9 par l'attaquant, difficulte est la difficult\xE9 du test pour se sortir de l'enveloppement, type est soit label, et dans ce cas, expr doit \xEAtre le label d'une attaque de l'attaquant, soit ability, et dans ce cas, expr est le nom d'une ability de l'attaquant. Cette attaque ou ability est appel\xE9e pour les d\xE9g\xE2ts p\xE9riodiques. Si les deux derniers arguments sont ommis, le script prend label et le label de l'attaque courante, et si le premier argument est ommis, la difficult\xE9 est de 15.
    • -
    • --etreinte difficulte : si l'attaque touche, il y a une chance que l'attaquant puisse s'enrouler autour de la cible. Dans ce cas, un bouton appara\xEEt qui lance un test en opposition. Si celui-ci est remport\xE9 par l'attaquant, difficulte est la difficult\xE9 du test pour se sortir de l'enveloppement. Cela fera appara\xEEtre un bouton pour les d\xE9g\xE2ts de l'\xE9treinte, par d\xE9faut 1d6, mais on peut sp\xE9cifier une autre expression pour les d\xE9g\xE2ts (optionelle, juste apr\xE8s la difficult\xE9).
    • -
    • --ouvertureMortelle : touche automatiquement, fait des d\xE9g\xE2t comme en cas de critique et multiplie par 2 les d\xE9g\xE2ts d'attaque sournoise (si il y en a).
    • -
    • --rate, --touche, --critique, --echecCritique, --pasDEchecCritique : options pour tricher : le r\xE9sultat des d\xE9s donne toujours le r\xE9sultat voulu.
    • -
    • --ligne : l'attaque porte sur toutes les cibles \xE0 port\xE9e, entre l'attaquant et le token cibl\xE9. Si le token cibl\xE9 est plus proche que la port\xE9e de l'attaque, les tokens derri\xE8re le token cibl\xE9 sont aussi vis\xE9s. Pour permettre de viser un point quelconque, on peut utiliser un personnage d\xE9di\xE9 avec un maximum de 0 pv. \xC0 chaque fois qu'un token repr\xE9sentant ce personnage est utilis\xE9 comme cible de --ligne, le token est enlev\xE9 de la carte.
    • -
    • --disque r : l'attaque porte sur toutes les cibles dans le disque de centre le token cibl\xE9 et de rayon r. Comme pour --ligne, on peut utiliser un token cible qui sera supprim\xE9 apr\xE8s l'attaque. \xC0 noter que l'attaquant lui-m\xEAme peut prendre des d\xE9g\xE2ts, sauf si l'attaque a une port\xE9e nulle et que l'attaquant se cible lui-m\xEAme (attaque centr\xE9e sur le lanceur). On peut donner en argument optionel le mot souffleDeMort pour ne valider l'attaque que si le centre du disque est un personnage mort depuis moins d'un tour et ne garder que les alli\xE9s de ce personnage de niveau inf\xE9rieur ou \xE9gal.
    • -
    • --cone angle : cible toutes les cr\xE9atures dans un c\xF4ne de sommet l'attaquant, d'angle angle degr\xE9s (90 degr\xE9s par d\xE9faut), et s\xE9par\xE9 en deux par le segment joignant l'attaquant et le token vis\xE9.
    • -
    • --explosion : si l'attaque n'est pas d\xE9j\xE0 un disque, consid\xE8re qu'elle forme un disque de rayon \xE9gal \xE0 la port\xE9e. L'attaquant est automatiquement exclus de la zone.
    • -
    • --dmCible dmg : utilis\xE9 conjointement aux options de zone ci-dessus, cette option permet de remplacer les dommages de base de l'attaque sp\xE9cifiquement sur la cible s\xE9lectionn\xE9e lors de l'attaque
    • -
    • --saufAllies : ne cible pas les allies dans la zone ou les cibles sp\xE9cifi\xE9es.
    • -
    • --target id : ajoute une cible \xE0 l'attaque (s'ajoute \xE0 la cible principale et aux options d'aoe).
    • -
    • --ciblesDansDisque n : impose que les diff\xE9rentes cibles soient dans un disque de rayon n.
    • -
    • --ricochets n : l'arme de jet peut faire n ricochets. Une cible ne peut \xEAtre touch\xE9e qu'une fois par attaque.
    • -
    • --message texte : ajoute une ligne avec le message dans la fen\xEAtre de l'attaque. Attention, texte ne doit pas contenir la s\xE9quence --.
    • -
    • --secret : affiche les jets et r\xE9sultats de l'attaque seulement aux joueurs qui contr\xF4lent l'attaquant ou ses cibles, ainsi qu'au MJ.
    • -
    • --allonge n : ajoute n m\xE8tres \xE0 la port\xE9e d'une attaque au contact. L'allonge peut \xEAtre un nombre \xE0 virgule et m\xEAme n\xE9gative.
    • -
    • --canaliseParFamilier : le point de d\xE9part de l'attaque est le familier s'il est actif sur la carte.
    • -
    • --peutAgripper : l'attaque peut agripper comme si l'attaquant avait le pr\xE9dicat agripper.
    • -
    • --soundAttack son : joue le son son, \xE0 moins qu'une version plus longue de l'option (voir ci-dessous) n'existe et qu'elle soit active.
    • -
    • --soundAttackEchec son : joue le son son lorque l'arme fait un echec, sauf si c'est un \xE9chec particulier et une version plus longue existe.
    • +
    • --asDeLaGachette : ajoute 1d6 DM si le jet d'attaque dépasse une DEF de 25.
    • +
    • --armeDArgent : bonus de +2 en attaque et 1d6 aux DM si la cible est un mort-vivant ou un démon (utilise le champ Race de la fiche ou si présent un prédicat mortVivant).
    • +
    • --pietine : si l'attaquant est de taille au moins égale à celle de la cible (ou si la taille de l'un des deux n'est pas connue), fait un test opposé de FOR. En cas d'échec de la cible, elle est renversée et les DM sont doublés.
    • +
    • --percute : comme --pietine, mais la cible est en plus projetée à 1d6+1 mètres et étourdie si elle rate un test de CON difficulté 15, renouvelable chaque tour.
    • +
    • --feinte : L'attaque ne fait pas de dégât, mais un bonus de +5 en attaque est donné sur les attaques du tour suivant sur cette cible (par celui qui a fait la feinte), et +2d6 DM si l'attaque fictive était un succès. Si l'attaquant possède un prédicat bonusFeinte, c'est la valeur de ce prédicat qui est donné en bonus aux attaques, à la place de +5.
    • +
    • --enveloppe difficulte type expr : si l'attaque touche, elle a une chance d'envelopper la cible. Dans ce cas, un bouton apparaît qui lance un test en opposition. Si celui-ci est remporté par l'attaquant, difficulte est la difficulté du test pour se sortir de l'enveloppement, type est soit label, et dans ce cas, expr doit être le label d'une attaque de l'attaquant, soit ability, et dans ce cas, expr est le nom d'une ability de l'attaquant. Cette attaque ou ability est appelée pour les dégâts périodiques. Si les deux derniers arguments sont ommis, le script prend label et le label de l'attaque courante, et si le premier argument est ommis, la difficulté est de 15.
    • +
    • --etreinte difficulte : si l'attaque touche, il y a une chance que l'attaquant puisse s'enrouler autour de la cible. Dans ce cas, un bouton apparaît qui lance un test en opposition. Si celui-ci est remporté par l'attaquant, difficulte est la difficulté du test pour se sortir de l'enveloppement. Cela fera apparaître un bouton pour les dégâts de l'étreinte, par défaut 1d6, mais on peut spécifier une autre expression pour les dégâts (optionelle, juste après la difficulté).
    • +
    • --ouvertureMortelle : touche automatiquement, fait des dégât comme en cas de critique et multiplie par 2 les dégâts d'attaque sournoise (si il y en a).
    • +
    • --rate, --touche, --critique, --echecCritique, --pasDEchecCritique : options pour tricher : le résultat des dés donne toujours le résultat voulu.
    • +
    • --ligne : l'attaque porte sur toutes les cibles à portée, entre l'attaquant et le token ciblé. Si le token ciblé est plus proche que la portée de l'attaque, les tokens derrière le token ciblé sont aussi visés. Pour permettre de viser un point quelconque, on peut utiliser un personnage dédié avec un maximum de 0 pv. À chaque fois qu'un token représentant ce personnage est utilisé comme cible de --ligne, le token est enlevé de la carte.
    • +
    • --disque r : l'attaque porte sur toutes les cibles dans le disque de centre le token ciblé et de rayon r. Comme pour --ligne, on peut utiliser un token cible qui sera supprimé après l'attaque. À noter que l'attaquant lui-même peut prendre des dégâts, sauf si l'attaque a une portée nulle et que l'attaquant se cible lui-même (attaque centrée sur le lanceur). On peut donner en argument optionel le mot souffleDeMort pour ne valider l'attaque que si le centre du disque est un personnage mort depuis moins d'un tour et ne garder que les alliés de ce personnage de niveau inférieur ou égal.
    • +
    • --cone angle : cible toutes les créatures dans un cône de sommet l'attaquant, d'angle angle degrés (90 degrés par défaut), et séparé en deux par le segment joignant l'attaquant et le token visé.
    • +
    • --explosion : si l'attaque n'est pas déjà un disque, considère qu'elle forme un disque de rayon égal à la portée. L'attaquant est automatiquement exclus de la zone.
    • +
    • --dmCible dmg : utilisé conjointement aux options de zone ci-dessus, cette option permet de remplacer les dommages de base de l'attaque spécifiquement sur la cible sélectionnée lors de l'attaque
    • +
    • --saufAllies : ne cible pas les allies dans la zone ou les cibles spécifiées.
    • +
    • --target id : ajoute une cible à l'attaque (s'ajoute à la cible principale et aux options d'aoe).
    • +
    • --ciblesDansDisque n : impose que les différentes cibles soient dans un disque de rayon n.
    • +
    • --ricochets n : l'arme de jet peut faire n ricochets. Une cible ne peut être touchée qu'une fois par attaque.
    • +
    • --message texte : ajoute une ligne avec le message dans la fenêtre de l'attaque. Attention, texte ne doit pas contenir la séquence --.
    • +
    • --secret : affiche les jets et résultats de l'attaque seulement aux joueurs qui contrôlent l'attaquant ou ses cibles, ainsi qu'au MJ.
    • +
    • --allonge n : ajoute n mètres à la portée d'une attaque au contact. L'allonge peut être un nombre à virgule et même négative.
    • +
    • --canaliseParFamilier : le point de départ de l'attaque est le familier s'il est actif sur la carte.
    • +
    • --peutAgripper : l'attaque peut agripper comme si l'attaquant avait le prédicat agripper.
    • +
    • --soundAttack son : joue le son son, à moins qu'une version plus longue de l'option (voir ci-dessous) n'existe et qu'elle soit active.
    • +
    • --soundAttackEchec son : joue le son son lorque l'arme fait un echec, sauf si c'est un échec particulier et une version plus longue existe.
    • --soundAttackEchecCritique son : joue le son n lorque l'arme fait un echec critique
    • --soundAttackEchecClignotement son : joue le son son lorque l'arme fait un echec par clignotement
    • -
    • --soundAttackSucces son : joue le son son lorque l'arme fait un succ\xE8s
    • -
    • --soundAttackSuccesCritique son : joue le son n lorque l'arme fait un succ\xE8s critique
    • -
    • --soundAttackSuccesChampion son : joue le son son lorque l'arme fait un succ\xE8s champion
    • -
    • --imgAttack img : Affiche dans le chat l'image (.jpg/.png/.gif) img, \xE0 moins qu'une version plus longue de l'option (voir ci-dessous) n'existe et qu'elle soit active.
    • +
    • --soundAttackSucces son : joue le son son lorque l'arme fait un succès
    • +
    • --soundAttackSuccesCritique son : joue le son n lorque l'arme fait un succès critique
    • +
    • --soundAttackSuccesChampion son : joue le son son lorque l'arme fait un succès champion
    • +
    • --imgAttack img : Affiche dans le chat l'image (.jpg/.png/.gif) img, à moins qu'une version plus longue de l'option (voir ci-dessous) n'existe et qu'elle soit active.
    • --imgAttackEchecCritique img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec critique
    • --imgAttackEchec img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec
    • --imgAttackEchecClignotement img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec par clignotement
    • -
    • --imgAttackSuccesCritique img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s critique
    • -
    • --imgAttackSucces img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s
    • -
    • --imgAttackSuccesChampion img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s champion
    • +
    • --imgAttackSuccesCritique img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès critique
    • +
    • --imgAttackSucces img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès
    • +
    • --imgAttackSuccesChampion img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès champion
    • +
    • --terrainDifficile duree : si l'attaque affecte une zone en forme de disque, cette zone sera considérée comme du terrain difficile pendant duree tours. En deuxième argument, on peut mettre le nom de la zone, et en troisième argument une image à afficher sur la carte.
    • +
    • --deplaceDe dmax : l'attaquant se déplacer de dmax mètres maximum pour arriver à portée de sa cible. Le déplacement (et l'attaque) n'a lieu que si il existe une position libre, sans aucun token sur le trajet. On peut spécifier une distance minimum avec --deplaceDe min max. On peut aussi ajouter le mot-clé saut pour ignorer les tokens sur le trajet.
    -

    R\xE9duction des d\xE9g\xE2ts

    +

    Réduction des dégâts

    Fonctionnement de base
      -
    • Le script utilise les cases RD et Casque pr\xE9sentes sur les fiches.
    • -
    • Il est possible d'indiquer plusieurs RD diff\xE9rentes, il suffit de les s\xE9parer par une virgule.
    • +
    • Le script utilise les cases RD et Casque présentes sur les fiches.
    • +
    • Il est possible d'indiquer plusieurs RD différentes, il suffit de les séparer par une virgule.
    • Toutes les RD se cumulent.
    • -
    • Le script se base sur les types de d\xE9g\xE2ts pour choisir d'appliquer ou non les d\xE9g\xE2ts.
    • -
    • Pour les armes magiques, il est possible de sp\xE9cifier \xE0 la fois le type de l'arme (par exemple --tranchant) et --magique.
    • +
    • Le script se base sur les types de dégâts pour choisir d'appliquer ou non les dégâts.
    • +
    • Pour les armes magiques, il est possible de spécifier à la fois le type de l'arme (par exemple --tranchant) et --magique.
    RD simple
    -

    Dans le cas d'une RD simple (r\xE9sistance \xE0 tous les d\xE9g\xE2ts), il suffit d'indiquer un nombre. Exemple : 3

    -
    RD \xE0 un type de d\xE9g\xE2ts particuliers
    -

    Pour une RD qui ne s'applique qu'\xE0 un type de d\xE9g\xE2ts particuliers, indiquer le type et la valeur s\xE9par\xE9s par :. Exemple : feu:5. On peut aussi sp\xE9cifier une RD conte tous les types \xE9l\xE9mentaires avec le mot cl\xE9 elementaire. On peut aussi avoir une RD qui ne s'applique qu'aux attaques \xE0 distance avec le mot cl\xE9 distance.

    -
    RD sauf un ou plusieurs types de d\xE9g\xE2ts particuliers
    -

    Pour une RD qui s'applique tout le temps sauf un ou plusieurs types de d\xE9g\xE2ts particuliers, indiquer la valeur puis / puis les diff\xE9rents types s\xE9par\xE9s par _. Exemple /. Exemple : 5/argent_magique
    - Pour une RD qui s'appliquerait \xE0 tous les types d'armes sauf une, utiliser \xE0 la place une r\xE9sistance aux 2 autres types d'armes. Exemple, pour 5/tranchant, utiliser percant:5,contondant:5.

    +

    Dans le cas d'une RD simple (résistance à tous les dégâts), il suffit d'indiquer un nombre. Exemple : 3

    +
    RD à un type de dégâts particuliers
    +

    Pour une RD qui ne s'applique qu'à un type de dégâts particuliers, indiquer le type et la valeur séparés par :. Exemple : feu:5. On peut aussi spécifier une RD conte tous les types élémentaires avec le mot clé elementaire. On peut aussi avoir une RD qui ne s'applique qu'aux attaques à distance avec le mot clé distance.

    +
    RD sauf un ou plusieurs types de dégâts particuliers
    +

    Pour une RD qui s'applique tout le temps sauf un ou plusieurs types de dégâts particuliers, indiquer la valeur puis / puis les différents types séparés par _. Exemple /. Exemple : 5/argent_magique
    + Pour une RD qui s'appliquerait à tous les types d'armes sauf une, utiliser à la place une résistance aux 2 autres types d'armes. Exemple, pour 5/tranchant, utiliser percant:5,contondant:5.

    RD critique
    -

    Utiliser un pr\xE9dicat RD_critique avec comme valeur la r\xE9sistance aux critiques. Se combine avec une \xE9ventuelle RD critique fournie par le port d'un casque.

    -
    R\xE9sistances
    -

    Pour les effets qui divisent la d\xE9g\xE2ts subits d'un type donn\xE9, utilisez un pr\xE9dicat resistanceA_type. Une resistance \xE0 tous les d\xE9g\xE2ts non-magiques est possible avec resistanceA_nonMagique.Il est aussi possible d'octroyer une r\xE9sistance temporaire, par exemple une potion de r\xE9sistance au feu pourra \xEAtre simul\xE9e par la commande !cof-set-attribute resistanceA_feu true. Cela ne sera pas visible dans les pr\xE9dicats, local \xE0 un mook, et il faut ensuite effacer l'attribut \xE0 la fin de l'effet.

    -

    Pour les effets qui divisent par 2 les d\xE9g\xE2ts ou la dur\xE9e, utiliser un pr\xE9dicat diviseEffet_type.

    -

    Pour les effets qui donnent un bonus aux tests pour r\xE9sister aux effets ou d\xE9g\xE2ts d'un certain type, utiliser un pr\xE9dicat bonusSaveContre_type de valeur le bonus accord\xE9. Par exemple, un objet qui donnerait +5 \xE0 tous les tests pour r\xE9sister au poison pourrait \xEAtre encod\xE9 par un pr\xE9dicat bonusSaveContre_poison de valeur 5.

    +

    Utiliser un prédicat RD_critique avec comme valeur la résistance aux critiques. Se combine avec une éventuelle RD critique fournie par le port d'un casque.

    +
    Résistances
    +

    Pour les effets qui divisent la dégâts subits d'un type donné, utilisez un prédicat resistanceA_type. Une resistance à tous les dégâts non-magiques est possible avec resistanceA_nonMagique.Il est aussi possible d'octroyer une résistance temporaire, par exemple une potion de résistance au feu pourra être simulée par la commande !cof-set-attribute resistanceA_feu true. Cela ne sera pas visible dans les prédicats, local à un mook, et il faut ensuite effacer l'attribut à la fin de l'effet.

    +

    Pour les effets qui divisent par 2 les dégâts ou la durée, utiliser un prédicat diviseEffet_type.

    +

    Pour les effets qui donnent un bonus aux tests pour résister aux effets ou dégâts d'un certain type, utiliser un prédicat bonusSaveContre_type de valeur le bonus accordé. Par exemple, un objet qui donnerait +5 à tous les tests pour résister au poison pourrait être encodé par un prédicat bonusSaveContre_poison de valeur 5.

    Armures/Boucliers de Protection (COF p. 203)
    -

    ajoutez un pr\xE9dicat armureProtection ou bouclierProtection. Le script d\xE9tecte si l'\xE9quipement est port\xE9 ou pas via la fiche, et fonctionne sp\xE9cifiquement contre les attaques qui utilisent --sournoise. Il est aussi possible de sp\xE9cifier le port d'un anneau de protection ayant le m\xEAme effet (pr\xE9dicat anneauProtection.

    +

    ajoutez un prédicat armureProtection ou bouclierProtection. Le script détecte si l'équipement est porté ou pas via la fiche, et fonctionne spécifiquement contre les attaques qui utilisent --sournoise. Il est aussi possible de spécifier le port d'un anneau de protection ayant le même effet (prédicat anneauProtection.

    Manoeuvres

    -

    !cof-action-defensive avec comme argument soit simple, soit totale donne le bonus en d\xE9fense de l'action d\xE9fensive (p 71). Cette action est disponible par d\xE9faut dans la liste des actions du tour. Alternativement, si vous n'utilisez pas cette m\xE9thode, vous pouvez cr\xE9er une macro accessible \xE0 tous les tokens, !cof-action-defensive ?{Action d\xE9fensive|simple|totale}.

    -

    Les manoeuvres risqu\xE9es peuvent \xEAtre lanc\xE9es avec la commande !cof-manoeuvre @{selected|token_id} @{target|token_id} effet. Liste des manoeuvres : aveugler, bloquer, desarmer, faireDiversion, menacer, renverser, repousser, tenirADistance.

    -

    Il est aussi possible de faire un test d'attaque oppos\xE9e avec la commande !cof-test-attaque-opposee @{selected|token_id} @{target|token_id}.

    +

    !cof-action-defensive avec comme argument soit simple, soit totale donne le bonus en défense de l'action défensive (p 71). Cette action est disponible par défaut dans la liste des actions du tour. Alternativement, si vous n'utilisez pas cette méthode, vous pouvez créer une macro accessible à tous les tokens, !cof-action-defensive ?{Action défensive|simple|totale}.

    +

    Les manoeuvres risquées peuvent être lancées avec la commande !cof-manoeuvre @{selected|token_id} @{target|token_id} effet. Liste des manoeuvres : aveugler, bloquer, desarmer, faireDiversion, menacer, renverser, repousser, tenirADistance.

    +

    Il est aussi possible de faire un test d'attaque opposée avec la commande !cof-test-attaque-opposee @{selected|token_id} @{target|token_id}.

    Recharger des armes : !cof-recharger N

    -

    Il faut un pr\xE9dicat charge dans le champ de pr\xE9dicat des armes qui ont besoin d'\xEAtre charg\xE9es pour fonctionner. On peut associer un nombre au pr\xE9dicat, pour indiquer un maximum de charges sup\xE9rieur \xE0 1. Noter que si on a 2 armes \xE0 une charge, il faut utiliser un maximum de 2.
    - Recharge l'arme N (augmente les charges d'un). Les armes sont toutes recharg\xE9es \xE0 la fin d'un combat.
    - La commande admet un argment optionel --grenaille pour charger (une arme \xE0 poudre) avec de la grenaille. +

    Il faut un prédicat charge dans le champ de prédicat des armes qui ont besoin d'être chargées pour fonctionner. On peut associer un nombre au prédicat, pour indiquer un maximum de charges supérieur à 1. Noter que si on a 2 armes à une charge, il faut utiliser un maximum de 2.
    + Recharge l'arme N (augmente les charges d'un). Les armes sont toutes rechargées à la fin d'un combat.
    + La commande admet un argment optionel --grenaille pour charger (une arme à poudre) avec de la grenaille.

    -

    D\xE9gainer une arme : !cof-degainer N

    +

    Dégainer une arme : !cof-degainer N

    -

    Pour certaines capacit\xE9s, (commme Plus vite que son ombre ou D\xE9sarmer), il peut \xEAtre utile de savoir quelle arme est en main. Pour cela, le script peut utiliser deux m\xE9thodes : +

    Pour certaines capacités, (commme Plus vite que son ombre ou Désarmer), il peut être utile de savoir quelle arme est en main. Pour cela, le script peut utiliser deux méthodes :

      -
    • !cof-degainer L o\xF9 L est le label d'une des attaques sur la fiche de personnage : cela fait rengainer l'arme en main et d\xE9gainer l'arme correspondant \xE0 cette attaque. Si le label ne correspond \xE0 aucune attaque (ou qu'on ne donne pas de label), l'action fait rengainer l'arme en main. On peut donner en argument 2 labels d'armes, pour faire d\xE9gainer \xE0 la fois une arme dans la main droite (le premier label) et une arme dans la main gauche. !cof-degainer l gauche permet de d\xE9gainer uniquement une arme dans la main gauche. \xC0 noter que si une arme est not\xE9e comme arme gauche dans l'attaque, alors elle est toujours port\xE9e en main gauche. L'ordre de rengainer fait rengainer les deux armes si le personnage porte une arme en main gauche.
    • -
    • Si on attaque avec !cof-attack tok1 tok2 L, et que l'attaque est de type Arme 1 main, Arme 2 mains ou Arme gauche, alors on consid\xE8re qu'on doit d\xE9gainer cette arme pour pouvoir l'utiliser. Le script envoie le message et consid\xE8re ensuite l'arme comme \xE9tant en main, au MJ de v\xE9rifier que le joueur dispose bien d'une action de mouvement pour le faire.
    • -
    • En fin de combat, si le personnage a la capacit\xE9 frappe du vide, le script va automatiquement lui faire rengainer son arme.
    • -
    • Enfin, en fin de combat, si le personnage poss\xE8de un pr\xE9dicat armeParDefaut, le script va lui faire d\xE9gainer l'arme dont le label est la valeur du pr\xE9dicat. Donc si le pr\xE9dicat n'a pas de label associ\xE9, le personnage va rengainer son arme.
    • +
    • !cof-degainer LL est le label d'une des attaques sur la fiche de personnage : cela fait rengainer l'arme en main et dégainer l'arme correspondant à cette attaque. Si le label ne correspond à aucune attaque (ou qu'on ne donne pas de label), l'action fait rengainer l'arme en main. On peut donner en argument 2 labels d'armes, pour faire dégainer à la fois une arme dans la main droite (le premier label) et une arme dans la main gauche. !cof-degainer l gauche permet de dégainer uniquement une arme dans la main gauche. À noter que si une arme est notée comme arme gauche dans l'attaque, alors elle est toujours portée en main gauche. L'ordre de rengainer fait rengainer les deux armes si le personnage porte une arme en main gauche.
    • +
    • Si on attaque avec !cof-attack tok1 tok2 L, et que l'attaque est de type Arme 1 main, Arme 2 mains ou Arme gauche, alors on considère qu'on doit dégainer cette arme pour pouvoir l'utiliser. Le script envoie le message et considère ensuite l'arme comme étant en main, au MJ de vérifier que le joueur dispose bien d'une action de mouvement pour le faire.
    • +
    • En fin de combat, si le personnage a la capacité frappe du vide, le script va automatiquement lui faire rengainer son arme.
    • +
    • Enfin, en fin de combat, si le personnage possède un prédicat armeParDefaut, le script va lui faire dégainer l'arme dont le label est la valeur du prédicat. Donc si le prédicat n'a pas de label associé, le personnage va rengainer son arme.
    -

    Dans tous les cas, si le personnage d\xE9gaine une arme \xE0 2 mains, le script fait enlever le bouclier, et il le fait remettre si on passe d'une arme \xE0 2 mains \xE0 une arme \xE0 1 main.

    -

    Il existe un pr\xE9dicat DEF qui permet d'ajouter sa valeur \xE0 la d\xE9fense d'un personnage. C'est particuli\xE8rement utile pour coder une arme de parade. Par exemple avecDEF:2 dans les pr\xE9dicats de l'arme, elle augmentera la d\xE9fense de 2 quand elle sera port\xE9e.

    +

    Dans tous les cas, si le personnage dégaine une arme à 2 mains, le script fait enlever le bouclier, et il le fait remettre si on passe d'une arme à 2 mains à une arme à 1 main.

    +

    Il existe un prédicat DEF qui permet d'ajouter sa valeur à la défense d'un personnage. C'est particulièrement utile pour coder une arme de parade. Par exemple avecDEF:2 dans les prédicats de l'arme, elle augmentera la défense de 2 quand elle sera portée.

    Couvert :!cof-bonus-couvert b

    - Pour donner un bonus en DEF contre toutes les attaques \xE0 distance, on peut utiliser !cof-bonus-couvert ?{Bonus du couvert?} en s\xE9lectionnant les tokens b\xE9n\xE9ficiant du couvert. La commande accepte un argument --secret permettant de ne pas faire conna\xEEtre l'action du personnage \xE0 tous les joueurs. Pour ne plus \xEAtre \xE0 couvert, il suffit de lancer la commande sans argument. + Pour donner un bonus en DEF contre toutes les attaques à distance, on peut utiliser !cof-bonus-couvert ?{Bonus du couvert?} en sélectionnant les tokens bénéficiant du couvert. La commande accepte un argument --secret permettant de ne pas faire connaître l'action du personnage à tous les joueurs. Pour ne plus être à couvert, il suffit de lancer la commande sans argument.
    -

    \xC9checs critiques :

    -

    En cas d'\xE9chec critique \xE0 une attaque, le script va sugg\xE9rer des effets d'\xE9chec critique inspir\xE9s de cette table sugg\xE9r\xE9e par l'auteur du jeu. Le script proposera m\xEAme dans la plupart des cas un bouton qui automatisera les lancers de d\xE9s et l'application de l'effet, si relevant.

    -

    Il est aussi possible d'utiliser une table personnelle, non-automatis\xE9e (voir les options d'affichage, !cof-options affichage). La table utilis\xE9e (Echec-Critique-Contact) peut \xEAtre modifi\xE9e par le MJ.

    -

    D\xE9g\xE2ts directs (sans attaquant, ou aire d'effet trop complexe pour !cof-attack) : !cof-dmg dm

    +

    Échecs critiques :

    +

    En cas d'échec critique à une attaque, le script va suggérer des effets d'échec critique inspirés de cette table suggérée par l'auteur du jeu. Le script proposera même dans la plupart des cas un bouton qui automatisera les lancers de dés et l'application de l'effet, si relevant.

    +

    Il est aussi possible d'utiliser une table personnelle, non-automatisée (voir les options d'affichage, !cof-options affichage). La table utilisée (Echec-Critique-Contact) peut être modifiée par le MJ.

    +

    Dégâts directs (sans attaquant, ou aire d'effet trop complexe pour !cof-attack) : !cof-dmg dm

    -

    Applique des d\xE9g\xE2ts \xE0 tous les tokens s\xE9lectionn\xE9s. L'argument dm peut \xEAtre un inline roll. Utile par exemple pour les chutes, ou bien les d\xE9g\xE2ts d'environnement, voire de pi\xE8ges.
    - Arguments optionels: une partie des options de !cof-attack, dont le type, et par exemple --psave carac seuil (jet de carac, si sup\xE9rieur au seuil, les d\xE9g\xE2ts sont divis\xE9s par 2). On peut aussi donner un titre aux d\xE9g\xE2ts en utilisant l'option --titre +

    Applique des dégâts à tous les tokens sélectionnés. L'argument dm peut être un inline roll. Utile par exemple pour les chutes, ou bien les dégâts d'environnement, voire de pièges.
    + Arguments optionels: une partie des options de !cof-attack, dont le type, et par exemple --psave carac seuil (jet de carac, si supérieur au seuil, les dégâts sont divisés par 2). On peut aussi donner un titre aux dégâts en utilisant l'option --titre

    -

    Il est possible d'infliger des d\xE9g\xE2ts sur la dur\xE9e en utilisant la commande !cof-effet-temp dotGen(nom) duree --valeur expr type. Les arguments de --valeur donnent l'expression \xE0 \xE9valuer, de type lanc\xE9 de d\xE9, et le type de d\xE9g\xE2ts. Par d\xE9faut, si rien n'est pr\xE9cis\xE9, c'est 1d6 et normal. On peut utiliser les options habituelles de !cof-effet-temp. Ainsi, si on souhaite infliger des d\xE9g\xE2ts de poison de 1d4+1 par tour, pendant 10 tours, avec un jet de CON difficult\xE9 12 pour arr\xEAter l'effet, on pourra \xE9crire !cof-effet-temp dotGen(monPoison) 10 --saveParTour CON 12 --valeur 1d4+1 poison. +

    Il est possible d'infliger des dégâts sur la durée en utilisant la commande !cof-effet-temp dotGen(nom) duree --valeur expr type. Les arguments de --valeur donnent l'expression à évaluer, de type lancé de dé, et le type de dégâts. Par défaut, si rien n'est précisé, c'est 1d6 et normal. On peut utiliser les options habituelles de !cof-effet-temp. Ainsi, si on souhaite infliger des dégâts de poison de 1d4+1 par tour, pendant 10 tours, avec un jet de CON difficulté 12 pour arrêter l'effet, on pourra écrire !cof-effet-temp dotGen(monPoison) 10 --saveParTour CON 12 --valeur 1d4+1 poison.

    Sortir du combat : !cof-fin-combat

    -

    Ferme aussi le tracker de tour. Encore \xE0 mettre en macro dans la barre du MJ (macro automatiquement g\xE9n\xE9r\xE9e par !cof-set-macros). Permet de tenir compte de pleins de capacit\xE9s qui durent un combat, ou utilisables une seule fois par combat,...

    +

    Ferme aussi le tracker de tour. Encore à mettre en macro dans la barre du MJ (macro automatiquement générée par !cof-set-macros). Permet de tenir compte de pleins de capacités qui durent un combat, ou utilisables une seule fois par combat,...

    -

    Utilisation sp\xE9ciale des images et son des armes

    +

    Utilisation spéciale des images et son des armes

    -

    Les images des armes et les sons peuvent \xEAtre red\xE9finis dans le champ d\xE9tail de l'arme.

    +

    Les images des armes et les sons peuvent être redéfinis dans le champ détail de l'arme.

    Pour ce faire vous devez ajouter les urls des images au format suivant dans la description de l'arme :

    -

    [Type de r\xE9ussite] url de l'image [Type de r\xE9ussite]

    +

    [Type de réussite] url de l'image [Type de réussite]

    Par exemple : [img-attack-echec-critique]https://media0.giphy.com/media/3og0INyCmHlNylks9O/giphy.gif[img-attack-echec-critique]

    -

    Les types de r\xE9ussite que vous pouvez mettre en image sont :

    +

    Les types de réussite que vous pouvez mettre en image sont :

    • [img-attack-echec-critique] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec critique
    • [img-attack-echec] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec
    • [img-attack-echec-clignotement] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec par clignotement
    • -
    • [img-attack-succes-critique] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s critique
    • -
    • [img-attack-succes] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s
    • -
    • [img-attack-succes-champion] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s champion
    • +
    • [img-attack-succes-critique] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès critique
    • +
    • [img-attack-succes] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès
    • +
    • [img-attack-succes-champion] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès champion
    -

    De la m\xEAme mani\xE8re vous pouvez ajouter des sons :

    -

    [Type de r\xE9ussite] Nom du son dans votre jukebox [Type de r\xE9ussite]

    +

    De la même manière vous pouvez ajouter des sons :

    +

    [Type de réussite] Nom du son dans votre jukebox [Type de réussite]

    • [sound-attack-echec-critique] son : joue le son n lorque l'arme fait un echec critique
    • [sound-attack-echec] son : joue le son son lorque l'arme fait un echec
    • [sound-attack-echec-clignotement] son : joue le son son lorque l'arme fait un echec par clignotement
    • -
    • [sound-attack-succes-critique] son : joue le son n lorque l'arme fait un succ\xE8s critique
    • -
    • [sound-attack-succes] son : joue le son son lorque l'arme fait un succ\xE8s
    • -
    • [sound-attack-succes-champion] son : joue le son son lorque l'arme fait un succ\xE8s champion
    • +
    • [sound-attack-succes-critique] son : joue le son n lorque l'arme fait un succès critique
    • +
    • [sound-attack-succes] son : joue le son son lorque l'arme fait un succès
    • +
    • [sound-attack-succes-champion] son : joue le son son lorque l'arme fait un succès champion

    Par exemple : [sound-attack-echec-critique]bang[sound-attack-echec-critique]

    -

    Dans cette exemple le son nom\xE9 "bang" dans votre jutbox serra jou\xE9 a chaque echec critique de cette arme

    +

    Dans cette exemple le son nomé "bang" dans votre jutbox serra joué a chaque echec critique de cette arme

    2.2 Soins :

    !cof-soin @{selected|token_id} @{target|token_id} x

    -

    x peut \xEAtre un nombre, un jet de d\xE9 ou leger, modere, groupe ou secondSouffle.

    -

    Les deux premiers arguments sont optionnels. Si !cof-soin n'a qu'un seul argument, c'est interpr\xE9t\xE9 comme le montant des soins, et les tokens soign\xE9s sont ceux s\xE9lectionn\xE9s. Si !cof-soin n'a que 2 arguments, le premier argument est le token du soigneur, et les cibles doivent \xEAtre d\xE9sign\xE9es avec une option de s\xE9lection de groupe.

    +

    x peut être un nombre, un jet de dé ou leger, modere, groupe ou secondSouffle.

    +

    Les deux premiers arguments sont optionnels. Si !cof-soin n'a qu'un seul argument, c'est interprété comme le montant des soins, et les tokens soignés sont ceux sélectionnés. Si !cof-soin n'a que 2 arguments, le premier argument est le token du soigneur, et les cibles doivent être désignées avec une option de sélection de groupe.

    Options (en plus de options normales de commandes):
      -
    • --portee n : permet de sp\xE9cifier une distance maximum entre le soigneur et le soign\xE9 (au-del\xE0, le soin \xE9choue)
    • -
    • --transfer : le soin est pay\xE9 avec les PV du soigneur
    • +
    • --portee n : permet de spécifier une distance maximum entre le soigneur et le soigné (au-delà, le soin échoue)
    • +
    • --transfer : le soin est payé avec les PV du soigneur
    • --mana n : demande au lanceur de payer n points de mana
    • -
    • --depasseLimite n : permet de lancer les sorts de soins l\xE9ger, mod\xE9r\xE9 ou de groupe quand la limite journali\xE8re est d\xE9pass\xE9e, mais en augmentant le co\xFBt en mana de n \xE0 chaque nouveau d\xE9passement.
    • -
    • --limiteSoinsParJour n : limite le nombre total de PVs soign\xE9s par jour. Cette limite peut \xEAtre associ\xE9e \xE0 une ressource (sp\xE9cifier en deuxi\xE8me argument de l'option, peut contenir des espaces), de sorte que seuls les soins qui mentionnent cette ressource sont concern\xE9s par cette limitation. Cette option n'a de sens que si un soigneur est pr\xE9cis\xE9.
    • -
    • --sacrifierPV : le soigneur doit sacrifier autant de PV que le montant des soins (que ces soins soient utilis\xE9s ou non).
    • +
    • --depasseLimite n : permet de lancer les sorts de soins léger, modéré ou de groupe quand la limite journalière est dépassée, mais en augmentant le coût en mana de n à chaque nouveau dépassement.
    • +
    • --limiteSoinsParJour n : limite le nombre total de PVs soignés par jour. Cette limite peut être associée à une ressource (spécifier en deuxième argument de l'option, peut contenir des espaces), de sorte que seuls les soins qui mentionnent cette ressource sont concernés par cette limitation. Cette option n'a de sens que si un soigneur est précisé.
    • +
    • --sacrifierPV : le soigneur doit sacrifier autant de PV que le montant des soins (que ces soins soient utilisés ou non).
    @@ -616,33 +620,33 @@

    2.3 Repos et changement de jour

    Changement de jour

    -

    !cof-nouveau-jour : remise \xE0 z\xE9ro de toutes les limites journali\xE8res.

    +

    !cof-nouveau-jour : remise à zéro de toutes les limites journalières.

    Repos de plus de 8 h

    -

    Fait r\xE9cup\xE9rer 1 PR ou les points de vie correspondant \xE0 1 PR, plus les points de mana.

    +

    Fait récupérer 1 PR ou les points de vie correspondant à 1 PR, plus les points de mana.

      -
    • !cof-nouveau-jour --repos : Pour une nuit qui se passe bien : fait l'effet d'un nouveau jour sur le monde, et, si aucun token n'est s\xE9lectionn\xE9, applique un repos de 8 h \xE0 tous les tokens de la page, sinon applique ce repos uniquement aux tokens s\xE9lectionn\xE9s.
    • -
    • !cof-recuperation --reposLong : applique le repos aux tokens selectionn\xE9s, sans remettre \xE0 z\xE9ro les limites journali\xE8res. +
    • !cof-nouveau-jour --repos : Pour une nuit qui se passe bien : fait l'effet d'un nouveau jour sur le monde, et, si aucun token n'est sélectionné, applique un repos de 8 h à tous les tokens de la page, sinon applique ce repos uniquement aux tokens sélectionnés.
    • +
    • !cof-recuperation --reposLong : applique le repos aux tokens selectionnés, sans remettre à zéro les limites journalières.

    Repos de 10 minutes

    -

    !cof-recuperation : d\xE9pense 1 PR pour se soigner. \xC0 mettre en macro associ\xE9e aux tokens, car tous les joueurs en ont besoin (g\xE9n\xE9r\xE9 par !cof-set-macros.

    +

    !cof-recuperation : dépense 1 PR pour se soigner. À mettre en macro associée aux tokens, car tous les joueurs en ont besoin (généré par !cof-set-macros.

    -

    2.4 Statut et \xE9tats

    +

    2.4 Statut et états

    -

    !cof-statut affiche l'\xE9tat courant de tous les tokens s\xE9lectionn\xE9s. Utile pour conna\xEEtre facilement les \xE9tats qui ne sont pas directement visibles sur un token (points de r\xE9cup\xE9ration, armes charg\xE9es, ...). Il est possible de rajouter l'affichage d'autres attributs que ceux s\xE9lectionn\xE9s par d\xE9faut par le script. Pour cela, utiliser un pr\xE9dicat attributsDeStatut, de valeur la liste des noms d'attributs \xE0 afficher, s\xE9par\xE9s par des virgules. Attention, si vous avez besoin de s\xE9parer vos attributs par des virgules, pensez \xE0 utiliser la syntaxe avec ::. Si vous le souhaitez, vous pouvez utiliser plusieurs pr\xE9dicats nomm\xE9s attributsDeStatut.

    -

    \xC9tats g\xE9r\xE9s en utilisant le statut des tokens

    +

    !cof-statut affiche l'état courant de tous les tokens sélectionnés. Utile pour connaître facilement les états qui ne sont pas directement visibles sur un token (points de récupération, armes chargées, ...). Il est possible de rajouter l'affichage d'autres attributs que ceux sélectionnés par défaut par le script. Pour cela, utiliser un prédicat attributsDeStatut, de valeur la liste des noms d'attributs à afficher, séparés par des virgules. Attention, si vous avez besoin de séparer vos attributs par des virgules, pensez à utiliser la syntaxe avec ::. Si vous le souhaitez, vous pouvez utiliser plusieurs prédicats nommés attributsDeStatut.

    +

    États gérés en utilisant le statut des tokens

    -

    !cof-set-state etat [true|false] permet de changer l'\xE9tat des tokens s\xE9lectionn\xE9s. Si cet \xE9tat concerne un personnage avec tokens li\xE9s (en liant la barre 1 aux points de vie), alors l'\xE9tat persiste si on change de carte (utilisation d'un attribut hors fiche).

    -

    Liste des \xE9tats et markers correspondants :

    +

    !cof-set-state etat [true|false] permet de changer l'état des tokens sélectionnés. Si cet état concerne un personnage avec tokens liés (en liant la barre 1 aux points de vie), alors l'état persiste si on change de carte (utilisation d'un attribut hors fiche).

    +

    Liste des états et markers correspondants :

    - + @@ -653,40 +657,40 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - + - - - - - @@ -700,14 +704,14 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - - @@ -716,19 +720,19 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - + - + - @@ -742,7 +746,7 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - @@ -756,7 +760,7 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - @@ -764,393 +768,393 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    LdB : Livre de Base, Comp : Compagnon
    \xC9tatÉtat Source Remarque Marker Std.
    Affaibli LdB p70Appara\xEEt sur la fiche persoApparaît sur la fiche perso half-heart cof-affaibli
    Apeur\xE9 + Apeuré Victime d'un sort de Peur screaming cof-apeure
    Assomm\xE9 + Assommé LdB p72 pummeled cof-assomme
    Aveugl\xE9 + Aveuglé LdB p70 Change aussi la vision du token bleeding-eye cof-aveugle
    Bless\xE9 + Blessé LdB p177 arrowed cof-blesse
    Encombr\xE9 + Encombré Comp p103 frozen-orbcof-endormi
    \xC9tourdi + Étourdi LdB p70 half-haze cof-etourdi
    Immobilis\xE9 + Immobilisé LdB p70 cobweb
    Invisible Sort d'invisibilit\xE9Sort d'invisibilité ninja-mask cof-invisible
    Mort LdB p73M\xEAme \xE9tat pour un PJ juste inconscient \xE0 0 PVMême état pour un PJ juste inconscient à 0 PV dead dead
    Paralys\xE9 + Paralysé LdB p70 fishing-netcof-ralenti
    Renvers\xE9 + Renversé LdB p70 back-paincof-surpris
    P\xE9nombre + Pénombre LdB p71 archery-target
    -

    Pour faciliter la gestion des \xE9tats, on peut deux macros dans la barre du GM, !cof-set-state ?{\xC9tat|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|bless\xE9|encombre} true, et la m\xEAme avec false. (N'oubliez pas que la commande !cof-set-macros permet de g\xE9n\xE9rer automatiquement les macros utiles au script). Une fois qu'on conna\xEEt bien les ic\xF4nes, on peut directement les changer sur les tokens pour le m\xEAme effet (et m\xEAme faire un undo de ces changements si besoin).

    -

    \xC0 noter qu'un personnage ayant un pr\xE9dicat nomm\xE9 immunite_etat ne pourra pas \xEAtre mis dans l'\xE9tat etat.

    -

    Enfin, il est possible de faire r\xE9aliser un jet pour se lib\xE9rer d'un \xE9tat, en utilisant la commande !cof-save-state etat carac seuil. Il est possible de remplacer seuil par une id de token pour faire faire un test en opposition avec ce token. On peut aussi passer la caract\xE9ristique et le seuil en argument \xE0 !cof-set-state pour proposer le jet \xE0 chaque fois qu'on affiche les actions du tour ou qu'on affiche le statut du personnage.

    +

    Pour faciliter la gestion des états, on peut deux macros dans la barre du GM, !cof-set-state ?{État|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blessé|encombre} true, et la même avec false. (N'oubliez pas que la commande !cof-set-macros permet de générer automatiquement les macros utiles au script). Une fois qu'on connaît bien les icônes, on peut directement les changer sur les tokens pour le même effet (et même faire un undo de ces changements si besoin).

    +

    À noter qu'un personnage ayant un prédicat nommé immunite_etat ne pourra pas être mis dans l'état etat.

    +

    Enfin, il est possible de faire réaliser un jet pour se libérer d'un état, en utilisant la commande !cof-save-state etat carac seuil. Il est possible de remplacer seuil par une id de token pour faire faire un test en opposition avec ce token. On peut aussi passer la caractéristique et le seuil en argument à !cof-set-state pour proposer le jet à chaque fois qu'on affiche les actions du tour ou qu'on affiche le statut du personnage.

    -

    Affaiblissements de caract\xE9ristiques

    +

    Affaiblissements de caractéristiques

    - !cof-affaiblir-carac carac valeur permet d'affaiblir temporairement une caract\xE9ristique (force, dext\xE9rit\xE9, constitution, intelligence, sagesse, charisme ou random) d'une valeur positive. Il existe aussi une option pour les attaques, --affaiblirCarac, qui permet de n'affaiblir une caract\xE9ristique que si une attaque est r\xE9ussie. + !cof-affaiblir-carac carac valeur permet d'affaiblir temporairement une caractéristique (force, dextérité, constitution, intelligence, sagesse, charisme ou random) d'une valeur positive. Il existe aussi une option pour les attaques, --affaiblirCarac, qui permet de n'affaiblir une caractéristique que si une attaque est réussie.

    -

    Une caract\xE9ristique affaiblie remonte de 1 apr\xE8s chaque nuit de repos. Le sort de r\xE9g\xE9n\xE9ration permet de r\xE9cup\xE9rer 1d4 points d'une seule caract\xE9ristique physique (d'abord constitution, puis force puis dext\xE9rit\xE9). Le sort d\xE9livrance permet de r\xE9cup\xE9rer 1d4 point d'une seule caract\xE9ristique, et comme indiqu\xE9 dans les r\xE8gles, le sort de gu\xE9rison annule tous les affaiblissements de caract\xE9ritiques. Enfin le script propose une commande d\xE9di\xE9e, !cof-soigner-affaiblissement carac valeur pour soigner les affaiblissements. +

    Une caractéristique affaiblie remonte de 1 après chaque nuit de repos. Le sort de régénération permet de récupérer 1d4 points d'une seule caractéristique physique (d'abord constitution, puis force puis dextérité). Le sort délivrance permet de récupérer 1d4 point d'une seule caractéristique, et comme indiqué dans les règles, le sort de guérison annule tous les affaiblissements de caractéritiques. Enfin le script propose une commande dédiée, !cof-soigner-affaiblissement carac valeur pour soigner les affaiblissements.

    -

    \xC0 noter que la diminution de constitution fait baisser les points de vie maximum, et qu'une constitution de 0 conduit \xE0 la mort.

    +

    À noter que la diminution de constitution fait baisser les points de vie maximum, et qu'une constitution de 0 conduit à la mort.

    -

    Conditions hostiles et extr\xEAmes

    +

    Conditions hostiles et extrêmes

    -

    Pour des conditions hostiles, faire !cof-effet conditionsHostiles oui en s\xE9lectionnant les personnages concern\xE9s. Pour des conditions extr\xEAmes, !cof-effet conditionsHostiles 5. \xC0 noter que le script permet de passer en argument n'importe quel nombre, qui sera appliqu\xE9 en malus \xE0 la DEX, FOR, DEF et attaque.

    +

    Pour des conditions hostiles, faire !cof-effet conditionsHostiles oui en sélectionnant les personnages concernés. Pour des conditions extrêmes, !cof-effet conditionsHostiles 5. À noter que le script permet de passer en argument n'importe quel nombre, qui sera appliqué en malus à la DEX, FOR, DEF et attaque.

    Autres bufs et debufs

    !cof-buf-def n : buf ou debuf de la DEF.

    -

    !cof-remove-buf-def : enl\xE8ve tout buf ou debuf de la def.

    -

    !cof-effet-temp effet duree : ajoute l'effet effet \xE0 la cible pour la dur\xE9e, !cof-effet-combat effet ajoute l'effet pour le combat, et !cof-effet effet ajoute ou enl\xE8ve un effet \xE0 dur\xE9e ind\xE9termin\xE9e. \xC0 noter que si la dur\xE9e est 0 ou fin, alors la commande met fin \xE0 l'effet (utile pour des effets temporaires qui ont une action en fin d'effet, comme agrandissement ou formeDArbre). Un personnage ayant un pr\xE9dicat nomm\xE9 immunite_effetTemp est immunis\xE9 \xE0 l'effet temporaire de nom effetTemp.

    +

    !cof-remove-buf-def : enlève tout buf ou debuf de la def.

    +

    !cof-effet-temp effet duree : ajoute l'effet effet à la cible pour la durée, !cof-effet-combat effet ajoute l'effet pour le combat, et !cof-effet effet ajoute ou enlève un effet à durée indéterminée. À noter que si la durée est 0 ou fin, alors la commande met fin à l'effet (utile pour des effets temporaires qui ont une action en fin d'effet, comme agrandissement ou formeDArbre). Un personnage ayant un prédicat nommé immunite_effetTemp est immunisé à l'effet temporaire de nom effetTemp.

    • --lanceur id : indique quel est le lanceur. Utile pour un certain nombre d'autres options.
    • -
    • --mana id cout : impose au token id de d\xE9penser cout mana. Si --lanceur est donn\xE9, id est inutile. La pr\xE9sence de cette option, m\xEAme avec un co\xFBt de 0, indique au script que l'effet devrait \xEAtre supprim\xE9 \xE0 la mort du lanceur.
    • -
    • --limiteParJour l : limite le nombre d'utilisations de cette effet \xE0 l fois par jour. On peut pr\xE9ciser un nom apr\xE8s l, qui va correspondre \xE0 une ressource pouvant \xEAtre partag\xE9e avec d'autres attaques ou d'autres effets (voir !cof-attack). Par d\xE9faut, le nom de cette ressource est effet. Attention, il faut un lanceur auquel appliquer la limite par jour !
    • -
    • --limiteParCombat : m\xEAme effet que la limite par jour. Si aucun argument n'est donn\xE9, la limite est de une fois par combat. Attention, il faut un lanceur auquel appliquer la limite par combat !
    • -
    • --tempsRecharge effet duree : l'action n'est possible que si l'effet est inactif sur le personnage qui g\xE9n\xE8re l'effet, et de plus active l'effet sur celui-ci pour la dur\xE9e indiqu\xE9e. Il existe un effet temporaire g\xE9n\xE9rique, rechargeGen(desc) que vous pouvez utiliser si aucun effet existant ne correspond.
    • -
    • --dose nom: d\xE9finie une ressource nomm\xE9e dose_nom, dont la valeur doit \xEAtre positive. Utile par exemple pour les parchemins, les potions ou les baguettes.
    • -
    • --portee id d : impose aux cibles de l'effet d'\xEAtre \xE0 moins de d m\xE8tres du token id. Si --lanceur est pr\xE9cis\xE9, inutile de donner id.
    • +
    • --mana id cout : impose au token id de dépenser cout mana. Si --lanceur est donné, id est inutile. La présence de cette option, même avec un coût de 0, indique au script que l'effet devrait être supprimé à la mort du lanceur.
    • +
    • --limiteParJour l : limite le nombre d'utilisations de cette effet à l fois par jour. On peut préciser un nom après l, qui va correspondre à une ressource pouvant être partagée avec d'autres attaques ou d'autres effets (voir !cof-attack). Par défaut, le nom de cette ressource est effet. Attention, il faut un lanceur auquel appliquer la limite par jour !
    • +
    • --limiteParCombat : même effet que la limite par jour. Si aucun argument n'est donné, la limite est de une fois par combat. Attention, il faut un lanceur auquel appliquer la limite par combat !
    • +
    • --tempsRecharge effet duree : l'action n'est possible que si l'effet est inactif sur le personnage qui génère l'effet, et de plus active l'effet sur celui-ci pour la durée indiquée. Il existe un effet temporaire générique, rechargeGen(desc) que vous pouvez utiliser si aucun effet existant ne correspond.
    • +
    • --dose nom: définie une ressource nommée dose_nom, dont la valeur doit être positive. Utile par exemple pour les parchemins, les potions ou les baguettes.
    • +
    • --portee id d : impose aux cibles de l'effet d'être à moins de d mètres du token id. Si --lanceur est précisé, inutile de donner id.
    • --puissant : lance la version puissante de l'effet
    • --puissant oui : idem
    • --puissant non : lance la version non puissante (efface le dernier effet puissant)
    • -
    • --puissant duree : multiplie la dur\xE9e par 2
    • -
    • --puissant portee : multiplie la port\xE9e par 2
    • -
    • --saveParTour carac seuil : la cible peut se sortir de l'effet chaque tour gr\xE2ce \xE0 un test de carac de difficulte seuil.
    • -
    • --saveActifParTour carac seuil : la cible peut se sortir de l'effet \xE0 tour gr\xE2ce \xE0 un test de carac de difficulte seuil (utilisation dans bouton dans la liste d'actions).
    • -
    • --save carac seuil : la cible peut faire un jet pour \xE9chapper \xE0 l'effet. Si on ajoute l'argument demiDuree, alors r\xE9ussir la sauvegarde ne fait que diviser la dur\xE9e.
    • +
    • --puissant duree : multiplie la durée par 2
    • +
    • --puissant portee : multiplie la portée par 2
    • +
    • --saveParTour carac seuil : la cible peut se sortir de l'effet chaque tour grâce à un test de carac de difficulte seuil.
    • +
    • --saveActifParTour carac seuil : la cible peut se sortir de l'effet à tour grâce à un test de carac de difficulte seuil (utilisation dans bouton dans la liste d'actions).
    • +
    • --save carac seuil : la cible peut faire un jet pour échapper à l'effet. Si on ajoute l'argument demiDuree, alors réussir la sauvegarde ne fait que diviser la durée.
    • --seulementVivant : l'effet ne peut s'appliquer qu'aux personnages vivants.
    • -
    • --tempeteDeMana liste : indique des effets de temp\xEAte de mana. La liste peut contenir un nombre (pour l'effet intense), duree, rapide et portee. Si le rang du sort est sp\xE9cifi\xE9 (par l'option --rang, un message est affich\xE9e si le co\xFBt en mana est sup\xE9rieur au rang. Si la liste d'options est vide, le script affiche un menu dans le chat pour sp\xE9cifier les options de temp\xEAte de mana.
    • -
    • --magieEnArmure : indique d'appliquer les r\xE8gles pour la magie en armure pour un profil hybride. Il faut pour cela un lanceur d\xE9fini. Par defaut, va faire test l'intelligence par un jet de difficult\xE9 10 + rang + malus d'armure. Le rang est obtenu par l'option --rang. J'utilise le malus d'armure car il n'y a pas moyen de distinguer la DEF intrins\xE8que de l'armure de ses bonus de DEF d\xFBs \xE0 un bonus magique. Enfin, on peut utiliser la r\xE8gle de d\xE9pense suppl\xE9mentaire de mana \xE0 la place du jet d'INT en utilisant l'option --magieEnarmure mana. Encore une fois, je prends le malus d'armure, divis\xE9 par 3 et arrondi au sup\xE9rieur pour les r\xE8gles de mana de base.
    • -
    • --accumuleDuree n : l'effet peut \xEAtre accumul\xE9 : chaque fois qu'on applique \xE0 nouveau l'effet avec une dur\xE9e donn\xE9e, on ajoute cette dur\xE9e \xE0 la dur\xE9e courante de l'effet sur la cible. On ne peut cumuler ainsi que n instances de l'effet.
    • -
    • --valeur n : pour certains effet, permet de sp\xE9cifier une valeur qui remplace la valeur par d\xE9faut de l'effet.
    • -
    • --optionEffet opt arg1 arg2 ... : sp\xE9cifie une option \xE0 l'effet. L'option opt doit \xEAtre donn\xE9e sans le -- et sera pass\xE9e telle quelle \xE0 l'effet, par exemple pour les d\xE9g\xE2ts p\xE9riodiques. Si on a besoin de plusieurs options, il faut utiliser plusieurs fois --optionEffet.
    • -
    • --secret : le r\xE9sultat de l'effet est chuchot\xE9 au joueur qui lance la commande.
    • -
    • --fx effet : affiche l'effet sp\xE9cial entre le lanceur et ses cibles. Il est possible d'utiliser un effet que vous avez d\xE9fini vous-m\xEAme en utilisant l'option --fx custom nom, o\xF9 nom est le nom de votre effet.
    • -
    • --targetFx effet : affiche l'effet sp\xE9cial sur toutes les cibles (l'effet ne doit pas \xEAtre directionnel).
    • +
    • --tempeteDeMana liste : indique des effets de tempête de mana. La liste peut contenir un nombre (pour l'effet intense), duree, rapide et portee. Si le rang du sort est spécifié (par l'option --rang, un message est affichée si le coût en mana est supérieur au rang. Si la liste d'options est vide, le script affiche un menu dans le chat pour spécifier les options de tempête de mana.
    • +
    • --magieEnArmure : indique d'appliquer les règles pour la magie en armure pour un profil hybride. Il faut pour cela un lanceur défini. Par defaut, va faire test l'intelligence par un jet de difficulté 10 + rang + malus d'armure. Le rang est obtenu par l'option --rang. J'utilise le malus d'armure car il n'y a pas moyen de distinguer la DEF intrinsèque de l'armure de ses bonus de DEF dûs à un bonus magique. Enfin, on peut utiliser la règle de dépense supplémentaire de mana à la place du jet d'INT en utilisant l'option --magieEnarmure mana. Encore une fois, je prends le malus d'armure, divisé par 3 et arrondi au supérieur pour les règles de mana de base.
    • +
    • --accumuleDuree n : l'effet peut être accumulé : chaque fois qu'on applique à nouveau l'effet avec une durée donnée, on ajoute cette durée à la durée courante de l'effet sur la cible. On ne peut cumuler ainsi que n instances de l'effet.
    • +
    • --valeur n : pour certains effet, permet de spécifier une valeur qui remplace la valeur par défaut de l'effet.
    • +
    • --optionEffet opt arg1 arg2 ... : spécifie une option à l'effet. L'option opt doit être donnée sans le -- et sera passée telle quelle à l'effet, par exemple pour les dégâts périodiques. Si on a besoin de plusieurs options, il faut utiliser plusieurs fois --optionEffet.
    • +
    • --secret : le résultat de l'effet est chuchoté au joueur qui lance la commande.
    • +
    • --fx effet : affiche l'effet spécial entre le lanceur et ses cibles. Il est possible d'utiliser un effet que vous avez défini vous-même en utilisant l'option --fx custom nom, où nom est le nom de votre effet.
    • +
    • --targetFx effet : affiche l'effet spécial sur toutes les cibles (l'effet ne doit pas être directionnel).
    • --son son : joue le son (normalement compatible avec Roll20AM)
    • --image img : affiche l'image dans le texte d'activation de l'effet.
    • -
    • --tokenSide n : utilisable seulement pour les tokens \xE0 plusieurs faces. Dans ce cas, va changer la face du token en n (\xE0 noter que les faces sont num\xE9rot\xE9es \xE0 partir de 0). Quand l'effet se termine, le token retrouve la face qu'il avait au moment o\xF9 on avait appliqu\xE9 l'effet.
    • -
    • --type : il est possible d'associer un type \xE0 l'effet. L'utilisation la plus courante est le type poison ou maladie, qui vont permettre de tenir compte des bonus ou immunit\xE9s contre les effets de ce type.
    • -
    • --montreActions : affiche les actions du tours de la cible apr\xE8s avoir appliqu\xE9 l'effet. Utile si les actions du tours d\xE9pendent de cet effet, pour afficher une liste \xE0 jour.
    • -
    • --degainer L : le lanceur d\xE9gaine l'arme de label L.
    • +
    • --tokenSide n : utilisable seulement pour les tokens à plusieurs faces. Dans ce cas, va changer la face du token en n (à noter que les faces sont numérotées à partir de 0). Quand l'effet se termine, le token retrouve la face qu'il avait au moment où on avait appliqué l'effet.
    • +
    • --type : il est possible d'associer un type à l'effet. L'utilisation la plus courante est le type poison ou maladie, qui vont permettre de tenir compte des bonus ou immunités contre les effets de ce type.
    • +
    • --montreActions : affiche les actions du tours de la cible après avoir appliqué l'effet. Utile si les actions du tours dépendent de cet effet, pour afficher une liste à jour.
    • +
    • --degainer L : le lanceur dégaine l'arme de label L.
    -

    !cof-boire-alcool et !cof-desaouler permettent de faire varier le niveau d'\xE9bri\xE9t\xE9. Par exemple, pour tester si le niveau d'\xE9bri\xE9t\xE9 augmente apr\xE8s avoir bu un certain nombre de verres, on peut utiliser la macro !cof-boire-alcool --save CON [[10+?{Nombre de verres}]]. +

    !cof-boire-alcool et !cof-desaouler permettent de faire varier le niveau d'ébriété. Par exemple, pour tester si le niveau d'ébriété augmente après avoir bu un certain nombre de verres, on peut utiliser la macro !cof-boire-alcool --save CON [[10+?{Nombre de verres}]].

    -

    Effets retard\xE9s

    +

    Effets retardés

    -

    On peut utiliser l'effet temporaire g\xE9n\xE9rique messageRetarde(nom) pour programmer un message qui sera affich\xE9 apr\xE8s un certain nombre de tours. Au bout de ce nombre de tours, le nom est affich\xE9, ainsi que le texte de valeur (avec --valeur si besoin). La syntaxe est !cof-effet-temp messageRetarde(nom) duree --valeur message. Si vous avez besoin d'un message qui contienne des espaces, remplacez les espaces par des _.

    -

    On peut aussi d\xE9clencher un effet apr\xE8s un certain nombre de tour avec l'effet temporaire g\xE9n\xE9rique effetRetarde(effet). Apr\xE8s la dur\xE9e de l'effet retard\xE9, si effet est un \xE9tat, la cible est mise dans cet \xE9tat, si c'est un effet temporaire, on lui applique cet effet pour une dur\xE9e de 1 tour, ou si un argument --valeur a \xE9t\xE9 donn\xE9, il sera utilis\xE9 comme dur\xE9e. Enfin si ce n'est ni l'un ni l'autre, un attribut avec le nom effet sera cr\xE9\xE9, de valeur courante true, ou bien si un argument --valeur a \xE9t\xE9 donn\xE9, cette valeur sera utilis\xE9e comme valeur courante de l'attribut effet.

    +

    On peut utiliser l'effet temporaire générique messageRetarde(nom) pour programmer un message qui sera affiché après un certain nombre de tours. Au bout de ce nombre de tours, le nom est affiché, ainsi que le texte de valeur (avec --valeur si besoin). La syntaxe est !cof-effet-temp messageRetarde(nom) duree --valeur message. Si vous avez besoin d'un message qui contienne des espaces, remplacez les espaces par des _.

    +

    On peut aussi déclencher un effet après un certain nombre de tour avec l'effet temporaire générique effetRetarde(effet). Après la durée de l'effet retardé, si effet est un état, la cible est mise dans cet état, si c'est un effet temporaire, on lui applique cet effet pour une durée de 1 tour, ou si un argument --valeur a été donné, il sera utilisé comme durée. Enfin si ce n'est ni l'un ni l'autre, un attribut avec le nom effet sera créé, de valeur courante true, ou bien si un argument --valeur a été donné, cette valeur sera utilisée comme valeur courante de l'attribut effet.

    -

    Pr\xE9dicats : !cof-set-predicate

    +

    Prédicats : !cof-set-predicate

    -

    Il est possible d'ajouter ou de retirer un pr\xE9dicat avec la fonction !cof-set-predicate nom, optionellement suivi de true ou false.

    +

    Il est possible d'ajouter ou de retirer un prédicat avec la fonction !cof-set-predicate nom, optionellement suivi de true ou false.

    Autres attributs : !cof-set-attribute

    - Il est possible de changer ou cr\xE9er n'importe quel attribut avec la fonction !cof-set-attribute nom val. Optionellement, on peut sp\xE9cifier en troisi\xE8me argument une valeur maximale de l'attribut (comme dans !cof-set-attribute nom val max). Attention, \xE7a peut interragir de fa\xE7on impr\xE9vue avec le script ou la fiche, si on \xE9crit dans un attribut utilis\xE9 par la fiche. + Il est possible de changer ou créer n'importe quel attribut avec la fonction !cof-set-attribute nom val. Optionellement, on peut spécifier en troisième argument une valeur maximale de l'attribut (comme dans !cof-set-attribute nom val max). Attention, ça peut interragir de façon imprévue avec le script ou la fiche, si on écrit dans un attribut utilisé par la fiche.

    2.5 Sorts

    -

    !cof-attaque-magique @{selected|token_id} @{target|token_id} : fait un jet d'attaque magique oppos\xE9 entre le lanceur et sa cible, et dit juste si le sort est rat\xE9 ou r\xE9ussi. Options disponibles : --portee et --mana.

    -

    !cof-lancer-sort texte : le token s\xE9lectionn\xE9 lance un sort sans support particulier du script (seul un whisper est envoy\xE9 au joueur et au MJ). Options disponibles : --manapour indiquer un co\xFBt en mana et --son pour jouer un son. Pour un sort sur plusieurs cibles, utiliser l'option --lanceur @{selected|token_id}.

    -

    !cof-peur difficult\xE9 dur\xE9e : effet de peur (n\xE9cromant, dragon, etc). Tant que la peur est active, statut screaming. difficult\xE9 est la difficult\xE9 du jet de SAG.

    +

    !cof-attaque-magique @{selected|token_id} @{target|token_id} : fait un jet d'attaque magique opposé entre le lanceur et sa cible, et dit juste si le sort est raté ou réussi. Options disponibles : --portee et --mana.

    +

    !cof-lancer-sort texte : le token sélectionné lance un sort sans support particulier du script (seul un whisper est envoyé au joueur et au MJ). Options disponibles : --manapour indiquer un coût en mana et --son pour jouer un son. Pour un sort sur plusieurs cibles, utiliser l'option --lanceur @{selected|token_id}.

    +

    !cof-peur difficulté durée : effet de peur (nécromant, dragon, etc). Tant que la peur est active, statut screaming. difficulté est la difficulté du jet de SAG.

    Options :
      -
    • --resisteAvecForce : on prend le max de FOR et SAG pour r\xE9sister
    • -
    • --etourdi : la peur fait fuir ou rend \xE9tourdi
    • +
    • --resisteAvecForce : on prend le max de FOR et SAG pour résister
    • +
    • --etourdi : la peur fait fuir ou rend étourdi
    • --ralenti : la peur ralenti
    • --paralyse : la peur paralyse
    • -
    • --secoue : la peur ne donne qu'un malus de -2 aux tests. Mais un autre effet de peur de m\xEAme type fait fuir.
    • +
    • --secoue : la peur ne donne qu'un malus de -2 aux tests. Mais un autre effet de peur de même type fait fuir.
    • --effroi : la peur est passive (pas un sort)
    • -
    • --portee n : limite la port\xE9e du sort \xE0 n metres.
    • -
    • --lanceur id : le lanceur de l'effet de peur (si il y en a un). N\xE9cessaire pour la port\xE9e, par exemple.
    • -
    • --titre message : sp\xE9cifie un titre pour la fen\xEAtre affichant les jets de r\xE9sistance \xE0 la peur.
    • -
    • --immuniseSiResiste nom : la personne qui r\xE9siste \xE0 cet effet de peur est ensuite immunis\xE9 pour la journ\xE9e aux effets de peur ayant la m\xEAme option (avec le m\xEAme nom).
    • +
    • --portee n : limite la portée du sort à n metres.
    • +
    • --lanceur id : le lanceur de l'effet de peur (si il y en a un). Nécessaire pour la portée, par exemple.
    • +
    • --titre message : spécifie un titre pour la fenêtre affichant les jets de résistance à la peur.
    • +
    • --immuniseSiResiste nom : la personne qui résiste à cet effet de peur est ensuite immunisé pour la journée aux effets de peur ayant la même option (avec le même nom).
    - Noter qu'un pr\xE9dicat courage permet d'obtenir un bonus (\xE9gal \xE0 la valeur du pr\xE9dicat) au jet pour r\xE9sister \xE0 la peur. + Noter qu'un prédicat courage permet d'obtenir un bonus (égal à la valeur du prédicat) au jet pour résister à la peur.

    2.6 Consommables !cof-consommables

    -

    Cette fonction affiche une liste de consommables, avec la possibilit\xE9 de cliquer sur un \xE9l\xE9ment de la liste pour le consommer (et activer son effet) ou l'\xE9changer avec un autre personnage (via le symbole d'\xE9change).

    -

    Pour cela, la fonction utilise la liste des consommables sur la fiche (onglet "\xC9quipement"). Elle ne va afficher que les consommables qui ont un effet (d\xE9crit dans la ligne Effet sous le nom du consommable).

    +

    Cette fonction affiche une liste de consommables, avec la possibilité de cliquer sur un élément de la liste pour le consommer (et activer son effet) ou l'échanger avec un autre personnage (via le symbole d'échange).

    +

    Pour cela, la fonction utilise la liste des consommables sur la fiche (onglet "Équipement"). Elle ne va afficher que les consommables qui ont un effet (décrit dans la ligne Effet sous le nom du consommable).

    Exemple d'une liste de consommable.
    - +

    Pour l'instant, seules les commandes !cof-effet-temp, !cof-effet-combat, !cof-effet, !cof-enduire-poison, !cof-attack, !cof-lancer-sort et !cof-soin diminuent correctement le nombre de consommables.

    Attention :

      -
    • Pour la commande !cof-attack, il est vivemement recommand\xE9 de ne pas utiliser de label, mais uniquement un nom et des options si vous voulez faciliter l'\xE9change du consommable.
    • -
    • De mani\xE8re g\xE9n\xE9rale, faites attention avec les r\xE9f\xE9rences utilis\xE9 dans le consommable du personnage qui utilise le consommable.
      +
    • Pour la commande !cof-attack, il est vivemement recommandé de ne pas utiliser de label, mais uniquement un nom et des options si vous voulez faciliter l'échange du consommable.
    • +
    • De manière générale, faites attention avec les références utilisé dans le consommable du personnage qui utilise le consommable.
    -

    L'\xE9change via le symbole vous permettra de s\xE9lectionner un token destinataire qui recevra le consommable dans sa liste. Si le consommable existe d\xE9j\xE0 pour le destinataire, sa quantit\xE9 sera augment\xE9 de 1, sinon le consommable sera cr\xE9\xE9.

    +

    L'échange via le symbole vous permettra de sélectionner un token destinataire qui recevra le consommable dans sa liste. Si le consommable existe déjà pour le destinataire, sa quantité sera augmenté de 1, sinon le consommable sera créé.

    -

    Cette fonction peut-\xEAtre tr\xE8s utile pour que les PJ \xE9changent entre eux un consommable, mais aussi pour faciliter la vente d'objet entre PNJ et PJ.

    -

    Pour cette derni\xE8re, il vous suffira de pr\xE9parer un personnage avec un token qui contient, dans son \xE9quipement, les consommables \xE0 \xE9changer/vendre.

    +

    Cette fonction peut-être très utile pour que les PJ échangent entre eux un consommable, mais aussi pour faciliter la vente d'objet entre PNJ et PJ.

    +

    Pour cette dernière, il vous suffira de préparer un personnage avec un token qui contient, dans son équipement, les consommables à échanger/vendre.

    -

    2.7 D\xE9placements

    +

    2.7 Déplacements

    Retrouver un personnage

    -

    Pour centrer la vue d'un joueur sur un token particulier, on peut utiliser !cof-centrer-sur-token suivi du nom du token. G\xE9n\xE9ralement, c'est une bonne id\xE9e pour un joueur d'avoir une macro avec le nom de son token pour le retrouver facilement quand il arrive sur une nouvelle carte.

    +

    Pour centrer la vue d'un joueur sur un token particulier, on peut utiliser !cof-centrer-sur-token suivi du nom du token. Généralement, c'est une bonne idée pour un joueur d'avoir une macro avec le nom de son token pour le retrouver facilement quand il arrive sur une nouvelle carte.

    -

    Personnages immobilis\xE9s

    +

    Personnages immobilisés

    -

    Le script bloque automatiquement personnages immobilis\xE9s (paralys\xE9, \xE9tourdi, etc...). Pour permettre de d\xE9placer ces personnages vous pouvez simplement enlever le blockage (click droit sur le token, propri\xE9t\xE9s avanc\xE9es). Si vous souhaitez \xEAtre le seul \xE0 pouvoir le bouger, s\xE9lectionner le (ou les) token et cliquer sur la macro Bouger. Cela cr\xE9e un token non bloqu\xE9 associ\xE9 au personnage. Bien penser \xE0 supprimer ce token apr\xE8s utilisation.

    +

    Le script bloque automatiquement personnages immobilisés (paralysé, étourdi, etc...). Pour permettre de déplacer ces personnages vous pouvez simplement enlever le blockage (click droit sur le token, propriétés avancées). Si vous souhaitez être le seul à pouvoir le bouger, sélectionner le (ou les) token et cliquer sur la macro Bouger. Cela crée un token non bloqué associé au personnage. Bien penser à supprimer ce token après utilisation.

    Il est possible de mettre le jeu en pause (les joueurs ne peuvent plus bouger leurs tokens) en utilisant la macro ⏸. La macro change alors de nom et devient ⏵, que vous pouvez utiliser pour enlever la pause.

    Escaliers

    -

    Pour g\xE9rer les escaliers sur les cartes, vous pouvez utiliser la m\xE9thode suivante, inspir\xE9e du script Teleport : placez dans le layer "GM Info Overlay", au niveau des escaliers, des tokens qui prennent exactement la place des escaliers. Nommez ces escaliers avec un nom, suivi d'une lettre majuscule. Par exemple EscalierA.

    -

    Chaque escalier de la m\xEAme colonne doit avoir le m\xEAme nom, et diff\xE9rer seulement par la lettre finale. Ensuite, si un ensemble de tokens est sur un escalier, utilisez !cof-escalier pour t\xE9l\xE9porter les tokens \xE0 l'emplacement de l'escalier suivant dans l'ordre des lettres. Si vous utilisez l'argument haut, alors les tokens n'iront pas plus loin que le dernier \xE9tage, et avec l'argument bas, il iront dans l'ordre inverse.

    -

    Dans l'exemple pr\xE9c\xE9dent, il serait t\xE9l\xE9port\xE9 \xE0 l'emplacement du token nomm\xE9 EscalierB. Cela ne fonctionne que si les bouts de l'escalier sont sur la m\xEAme carte. \xC0 vous de choisir sir vous pr\xE9f\xE9rez r\xE9v\xE9ler cette fonctionalit\xE9 \xE0 vos joueurs, ou si vous le faites vous-m\xEAme.

    -

    La limite au nombre d'escaliers est de 12 \xE9tages, donc pas de lettre apr\xE8s L.

    -

    Il est possible d'avoir des escaliers qui m\xE8nent \xE0 d'autres cartes (ce qui fait alors changer la carte vue par le joueur). Il suffit que le nom de l'escalier commence par tmap_. Attention, \xE0 cause de limitations de Roll20, cela ne peut fonctionner que si l'image du token est dans une lirary personnelle d'un joueur : si elle vient du marketplace, il fait d'abord la copier dans sa library, puis utiliser l'image qui est dans la library pour le token.

    +

    Pour gérer les escaliers sur les cartes, vous pouvez utiliser la méthode suivante, inspirée du script Teleport : placez dans le layer "GM Info Overlay", au niveau des escaliers, des tokens qui prennent exactement la place des escaliers. Nommez ces escaliers avec un nom, suivi d'une lettre majuscule. Par exemple EscalierA.

    +

    Chaque escalier de la même colonne doit avoir le même nom, et différer seulement par la lettre finale. Ensuite, si un ensemble de tokens est sur un escalier, utilisez !cof-escalier pour téléporter les tokens à l'emplacement de l'escalier suivant dans l'ordre des lettres. Si vous utilisez l'argument haut, alors les tokens n'iront pas plus loin que le dernier étage, et avec l'argument bas, il iront dans l'ordre inverse.

    +

    Dans l'exemple précédent, il serait téléporté à l'emplacement du token nommé EscalierB. Cela ne fonctionne que si les bouts de l'escalier sont sur la même carte. À vous de choisir sir vous préférez révéler cette fonctionalité à vos joueurs, ou si vous le faites vous-même.

    +

    La limite au nombre d'escaliers est de 12 étages, donc pas de lettre après L.

    +

    Il est possible d'avoir des escaliers qui mènent à d'autres cartes (ce qui fait alors changer la carte vue par le joueur). Il suffit que le nom de l'escalier commence par tmap_. Attention, à cause de limitations de Roll20, cela ne peut fonctionner que si l'image du token est dans une lirary personnelle d'un joueur : si elle vient du marketplace, il fait d'abord la copier dans sa library, puis utiliser l'image qui est dans la library pour le token.

    Montures

    -

    Pour qu'un personnage puisse monter sur une monture, il faut que cette monture soit associ\xE9e \xE0 une fiche de personnage et qu'il poss\xE8de un pr\xE9dicat monture. La commande pour monter sur la monture est !cof-en-selle @{selected|token_id} @{target|token_id}, \xE0 lancer en s\xE9lectionnant le cavalier.

    -

    On peut ensuite bouger la monture, cela d\xE9place le cavalier. Le mieux est de lancer la commander alors que le token du cavalier est sur le token de la monture. Si on d\xE9place le cavalier, cela fait aussi bouger sa monture.

    +

    Pour qu'un personnage puisse monter sur une monture, il faut que cette monture soit associée à une fiche de personnage et qu'il possède un prédicat monture. La commande pour monter sur la monture est !cof-en-selle @{selected|token_id} @{target|token_id}, à lancer en sélectionnant le cavalier.

    +

    On peut ensuite bouger la monture, cela déplace le cavalier. Le mieux est de lancer la commander alors que le token du cavalier est sur le token de la monture. Si on déplace le cavalier, cela fait aussi bouger sa monture.

    Suivre un autre personnages

    - Le principe est le suivant : on s\xE9lectionne un token, dans les abilities qui s'affichent en haut de la map, on clique sur Suivre, puis on s\xE9lectionne le token \xE0 suivre. \xC0 partir de ce moment, le script d\xE9place le premier token \xE0 chaque fois qu'on d\xE9place le second (en tenant compte des \xE9tats qui emp\xEAchent le mouvement et des obstacles sur le layer de lumi\xE8re, si ils doivent emp\xEAcher le mouvement). On peut aussi suivre un token qui en suit un autre. Et pour arr\xEAter de suivre un token, il suffit de d\xE9placer manuellement le premier token. + Le principe est le suivant : on sélectionne un token, dans les abilities qui s'affichent en haut de la map, on clique sur Suivre, puis on sélectionne le token à suivre. À partir de ce moment, le script déplace le premier token à chaque fois qu'on déplace le second (en tenant compte des états qui empêchent le mouvement et des obstacles sur le layer de lumière, si ils doivent empêcher le mouvement). On peut aussi suivre un token qui en suit un autre. Et pour arrêter de suivre un token, il suffit de déplacer manuellement le premier token. - Ça permet donc d'avoir un familier qui suit un personnage, ou bien de faire automatiquement bouger un groupe de perosnnage dont l'ordre de marche est d\xE9termin\xE9. + Ça permet donc d'avoir un familier qui suit un personnage, ou bien de faire automatiquement bouger un groupe de perosnnage dont l'ordre de marche est déterminé.
    -

    D\xE9placer un personnage sur plusieurs cartes

    +

    Déplacer un personnage sur plusieurs cartes

    -

    Il est possible de synchroniser des tokens de m\xEAme nom (repr\xE9sentant le m\xEAme personnage) sur plusieurs cartes. Ainsi, d\xE9placer le token sur une carte d\xE9place aussi les token sur les autres cartes. Cela peut servir par exemple si tous les joueurs ne doivent pas voir la m\xEAme chose sur une carte : chaque joueur est alors sur la carte qui lui montre ce qu'il doit voir, et tous les tokens des joueurs sont synchronis\xE9s entre les cartes.

    -

    La commande pour activer la synchonisation d'un (ou plusieurs) tokens s\xE9l\xE9ctionn\xE9s est !cof-multi-cartes. Pour mettre fin \xE0 la synchronisation, on peut s\xE9lectionner ces tokens et faire !cof-multi-cartes false. Enfin, cette m\xEAme commande sans selectionner aucun token met fin \xE0 toutes les synchronisations.

    +

    Il est possible de synchroniser des tokens de même nom (représentant le même personnage) sur plusieurs cartes. Ainsi, déplacer le token sur une carte déplace aussi les token sur les autres cartes. Cela peut servir par exemple si tous les joueurs ne doivent pas voir la même chose sur une carte : chaque joueur est alors sur la carte qui lui montre ce qu'il doit voir, et tous les tokens des joueurs sont synchronisés entre les cartes.

    +

    La commande pour activer la synchonisation d'un (ou plusieurs) tokens séléctionnés est !cof-multi-cartes. Pour mettre fin à la synchronisation, on peut sélectionner ces tokens et faire !cof-multi-cartes false. Enfin, cette même commande sans selectionner aucun token met fin à toutes les synchronisations.

    -

    2.8 Lumi\xE8re

    +

    2.8 Lumière

    -

    Pour faire de la lumi\xE8re, on peut utiliser !cof-lumiere token_id portee. Cela va faire en sorte que le token fasse de la lumi\xE8re jusqu'\xE0 portee m\xE8tres. Il est possible d'avoir plusieurs sources de lumi\xE8re, et la commande est compatible avec la vision dans le noir. La commande admet un troisi\xE8me argument qui est la distance \xE0 laquelle la lumi\xE8re devient moins brillante, et un quatri\xE8me argument qui est le nom du type de lumi\xE8re (par d\xE9faut, lumiere), utilis\xE9 quand on \xE9teint les lumi\xE8res.

    -

    Pour \xE9teindre des lumi\xE8res, utiliser !cof-eteindre-lumiere en s\xE9lectionnant le ou les tokens d\xE9sir\xE9s. Il est possible de prendre un argument optionnel qui est le nom du groupe de lumi\xE8res que l'on souhaite \xE9teindre. Par exemple, on peut ainsi \xE9teindre toutes les torches et laisser les effets de lumi\xE8re magique actifs.

    -

    Pour les torches, le script propose d'automatiser la gestion en utilisant la commande !cof-torche token_id. Si le token tient une torche allum\xE9e, cela \xE9teint la torche (et propose au MJ d'indiquer combien de temps la torche est rest\xE9e allum\xE9e), et sinon, si le token poss\xE8de des torches, cela allume une torche. Le nombre de torche et leur \xE9tat est stock\xE9 dans un attribut torches, dont la valeur courante contient le nombre de torches dans l'inventaire, et la valeur max le temps restant pour la torche en cours d'utilisation (60 minutes pour une torche neuve). Si aucun attribut de ce nom n'existe, le script se contente d'allumer ou d'\xE9teindre une torche, sans g\xE9rer leur nombre.

    -

    Pour les armes qui font de la lumi\xE8re, on peut pr\xE9ciser un pr\xE9dicat eclaire dans le champ de pr\xE9dicats de l'arme. La valeur du pr\xE9dicat doit \xEAtre la distance \xE0 laquelle l'arme \xE9claire. On peut pr\xE9ciser dans un pr\xE9dicat eclaireFaible (toujours dans le champ de l'arme) le d\xE9but de la lumi\xE8re faible, si besoin. Ça peut aussi \xEAtre une fa\xE7on de g\xE9rer les torches.

    -

    Quand les personnages sont dans le brouillard, je mets la carte sans lumi\xE8re, et je s\xE9lectionne les tokens et lance la commande !cof-vision-nocturne 6 pour qu'ils voient \xE0 6 m.

    +

    Pour faire de la lumière, on peut utiliser !cof-lumiere token_id portee. Cela va faire en sorte que le token fasse de la lumière jusqu'à portee mètres. Il est possible d'avoir plusieurs sources de lumière, et la commande est compatible avec la vision dans le noir. La commande admet un troisième argument qui est la distance à laquelle la lumière devient moins brillante, et un quatrième argument qui est le nom du type de lumière (par défaut, lumiere), utilisé quand on éteint les lumières.

    +

    Pour éteindre des lumières, utiliser !cof-eteindre-lumiere en sélectionnant le ou les tokens désirés. Il est possible de prendre un argument optionnel qui est le nom du groupe de lumières que l'on souhaite éteindre. Par exemple, on peut ainsi éteindre toutes les torches et laisser les effets de lumière magique actifs.

    +

    Pour les torches, le script propose d'automatiser la gestion en utilisant la commande !cof-torche token_id. Si le token tient une torche allumée, cela éteint la torche (et propose au MJ d'indiquer combien de temps la torche est restée allumée), et sinon, si le token possède des torches, cela allume une torche. Le nombre de torche et leur état est stocké dans un attribut torches, dont la valeur courante contient le nombre de torches dans l'inventaire, et la valeur max le temps restant pour la torche en cours d'utilisation (60 minutes pour une torche neuve). Si aucun attribut de ce nom n'existe, le script se contente d'allumer ou d'éteindre une torche, sans gérer leur nombre.

    +

    Pour les armes qui font de la lumière, on peut préciser un prédicat eclaire dans le champ de prédicats de l'arme. La valeur du prédicat doit être la distance à laquelle l'arme éclaire. On peut préciser dans un prédicat eclaireFaible (toujours dans le champ de l'arme) le début de la lumière faible, si besoin. Ça peut aussi être une façon de gérer les torches.

    +

    Quand les personnages sont dans le brouillard, je mets la carte sans lumière, et je sélectionne les tokens et lance la commande !cof-vision-nocturne 6 pour qu'ils voient à 6 m.

    -

    2.9 Jet de caract\xE9ristiques

    +

    2.9 Jet de caractéristiques

    -

    !cof-jet ?{Faire un jet de |Charisme, CHA|Constitution, CON|Dext\xE9rit\xE9, DEX|Force, FOR|Intelligence, INT|Sagesse, SAG} : fait un simple jet pour la caract\xE9risique s\xE9lectionn\xE9e.

    -

    Il est aussi possible de donner en argument une difficult\xE9 au jet. Par exemple en faisant !cof-jet INT ?{difficult\xE9}.

    -

    Si on ne donne aucun argument (en dehors des options), la commande demande de pr\xE9ciser la caract\xE9ristique \xE0 tester. Pour chaque caract\xE9ristique, le script va proposer d'utiliser une des comp\xE9tences d\xE9finies sur la fiche (liste sous les capacit\xE9s). Si il existe un handout nomm\xE9 Comp\xE9tences, celui-ci sera aussi utilis\xE9 pour proposer pour chaque caract\xE9ristique un choix de comp\xE9tences \xE0 tester. Le handout doit contenir dans ses notes des lignes commen\xE7ant par une caract\xE9ristique (FOR, DEX, ...), suivi de :, puis des noms de comp\xE9tences, s\xE9par\xE9s par des blancs, des retours \xE0 la ligne, des virgules ou des /.

    +

    !cof-jet ?{Faire un jet de |Charisme, CHA|Constitution, CON|Dextérité, DEX|Force, FOR|Intelligence, INT|Sagesse, SAG} : fait un simple jet pour la caractérisique sélectionnée.

    +

    Il est aussi possible de donner en argument une difficulté au jet. Par exemple en faisant !cof-jet INT ?{difficulté}.

    +

    Si on ne donne aucun argument (en dehors des options), la commande demande de préciser la caractéristique à tester. Pour chaque caractéristique, le script va proposer d'utiliser une des compétences définies sur la fiche (liste sous les capacités). Si il existe un handout nommé Compétences, celui-ci sera aussi utilisé pour proposer pour chaque caractéristique un choix de compétences à tester. Le handout doit contenir dans ses notes des lignes commençant par une caractéristique (FOR, DEX, ...), suivi de :, puis des noms de compétences, séparés par des blancs, des retours à la ligne, des virgules ou des /.

    La fonction accepte les arguments suivants:

      -
    • --bonus pour sp\xE9cifier un bonus num\xE9rique au jet.
    • -
    • --attribut pour sp\xE9cifier un attribut dont la valeur doit \xEAtre ajout\xE9e au jet. Il est possible de sp\xE9cifier plusieurs attributs, comme par exemple --attribut perception --attribut vigilance pour un jet de vigilance.
    • -
    • --predicat pour sp\xE9cifier un pr\xE9dicat dont la valeur doit \xEAtre ajout\xE9e au jet. Il est possible de sp\xE9cifier plusieurs p\xE9dicats.
    • -
    • --nom pr\xE9cise le nom du jet \xE0 afficher. De plus, cela va aussi faire rechercher une comp\xE9tence de m\xEAme nom (sans tenir compte des majuscules) pour une fiche de PJ et un attribut ou un pr\xE9dicat pour une fiche de PNJ. Par exemple !cof-jet DEX --nom Discr\xE9tion va lancer un jet de DEX, qui sera affich\xE9 comme un jet de Discr\xE9tion, et qui va ajouter au jet le bonus d'une comp\xE9tence discr\xE9tion ou d'un \xE9ventuel pr\xE9dicat discr\xE9tion.
    • -
    • --secret : le jet n'est visible que par les personnes qui contr\xF4lent le personnage, plus le MJ. Si la personne qui a lanc\xE9 la commande est MJ, il sera le seul \xE0 voir le r\xE9sultat.
    • -
    • --competences : si la commande n'a pas d\xE9j\xE0 d'option --nom, invite l'utilisateur \xE0 choisir une comp\xE9tence parmis une liste correspondant \xE0 la caract\xE9ristique (incluant celles provenant du handout Comp\xE9tences tel que d\xE9fini plus haut).
    • -
    • --plageEchecCritique c : permet de consid\xE9rer tout jet de d\xE9 inf\xE9rieur ou \xE9gal \xE0 c comme un \xE9chec critique.
    • -
    • --succes message : affiche message en cas de succ\xE8s au jet. N'a pas d'effet si la difficult\xE9 du jet n'est pas d\xE9finie.
    • +
    • --bonus pour spécifier un bonus numérique au jet.
    • +
    • --attribut pour spécifier un attribut dont la valeur doit être ajoutée au jet. Il est possible de spécifier plusieurs attributs, comme par exemple --attribut perception --attribut vigilance pour un jet de vigilance.
    • +
    • --predicat pour spécifier un prédicat dont la valeur doit être ajoutée au jet. Il est possible de spécifier plusieurs pédicats.
    • +
    • --nom précise le nom du jet à afficher. De plus, cela va aussi faire rechercher une compétence de même nom (sans tenir compte des majuscules) pour une fiche de PJ et un attribut ou un prédicat pour une fiche de PNJ. Par exemple !cof-jet DEX --nom Discrétion va lancer un jet de DEX, qui sera affiché comme un jet de Discrétion, et qui va ajouter au jet le bonus d'une compétence discrétion ou d'un éventuel prédicat discrétion.
    • +
    • --secret : le jet n'est visible que par les personnes qui contrôlent le personnage, plus le MJ. Si la personne qui a lancé la commande est MJ, il sera le seul à voir le résultat.
    • +
    • --competences : si la commande n'a pas déjà d'option --nom, invite l'utilisateur à choisir une compétence parmis une liste correspondant à la caractéristique (incluant celles provenant du handout Compétences tel que défini plus haut).
    • +
    • --plageEchecCritique c : permet de considérer tout jet de dé inférieur ou égal à c comme un échec critique.
    • +
    • --succes message : affiche message en cas de succès au jet. N'a pas d'effet si la difficulté du jet n'est pas définie.
    -

    Si le personnage poss\xE8de un attribut num\xE9rique modificateurTests, ce modificateur sera pris en compte pour tous les tests.

    -

    Dans les options de jeu (affich\xE9s en utilisant !cof-options, dans le menu des options d'affichage, il est possible de choisir de ne faire afficher les r\xE9sultats qu'au MJ, qui peut alors en cliquant sur un bouton le montrer aux joueurs (ou pas).

    +

    Si le personnage possède un attribut numérique modificateurTests, ce modificateur sera pris en compte pour tous les tests.

    +

    Dans les options de jeu (affichés en utilisant !cof-options, dans le menu des options d'affichage, il est possible de choisir de ne faire afficher les résultats qu'au MJ, qui peut alors en cliquant sur un bouton le montrer aux joueurs (ou pas).

    -

    2.10 Anonymat et fausses identit\xE9s

    +

    2.10 Anonymat et fausses identités

    -

    La fiche de personnage propose deux noms par personnage : le nom principal (appel\xE9 simplement "nom") et un alias. Le nom principal est celui visible dans la liste des personnages de l'interface Roll20. C'est aussi celui qui est montr\xE9 quand on montre une fiche aux joueurs. La fiche propose de choisir le nom affich\xE9 lors des jets (champ "connu") : soit le nom principal, soit l'alias. Le script part toujours de l'hypoth\xE8se que c'est ce nom qui est connu des joueurs, et que le second est le "vrai" nom. Je laisse le choix au MJ de d\xE9cider lequel est quoi, car les deux m\xE9thodes ont leurs avantages et leurs inconv\xE9nients : si on choisit d'avoir l'alias en nom cach\xE9, on peut montrer la fiche aux joueurs, sans d\xE9voiler le vrai nom. En revanche, dans la liste des personnages, il peut \xEAtre plus difficile de s'y retrouver, car le MJ ne verra pas le vrai nom. Si on choisit d'avoir le vrai nom cach\xE9, tout est bien clair pour le MJ, mais il doit faire attention \xE0 ne pas montrer la fiche aux joueurs.

    +

    La fiche de personnage propose deux noms par personnage : le nom principal (appelé simplement "nom") et un alias. Le nom principal est celui visible dans la liste des personnages de l'interface Roll20. C'est aussi celui qui est montré quand on montre une fiche aux joueurs. La fiche propose de choisir le nom affiché lors des jets (champ "connu") : soit le nom principal, soit l'alias. Le script part toujours de l'hypothèse que c'est ce nom qui est connu des joueurs, et que le second est le "vrai" nom. Je laisse le choix au MJ de décider lequel est quoi, car les deux méthodes ont leurs avantages et leurs inconvénients : si on choisit d'avoir l'alias en nom caché, on peut montrer la fiche aux joueurs, sans dévoiler le vrai nom. En revanche, dans la liste des personnages, il peut être plus difficile de s'y retrouver, car le MJ ne verra pas le vrai nom. Si on choisit d'avoir le vrai nom caché, tout est bien clair pour le MJ, mais il doit faire attention à ne pas montrer la fiche aux joueurs.

    Concernant les tokens, le script suppose que vous mettez en "connu" le nom visible par les joueurs.

    -

    R\xE9v\xE9ler le vrai nom d'un personnage

    +

    Révéler le vrai nom d'un personnage

    -

    Pour r\xE9v\xE9ler le vrai nom d'un personnage au joueurs, vous pourrez utiliser !cof-reveler-nom. L'effet s'applique \xE0 tous les personnages s\xE9lectionn\xE9s (voir les m\xE9thodes de s\xE9lection). L'effet est le suivant :

    +

    Pour révéler le vrai nom d'un personnage au joueurs, vous pourrez utiliser !cof-reveler-nom. L'effet s'applique à tous les personnages sélectionnés (voir les méthodes de sélection). L'effet est le suivant :

      -
    • Si le personnage \xE9tait connu par son nom, et que l'alias \xE9tait non vide, alors on copie l'alias \xE0 la place du nom, et on efface l'alias.
    • -
    • Si le personnage \xE9tait connu par son alias, alors on le passe en connu par son nom et on efface l'alias.
    • -
    • Si on a fait un des deux changements ci-dessus, alors on change aussi les noms des tokens : si on a pass\xE9 un nom en argument \xE0 !cof-reveler-nom, alors on utilise ce nom. Sinon, on utilise le nouveau nom public. Tous les tokens li\xE9s prennent ce nom, et tous les tokens non li\xE9s gardent leur num\xE9ro et changent juste la partie avant le num\xE9ro en ce nom. On n'applique cette transformation qu'aux tokens dont les noms n'ont pas \xE9t\xE9 modifi\xE9s (par rapport au token par d\xE9faut d\xE9fini sur la fiche).
    • -
    • Et on change aussi le nom du token par d\xE9faut.
    • +
    • Si le personnage était connu par son nom, et que l'alias était non vide, alors on copie l'alias à la place du nom, et on efface l'alias.
    • +
    • Si le personnage était connu par son alias, alors on le passe en connu par son nom et on efface l'alias.
    • +
    • Si on a fait un des deux changements ci-dessus, alors on change aussi les noms des tokens : si on a passé un nom en argument à !cof-reveler-nom, alors on utilise ce nom. Sinon, on utilise le nouveau nom public. Tous les tokens liés prennent ce nom, et tous les tokens non liés gardent leur numéro et changent juste la partie avant le numéro en ce nom. On n'applique cette transformation qu'aux tokens dont les noms n'ont pas été modifiés (par rapport au token par défaut défini sur la fiche).
    • +
    • Et on change aussi le nom du token par défaut.

    2.11 Autres aspects du jeu

    Annuler une action : !cof-undo

    -

    Fait partie des fonctions que je met en macro dans la barre du MJ, \xE7a peut servir tr\xE8s souvent. Elle est d'ailleurs g\xE9n\xE9r\xE9e par la commande !cof-set-macros.

    +

    Fait partie des fonctions que je met en macro dans la barre du MJ, ça peut servir très souvent. Elle est d'ailleurs générée par la commande !cof-set-macros.

    Chance

    -

    Le script essaie de d\xE9tecter les cas o\xF9 un point de chance peut \xEAtre utile, et dans ce cas fournit un bouton (utilisable par les joueurs contr\xF4lant le perosnnage ou le GM), permettant de d\xE9penser un point de chance. Attention, pour l'instant, il n'est pas possible de faire juste un undo de la d\xE9pense de point de chnce. Le undo apr\xE8s la d\xE9pense de point de chance annule toute l'action. Il faut ensuite faire un undo par point de chance d\xE9pens\xE9.

    +

    Le script essaie de détecter les cas où un point de chance peut être utile, et dans ce cas fournit un bouton (utilisable par les joueurs contrôlant le perosnnage ou le GM), permettant de dépenser un point de chance. Attention, pour l'instant, il n'est pas possible de faire juste un undo de la dépense de point de chnce. Le undo après la dépense de point de chance annule toute l'action. Il faut ensuite faire un undo par point de chance dépensé.

    Surprise : !cof-surprise ?difficulte

    -

    Fait un test de surprise sur tous les tokens s\xE9lectionn\xE9. Si la difficult\xE9 n'est pas pr\xE9sente, ils sont automatiquement surpris. Les valeurs des comp\xE9tences vigilance et perception sont ajout\xE9s au test de sagesse.

    -

    Si vous souhaitez pr\xE9ciser que la surprise est le fait d'un personnage ou effet non vivant (pour ne pas faire b\xE9n\xE9ficier du bonus de la capacit\xE9 Radar mental), vous pouvez rajouter l'option --nonVivant.

    +

    Fait un test de surprise sur tous les tokens sélectionné. Si la difficulté n'est pas présente, ils sont automatiquement surpris. Les valeurs des compétences vigilance et perception sont ajoutés au test de sagesse.

    +

    Si vous souhaitez préciser que la surprise est le fait d'un personnage ou effet non vivant (pour ne pas faire bénéficier du bonus de la capacité Radar mental), vous pouvez rajouter l'option --nonVivant.

    Gestion de la bourse : !cof-bourse

    -

    La gestion de la bourse peut se faire sans ouvrir la fiche \xE0 l'aide de la commande !cof-bourse. Si un seul token est s\xE9lectionn\xE9 (quelle que soit la m\xE9thode de s\xE9lection), la commande affiche le montant de la bourse, avec la possibilit\xE9 de modifier directement les nombres de pi\xE8ces ou de d\xE9penser ou gagner un certain nombre de pi\xE8ces.

    -

    !cof-bourse depenser n permet de faire d\xE9penser de l'argent aux tokens s\xE9lectionn\xE9s. On peut pr\xE9ciser le type de pi\xE8ces (pc, pa, po ou pp) apr\xE8s le montant, par d\xE9faut le script utilise les pi\xE8ces d'argent. De m\xEAme, on peut utiliser !cof-bourse gagner n pour ajouter de l'argent.

    +

    La gestion de la bourse peut se faire sans ouvrir la fiche à l'aide de la commande !cof-bourse. Si un seul token est sélectionné (quelle que soit la méthode de sélection), la commande affiche le montant de la bourse, avec la possibilité de modifier directement les nombres de pièces ou de dépenser ou gagner un certain nombre de pièces.

    +

    !cof-bourse depenser n permet de faire dépenser de l'argent aux tokens sélectionnés. On peut préciser le type de pièces (pc, pa, po ou pp) après le montant, par défaut le script utilise les pièces d'argent. De même, on peut utiliser !cof-bourse gagner n pour ajouter de l'argent.

    Jouer un son

    -

    Les fonctions d'attaque peuvent jouer un son (options commen\xE7ant par --soundAttack). Une partie des actions admet aussi une option --son pour jouer un son. Finalement, il est aussi possible de simplement jouer un son en utilisant !cof-jouer-son son. Il est possible d'arr\xEAter tous les sons avec la commande !cof-jouer-son, sans argument.

    +

    Les fonctions d'attaque peuvent jouer un son (options commençant par --soundAttack). Une partie des actions admet aussi une option --son pour jouer un son. Finalement, il est aussi possible de simplement jouer un son en utilisant !cof-jouer-son son. Il est possible d'arrêter tous les sons avec la commande !cof-jouer-son, sans argument.

    -

    Le script est compatible avec Roll20AM, et si ce script est install\xE9, il fera appel \xE0 lui. Mais si il n'est pas install\xE9 (et seulement dans ce cas !), il va simplement utiliser les sons dans le jukebox.

    +

    Le script est compatible avec Roll20AM, et si ce script est installé, il fera appel à lui. Mais si il n'est pas installé (et seulement dans ce cas !), il va simplement utiliser les sons dans le jukebox.

    Changer la taille d'une page : !cof-agrandir-page

    - !cof-agrandir-carte coef permet de multiplier par coef les dimensions de tout ce qui se trouve sur la carte et le layer de la lumi\xE8re. Les tokens sont d\xE9plac\xE9s pour se retrouver \xE0 la m\xEAme position relative sur la carte. Je l'utilise pour les cartes que je trouve trop petites pour des groupes de 5-6 joueurs. + !cof-agrandir-carte coef permet de multiplier par coef les dimensions de tout ce qui se trouve sur la carte et le layer de la lumière. Les tokens sont déplacés pour se retrouver à la même position relative sur la carte. Je l'utilise pour les cartes que je trouve trop petites pour des groupes de 5-6 joueurs.

    Retarder l'affichage de la mort

    -

    Pour retarder l'affichage de la mort d'un personnage, ajoutez \xE0 ce personnage un pr\xE9dicat mortDemandeConfirmation. Ainsi, si le personnage meurt \xE0 la suite d'une attaque, les PVs finaux ne seront pas enlev\xE9s, et la croix rouge indiquant la mort ne sera pas dessin\xE9e. \xC0 la place, le MJ verra au bout de 2 secondes un bouton lui-demandant de confirmer la mort (par exemple le temps de d\xE9crire comment la mort advient).

    +

    Pour retarder l'affichage de la mort d'un personnage, ajoutez à ce personnage un prédicat mortDemandeConfirmation. Ainsi, si le personnage meurt à la suite d'une attaque, les PVs finaux ne seront pas enlevés, et la croix rouge indiquant la mort ne sera pas dessinée. À la place, le MJ verra au bout de 2 secondes un bouton lui-demandant de confirmer la mort (par exemple le temps de décrire comment la mort advient).

    -

    3. Capacit\xE9s par Classe

    +

    3. Capacités par Classe

    Arquebusier

    Voie de l'artilleur

      -
    1. M\xE9canismes : ajouter les bonus sur la fiche
    2. -
    3. Tir de semonce : utiliser le modificateur semonce aux attaques. On laisse le MJ v\xE9rifier si la derni\xE8re attaque du personnage \xE9tait bien un \xE9chec (devrait \xEAtre facile \xE0 voir dans le chat). Le plus pratique pour l'utilisation avec differentes armes, est de cr\xE9er une action Tir de barrage dans les actions du tour, avec comme code #Attaque -1 --semonce. -
    4. Tir de barrage : Utiliser l'option --tirDeBarrage. Ça multiplie les d\xE9g\xE2ts par 2, ignore la charge, et laisse un message demandant le undo si la cible d\xE9cide de ne pas bouger.
    5. -
    6. Couleuvrine : ajouter une attaque \xE0 distance, avec dans les modificateurs, poudre, limiteParCombat (ou en ligne de commande, avec l'option --limiteParCombat)
    7. -
    8. Feu nourri : faire les attaques comme pour le tirde barrage. Le script ne va pas v\xE9rifier que les cibles ne sont pas trop loin les unes des autres.
    9. +
    10. Mécanismes : ajouter les bonus sur la fiche
    11. +
    12. Tir de semonce : Ajouter une prédicat tirDeSemonce. Si vous affichez les attaques avec armes en main, cela va automatiquement proposer des tirs de semonces dans les tours suivants les attaques à distance ratées. Si vous préférez le faire à la main, utilisez le modificateur semonce aux attaques.
    13. +
    14. Tir de barrage : Utiliser l'option --tirDeBarrage. Ça multiplie les dégâts par 2, ignore la charge, et laisse un message demandant le undo si la cible décide de ne pas bouger.
    15. +
    16. Couleuvrine : ajouter une attaque à distance, avec dans les modificateurs, poudre, limiteParCombat (ou en ligne de commande, avec l'option --limiteParCombat)
    17. +
    18. Feu nourri : faire les attaques comme pour le tir de barrage. Le script ne va pas vérifier que les cibles ne sont pas trop loin les unes des autres.

    Voie des explosifs

      -
    1. Chimiste : ajoutez un pr\xE9dicat chimiste, ainsi que les comp\xE9tences de chimie et alchimie sur la fiche. Si vous utilisez la capacit\xE9 alternative Grenaille, vous pouvez soit g\xE9rer les charges de grenaille avec !cof-recharger L --grenaille, soit (si vous ne voulez pas faire g\xE9rer les charges) utiliser l'option --grenaille. Si vous utilisez la m\xEAme attaque pour plusieurs armes et que seule une partie est charg\xE9e de grenaille, il faudra aussi utiliser cette option pour utiliser l'arme charg\xE9e de grenaille.
    2. -
    3. D\xE9molition : pas de support particulier
    4. -
    5. Poudre puissante : ajuster les attaques
    6. -
    7. Pi\xE8ge explosif :
    8. -
    9. Boulet explosif : ajouter une attaque de type Arme de jet, d\xE9g\xE2ts 5d6 de type contondant (ou feu ?), port\xE9e 20, modificateurs auto, options --disque 5 --psave DEX [[12+@{selected|DEX}]]
    10. +
    11. Chimiste : ajoutez un prédicat chimiste, ainsi que les compétences de chimie et alchimie sur la fiche. Si vous utilisez la capacité alternative Grenaille, vous pouvez soit gérer les charges de grenaille avec !cof-recharger L --grenaille, soit (si vous ne voulez pas faire gérer les charges) utiliser l'option --grenaille. Si vous utilisez la même attaque pour plusieurs armes et que seule une partie est chargée de grenaille, il faudra aussi utiliser cette option pour utiliser l'arme chargée de grenaille.
    12. +
    13. Démolition : On peut noter le nombre de charges disponibles par jour dans un prédicat, par exemple nommé voieDesExplosifs. Pour poser une charge de démolition, faire !cof-poser-bombe @{selected|token_id} demolition voieDesExplosifs --limiteParJour voieDesExplosifs chargesExplosives. L'explosion a lieu automatiquement au bout de 4 tours de combat (3 pour poser, 1 pour s'éloigner). Si vous avez un son nommé Explosion dans votre liste de sons du jeu, il sera joué au moment de l'explosion.
    14. +
    15. Poudre puissante : ajouter un prédicat poudrePuissante.
    16. +
    17. Piège explosif : en supposant encore que le nombre maximum de charges par jour soit indiqué dans un prédicat voieDesExposifs, on peut poser une bombe à retardement avec !cof-poser-bombe @{selected|token_id} piege 5d6 retard ?{Nombre de round?|1|2|3|4|5|6|7|8|9|10} --limiteParJour voieDesExplosifs chargesExplosives, et pour la bombe à intrusion, !cof-poser-bombe @{selected|token_id} piege 5d6 intrusion --limiteParJour voieDesExplosifs chargesExplosives. Personnellement, j'aime bien utiliser des dégâts explosifs pour les charges (5d6!). Il est aussi possible de changer la distance d'intrusion en ajoutant le nombre de mètres après le mot clé intrusion. La détection des pièges est laissée à gérer par le MJ.
    18. +
    19. Boulet explosif : ajouter une attaque de type Arme de jet, dégâts 5d6 de type contondant (ou feu ?), portée 20, modificateurs auto, options --disque 5 --psave DEX [[12+@{selected|DEX}]] --limiteParJour 5 chargesExplosives

    Voie du champ de bataille

      -
    1. Action concert\xE9e : utiliser !cof-echange-init @{selected|token_id} @{target|token_id} n o\xF9 n peut valoir 0, 1 ou 2 selon le rang dans la voie.
    2. -
    3. \xC0 couvert : !cof-a-couvert @{selected|token_id} @{target|token_id} le target est l'alli\xE9 qui se d\xE9place avec l'arquebusier. Se s\xE9lectionner soi-m\xEAme si pas d'alli\xE9.
    4. -
    5. Combattant aguerri : se reporter \xE0 la capacit\xE9 choisie
    6. -
    7. Combat de masse : pas de support particulier, effectuer les actions suppl\xE9mentaires en fonction des situations.
    8. -
    9. Constitution h\xE9ro\xEFque : reporter le bonus sur la fiche
    10. +
    11. Action concertée : utiliser !cof-echange-init @{selected|token_id} @{target|token_id} nn peut valoir 0, 1 ou 2 selon le rang dans la voie.
    12. +
    13. À couvert : !cof-a-couvert @{selected|token_id} @{target|token_id} le target est l'allié qui se déplace avec l'arquebusier. Se sélectionner soi-même si pas d'allié.
    14. +
    15. Combattant aguerri : se reporter à la capacité choisie
    16. +
    17. Combat de masse : pas de support particulier, effectuer les actions supplémentaires en fonction des situations.
    18. +
    19. Constitution héroïque : reporter le bonus sur la fiche

    Voie du Pistolero

    1. - Plus vite que son ombre : ajouter un pr\xE9dicat plusViteQueSonOmbre. On peut associer un nombre \xE0 ce pr\xE9dicat pour modifier le bonus \xE0 l'initiative, ou bien lui donner la valeur arbalete pour activer le bonus sur les arbal\xE8tes au lieu des armes \xE0 poudre. + 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.
    2. Cadence de tir : pas de support
    3. -
    4. Tir double : utiliser l'option --tirDouble si deux tirs sur une m\xEAme cible. Si les deux armes sont diff\xE9rentes, rajouter le label de la deuxi\xE8me arme apr\xE8s l'option (si le label est l2, cela donne --tirDouble l2).
    5. -
    6. As de la g\xE2chette : utiliser l'option --asDeLaGachette pour les attaques avec des armes \xE0 poudre ou des arbal\xE8tes.
    7. -
    8. Dext\xE9rit\xE9 h\xE9ro\xEFque : reporter le bonus sur la fiche
    9. +
    10. 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).
    11. +
    12. As de la gâchette : utiliser l'option --asDeLaGachette pour les attaques avec des armes à poudre ou des arbalètes.
    13. +
    14. Dextérité héroïque : reporter le bonus sur la fiche
    -

    Voie de la pr\xE9cision

    +

    Voie de la précision

      -
    1. Joli coup ! : ajouter un pr\xE9dicat joliCoup sur la fiche.
    2. -
    3. Tir pr\xE9cis : ajouter un pr\xE9dicat tirPrecis, valeur 1 ou 2 (le bonus apport\xE9 par la capacit\xE9)
    4. -
    5. D\xE9faut dans la cuirasse : utiliser !cof-defaut-dans-la-cuirasse @{selected|token_id} @{target|token_id}
    6. -
    7. Tir parabolique : ajouter un pr\xE9dicat tirParabolique. Surtout ne pas changer la port\xE9e des armes, pour que le script g\xE8re correctement les distances entre port\xE9ex2 et port\xE9ex3.
    8. -
    9. Tir mortel : Ajouter ?{Tir mortel ?|Oui, --avecd12crit --plus 2d6|Non,} aux attaques \xE0 distance du personnage
    10. +
    11. Joli coup ! : ajouter un prédicat joliCoup sur la fiche.
    12. +
    13. Tir précis : ajouter un prédicat tirPrecis, valeur 1 ou 2 (le bonus apporté par la capacité)
    14. +
    15. Défaut dans la cuirasse : utiliser !cof-defaut-dans-la-cuirasse @{selected|token_id} @{target|token_id}
    16. +
    17. Tir parabolique : ajouter un prédicat tirParabolique. Surtout ne pas changer la portée des armes, pour que le script gère correctement les distances entre portéex2 et portéex3.
    18. +
    19. Tir mortel : Ajouter ?{Tir mortel ?|Oui, --avecd12crit --plus 2d6|Non,} aux attaques à distance du personnage

    Barbare

    Voie de la brute

      -
    1. Argument de taille : ajouter le bonus de PV sur la fiche. Ajouter un pr\xE9dicat argumentDeTaille. Le script devrait automatiquement tenir compte de cette capacit\xE9 pour les tests de n\xE9gociation, persuasion et intimidation. Pour s'assurer que la bonne comp\xE9tence est utilis\xE9e, vous pouvez ajouter ces noms au handout de comp\xE9tence (voir la partie sur les jet de caract\xE9ristiques, le handout Comp\xE9tences) ou sur les fiches de personnages.
    2. -
    3. Tour de force : ajouter un pr\xE9dicat tourDeForce. Le script ajoutera syst\xE9matique un bouton lors de tous les tests de FOR du personnage. Au MJ de d\xE9cider s'il peut \xEAtre utilis\xE9 ou non.
    4. +
    5. Argument de taille : ajouter le bonus de PV sur la fiche. Ajouter un prédicat argumentDeTaille. Le script devrait automatiquement tenir compte de cette capacité pour les tests de négociation, persuasion et intimidation. Pour s'assurer que la bonne compétence est utilisée, vous pouvez ajouter ces noms au handout de compétence (voir la partie sur les jet de caractéristiques, le handout Compétences) ou sur les fiches de personnages.
    6. +
    7. Tour de force : ajouter un prédicat tourDeForce. Le script ajoutera systématique un bouton lors de tous les tests de FOR du personnage. Au MJ de décider s'il peut être utilisé ou non.
    8. Attaque brutale : faire l'attaque avec les options --bonusAttaque -2 --plus 1d6
    9. -
    10. Briseur d'os : ajouter un pr\xE9dicat briseurDOs. Cela va automatiquement affecter les chances de coups critique au contact.
    11. -
    12. Force h\xE9ro\xEFque : reporter sur la fiche.
    13. +
    14. Briseur d'os : ajouter un prédicat briseurDOs. Cela va automatiquement affecter les chances de coups critique au contact.
    15. +
    16. Force héroïque : reporter sur la fiche.

    Voie du pagne

      -
    1. Vigueur : ajouter les comp\xE9tences avec leurs bonus sur la fiche
    2. -
    3. Peau de pierre : ajouter un pr\xE9dicat peauDePierre. La nouvelle DEF sera calcul\xE9e automatiquement.
    4. +
    5. Vigueur : ajouter les compétences avec leurs bonus sur la fiche
    6. +
    7. Peau de pierre : ajouter un prédicat peauDePierre. La nouvelle DEF sera calculée automatiquement.
    8. Tatouages : ajouter le bonus choisi sur la fiche
    9. Peau d'acier : ajouter dans la partie RD de la fiche, 3/1
    10. -
    11. Constitution h\xE9ro\xEFque : reporter les bonus sur la fiche
    12. +
    13. Constitution héroïque : reporter les bonus sur la fiche

    Voie du pourfendeur

      -
    1. R\xE9flexes f\xE9lins : ajouter un pr\xE9dicat reflexesFelins, avec comme valeur le bonus aux saves et \xE0 l'initiative.
    2. -
    3. Charge : faire une attaque avec les options --bonusAttaque 2 --plus 1d6. Pour g\xE9rer plusieurs armes, vous pouvez utiliser la commande #Attaque -1.
    4. -
    5. Encha\xEEnement : ajouter un pr\xE9dicat enchainement.
    6. -
    7. D\xE9cha\xEEnement d'acier : !cof-attack-line @{selected|token_id} --distanceMax 10. L'attaque va \xEAtre faite avec l'arme en main, mais on peut sp\xE9cifier un label d'attaque (avant les options) et toutes les options support\xE9es par !cof-attack.
    8. +
    9. Réflexes félins : ajouter un prédicat reflexesFelins, avec comme valeur le bonus aux saves et à l'initiative.
    10. +
    11. Charge : faire une attaque avec les options --deplaceDe 5 20 --bonusAttaque 2 --plus 1d6. Pour gérer plusieurs armes, vous pouvez utiliser la commande #Attaque -1.
    12. +
    13. Enchaînement : ajouter un prédicat enchainement.
    14. +
    15. Déchaînement d'acier : !cof-attack-line @{selected|token_id} --distanceMax 10. L'attaque va être faite avec l'arme en main, mais on peut spécifier un label d'attaque (avant les options) et toutes les options supportées par !cof-attack.
    16. Attaque tourbillon : Faite une action avec le code !cof-explosion -1 --auto --disque 5 --saufAllies --limiteParCombat 1 tourbillon.

    Voie du primitif

      -
    1. Proche de la nature : ajouter le rang \xE0 une comp\xE9tence perception
    2. -
    3. Armure de vent : Ajouter un pr\xE9dicat armureDeVent avec comme valeur le rang dans la voie du primitif. Cela augmente la DEF, mais seulement lorsque le barbare ne porte pas d'armure (ne se voit pas sur le total de DEF de la fiche)
    4. -
    5. Vigilance : ajouter 5 \xE0 une comp\xE9tence vigilance et ajouter un pr\xE9dicat immuniteAuxSournoises
    6. -
    7. R\xE9sistance \xE0 la magie : ajouter un pr\xE9dicat resistanceALaMagieBarbare.
    8. -
    9. Vitalit\xE9 d\xE9bordante : faire une ability de type token action, avec le code !cof-soin ?{Nombre d'heures \xE9coul\xE9es}d6 --message gu\xE9rit \xE0 une vitesse surnaturelle
    10. +
    11. Proche de la nature : ajouter le rang à une compétence perception
    12. +
    13. Armure de vent : Ajouter un prédicat armureDeVent avec comme valeur le rang dans la voie du primitif. Cela augmente la DEF, mais seulement lorsque le barbare ne porte pas d'armure (ne se voit pas sur le total de DEF de la fiche)
    14. +
    15. Vigilance : ajouter 5 à une compétence vigilance et ajouter un prédicat immuniteAuxSournoises
    16. +
    17. Résistance à la magie : ajouter un prédicat resistanceALaMagieBarbare.
    18. +
    19. Vitalité débordante : faire une ability de type token action, avec le code !cof-soin ?{Nombre d'heures écoulées}d6 --message guérit à une vitesse surnaturelle

    Voie de la rage

    1. Cri de guerre : !cof-effet-combat criDeGuerre
    2. -
    3. D\xE9fier la mort : ajouter un pr\xE9dicat defierLaMort.
    4. -
    5. Rage du berserk : utiliser !cof-rage-du-berserk, \xE0 la fois pour entrer en rage et pour tenter d'en sortir avant la fin du combat.
    6. -
    7. M\xEAme pas mal : ajouter un pr\xE9dicat memePasMal. Le joueur doit lui-m\xEAme activer la rage ou le furie si il souhaite en profiter.
    8. -
    9. Furie du berserk : utiliser !cof-rage-du-berserk --furie pour entrer en rage et pour tenter d'en sortir avant la fin du combat. Pour sortir de la rage, l'option --furie peut \xEAtre omise.
    10. +
    11. Défier la mort : ajouter un prédicat defierLaMort.
    12. +
    13. Rage du berserk : utiliser !cof-rage-du-berserk, à la fois pour entrer en rage et pour tenter d'en sortir avant la fin du combat.
    14. +
    15. Même pas mal : ajouter un prédicat memePasMal. Le joueur doit lui-même activer la rage ou le furie si il souhaite en profiter.
    16. +
    17. Furie du berserk : utiliser !cof-rage-du-berserk --furie pour entrer en rage et pour tenter d'en sortir avant la fin du combat. Pour sortir de la rage, l'option --furie peut être omise.
    - Note: en option, il est possible de diviser par 2 la p\xE9nalit\xE9 de d\xE9fense inflig\xE9e par la Rage ou la Furie en ajoutant un pr\xE9dicat rageDuBerserkAmelioree au personnage (par exemple pour la ceinture d'Anathazer\xEFn p. 341) + Note: en option, il est possible de diviser par 2 la pénalité de défense infligée par la Rage ou la Furie en ajoutant un prédicat rageDuBerserkAmelioree au personnage (par exemple pour la ceinture d'Anathazerïn p. 341)

    Barde

    Voie de l'escrime

      -
    1. Pr\xE9cision : simplement utiliser le bon score sur la fiche.
    2. -
    3. Intelligence du combat : ajouter un pr\xE9dicat intelligenceDuCombat.
    4. -
    5. Feinte : faire une attaque avec l'option --feinte pour profiter des effets de feinte au tour suivant. Par d\xE9faut, le bonus \xE0 l'attaque suivante est de +5 (r\xE8gles de base), mais vous pouvez sp\xE9cifier un bonus diff\xE9rent (par exemple 10 pour les r\xE8gles de la bo\xEEte d'initiation) avec un pr\xE9dicat bonusFeinte (la valeur du pr\xE9dicat remplace le bonus de +5 par d\xE9faut). Il est aussi possible de changer le nombre de d\xE9s de d\xE9g\xE2t bonus en utilisant un pr\xE9dicatnbDesFeinte.
    6. -
    7. Attaque flamboyante : faire une attaque avec le modificateur attaqueFlamboyante. Le plus pratique pour l'utilisation avec diff\xE9rentes armes, est d'ajouter \xE0 la liste des actions du tour une action de titre Attaque flamboyante et de code #Attaque -1 --attaqueFlamboyante. Attention, afin de garder un int\xE9r\xEAt \xE0 la feinte quand on dispose de cette attaque, j'ai choisi de rajouter encore le mod. de charisme aux DM en cas d'attaque flamboyante suivant une feinte r\xE9ussie. Si cela ne vous convient pas, vous pouvez \xE0 la place de cette option ajouter --bonusAttaque [[@{selected|CHA}]] --plus [[@{selected|CHA}]].
    8. -
    9. Botte mortelle : ajoutez un pr\xE9dicat botteMortelle.
    10. +
    11. Précision : simplement utiliser le bon score sur la fiche.
    12. +
    13. Intelligence du combat : ajouter un prédicat intelligenceDuCombat.
    14. +
    15. Feinte : faire une attaque avec l'option --feinte pour profiter des effets de feinte au tour suivant. Par défaut, le bonus à l'attaque suivante est de +5 (règles de base), mais vous pouvez spécifier un bonus différent (par exemple 10 pour les règles de la boîte d'initiation) avec un prédicat bonusFeinte (la valeur du prédicat remplace le bonus de +5 par défaut). Il est aussi possible de changer le nombre de dés de dégât bonus en utilisant un prédicatnbDesFeinte.
    16. +
    17. Attaque flamboyante : faire une attaque avec le modificateur attaqueFlamboyante. Le plus pratique pour l'utilisation avec différentes armes, est d'ajouter à la liste des actions du tour une action de titre Attaque flamboyante et de code #Attaque -1 --attaqueFlamboyante. Attention, afin de garder un intérêt à la feinte quand on dispose de cette attaque, j'ai choisi de rajouter encore le mod. de charisme aux DM en cas d'attaque flamboyante suivant une feinte réussie. Si cela ne vous convient pas, vous pouvez à la place de cette option ajouter --bonusAttaque [[@{selected|CHA}]] --plus [[@{selected|CHA}]].
    18. +
    19. Botte mortelle : ajoutez un prédicat botteMortelle.

    Voie du musicien

      -
    1. Chant des h\xE9ros : !cof-effet-temp chantDesHeros [[5+@{selected|CHA}]] --allies. Il faut avoir d\xE9fini une \xE9quipe avec le barde.
    2. +
    3. Chant des héros : !cof-effet-temp chantDesHeros [[5+@{selected|CHA}]] --allies. Il faut avoir défini une équipe avec le barde.
    4. Attaque sonore :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, DM 1d6+CHA, de port\xE9e 10, type Sortil\xE8ge, d\xE9g\xE2ts soniques, options --mana 0 --cone --fx breath-smoke.
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, DM 1d6+CHA, de portée 10, type Sortilège, dégâts soniques, options --mana 0 --cone --fx breath-smoke.
      • Objet de sort : #Attaque Attaque sonore --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|CHA}]] --portee 10 --sortilege --sonique --cone --fx breath-smoke
    5. -
    6. Zone de silence : !cof-effet-temp zoneDeSilence [[1d6+@{selected|CHA}]] --lanceur @{selected|token_id} --portee 35 --disque @{target|token_id} 3 --mana 1. Le script ne g\xE8re pas le moment o\xF9 les cibles sortent de la zone. Si cela arrive, le MJ doit enlever \xE0 la main l'attribut zoneDeSilence cr\xE9\xE9 par le script pour le personnage concern\xE9.
    7. -
    8. Danse irr\xE9sisitible : +
    9. Zone de silence : !cof-effet-temp zoneDeSilence [[1d6+@{selected|CHA}]] --lanceur @{selected|token_id} --portee 35 --disque @{target|token_id} 3 --mana 1. Le script ne gère pas le moment où les cibles sortent de la zone. Si cela arrive, le MJ doit enlever à la main l'attribut zoneDeSilence créé par le script pour le personnage concerné.
    10. +
    11. Danse irrésisitible :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateur pasDeDmg, options --mana 2 --effet danseIrresistible [[1d4+@{selected|CHA]].
      • -
      • Objet de sort : #Attaque Danse irr\xE9sisitible --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet danseIrresistible [[1d4+@{selected|CHA]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateur pasDeDmg, options --mana 2 --effet danseIrresistible [[1d4+@{selected|CHA]].
      • +
      • Objet de sort : #Attaque Danse irrésisitible --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet danseIrresistible [[1d4+@{selected|CHA]]
    12. -
    13. Musique fascinante : !cof-lancer-sort joue une musique fascinante qui contr\xF4le toutes les cr\xE9atures de son choix de moins de [[5+@{selected|CHA}]] PV --mana 3
    14. +
    15. Musique fascinante : !cof-lancer-sort joue une musique fascinante qui contrôle toutes les créatures de son choix de moins de [[5+@{selected|CHA}]] PV --mana 3

    Voie du saltimbanque

      -
    1. Acrobate : ajouter les comp\xE9tences sur la fiche
    2. -
    3. Gr\xE2ce f\xE9line : ajouter un pr\xE9dicat graceFeline. Cela va affecter l'initiative et la DEF, mais sans se voir sur la fiche.
    4. +
    5. Acrobate : ajouter les compétences sur la fiche
    6. +
    7. Grâce féline : ajouter un prédicat graceFeline. Cela va affecter l'initiative et la DEF, mais sans se voir sur la fiche.
    8. Lanceur de couteau : faire normalement l'attaque.
    9. -
    10. Esquive acrobatique : ajouter un pr\xE9dicat esquiveAcrobatique.
    11. -
    12. Libert\xE9 d'action : ajouter un pr\xE9dicat liberteDAction.
    13. +
    14. Esquive acrobatique : ajouter un prédicat esquiveAcrobatique.
    15. +
    16. Liberté d'action : ajouter un prédicat liberteDAction.
    -

    Voie de la s\xE9duction

    +

    Voie de la séduction

      -
    1. Charmant : ajouter les comp\xE9tences sur la fiche
    2. -
    3. Dentelles et rapi\xE8re : Ajouter un pr\xE9dicat dentellesEtRapiere avec comme valeur le rang dans la voie de la s\xE9duction. Cela augmente la DEF, mais seulement lorsque le barde ne porte pas d'armure et seulement contre les attaques au contact. (ne se voit pas sur le total de DEF de la fiche)
    4. -
    5. Arme secr\xE8te : !cof-arme-secrete @{selected|token_id} @{target|token_id}
    6. +
    7. Charmant : ajouter les compétences sur la fiche
    8. +
    9. Dentelles et rapière : Ajouter un prédicat dentellesEtRapiere avec comme valeur le rang dans la voie de la séduction. Cela augmente la DEF, mais seulement lorsque le barde ne porte pas d'armure et seulement contre les attaques au contact. (ne se voit pas sur le total de DEF de la fiche)
    10. +
    11. Arme secrète : !cof-arme-secrete @{selected|token_id} @{target|token_id}
    12. Suggestion :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg, options --mana 2 --difficultePVmax --attaqueMentale --if touche --message la cible doit faire l'action sugg\xE9r\xE9e --endif.
      • -
      • Objet de sort : #Attaque Suggestion --toucher [[@{selected|ATKMAG}]] --portee 20 --pasDeDmg --difficultePVmax --sortilege --attaqueMentale --if touche --message la cible doit faire l'action sugg\xE9r\xE9e --endif
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg, options --mana 2 --difficultePVmax --attaqueMentale --if touche --message la cible doit faire l'action suggérée --endif.
      • +
      • Objet de sort : #Attaque Suggestion --toucher [[@{selected|ATKMAG}]] --portee 20 --pasDeDmg --difficultePVmax --sortilege --attaqueMentale --if touche --message la cible doit faire l'action suggérée --endif
    13. -
    14. Charisme h\xE9ro\xEFque : Reporter le bonus sur la fiche.
    15. +
    16. Charisme héroïque : Reporter le bonus sur la fiche.

    Voie du vagabond

      -
    1. Rumeurs et l\xE9gendes : ajouter les comp\xE9tences sur la fiche
    2. -
    3. Compr\xE9hension des langues : !cof-lancer-sort lance un sort de compr\xE9hension des langues. --messageMJ la compr\xE9hension des langues va durer [[1d6+@{selected|CHA}]] minutes --mana 0
    4. -
    5. D\xE9brouillard : pas de support particulier. Ajouter le bonus aux comp\xE9tences que vous souhaitez noter.
    6. -
    7. D\xE9guisement :!cof-lancer-sort lance un sort de d\xE9guisement --mana 2
    8. -
    9. Touche \xE0 tout : se reporter aux capacit\xE9s choisies
    10. +
    11. Rumeurs et légendes : ajouter les compétences sur la fiche
    12. +
    13. Compréhension des langues : !cof-lancer-sort lance un sort de compréhension des langues. --messageMJ la compréhension des langues va durer [[1d6+@{selected|CHA}]] minutes --mana 0
    14. +
    15. Débrouillard : pas de support particulier. Ajouter le bonus aux compétences que vous souhaitez noter.
    16. +
    17. Déguisement :!cof-lancer-sort lance un sort de déguisement --mana 2
    18. +
    19. Touche à tout : se reporter aux capacités choisies

    Chevalier

    Voie du cavalier

      -
    1. Fid\xE8le monture : Faire un personnage pour la monture, avec un pr\xE9dicat monture. Pour monter sur la monture, on peut utiliser une ability de type token action, avec !cof-en-selle @{selected|token_id} nom_de_la_monture. Pour en descendre, il suffit de cliquer \xE0 nouveau sur le bouton de l'ability. Si vous souhaitez \xE9viter que la monture apparaisse dans le turn tracker, vous pouvez ajouter un pr\xE9dicat aucuneActionCombat \xE0 la monture.
    2. -
    3. Cavalier \xE9m\xE9rite : Ajouter au chevalier un pr\xE9dicat cavalierEmerite:2. Pour la d\xE9fense de la monture, ajouter \xE0 cellle-ci un pr\xE9dicat defDeriveeDe de valeur le nom du chevalier (exactement tel qu'il appara\xEEt sur la fiche, il est possible que cela demande d'utiliser la syntaxe avec ::).
    4. -
    5. Monture magique : pour les soins automatiques de la nuit, ajouter un pr\xE9dicat montureMagique.
    6. +
    7. Fidèle monture : Faire un personnage pour la monture, avec un prédicat monture. Pour monter sur la monture, on peut utiliser une ability de type token action, avec !cof-en-selle @{selected|token_id} nom_de_la_monture. Pour en descendre, il suffit de cliquer à nouveau sur le bouton de l'ability. Si vous souhaitez éviter que la monture apparaisse dans le turn tracker, vous pouvez ajouter un prédicat aucuneActionCombat à la monture.
    8. +
    9. Cavalier émérite : Ajouter au chevalier un prédicat cavalierEmerite:2. Pour la défense de la monture, ajouter à cellle-ci un prédicat defDeriveeDe de valeur le nom du chevalier (exactement tel qu'il apparaît sur la fiche, il est possible que cela demande d'utiliser la syntaxe avec ::).
    10. +
    11. Monture magique : pour les soins automatiques de la nuit, ajouter un prédicat montureMagique.
    12. - Charge : pas de support pour le d\xE9placement, mais + Charge : pas de support pour le déplacement, mais
      • Pour l'attaque : utiliser --m2d20 --plus 1d6
      • -
      • Pour les cr\xE9atures sur la trajectoire, utiliser !cof-jet FOR 18, et en cas de succ\xE8s, infliger les DM.
      • +
      • Pour les créatures sur la trajectoire, utiliser !cof-jet FOR 18, et en cas de succès, infliger les DM.
    13. -
    14. Monture fantastique : Faire un personnage pour la monture, avec un pr\xE9dicat monture.
    15. +
    16. Monture fantastique : Faire un personnage pour la monture, avec un prédicat monture.

    Voie de la guerre

      @@ -1158,38 +1162,38 @@

      Voie de la guerre

    1. Encaisser un coup :
      • utiliser !cof-effet-temp encaisserUnCoup 1 pour se mettre en position
      • -
      • Le script proposera un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le chevalier est en position.
      • +
      • Le script proposera un bouton à activer en cas d'attaque réussie alors que le chevalier est en position.
    2. -
    3. Coup de bouclier : faire une attaque de bouclier, de type Arme gauche, avec le modificateur avecd12crit. Pour que cette attaque soit propos\xE9e dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un pr\xE9dicat attaqueAuBouclier de valeur le label de l'attaque.
    4. +
    5. Coup de bouclier : faire une attaque de bouclier, de type Arme gauche, avec le modificateur avecd12crit. Pour que cette attaque soit proposée dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un prédicat attaqueAuBouclier de valeur le label de l'attaque.
    6. Frappe lourde : faire l'attaque avec les options --avecd12crit --plus 2d6 --ignoreMoitieRD --seulementContact
    7. -
    8. Force h\xE9ro\xEFque : reporter les bonus sur la fiche
    9. +
    10. Force héroïque : reporter les bonus sur la fiche
    -

    Voie du h\xE9ro

    +

    Voie du héro

      -
    1. Ignorer la douleur : Ajouter un pr\xE9dicat ignorerLaDouleur. Normalement, le script affiche un bouton quand cela est utilisable, mais on peut aussi le d\xE9clencher avec !cof-ignorer-la-douleur juste apr\xE8s le coup.
    2. -
    3. Piqures d'insectes : ajouter un pr\xE9dicat piquresDInsectes, avec comme valeur le rang dans la voie.
    4. -
    5. Laissez-le-moi ! : Ajouter un pr\xE9dicat laissezLeMoi. Le bonus sera accord\xE9 contre tous les tokens ayant le statut de chef (donn\xE9s avec !cof-set-state chef true, ou alors simplement en activant le marker sur le token).
    6. -
    7. Seul contre tous : Utiliser !cof-effet-temp seulContreTous 1 pour se mettre en position. Les actions affich\xE9es en cas de riposte seront normalement une attaque avec l'arme en main si il y en a, plus les attaques naturelles coch\xE9es sur la liste d'attaque. Si \xE7a ne convient pas, vous pouvez \xE9crire une liste d'actions nomm\xE9eRipostes (voir les actions du tour).
    8. -
    9. Charisme h\xE9ro\xEFque : reporter sur la fiche.
    10. +
    11. Ignorer la douleur : Ajouter un prédicat ignorerLaDouleur. Normalement, le script affiche un bouton quand cela est utilisable, mais on peut aussi le déclencher avec !cof-ignorer-la-douleur juste après le coup.
    12. +
    13. Piqures d'insectes : ajouter un prédicat piquresDInsectes, avec comme valeur le rang dans la voie.
    14. +
    15. Laissez-le-moi ! : Ajouter un prédicat laissezLeMoi. Le bonus sera accordé contre tous les tokens ayant le statut de chef (donnés avec !cof-set-state chef true, ou alors simplement en activant le marker sur le token).
    16. +
    17. Seul contre tous : Utiliser !cof-effet-temp seulContreTous 1 pour se mettre en position. Les actions affichées en cas de riposte seront normalement une attaque avec l'arme en main si il y en a, plus les attaques naturelles cochées sur la liste d'attaque. Si ça ne convient pas, vous pouvez écrire une liste d'actions nomméeRipostes (voir les actions du tour).
    18. +
    19. Charisme héroïque : reporter sur la fiche.

    Voie du meneur d'hommes

      -
    1. Sans peur : Ajouter un pr\xE9dicat sansPeur, utilis\xE9 quand on essaiera de faire peur \xE0 un alli\xE9.
    2. -
    3. Intercepter : Ajouter un pr\xE9dicat intercepter, et un autre voieDuMeneurDHomme de valeur le rang dans la voie, s'il est diff\xE9rent de 2.
    4. -
    5. Exemplaire : !cof-exemplaire, juste apr\xE8s l'attaque rat\xE9e.
    6. +
    7. Sans peur : Ajouter un prédicat sansPeur, utilisé quand on essaiera de faire peur à un allié.
    8. +
    9. Intercepter : Ajouter un prédicat intercepter, et un autre voieDuMeneurDHomme de valeur le rang dans la voie, s'il est différent de 2.
    10. +
    11. Exemplaire : !cof-exemplaire, juste après l'attaque ratée.
    12. Ordre de bataille : pas de support
    13. Charge fantastique : !cof-charge-fantastique @{selected|token_id} --alliesEnVue --self --limiteParCombat 1

    Voie de la noblesse

      -
    1. \xC9duqu\xE9 : pas de support particulier, juste reporter les bonus sur la fiche.
    2. -
    3. Autorit\xE9 naturelle : simplement reporter sur la fiche les bonus d'init et de DEF, et ajouter la capacit\xE9 intimider.
    4. -
    5. \xC9cuyer : +
    6. Éduqué : pas de support particulier, juste reporter les bonus sur la fiche.
    7. +
    8. Autorité naturelle : simplement reporter sur la fiche les bonus d'init et de DEF, et ajouter la capacité intimider.
    9. +
    10. Écuyer :
        -
      • Pour le bonus au critique, ajouter un pr\xE9dicat ecuyer.
      • -
      • Pour les soins de nuit, ajouter \xE0 l'\xE9cuyer un pr\xE9dicat ecuyerDe, avec comme valeur le nom du chevalier (attention \xE0 utiliser la syntaxe avec :: si ce nom contient des espaces). L'\xE9cuyer pourra soigner chaque nuit le chevalier et certains alli\xE9s, mais pour qu'il soigne les alli\xE9s, il ne faut pas oublier de le mettre dans la liste de l'\xE9quipe du chevalier.
      • -
      • Si on souhaite que l'\xE9cuyer puisse soigner gratuitement la monture, il faut aussi que celle-ci ait un pr\xE9dicat montureDe, avec comme valeur le nom du chevalier.
      • +
      • Pour le bonus au critique, ajouter un prédicat ecuyer.
      • +
      • Pour les soins de nuit, ajouter à l'écuyer un prédicat ecuyerDe, avec comme valeur le nom du chevalier (attention à utiliser la syntaxe avec :: si ce nom contient des espaces). L'écuyer pourra soigner chaque nuit le chevalier et certains alliés, mais pour qu'il soigne les alliés, il ne faut pas oublier de le mettre dans la liste de l'équipe du chevalier.
      • +
      • Si on souhaite que l'écuyer puisse soigner gratuitement la monture, il faut aussi que celle-ci ait un prédicat montureDe, avec comme valeur le nom du chevalier.
    @@ -1199,52 +1203,52 @@

    Druide

    Voie des animaux

    1. Langage des animaux : pas de support particulier
    2. -
    3. Nu\xE9e d'insectes : Pas de support particulier pour les DM de zone qui d\xE9truisent la nu\xE9e (enlever l'attribut nueeDInsecte sur la cible dans ce cas). +
    4. Nuée d'insectes : Pas de support particulier pour les DM de zone qui détruisent la nuée (enlever l'attribut nueeDInsecte sur la cible dans ce cas).
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateur pasDeDmg, options --mana 0 --effet nueeDInsectes [[5+@{selected|SAG}]].
      • -
      • Objet de sort : #Attaque Nu\xE9e d'insectes --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet nueeDInsectes [[5+@{selected|SAG}]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateur pasDeDmg, options --mana 0 --effet nueeDInsectes [[5+@{selected|SAG}]].
      • +
      • Objet de sort : #Attaque Nuée d'insectes --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet nueeDInsectes [[5+@{selected|SAG}]]
    5. -
    6. Le guetteur : Si elle n'est pas d\xE9j\xE0 pr\xE9sente dans votre handout de comp\xE9tences, ajouter au druide une comp\xE9tence perception (valeur 0 pour le moment). Cr\xE9er un personnage et un token pour l'oiseau. Ajouter au druide un pr\xE9dicat guetteur de valeur le nom exact de l'oiseau (sur la fiche, attention \xE0 utiliser la symtaxe avec :: si le nom comporte des espaces). Ajouter de m\xEAme un pr\xE9dicat PVPartagesAvec de valeur le nom de l'oiseau. Ajouter aussi \xE0 l'oiseau un pr\xE9dicat PVPartagesAvec de valeur le nom du druide. Pour le faire agir en m\xEAme temps que le druide, ajoutez aussi \xE0 l'oiseau un pr\xE9dicat initiativeDeriveeDe de valeur le nom du druide. Pour l'attaque, ajouter sur la fiche une attaque de contact faisant 1d4 DM, avec dans les options --attaqueMagiqueDe nom de personnage du druide. Si vous souhaitez que le guetteur rentre en combat en m\xEAme temps que le druide, ajoutez au druide un pr\xE9dicat nomm\xE9 entrerEnCombatAvec, de valeur le nom du token de l'oiseau.
    7. -
    8. Masque du pr\xE9dateur : !cof-effet-temp masqueDuPredateur [[5+@{selected|SAG}]] --mana 2
    9. +
    10. Le guetteur : Si elle n'est pas déjà présente dans votre handout de compétences, ajouter au druide une compétence perception (valeur 0 pour le moment). Créer un personnage et un token pour l'oiseau. Ajouter au druide un prédicat guetteur de valeur le nom exact de l'oiseau (sur la fiche, attention à utiliser la symtaxe avec :: si le nom comporte des espaces). Ajouter de même un prédicat PVPartagesAvec de valeur le nom de l'oiseau. Ajouter aussi à l'oiseau un prédicat PVPartagesAvec de valeur le nom du druide. Pour le faire agir en même temps que le druide, ajoutez aussi à l'oiseau un prédicat initiativeDeriveeDe de valeur le nom du druide. Pour l'attaque, ajouter sur la fiche une attaque de contact faisant 1d4 DM, avec dans les options --attaqueMagiqueDe nom de personnage du druide. Si vous souhaitez que le guetteur rentre en combat en même temps que le druide, ajoutez au druide un prédicat nommé entrerEnCombatAvec, de valeur le nom du token de l'oiseau.
    11. +
    12. Masque du prédateur : !cof-effet-temp masqueDuPredateur [[5+@{selected|SAG}]] --mana 2
    13. Forme animale : pas d'autre support que !cof-lancer-sort se transforme en ?{Transformation en ?} --mana 3

    Voie du fauve

      -
    1. Vitesse du f\xE9lin : ajouter un pr\xE9dicat vitesseDuFelin, de valeur le rang dans la voie. Pensez \xE0 ajouter des comp\xE9tences de saut, escalade et course sur la fiche (sans les bonus !) s'ils ne sont pas d\xE9j\xE0 pr\xE9sent dans votre handout de comp\xE9tences.
    2. -
    3. Panth\xE8re : ajouter un personnage pour la panth\xE8re, qui sera contr\xF4l\xE9 par le joueur. Si vous souhaitez que la panth\xE8re rentre en combat \xE0 chaque fois que le druide entre en combat, ajoutez au druide un pr\xE9dicat nomm\xE9 entrerEnCombatAvec, de valeur le nom du token de la panth\xE8re (il peut y avoir plusieurs pr\xE9dicats avec ce nom).
    4. -
    5. Attaque bondissante : faire l'attaque avec les options --bonusAttaque 5 --plus 1d6. Les conditions d'utilisation sont \xE0 v\xE9rifier par le MJ.
    6. -
    7. Grand f\xE9lin : ajuster la fiche de la panth\xE8re, et pour le soin, utiliser !cof-soin @{selected|token_id} nom_familier ?{Montant des soins} --transfer.
    8. -
    9. Les sept vies du chat : pas de support particulier, la commande Undo peut \xEAtre utilis\xE9e pour annuler l'action qui a men\xE9 le Druide \xE0 0 PV.
    10. +
    11. Vitesse du félin : ajouter un prédicat vitesseDuFelin, de valeur le rang dans la voie. Pensez à ajouter des compétences de saut, escalade et course sur la fiche (sans les bonus !) s'ils ne sont pas déjà présent dans votre handout de compétences.
    12. +
    13. Panthère : ajouter un personnage pour la panthère, qui sera contrôlé par le joueur. Si vous souhaitez que la panthère rentre en combat à chaque fois que le druide entre en combat, ajoutez au druide un prédicat nommé entrerEnCombatAvec, de valeur le nom du token de la panthère (il peut y avoir plusieurs prédicats avec ce nom).
    14. +
    15. Attaque bondissante : faire l'attaque avec les options --si premiereAttaque --deplaceDe 5 30 saut --bonusAttaque 5 --plus 1d6.
    16. +
    17. Grand félin : ajuster la fiche de la panthère, et pour le soin, utiliser !cof-soin @{selected|token_id} nom_familier ?{Montant des soins} --transfer.
    18. +
    19. Les sept vies du chat : pas de support particulier, la commande Undo peut être utilisée pour annuler l'action qui a mené le Druide à 0 PV.

    Voie de la nature

      -
    1. Ma\xEEtre de la survie : Ajouter +2 par rang \xE0 une comp\xE9tence vigilance
    2. -
    3. Marche sylvestre : ajouter un pr\xE9dicat marcheSylvestre. Pour indiquer un terrain difficile, on peut utiliser les objets graphiques sur le layer des cartes (map en anglais). Pour cela, \xE9diter l'objet, et ajouter dans les notes pour MJ une ligne terrainDifficile. Tout le dessin est consid\xE9r\xE9 comme un terrain difficile. On peut restreindre la partie consid\xE9r\xE9e comme difficile \xE0 un disque en \xE9crivant terrainDifficile: disque n o\xF9 n est le diam\xE8tre du disque en pixels. \xC0 noter que la zone d'une prison v\xE9g\xE9tale est consid\xE9r\xE9e difficile par le script. Le druide est consid\xE9r\xE9 en terrain difficile si vous le mettez dans l'\xE9tat conditionsHostiles (pour des valeurs inf\xE9rieures \xE0 5). Alternativement, si vous n'avez pas ajout\xE9 le type de terrain vous pouvez taper !cof-effet marcheSylvestre oui quand le druide entre dans un terrain que vous consid\xE9rez difficile. Dans ce cas, faire !cof-effet marcheSylvestre non quand il sort de cette zone.
    4. -
    5. R\xE9sistant : ajouter dans la RD sur la fiche, nature:v, avec comme valeur v la RD (donc deux fois le rang dans la voie). Cette RD s'applique \xE0 toute attaque ou dommages avec l'option --nature ou --naturel. Il s'applique aussi \xE0 toute attaque venant d'un personnage avec un pr\xE9dicat animal, ou insecte ou bien avec un profil animal ou insecte, ou avec une race reconnue comme \xE9tant un animal ou un insecte. Dans ce cas, si on souhaite qu'une attaque d'une telle cr\xE9ature ne soit pas consid\xE9r\xE9e comme naturelle, on peut utiliser l'option --artificiel \xE0 l'attaque.
    6. -
    7. B\xE2ton de druide : Simplement cr\xE9er l'attaque correspondante et permettre les deux attaques en action limit\xE9e.
    8. -
    9. Constitution h\xE9ro\xEFque : reporter sur la fiche
    10. +
    11. Maître de la survie : Ajouter +2 par rang à une compétence vigilance
    12. +
    13. Marche sylvestre : ajouter un prédicat marcheSylvestre. Pour indiquer un terrain difficile, on peut utiliser les objets graphiques sur le layer des cartes (map en anglais). Pour cela, éditer l'objet, et ajouter dans les notes pour MJ une ligne terrainDifficile. Tout le dessin est considéré comme un terrain difficile. On peut restreindre la partie considérée comme difficile à un disque en écrivant terrainDifficile: disque nn est le diamètre du disque en pixels. À noter que la zone d'une prison végétale est considérée difficile par le script. Le druide est considéré en terrain difficile si vous le mettez dans l'état conditionsHostiles (pour des valeurs inférieures à 5). Alternativement, si vous n'avez pas ajouté le type de terrain vous pouvez taper !cof-effet marcheSylvestre oui quand le druide entre dans un terrain que vous considérez difficile. Dans ce cas, faire !cof-effet marcheSylvestre non quand il sort de cette zone.
    14. +
    15. Résistant : ajouter dans la RD sur la fiche, nature:v, avec comme valeur v la RD (donc deux fois le rang dans la voie). Cette RD s'applique à toute attaque ou dommages avec l'option --nature ou --naturel. Il s'applique aussi à toute attaque venant d'un personnage avec un prédicat animal, ou insecte ou bien avec un profil animal ou insecte, ou avec une race reconnue comme étant un animal ou un insecte. Dans ce cas, si on souhaite qu'une attaque d'une telle créature ne soit pas considérée comme naturelle, on peut utiliser l'option --artificiel à l'attaque.
    16. +
    17. Bâton de druide : Simplement créer l'attaque correspondante et permettre les deux attaques en action limitée.
    18. +
    19. Constitution héroïque : reporter sur la fiche

    Voie du protecteur

      -
    1. Baies magiques : Pour simplement cr\xE9er les baies, on peut utiliser !cof-creer-baies, avec \xE9ventuellement des arguments pour la d\xE9pense de mana. Si le sort ne demande pas de d\xE9pense et que le temps pass\xE9 n'est pas important, il peut \xEAtre plus simple de directement utiliser !cof-distribuer-baies avec option --allies --self ou --target pour cr\xE9er et donner des baies (en ayant s\xE9lectionn\xE9 le druide, le mieux est d'utiliser une ability). Pour consommer ensuite une baie, il faut utiliser !cof-consommables.
    2. -
    3. For\xEAt vivante : on peut mettre un effet (avec !cof-effet) foretVivanteEnnemie aux personnages affect\xE9s. Par exemple, si on veut donner l'effet aux personnages non alli\xE9s du druide, on peut faire !cof-effet foretVivanteEnnemie oui --disque @{selected|token_id} 2000 --saufAllies --mana 0. Attention, l'effet ne dispara\xEEt que si on fait un !cof-effet foretVivanteEnnemie non sur les personnages.
    4. -
    5. R\xE9g\xE9n\xE9ration : !cof-effet-temp regeneration [[@{selected|niveau} + @{selected|SAG}]] --lanceur @{selected|token_id} --target @{target|token_id} --limiteCibleParJour 1 --portee 0 --mana 1.
    6. -
    7. Forme d'arbre : !cof-effet-temp formeDArbre [[5+@{selected|SAG}]] --mana 2. J'ai choisi de donner comme pouvoir suppl\xE9mentaire \xE0 cette forme d'avoir ses propres PVs, et le druide r\xE9cup\xE8re ses PVs originaux \xE0 la fin de l'effet. La transformation est annul\xE9e aussi si l'arbre perd tous ses PVs. Le nombre de PVs par d\xE9faut est de niveau x 5, mais il peut \xEAtre modifi\xE9 en ajoutant au argument --valeur pv. Pour augmenter un peu l'int\xE9r\xEAt de ce sort, je lui fais aussi augmenter de 50% le bonus de peau d'\xE9corce. Si vous utilisez les actions \xE0 afficher \xE0 chaque tour, vous pouvez aussi cr\xE9er une liste d'actions nomm\xE9e Forme d'arbre contenant les sorts et actions possibles en forme d'arbre. Si une telle liste existe, elle va toujours afficher au moins les actions d\xE9fensive, d'attente et d'attaque sous forme d'arbre (pas besoin de cr\xE9er une attaque d\xE9di\xE9e sur la fiche). Il est possible de sp\xE9cifier une image pour le token en forme d'arbre, en utilisant le valeur d'un pr\xE9dicat tokenFormeDArbre.
    8. -
    9. Sagesse h\xE9ro\xEFque : reporter sur la fiche
    10. +
    11. Baies magiques : Pour simplement créer les baies, on peut utiliser !cof-creer-baies, avec éventuellement des arguments pour la dépense de mana. Si le sort ne demande pas de dépense et que le temps passé n'est pas important, il peut être plus simple de directement utiliser !cof-distribuer-baies avec option --allies --self ou --target pour créer et donner des baies (en ayant sélectionné le druide, le mieux est d'utiliser une ability). Pour consommer ensuite une baie, il faut utiliser !cof-consommables.
    12. +
    13. Forêt vivante : on peut mettre un effet (avec !cof-effet) foretVivanteEnnemie aux personnages affectés. Par exemple, si on veut donner l'effet aux personnages non alliés du druide, on peut faire !cof-effet foretVivanteEnnemie oui --disque @{selected|token_id} 2000 --saufAllies --mana 0. Attention, l'effet ne disparaît que si on fait un !cof-effet foretVivanteEnnemie non sur les personnages.
    14. +
    15. Régénération : !cof-effet-temp regeneration [[@{selected|niveau} + @{selected|SAG}]] --lanceur @{selected|token_id} --target @{target|token_id} --limiteCibleParJour 1 --portee 0 --mana 1.
    16. +
    17. Forme d'arbre : !cof-effet-temp formeDArbre [[5+@{selected|SAG}]] --mana 2. J'ai choisi de donner comme pouvoir supplémentaire à cette forme d'avoir ses propres PVs, et le druide récupère ses PVs originaux à la fin de l'effet. La transformation est annulée aussi si l'arbre perd tous ses PVs. Le nombre de PVs par défaut est de niveau x 5, mais il peut être modifié en ajoutant au argument --valeur pv. Pour augmenter un peu l'intérêt de ce sort, je lui fais aussi augmenter de 50% le bonus de peau d'écorce. Si vous utilisez les actions à afficher à chaque tour, vous pouvez aussi créer une liste d'actions nommée Forme d'arbre contenant les sorts et actions possibles en forme d'arbre. Si une telle liste existe, elle va toujours afficher au moins les actions défensive, d'attente et d'attaque sous forme d'arbre (pas besoin de créer une attaque dédiée sur la fiche). Il est possible de spécifier une image pour le token en forme d'arbre, en utilisant le valeur d'un prédicat tokenFormeDArbre.
    18. +
    19. Sagesse héroïque : reporter sur la fiche
    -

    Voie des v\xE9g\xE9taux

    +

    Voie des végétaux

      -
    1. Peau d'\xE9corce : !cof-effet-temp peauDEcorce [[5+@{selected|SAG}]] --mana 0. Par d\xE9faut, utilise la valeur d'un pr\xE9dicat voieDesVegetaux (qui devrait avoir comme valeur le rang dans la voie). Il est possible de choisir une autre valeur en utilisant l'option --valeur, et si aucune des deux m\xE9thodes n'est utilis\xE9e, le bonus de DEF est de 1.
    2. -
    3. Prison v\xE9g\xE9tale : !cof-effet-temp prisonVegetale [[5+@{selected|SAG}]] --saveActifParTour FOR [[10+@{selected|SAG}]] --lanceur @{selected|token_id} --disque @{target|token_id} 5 20 --saufAllies --mana 0.
    4. -
    5. Animation d'un arbre : !cof-animer-arbre @{selected|token_id} @{target|token_id} --portee 0 --mana 1. Cela implique d'avoir un token repr\xE9sentant l'arbre sur la carte. Ce que je fais, c'est de passer un token d'arbre du layer map au layer tokens, puis je laisse le joueur faire le sort. Si c'est trop compliqu\xE9, vous pouvez aussi pr\xE9parer un personnage arbre, avec les caract\xE9ristiques d\xE9crites, et le faire arriver sur la carte \xE0 la main (ne pas oublier sa RD 10/feu_hache, dans ce cas).
    6. +
    7. Peau d'écorce : !cof-effet-temp peauDEcorce [[5+@{selected|SAG}]] --mana 0. Par défaut, utilise la valeur d'un prédicat voieDesVegetaux (qui devrait avoir comme valeur le rang dans la voie). Il est possible de choisir une autre valeur en utilisant l'option --valeur, et si aucune des deux méthodes n'est utilisée, le bonus de DEF est de 1.
    8. +
    9. Prison végétale : !cof-effet-temp prisonVegetale [[5+@{selected|SAG}]] --saveActifParTour FOR [[10+@{selected|SAG}]] --lanceur @{selected|token_id} --disque @{target|token_id} 5 20 --saufAllies --mana 0.
    10. +
    11. Animation d'un arbre : !cof-animer-arbre @{selected|token_id} @{target|token_id} --portee 0 --mana 1. Cela implique d'avoir un token représentant l'arbre sur la carte. Ce que je fais, c'est de passer un token d'arbre du layer map au layer tokens, puis je laisse le joueur faire le sort. Si c'est trop compliqué, vous pouvez aussi préparer un personnage arbre, avec les caractéristiques décrites, et le faire arriver sur la carte à la main (ne pas oublier sa RD 10/feu_hache, dans ce cas).
    12. Gland de pouvoir :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateur pasDeDmg, options --mana 2 --effet statueDeBois [[2d6+@{selected|SAG}]] --valeur 10 10. \xC0 noter qu'un pr\xE9dicat immunite_petrification permet d'\xEAtre immunis\xE9 \xE0 cet effet.
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateur pasDeDmg, options --mana 2 --effet statueDeBois [[2d6+@{selected|SAG}]] --valeur 10 10. À noter qu'un prédicat immunite_petrification permet d'être immunisé à cet effet.
      • Objet de sort : #Attaque Gland de pouvoir --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --effet statueDeBois [[2d6+@{selected|SAG}]] --valeur 10 10
    13. -
    14. Porte v\xE9g\xE9tale : Pas de support au niveau du script, \xE0 part !cof-lancer-sort lance un sort de porte v\xE9g\xE9tale --mana 3.
    15. +
    16. Porte végétale : Pas de support au niveau du script, à part !cof-lancer-sort lance un sort de porte végétale --mana 3.

    Ensorceleur

    @@ -1255,225 +1259,225 @@

    Voie de l'air

  • Sous tension :
    1. !cof-effet-temp sousTension [[5+@{selected|CHA}]] --mana 0 pour lancer le sort et mettre l'ensorceleur sous tension
    2. -
    3. Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+CHA, port\xE9e 10, type Sortil\xE8ge, d\xE9g\xE2ts \xE9lectriques, options --si etat sousTension --fx beam-holy.
    4. -
    5. Pour les objets de sorts, on peut mettre l'attaque directement sous la forme #Attaque D\xE9charge \xE9lectrique --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|CHA}]] --electrique --portee 10 --sortilege --si etat sousTension --fx beam-holy
    6. +
    7. Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+CHA, portée 10, type Sortilège, dégâts électriques, options --si etat sousTension --fx beam-holy.
    8. +
    9. Pour les objets de sorts, on peut mettre l'attaque directement sous la forme #Attaque Décharge électrique --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|CHA}]] --electrique --portee 10 --sortilege --si etat sousTension --fx beam-holy
  • - Note : Il est possible de sp\xE9cifier une autre valeur pour les DM automatiques quand le lanceur est touch\xE9 en contact, en rajoutant --valeur X \xE0 la premi\xE8re ability. + Note : Il est possible de spécifier une autre valeur pour les DM automatiques quand le lanceur est touché en contact, en rajoutant --valeur X à la première ability. -
  • T\xE9l\xE9kin\xE9sie : Pas de support autre que !cof-lancer-sort lance un sort de t\xE9l\xE9kin\xE9sie --mana 1
  • +
  • Télékinésie : Pas de support autre que !cof-lancer-sort lance un sort de télékinésie --mana 1
  • Foudre :
      -
    • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, 4d6+CHA, port\xE9e 10, type Sortil\xE8ge, options --mana 2 --psave DEX [[12+@{selected|DEX}]] --ligne --fx beam-holy.
    • +
    • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, 4d6+CHA, portée 10, type Sortilège, options --mana 2 --psave DEX [[12+@{selected|DEX}]] --ligne --fx beam-holy.
    • Objet de sort : #Attaque Foudre --toucher [[@{selected|ATKMAG}]] --dm 4d6+[[@{selected|CHA}]] --portee 10 --sortilege --psave DEX [[12+@{selected|DEX}]] --ligne --fx beam-holy
  • -
  • Forme \xE9th\xE9r\xE9e : !cof-effet-temp intangible [[5 + @{selected|CHA}]] --mana 3. Pour impl\xE9mentaer des variantes, il existe aussi un effet intangibleInvisible qui cumule les \xE9tats intangible et invisible, et l'option --puissant donne la possibilit\xE9 au personnage de passer entre l'\xE9tat tangible et intangible \xE0 chaque tour, tant que dure l'effet.
  • +
  • Forme éthérée : !cof-effet-temp intangible [[5 + @{selected|CHA}]] --mana 3. Pour implémentaer des variantes, il existe aussi un effet intangibleInvisible qui cumule les états intangible et invisible, et l'option --puissant donne la possibilité au personnage de passer entre l'état tangible et intangible à chaque tour, tant que dure l'effet.
  • Voie de la divination

      -
    1. 6eme sens : ajouter le bonus en DEF divers et initiative diver, ajouter une comp\xE9tence vigilance, de valeur 2*rang (le bonus aux jet de surprise).
    2. -
    3. D\xE9tection de l'invisible : !cof-effet-temp detectionDeLInvisible [[5+@{selected|CHA}]] --mana 0.
    4. -
    5. Clairvoyance : !cof-lancer-sort peut voir et entendre \xE0 distance --mana 1
    6. -
    7. Prescience : ajouter un pr\xE9dicat prescience (on peut y associer un nombre pour avoir plus d'une prescience par tour). Si le personnage \xE9tait sur la carte au moment de lancer le combat, il se verra proposer un bouton pour utiliser sa prescience \xE0 la fin de chaque tour. Attention, en l'\xE9tat, il est impossible d'annuler l'utilisation de ce bouton. De plus, ce bouton ne fera rien si le script a \xE9t\xE9 interrompu depuis le d\xE9but du tour (interruption de la partie, red\xE9marrage du script, etc...).
    8. +
    9. 6eme sens : ajouter le bonus en DEF divers et initiative diver, ajouter une compétence vigilance, de valeur 2*rang (le bonus aux jet de surprise).
    10. +
    11. Détection de l'invisible : !cof-effet-temp detectionDeLInvisible [[5+@{selected|CHA}]] --mana 0.
    12. +
    13. Clairvoyance : !cof-lancer-sort peut voir et entendre à distance --mana 1
    14. +
    15. Prescience : ajouter un prédicat prescience (on peut y associer un nombre pour avoir plus d'une prescience par tour). Si le personnage était sur la carte au moment de lancer le combat, il se verra proposer un bouton pour utiliser sa prescience à la fin de chaque tour. Attention, en l'état, il est impossible d'annuler l'utilisation de ce bouton. De plus, ce bouton ne fera rien si le script a été interrompu depuis le début du tour (interruption de la partie, redémarrage du script, etc...).
    16. Hyperconscience : reporter sur la fiche.
    -

    Voie de l'envo\xFBteur

    +

    Voie de l'envoûteur

    1. Injonction : utiliser !cof-injonction @{selected|token_id} @{target|token_id} --portee 20 --mana 0
    2. -
    3. Sommeil : !cof-sommeil @{selected|token_id} --disque @{target|token_id} 5 20 --mana 0. Pour s\xE9lectionner le centre de la zone, on peut utiliser un personnage fictif (avec un token repr\xE9sentant une cible, par exemple) ayant 0 de max de PV.
    4. +
    5. Sommeil : !cof-sommeil @{selected|token_id} --disque @{target|token_id} 5 20 --mana 0. Pour sélectionner le centre de la zone, on peut utiliser un personnage fictif (avec un token représentant une cible, par exemple) ayant 0 de max de PV.
    6. Confusion:
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg options --mana 1 --attaqueMentale --effet confusion [[3+@{selected|CHA}]] --saveParTour SAG [[10+@{selected|CHA}]].
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg options --mana 1 --attaqueMentale --effet confusion [[3+@{selected|CHA}]] --saveParTour SAG [[10+@{selected|CHA}]].
      • Objet de sort : #Attaque Confusion --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --attaqueMentale --effet confusion [[3+@{selected|CHA}]] --saveParTour SAG [[10+@{selected|CHA}]]
    7. -
    8. Amiti\xE9: +
    9. Amitié:
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg options --mana 2 --attaqueMentale --difficultePVmax --effet charme --save SAG [[12+@{selected|CHA}]] --saveParJour SAG [[12+@{selected|CHA}]].
      • -
      • Objet de sort : #Attaque Amiti\xE9 --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --attaqueMentale --difficultePVmax --effet charme --save SAG [[12+@{selected|CHA}]] --saveParJour SAG [[12+@{selected|CHA}]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg options --mana 2 --attaqueMentale --difficultePVmax --effet charme --save SAG [[12+@{selected|CHA}]] --saveParJour SAG [[12+@{selected|CHA}]].
      • +
      • Objet de sort : #Attaque Amitié --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --attaqueMentale --difficultePVmax --effet charme --save SAG [[12+@{selected|CHA}]] --saveParJour SAG [[12+@{selected|CHA}]]
    10. Domination : utiliser !cof-attaque-magique @{selected|token_id} @{target|token_id} --portee 20 --attaqueMentale

    Voie des illusions

      -
    1. Image d\xE9cal\xE9e : !cof-effet-temp imageDecalee [[5+@{selected|CHA}]] --mana 0.
    2. +
    3. Image décalée : !cof-effet-temp imageDecalee [[5+@{selected|CHA}]] --mana 0.
    4. Mirage : pas de support autre que !cof-lancer-sort lance un sort de mirage ([[5+@{selected|CHA}]] minutes) --mana 0
    5. Imitation : pas de support autre que !cof-lancer-sort lance un sort d'imitation ([[5+@{selected|CHA}]] minutes) --mana 1
    6. -
    7. D\xE9doublement : +
    8. Dédoublement :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg options --mana 2 --effet dedoublement [[5+@{selected|CHA}]].
      • -
      • Objet de sort : #Attaque D\xE9doublement --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet dedoublement [[5+@{selected|CHA}]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg options --mana 2 --effet dedoublement [[5+@{selected|CHA}]].
      • +
      • Objet de sort : #Attaque Dédoublement --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet dedoublement [[5+@{selected|CHA}]]
    9. -
    10. Tueur fantasmagorique : !cof-tueur-fantasmagorique @{selected|token_id} @{target|token_id} --portee 20 --mana 3. Attention, j'en ai fait une interpr\xE9tation un peu personnelle : au lieu de ne pas pouvoir toucher les cibles de niveau sup\xE9rieur au lanceur, les cible de niveau sup\xE9rieur gagnent un bonus de 5 par niveau au dessus de celui du lanceur pour r\xE9sister au tueur fantasmagorique. Et ceux de niveau inf\xE9rieur un malus de 1 par niveau de diff\xE9rence. Si cette interpr\xE9tation ne vous convient pas, n'h\xE9sitez pas \xE0 me demander des changements.
    11. +
    12. Tueur fantasmagorique : !cof-tueur-fantasmagorique @{selected|token_id} @{target|token_id} --portee 20 --mana 3. Attention, j'en ai fait une interprétation un peu personnelle : au lieu de ne pas pouvoir toucher les cibles de niveau supérieur au lanceur, les cible de niveau supérieur gagnent un bonus de 5 par niveau au dessus de celui du lanceur pour résister au tueur fantasmagorique. Et ceux de niveau inférieur un malus de 1 par niveau de différence. Si cette interprétation ne vous convient pas, n'hésitez pas à me demander des changements.

    Voie de l'invocation

      -
    1. Familier : cr\xE9er un personnage (de type PNJ) pour le familier, control\xE9 par le joueur et avec un token li\xE9 ayant la capacit\xE9 de voir. +
    2. Familier : créer un personnage (de type PNJ) pour le familier, controlé par le joueur et avec un token lié ayant la capacité de voir.
        -
      • Pour le bonus en initiative, ajouter un pr\xE9dicat familier au personnage, avec comme valeur le nom du compagnon (doit \xEAtre exactement le m\xEAme que celui du token du compagnon). Cela automatise l'initiative quand le familier est pr\xE9sent.
      • -
      • Pour les points de vie partag\xE9s avec le familier, il faut mettre un pr\xE9dicat PVPartagesAvec de valeur le nom du familier (celui de la fiche, pas forc\xE9ment le m\xEAme que le token) pour le personnage, et un pr\xE9dicat similaire chez le familier, de valeur le nom du personnage. Le partage de PVs ne fonctionne pas avec des mooks, et il ne fait pas le partage de d\xE9g\xE2ts temporaires. En revanche, le script devrait g\xE9rer correctement les d\xE9g\xE2ts de zone.
      • -
      • Pour la d\xE9fense du familier, lui ajouter un pr\xE9dicat defDeriveeDe, de valeur le nom du personnage (nom complet sur la fiche, attention \xE0 bien utiliser la syntaxe avec :: si ce nom contient des espaces ou autres caract\xE8res sp\xE9ciaux).
      • -
      • L'initiative ne devrait pas \xEAtre tr\xE8s utile, mais si besoin, ajoutez un pr\xE9dicat initiativeDeriveeDe de valeur le nom du personnage. En fait, pour les familiers normaux, je pr\xE9f\xE8res m\xEAme qu'ils n'apparaissent pas sur le turn tracker, et je leur met donc un pr\xE9dicat aucuneActionCombat.
      • +
      • Pour le bonus en initiative, ajouter un prédicat familier au personnage, avec comme valeur le nom du compagnon (doit être exactement le même que celui du token du compagnon). Cela automatise l'initiative quand le familier est présent.
      • +
      • Pour les points de vie partagés avec le familier, il faut mettre un prédicat PVPartagesAvec de valeur le nom du familier (celui de la fiche, pas forcément le même que le token) pour le personnage, et un prédicat similaire chez le familier, de valeur le nom du personnage. Le partage de PVs ne fonctionne pas avec des mooks, et il ne fait pas le partage de dégâts temporaires. En revanche, le script devrait gérer correctement les dégâts de zone.
      • +
      • Pour la défense du familier, lui ajouter un prédicat defDeriveeDe, de valeur le nom du personnage (nom complet sur la fiche, attention à bien utiliser la syntaxe avec :: si ce nom contient des espaces ou autres caractères spéciaux).
      • +
      • L'initiative ne devrait pas être très utile, mais si besoin, ajoutez un prédicat initiativeDeriveeDe de valeur le nom du personnage. En fait, pour les familiers normaux, je préfères même qu'ils n'apparaissent pas sur le turn tracker, et je leur met donc un prédicat aucuneActionCombat.
    3. -
    4. Serviteur invisible : pas de support autre que !cof-lancer-sort cr\xE9e une force invisible pour ([[5+@{selected|CHA}]] minutes) --mana 0
    5. -
    6. Mur de force : !cof-mur-de-force ?{Spherique?|Oui,&#32;|Non,mur} --mana 1. Cela affiche une image d'un champ de force, mais seulement si il est sph\xE9rique. Il est possible de ne pas afficher d'image avec la commande !cof-mur-de-force noImage. Il est possible d'utiliser une autre image que l'image par d\xE9faut en utilisant la commande !cof-mur-de-force path o\xF9 path est l'adresse url d'une image de la librairie Roll20 qui repr\xE9sente un mur de force sph\xE9rique. On peut aussi changer l'image par d\xE9faut dans les options de jeu.
    7. -
    8. \xC9p\xE9e dansante : +
    9. Serviteur invisible : pas de support autre que !cof-lancer-sort crée une force invisible pour ([[5+@{selected|CHA}]] minutes) --mana 0
    10. +
    11. Mur de force : !cof-mur-de-force ?{Spherique?|Oui,&#32;|Non,mur} --mana 1. Cela affiche une image d'un champ de force, mais seulement si il est sphérique. Il est possible de ne pas afficher d'image avec la commande !cof-mur-de-force noImage. Il est possible d'utiliser une autre image que l'image par défaut en utilisant la commande !cof-mur-de-force pathpath est l'adresse url d'une image de la librairie Roll20 qui représente un mur de force sphérique. On peut aussi changer l'image par défaut dans les options de jeu.
    12. +
    13. Épée dansante :
      • !cof-effet-temp epeeDansante [[5+@{selected|CHA}]] --mana 2 pour lancer le sort
      • -
      • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+CHA, port\xE9e 20, type Sortil\xE8ge, d\xE9g\xE2ts magiques, options --si etat epeeDansante --ignoreObstacles.
      • -
      • Pour les objets de sort, on peut utiliser une action #Attaque \xC9p\xE9e dansante --toucher [[@{selected|ATKMAG}]] --dm 1d8+[[@{selected|CHA}]] --magique --portee 20 --sortilege --si etat epeeDansante --ignoreObstacles
      • +
      • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+CHA, portée 20, type Sortilège, dégâts magiques, options --si etat epeeDansante --ignoreObstacles.
      • +
      • Pour les objets de sort, on peut utiliser une action #Attaque Épée dansante --toucher [[@{selected|ATKMAG}]] --dm 1d8+[[@{selected|CHA}]] --magique --portee 20 --sortilege --si etat epeeDansante --ignoreObstacles
      - Pour une rapi\xE8re dansante, il existe aussi un effet temporaire rapiereDansante. + Pour une rapière dansante, il existe aussi un effet temporaire rapiereDansante.
    14. -
    15. Charisme h\xE9ro\xEFque : reporter sur la fiche
    16. +
    17. Charisme héroïque : reporter sur la fiche

    Forgesort

    Voie des artefacts

      -
    1. B\xE2ton de mage : simplement adapter l'attaque, avec aussi le modificateur magique. Pour l'\xE9clair d'\xE9nergie, ajoutez dans les options ?{Attaque|Normale,--magieRapide 2|\xC9clair d'\xE9nergie (L),--eclairDEnergie}. Si vous autorisez les r\xE8gles de mana pour cette attaque, remplacez par ?{Attaque|Normale,&#32;|\xC9clair d'\xE9nergie (L),--eclairDEnergie|\xC9clair d'\xE9nergie rapide, --eclairDEnergie --magieRapide|\xC9clair d'\xE9nergie puissant (L), --eclairDEnergie --tempeteDeMana 1}.
    2. -
    3. Blocage : pas de support autre que !cof-lancer-sort scelle une porte ou un coffre (+5 solidit\xE9 & RD) pour [[@{selected|INT}]] minutes --mana 0
    4. +
    5. Bâton de mage : simplement adapter l'attaque, avec aussi le modificateur magique. Pour l'éclair d'énergie, ajoutez dans les options ?{Attaque|Normale,--magieRapide 2|Éclair d'énergie (L),--eclairDEnergie}. Si vous autorisez les règles de mana pour cette attaque, remplacez par ?{Attaque|Normale,&#32;|Éclair d'énergie (L),--eclairDEnergie|Éclair d'énergie rapide, --eclairDEnergie --magieRapide|Éclair d'énergie puissant (L), --eclairDEnergie --tempeteDeMana 1}.
    6. +
    7. Blocage : pas de support autre que !cof-lancer-sort scelle une porte ou un coffre (+5 solidité & RD) pour [[@{selected|INT}]] minutes --mana 0
    8. Sac sans fond : pas de support particulier
    9. -
    10. Frappe des arcanes : le plus simple est d'utiliser la m\xEAme ligne d'attaque (disons que son label est E) que pour l'attaque d'\xE9nergie (mais si besoin, rien n'emp\xEAche d'en utiliser une autre). La commande sera alors !cof-explosion E --auto --magique --sortilege --portee 10 --etat renverse --save FOR [[10+@{selected|INT}]].
    11. +
    12. Frappe des arcanes : le plus simple est d'utiliser la même ligne d'attaque (disons que son label est E) que pour l'attaque d'énergie (mais si besoin, rien n'empêche d'en utiliser une autre). La commande sera alors !cof-explosion E --auto --magique --sortilege --portee 10 --etat renverse --save FOR [[10+@{selected|INT}]].
    13. Artefact majeur : pas de support particulier
    -

    Voie des \xE9lixirs

    -

    Pour cr\xE9er ou juste voir ses \xE9lixirs, utiliser la commande !cof-elixirs. Pour cela, il faut aussi un pr\xE9dicat voieDesElixirs avec comme valeur le rang dans la voie. Noter que la commande !cof-elixirs affiche une liste d'\xE9lixirs, et que pour effectivement cr\xE9er un \xE9lixir, il faut cliquer sur le bouton correspondant dans cette liste. Le script propose les \xE9lixirs par d\xE9faut du jeu, mais vous pouvez modifier cette liste : pour changer un \xE9lixir de rang k (k<4), ajouter un attribut de nom Elixir k, de valeur courante le nom et de valeur maximale l'effet.

    +

    Voie des élixirs

    +

    Pour créer ou juste voir ses élixirs, utiliser la commande !cof-elixirs. Pour cela, il faut aussi un prédicat voieDesElixirs avec comme valeur le rang dans la voie. Noter que la commande !cof-elixirs affiche une liste d'élixirs, et que pour effectivement créer un élixir, il faut cliquer sur le bouton correspondant dans cette liste. Le script propose les élixirs par défaut du jeu, mais vous pouvez modifier cette liste : pour changer un élixir de rang k (k<4), ajouter un attribut de nom Elixir k, de valeur courante le nom et de valeur maximale l'effet.

      -
    1. Fortifiant : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables. Si vous souhaitez avoir une potion de fortifiant ind\xE9pendament de cette Voie (par exemple achet\xE9e dans une \xE9chope), vous pouvez ajouter un consommable avec l'effet !cof-fortifiant n, o\xF9 n est le rang dans la Voie du forgesort qui a cr\xE9\xE9 la potion.
    2. -
    3. Feu gr\xE9geois : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
    4. -
    5. \xC9lixir de gu\xE9rison : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
    6. -
    7. Potion magique : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
    8. -
    9. \xC9lixirs magiques : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
    10. +
    11. Fortifiant : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables. Si vous souhaitez avoir une potion de fortifiant indépendament de cette Voie (par exemple achetée dans une échope), vous pouvez ajouter un consommable avec l'effet !cof-fortifiant n, où n est le rang dans la Voie du forgesort qui a créé la potion.
    12. +
    13. Feu grégeois : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
    14. +
    15. Élixir de guérison : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
    16. +
    17. Potion magique : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
    18. +
    19. Élixirs magiques : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
    -

    Voie du m\xE9tal

    +

    Voie du métal

      -
    1. Forgeron : Il faut un pr\xE9dicat voieDuMetal pour conna\xEEtre le rang (ou utiliser l'option --valeur). Lancer le sort avec !cof-effet-temp forgeron(L) [[5+@{selected|INT}]] o\xF9 L est le label d'une attaque. Ensuite, chaque fois que cette attaque sera utilis\xE9e, les d\xE9g\xE2ts seront ajout\xE9s. Limitations : si deux attaques utilisent la m\xEAme arme, il faut faire deux fois l'action, une pour chaque attaque.
    2. -
    3. M\xE9tal br\xFBlant : +
    4. Forgeron : Il faut un prédicat voieDuMetal pour connaître le rang (ou utiliser l'option --valeur). Lancer le sort avec !cof-effet-temp forgeron(L) [[5+@{selected|INT}]]L est le label d'une attaque. Ensuite, chaque fois que cette attaque sera utilisée, les dégâts seront ajoutés. Limitations : si deux attaques utilisent la même arme, il faut faire deux fois l'action, une pour chaque attaque.
    5. +
    6. Métal brûlant :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg options --mana 0 --effet ?{Chauffer|une arme,armeBrulante|une armure,armureBrulante} [[5+@{selected|INT}]].
      • -
      • Objet de sort : #Attaque M\xE9tal br\xFBlant --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet ?{Chauffer|une arme,armeBrulante|une armure,armureBrulante} [[5+@{selected|INT}]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg options --mana 0 --effet ?{Chauffer|une arme,armeBrulante|une armure,armureBrulante} [[5+@{selected|INT}]].
      • +
      • Objet de sort : #Attaque Métal brûlant --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet ?{Chauffer|une arme,armeBrulante|une armure,armureBrulante} [[5+@{selected|INT}]]
      - Pour mettre fin \xE0 l'effet (si la cible l\xE2che son arme ou enl\xE8ve son armure), vous pouvez utiliser la macro !cof-effet-temp ?{Se d\xE9barrasser d'une |arme,armeBrulante|armure,armureBrulante} 0 + Pour mettre fin à l'effet (si la cible lâche son arme ou enlève son armure), vous pouvez utiliser la macro !cof-effet-temp ?{Se débarrasser d'une |arme,armeBrulante|armure,armureBrulante} 0
    7. -
    8. Magn\xE9tisme : !cof-effet-temp magnetisme [[3+@{selected|INT}]] --mana 1. L'effet n'est actif que contre les attaques ayant l'option --metal. Il est possible de changer le bonus de DEF apport\xE9 avec l'option --valeur.
    9. -
    10. M\xE9tal hurlant :
    11. +
    12. Magnétisme : !cof-effet-temp magnetisme [[3+@{selected|INT}]] --mana 1. L'effet n'est actif que contre les attaques ayant l'option --metal. Il est possible de changer le bonus de DEF apporté avec l'option --valeur.
    13. +
    14. Métal hurlant :
    15. Endurer : reporter les bonus sur la fiche

    Voie du golem

      -
    1. Grosse t\xEAte : Vous pouvez ajouter un pr\xE9dicat grosseTete. Normalement, le bonus devrait d\xE9pendre des actions du forgesort. Si vous souhaitez le faire, vous pouvez ne pas mettre le pr\xE9dicat, mais juste avant un jet de force pour lequel vous pensez que la grosse t\xEAte s'applique, faire !cof-set-predicate grosseTete true (en s\xE9lectionnant le token du forgesort), puis apr\xE8s le jet faire !cof-set-predicate grosseTete false. Si vous voulez l'ajout de grosse t\xEAte par d\xE9faut, vous pouvez aussi faire l'op\xE9ration dans l'ordre inverse pour les jets pour lesquels vous pensez que le bonus ne peut pas s'appliquer.
    2. -
    3. Golem : ajouter un personnage et un token pour le golem (ne pas oublier le pr\xE9dicat nonVivant pour le golem). Pour les r\xE9parations, utiliser !cof-soin @{selected|token_id} nom_du_golem rangd6+@{selected|INT}. Bien remplacer rang par le rang dans la voie, dans cette commande. Attention, le nom du golem est celui du token repr\xE9sentant le golem, et il ne doit pas contenir de blanc.
    4. -
    5. Protecteur : !cof-interposer permet de s'interposer \xE0 la place de la cible de la derni\xE8re attaque. (Attention, pas de undo pour cette action)
    6. -
    7. Golem sup\xE9rieur : reporter les avantages sur la fiche du golem.
    8. -
    9. Intelligence h\xE9ro\xEFque : reporter sur la fiche
    10. +
    11. Grosse tête : Vous pouvez ajouter un prédicat grosseTete. Normalement, le bonus devrait dépendre des actions du forgesort. Si vous souhaitez le faire, vous pouvez ne pas mettre le prédicat, mais juste avant un jet de force pour lequel vous pensez que la grosse tête s'applique, faire !cof-set-predicate grosseTete true (en sélectionnant le token du forgesort), puis après le jet faire !cof-set-predicate grosseTete false. Si vous voulez l'ajout de grosse tête par défaut, vous pouvez aussi faire l'opération dans l'ordre inverse pour les jets pour lesquels vous pensez que le bonus ne peut pas s'appliquer.
    12. +
    13. Golem : ajouter un personnage et un token pour le golem (ne pas oublier le prédicat nonVivant pour le golem). Pour les réparations, utiliser !cof-soin @{selected|token_id} nom_du_golem rangd6+@{selected|INT}. Bien remplacer rang par le rang dans la voie, dans cette commande. Attention, le nom du golem est celui du token représentant le golem, et il ne doit pas contenir de blanc.
    14. +
    15. Protecteur : !cof-interposer permet de s'interposer à la place de la cible de la dernière attaque. (Attention, pas de undo pour cette action)
    16. +
    17. Golem supérieur : reporter les avantages sur la fiche du golem.
    18. +
    19. Intelligence héroïque : reporter sur la fiche

    Voie des runes

    -

    Ajouter un pr\xE9dicat voieDesRunes pour le personnage avec comme valeur le niveau dans la voie des Runes.

    +

    Ajouter un prédicat voieDesRunes pour le personnage avec comme valeur le niveau dans la voie des Runes.

      -
    1. Runes de d\xE9fense : Rien \xE0 faire, le pr\xE9dicat voieDesRunes est pris en compte dans le calcule de la DEF.
    2. -
    3. Rune d'\xE9nergie : La fabrication des runes de combat est g\xE9r\xE9e par la commande !cof-runes (il est fortement conseill\xE9 de cr\xE9er une ability pour le forgesort). Le script tente de d\xE9tecter quand les runes peuvent \xEAtre utilis\xE9es en combat et propose un bouton (\xE0 la mani\xE8re des points de chance). Lors de chaque nuit (utilisation de la commande !cof-nouveau-jour) toutes les runes sont retir\xE9es, mais le script va sugg\xE9rer des raccourcis au forgesort pour les restaurer facilement \xE0 tous les tokens pr\xE9sents sur la page des joueurs (par personnage, type de rune, et aussi un bouton "Tout renouveler"). Les points de mana sont automatiquement d\xE9compt\xE9s.
    4. -
    5. Rune de protection : cf. ci-dessus. Le script impl\xE9mente par d\xE9faut un maximum de dommages absorb\xE9s par la rune \xE9quivalent au rang du forgesort dans la voie des Runes multipli\xE9 par 10. Il est possible de d\xE9sactiver cette limitation via !cof-options.
    6. -
    7. Rune de puissance : cf. ci-dessus. Cr\xE9er une rune de puissance vous demandera d'indiquer en plus le num\xE9ro de l'arme sur la fiche du propri\xE9taire.
    8. -
    9. Rune de pouvoir : pas de support particulier, cr\xE9er l'objet de pouvoir appropri\xE9.
    10. +
    11. Runes de défense : Rien à faire, le prédicat voieDesRunes est pris en compte dans le calcule de la DEF.
    12. +
    13. Rune d'énergie : La fabrication des runes de combat est gérée par la commande !cof-runes (il est fortement conseillé de créer une ability pour le forgesort). Le script tente de détecter quand les runes peuvent être utilisées en combat et propose un bouton (à la manière des points de chance). Lors de chaque nuit (utilisation de la commande !cof-nouveau-jour) toutes les runes sont retirées, mais le script va suggérer des raccourcis au forgesort pour les restaurer facilement à tous les tokens présents sur la page des joueurs (par personnage, type de rune, et aussi un bouton "Tout renouveler"). Les points de mana sont automatiquement décomptés.
    14. +
    15. Rune de protection : cf. ci-dessus. Le script implémente par défaut un maximum de dommages absorbés par la rune équivalent au rang du forgesort dans la voie des Runes multiplié par 10. Il est possible de désactiver cette limitation via !cof-options.
    16. +
    17. Rune de puissance : cf. ci-dessus. Créer une rune de puissance vous demandera d'indiquer en plus le numéro de l'arme sur la fiche du propriétaire.
    18. +
    19. Rune de pouvoir : pas de support particulier, créer l'objet de pouvoir approprié.

    Guerrier

    Voie du bouclier

      -
    1. Prot\xE9ger un alli\xE9 : !cof-proteger-un-allie @{selected|token_id} @{target|token_id}. Fonctionne aussi si on remplace le target par un nom de token. Le script ne v\xE9rifie pas que le guerrier ne change pas d'alli\xE9 plus d'une fois par tour.
    2. +
    3. Protéger un allié : !cof-proteger-un-allie @{selected|token_id} @{target|token_id}. Fonctionne aussi si on remplace le target par un nom de token. Le script ne vérifie pas que le guerrier ne change pas d'allié plus d'une fois par tour.
    4. Absorber un coup :
        -
      • utiliser !cof-effet-temp absorberUnCoup 1 pour se mettre en position. Attention, \xE7a ne v\xE9rifie pas si le guerrier porte son bouclier.
      • -
      • le script propose un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le guerrier est en position.
      • +
      • utiliser !cof-effet-temp absorberUnCoup 1 pour se mettre en position. Attention, ça ne vérifie pas si le guerrier porte son bouclier.
      • +
      • le script propose un bouton à activer en cas d'attaque réussie alors que le guerrier est en position.
    5. Absorber un sort :
        -
      • utiliser !cof-effet-temp absorberUnSort 1 pour se mettre en position. Attention, \xE7a ne v\xE9rifie pas si le guerrier porte son bouclier.
      • -
      • le script propose un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le guerrier est en position.
      • +
      • utiliser !cof-effet-temp absorberUnSort 1 pour se mettre en position. Attention, ça ne vérifie pas si le guerrier porte son bouclier.
      • +
      • le script propose un bouton à activer en cas d'attaque réussie alors que le guerrier est en position.
    6. -
    7. Armure lourde : Noter l'armure sur la feuille du personnage, et ajouter un pr\xE9dicat armureLourdeGuerrier au personnage. L'annulation du critique ne se produira que si l'armure est port\xE9e et que la valeur totale du bonus de d\xE9fense sup\xE9rieure ou \xE9gale \xE0 7 (le bonus de DEF d'une armure de plaques compl\xE8te).
    8. +
    9. Armure lourde : Noter l'armure sur la feuille du personnage, et ajouter un prédicat armureLourdeGuerrier au personnage. L'annulation du critique ne se produira que si l'armure est portée et que la valeur totale du bonus de défense supérieure ou égale à 7 (le bonus de DEF d'une armure de plaques complète).

    Voie du combat

      -
    1. Vivacit\xE9 : simplement augmenter l'init sur la fiche.
    2. -
    3. D\xE9sarmer : !cof-desarmer @{selected|token_id} @{target|token_id}. On peut utiliser un troisi\xE8me argument optionnel, qui est le label d'une arme par d\xE9faut, au cas o\xF9 le guerrier n'aurait pas d'arme en main.
    4. -
    5. Double attaque : faire deux attaques, avec l'option suppl\xE9mentaire --bonusAttaque -2.
    6. -
    7. Attaque circulaire : faire les attaques normalement, ce n'est pas consid\xE9r\xE9 comme une aoe.
    8. +
    9. Vivacité : simplement augmenter l'init sur la fiche.
    10. +
    11. Désarmer : !cof-desarmer @{selected|token_id} @{target|token_id}. On peut utiliser un troisième argument optionnel, qui est le label d'une arme par défaut, au cas où le guerrier n'aurait pas d'arme en main.
    12. +
    13. Double attaque : faire deux attaques, avec l'option supplémentaire --bonusAttaque -2.
    14. +
    15. Attaque circulaire : faire les attaques normalement, ce n'est pas considéré comme une aoe.
    16. Attaque puissante : #Attaque -1 --avecd12crit --plus 2d6 --seulementContact.
    -

    Voie du ma\xEEtre d'armes

    +

    Voie du maître d'armes

      -
    1. Arme de pr\xE9dilection : il est possible de pr\xE9ciser une famille d'armes de pr\xE9dilection (un peu plus large que dans les r\xE8gles), parmis arc, arbalete, hache, epee, marteau, masse, epieu, poudre, baton et rapiere. Si cela vous convient, ajoutez un pr\xE9dicat armeDePredilection de valeur une de ces familles. Sinon, simplement ajouter le bonus sur les attaques dans la fiche.
    2. -
    3. Science du critique : pour ne pas avoir \xE0 modifier les chances de critique pour toutes les attaques, utiliser un pr\xE9dicat scienceDuCritique. Attention \xE0 ne pas faire \xE7a ET modifier les chances de critiques de l'attaque, car \xE7a s'additionne.
    4. -
    5. Sp\xE9cialisation : reporter le bonus aux DM sur la fiche.
    6. +
    7. Arme de prédilection : il est possible de préciser une famille d'armes de prédilection (un peu plus large que dans les règles), parmis arc, arbalete, hache, epee, marteau, masse, epieu, poudre, baton et rapiere. Si cela vous convient, ajoutez un prédicat armeDePredilection de valeur une de ces familles. Sinon, simplement ajouter le bonus sur les attaques dans la fiche.
    8. +
    9. Science du critique : pour ne pas avoir à modifier les chances de critique pour toutes les attaques, utiliser un prédicat scienceDuCritique. Attention à ne pas faire ça ET modifier les chances de critiques de l'attaque, car ça s'additionne.
    10. +
    11. Spécialisation : reporter le bonus aux DM sur la fiche.
    12. Attaque parfaite : utiliser les options --m2d20 --plus 1d6.
    13. -
    14. Riposte : ajouter un pr\xE9dicat riposteGuerrier. Les actions affich\xE9es en cas de riposte seront normalement une attaque avec l'arme en main, et les attaques naturelles coch\xE9es du personnage. Si cela ne convient pas, \xE9crivez une liste d'actions nomm\xE9e Ripostes.
    15. +
    16. Riposte : ajouter un prédicat riposteGuerrier. Les actions affichées en cas de riposte seront normalement une attaque avec l'arme en main, et les attaques naturelles cochées du personnage. Si cela ne convient pas, écrivez une liste d'actions nommée Ripostes.
    -

    Voie de la r\xE9sistance

    +

    Voie de la résistance

    1. Robustesse : rajouter les PV sur la fiche.
    2. Armure naturelle : rajouter la DEF sur la fiche.
    3. -
    4. Second souffle : Ajouter un pr\xE9dicat secondSouffle permet de faire appara\xEEtre un bouton pour utiliser le second souffle quand le guerrier a perdu des PVs en combat, limite le gain de PVs \xE0 ceux perdus dans le combat en cours, et utilise automatiquement la capacit\xE9 en fin de combat si elle n'a pas \xE9t\xE9 utilis\xE9e. Si cette automatisation ne vous convient pas, vous pouvez utiliser la commande !cof-soin @{selected|token_id} secondSouffle \xE0 la place. Enfin, on peut pr\xE9ciser une valeur pour ce pr\xE9dicat, pour remplacer le niveau + CON (par exemple pour un PNJ).
    5. -
    6. Dur \xE0 cuire : rajouter un pr\xE9dicat durACuire sur la fiche.
    7. -
    8. Constitution h\xE9ro\xEFque : reporter les bonus sur la fiche.
    9. +
    10. Second souffle : Ajouter un prédicat secondSouffle permet de faire apparaître un bouton pour utiliser le second souffle quand le guerrier a perdu des PVs en combat, limite le gain de PVs à ceux perdus dans le combat en cours, et utilise automatiquement la capacité en fin de combat si elle n'a pas été utilisée. Si cette automatisation ne vous convient pas, vous pouvez utiliser la commande !cof-soin @{selected|token_id} secondSouffle à la place. Enfin, on peut préciser une valeur pour ce prédicat, pour remplacer le niveau + CON (par exemple pour un PNJ).
    11. +
    12. Dur à cuire : rajouter un prédicat durACuire sur la fiche.
    13. +
    14. Constitution héroïque : reporter les bonus sur la fiche.

    Voie du soldat

      -
    1. Posture de combat : !cof-posture-de-combat bonus attr1 attr2, o\xF9 les deux attr peuvent \xEAtre soit DEF soit ATT soit DM, et le bonus est retir\xE9 au premier attribut pour \xEAtre ajout\xE9 au second. Le bonus peut \xEAtre limit\xE9 si le guerrier a un pr\xE9dicat voieDuSoldat qui indique son rang dans la voie. Exemple d'utilisation : !cof-posture-de-combat ?{Bonus} ?{Baisser|D\xE9fense,DEF|Attaque,ATT|D\xE9g\xE2ts,DM} ?{Augmenter|D\xE9fense,DEF|Attaque,ATT|D\xE9g\xE2ts,DM}. Normalement, la r\xE8gle fait d\xE9cider de sa posture au guerrier \xE0 chaque tour, mais en pratique, il en change assez rarement. Une posture de combat reste donc active jusqu'\xE0 la fin du combat ou jusqu'\xE0 ce qu'on en change (elle est neutre si on a le m\xEAme attribut \xE0 buffer et d\xE9buffer).
    2. -
    3. Combat en phalange : ajouter un pr\xE9dicat combatEnPhalange. Les bonus seront ajout\xE9s automatiquement en fonctions des alli\xE9s d\xE9finis selon cette m\xE9thode.
    4. -
    5. Prouesse : ajouter un pr\xE9dicat prouesse (on peut y associer un nombre, si on souhaite plus d'une utilisation par tour). Le script g\xE9n\xE9rera automatiquement les boutons Prouesse sur les test appropri\xE9s.
    6. -
    7. Dernier rempart : pas de support particulier, le MJ doit g\xE9rer les attaques suppl\xE9mentaires.
    8. -
    9. Force h\xE9ro\xEFque : reporter sur la fiche.
    10. +
    11. Posture de combat : !cof-posture-de-combat bonus attr1 attr2, où les deux attr peuvent être soit DEF soit ATT soit DM, et le bonus est retiré au premier attribut pour être ajouté au second. Le bonus peut être limité si le guerrier a un prédicat voieDuSoldat qui indique son rang dans la voie. Exemple d'utilisation : !cof-posture-de-combat ?{Bonus} ?{Baisser|Défense,DEF|Attaque,ATT|Dégâts,DM} ?{Augmenter|Défense,DEF|Attaque,ATT|Dégâts,DM}. Normalement, la règle fait décider de sa posture au guerrier à chaque tour, mais en pratique, il en change assez rarement. Une posture de combat reste donc active jusqu'à la fin du combat ou jusqu'à ce qu'on en change (elle est neutre si on a le même attribut à buffer et débuffer).
    12. +
    13. Combat en phalange : ajouter un prédicat combatEnPhalange. Les bonus seront ajoutés automatiquement en fonctions des alliés définis selon cette méthode.
    14. +
    15. Prouesse : ajouter un prédicat prouesse (on peut y associer un nombre, si on souhaite plus d'une utilisation par tour). Le script générera automatiquement les boutons Prouesse sur les test appropriés.
    16. +
    17. Dernier rempart : pas de support particulier, le MJ doit gérer les attaques supplémentaires.
    18. +
    19. Force héroïque : reporter sur la fiche.

    Invocateur

    Voie de la conjuration

      -
    1. Conjuration de pr\xE9dateur : !cof-conjuration-de-predateur --mana 0.
    2. -
    3. Conjuration renforc\xE9e : vous pouvez soit utiliser un pr\xE9dicat voieDeLaConjuration, de valeur le rang dans la voie, soit ajouter ce rang en premier argument de !cof-conjuration-de-predateur.
    4. -
    5. Conjuration d'arm\xE9e : !cof-conjuration-armee --limiteParJour 1 --mana 1. Le niveau de puissance de l'arm\xE9e et d\xE9termin\xE9 par la valeur d'un pr\xE9dicat voieDeLaConjuration, ou sinon par un argument optionnel qui donne les DMs inflig\xE9s par l'arm\xE9e (par exemple, !cof-conjuration-armee 2d6). L'arm\xE9e va appara\xEEtre comme un token normal, mais avec une aura de 20m de cot\xE9 qui repr\xE9sente la place qu'elle occupe. Pour les d\xE9g\xE2ts qu'elle inflige, utiliser son attaque sur toutes les cibles d\xE9sign\xE9es par l'invocateur. Pour faire dispara\xEEtre l'arm\xE9e, il suffit de la tuer (par exemple en utilisant !cof-set-state mort true). Tous les personnages dans la zone de l'arm\xE9e et qui ne sont pas alli\xE9s de l'invocateurs ont automatiquement une nouvelle action dans leur liste pour attaquer l'arm\xE9e. Cette action leur permet aussi de b\xE9n\xE9ficier d'une division des DM par 2 lorsque l'arm\xE9e les attaque.
    6. +
    7. Conjuration de prédateur : !cof-conjuration-de-predateur --mana 0.
    8. +
    9. Conjuration renforcée : vous pouvez soit utiliser un prédicat voieDeLaConjuration, de valeur le rang dans la voie, soit ajouter ce rang en premier argument de !cof-conjuration-de-predateur.
    10. +
    11. Conjuration d'armée : !cof-conjuration-armee --limiteParJour 1 --mana 1. Le niveau de puissance de l'armée et déterminé par la valeur d'un prédicat voieDeLaConjuration, ou sinon par un argument optionnel qui donne les DMs infligés par l'armée (par exemple, !cof-conjuration-armee 2d6). L'armée va apparaître comme un token normal, mais avec une aura de 20m de coté qui représente la place qu'elle occupe. Pour les dégâts qu'elle inflige, utiliser son attaque sur toutes les cibles désignées par l'invocateur. Pour faire disparaître l'armée, il suffit de la tuer (par exemple en utilisant !cof-set-state mort true). Tous les personnages dans la zone de l'armée et qui ne sont pas alliés de l'invocateurs ont automatiquement une nouvelle action dans leur liste pour attaquer l'armée. Cette action leur permet aussi de bénéficier d'une division des DM par 2 lorsque l'armée les attaque.
    -

    Voie de l'entit\xE9

    +

    Voie de l'entité

      -
    1. Invocation d'une entit\xE9 : ajouter la fiche correspondante.
    2. -
    3. Lien magique : pour l'instant, g\xE9rer \xE0 la main le transfert de d\xE9g\xE2ts.
    4. -
    5. Am\xE9lioration : ajuster la fiche de l'entit\xE9.
    6. +
    7. Invocation d'une entité : ajouter la fiche correspondante.
    8. +
    9. Lien magique : pour l'instant, gérer à la main le transfert de dégâts.
    10. +
    11. Amélioration : ajuster la fiche de l'entité.

    Voie du familier

      -
    1. Familier : cr\xE9er un token pour le familier, avec vue et control\xE9 par le joueur. Le partage des PV n'est pas g\xE9r\xE9. Pour le bonus en initiative, ajouter un pr\xE9dicat familier, avec comme valeur le nom du compagnon (doit \xEAtre exactement le m\xEAme que celui du token du compagnon). Cela automatise l'initiative quand le familier est pr\xE9sent.
    2. -
    3. R\xE9sistance : ajouter la valeur de RD sur la fiche du familier.
    4. -
    5. Sens d\xE9velopp\xE9s : ajouter un pr\xE9dicat perception de valeur 5 (ou augmenter ce pr\xE9dicat, si il existe d\xE9j\xE0), et ajouter un pr\xE9dicat visionDansLeNoir de valeur 20 (40 si le personnage dispose d\xE9j\xE0 de la vision dans le noir).
    6. +
    7. Familier : créer un token pour le familier, avec vue et controlé par le joueur. Le partage des PV n'est pas géré. Pour le bonus en initiative, ajouter un prédicat familier, avec comme valeur le nom du compagnon (doit être exactement le même que celui du token du compagnon). Cela automatise l'initiative quand le familier est présent.
    8. +
    9. Résistance : ajouter la valeur de RD sur la fiche du familier.
    10. +
    11. Sens développés : ajouter un prédicat perception de valeur 5 (ou augmenter ce prédicat, si il existe déjà), et ajouter un prédicat visionDansLeNoir de valeur 20 (40 si le personnage dispose déjà de la vision dans le noir).

    Voie des mutations

    1. Mutation offensive :
      • !cof-effet-temp mutationOffensive [[5+@{selected|CHA}]] --mana 0 pour lancer le sort
      • -
      • Ajouter une attaque sur la fiche utilisant l'attaque au contact, dommages 1d6+FOR+3, type Naturel, d\xE9g\xE2ts magiques, options --si etat mutationOffensive
      • +
      • Ajouter une attaque sur la fiche utilisant l'attaque au contact, dommages 1d6+FOR+3, type Naturel, dégâts magiques, options --si etat mutationOffensive
      • Pour un objet de sort, vous pouvez utiliser une action avec le code #Attaque Mutation offensive --toucher [[@{selected|ATKCAC}]] --dm 1d6+[[3+@{selected|FOR}]] --magique --naturel --si etat mutationOffensive
    2. -
    3. Mutation protectrice : !cof-effet ?{Mutation protectrice|Cuirasse,mutationCuirasse|\xC9cailles rouges,mutationEcaillesRouges|Fourrure violette,mutationFourrureViolette|Ou\xEFes,mutationOuies|Sang noir,mutationSangNoir} true --classeEffet mutationProtectrice --mana 0. Pour la valeur de protection de la cuirasse, vous pouvez soit utiliser un pr\xE9dicat voieDesMutations, de valeur le rang dans la voie, soit remplacer mutationCuirasse par mutationCuirasse --valeur rang. Pour enlever la mutation, le MJ peut ensuite simplement s\xE9lectionner le personnage et utiliser !cof-fin-classe-effet mutationProtectrice.
    4. -
    5. Surpuissance physique : !cof-effet ?{Surpuissance physique|Muscles hypertrophi\xE9s,mutationMusclesHypertrophies|Silhouette filiforme,mutationSilhouetteFiliforme|Silhouette massive,mutationSilhouetteMassive} true --classeEffet surpuissancePhysique --mana 1. Pour enlever la mutation, le MJ peut ensuite simplement s\xE9lectionner le personnage et utiliser !cof-fin-classe-effet surpuissancePhysique.
    6. -
    7. Adaptation motrice : pas d'autre support que !cof-lancer-sort --message se fait pousser ?{Adaptation motrice ?|Ailes|des ailes|Pattes demesur\xE9es,des pattes demesur\xE9es|Queue de poisson,une queue de poisson} --mana 2
    8. +
    9. Mutation protectrice : !cof-effet ?{Mutation protectrice|Cuirasse,mutationCuirasse|Écailles rouges,mutationEcaillesRouges|Fourrure violette,mutationFourrureViolette|Ouïes,mutationOuies|Sang noir,mutationSangNoir} true --classeEffet mutationProtectrice --mana 0. Pour la valeur de protection de la cuirasse, vous pouvez soit utiliser un prédicat voieDesMutations, de valeur le rang dans la voie, soit remplacer mutationCuirasse par mutationCuirasse --valeur rang. Pour enlever la mutation, le MJ peut ensuite simplement sélectionner le personnage et utiliser !cof-fin-classe-effet mutationProtectrice.
    10. +
    11. Surpuissance physique : !cof-effet ?{Surpuissance physique|Muscles hypertrophiés,mutationMusclesHypertrophies|Silhouette filiforme,mutationSilhouetteFiliforme|Silhouette massive,mutationSilhouetteMassive} true --classeEffet surpuissancePhysique --mana 1. Pour enlever la mutation, le MJ peut ensuite simplement sélectionner le personnage et utiliser !cof-fin-classe-effet surpuissancePhysique.
    12. +
    13. Adaptation motrice : pas d'autre support que !cof-lancer-sort --message se fait pousser ?{Adaptation motrice ?|Ailes|des ailes|Pattes demesurées,des pattes demesurées|Queue de poisson,une queue de poisson} --mana 2

    Voie des portes

    1. Raccourci : pas de support autre que !cof-lancer-sort lance un sort de Raccourci --mana 0
    2. -
    3. Porte artificielle : pas de support autre que !cof-lancer-sort lance un sort de Porte artificielle --mana 0. Un jour, je compte lui faire cr\xE9er une porte.
    4. +
    5. Porte artificielle : pas de support autre que !cof-lancer-sort lance un sort de Porte artificielle --mana 0. Un jour, je compte lui faire créer une porte.
    6. Manoir d'outre-tombe : pas d'autre support que !cof-lancer-sort enchante une porte --mana 1
    7. Enkystement lointain : !cof-enkystement-lointain @{selected|token_id} @{target|token_id} --portee 20 --mana 2 --limiteParCombat 1 enkystement.
    8. Porte dimensionnelle : pas de support pour l'instant.
    9. @@ -1483,14 +1487,14 @@

      Magicien

      Voie de la magie des arcanes

        -
      1. Agrandissement : !cof-effet-temp agrandissement [[5+@{selected|INT}]] --target @{target|token_id} --lanceur @{selected|token_id} --portee 0 --mana 0. Si vous souhaitez qu'une arme puisse \xEAtre tenue \xE0 une main quand le personnage est agrandi, ajoutez \xE0 l'arme le pr\xE9dicat armeDeGrand.
      2. -
      3. Forme gazeuse : !cof-effet-temp formeGazeuse [[1d4 + @{selected|INT}]] --mana 0. Au MJ de faire attention que sous cette forme, toutes les capacit\xE9s sont interdites.
      4. -
      5. H\xE2te : !cof-effet-temp hate [[1d6+@{selected|INT}]] --mana 1, au MJ de g\xE9rer ensuite les actions possibles chaque tour.
      6. -
      7. T\xE9l\xE9portation : Pas de support autre que !cof-lancer-sort se t\xE9l\xE9porte (\xE0 [[@{selected|INTELLIGENCE}*10]] m maximum) --mana 2.
      8. -
      9. D\xE9sint\xE9gration : +
      10. Agrandissement : !cof-effet-temp agrandissement [[5+@{selected|INT}]] --target @{target|token_id} --lanceur @{selected|token_id} --portee 0 --mana 0. Si vous souhaitez qu'une arme puisse être tenue à une main quand le personnage est agrandi, ajoutez à l'arme le prédicat armeDeGrand.
      11. +
      12. Forme gazeuse : !cof-effet-temp formeGazeuse [[1d4 + @{selected|INT}]] --mana 0. Au MJ de faire attention que sous cette forme, toutes les capacités sont interdites.
      13. +
      14. Hâte : !cof-effet-temp hate [[1d6+@{selected|INT}]] --mana 1, au MJ de gérer ensuite les actions possibles chaque tour.
      15. +
      16. Téléportation : Pas de support autre que !cof-lancer-sort se téléporte (à [[@{selected|INTELLIGENCE}*10]] m maximum) --mana 2.
      17. +
      18. Désintégration :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 5D6+INT, port\xE9e 20, type Sortil\xE8ge, d\xE9g\xE2ts magiques, options --mana 3.
        • -
        • Objet de sort : #Attaque D\xE9sint\xE9gration --toucher [[@{selected|ATKMAG}]] --dm 5d6+[[@{selected|INT}]] --magique --portee 20 --sortilege
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 5D6+INT, portée 20, type Sortilège, dégâts magiques, options --mana 3.
        • +
        • Objet de sort : #Attaque Désintégration --toucher [[@{selected|ATKMAG}]] --dm 5d6+[[@{selected|INT}]] --magique --portee 20 --sortilege
      @@ -1498,519 +1502,527 @@

      Voie de la magie destructrice

      1. Projectile magique :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4, port\xE9e 50, type Sortil\xE8ge, modificateurs auto d\xE9g\xE2ts magiques, options --mana 0 --fx beam-magic.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4, portée 50, type Sortilège, modificateurs auto dégâts magiques, options --mana 0 --fx beam-magic.
        • Objet de sort : #Attaque Projectile Magique --auto --dm 1d4 --magique --portee 50 --sortilege --fx beam-magic
      2. Rayon affaiblissant :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateurs pasDeDmg d\xE9g\xE2ts magiques, options --mana 0 --effet rayonAffaiblissant [[1d6+@{selected|INT}]] --fx splatter-magic.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateurs pasDeDmg dégâts magiques, options --mana 0 --effet rayonAffaiblissant [[1d6+@{selected|INT}]] --fx splatter-magic.
        • Objet de sort : #Attaque Rayon affaiblissant --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --effet rayonAffaiblissant [[1d6+@{selected|INT}]] --fx splatter-magic
      3. -
      4. Fl\xE8che enflamm\xE9e : +
      5. Flèche enflammée :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, port\xE9e 30, type Sortil\xE8ge, d\xE9g\xE2ts feu, options --mana 1 --fx beam-fire --feu --enflamme.
        • -
        • Objet de sort : #Attaque Fl\xE8che enflamm\xE9e --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --feu --portee 30 --sortilege --fx beam-fire --enflamme
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, portée 30, type Sortilège, dégâts feu, options --mana 1 --fx beam-fire --feu --enflamme.
        • +
        • Objet de sort : #Attaque Flèche enflammée --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --feu --portee 30 --sortilege --fx beam-fire --enflamme
      6. Boule de feu :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 4d6+INT, port\xE9e 30, type Sortil\xE8ge, d\xE9g\xE2ts feu, options --mana 2 --demiAuto --disque 6 --psave DEX [[10+@{selected|INT}]] --targetFx explode-fire.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 4d6+INT, portée 30, type Sortilège, dégâts feu, options --mana 2 --demiAuto --disque 6 --psave DEX [[10+@{selected|INT}]] --targetFx explode-fire.
        • Objet de sort : #Attaque Boule de feu --toucher [[@{selected|ATKMAG}]] --dm 4d6+[[@{selected|INT}]] --feu --magique --portee 30 --sortilege --demiAuto --disque 6 --psave DEX [[10+@{selected|INT}]] --targetFx explode-fire
      7. -
      8. Rituel de puissance : faire l'appel aux attaques avec --avecd12crit --plus 2d6. On peut par exemple ajouter ceci dans les options des attaques lorsque le Rituel peut \xEAtre utilis\xE9 :?{Rituel de puissance?|Non,&#32;|Oui,--avecd12crit --plus 2d6}
      9. +
      10. Rituel de puissance : faire l'appel aux attaques avec --avecd12crit --plus 2d6. On peut par exemple ajouter ceci dans les options des attaques lorsque le Rituel peut être utilisé :?{Rituel de puissance?|Non,&#32;|Oui,--avecd12crit --plus 2d6}
      -

      Voie de la magie \xE9l\xE9mentaire

      +

      Voie de la magie élémentaire

      1. Asphyxie :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge,modificateurs pasDeDmg, options --mana 0 --effet asphyxie [[1+@{selected|INT}]].
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège,modificateurs pasDeDmg, options --mana 0 --effet asphyxie [[1+@{selected|INT}]].
        • Objet de sort : #Attaque Asphyxie --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet asphyxie [[1+@{selected|INT}]]
      2. -
      3. Protection contre les \xE9l\xE9ments : ajouter un pr\xE9dicat voieDeLaMagieElementaire avec comme valeur le rang dans la voie. Pour lancer le sort, faire !cof-effet-temp protectionContreLesElements [[5+@{selected|INT}]] --mana 0. Notez que si vous utilisez une option --valeur \xE0 la place d'utiliser le pr\xE9dicat, la RD sera cette valeur multipli\xE9e par 2.
      4. -
      5. Arme enflamm\xE9e : Lancer le sort avec !cof-effet-temp armeEnflammee [[5+@{selected|INT}]] --lanceur @{selected|token_id} --target @{target|token_id} --portee 0 --mana 1. Il faut que la cible tienne une arme en main (voir !cof-degainer). Limitations : si deux attaques utilisent la m\xEAme arme, il faut faire deux fois l'action, une pour chaque attaque. Si vous souhaitez faire le m\xEAme effet mais avec des d\xE9g\xE2ts de froid, vous pouvez utiliser armeGlacee \xE0 la place.
      6. -
      7. Respiration aquatique : pas de support autre que !cof-lancer-sort lance un sort de respiration aquatique (dur\xE9e 10 minutes, sur soi plus [[@{selected|INT}]] compagnons) --mana 2.
      8. -
      9. Peau de pierre : !cof-effet-temp peauDePierreMag [[5+@{selected|INT}]] --mana 3. Le script va appliquer une RD de [5+Mod. d'INT] en dernier lieu, et compter le maximum des 40 d\xE9g\xE2ts par d\xE9faut. Il est possible de changer la valeur de la RD et le nombre de points de d\xE9g\xE2ts absorb\xE9s en ajoutant l'option --valeur rd absorbe. \xC0 noter que le script rajoute +1 \xE0 la RD et +5 au total de d\xE9g\xE2ts absorb\xE9s en cas de magie puissante, ou par point de mana depens\xE9 en magie intense.
      10. +
      11. Protection contre les éléments : ajouter un prédicat voieDeLaMagieElementaire avec comme valeur le rang dans la voie. Pour lancer le sort, faire !cof-effet-temp protectionContreLesElements [[5+@{selected|INT}]] --mana 0. Notez que si vous utilisez une option --valeur à la place d'utiliser le prédicat, la RD sera cette valeur multipliée par 2.
      12. +
      13. Arme enflammée : Lancer le sort avec !cof-effet-temp armeEnflammee [[5+@{selected|INT}]] --lanceur @{selected|token_id} --target @{target|token_id} --portee 0 --mana 1. Il faut que la cible tienne une arme en main (voir !cof-degainer). Limitations : si deux attaques utilisent la même arme, il faut faire deux fois l'action, une pour chaque attaque. Si vous souhaitez faire le même effet mais avec des dégâts de froid, vous pouvez utiliser armeGlacee à la place.
      14. +
      15. Respiration aquatique : pas de support autre que !cof-lancer-sort lance un sort de respiration aquatique (durée 10 minutes, sur soi plus [[@{selected|INT}]] compagnons) --mana 2.
      16. +
      17. Peau de pierre : !cof-effet-temp peauDePierreMag [[5+@{selected|INT}]] --mana 3. Le script va appliquer une RD de [5+Mod. d'INT] en dernier lieu, et compter le maximum des 40 dégâts par défaut. Il est possible de changer la valeur de la RD et le nombre de points de dégâts absorbés en ajoutant l'option --valeur rd absorbe. À noter que le script rajoute +1 à la RD et +5 au total de dégâts absorbés en cas de magie puissante, ou par point de mana depensé en magie intense.

      Voie de la magie protectrice

      1. Armure du mage : !cof-effet-combat armureDuMage --mana 0.
      2. Chute ralentie : pas de support autre que !cof-lancer-sort lance un sort de Chute ralentie --mana 0
      3. Flou : !cof-effet-temp flou [[1d4+@{selected|INT}]] --mana 1.
      4. -
      5. Cercle de protection : Le script ne g\xE8re pas le cercle en lui-m\xEAme, mais vous pouvez cr\xE9er deux abilities. +
      6. Cercle de protection : Le script ne gère pas le cercle en lui-même, mais vous pouvez créer deux abilities.
        • !cof-effet-temp cercleDeProtection 100 --target @{target|token_id} --lanceur @{selected|token_id} --valeur @{selected|token_id} et cibler un personnage pour lui appliquer l'effet.
        • !cof-effet-temp cercleDeProtection fin --target @{target|token_id} --lanceur @{selected|token_id} pour supprimer l'effet sur un personnage.
        - Le script proposera alors automatiquement \xE0 ces personnages un bouton avec le nom du magicien si une cible prot\xE9g\xE9e est cibl\xE9e par une attaque magique. Le jet d'attaque magique oppos\xE9 sera automatis\xE9. Si vous utilisez les options de mana, rajoutez --mana {Co\xFBt ?} \xE0 la premi\xE8re ability. Indiquer le co\xFBt au lancement, et 0 pour les autres applications. + Le script proposera alors automatiquement à ces personnages un bouton avec le nom du magicien si une cible protégée est ciblée par une attaque magique. Le jet d'attaque magique opposé sera automatisé. Si vous utilisez les options de mana, rajoutez --mana {Coût ?} à la première ability. Indiquer le coût au lancement, et 0 pour les autres applications.
      7. -
      8. Arr\xEAt du temps : pas de support autre que !cof-lancer-sort arr\xEAte le temps pour [[1d6+@{selected|INT}]] tours --mana 3
      9. +
      10. Arrêt du temps : pas de support autre que !cof-lancer-sort arrête le temps pour [[1d6+@{selected|INT}]] tours --mana 3

      Voie de la magie universelle

        -
      1. Lumi\xE8re : !cof-lumiere @{target|token_id} 20 --mana 0. On peut utiliser une cible qui ne soit qu'un personnage sans PV, et dans ce cas le token dispara\xEEt, et pour \xE9teindre la lumi\xE8re, le MJ doit supprimer le token dans le layer de l'\xE9clairage dynamique. Si la cible est un personnage avec des PV, alors la lumi\xE8re se d\xE9placera avec lui, et pour \xE9teindre la lumi\xE8re, il faut s\xE9clectionner le ou les tokens et lancer !cof-eteindre-lumiere lumiere.
      2. -
      3. D\xE9tection de la magie : pas de support autre que !cof-lancer-sort lance un sort de D\xE9tection de la Magie --mana 0.
      4. -
      5. Invisibilit\xE9 : utiliser !cof-set-state invisible true --message se rend invisible --messageMJ l'invisibilit\xE9 va durer [[1d6+@{selected|INT}]] minutes --mana 1. Pour les ennemis, mettre dans le layer gm, pour les joueurs, ne pas les cibler. Reste le probl\xE8me des AOE...
      6. +
      7. Lumière : !cof-lumiere @{target|token_id} 20 --mana 0. On peut utiliser une cible qui ne soit qu'un personnage sans PV, et dans ce cas le token disparaît, et pour éteindre la lumière, le MJ doit supprimer le token dans le layer de l'éclairage dynamique. Si la cible est un personnage avec des PV, alors la lumière se déplacera avec lui, et pour éteindre la lumière, il faut séclectionner le ou les tokens et lancer !cof-eteindre-lumiere lumiere.
      8. +
      9. Détection de la magie : pas de support autre que !cof-lancer-sort lance un sort de Détection de la Magie --mana 0.
      10. +
      11. Invisibilité : utiliser !cof-set-state invisible true --message se rend invisible --messageMJ l'invisibilité va durer [[1d6+@{selected|INT}]] minutes --mana 1. Pour les ennemis, mettre dans le layer gm, pour les joueurs, ne pas les cibler. Reste le problème des AOE...
      12. Vol : pas de support autre que !cof-lancer-sort vole --messageMJ le vol va durer [[1d6+@{selected|INT}]] minutes --mana 2
      13. -
      14. Intelligence h\xE9ro\xEFque : reporter sur la fiche
      15. +
      16. Intelligence héroïque : reporter sur la fiche

      Moine

      -

      Voie de l\x2019\xE9nergie vitale

      +

      Voie de l’énergie vitale

        -
      1. Main d'\xE9nergie : utiliser l'attaque \xE0 mains nues avec l'option --mainsDEnergie. D'autre part, ajouter l'option --magique \xE0 toutes les attaques \xE0 mains nues.
      2. -
      3. Pression mortelle : utiliser l'option --pointsVitaux pour ne pas infliger imm\xE9diatement les d\xE9g\xE2ts, et l'option --pressionMortelle pour lib\xE9rer les d\xE9g\xE2ts.
      4. -
      5. Invuln\xE9rable: utiliser un pr\xE9dicat invulnerable
      6. -
      7. Projection du ki : ajouter simplement l'attaque sur la fiche, et utiliser le type d'attaque Sortilege et le type de d\xE9g\xE2ts magique.
      8. -
      9. Asc\xE9tisme : noter la constitution comme une caract\xE9ristique sup\xE9rieure sur la fiche.
      10. +
      11. Main d'énergie : utiliser l'attaque à mains nues avec l'option --mainsDEnergie. D'autre part, ajouter l'option --magique à toutes les attaques à mains nues.
      12. +
      13. Pression mortelle : utiliser l'option --pointsVitaux pour ne pas infliger immédiatement les dégâts, et l'option --pressionMortelle pour libérer les dégâts.
      14. +
      15. Invulnérable: utiliser un prédicat invulnerable
      16. +
      17. Projection du ki : ajouter simplement l'attaque sur la fiche, et utiliser le type d'attaque Sortilege et le type de dégâts magique.
      18. +
      19. Ascétisme : noter la constitution comme une caractéristique supérieure sur la fiche.
      -

      Voie de la ma\xEEtrise

      +

      Voie de la maîtrise

        -
      1. Esquive du singe : mettre \xE0 jour la d\xE9fense sur la fiche, et ajouter une comp\xE9tence acrobatie avec le bonus donn\xE9 par la capacit\xE9.
      2. -
      3. Morsure du serpent : pour ne pas avoir \xE0 modifier les chances de critique pour toutes les attaques au contact, utiliser un pr\xE9dicat morsureDuSerpent. Attention \xE0 ne pas faire \xE7a ET modifier les chances de critiques de l'attaque, car \xE7a s'additionne. (En revanche, pas de soucis avec la science du critique).
      4. -
      5. Griffes du tigre : rajouter l'option --explodeMax aux attaques \xE0 mains nues.
      6. -
      7. Fureur du dragon : Cr\xE9er une action : !cof-explosion Fureur du dragon --auto --portee 0 --disque 1 --saufAllies --dm 2D6+[[@{selected|FOR}]] --etat renverse --save FOR 10 --limiteParCombat 1 fureurDuDragon
      8. +
      9. Esquive du singe : mettre à jour la défense sur la fiche, et ajouter une compétence acrobatie avec le bonus donné par la capacité.
      10. +
      11. Morsure du serpent : pour ne pas avoir à modifier les chances de critique pour toutes les attaques au contact, utiliser un prédicat morsureDuSerpent. Attention à ne pas faire ça ET modifier les chances de critiques de l'attaque, car ça s'additionne. (En revanche, pas de soucis avec la science du critique).
      12. +
      13. Griffes du tigre : rajouter l'option --explodeMax aux attaques à mains nues.
      14. +
      15. Fureur du dragon : Créer une action : !cof-explosion Fureur du dragon --auto --portee 0 --disque 1 --saufAllies --dm 2D6+[[@{selected|FOR}]] --etat renverse --save FOR 10 --limiteParCombat 1 fureurDuDragon
      16. Moment de perfection : !cof-effet-temp momentDePerfection 1 --limiteParCombat 1
      -

      Voie de la m\xE9ditation

      +

      Voie de la méditation

        -
      1. Pacifisme : ajouter un pr\xE9dicat pacifisme. Il est possible d'y associer une valeur pour appliquer un bonus \xE0 la d\xE9fense diff\xE9rent de 5.
      2. -
      3. Transe de gu\xE9rison : !cof-transe-guerison
      4. -
      5. Ma\xEEtrise du ki : adapter les valeurs de DEF et init
      6. +
      7. Pacifisme : ajouter un prédicat pacifisme. Il est possible d'y associer une valeur pour appliquer un bonus à la défense différent de 5.
      8. +
      9. Transe de guérison : !cof-transe-guerison
      10. +
      11. Maîtrise du ki : adapter les valeurs de DEF et init
      12. Projection mentale : aucun support
      13. -
      14. Sagesse h\xE9ro\xEFque : reporter sur la fiche
      15. +
      16. Sagesse héroïque : reporter sur la fiche

      Voie du poing

        -
      1. Poings de fer : simplement enlever le --tempDmg et ajuster les d\xE9g\xE2ts
      2. -
      3. Parade de projectiles : ajouter un pr\xE9dicat paradeDeProjectiles. Le script proposera automatiquement un bouton pour parer l'attaque dans les cas appropri\xE9s.
      4. +
      5. Poings de fer : simplement enlever le --tempDmg et ajuster les dégâts
      6. +
      7. Parade de projectiles : ajouter un prédicat paradeDeProjectiles. Le script proposera automatiquement un bouton pour parer l'attaque dans les cas appropriés.
      8. Peau de fer : ajuster la DEF sur la fiche.
      9. -
      10. D\xE9luge de coups : le MJ g\xE8re le nombre d'attaques. Pour les attaques au d12, utiliser l'option --avecd12.
      11. +
      12. Déluge de coups : le MJ gère le nombre d'attaques. Pour les attaques au d12, utiliser l'option --avecd12.
      13. Puissance du ki : utiliser les options --avecd12crit --plus 2d6.

      Voie du vent

        -
      1. Pas du vent : un pr\xE9dicat pasDuVent avec comme valeur le rang dans la voie permet d'augmenter automatiquement l'initiative. Pour le reste, il n'y a pas de support particulier.
      2. -
      3. Course du vent : g\xE9r\xE9 par le MJ.
      4. +
      5. Pas du vent : un prédicat pasDuVent avec comme valeur le rang dans la voie permet d'augmenter automatiquement l'initiative. Pour le reste, il n'y a pas de support particulier.
      6. +
      7. Course du vent : géré par le MJ.
      8. Course des airs : pas de support.
      9. -
      10. L\xE9vitation : pas de support.
      11. +
      12. Lévitation : pas de support.
      13. Passe-muraille : pas de support.
      -

      N\xE9cromancien

      +

      Nécromancien

      -

      Voie du d\xE9mon

      +

      Voie du démon

        -
      1. Mal\xE9diction : +
      2. Malédiction :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg malediction, options --mana 0.
        • -
        • Objet de sort : #Attaque Mal\xE9diction --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --malediction
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg malediction, options --mana 0.
        • +
        • Objet de sort : #Attaque Malédiction --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --malediction
      3. Aspect de la succube :
        • !cof-effet-temp aspectDeLaSuccube [[5+@{selected|INT}]] --mana 0 pour lancer le sort
        • -
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4+CHA, port\xE9e 0, type Sortil\xE8ge, d\xE9g\xE2ts de drain, options --si etat aspectDeLaSuccube.
        • +
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4+CHA, portée 0, type Sortilège, dégâts de drain, options --si etat aspectDeLaSuccube.
        • Pour un objet de sort, le code sera #Attaque Attaque de la succube --toucher [[@{selected|ATKMAG}]] --dm 1d4+[[@{selected|CHA}]] --magique --portee 0 --sortilege --si etat aspectDeLaSuccube --drain
      4. -
      5. Pacte sanglant : cr\xE9er un pr\xE9dicat pacteSanglant de valeur 3 (rang 3) ou 5 (rang 5). Le script va automatiser l'ajout de boutons sur tous les tests a posteriori, y compris sur les attaques qui ciblent le personnage. Aux joueurs de s'accorder sur la n\xE9cessit\xE9 d'une d\xE9claration a priori n\xE9cessaire pour l'utilisation de la capacit\xE9.
      6. -
      7. Aspect du d\xE9mon : +
      8. Pacte sanglant : créer un prédicat pacteSanglant de valeur 3 (rang 3) ou 5 (rang 5). Le script va automatiser l'ajout de boutons sur tous les tests a posteriori, y compris sur les attaques qui ciblent le personnage. Aux joueurs de s'accorder sur la nécessité d'une déclaration a priori nécessaire pour l'utilisation de la capacité.
      9. +
      10. Aspect du démon :
        • !cof-effet-temp aspectDuDemon [[5+@{selected|INT}]] --mana 2 pour lancer le sort
        • -
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+4, port\xE9e 0, type Sortil\xE8ge, d\xE9g\xE2ts magiques, options --si etat aspectDuDemon
        • -
        • Pour un objet de sort, l'attaque pourra avoir le code #Attaque Attaque du d\xE9mon --toucher [[@{selected|ATKMAG}]] --dm 1d6+4 --magique --portee 0 --sortilege --si etat aspectDuDemon
        • +
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+4, portée 0, type Sortilège, dégâts magiques, options --si etat aspectDuDemon
        • +
        • Pour un objet de sort, l'attaque pourra avoir le code #Attaque Attaque du démon --toucher [[@{selected|ATKMAG}]] --dm 1d6+4 --magique --portee 0 --sortilege --si etat aspectDuDemon
      11. -
      12. Invocation d'un d\xE9mon : !cof-invoquer-demon @{selected|token_id} --mana 3
      13. +
      14. Invocation d'un démon : !cof-invoquer-demon @{selected|token_id} --mana 3

      Voie de la mort

        -
      1. Siphon des \xE2mes : ajouter un pr\xE9dicat siphonDesAmes. Par d\xE9faut, si il y a plusieurs personnages avec ce pouvoir, tous vont siphoner les \xE2mes sans interaction. Mais il est possible de d\xE9clarer un ordre de priorit\xE9, telle que si les personnages de plus haute priorit\xE9 ont siphon\xE9 tous les points de vie qu'ils pouvaient, il ne reste rien \xE0 siphoner pour les autre. Pour se faire, utilisez un pr\xE9dicat siphonDesAmesPrioritaire avec la valeur num\xE9rique de la priorit\xE9 (0 par d\xE9faut, plus la valeur est grande, plus le personnage est prioritaire).
      2. +
      3. Siphon des âmes : ajouter un prédicat siphonDesAmes. Par défaut, si il y a plusieurs personnages avec ce pouvoir, tous vont siphoner les âmes sans interaction. Mais il est possible de déclarer un ordre de priorité, telle que si les personnages de plus haute priorité ont siphoné tous les points de vie qu'ils pouvaient, il ne reste rien à siphoner pour les autre. Pour se faire, utilisez un prédicat siphonDesAmesPrioritaire avec la valeur numérique de la priorité (0 par défaut, plus la valeur est grande, plus le personnage est prioritaire).
      4. Masque mortuaire : !cof-effet-temp masqueMortuaire [[5+@{selected|INT}]] --mana 0
      5. Baiser du vampire :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+INT, port\xE9e 50, type Sortil\xE8ge, d\xE9g\xE2ts de drain, options --mana 1 --seulementVivant.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+INT, portée 50, type Sortilège, dégâts de drain, options --mana 1 --seulementVivant.
        • Objet de sort : #Attaque Baiser du vampire --toucher [[@{selected|ATKMAG}]] --dm 1d8+[[@{selected|INT}]] --portee 50 --sortilege --drain --seulementVivant
      6. Briser les coeurs :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 5d6+INT, port\xE9e 20, type Sortil\xE8ge, modificateurs seulementVivant necromancie, options --mana 2 --psave CON [[10+@{selected|INT}]] tempete 2.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 5d6+INT, portée 20, type Sortilège, modificateurs seulementVivant necromancie, options --mana 2 --psave CON [[10+@{selected|INT}]] tempete 2.
        • Objet de sort : #Attaque Briser les coeurs --toucher [[@{selected|ATKMAG}]] --dm 5d6+[[@{selected|INT}]] --portee 20 --sortilege --psave CON [[10+@{selected|INT}]] tempete 2 --seulementVivant --necromancie
        - \xC0 noter que la partie tempete 2 impl\xE9mente une chose qui n'est pas dans les r\xE8gles, \xE0 savoir augmenter la difficult\xE9 du test de constitution de 2 par point de mana investi en temp\xEAte de mana intense. Je trouvais en effet que sans cet ajout, \xE0 mana \xE9gale, le sort \xE9tait moins int\xE9ressant que le baiser du vampire. Il reste moins fort et plus situationnel que la d\xE9sint\xE9gration du magicien (\xE0 mana \xE9gale), m\xEAme avec ce changement. + À noter que la partie tempete 2 implémente une chose qui n'est pas dans les règles, à savoir augmenter la difficulté du test de constitution de 2 par point de mana investi en tempête de mana intense. Je trouvais en effet que sans cet ajout, à mana égale, le sort était moins intéressant que le baiser du vampire. Il reste moins fort et plus situationnel que la désintégration du magicien (à mana égale), même avec ce changement.
      7. Mot de mort :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateurs pasDeDmg necromancie difficultePV, options --mana 3 --etat mort --save CON [[10+@{selected|INT}]] tempete 2.
        • -
        • Objet de sort : #Attaque Mot de mort --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --necromancie --difficultePV --etat mort --save CON [[10+@{selected|INT}]] tempete 2
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateurs pasDeDmg necromancie difficultePV seulementVivant, options --mana 3 --etat mort --save CON [[10+@{selected|INT}]] tempete 2.
        • +
        • Objet de sort : #Attaque Mot de mort --toucher [[@{selected|ATKMAG}]] --pasDeDmg --seulementVivant --portee 20 --sortilege --necromancie --difficultePV --etat mort --save CON [[10+@{selected|INT}]] tempete 2
        - Comme pour Briser les coeurs, je pense qu'on peut augmenter la difficult\xE9 du jet de r\xE9sistance avec la puissance de la temp\xEAte de mana. + Comme pour Briser les coeurs, je pense qu'on peut augmenter la difficulté du jet de résistance avec la puissance de la tempête de mana.

      Voie de l'outre-tombe

      1. Peur :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg, options --mana 0 --peur [[10+@{selected|INT}]] [[1d4+r]]o\xF9 r est le rang dans la voie
        • -
        • Objet de sort : #Attaque Peur --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --peur [[10+@{selected|INT}]] [[1d4+r]]o\xF9 r est le niveau de l'objet
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg, options --mana 0 --peur [[10+@{selected|INT}]] [[1d4+r]]r est le rang dans la voie
        • +
        • Objet de sort : #Attaque Peur --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --peur [[10+@{selected|INT}]] [[1d4+r]]r est le niveau de l'objet
      2. -
      3. Animation d'un mort-vivant : !cof-animer-mort @{selected|token_id} --mana 0. Cela met directement le n\xE9cromant et le zombie en combat. Les Zombies perdent automatiquement 1 PV tous les 6 rounds. Lorsqu'ils atteignent 0 PV (quelle qu'en soit la raison) ou \xE0 la fin du combat, ils sont automatiquement d\xE9truits et supprim\xE9s. Si le lanceur a un pr\xE9dicat voieOutreTombe, le script g\xE8re le maximum de zombies qu'il peut invoquer. Mana, consommables et limites sont g\xE9r\xE9es, mais pas Temp\xEAte de Mana.
      4. -
      5. Putr\xE9faction : +
      6. Animation d'un mort-vivant : !cof-animer-mort @{selected|token_id} --mana 0. Cela met directement le nécromant et le zombie en combat. Les Zombies perdent automatiquement 1 PV tous les 6 rounds. Lorsqu'ils atteignent 0 PV (quelle qu'en soit la raison) ou à la fin du combat, ils sont automatiquement détruits et supprimés. Si le lanceur a un prédicat voieOutreTombe, le script gère le maximum de zombies qu'il peut invoquer. Mana, consommables et limites sont gérées, mais pas Tempête de Mana.
      7. +
      8. Putréfaction :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, port\xE9e 10, type Sortil\xE8ge, modificateurs necromancie, options --mana 1 --effet putrefactionOutreTombe --save CON [[12+@{selected|INT}]]
        • -
        • Objet de sort : #Attaque Putr\xE9faction --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --portee 10 --sortilege --necromancie --effet putrefactionOutreTombe --save CON [[12+@{selected|INT}]]
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, portée 10, type Sortilège, modificateurs necromancie, options --mana 1 --effet putrefactionOutreTombe --save CON [[12+@{selected|INT}]]
        • +
        • Objet de sort : #Attaque Putréfaction --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --portee 10 --sortilege --necromancie --effet putrefactionOutreTombe --save CON [[12+@{selected|INT}]]
      9. Ensevelissement :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg necromancie, options --mana 2 --etat enseveli FORDEX [[13+@{selected|INT}]]
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg necromancie, options --mana 2 --etat enseveli FORDEX [[13+@{selected|INT}]]
        • Objet de sort : #Attaque Ensevelissement --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --necromancie --etat enseveli FORDEX [[13+@{selected|INT}]]
        - Les d\xE9g\xE2ts sont inflig\xE9s au d\xE9but de chaque tour, et la cible recevra \xE0 son initiative un bouton lui permettant d'effectuer le jet pour sortir. Elle pourra \xE9galement ajouter un bonus manuel au jet, en fonction des actions r\xE9alis\xE9es pour l'aider \xE0 sortir. + Les dégâts sont infligés au début de chaque tour, et la cible recevra à son initiative un bouton lui permettant d'effectuer le jet pour sortir. Elle pourra également ajouter un bonus manuel au jet, en fonction des actions réalisées pour l'aider à sortir.
      10. -
      11. Arm\xE9e des morts : !cof-effet-temp armeeDesMorts @{selected|niveau} --limiteParJour 1 --mana 3. La zone couverte est symbolis\xE9e par l'activation d'une aura sur le token du lanceur. Le script utilisera pour cela l'aura 2 du token, donc attention si vous l'utilisez d\xE9j\xE0 sur le token du lanceur, elle sera \xE9cras\xE9e. Toute cible (le script ignore les alli\xE9s du lanceur) qui s'active dans une zone couverte par une arm\xE9e recevra dans ses actions un bouton sp\xE9cial pour se d\xE9fendre. Les d\xE9g\xE2ts sont inflig\xE9s automatiquement en d\xE9but de tour. En option, le script support l'argument --puissant des r\xE8gles de Mana de base, qui doublent la surface couverte (rayon 28m). Il est aussi possible d'utiliser l'option de Temp\xEAte de Mana ; la surface couverte sera multipli\xE9e par le nombre de PM investis en Magie Intense. Les adversaires avec un pr\xE9dicat volant ne seront pas affect\xE9s.
      12. +
      13. Armée des morts : !cof-effet-temp armeeDesMorts @{selected|niveau} --limiteParJour 1 --mana 3. La zone couverte est symbolisée par l'activation d'une aura sur le token du lanceur. Le script utilisera pour cela l'aura 2 du token, donc attention si vous l'utilisez déjà sur le token du lanceur, elle sera écrasée. Toute cible (le script ignore les alliés du lanceur) qui s'active dans une zone couverte par une armée recevra dans ses actions un bouton spécial pour se défendre. Les dégâts sont infligés automatiquement en début de tour. En option, le script support l'argument --puissant des règles de Mana de base, qui doublent la surface couverte (rayon 28m). Il est aussi possible d'utiliser l'option de Tempête de Mana ; la surface couverte sera multipliée par le nombre de PM investis en Magie Intense. Les adversaires avec un prédicat volant ne seront pas affectés.

      Voie du sang

      1. Saignements :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateurs pasDeDmg necromancie, options --mana 0 --effet saignementsSang rang, o\xF9 rang est le rang dans la Voie
        • -
        • Objet de sort : #Attaque Saignements --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --necromancie --effet saignementsSang rang, o\xF9 rang est le niveau de l'objet
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateurs pasDeDmg necromancie, options --mana 0 --effet saignementsSang rang, où rang est le rang dans la Voie
        • +
        • Objet de sort : #Attaque Saignements --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --necromancie --effet saignementsSang rang, où rang est le niveau de l'objet
        - Si vous souhaitez que le saignement ne puisse pas \xEAtre appliqu\xE9 \xE0 certains personnages (comme des golems ou des squelettes), vous pouvez leur ajouter un pr\xE9dicat immuniteSaignement. + Si vous souhaitez que le saignement ne puisse pas être appliqué à certains personnages (comme des golems ou des squelettes), vous pouvez leur ajouter un prédicat immuniteSaignement.
      2. Sang mordant : !cof-effet-temp sangMordant [[5+@{selected|INT}]] --mana 0.
      3. -
      4. Exsangue : ajouter un pr\xE9dicat exsangue.
      5. -
      6. H\xE9morragie : +
      7. Exsangue : ajouter un prédicat exsangue.
      8. +
      9. Hémorragie :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateurs pasDeDmg necromancie, options --mana 2 --effet hemorragie [[5+@{selected|INT}]]
        • -
        • Objet de sort : #Attaque H\xE9morragie --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --necromancie --effet hemorragie [[5+@{selected|INT}]]
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateurs pasDeDmg necromancie, options --mana 2 --effet hemorragie [[5+@{selected|INT}]]
        • +
        • Objet de sort : #Attaque Hémorragie --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --necromancie --effet hemorragie [[5+@{selected|INT}]]
      10. Lien de sang :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg necromancie, options --mana 3 --effet lienDeSang [[5+@{selected|INT}]]
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg necromancie, options --mana 3 --effet lienDeSang [[5+@{selected|INT}]]
        • Objet de sort : #Attaque Lien de sang --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --necromancie --effet lienDeSang [[5+@{selected|INT}]]
        Pas de support pour le lancement de sort sans ligne de vue.

      Voie de la sombre magie

      -

      Ajouter sur la fiche une comp\xE9tence Occultisme avec en bonus 2 fois le rang dans cette voie.

      +

      Ajouter sur la fiche une compétence Occultisme avec en bonus 2 fois le rang dans cette voie.

        -
      1. T\xE9n\xE8bres : !cof-tenebres @{selected|token_id} @{target|token_id} --mana 0. La commande pose un token transparent avec une aura noire visible par les joueurs pour visualiser la zone, et une petite aura jaune visible uniquement par le MJ (pour s\xE9lectionner le token si n\xE9cessaire). Tous les tokens pr\xE9sents dans la zone au lancement du sort sont automatiquement aveugl\xE9s. Au MJ ensuite d'enlever l'\xE9tat aveugl\xE9 quand les cibles sortent de la zone. A la fin de la dur\xE9e du sort, ou \xE0 la fin du combat, la zone et les \xE9tats aveugl\xE9s restant disparaissent automatiquement. Il est aussi possible de changer les valeurs par d\xE9faut du sort (port\xE9e 20m, rayon 5m) avec les options --portee X et --rayon X. En r\xE8gle custom, l'option puissant permet de doubler la superficie couverte (le script calcule le rayon appropri\xE9 si custom).
      2. -
      3. Pattes d'araign\xE9es : !cof-lancer-sort peut se d\xE9placer sur les murs pendants [[5+@{selected|INT}]] tours --mana 0
      4. -
      5. Strangulation : Le script va v\xE9rifier que la cible est bien vivante, en se basant sur la race, et sinon sur la pr\xE9sence \xE9ventuelle d'un pr\xE9dicat nonVivant. +
      6. Ténèbres : !cof-tenebres @{selected|token_id} @{target|token_id} --mana 0. La commande pose un token transparent avec une aura noire visible par les joueurs pour visualiser la zone, et une petite aura jaune visible uniquement par le MJ (pour sélectionner le token si nécessaire). Tous les tokens présents dans la zone au lancement du sort sont automatiquement aveuglés. Au MJ ensuite d'enlever l'état aveuglé quand les cibles sortent de la zone. A la fin de la durée du sort, ou à la fin du combat, la zone et les états aveuglés restant disparaissent automatiquement. Il est aussi possible de changer les valeurs par défaut du sort (portée 20m, rayon 5m) avec les options --portee X et --rayon X. En règle custom, l'option puissant permet de doubler la superficie couverte (le script calcule le rayon approprié si custom).
      7. +
      8. Pattes d'araignées : !cof-lancer-sort peut se déplacer sur les murs pendants [[5+@{selected|INT}]] tours --mana 0
      9. +
      10. Strangulation : Le script va vérifier que la cible est bien vivante, en se basant sur la race, et sinon sur la présence éventuelle d'un prédicat nonVivant.
          -
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, port\xE9e 20, type Sortil\xE8ge, d\xE9g\xE2ts magiques, modificateurs necromancie, options --mana 1 --effet strangulation rang
        • +
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, portée 20, type Sortilège, dégâts magiques, modificateurs necromancie, options --mana 1 --effet strangulation rang
        • !cof-strangulation @{selected|token_id} @{target|token_id} pour maintenir la strangulation
        • Pour un objet de sort, le code de l'attaque sera #Attaque Strangulation --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --magique --portee 20 --sortilege --effet strangulation rang
      11. -
      12. Ombre mortelle : !cof-ombre-mortelle @{selected|token_id} @{target|token_id} [[3+@{selected|INT}]] --portee 20 --mana 2 va cr\xE9er un double de la cible, (\xE0 condition de disposer de 2 points de mana) et ajouter ce double \xE0 l'initiative. Au MJ ensuite de la faire attaquer \xE0 son tour (pas d'aoe, juste attaquer le token dont elle est l'ombre). Le token dispara\xEEt lorsque le nombre de tours est \xE9coul\xE9. Il est possible de choisir l'image utilis\xE9e pour repr\xE9senter l'ombre en passant l'url de l'image avec l'option --image.
      13. -
      14. Intelligence h\xE9ro\xEFque : utiliser la fiche
      15. +
      16. Ombre mortelle : !cof-ombre-mortelle @{selected|token_id} @{target|token_id} [[3+@{selected|INT}]] --portee 20 --mana 2 va créer un double de la cible, (à condition de disposer de 2 points de mana) et ajouter ce double à l'initiative. Au MJ ensuite de la faire attaquer à son tour (pas d'aoe, juste attaquer le token dont elle est l'ombre). Le token disparaît lorsque le nombre de tours est écoulé. Il est possible de choisir l'image utilisée pour représenter l'ombre en passant l'url de l'image avec l'option --image.
      17. +
      18. Intelligence héroïque : utiliser la fiche
      -

      Pr\xEAtre

      +

      Prêtre

      Voie de la foi

        -
      1. Parole divine : ajouter une comp\xE9tence convaincre, de valeur 2 fois le rang dans la voie, et ajouter cette comp\xE9tence dans la liste.
      2. +
      3. Parole divine : ajouter une compétence convaincre, de valeur 2 fois le rang dans la voie, et ajouter cette compétence dans la liste.
      4. Arme d'argent :
          -
        • Pour attaquer avec l'arme d'argent, faire l'attaque avec les DM appropri\xE9s, les modificateurs armeDArgent, magique et l'option --si etat armeDArgent.
        • -
        • !cof-effet-combat armeDArgent --mana 0 pour lancer le sort. Vous pouvez ajouter l'option --degainer L (o\xF9 L est le label de l'attaque avec l'arme d'argent) si vous souhaitez que le pr\xEAtre puisse prendre l'arme en main dans le m\xEAme tour.
        • +
        • Pour attaquer avec l'arme d'argent, faire l'attaque avec les DM appropriés, les modificateurs armeDArgent, magique et l'option --si etat armeDArgent.
        • +
        • !cof-effet-combat armeDArgent --mana 0 pour lancer le sort. Vous pouvez ajouter l'option --degainer L (où L est le label de l'attaque avec l'arme d'argent) si vous souhaitez que le prêtre puisse prendre l'arme en main dans le même tour.
      5. -
      6. Ailes c\xE9lestes : !cof-effet-temp ailesCelestes [[5+@{selected|SAG}]] --mana 1.
      7. +
      8. Ailes célestes : !cof-effet-temp ailesCelestes [[5+@{selected|SAG}]] --mana 1.
      9. Foudres divines :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+SAG, port\xE9e 10, type Sortil\xE8ge, d\xE9g\xE2ts \xE9lectrique, modificateur saufAllies, option --mana 2. D\xE9cochez cette attaque, car elle sera appel\xE9e de mani\xE8re sp\xE9ciale : si le label de ce sort est L, il ne vous reste plus qu'\xE0 faire une action avec !cof-explosion L.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+SAG, portée 10, type Sortilège, dégâts électrique, modificateur saufAllies, option --mana 2. Décochez cette attaque, car elle sera appelée de manière spéciale : si le label de ce sort est L, il ne vous reste plus qu'à faire une action avec !cof-explosion L.
        • Objet de sort : !cof-explosion Foudres divines --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|SAG}]] --electrique --sortilege --portee 10 --saufAllies
      10. -
      11. Charisme h\xE9ro\xEFque : reporter les bonus sur la fiche
      12. +
      13. Charisme héroïque : reporter les bonus sur la fiche

      Voie de la guerre sainte

        -
      1. Arme b\xE9nie : utiliser les modificateurs reroll1, beni et magique \xE0 l'attaque
      2. -
      3. Bouclier de la foi : ajouter un pr\xE9dicat bouclierDeLaFoi, de valeur le bonus en DEF. Ce bonus sera automatiquement ajout\xE9 quand le pr\xEAtre porte son bouclier.
      4. +
      5. Arme bénie : utiliser les modificateurs reroll1, beni et magique à l'attaque
      6. +
      7. Bouclier de la foi : ajouter un prédicat bouclierDeLaFoi, de valeur le bonus en DEF. Ce bonus sera automatiquement ajouté quand le prêtre porte son bouclier.
      8. Marteau sprirituel :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+SAG, port\xE9e 30, type Sortil\xE8ge, options --mana 1
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+SAG, portée 30, type Sortilège, options --mana 1
        • Objet de sort : #Attaque Marteau sprirituel --toucher [[@{selected|ATKMAG}]] --dm 1d8+[[@{selected|SAG}]] --portee 30 --sortilege
      9. -
      10. Ch\xE2timent divin : Ajoutez dans la actions du tour une action nomm\xE9e Ch\xE2timent divin, de code #Attaque -1 --bonusAttaque [[@{selected|SAG}]] --plus [[@{selected|SAG}]].
      11. +
      12. Châtiment divin : Ajoutez dans la actions du tour une action nommée Châtiment divin, de code #Attaque -1 --bonusAttaque [[@{selected|SAG}]] --plus [[@{selected|SAG}]].
      13. Mot de pouvoir : !cof-effet-temp etourdi 1 --lanceur @{selected|token_id} --enVue --saufAllies --message @{selected|token_name} prononce un mot avec la voix de son dieu --mana 3
      -

      Voie de la pri\xE8re

      +

      Voie de la prière

        -
      1. B\xE9n\xE9diction : !cof-effet-temp benediction [[3+@{selected|SAG}]] --alliesEnVue --self --mana 0. Il faut avoir d\xE9fini une \xE9quipe avec le pr\xEAtre.
      2. -
      3. Destruction des morts-vivants : !cof-destruction-des-morts-vivants 2d6 --mana 0. Au rang 4 dans la voie, ajuster les d\xE9g\xE2ts. Notez que le script consid\xE8re comme mort-vivant tout personnage avec le champ race \xE0 squelette, zombie, momie, goule,vampire ou mort-vivant, ou alors qui poss\xE8de un pr\xE9dicat mortVivant. Pour \xE9viter la r\xE9p\xE9tition abusive du sort, vous pouvez augmenter la difficult\xE9 \xE0 chaque fois que le sort est r\xE9ussi pendant un m\xEAme combat, avec l'option --malusRepetition m. Un mort-vivant ayant le pr\xE9dicat immunite_destruction ne sera pas affect\xE9 par ce sort.
      4. +
      5. Bénédiction : !cof-effet-temp benediction [[3+@{selected|SAG}]] --alliesEnVue --self --mana 0. Il faut avoir défini une équipe avec le prêtre.
      6. +
      7. Destruction des morts-vivants : !cof-destruction-des-morts-vivants 2d6 --mana 0. Au rang 4 dans la voie, ajuster les dégâts. Notez que le script considère comme mort-vivant tout personnage avec le champ race à squelette, zombie, momie, goule,vampire ou mort-vivant, ou alors qui possède un prédicat mortVivant. Pour éviter la répétition abusive du sort, vous pouvez augmenter la difficulté à chaque fois que le sort est réussi pendant un même combat, avec l'option --malusRepetition m. Un mort-vivant ayant le prédicat immunite_destruction ne sera pas affecté par ce sort.
      8. Sanctuaire : !cof-effet-temp sanctuaire [[5+@{selected|SAG}]] --mana 1.
      9. -
      10. Intervention Divine : ajouter au personnage un pr\xE9dicat interventionDivine. Ensuite, utiliser !cof-intervention-divine ?{Type ?|rate|touche} juste apr\xE8s l'attaque en s\xE9lectionnant le token du Pr\xEAtre pour modifier le r\xE9sultat selon le choix. Il est tr\xE8s pratique de mettre cette commande dans une Ability \xE0 afficher en Token Action. Ne supporte que le jet de touche de la derni\xE8re attaque effectu\xE9e.
      11. -
      12. Sagesse h\xE9ro\xEFque : Reporter les bonus sur la fiche.
      13. +
      14. Intervention Divine : ajouter au personnage un prédicat interventionDivine. Ensuite, utiliser !cof-intervention-divine ?{Type ?|rate|touche} juste après l'attaque en sélectionnant le token du Prêtre pour modifier le résultat selon le choix. Il est très pratique de mettre cette commande dans une Ability à afficher en Token Action. Ne supporte que le jet de touche de la dernière attaque effectuée.
      15. +
      16. Sagesse héroïque : Reporter les bonus sur la fiche.

      Voie des soins

      -

      Ajouter un pr\xE9dicat voieDesSoins avec comme valeur le rang dans la voie.

      +

      Ajouter un prédicat voieDesSoins avec comme valeur le rang dans la voie.

        -
      1. Soins l\xE9gers : !cof-soin @{selected|token_id} @{target|token_id} leger --mana 0. Vous pouvez rajouter un petit effet visuel, par exemple avec --targetFx bubbling-holy. \xC0 titre personnel, j'ajoute --depasseLimite 1 pour permettre de lancer plus de sorts de soins l\xE9ger en une journ\xE9e (mais avec une augmentation cumulative du co\xFBt en mana de 1 \xE0 chaque d\xE9passement).
      2. -
      3. Soins mod\xE9r\xE9s : !cof-soin @{selected|token_id} @{target|token_id} modere --mana 0.
      4. -
      5. Soins de groupe : !cof-soin @{selected|token_id} groupe --mana 1 (ne pas oublier de d\xE9finir des alli\xE9s). Attention, toutefois, le sort ne va pas automatiquement soigner les personnages not\xE9s comme morts, ce qui est le cas g\xE9n\xE9ral si ils sont tomb\xE9s \xE0 0 PV. Si certains alli\xE9s not\xE9s morts ne sont pas vraiment morts, mais juste inconscient, il faudra que le MJ fasse la mise \xE0 jour de l'\xE9tat et des PV lui-m\xEAme.
      6. -
      7. Gu\xE9rison : !cof-guerison @{selected|token_id} @{target|token_id} --portee 0 --limiteParJour 1 --mana 2. Pour l'instant \xE7a ne fait que remettre les points de vie au maximum.
      8. -
      9. Rappel \xE0 la vie : pas de suport, simplement faire !cof-lancer-sort Rappel \xE0 la vie --mana 3 --limiteParJour 1 rappelALaVie.
      10. +
      11. Soins légers : !cof-soin @{selected|token_id} @{target|token_id} leger --mana 0. Vous pouvez rajouter un petit effet visuel, par exemple avec --targetFx bubbling-holy. À titre personnel, j'ajoute --depasseLimite 1 pour permettre de lancer plus de sorts de soins léger en une journée (mais avec une augmentation cumulative du coût en mana de 1 à chaque dépassement).
      12. +
      13. Soins modérés : !cof-soin @{selected|token_id} @{target|token_id} modere --mana 0.
      14. +
      15. Soins de groupe : !cof-soin @{selected|token_id} groupe --mana 1 (ne pas oublier de définir des alliés). Attention, toutefois, le sort ne va pas automatiquement soigner les personnages notés comme morts, ce qui est le cas général si ils sont tombés à 0 PV. Si certains alliés notés morts ne sont pas vraiment morts, mais juste inconscient, il faudra que le MJ fasse la mise à jour de l'état et des PV lui-même.
      16. +
      17. Guérison : !cof-guerison @{selected|token_id} @{target|token_id} --portee 0 --limiteParJour 1 --mana 2. Pour l'instant ça ne fait que remettre les points de vie au maximum.
      18. +
      19. Rappel à la vie : pas de suport, simplement faire !cof-lancer-sort Rappel à la vie --mana 3 --limiteParJour 1 rappelALaVie.
      -

      Voie de la spiritualit\xE9

      +

      Voie de la spiritualité

        -
      1. V\xEAtements sacr\xE9s : Ajouter un pr\xE9dicat vetementsSacres avec comme valeur le rang dans la voie de la spiritualit\xE9. Cela augmente la DEF, mais seulement lorsque le pr\xEAtre ne porte pas d'armure (ne se voit pas sur le total de DEF de la fiche)
      2. -
      3. Protection contre le mal : !cof-effet-combat protectionContreLeMal --lanceur @{selected|token_id} --target @{target|token_id} --portee 0 --mana 0. Donne le bonus contre toute cr\xE9ature dont l'attribut race est squelette, zombie, d\xE9mon, \xE9l\xE9mentaire, ou bien qui poss\xE8de un pr\xE9dicat mauvais.
      4. -
      5. D\xE9livrance : !cof-delivrance @{selected|token_id} @{target|token_id} --portee 0 --mana 1
      6. -
      7. Marche des plans : !cof-lancer-sort marche entre les plans (il peut se d\xE9placer de [[(3+@{selected|SAG})*10]] km) --mana 2.
      8. -
      9. Messie : pas d'autre support que !cof-lancer-sort entre directement en contact avec son dieu pour r\xE9aliser un miracle --mana 3
      10. +
      11. Vêtements sacrés : Ajouter un prédicat vetementsSacres avec comme valeur le rang dans la voie de la spiritualité. Cela augmente la DEF, mais seulement lorsque le prêtre ne porte pas d'armure (ne se voit pas sur le total de DEF de la fiche)
      12. +
      13. Protection contre le mal : !cof-effet-combat protectionContreLeMal --lanceur @{selected|token_id} --target @{target|token_id} --portee 0 --mana 0. Donne le bonus contre toute créature dont l'attribut race est squelette, zombie, démon, élémentaire, ou bien qui possède un prédicat mauvais.
      14. +
      15. Délivrance : !cof-delivrance @{selected|token_id} @{target|token_id} --portee 0 --mana 1
      16. +
      17. Marche des plans : !cof-lancer-sort marche entre les plans (il peut se déplacer de [[(3+@{selected|SAG})*10]] km) --mana 2.
      18. +
      19. Messie : pas d'autre support que !cof-lancer-sort entre directement en contact avec son dieu pour réaliser un miracle --mana 3

      Psionique

      Voie de l'attaque mentale

        -
      1. Attaque mentale : faire 2 attaques, une pour les DMs l\xE9taux, avec les options --sortilege --attaqueMentale --mana 0 et l'autre avec l'option suppl\xE9mentaire --tempDmg (et en ajustant les DM).
      2. -
      3. Bouclier psi : ajouter un pr\xE9dicat bouclierPsi.
      4. -
      5. Attaque \xE9tourdissante : faire une attaque mentale, avec les options --avecd12 --if moins niveau --if etatCible bouclierPsi --effet etourdi 1 --save CHA [[8+@{selected|CHA}]] --else --effet etourdi 1 --endif --endif --mana 1.
      6. +
      7. Attaque mentale : faire 2 attaques, une pour les DMs létaux, avec les options --sortilege --attaqueMentale --mana 0 et l'autre avec l'option supplémentaire --tempDmg (et en ajustant les DM).
      8. +
      9. Bouclier psi : ajouter un prédicat bouclierPsi.
      10. +
      11. Attaque étourdissante : faire une attaque mentale, avec les options --avecd12 --if moins niveau --if etatCible bouclierPsi --effet etourdi 1 --save CHA [[8+@{selected|CHA}]] --else --effet etourdi 1 --endif --endif --mana 1.
      12. Vague psionique : faire les attaques mentales sur toutes les cibles. En cas d'utilisation avec la Mana, le plus simple est de faire deux ability :
          -
        • !cof-lancer-sort lance une vague psychique --mana 2 qui lance le sort (pratique pour y mettre votre d\xE9pense de Mana unique)
        • -
        • Une ability qui permet de faire une attaque mentale (sans d\xE9pense de Mana)
        • +
        • !cof-lancer-sort lance une vague psychique --mana 2 qui lance le sort (pratique pour y mettre votre dépense de Mana unique)
        • +
        • Une ability qui permet de faire une attaque mentale (sans dépense de Mana)
      13. -
      14. Ego h\xE9ro\xEFque : reporter les bonus sur la fiche
      15. +
      16. Ego héroïque : reporter les bonus sur la fiche
      -

      Voie du contr\xF4le corporel

      +

      Voie du contrôle corporel

        -
      1. Proprioception : ajouter les PVs sur la fiche, et ajouter un pr\xE9dicat proprioception.
      2. -
      3. Transe de r\xE9g\xE9n\xE9ration : ajoutez une ability !cof-soin @{selected|token_id} 1d6+[[@{selected|niveau} + @{selected|CHA}]] --limiteParJour rang --mana 0 --message entre en transe de r\xE9g\xE9n\xE9ration pour [[2d6]] tours.
      4. -
      5. Contr\xF4le du m\xE9tabolisme : ajouter un pr\xE9dicat controleDuMetabolisme. Ne pas modifier l'initiative, le bonus de charisme sera pris en compte par le script.
      6. -
      7. Contr\xF4le sanguin : ajouter un pr\xE9dicat controleSanguin. Le script immunise aux poison, aux effets saignements automatis\xE9s, et divise par deux les dommages des attaques avec --vampirise.
      8. +
      9. Proprioception : ajouter les PVs sur la fiche, et ajouter un prédicat proprioception.
      10. +
      11. Transe de régénération : ajoutez une ability !cof-soin @{selected|token_id} 1d6+[[@{selected|niveau} + @{selected|CHA}]] --limiteParJour rang --mana 0 --message entre en transe de régénération pour [[2d6]] tours.
      12. +
      13. Contrôle du métabolisme : ajouter un prédicat controleDuMetabolisme. Ne pas modifier l'initiative, le bonus de charisme sera pris en compte par le script.
      14. +
      15. Contrôle sanguin : ajouter un prédicat controleSanguin. Le script immunise aux poison, aux effets saignements automatisés, et divise par deux les dommages des attaques avec --vampirise.

      Voie de l'empathie

        -
      1. Perception extra-sensorielle : ajuster l'initiative et ajouter le bonus \xE0 une comp\xE9tence perception (pour les jets).
      2. -
      3. D\xE9fense intuitive : ajouter un pr\xE9dicat defenseIntuitive. Ne pas modifier la DEF sur la fiche, la sagesse sera automatiquement prise en compte.
      4. -
      5. Perception du pass\xE9 : !cof-lancer-sort tente de percevoir le pass\xE9 --mana 1 pour lancer le sort. On peut faire le jet en utilisant !cof-jet SAG 15.
      6. -
      7. Vision lointaine : pas de support autre que !cof-lancer-sort projette son esprit \xE0 grande distance --mana 2. Utiliser !cof-jet SAG pour les jets de sagesse.
      8. -
      9. Perception h\xE9ro\xEFque : reporter les bonus sur la fiche
      10. +
      11. Perception extra-sensorielle : ajuster l'initiative et ajouter le bonus à une compétence perception (pour les jets).
      12. +
      13. Défense intuitive : ajouter un prédicat defenseIntuitive. Ne pas modifier la DEF sur la fiche, la sagesse sera automatiquement prise en compte.
      14. +
      15. Perception du passé : !cof-lancer-sort tente de percevoir le passé --mana 1 pour lancer le sort. On peut faire le jet en utilisant !cof-jet SAG 15.
      16. +
      17. Vision lointaine : pas de support autre que !cof-lancer-sort projette son esprit à grande distance --mana 2. Utiliser !cof-jet SAG pour les jets de sagesse.
      18. +
      19. Perception héroïque : reporter les bonus sur la fiche
      -

      Voie de la t\xE9l\xE9kin\xE9sie

      +

      Voie de la télékinésie

        -
      1. Manipulation \xE0 distance : pour les attaques \xE0 distance, le plus simple est d'utiliser une autre attaque en utilisant le score d'attaque magique et le bon modificateur de DMs.
      2. -
      3. Champ de protection : pour l'effet de base, si vous suivez les r\xE8gles, ajustez simplement la DEF sur la fiche. Si vous pr\xE9f\xE9rez en faire un sort, vous pouvez utiliser la commande !cof-effet-temp champDeProtection [[5+@{selected|CHA}]]. La valeur par d\xE9faut est celle d'un pr\xE9dicat voieDeLaTelekinesie, et pour utiliser une autre valeur, on peut utiliser l'option --valeur. Pour le champ \xE0 distance, faire !cof-effet-temp champDeProtection 1 --lanceur @{selected|token_id} --portee 10 --valeur n --target @{target|token_id}.
      4. +
      5. Manipulation à distance : pour les attaques à distance, le plus simple est d'utiliser une autre attaque en utilisant le score d'attaque magique et le bon modificateur de DMs.
      6. +
      7. Champ de protection : pour l'effet de base, si vous suivez les règles, ajustez simplement la DEF sur la fiche. Si vous préférez en faire un sort, vous pouvez utiliser la commande !cof-effet-temp champDeProtection [[5+@{selected|CHA}]]. La valeur par défaut est celle d'un prédicat voieDeLaTelekinesie, et pour utiliser une autre valeur, on peut utiliser l'option --valeur. Pour le champ à distance, faire !cof-effet-temp champDeProtection 1 --lanceur @{selected|token_id} --portee 10 --valeur n --target @{target|token_id}.
      8. Onde de choc :
          -
        • Sort : Ajouter une attaque sur la fiche dommages 1d8+CHA, port\xE9e 0, type Sortil\xE8ge, modificateurs auto, options --mana 1 --disque ?{Port\xE9e (max 10) ?|10} --etat renverse --save FOR [[10+@{selected|CHA}]] --targetFx explode-magic. D\xE9cochez cette attaque, et appelez la dans une action qui fait !cof-explosion l o\xF9 i est le label de l'attaque.
        • -
        • Objet de sort : !cof-explosion Onde de choc --auto --dm 1d8+[[@{selected|SAG}]] --portee 0 --sortilege --disque ?{Port\xE9e (max 10) ?|10} --etat renverse --save FOR [[10+@{selected|CHA}]] --targetFx explode-magic
        • +
        • Sort : Ajouter une attaque sur la fiche dommages 1d8+CHA, portée 0, type Sortilège, modificateurs auto, options --mana 1 --disque ?{Portée (max 10) ?|10} --etat renverse --save FOR [[10+@{selected|CHA}]] --targetFx explode-magic. Décochez cette attaque, et appelez la dans une action qui fait !cof-explosion li est le label de l'attaque.
        • +
        • Objet de sort : !cof-explosion Onde de choc --auto --dm 1d8+[[@{selected|SAG}]] --portee 0 --sortilege --disque ?{Portée (max 10) ?|10} --etat renverse --save FOR [[10+@{selected|CHA}]] --targetFx explode-magic
      9. -
      10. Combat kin\xE9tique : cr\xE9er un pr\xE9dicat combatKinetique. Cela appliquera automatiquement la RD dans tous les cas o\xF9 le personnage est attaqu\xE9 par un adversaire et qu'il est conscient. Pour l'augmentation des dommages, reporter sur les attaques sur la fiche.
      11. -
      12. Psychoportation : !cof-lancer-sort s'\xE9l\xE8ve dans les airs pendant [[5+@{selected|INT}]] tours --mana 3. Passer la FOR en caract\xE9ristique sup\xE9rieure via la fiche.
      13. +
      14. Combat kinétique : créer un prédicat combatKinetique. Cela appliquera automatiquement la RD dans tous les cas où le personnage est attaqué par un adversaire et qu'il est conscient. Pour l'augmentation des dommages, reporter sur les attaques sur la fiche.
      15. +
      16. Psychoportation : !cof-lancer-sort s'élève dans les airs pendant [[5+@{selected|INT}]] tours --mana 3. Passer la FOR en caractéristique supérieure via la fiche.
      -

      Voie de la t\xE9l\xE9pathie

      +

      Voie de la télépathie

        -
      1. T\xE9l\xE9pathie : pas de support autre que !cof-lancer-sort communique par t\xE9l\xE9pathie pendant [[5+@{selected|SAG}]] tours --mana 0
      2. -
      3. Radar mental : ajouter un pr\xE9dicat radarMental, de valeur le bonus procur\xE9 par le radar mental (2 fois le rang dans la voie). En cas de surprise provoqu\xE9e par quelque chose de non-vivant penser \xE0 utiliser l'option --nonVivant dans !cof-surprise.
      4. -
      5. Suggestion : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg, difficultePVmax, attaqueMentale, options --si moins niveau --if touche --message la cible doit faire l'action sugg\xE9r\xE9e --endif.
      6. -
      7. Lire les pens\xE9es: faire une attaque de type sortil\xE8ge, port\xE9e 10 m, avec l'option --difficulteCarac SAG --if touche --message lit les pens\xE9es de @{target|token_name} pendant [[1d6+@{selected|SAG}]] tours --endif.
      8. -
      9. Domination psy : faire une attaque de type sortil\xE8ge, port\xE9e 20 m, avec les modificateurs dominationPsy, attaqueMentale et pasDeDmg.
      10. +
      11. Télépathie : pas de support autre que !cof-lancer-sort communique par télépathie pendant [[5+@{selected|SAG}]] tours --mana 0
      12. +
      13. Radar mental : ajouter un prédicat radarMental, de valeur le bonus procuré par le radar mental (2 fois le rang dans la voie). En cas de surprise provoquée par quelque chose de non-vivant penser à utiliser l'option --nonVivant dans !cof-surprise.
      14. +
      15. Suggestion : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg, difficultePVmax, attaqueMentale, options --si moins niveau --if touche --message la cible doit faire l'action suggérée --endif.
      16. +
      17. Lire les pensées: faire une attaque de type sortilège, portée 10 m, avec l'option --difficulteCarac SAG --if touche --message lit les pensées de @{target|token_name} pendant [[1d6+@{selected|SAG}]] tours --endif.
      18. +
      19. Domination psy : faire une attaque de type sortilège, portée 20 m, avec les modificateurs dominationPsy, attaqueMentale et pasDeDmg.
      -

      R\xF4deur

      +

      Rôdeur

      Voie de l'archer

        -
      1. Sens affut\xE9s : Cr\xE9ez un pr\xE9dicat sensAffutes. Cela va ajuster l'initiative (ne se voit pas sur la fiche), ainsi que les d\xE9g\xE2ts des arcs (attention \xE0 ne pas en plus le rajouter sur la fiche !). Ajoutez ensuite le bonus aux comp\xE9tences perception et vigilance (ou cr\xE9ez-les).
      2. +
      3. Sens affutés : Créez un prédicat sensAffutes. Cela va ajuster l'initiative (ne se voit pas sur la fiche), ainsi que les dégâts des arcs (attention à ne pas en plus le rajouter sur la fiche !). Ajoutez ensuite le bonus aux compétences perception et vigilance (ou créez-les).
      4. Tir aveugle : utiliser une attaque avec l'option --tirAveugle.
      5. Tir rapide : faire simplement deux attaques dans le tour
      6. -
      7. Fl\xE8che de mort : faire l'attaque avec les options --m2d20 --incrDmgCoef
      8. +
      9. Flèche de mort : faire l'attaque avec les options --m2d20 --incrDmgCoef
      10. Dans le mille : faire l'attaque avec les options --avecd12crit --plus 2d6

      Voie du compagnon animal

        -
      1. Odorat : ajouter une comp\xE9tence pistage, de valeur 5 (ou augment\xE9e de 5)
      2. -
      3. Surveillance : ajouter un pr\xE9dicat surveillance, avec comme valeur le nom du compagnon (doit \xEAtre exactement le m\xEAme que celui du token du compagnon). Cela automatise l'initiative et le bonus aux jets de surprise, le reste se g\xE8re manuellement
      4. -
      5. Combat : ajouter le loup sous contr\xF4le du joueur. Si vous souhaitez que le loup rentre en combat \xE0 chaque fois que le r\xF4deur entre en combat, ajoutez au r\xF4deur un pr\xE9dicat nomm\xE9 entrerEnCombatAvec, de valeur le nom du token du loup.
      6. +
      7. Odorat : ajouter une compétence pistage, de valeur 5 (ou augmentée de 5)
      8. +
      9. Surveillance : ajouter un prédicat surveillance, avec comme valeur le nom du compagnon (doit être exactement le même que celui du token du compagnon). Cela automatise l'initiative et le bonus aux jets de surprise, le reste se gère manuellement
      10. +
      11. Combat : ajouter le loup sous contrôle du joueur. Si vous souhaitez que le loup rentre en combat à chaque fois que le rôdeur entre en combat, ajoutez au rôdeur un prédicat nommé entrerEnCombatAvec, de valeur le nom du token du loup.
      12. Empathie animale : pour soigner, utiliser !cof-soin @{selected|token_id} nom_familier ?{Montant des soins} --transfer
      13. -
      14. Animal fabuleux : ajuster les caract\xE9ristiques du loup
      15. +
      16. Animal fabuleux : ajuster les caractéristiques du loup

      Voie de l'escarmouche

        -
      1. Chasseur \xE9m\xE9rite : ajouter un pr\xE9dicat chasseurEmerite. Puis, si dans le profil (attribut profil) de la cible, il y a animal (ou si la cible a un pr\xE9dicat animal), le bonus s'applique. Ajouter aussi le bonus \xE0 une comp\xE9tence pistage.
      2. -
      3. Traquenard : ajouter un pr\xE9dicat traquenard, puis option --traquenard pour l'attaque. Pour une utilisation pratique, le mieux est de faire une attaque d'arme en main avec l'option : #Attaque -1 --traquenard.
      4. -
      5. Attaque \xE9clair : --plus [[@{selected|DEX}]] --bonusAttaque [[@{selected|DEX}]]
      6. -
      7. Repli : simplement faire un jet en utilisant par exemple !cof-jet DEX 10, et d\xE9crire le r\xE9sultat.
      8. -
      9. Dext\xE9rit\xE9 h\xE9ro\xEFque : reporter sur la fiche.
      10. +
      11. Chasseur émérite : ajouter un prédicat chasseurEmerite. Puis, si dans le profil (attribut profil) de la cible, il y a animal (ou si la cible a un prédicat animal), le bonus s'applique. Ajouter aussi le bonus à une compétence pistage.
      12. +
      13. Traquenard : ajouter un prédicat traquenard, puis option --traquenard pour l'attaque. Pour une utilisation pratique, le mieux est de faire une attaque d'arme en main avec l'option : #Attaque -1 --traquenard.
      14. +
      15. Attaque éclair : --plus [[@{selected|DEX}]] --bonusAttaque [[@{selected|DEX}]]
      16. +
      17. Repli : simplement faire un jet en utilisant par exemple !cof-jet DEX 10, et décrire le résultat.
      18. +
      19. Dextérité héroïque : reporter sur la fiche.

      Voie de la survie

        -
      1. Endurant : ajouter une comp\xE9tence survie, de caract\xE9ristique CON, avec le bonus 2xrang dans la Voie.
      2. -
      3. Nature nourrici\xE8re : pour la recherche d'herbes, ajouter un pr\xE9dicat voieDeLaSurvie avec comme valeur le rang du personnage dans la voie. On peut utiliser !cof-nature-nourriciere pour lancer la recherche. Cela cr\xE9e automatiquement les doses de plantes m\xE9dicinales dans les consommables du personnage. Ces doses sont supprim\xE9es toutes les nuits. Pour les besoins d'un personnage, j'ai aussi donn\xE9 la possibilit\xE9 de trouver des baies magiques \xE0 la place des herbes m\xE9dicinales. Pour cela, il faut un pr\xE9dicat natureNourriciereBaies.
      4. -
      5. Grand pas : ajouter les comp\xE9tences natation et escalade, de valeur 5.
      6. -
      7. Increvable : ajouter un pr\xE9dicat increvable.
      8. -
      9. Constitution h\xE9ro\xEFque : reporter les bonus sur la fiche
      10. +
      11. Endurant : ajouter une compétence survie, de caractéristique CON, avec le bonus 2xrang dans la Voie.
      12. +
      13. Nature nourricière : pour la recherche d'herbes, ajouter un prédicat voieDeLaSurvie avec comme valeur le rang du personnage dans la voie. On peut utiliser !cof-nature-nourriciere pour lancer la recherche. Cela crée automatiquement les doses de plantes médicinales dans les consommables du personnage. Ces doses sont supprimées toutes les nuits. Pour les besoins d'un personnage, j'ai aussi donné la possibilité de trouver des baies magiques à la place des herbes médicinales. Pour cela, il faut un prédicat natureNourriciereBaies.
      14. +
      15. Grand pas : ajouter les compétences natation et escalade, de valeur 5.
      16. +
      17. Increvable : ajouter un prédicat increvable.
      18. +
      19. Constitution héroïque : reporter les bonus sur la fiche

      Voie du traqueur

        -
      1. Pas de loup : ajouter le bonus \xE0 une comp\xE9tence discr\xE9tion.
      2. -
      3. Ennemi jur\xE9 : ajouter un pr\xE9dicat ennemiJure avec comme valeur la race des ennemis. Cette race doit se retrouver dans le champ race de l'ennemi. Le script reconnait aussi le type mort-vivant (tout en minuscules) et dans ce cas va d\xE9terminer si la cible est un mort-vivant (pr\xE9dicat mortVivant ou race reconnue comme mort-vivant), ainsi que le type g\xE9ant (pour les g\xE9ants, ogres, trolls, etc.) et le type gobelin.
      4. +
      5. Pas de loup : ajouter le bonus à une compétence discrétion.
      6. +
      7. Ennemi juré : ajouter un prédicat ennemiJure avec comme valeur la race des ennemis. Cette race doit se retrouver dans le champ race de l'ennemi. Le script reconnait aussi le type mort-vivant (tout en minuscules) et dans ce cas va déterminer si la cible est un mort-vivant (prédicat mortVivant ou race reconnue comme mort-vivant), ainsi que le type géant (pour les géants, ogres, trolls, etc.) et le type gobelin.
      8. Embuscade : en cas d'attaque sur les ennemis, les mettre tous surpris avec la commande !cof-set-state surpris true
      9. -
      10. Second ennemi jur\xE9 : on peut renseigner une seconde race dans un nouveau pr\xE9dicat ennemiJure, ou alors le rajouter au pr\xE9dicat ennemiJure pr\xE9c\xE9dant, en la s\xE9parant de la premi\xE8re par une virgule (exemple : ennemiJure:: orque, araign\xE9e, sans rien ensuite sur la ligne)
      11. -
      12. Perception h\xE9ro\xEFque : reporter les bonus sur la fiche
      13. +
      14. Second ennemi juré : on peut renseigner une seconde race dans un nouveau prédicat ennemiJure, ou alors le rajouter au prédicat ennemiJure précédant, en la séparant de la première par une virgule (exemple : ennemiJure:: orque, araignée, sans rien ensuite sur la ligne)
      15. +
      16. Perception héroïque : reporter les bonus sur la fiche
      -

      Samoura\xEF

      +

      Samouraï

      Voie de l'arc et du cheval

        -
      1. Monture loyale : ajouter un pr\xE9dicat montureLoyale. Pour la monture, il faut faire un personnage avec un pr\xE9dicat monture. Pour monter sur la monture, utiliser !cof-en-selle @{selected|token_id} nom_de_la_monture, et pour en descendre, il suffit de faire la m\xEAme commande (utiliser une ability "token action" rend cela assez facile \xE0 l'usage).
      2. +
      3. Monture loyale : ajouter un prédicat montureLoyale. Pour la monture, il faut faire un personnage avec un prédicat monture. Pour monter sur la monture, utiliser !cof-en-selle @{selected|token_id} nom_de_la_monture, et pour en descendre, il suffit de faire la même commande (utiliser une ability "token action" rend cela assez facile à l'usage).
      4. Tir en mouvement : pas de support particulier.
      5. -
      6. Tir fatal : ajouter un pr\xE9dicat tirFatal. Pour tenir compte du bonus suppl\xE9mentaire avec le rang dans la voie, ajouter un pr\xE9dicat voieDeLArcEtDuCheval de valeur le rang atteint dans cette voie. Si vous souhaitez que cette capacit\xE9 s'applique \xE0 une autre classe d'arme que les arcs, vous pouvez associer ce nom au pr\xE9dicat tirfatal (attention, sans accent). Par exemple, pour les arbal\xE8tes, tirFatal:arbalete.
      7. +
      8. Tir fatal : ajouter un prédicat tirFatal. Pour tenir compte du bonus supplémentaire avec le rang dans la voie, ajouter un prédicat voieDeLArcEtDuCheval de valeur le rang atteint dans cette voie. Si vous souhaitez que cette capacité s'applique à une autre classe d'arme que les arcs, vous pouvez associer ce nom au prédicat tirfatal (attention, sans accent). Par exemple, pour les arbalètes, tirFatal:arbalete.

      Voie du dirigeant

        -
      1. \xC9duqu\xE9 : simplement noter les bonus et comp\xE9tences sur la fiche.
      2. -
      3. Homme de cour : ajouter une comp\xE9tence \xE9tiquette, de valeur 5.
      4. -
      5. Lame de lign\xE9e : pas de support particulier pour l'arme, mais quand le samoura\xEF perd l'arme, vous pouvez utiliser la commande !cof-effet lameDeLigneePerdue true (avec le samoura\xEF s\xE9lectionn\xE9). Quand il la retrouve, utilisez !cof-effet lameDeLigneePerdue false.
      6. +
      7. Éduqué : simplement noter les bonus et compétences sur la fiche.
      8. +
      9. Homme de cour : ajouter une compétence étiquette, de valeur 5.
      10. +
      11. Lame de lignée : pas de support particulier pour l'arme, mais quand le samouraï perd l'arme, vous pouvez utiliser la commande !cof-effet lameDeLigneePerdue true (avec le samouraï sélectionné). Quand il la retrouve, utilisez !cof-effet lameDeLigneePerdue false.

      Voie de l'honneur

        -
      1. Chef n\xE9 : ajouter un pr\xE9dicat immunite_peur, et des comp\xE9tences pour l'intimidation et commander.
      2. -
      3. D\xE9fi : !cof-defi-samourai @{selected|token_id} @{target|token_id} bonus. Le bonus en argument est optionnel. S'il n'est pas pr\xE9sent, le script utilise la valeur d'un pr\xE9dicat voieDeLHonneur.
      4. +
      5. Chef né : ajouter un prédicat immunite_peur, et des compétences pour l'intimidation et commander.
      6. +
      7. Défi : !cof-defi-samourai @{selected|token_id} @{target|token_id} bonus. Le bonus en argument est optionnel. S'il n'est pas présent, le script utilise la valeur d'un prédicat voieDeLHonneur.
      8. Honorable : pas de support particulier.

      Voie du ki

        -
      1. Esprit vide : ajouter un pr\xE9dicat espritVide. Si vous voulez un boonus diff\xE9rent (par exemple \xE0 partir du rang 4 dans la voie), associez les bonus au pr\xE9dicat.
      2. -
      3. Main vide : faire l'attaque \xE0 mains nues correspondant \xE0 la capacit\xE9.
      4. -
      5. Kiai : ajouter un pr\xE9dicat kiai, de valeur 1. Au rang 5, mettre cette valeur \xE0 2, le script se charge d'attendre 1d6 tours avant de proposer le deuxi\xE8me kiai.
      6. -
      7. Course mortelle : !cof-attack-line @{selected|token_id} --distanceMax 10. L'attaque va \xEAtre faite avec l'arme en main, mais on peut sp\xE9cifier un label d'attaque (avant les options) et toutes les options support\xE9es par !cof-attack.
      8. +
      9. Esprit vide : ajouter un prédicat espritVide. Si vous voulez un boonus différent (par exemple à partir du rang 4 dans la voie), associez les bonus au prédicat.
      10. +
      11. Main vide : faire l'attaque à mains nues correspondant à la capacité.
      12. +
      13. Kiai : ajouter un prédicat kiai, de valeur 1. Au rang 5, mettre cette valeur à 2, le script se charge d'attendre 1d6 tours avant de proposer le deuxième kiai.
      14. +
      15. Course mortelle : !cof-attack-line @{selected|token_id} --distanceMax 10. L'attaque va être faite avec l'arme en main, mais on peut spécifier un label d'attaque (avant les options) et toutes les options supportées par !cof-attack.
      16. Puissance du ki : #Attaque -1 --avecd12crit --plus 2d6 --seulementContact.

      Voie du sabre

        -
      1. Technique du sabre : ajouter un pr\xE9dicat techniqueDuSabre, de valeur le rang dans la Voie.
      2. -
      3. Frappe du vide : ajouter un pr\xE9dicat frappeDuVide.
      4. -
      5. Lames Jumelles : faire les attaques avec le modificateur lamesJumelles permet de prendre en compte la force courante de l'attaquant pour les malus \xE9ventuels \xE0 l'attaque. Comme le samoura\xEF va par d\xE9faut commencer le combat les mains vides, et qu'avec cette capacit\xE9 il voudra certainement d\xE9gainer \xE0 la fois le katana et le wakizachi, on peut utiliser un pr\xE9dicat pour lui faciliter la t\xE2che : si le label du katana est 5 et celui du wakizachi par exemple 3, ajouter un pr\xE9dicat actionDegainer1:5-3 (de cette fa\xE7on, le fait de d\xE9gainer le katana et le wakizachi sera en t\xEAte de liste).
      6. +
      7. Technique du sabre : ajouter un prédicat techniqueDuSabre, de valeur le rang dans la Voie.
      8. +
      9. Frappe du vide : ajouter un prédicat frappeDuVide.
      10. +
      11. Lames Jumelles : faire les attaques avec le modificateur lamesJumelles permet de prendre en compte la force courante de l'attaquant pour les malus éventuels à l'attaque. Comme le samouraï va par défaut commencer le combat les mains vides, et qu'avec cette capacité il voudra certainement dégainer à la fois le katana et le wakizachi, on peut utiliser un prédicat pour lui faciliter la tâche : si le label du katana est 5 et celui du wakizachi par exemple 3, ajouter un prédicat actionDegainer1:5-3 (de cette façon, le fait de dégainer le katana et le wakizachi sera en tête de liste).

      Voleur

      Voie de l'assassin

        -
      1. Discr\xE9tion : ajouter une comp\xE9tence discr\xE9tion sur la fiche, avec le bon bonus.
      2. -
      3. Attaque sournoise : Ajouter un pr\xE9dicat attaqueSournoise, de valeur le nombre de d\xE9s de l'attaque sournoise. Ensuite, faire des versions des attaques avec --sournoise. Au MJ de v\xE9rifier que les conditions de l'attaque sournoise sont remplies. Le plus pratique pour l'utilisation avec diff\xE9rentes armes, est d'ajouter \xE0 la liste des actions du tour une action de titre Attaque sournoise et de code #Attaque -1 --sournoise.
      4. -
      5. Ombre mouvante : utiliser la commande !cof-ombre-mouvante --fx burst-smoke (la partie --fx burst-smoke peut \xEAtre omise ou chang\xE9e, bien s\xFBr). Le script ne g\xE8re pas encore l'attaque sournoise qui peut suivre, au MJ de surveiller l'initiative du voleur par rapport \xE0 sa cible.
      6. -
      7. Surprise : ajouter un pr\xE9dicat immunite_surpris. Pour le reste, \xE0 g\xE9rer par le MJ.
      8. -
      9. Ouverture mortelle : ajouter les options --ouvertureMortelle --limiteParCombat 1 ouvertureMortelle --sournoise. Selon les indications de Kegron, ne mettre la partie --sournoise que si les conditions s'y pr\xEAtent (dans le dos, surprise, acrobatie, etc).
      10. +
      11. Discrétion : ajouter une compétence discrétion sur la fiche, avec le bon bonus.
      12. +
      13. Attaque sournoise : Ajouter un prédicat attaqueSournoise, de valeur le nombre de dés de l'attaque sournoise. Ensuite, faire des versions des attaques avec --sournoise. Au MJ de vérifier que les conditions de l'attaque sournoise sont remplies. Le plus pratique pour l'utilisation avec différentes armes, est d'ajouter à la liste des actions du tour une action de titre Attaque sournoise et de code #Attaque -1 --sournoise.
      14. +
      15. Ombre mouvante : utiliser la commande !cof-ombre-mouvante --fx burst-smoke (la partie --fx burst-smoke peut être omise ou changée, bien sûr). Le script ne gère pas encore l'attaque sournoise qui peut suivre, au MJ de surveiller l'initiative du voleur par rapport à sa cible.
      16. +
      17. Surprise : ajouter un prédicat immunite_surpris. Pour le reste, à gérer par le MJ.
      18. +
      19. Ouverture mortelle : ajouter les options --ouvertureMortelle --limiteParCombat 1 ouvertureMortelle --sournoise. Selon les indications de Kegron, ne mettre la partie --sournoise que si les conditions s'y prêtent (dans le dos, surprise, acrobatie, etc).

      Voie de l'aventurier

        -
      1. Sprint : Pour v\xE9rifier que ce n'est bien utilis\xE9 qu'une fois par combat, on pourra utiliser !cof-lancer-sort pousse un sprint --limiteParCombat 1 sprint.
      2. -
      3. Provocation : !cof-provocation @{selected|token_id} @{target|token_id}. Au joueur ensuite de faire son attaque gratuite si la provocation est r\xE9ussie et que l'adversaire l'attaque.
      4. -
      5. Gr\xE2ce f\xE9line : ajouter un pr\xE9dicat graceFeline. Cela va affecter l'initiative et la DEF, mais sans se voir sur la fiche. Pour les tests de d\xE9placement, ajouter un pr\xE9dicat graceFelineVoleur (penser \xE0 proposer l'utilisation de comp\xE9tences, en ajoutant les comp\xE9tences course, saut, acrobatie et escalade au voleur ou sur le handout de comp\xE9tences).
      6. +
      7. Sprint : Pour vérifier que ce n'est bien utilisé qu'une fois par combat, on pourra utiliser !cof-lancer-sort pousse un sprint --limiteParCombat 1 sprint.
      8. +
      9. Provocation : !cof-provocation @{selected|token_id} @{target|token_id}. Au joueur ensuite de faire son attaque gratuite si la provocation est réussie et que l'adversaire l'attaque.
      10. +
      11. Grâce féline : ajouter un prédicat graceFeline. Cela va affecter l'initiative et la DEF, mais sans se voir sur la fiche. Pour les tests de déplacement, ajouter un prédicat graceFelineVoleur (penser à proposer l'utilisation de compétences, en ajoutant les compétences course, saut, acrobatie et escalade au voleur ou sur le handout de compétences).
      -

      Voie du d\xE9placement

      +

      Voie du déplacement

        -
      1. Esquive : Ajouter un pr\xE9dicat esquiveVoleur, de valeur le rang dans la voie. Ne pas modifier la DEF sur la fiche, le script fera les ajustements (et montrera le total avec !cof-statut).
      2. +
      3. Esquive : Ajouter un prédicat esquiveVoleur, de valeur le rang dans la voie. Ne pas modifier la DEF sur la fiche, le script fera les ajustements (et montrera le total avec !cof-statut).
      4. Chute : pas de support particulier.
      5. -
      6. Acrobaties : faire !cof-jet DEX 15 --nom acrobatie pour le jet de dext\xE9rit\xE9, le reste est g\xE9r\xE9 par le MJ. Il est possible d'automatiser quand le personnage d\xE9cide de faire une attaque quel que soit le r\xE9sultat du jet d'acrobatie grace \xE0 la commande #Attaque -1 --attaqueAcrobatique.
      7. -
      8. Esquive de la magie : ajouter un pr\xE9dicat esquiveDeLaMagie.
      9. -
      10. Dext\xE9rit\xE9 h\xE9ro\xEFque : ajouter les bonus sur la fiche
      11. +
      12. Acrobaties : faire !cof-jet DEX 15 --nom acrobatie pour le jet de dextérité, le reste est géré par le MJ. Il est possible d'automatiser quand le personnage décide de faire une attaque quel que soit le résultat du jet d'acrobatie grace à la commande #Attaque -1 --attaqueAcrobatique.
      13. +
      14. Esquive de la magie : ajouter un prédicat esquiveDeLaMagie.
      15. +
      16. Dextérité héroïque : ajouter les bonus sur la fiche

      Voie du roublard

        -
      1. Doigts agiles : utiliser des comp\xE9tences sur la fiche de personnage
      2. -
      3. D\xE9tecter les pi\xE8ges : faire le jet avec !cof-jet INT ?{Pi\xE8ge normal?|Oui,10|Magique,15} --secret
      4. -
      5. Croc-en-jambe : ajouter un pr\xE9dicat crocEnJambe. Pour distinguer les adversaires quadrup\xE8des qui ne seraient pas connues du script, lui ajouter un pr\xE9dicat quadrupede. Les adversaires avec un pr\xE9dicat volant ne seront pas affect\xE9s.
      6. +
      7. Doigts agiles : utiliser des compétences sur la fiche de personnage
      8. +
      9. Détecter les pièges : faire le jet avec !cof-jet INT ?{Piège normal?|Oui,10|Magique,15} --secret
      10. +
      11. Croc-en-jambe : ajouter un prédicat crocEnJambe. Pour distinguer les adversaires quadrupèdes qui ne seraient pas connues du script, lui ajouter un prédicat quadrupede. Les adversaires avec un prédicat volant ne seront pas affectés.
      12. Attaque paralysante : lancer une des attaques de contact du voleur en rajoutant les options --limiteParCombat 1 attaqueParalysante --pasDeDmg --effet paralysieRoublard [[1d4]].
      13. -
      14. Attaque en tra\xEEtre : Ajouter un pr\xE9dicat attaqueEnTraitre. Les actions affich\xE9es en cas d'attaque en tra\xEEtre seront par d\xE9faut une attaque avec l'arme en main et les attaques naturelles de la fiche coch\xE9es. Si cela ne convient pas, vous pouvez cr\xE9er une liste d'actions nomm\xE9e Attaques en traitre contenant les attaques possibles pour l'attaque en tra\xEEtre.
      15. +
      16. Attaque en traître : Ajouter un prédicat attaqueEnTraitre. Les actions affichées en cas d'attaque en traître seront par défaut une attaque avec l'arme en main et les attaques naturelles de la fiche cochées. Si cela ne convient pas, vous pouvez créer une liste d'actions nommée Attaques en traitre contenant les attaques possibles pour l'attaque en traître.

      Voie du spadassin

      1. Attaque en finesse : faire les modifications sur la fiche
      2. -
      3. Esquive fatale : Ajouter un pr\xE9dicat esquiveFatale (on peut y associer un nombre pour permettre plus d'une utilisation par combat). En combat, si la situation s'y pr\xEAte, un bouton permettre d'utiliser l'esquive. Ne pas oublier de d\xE9finir les alli\xE9s du voleur pour que la v\xE9rification des cibles soit correcte.
      4. -
      5. Frappe chirurgicale : ajouter un pr\xE9dicat frappeChirurgicale.
      6. -
      7. Ambidextrie : pas g\xE9r\xE9 par le script.
      8. -
      9. Botte secr\xE8te : ajouter un pr\xE9dicat botteSecrete. Ne pas oublier le pr\xE9dicat attaqueSournoise qui doit \xEAtre associ\xE9 au nombre de d\xE9s des attaques sournoises du voleur.
      10. +
      11. Esquive fatale : Ajouter un prédicat esquiveFatale (on peut y associer un nombre pour permettre plus d'une utilisation par combat). En combat, si la situation s'y prête, un bouton permettre d'utiliser l'esquive. Ne pas oublier de définir les alliés du voleur pour que la vérification des cibles soit correcte.
      12. +
      13. Frappe chirurgicale : ajouter un prédicat frappeChirurgicale.
      14. +
      15. Ambidextrie : pas géré par le script.
      16. +
      17. Botte secrète : ajouter un prédicat botteSecrete. Ne pas oublier le prédicat attaqueSournoise qui doit être associé au nombre de dés des attaques sournoises du voleur.
    -

    4. Autres capacit\xE9s

    +

    4. Autres capacités

    -

    4.1 Voies et capacit\xE9s raciales

    +

    4.1 Voies et capacités raciales

    - Quelques capacit\xE9s communes \xE0 plusieurs races : + Quelques capacités communes à plusieurs races :
      -
    • Vision dans le noir : ajoutez un pr\xE9dicat visionDansLeNoir de valeur le nombre de metres \xE0 laquelle le personnage peut voir dans le noir. Le script va adapter la vison dans le noir \xE0 l'unit\xE9 de mesure utilis\xE9e sur la page o\xF9 le token du personnage est cr\xE9\xE9.
    • +
    • Vision dans le noir : ajoutez un prédicat visionDansLeNoir de valeur le nombre de metres à laquelle le personnage peut voir dans le noir. Le script va adapter la vison dans le noir à l'unité de mesure utilisée sur la page où le token du personnage est créé.
    -

    \xC2me forg\xE9e

    -

    Pour les capacit\xE9s raciales, un pr\xE9dicat vieArtificielle permet de diviser tous les soins par 2. Pour la r\xE9sistance aux effets de drains, au feu et au froid, ajouter dans la RD sur la fiche drain:5, feu:5, froid:5. Pour l'immunit\xE9 aux poisons et maladies, utiliser un pr\xE9dicat creatureArtificielle. Enfin pour le saignement, ajouter un pr\xE9dicat immuniteSaignement.

    +

    Âme forgée

    +

    Pour les capacités raciales, un prédicat vieArtificielle permet de diviser tous les soins par 2. Pour la résistance aux effets de drains, au feu et au froid, ajouter dans la RD sur la fiche drain:5, feu:5, froid:5. Pour l'immunité aux poisons et maladies, utiliser un prédicat creatureArtificielle. Enfin pour le saignement, ajouter un prédicat immuniteSaignement.

      -
    1. Main lourde : ajuster les DM, et enlever l'option --tempDmg pour l'attaque \xE0 mains nues.
    2. +
    3. Main lourde : ajuster les DM, et enlever l'option --tempDmg pour l'attaque à mains nues.

    Demi-ogre

    • Vision dans le noir.
    • -
    • \xC9norme : pas de support, ajuster les attaques
    • -
    • Grande taille : quand le demi-ogre rentre dans une construction de taille humaine, utiliser !cof-effet constructionTailleHumaine true. \xC0 la sortie du b\xE2timent, !cof-effet constructionTailleHumaine false. Pour les espaces exigus, de m\xEAme avec l'effet espaceExigu.
    • -
    • R\xE9action violente : en cas de provocation, ex\xE9cuter !cof-effet-temp reactionViolente [[1d6]] --save SAG 10. On peut par exemple mettre ce code en ability li\xE9e au token. Au MJ et au joueur de g\xE9rer les actions qui s'ensuivent. Le script propose une action \xE0 l'ogre pour prendre sur lui \xE0 chaque tour.
    • +
    • Énorme : pas de support, ajuster les attaques
    • +
    • Grande taille : quand le demi-ogre rentre dans une construction de taille humaine, utiliser !cof-effet constructionTailleHumaine true. À la sortie du bâtiment, !cof-effet constructionTailleHumaine false. Pour les espaces exigus, de même avec l'effet espaceExigu.
    • +
    • Réaction violente : en cas de provocation, exécuter !cof-effet-temp reactionViolente [[1d6]] --save SAG 10. On peut par exemple mettre ce code en ability liée au token. Au MJ et au joueur de gérer les actions qui s'ensuivent. Le script propose une action à l'ogre pour prendre sur lui à chaque tour.
      -
    1. Sang-froid : ajouter un pr\xE9dicat sangFroid. Modifier la commande pour les provocations en !cof-effet-temp reactionViolente [[1d4]] --save SAG 5.
    2. -
    3. Violence cibl\xE9e : ajouter un pr\xE9dicat violenceCiblee.
    4. +
    5. Sang-froid : ajouter un prédicat sangFroid. Modifier la commande pour les provocations en !cof-effet-temp reactionViolente [[1d4]] --save SAG 5.
    6. +
    7. Violence ciblée : ajouter un prédicat violenceCiblee.

    Demi-orque

    Vision dans le noir.
    1. Force de la nature : ajouter les bonus sur la fiche
    2. -
    3. Talent pour la violence : voir les capacit\xE9s choisies
    4. +
    5. Talent pour la violence : voir les capacités choisies
    6. Critique brutal : pour l'instant, ajouter le modificateur incrCritCoef pour toutes les attaques au contact.
    7. Attaque sanglante : faire une attaque (ou liste d'attaques) avec les options --effet blessureQuiSaigne --saveParTour CON [[12 + @{selected|FOR}]]
    8. -
    9. Colosse : augmenter les caract\xE9ristiques sur la fiche.
    10. +
    11. Colosse : augmenter les caractéristiques sur la fiche.
    12. +
    +

    Drakonide

    +
      +
    1. Souffle : ajouter une attaque naturelle cochée, faisant des dégâts du type du drakonide, de portée 10 m, avec comme option --cone 30 --psave DEX 12 --tempsRecharge rechargeSouffle [[1d4]].
    2. +
    3. Intimidant : ajouter la compétence intimidation sur la fiche, avec un bonus de +5.
    4. +
    5. Écailles robustes : ajouter le bonus sur la fiche.
    6. +
    7. Fureur drakonide : ajouter un prédicat fureurDrakonide.
    8. +
    9. Héritage draconique : ajuster les caractéristiques sur la fiche.

    Elfe sylvain

      -
    1. Gr\xE2ce elfique : simplement reporter sur la fiche
    2. -
    3. Enfant de la for\xEAt : voir les capacit\xE9s choisies
    4. -
    5. Archer \xE9m\xE9rite : ajuster les chances de critique sur les attaques \xE0 l'arc
    6. -
    7. Fl\xE8che sanglante : faire une attaque (ou liste d'attaques) avec les options --effet blessureQuiSaigne --saveParTour CON [[12 + @{selected|DEX}]]
    8. -
    9. Sup\xE9riorit\xE9 elfique : augmenter les caract\xE9ristiques sur la fiche.
    10. +
    11. Grâce elfique : simplement reporter sur la fiche
    12. +
    13. Enfant de la forêt : voir les capacités choisies
    14. +
    15. Archer émérite : ajuster les chances de critique sur les attaques à l'arc
    16. +
    17. Flèche sanglante : faire une attaque (ou liste d'attaques) avec les options --effet blessureQuiSaigne --saveParTour CON [[12 + @{selected|DEX}]]
    18. +
    19. Supériorité elfique : augmenter les caractéristiques sur la fiche.
    -

    F\xE9e et lutin

    +

    Fée et lutin

    • Vision dans le noir.
    • -
    • Tout petit : ajouter un pr\xE9dicat toutPetit qui va automatiquement ajuster la d\xE9fense et les jets de discr\xE9tion.
    • -
    • Vol et T\xE9l\xE9portation : pas de support.
    • -
    • Trop petit : ajouter un pr\xE9dicat tropPetit. Cela va aussi changer les d\xE9g\xE2ts de base des armes (il vaut mieux laisser les vrais DM pour que la capacit\xE9 Grande taille fonctionne).
    • +
    • Tout petit : ajouter un prédicat toutPetit qui va automatiquement ajuster la défense et les jets de discrétion.
    • +
    • Vol et Téléportation : pas de support.
    • +
    • Trop petit : ajouter un prédicat tropPetit. Cela va aussi changer les dégâts de base des armes (il vaut mieux laisser les vrais DM pour que la capacité Grande taille fonctionne).
    1. Langage des animaux : aucun support
    2. -
    3. Invisibilit\xE9 : !cof-set-state invisible true --message se rend invisible --messageMJ l'invisibilit\xE9 va durer [[1d6+@{selected|INT}]] minutes --limiteParJour r o\xF9 r est le rang dans la Voie.
    4. -
    5. Monture f\xE9\xE9rique : ajouter un ersonnage pour la monture. Ajoutez-lui le pr\xE9dicat monture. Pour monter sur la monture, utiliser !cof-en-selle @{selected|token_id} nom_de_la_monture, et pour en descendre, il suffit de faire la m\xEAme commande (utiliser une ability "token action" rend cela assez facile \xE0 l'usage). Si vous souhaitez que la monture rentre en combat \xE0 chaque fois que l'\xEAtre f\xE9\xE9rique entre en combat, ajoutez \xE0 l'\xEAtre f\xE9\xE9rique un pr\xE9dicat nomm\xE9 entrerEnCombatAvec, de valeur le nom du token de la monture (pensez \xE0 utiliser la syntaxe avec :: si ce nom contient des caract\xE8res sp\xE9ciaux).
    6. -
    7. Grande taille : !cof-effet grandeTaille oui --lanceur @{selected|token_id} --limiteParJour 3 --messageMJ La taille humaine durera [[1d6+@{selected|CHA}]] minutes. Le script ne g\xE8re pas les dur\xE9es en minutes, le MJ devra penser \xE0 supprimer l'effet, par exemple depuis le statut (!cof-statut).
    8. +
    9. Invisibilité : !cof-set-state invisible true --message se rend invisible --messageMJ l'invisibilité va durer [[1d6+@{selected|INT}]] minutes --limiteParJour rr est le rang dans la Voie.
    10. +
    11. Monture féérique : ajouter un ersonnage pour la monture. Ajoutez-lui le prédicat monture. Pour monter sur la monture, utiliser !cof-en-selle @{selected|token_id} nom_de_la_monture, et pour en descendre, il suffit de faire la même commande (utiliser une ability "token action" rend cela assez facile à l'usage). Si vous souhaitez que la monture rentre en combat à chaque fois que l'être féérique entre en combat, ajoutez à l'être féérique un prédicat nommé entrerEnCombatAvec, de valeur le nom du token de la monture (pensez à utiliser la syntaxe avec :: si ce nom contient des caractères spéciaux).
    12. +
    13. Grande taille : !cof-effet grandeTaille oui --lanceur @{selected|token_id} --limiteParJour 3 --messageMJ La taille humaine durera [[1d6+@{selected|CHA}]] minutes. Le script ne gère pas les durées en minutes, le MJ devra penser à supprimer l'effet, par exemple depuis le statut (!cof-statut).
    -

    F\xE9lis

    +

    Félis

      -
    1. \xC2me f\xE9line : ajouter un pr\xE9dicat ameFeline, de valeur le rang dans la voie. Pensez \xE0 ajouter des comp\xE9tences pour le mouvement sur la fiche si ils ne sont pas d\xE9j\xE0 pr\xE9sent dans votre handout de comp\xE9tences.
    2. +
    3. Âme féline : ajouter un prédicat ameFeline, de valeur le rang dans la voie. Pensez à ajouter des compétences pour le mouvement sur la fiche si ils ne sont pas déjà présent dans votre handout de compétences.
    4. Armes naturelles :
        -
      • Cr\xE9ez une attaque "Griffes et crocs" naturelle de contact avec en DM 1d6 + Mod de FOR et les options --si etat armesNaturelles --message Attaque de ses griffes et crocs !.
      • +
      • Créez une attaque "Griffes et crocs" naturelle de contact avec en DM 1d6 + Mod de FOR et les options --si etat armesNaturelles --message Attaque de ses griffes et crocs !.
      • Pour faire sortir les griffes, dans l'onglet script, ajouter une action "Sortir/rentrer les griffes" faisant !cof-effet armesNaturelles.
    5. @@ -2018,49 +2030,50 @@

      F\xE9lis

      Gnome

      1. Petit pote : ajouter le bonus de CHA sur la fiche
      2. -
      3. Don occulte : se reporter aux capacit\xE9s choisies.
      4. -
      5. Insignifiant : ajouter un pr\xE9dicat insignifiant. +
      6. Don occulte : se reporter aux capacités choisies.
      7. +
      8. Insignifiant : ajouter un prédicat insignifiant. +
      +

      Gobelin

      +
        +
      • Vision dans le noir.
      • +
      • Attaque en meute : ajouter un prédicat attaqueEnMeute.
      • +
      • Petite taille : ajouter un prédicat petiteTaille pour ajouter les bonus de DEF et discrétion. Pour la limitation des armes, je préfère laisser le MJ vérifier.
      • +
      +
        +
      1. Rapide comme son ombre : ajouter un prédicat rapideCommeSonOmbre de valeur le bonus en discrétion et initiative.

      Halfelin

      -

      Petite taille : ajouter le bonus de DEF sur la ficher, et ajouter 2 \xE0 une comp\xE9tence discr\xE9tion.

      +

      Petite taille : ajouter un prédicat petiteTaille pour ajouter les bonus de DEF et discrétion. Pour la limitation des armes, je préfère laisser le MJ vérifier.

        -
      1. Petit veinard : ajouter un pr\xE9dicat petitVeinard (on peut y associer un nombre si on veut plus d'une utilisation par combat). Le script ne va automatiser que les relancer de d\xE9s d'attaque ou de jets de caract\xE9ristiques (et encore, pas tous). Il propose d'utiliser la chance \xE0 chaque attaque, m\xEAme r\xE9ussie, mais dans ce cas, c'est au joueur de relancer le d\xE9 concern\xE9, et au MJ d'en appliquer les cons\xE9quences.
      2. -
      3. R\xE9sistance l\xE9gendaire : ajouter le bonus en CON sur la fiche, et ajouter un pr\xE9dicat DEF_magie avec comme valeur 5.
      4. +
      5. Petit veinard : ajouter un prédicat petitVeinard (on peut y associer un nombre si on veut plus d'une utilisation par combat). Le script ne va automatiser que les relancer de dés d'attaque ou de jets de caractéristiques (et encore, pas tous). Il propose d'utiliser la chance à chaque attaque, même réussie, mais dans ce cas, c'est au joueur de relancer le dé concerné, et au MJ d'en appliquer les conséquences.
      6. +
      7. Résistance légendaire : ajouter le bonus en CON sur la fiche, et ajouter un prédicat DEF_magie avec comme valeur 5.

      Haut elfe

        -
      1. Gr\xE2ce elfique : ajouter les bonus sur la fiche
      2. -
      3. Talent pour la magie : voir les capacit\xE9s choisies
      4. -
      5. Force d'\xE2me : ajouter des pr\xE9dicat immunite_peur et immunite_endormi. Ajouter aussi des pr\xE9dicats DEF_magie et bonusSagesseMagie de valeur 5.
      6. +
      7. Grâce elfique : ajouter les bonus sur la fiche
      8. +
      9. Talent pour la magie : voir les capacités choisies
      10. +
      11. Force d'âme : ajouter des prédicat immunite_peur et immunite_endormi. Ajouter aussi des prédicats DEF_magie et bonusSagesseMagie de valeur 5.

      Humain

      -

      Instinct de survie : cr\xE9er un pr\xE9dicat instinctDeSurvieHumain.

      -
        -
      1. Adaptable : ajouter un pr\xE9dicat adaptable, de valeur le bonus en cas de test rat\xE9. Le script ne va appliquer le bonus que pour les tests avec difficult\xE9 identifi\xE9e. Le MJ devra l'appliquer dans les cas rat\xE9s par le script.
      2. -
      3. Loup parmi les loups : ajouter un pr\xE9dicat loupParmiLesLoups avec comme valeur 1 ou 2 selon le rang dans la voie. Une cr\xE9ature sera consid\xE9r\xE9e comme humano\xEFde si elle a un pr\xE9dicat humanoide, ou si sa race est reconnue comme humano\xEFde.
      4. -
      5. Versatile : se reporter \xE0 la capacit\xE9 choisie.
      6. -
      7. Increvable : ajouter un pr\xE9dicat increvableHumain.
      8. -
      -

      Drakonide

      +

      Instinct de survie : créer un prédicat instinctDeSurvieHumain.

        -
      1. Souffle : ajouter une attaque naturelle coch\xE9e, faisant des d\xE9g\xE2ts du type du drakonide, de port\xE9e 10 m, avec comme option --cone 30 --psave DEX 12 --tempsRecharge rechargeSouffle [[1d4]].
      2. -
      3. Intimidant : ajouter la comp\xE9tence intimidation sur la fiche, avec un bonus de +5.
      4. -
      5. \xC9cailles robustes : ajouter le bonus sur la fiche.
      6. -
      7. Fureur drakonide : ajouter un pr\xE9dicat fureurDrakonide.
      8. -
      9. H\xE9ritage draconique : ajuster les caract\xE9ristiques sur la fiche.
      10. +
      11. Adaptable : ajouter un prédicat adaptable, de valeur le bonus en cas de test raté. Le script ne va appliquer le bonus que pour les tests avec difficulté identifiée. Le MJ devra l'appliquer dans les cas ratés par le script.
      12. +
      13. Loup parmi les loups : ajouter un prédicat loupParmiLesLoups avec comme valeur 1 ou 2 selon le rang dans la voie. Une créature sera considérée comme humanoïde si elle a un prédicat humanoide, ou si sa race est reconnue comme humanoïde.
      14. +
      15. Versatile : se reporter à la capacité choisie.
      16. +
      17. Increvable : ajouter un prédicat increvableHumain.

      Lutin

      - Voir les f\xE9es. + Voir les fées.

      Minotaure

      • Vision dans le noir.
      • Coup de corne : ajouter simplement l'attaque.
      • -
      • Sens de l'orientation : utiliser une comp\xE9tence/
      • -
      • Grande taille : quand le minotaure rentre dans une construction de taille humaine, utiliser !cof-effet constructionTailleHumaine true. \xC0 la sortie du b\xE2timent, !cof-effet constructionTailleHumaine false. Pour les espaces exigus, de m\xEAme avec l'effet espaceExigu. Si on veut un seul bouton, enlever simplement l'argument true.
      • +
      • Sens de l'orientation : utiliser une compétence/
      • +
      • Grande taille : quand le minotaure rentre dans une construction de taille humaine, utiliser !cof-effet constructionTailleHumaine true. À la sortie du bâtiment, !cof-effet constructionTailleHumaine false. Pour les espaces exigus, de même avec l'effet espaceExigu. Si on veut un seul bouton, enlever simplement l'argument true.
        -
      1. Charge : #Attaque -1 --bonusAttaque 2 --plus 1d6. Le d\xE9placement n'est pas encore g\xE9r\xE9. Modifier les bonus si le minotaure poss\xE8de la capacit\xE9 Charge du barbare.
      2. -
      3. Fr\xE9n\xE9sie : On peut faire passer en fr\xE9n\xE9sie avec la commande !cof-effet-temp frenesieMinotaure [[1d6]]. Quand j'aurai le temps, il devrait \xEAtre possible de faire appara\xEEtre un bouton quand le minotaure est bless\xE9.
      4. +
      5. Charge : #Attaque -1 --deplaceDe 5 20 --bonusAttaque 2 --plus 1d6. Modifier les bonus si le minotaure possède la capacité Charge du barbare.
      6. +
      7. Frénésie : On peut faire passer en frénésie avec la commande !cof-effet-temp frenesieMinotaure [[1d6]]. Quand j'aurai le temps, il devrait être possible de faire apparaître un bouton quand le minotaure est blessé.
      8. Orientation infaillible : pas de support particulier.
      9. Encorner : pas de support particulier.
      10. Colosse : reporter sur la fiche.
      11. @@ -2070,137 +2083,137 @@

        Nain

      12. Vision dans le noir.
        1. -
        2. R\xE9sistance : ajouter les bonus sur la fiche
        3. +
        4. Résistance : ajouter les bonus sur la fiche
        5. Solide comme un roc : ajouter le texte 2/1 dans la RD sur la fiche.
        6. -
        7. Haches et marteaux : ajouter un pr\xE9dicat hachesEtMarteaux. Ne pas oublier de mettre le modificateur hache ou marteau pour les attaques qui sont concern\xE9es.
        8. +
        9. Haches et marteaux : ajouter un prédicat hachesEtMarteaux. Ne pas oublier de mettre le modificateur hache ou marteau pour les attaques qui sont concernées.

        Tieflin

        • Vision dans le noir.
        • -
        • R\xE9sistance aux \xE9l\xE9ments : ajouter dans la RD sur la fiche feu:5, electrique:5, froid:5
        • +
        • Résistance aux éléments : ajouter dans la RD sur la fiche feu:5, electrique:5, froid:5
          -
        1. Se faire discret : ajouter les jets sur la fiche, ou bien des comp\xE9tences mentir et deguisement de valeur 5, \xE0 utiliser avec !cof-jet.
        2. +
        3. Se faire discret : ajouter les jets sur la fiche, ou bien des compétences mentir et deguisement de valeur 5, à utiliser avec !cof-jet.
    -

    4.2 Voies de prestige et capacit\xE9s \xE9piques

    +

    4.2 Voies de prestige et capacités épiques

    -

    Voie d'Arwend\xE9e

    +

    Voie d'Arwendée

      -
    1. Sens affut\xE9s : Cr\xE9ez un pr\xE9dicat sensAffutes. Cela va ajuster l'initiative (ne se voit pas sur la fiche), ainsi que les d\xE9g\xE2ts des arcs. Ajoutez ensuite le bonus aux comp\xE9tences perception et vigilance (ou cr\xE9ez-les).
    2. -
    3. Arc de ma\xEEtre : Cr\xE9ez un pr\xE9dicat arcDeMaitre pour automatiquement augmenter la port\xE9e des arcs de 20 m.
    4. +
    5. Sens affutés : Créez un prédicat sensAffutes. Cela va ajuster l'initiative (ne se voit pas sur la fiche), ainsi que les dégâts des arcs. Ajoutez ensuite le bonus aux compétences perception et vigilance (ou créez-les).
    6. +
    7. Arc de maître : Créez un prédicat arcDeMaitre pour automatiquement augmenter la portée des arcs de 20 m.
    8. Carquois magique : !cof-effet-temp carquoisMagique [[5+@{selected|SAG}]] --valeur ?{Type de DM?|feu|froid|foudre} --mana 1.
    9. -
    10. Protection contre les projectiles : Cr\xE9ez un pr\xE9dicat protectionContreLesProjectiles de valeur 10. Puis, pour lancer le sort, utilisez !cof-effet-temp protectionContreLesProjectiles [[6*(5+@{selected|SAG})]] --lanceur @{selected|token_id} --target @{target|token_id} --mana 2.
    11. -
    12. Pluie de fl\xE8ches : lancer l'attaque avec les options --limiteParCombat 1 pluieDeFleches --disque 5 --toucheDoubleDmg --mana 3.
    13. +
    14. Protection contre les projectiles : Créez un prédicat protectionContreLesProjectiles de valeur 10. Puis, pour lancer le sort, utilisez !cof-effet-temp protectionContreLesProjectiles [[6*(5+@{selected|SAG})]] --lanceur @{selected|token_id} --target @{target|token_id} --mana 2.
    15. +
    16. Pluie de flèches : lancer l'attaque avec les options --limiteParCombat 1 pluieDeFleches --disque 5 --toucheDoubleDmg --mana 3.

    Voie de l'archange

      -
    1. Forme d'ange : !cof-effet-temp formeDAnge [[5+@{selected|SAG}]] --mana 0. Le MJ devra g\xE9rer l'aspect en vol.
    2. -
    3. Soins am\xE9lior\xE9s : utiliser un pr\xE9dicat voieDeLArchange avec comme valeur le rang dans la voie.
    4. -
    5. \xC9p\xE9e c\xE9leste : rien \xE0 faire si le pr\xE9dicat voieDeLArchange a la bonne valeur. Si le personnage n'a pas d\xE9j\xE0 la capacit\xE9 Arme d'argent, ajouter une attaque pour cette arme, avec le modificateur armeDArgent et l'option --si etat armeDArgent.
    6. +
    7. Forme d'ange : !cof-effet-temp formeDAnge [[5+@{selected|SAG}]] --mana 0. Le MJ devra gérer l'aspect en vol.
    8. +
    9. Soins améliorés : utiliser un prédicat voieDeLArchange avec comme valeur le rang dans la voie.
    10. +
    11. Épée céleste : rien à faire si le prédicat voieDeLArchange a la bonne valeur. Si le personnage n'a pas déjà la capacité Arme d'argent, ajouter une attaque pour cette arme, avec le modificateur armeDArgent et l'option --si etat armeDArgent.

    Voie de l'archer arcanique

      -
    1. Fl\xE8che magique : vous pouvez ajouter une munition de type fl\xE8che, avec les modificateurs magique, reroll1.
    2. -
    3. Fl\xE8che tueuse : ajouter une munition d\xE9di\xE9e, avec les modificateurs magique, reroll1 et les options --bonusAttaque 3 --plus rd6. Au Mj et au joueur de v\xE9rifier que cette fl\xE8che n'est utilis\xE9e que contre la bonne cible...
    4. -
    5. Fl\xE8che intangible : ajouter une action avec le code #Attaque -1 --difficulteCarac DEX --ignoreObstacles. Attention, pour l'instant le script ne v\xE9rifie pas que l'arme utilis\xE9e est bien un arc.
    6. -
    7. Fl\xE8ches vivantes : ajoutez aux munitions du rang 1 et 2 l'option --if deAttaque 15 --plus 2d6 --message la fl\xE8che prend vie au contact du sang --endif.
    8. -
    9. Fl\xE8che chercheuse : faire une action avec le code #Attaque -1 --plus 2d6 --portee 1000 --limiteParJour 1 flecheChercheuse.
    10. +
    11. Flèche magique : vous pouvez ajouter une munition de type flèche, avec les modificateurs magique, reroll1.
    12. +
    13. Flèche tueuse : ajouter une munition dédiée, avec les modificateurs magique, reroll1 et les options --bonusAttaque 3 --plus rd6. Au Mj et au joueur de vérifier que cette flèche n'est utilisée que contre la bonne cible...
    14. +
    15. Flèche intangible : ajouter une action avec le code #Attaque -1 --difficulteCarac DEX --ignoreObstacles. Attention, pour l'instant le script ne vérifie pas que l'arme utilisée est bien un arc.
    16. +
    17. Flèches vivantes : ajoutez aux munitions du rang 1 et 2 l'option --if deAttaque 15 --plus 2d6 --message la flèche prend vie au contact du sang --endif.
    18. +
    19. Flèche chercheuse : faire une action avec le code #Attaque -1 --plus 2d6 --portee 1000 --limiteParJour 1 flecheChercheuse.

    Voie de l'expert

    - Reporter les bonus sur la fiche et cr\xE9er les comp\xE9tences ad\xE9quates. + Reporter les bonus sur la fiche et créer les compétences adéquates.

    Voie de l'expert du combat

      -
    1. Expertise du combat : cr\xE9er un pr\xE9dicat expertDuCombat avec comme valeur le rang dans la voie. La commande !cof-statut donne un \xE9tat des lieux des d\xE9s d\xE9pens\xE9s pendant le combat/le tour. Les d\xE9s ne sont actifs qu'en combat et sont r\xE9initialis\xE9s \xE0 l'utilisation de !cof-fin-combat. L'impl\xE9mentation part du principe que l'augmentation de la DEF doit \xEAtre d\xE9cid\xE9e avant le jet de dommages, comme une esquive acrobatique par exemple.
    2. +
    3. Expertise du combat : créer un prédicat expertDuCombat avec comme valeur le rang dans la voie. La commande !cof-statut donne un état des lieux des dés dépensés pendant le combat/le tour. Les dés ne sont actifs qu'en combat et sont réinitialisés à l'utilisation de !cof-fin-combat. L'implémentation part du principe que l'augmentation de la DEF doit être décidée avant le jet de dommages, comme une esquive acrobatique par exemple.
    4. Bousculer : !cof-expert-combat-bousculer @{selected|token_id} @{target|token_id}
    5. -
    6. Expertise sup\xE9rieure : il suffit de mettre \xE0 jour la valeur du pr\xE9dicat expertDuCombat ; le script automatise la mise \xE0 jour des limites et la possibilit\xE9 d'augmenter les DM.
    7. -
    8. D\xE9placement tactique : pas de support sp\xE9cifique pour le d\xE9placement, mais on peut pr\xE9voir une action !cof-expert-combat pour le personnage, qui ne fera qu'une d\xE9pense simple de d\xE9 d'expertise.
    9. -
    10. Expertise majeure : les limites de d\xE9s par tour sont automatiques avec la bonne valeur du pr\xE9dicat expertDuCombat. Pour l'instant le cumul de d\xE9s sur le m\xEAme jet n'est pas support\xE9.
    11. +
    12. Expertise supérieure : il suffit de mettre à jour la valeur du prédicat expertDuCombat ; le script automatise la mise à jour des limites et la possibilité d'augmenter les DM.
    13. +
    14. Déplacement tactique : pas de support spécifique pour le déplacement, mais on peut prévoir une action !cof-expert-combat pour le personnage, qui ne fera qu'une dépense simple de dé d'expertise.
    15. +
    16. Expertise majeure : les limites de dés par tour sont automatiques avec la bonne valeur du prédicat expertDuCombat. Pour l'instant le cumul de dés sur le même jet n'est pas supporté.

    Voie de l'homme du peuple

    - Reporter les bonus sur la fiche et cr\xE9er les comp\xE9tences ad\xE9quates. + Reporter les bonus sur la fiche et créer les compétences adéquates.

    Voie de la fusion lycanthropique

      -
    1. Lycanthropie : !cof-effet-temp lycanthropie [[5*@{selected|SAG}]]. Si vous souhaitez un changement d'image du token, utilisez un token \xE0 plusieurs faces. Dans la liste des faces, en partant de 0, on note n le num\xE9ro de la face qui contient l'image de loup-garou. Ajoutez alors --tokenSide n \xE0 la commande. Par exemple, si la premi\xE8re face est l'image normale du personnage, et la seconde face celle d'un loup-garou, on pourra utiliser !cof-effet-temp lycanthropie [[5*@{selected|SAG}]] --tokenSide 1.
    2. -
    3. \xC9ventration : ajouter un pr\xE9dicat lycanthropeEventre.
    4. +
    5. Lycanthropie : !cof-effet-temp lycanthropie [[5*@{selected|SAG}]]. Si vous souhaitez un changement d'image du token, utilisez un token à plusieurs faces. Dans la liste des faces, en partant de 0, on note n le numéro de la face qui contient l'image de loup-garou. Ajoutez alors --tokenSide n à la commande. Par exemple, si la première face est l'image normale du personnage, et la seconde face celle d'un loup-garou, on pourra utiliser !cof-effet-temp lycanthropie [[5*@{selected|SAG}]] --tokenSide 1.
    6. +
    7. Éventration : ajouter un prédicat lycanthropeEventre.

    Voie de Morn

      -
    1. Secrets de l'au-del\xE0 : !cof-effet-temp secretsDeLAuDela 1 --mana 0
    2. +
    3. Secrets de l'au-delà : !cof-effet-temp secretsDeLAuDela 1 --mana 0
    4. Souffle de vie : !cof-soin @{selected|token_id} @{target|token_id} souffleDeVie --mana 0
    5. -
    6. Souffle de mort : faire une attaque magique, de port\xE9e 20 m (la port\xE9e par d\xE9faut pour les sorts, mais rien n'est sp\xE9cifi\xE9 dans le texte), de d\xE9g\xE2ts 2d8+INT. Ajoutez auto dans les modificateurs. Pour les options, --disque 10 souffleDeMort --effet souffleDeMort 1 --save CON 10 --mana 1.
    7. +
    8. Souffle de mort : faire une attaque magique, de portée 20 m (la portée par défaut pour les sorts, mais rien n'est spécifié dans le texte), de dégâts 2d8+INT. Ajoutez auto dans les modificateurs. Pour les options, --disque 10 souffleDeMort --effet souffleDeMort 1 --save CON 10 --mana 1.
    -

    Voie de Prestige sp\xE9cialis\xE9e

    +

    Voie de Prestige spécialisée

      -
    1. Expertise : ajouter un pr\xE9dicat expertiseSpecialisee, de valeur soit une caract\xE9ristique, soit une comp\xE9tence, soit un mot-cl\xE9 pour une capacit\xE9. Pour l'instant, ne sont impl\xE9ment\xE9s que la rage du berserk (rageDuBerserk) et la furie du berserk (furieDuBerserk).
    2. +
    3. Expertise : ajouter un prédicat expertiseSpecialisee, de valeur soit une caractéristique, soit une compétence, soit un mot-clé pour une capacité. Pour l'instant, ne sont implémentés que la rage du berserk (rageDuBerserk) et la furie du berserk (furieDuBerserk).
    -

    Voie de P\xE9rind\xE9

    +

    Voie de Périndé

    1. Soutient
    2. -
    3. Pr\xE9sence r\xE9confortante
    4. +
    5. Présence réconfortante
    6. Prendre sur soit
    7. -
    8. D\xE9fendre les siens
    9. -
    10. Don de soi : !cof-soin @{selected|token_id} ?{Nombre de d\xE9s?|1|2|3|4|5}d6 --allies 10 --sacrifierPV --mana 3
    11. +
    12. Défendre les siens
    13. +
    14. Don de soi : !cof-soin @{selected|token_id} ?{Nombre de dés?|1|2|3|4|5}d6 --allies 10 --sacrifierPV --mana 3
    -

    Voie des armes \xE0 deux mains

    +

    Voie des armes à deux mains

      -
    1. Allonge : reporter le bonus d'attaque sur la fiche. Par facilit\xE9, j'ai consid\xE9r\xE9 que le bonus d'Init \xE9tait permanent et nous l'avons report\xE9 sur la fiche.
    2. -
    3. Gros Monstre, grosse arme : ajouter un pr\xE9dicat grosMonstreGrosseArme.
    4. -
    5. Tenir \xE0 distance (L) : !cof-effet-temp tenirADistance 1.
    6. -
    7. Attaque \xE0 outrance : !cof-attaque-a-outrance ?{Attaque \xE0 outrance ?|Non,0|-2 DEF / +1D6 DM,2}. Par facilit\xE9, cette "posture de combat" perdure jusqu'\xE0 la fin du combat ou jusqu'\xE0 ce que le guerrier en change. Au rang 5, on pourra utiliser !cof-attaque-a-outrance ?{Attaque \xE0 outrance ?|Non,0|-2 DEF/+1D6 DM,2|-5 DEF/+2D6 DM,5}
    8. -
    9. Critique destructeur : ajouter --plusCrit 2d6 aux attaques d'armes \xE0 2 mains
    10. +
    11. Allonge : reporter le bonus d'attaque sur la fiche. Par facilité, j'ai considéré que le bonus d'Init était permanent et nous l'avons reporté sur la fiche.
    12. +
    13. Gros Monstre, grosse arme : ajouter un prédicat grosMonstreGrosseArme.
    14. +
    15. Tenir à distance (L) : !cof-effet-temp tenirADistance 1.
    16. +
    17. Attaque à outrance : !cof-attaque-a-outrance ?{Attaque à outrance ?|Non,0|-2 DEF / +1D6 DM,2}. Par facilité, cette "posture de combat" perdure jusqu'à la fin du combat ou jusqu'à ce que le guerrier en change. Au rang 5, on pourra utiliser !cof-attaque-a-outrance ?{Attaque à outrance ?|Non,0|-2 DEF/+1D6 DM,2|-5 DEF/+2D6 DM,5}
    18. +
    19. Critique destructeur : ajouter --plusCrit 2d6 aux attaques d'armes à 2 mains

    Voie des vermines

      -
    1. Nu\xE9e de criquets : ajouter une attaque magique, de port\xE9e 20 m, type Sortilege, modificateur pasDeDmg et options --effet nueeDeCriquets [[5+@{selected|SAG}]]. Pas de support particulier pour les DM de zone qui d\xE9truisent la nu\xE9e (enlever l'attribut nueeDeCriquets sur la cible dans ce cas).
    2. +
    3. Nuée de criquets : ajouter une attaque magique, de portée 20 m, type Sortilege, modificateur pasDeDmg et options --effet nueeDeCriquets [[5+@{selected|SAG}]]. Pas de support particulier pour les DM de zone qui détruisent la nuée (enlever l'attribut nueeDeCriquets sur la cible dans ce cas).

    Voie du chasseur de corruption

    -

    Pour savoir si une cible est corrompue, le script va utiliser un pr\xE9dicat corrompu qu'il appartient au MJ d'ajouter pour les cr\xE9atures selon ses crit\xE8res.

    +

    Pour savoir si une cible est corrompue, le script va utiliser un prédicat corrompu qu'il appartient au MJ d'ajouter pour les créatures selon ses critères.

    1. Sentir la corruption : !cof-sentir-la-corruption @{selected|token_id} @{target|token_id}.
    2. -
    3. Combattre la corruption : ajouter un pr\xE9dicat combattreLaCorruption. Y associer la valeur 2 au rang 4 dans la voie.
    4. -
    5. Chasseur de sorci\xE8re : ajouter un pr\xE9dicat chasseurDeSorciere. Pour reconna\xEEtre les n\xE9cromanciens et autres pr\xEAtres mal\xE9fiques, il faut aussi leur ajouter un pr\xE9dicat necromancien.
    6. -
    7. Frappe pr\xE9ventive : pas de support du script.
    8. +
    9. Combattre la corruption : ajouter un prédicat combattreLaCorruption. Y associer la valeur 2 au rang 4 dans la voie.
    10. +
    11. Chasseur de sorcière : ajouter un prédicat chasseurDeSorciere. Pour reconnaître les nécromanciens et autres prêtres maléfiques, il faut aussi leur ajouter un prédicat necromancien.
    12. +
    13. Frappe préventive : pas de support du script.

    Voie du chevalier dragon

      -
    1. Ordre du chevalier dragon : cr\xE9er les comp\xE9tences Persuasion et Intimidation avec les bonus de base de +5. Ajouter un pr\xE9dicat ordreDuChevalierDragon. Quand le personnage est mont\xE9, le script rajoutera automatiquement un bonus de +5 via !cof-jet
    2. -
    3. \xC9p\xE9e de feu : !cof-effet-temp armeEnflammee [[5+@{selected|CHA}]] --lanceur @{selected|token_id} --target @{selected|token_id}. Ne se cumule pas avec l'Arme enflamm\xE9e du Magicien.
    4. -
    5. R\xE9sistance au feu : rajouter feu:5 (ou 10 au rang 5) dans la partie RD de la fiche
    6. +
    7. Ordre du chevalier dragon : créer les compétences Persuasion et Intimidation avec les bonus de base de +5. Ajouter un prédicat ordreDuChevalierDragon. Quand le personnage est monté, le script rajoutera automatiquement un bonus de +5 via !cof-jet
    8. +
    9. Épée de feu : !cof-effet-temp armeEnflammee [[5+@{selected|CHA}]] --lanceur @{selected|token_id} --target @{selected|token_id}. Ne se cumule pas avec l'Arme enflammée du Magicien.
    10. +
    11. Résistance au feu : rajouter feu:5 (ou 10 au rang 5) dans la partie RD de la fiche
    12. Monture puissante : modifier la fiche du Drake
    13. -
    14. Souffle enflamm\xE9 : ajouter une attaque au dragon, m\xEAme jet pour touche, dm 2d6, port\xE9e 40, arme naturelle qui inflige des d\xE9g\xE2ts de feu, avec comme options --disque 3 --dmSiRate 1d6 --dmCible 4d6
    15. +
    16. Souffle enflammé : ajouter une attaque au dragon, même jet pour touche, dm 2d6, portée 40, arme naturelle qui inflige des dégâts de feu, avec comme options --disque 3 --dmSiRate 1d6 --dmCible 4d6
    -

    Voie du combat \xE0 deux armes

    +

    Voie du combat à deux armes

      -
    1. Combat \xE0 deux armes am\xE9lior\xE9 : mettre une des attaques de type arme gauche, et y ajouter le modificateur avecd12crit. Pas encore de support pour la capacit\xE9 avanc\xE9e : dans ce cas, ajoutez le +1 dans la barre 3 du token ou sur les attaques.
    2. -
    3. Parade crois\xE9e : !cof-effet-temp paradeCroisee 1 --valeur rang --montreActions o\xF9 rang est le rang dans la Voie.
    4. +
    5. Combat à deux armes amélioré : mettre une des attaques de type arme gauche, et y ajouter le modificateur avecd12crit. Pas encore de support pour la capacité avancée : dans ce cas, ajoutez le +1 dans la barre 3 du token ou sur les attaques.
    6. +
    7. Parade croisée : !cof-effet-temp paradeCroisee 1 --valeur rang --montreActionsrang est le rang dans la Voie.

    Voie du danseur de guerre

      -
    1. Pirouettes : on peut rajouter les bonus sur la fiche, ou bien ajouter un pr\xE9dicat pirouettes, de valeur le bonus en d\xE9fense (qui ne s'applique que si le malus d'armure est inf\xE9rieur \xE0 4).
    2. -
    3. Vent des lames : pas de support du script, simplement ajouter les attaques adapt\xE9es sur la fiche
    4. +
    5. Pirouettes : on peut rajouter les bonus sur la fiche, ou bien ajouter un prédicat pirouettes, de valeur le bonus en défense (qui ne s'applique que si le malus d'armure est inférieur à 4).
    6. +
    7. Vent des lames : pas de support du script, simplement ajouter les attaques adaptées sur la fiche
    8. Attaque en mouvement : pas de support du script.
    9. -
    10. Danse des lames : !cof-effet-combat danseDesLames. Pour l'attaque gratuite suppl\xE9mentaire, on peut faire #Attaque -1 --si etat danseDesLames --avecd12crit.
    11. +
    12. Danse des lames : !cof-effet-combat danseDesLames. Pour l'attaque gratuite supplémentaire, on peut faire #Attaque -1 --si etat danseDesLames --avecd12crit.

    Voie du familier fantastique

      -
    1. Familier fantastique : cr\xE9er un personnage (de type PNJ) pour le familier, control\xE9 par le joueur et avec un token li\xE9 ayant la capacit\xE9 de voir. +
    2. Familier fantastique : créer un personnage (de type PNJ) pour le familier, controlé par le joueur et avec un token lié ayant la capacité de voir.
        -
      • Pour le bonus en initiative, ajouter au personnage un pr\xE9dicat familier de valeur le nom du compagnon (doit \xEAtre exactement le m\xEAme que celui du token du compagnon). Cela automatise l'initiative quand le familier est pr\xE9sent.
      • -
      • Pour les points de vie partag\xE9s avec le familier, il faut mettre un pr\xE9dicat PVPartagesAvec de valeur le nom du familier (celui de la fiche, pas forc\xE9ment le m\xEAme que le token) pour le personnage, et un pr\xE9dicat similaire chez le familier, de valeur le nom du personnage. Le partage de PVs ne fonctionne pas avec des mooks, et il ne fait pas le partage de d\xE9g\xE2ts temporaires. En revanche, le script devrait g\xE9rer correctement les d\xE9g\xE2ts de zone.
      • -
      • Pour la d\xE9fense du familier, ajouter lui un pr\xE9dicat defDeriveeDe, de valeur le nom du personnage (nom complet sur la fiche, attention \xE0 bien utiliser la syntaxe avec :: si ce nom contient des espaces ou d'autres caract\xE8res sp\xE9ciaux).
      • -
      • Pour l'initiative, ajoutez un pr\xE9dicat initiativeDeriveeDe de valeur le nom du personnage.
      • +
      • Pour le bonus en initiative, ajouter au personnage un prédicat familier de valeur le nom du compagnon (doit être exactement le même que celui du token du compagnon). Cela automatise l'initiative quand le familier est présent.
      • +
      • Pour les points de vie partagés avec le familier, il faut mettre un prédicat PVPartagesAvec de valeur le nom du familier (celui de la fiche, pas forcément le même que le token) pour le personnage, et un prédicat similaire chez le familier, de valeur le nom du personnage. Le partage de PVs ne fonctionne pas avec des mooks, et il ne fait pas le partage de dégâts temporaires. En revanche, le script devrait gérer correctement les dégâts de zone.
      • +
      • Pour la défense du familier, ajouter lui un prédicat defDeriveeDe, de valeur le nom du personnage (nom complet sur la fiche, attention à bien utiliser la syntaxe avec :: si ce nom contient des espaces ou d'autres caractères spéciaux).
      • +
      • Pour l'initiative, ajoutez un prédicat initiativeDeriveeDe de valeur le nom du personnage.
    3. Pouvoir mineur :
        -
      • Minimoi (\xC9gocentrisme) : T\xE9l\xE9portation, pas de support.
      • +
      • Minimoi (Égocentrisme) : Téléportation, pas de support.
    4. Canalisation : Lancer l'attaque avec l'option --canaliseParFamilier.
    5. -
    6. Pouvoir sup\xE9rieur : +
    7. Pouvoir supérieur :
        -
      • Minimoi (Clone) : \xE0 faire.
      • +
      • Minimoi (Clone) : à faire.
    @@ -2208,326 +2221,326 @@

    Voie du gel

    1. -
    2. C\xF4ne de froid : faire une attaque portee 20m, d\xE9g\xE2ts 2d6+INT de froid, avec comme modificateur auto et comme options --cone 30 --fx breath-frost --ifSaveFails CON 13 --effet ralenti 1 --else --diviseDmg 2 --endif. Pour un objet de sort : !cof-attack @{selected|token_id} @{target|token_id} C\xF4ne de froid --sortilege --auto --dm 2d6+[[@{selected|INT}]] --froid --portee 20 --cone 30 --fx breath-frost --ifSaveFails CON 13 --effet ralentiTemp 1 --else --diviseDmg 2 --endif
    3. -
    4. Pr\xE9sence glaciale : !cof-effet presenceGlaciale oui. Utiliser !cof-effet presenceGlaciale non pour mettre fin \xE0 l'effet. On peut pr\xE9ciser un bonus de DEF et des d\xE9g\xE2ts diff\xE9rents avec l'option --valeur. Ainsi, la version grimoire sera !cof-effet presenceGlaciale oui --valeur 3 1d4.
    5. +
    6. Cône de froid : faire une attaque portee 20m, dégâts 2d6+INT de froid, avec comme modificateur auto et comme options --cone 30 --fx breath-frost --ifSaveFails CON 13 --effet ralenti 1 --else --diviseDmg 2 --endif. Pour un objet de sort : !cof-attack @{selected|token_id} @{target|token_id} Cône de froid --sortilege --auto --dm 2d6+[[@{selected|INT}]] --froid --portee 20 --cone 30 --fx breath-frost --ifSaveFails CON 13 --effet ralentiTemp 1 --else --diviseDmg 2 --endif
    7. +
    8. Présence glaciale : !cof-effet presenceGlaciale oui. Utiliser !cof-effet presenceGlaciale non pour mettre fin à l'effet. On peut préciser un bonus de DEF et des dégâts différents avec l'option --valeur. Ainsi, la version grimoire sera !cof-effet presenceGlaciale oui --valeur 3 1d4.
    -

    Voie du gu\xE9risseur

    +

    Voie du guérisseur

      -
    1. Premiers soins : ajouter un pr\xE9dicat voieDuGuerisseur de valeur le rang dans cette voie pour le bonus aux soins de la Voie des soins. Pour le sort, faire !cof-soin @{selected|token_id} @{target|token_id} premiersSoins --mana 0.
    2. -
    3. Immunit\xE9 : utilisez !cof-immunite-guerisseur [[1d6+@{selected|SAG}]] --mana 0 --target @{target|token_id} dans les actions du tour. Si utilis\xE9 directement dans le chat, ajoutez --lanceur @{selected|token_id}.
    4. +
    5. Premiers soins : ajouter un prédicat voieDuGuerisseur de valeur le rang dans cette voie pour le bonus aux soins de la Voie des soins. Pour le sort, faire !cof-soin @{selected|token_id} @{target|token_id} premiersSoins --mana 0.
    6. +
    7. Immunité : utilisez !cof-immunite-guerisseur [[1d6+@{selected|SAG}]] --mana 0 --target @{target|token_id} dans les actions du tour. Si utilisé directement dans le chat, ajoutez --lanceur @{selected|token_id}.
    8. Soins rapides : pas de support au niveau du script.
    9. -
    10. Zone de vie : !cof-zone-de-vie [[1d6+@{selected|SAG}]] --mana 1 --limiteParJour 3 --lanceur @{selected|token_id}. Cela devrait respecter le sort, sauf pour le moment o\xF9 le soin prend effet : c'est au d\xE9but de chaque tour du pr\xEAtre.
    11. +
    12. Zone de vie : !cof-zone-de-vie [[1d6+@{selected|SAG}]] --mana 1 --limiteParJour 3 --lanceur @{selected|token_id}. Cela devrait respecter le sort, sauf pour le moment où le soin prend effet : c'est au début de chaque tour du prêtre.

    Voie du guerrier-mage

    -

    Penser \xE0 utiliser l'option --magieEnArmure pour le lancement des sorts affect\xE9s.

    +

    Penser à utiliser l'option --magieEnArmure pour le lancement des sorts affectés.

      -
    1. Magie en armure : Ajouter un pr\xE9dicat magieEnArmure de valeur la DEF totale \xE0 partir de laquelle le personnage peut lancer des sorts. Comme la fiche ne contient pas l'information de la DEF normale (sans magie) de l'armure port\xE9e, le script utilise la moyenne de la DEF et du malus d'armure. En ajoutant un pr\xE9dicat magieEnArmureFacilitee, le script diminue aussi la difficult\xE9 des jets d'INT pour les armures avec une DEF trop grande de la valeur du pr\xE9dicat de magie en armure.
    2. -
    3. Rituel Assur\xE9 : !cof-effet-temp rituelAssure 2 --mana 0. Le script ne permet pas de pr\xE9ciser le sort, le premier qui sera lanc\xE9 apr\xE8s le rituel assur\xE9 b\xE9n\xE9ficiera de l'effet.
    4. -
    5. MagieDeCombat : Ajouter un pr\xE9dicat magieDeCombat.
    6. +
    7. Magie en armure : Ajouter un prédicat magieEnArmure de valeur la DEF totale à partir de laquelle le personnage peut lancer des sorts. Comme la fiche ne contient pas l'information de la DEF normale (sans magie) de l'armure portée, le script utilise la moyenne de la DEF et du malus d'armure. En ajoutant un prédicat magieEnArmureFacilitee, le script diminue aussi la difficulté des jets d'INT pour les armures avec une DEF trop grande de la valeur du prédicat de magie en armure.
    8. +
    9. Rituel Assuré : !cof-effet-temp rituelAssure 2 --mana 0. Le script ne permet pas de préciser le sort, le premier qui sera lancé après le rituel assuré bénéficiera de l'effet.
    10. +
    11. MagieDeCombat : Ajouter un prédicat magieDeCombat.
    12. Frappe des arcanes : faire une attaque avec l'option --frappeDesArcanes, par exemple dans une action dont le code serait #Attaque -1 --frappeDesArcanes.
    13. Expertise du combat : aucun support du script.
    -

    Voie du h\xE9ro

    +

    Voie du héro

      -
    1. Destin h\xE9ro\xEFque : ajouter le bonus au bonus de points de chances sur la fiche (utiliser la roue crant\xE9e \xE0 droite de la section CHANCE de la fiche).
    2. -
    3. T\xE9nacit\xE9 : ajouter un pr\xE9dicat tenacite.
    4. +
    5. Destin héroïque : ajouter le bonus au bonus de points de chances sur la fiche (utiliser la roue crantée à droite de la section CHANCE de la fiche).
    6. +
    7. Ténacité : ajouter un prédicat tenacite.
    8. Homme de la situation : pas de support.
    9. -
    10. Meneur d'hommes : Ajouter une action : !cof-set-attribute meneurDHommesCible @{selected|token_id} --target @{target|token_id}. Le personnage peut utiliser cette action pour d\xE9signer sa cible. Tous les alli\xE9s du personnage recevront automatiquement les bonus sur le reste du combat.
    11. +
    12. Meneur d'hommes : Ajouter une action : !cof-set-attribute meneurDHommesCible @{selected|token_id} --target @{target|token_id}. Le personnage peut utiliser cette action pour désigner sa cible. Tous les alliés du personnage recevront automatiquement les bonus sur le reste du combat.
    -

    Voie du ma\xEEtre des poisons

    +

    Voie du maître des poisons

    Rappel : pour appliquer un poison, utiliser !cof-enduire-poison -1 type force save.
      -
    1. Connaissance du poison : ajouter un pr\xE9dicat connaissanceDuPoison pour \xE9viter le test d'INT quand le voleur applique du poison.
    2. -
    3. Poison rapide : faire les applications \xE0 la main (!cof-enduire-poison L rapide 2d6 12).
    4. -
    5. Poison affaiblissant : faire les applications \xE0 la main (!cof-enduire-poison L affaiblissant 0 15).
    6. +
    7. Connaissance du poison : ajouter un prédicat connaissanceDuPoison pour éviter le test d'INT quand le voleur applique du poison.
    8. +
    9. Poison rapide : faire les applications à la main (!cof-enduire-poison L rapide 2d6 12).
    10. +
    11. Poison affaiblissant : faire les applications à la main (!cof-enduire-poison L affaiblissant 0 15).

    Voie du messager

    1. Muet comme une tombe : pas de support pour l'instant.
    2. -
    3. Jusqu'\xE0 bon port : ajouter les comp\xE9tences correspondantes sur la fiche.
    4. -
    5. Conducteur de diligence : ajouter les comp\xE9tences, et en cas de combat depuis une diligence, utiliser la barre 3 pour le bonus \xE0 l'attaque.
    6. +
    7. Jusqu'à bon port : ajouter les compétences correspondantes sur la fiche.
    8. +
    9. Conducteur de diligence : ajouter les compétences, et en cas de combat depuis une diligence, utiliser la barre 3 pour le bonus à l'attaque.
    10. Sens du devoir : Activer avec !cof-effet sensDuDevoir true. On peut enlever cet effet depuis le statut, au changement de jour, ou avec la commande !cof-effet sensDuDevoir false.
    11. Attaque en mouvement : pas de support pour l'instant.

    Voie du pacte vampirique

      -
    1. Blessure sanglante : ajuter un pr\xE9dicat blessureSanglante.
    2. -
    3. Sang puissant : ajouter un pr\xE9dicat immuniteSaignement et un pr\xE9dicat immuniteAbsorptionVampire.
    4. -
    5. Drain de sang : ajouter un pr\xE9dicat drainDeSang.
    6. -
    7. Flot de sang : associer la valeur 2 au pr\xE9dicat blessureSanglante.
    8. -
    9. \xC9nergie impie : ajouter un pr\xE9dicat energieImpie.
    10. +
    11. Blessure sanglante : ajuter un prédicat blessureSanglante.
    12. +
    13. Sang puissant : ajouter un prédicat immuniteSaignement et un prédicat immuniteAbsorptionVampire.
    14. +
    15. Drain de sang : ajouter un prédicat drainDeSang.
    16. +
    17. Flot de sang : associer la valeur 2 au prédicat blessureSanglante.
    18. +
    19. Énergie impie : ajouter un prédicat energieImpie.

    Voie du porteur de bouclier

      -
    1. Expertise du bouclier : reporter le bonus sur la fiche dans le bonus de DEF conf\xE9r\xE9 par le bouclier.
    2. -
    3. Progresser \xE0 couvert : !cof-effet-temp progresserACouvert 1 --lanceur @{selected|token_id} --target @{target|token_id} --self --portee 1. A utiliser pour cibler un alli\xE9 \xE0 port\xE9e si n\xE9cessaire. Au MJ de v\xE9rifier qu'elle reste bien pr\xE8s du chevalier pour profiter du bonus.
    4. -
    5. Attaque au bouclier : Ajouter une arme avec son Bouclier en "Arme gauche" sur la fiche du personnage. Dans les modificateurs de l'arme, ajoutez avecd12crit. Pour que cette attaque soit propos\xE9e dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un pr\xE9dicat attaqueAuBouclier de valeur le label de l'attaque.
    6. -
    7. D\xE9vier les coups : Ajouter un pr\xE9dicat devierLesCoups (on peut y associer un nombre, si on souhaite plus d'une utlisation par tour). Le script ajoute automatiquement un bouton sur les attaques sur lesquelles cette capacit\xE9 peut-\xEAtre utilis\xE9e.
    8. -
    9. Parade au bouclier : Ajouter un pr\xE9dicat paradeAuBouclier. Sur l'ability Coup de bouclier cr\xE9\xE9 pour le rang 3, ajouter --attaqueBouclierRenverse --decrLimitePredicatParTour paradeAuBouclier. Le script ajoute automatiquement un bouton sur les attaques sur lesquelles cette capacit\xE9 peut-\xEAtre utilis\xE9e. Si le personnage poss\xE8de un bouclier en arme gauche, le script utilisera le bonus \xE9ventuel de l'arme en question sur le jet oppos\xE9.
    10. +
    11. Expertise du bouclier : reporter le bonus sur la fiche dans le bonus de DEF conféré par le bouclier.
    12. +
    13. Progresser à couvert : !cof-effet-temp progresserACouvert 1 --lanceur @{selected|token_id} --target @{target|token_id} --self --portee 1. A utiliser pour cibler un allié à portée si nécessaire. Au MJ de vérifier qu'elle reste bien près du chevalier pour profiter du bonus.
    14. +
    15. Attaque au bouclier : Ajouter une arme avec son Bouclier en "Arme gauche" sur la fiche du personnage. Dans les modificateurs de l'arme, ajoutez avecd12crit. Pour que cette attaque soit proposée dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un prédicat attaqueAuBouclier de valeur le label de l'attaque.
    16. +
    17. Dévier les coups : Ajouter un prédicat devierLesCoups (on peut y associer un nombre, si on souhaite plus d'une utlisation par tour). Le script ajoute automatiquement un bouton sur les attaques sur lesquelles cette capacité peut-être utilisée.
    18. +
    19. Parade au bouclier : Ajouter un prédicat paradeAuBouclier. Sur l'ability Coup de bouclier créé pour le rang 3, ajouter --attaqueBouclierRenverse --decrLimitePredicatParTour paradeAuBouclier. Le script ajoute automatiquement un bouton sur les attaques sur lesquelles cette capacité peut-être utilisée. Si le personnage possède un bouclier en arme gauche, le script utilisera le bonus éventuel de l'arme en question sur le jet opposé.
    -

    Voie du tueur de g\xE9ant

    +

    Voie du tueur de géant

      -
    1. R\xE9duire la distance : ajouter un pr\xE9dicat reduireLaDistance.
    2. -
    3. Ventre mou : ajouter un pr\xE9dicat ventreMou. Cela va diminuer la RD fixe de 3 maximum pour une cr\xE9ature grande, 6 maximum pour une cr\xE9ature \xE9norme et 10 maximum pour une cr\xE9ature colossale.
    4. -
    5. B\xFBcheron : ajouter un pr\xE9dicat bucheron.
    6. +
    7. Réduire la distance : ajouter un prédicat reduireLaDistance.
    8. +
    9. Ventre mou : ajouter un prédicat ventreMou. Cela va diminuer la RD fixe de 3 maximum pour une créature grande, 6 maximum pour une créature énorme et 10 maximum pour une créature colossale.
    10. +
    11. Bûcheron : ajouter un prédicat bucheron.
    -

    Capacit\xE9s \xE9piques

    +

    Capacités épiques

      -
    • Lib\xE9rateur de Dorn : ajouter un pr\xE9dicat liberateurDeDorn.
    • -
    • Lib\xE9rateur de Kerserac : ajouter un pr\xE9dicat liberateurDeKerserac.
    • -
    • Lib\xE9rateur d'Anathazer\xEFn : ajouter un pr\xE9dicat liberateurDAnathazerin. La capacit\xE9 donne le bonus de +2 quel que soit le poison.
    • -
    • Lien \xE9pique: ajouter pour chaque personnage un pr\xE9dicat lienEpique, qui contiennent la m\xEAme chose dans le champ courant (pensez \xE0 un nom d'\xE9quipe, par exemple).
    • -
    • Vitalit\xE9 \xE9pique : ajouter un pr\xE9dicat vitaliteEpique. Pas de support pour le coup mortel ou la r\xE9g\xE9n\xE9ration horaire. Attention, si vous utlisez !cof-soin pour cette r\xE9g\xE9n\xE9ration, les soins seront aussi doubl\xE9s.
    • +
    • Libérateur de Dorn : ajouter un prédicat liberateurDeDorn.
    • +
    • Libérateur de Kerserac : ajouter un prédicat liberateurDeKerserac.
    • +
    • Libérateur d'Anathazerïn : ajouter un prédicat liberateurDAnathazerin. La capacité donne le bonus de +2 quel que soit le poison.
    • +
    • Lien épique: ajouter pour chaque personnage un prédicat lienEpique, qui contiennent la même chose dans le champ courant (pensez à un nom d'équipe, par exemple).
    • +
    • Vitalité épique : ajouter un prédicat vitaliteEpique. Pas de support pour le coup mortel ou la régénération horaire. Attention, si vous utlisez !cof-soin pour cette régénération, les soins seront aussi doublés.
    -

    4.3 Voies de cr\xE9atures

    +

    4.3 Voies de créatures

    Voie du champion

    1. Imparable:
        -
      • Utiliser l'option --m2d20 pour l'action limit\xE9e.
      • -
      • Pour l'effet permanent, utiliser un pr\xE9dicat champion
      • +
      • Utiliser l'option --m2d20 pour l'action limitée.
      • +
      • Pour l'effet permanent, utiliser un prédicat champion
    2. -
    3. Riposte : Ajouter un pr\xE9dicat riposte. Les actions affich\xE9es en cas de riposte seront normalement une attaque avec l'arme en main si il y en a, plus les attaques naturelles coch\xE9es sur la liste d'attaque. Si \xE7a ne convient pas, vous pouvez \xE9crire une liste d'actions nomm\xE9eRipostes (voir les actions du tour).
    4. -
    5. Hausser le ton : ajouter un pr\xE9dicat hausserLeTon.
    6. +
    7. Riposte : Ajouter un prédicat riposte. Les actions affichées en cas de riposte seront normalement une attaque avec l'arme en main si il y en a, plus les attaques naturelles cochées sur la liste d'attaque. Si ça ne convient pas, vous pouvez écrire une liste d'actions nomméeRipostes (voir les actions du tour).
    8. +
    9. Hausser le ton : ajouter un prédicat hausserLeTon.
    -

    Voie du chef d'arm\xE9e

    +

    Voie du chef d'armée

      -
    1. Sergent : ne pas oublier l'action de plus donn\xE9e \xE0 un alli\xE9 par tour. Utiliser un pr\xE9dicat sergent (pour l'attaque ignor\xE9e par combat)
    2. -
    3. Capitaine : pour d\xE9signer le capitaine d'un ensemble de tokens s\xE9lectionn\xE9 (quelle que soit la m\xE9thode), on peut utiliser !cof-capitaine @{selected|token_id} 2, en ajoutant les options de s\xE9lection (comme --target @{target|token_id}). Au lieu de s\xE9lectionner une cible, on peut utiliser le nom d'un token. Si le capitaine fait parti de la s\xE9lection, il sera automatiquement exclu (on ne peut \xEAtre son propre capitaine). Si \xE0 la place de 2, le deuxi\xE8me argument est 0, cela enl\xE8ve le capitaine. L'attribut g\xE9n\xE9r\xE9 est li\xE9 \xE0 un personnage, pas un token sp\xE9cifique, il suffit donc de cibler un token repr\xE9sentant un personnage pour affecter tous les tokens qui repr\xE9sentent ce personnage. Pas de support particulier pour l'attaque suppl\xE9mentaire en cas d'action limit\xE9e.
    4. -
    5. Commandant : il faut ajouter un pr\xE9dicat commandant. La m\xE9thode pour d\xE9signer les personnages sous les ordres du commandant est la m\xEAme que pour le capitaine : !cof-capitaine @{selected|token_id} 3 (notez que la valeur est 3 pour le commandant, et 2 pour le capitaine).
    6. +
    7. Sergent : ne pas oublier l'action de plus donnée à un allié par tour. Utiliser un prédicat sergent (pour l'attaque ignorée par combat)
    8. +
    9. Capitaine : pour désigner le capitaine d'un ensemble de tokens sélectionné (quelle que soit la méthode), on peut utiliser !cof-capitaine @{selected|token_id} 2, en ajoutant les options de sélection (comme --target @{target|token_id}). Au lieu de sélectionner une cible, on peut utiliser le nom d'un token. Si le capitaine fait parti de la sélection, il sera automatiquement exclu (on ne peut être son propre capitaine). Si à la place de 2, le deuxième argument est 0, cela enlève le capitaine. L'attribut généré est lié à un personnage, pas un token spécifique, il suffit donc de cibler un token représentant un personnage pour affecter tous les tokens qui représentent ce personnage. Pas de support particulier pour l'attaque supplémentaire en cas d'action limitée.
    10. +
    11. Commandant : il faut ajouter un prédicat commandant. La méthode pour désigner les personnages sous les ordres du commandant est la même que pour le capitaine : !cof-capitaine @{selected|token_id} 3 (notez que la valeur est 3 pour le commandant, et 2 pour le capitaine).

    Voie du cogneur

      -
    1. Charge : Faire l'attaque avec les arguments --m2d20 --pietine.
    2. -
    3. Enrager : ajouter un pr\xE9dicat peutEnrager.
    4. +
    5. Charger : Faire l'attaque avec les arguments --deplaceDe 30 --m2d20 --pietine.
    6. +
    7. Enrager : ajouter un prédicat peutEnrager.
    8. Percuter : Remplacer --pietine par --percute dans l'attaque de Charge.

    Voie du colosse

      -
    1. Fauchage : ajouter la RD, et ajouter un pr\xE9dicat fauchage, qui va faire automatiquement le renversement si le d\xE9 d'attaque est entre 15 et 20. Il est possible de changer ce seuil associant au pr\xE9dicat la valeur \xE0 laquelle le d\xE9 d'attaque provoque le renversement (15 par d\xE9faut). Par d\xE9faut, le fauchage est impossible si la taille du d\xE9fenseur est sup\xE9rieure ou \xE9gale \xE0 celle de l'attaquant. Vous pouvez sp\xE9cifier un seuil de taille maximale dans un pr\xE9dicat tailleFauchage (5 = grand, 6 \xE9norme et 7 colossal).
    2. +
    3. Fauchage : ajouter la RD, et ajouter un prédicat fauchage, qui va faire automatiquement le renversement si le dé d'attaque est entre 15 et 20. Il est possible de changer ce seuil associant au prédicat la valeur à laquelle le dé d'attaque provoque le renversement (15 par défaut). Par défaut, le fauchage est impossible si la taille du défenseur est supérieure ou égale à celle de l'attaquant. Vous pouvez spécifier un seuil de taille maximale dans un prédicat tailleFauchage (5 = grand, 6 énorme et 7 colossal).
    4. Balayage : faire une version de l'attaque avec --target @{target|Cible 2|token_id}
    5. -
    6. Projection : ajouter un pr\xE9dicat projection.
    7. +
    8. Projection : ajouter un prédicat projection.
    -

    Voie des cr\xE9atures \xE9l\xE9mentaires

    -

    Ajouter un pr\xE9dicat immunite_type, o\xF9 type est le type de la cr\xE9ature \xE9l\xE9mentaire (feu, acide, froid, ...)

    +

    Voie des créatures élémentaires

    +

    Ajouter un prédicat immunite_type, où type est le type de la créature élémentaire (feu, acide, froid, ...)

      -
    1. Souffle : faire une attaque avec le bon nombre de d6 en DM, du type voulu, de port\xE9e la port\xE9e du souffle, \xE0 utiliser avec les modificateurs auto cone et les options --tempsRecharge rechargeSouffle [[1d4]] --psave DEX 13. Ne pas oublier la possibilit\xE9 d'utiliser un token cible temporaire pour le cone.
    2. -
    3. Corps \xE9l\xE9mentaire : ajouter un pr\xE9dicat corpsElementaire, de valeur l'\xE9l\xE9ment (feu, froid,...). Cela va automatiquement ajouter les d\xE9g\xE2ts aux attaques de contact, et faire des d\xE9g\xE2ts \xE0 ceux qui l'attaquent au contact. Cela va aussi faire appara\xEEtre dans les actions du tour une action de r\xE9g\xE9neration, que le MJ peut utiliser chaque tour, \xE0 lui de voir si les conditions s'y pr\xEAtent (source \xE9l\xE9mentaire proche). Pas de support g\xE9n\xE9rique pour les victimes saisies ou agripp\xE9es, \xE0 g\xE9rer au cas par cas.
    4. -
    5. Explosion finale : ajouter un pr\xE9dicat explosionFinale de valeur le label de l'attaque d'explosion. Cette attaque ne doit contenir aucune demande de valeur (de type ?{Munitions}). Par exemple, pour une explosion finale qui fait 3d6 DM \xE0 tout le monde dans les 10 m et qui permettrait de diviser les d\xE9g\xE2ts par 2 par un test de DEX difficulte 13 (18 si au contact) : on cr\xE9e une attaque Explosion, de d\xE9g\xE2ts 3d6 du type voulu, de port\xE9e 10, de modificateur auto et avec l'option --psave DEX 13 contact 18. Pour changer les d\xE9g\xE2ts du corps \xE9l\xE9mentaire, on peut utiliser un pr\xE9dicat nbCorpsElementaire de valeur le nombre de d6 \xE0 utiliser (2 normalement pour cette capacit\xE9).
    6. +
    7. Souffle : faire une attaque avec le bon nombre de d6 en DM, du type voulu, de portée la portée du souffle, à utiliser avec les modificateurs auto cone et les options --tempsRecharge rechargeSouffle [[1d4]] --psave DEX 13. Ne pas oublier la possibilité d'utiliser un token cible temporaire pour le cone.
    8. +
    9. Corps élémentaire : ajouter un prédicat corpsElementaire, de valeur l'élément (feu, froid,...). Cela va automatiquement ajouter les dégâts aux attaques de contact, et faire des dégâts à ceux qui l'attaquent au contact. Cela va aussi faire apparaître dans les actions du tour une action de régéneration, que le MJ peut utiliser chaque tour, à lui de voir si les conditions s'y prêtent (source élémentaire proche). Pas de support générique pour les victimes saisies ou agrippées, à gérer au cas par cas.
    10. +
    11. Explosion finale : ajouter un prédicat explosionFinale de valeur le label de l'attaque d'explosion. Cette attaque ne doit contenir aucune demande de valeur (de type ?{Munitions}). Par exemple, pour une explosion finale qui fait 3d6 DM à tout le monde dans les 10 m et qui permettrait de diviser les dégâts par 2 par un test de DEX difficulte 13 (18 si au contact) : on crée une attaque Explosion, de dégâts 3d6 du type voulu, de portée 10, de modificateur auto et avec l'option --psave DEX 13 contact 18. Pour changer les dégâts du corps élémentaire, on peut utiliser un prédicat nbCorpsElementaire de valeur le nombre de d6 à utiliser (2 normalement pour cette capacité).
    -

    Voie des cr\xE9atures magique

    +

    Voie des créatures magique

      -
    1. R\xE9duction des DM : Ajouter la RD sur la fiche 5/genre, o\xF9 genre peut \xEAtre magique ou un des types d'attaque (feu, acide, poison, etc...).
    2. -
    3. Vitalit\xE9 surnaturelle : ajouter un pr\xE9dicat vitaliteSurnaturelle, de valeur le nombre de PV r\xE9g\xE9n\xE9r\xE9 par tour. Si la r\xE9g\xE9n\xE9ration doit continuer m\xEAme \xE0 la mort du personnage, ajoutez un + \xE0 la fin de la valeur. Si un type de d\xE9g\xE2t emp\xEAche la r\xE9g\xE9n\xE9ration, faites suivre la valeur de r\xE9g\xE9n\xE9ration d'un / suivi du type (attention, \xE7a ne peut pas \xEAtre le type drain). Si plusieurs types de d\xE9g\xE2ts, les s\xE9parer par une virgule (et dans ce cas, penser \xE0 utiliser la syntaxe avec ::. Par exemple, un troll aura un pr\xE9dicat vitaliteSurnaturelle:: 5+ / feu, acide, en faisant attention \xE0 ne rien mettre ensuite sur la m\xEAme ligne. Si vous voulez r\xE9initialiser les d\xE9g\xE2ts qui ne peuvent pas se r\xE9g\xE9n\xE9rer sur un personnage, vous pouvez utiliser des soins normaux (!cof-soin), et si vous avez augment\xE9 \xE0 la main les PVs, vous pouvez effacer les attributs DMSuivistype qui ont \xE9t\xE9 cr\xE9\xE9s par le script. Pour emp\xEAcher la r\xE9g\xE9n\xE9ration m\xEAme mort, le mieux est d'enlever le token de la page (ou de le mettre en token g\xE9n\xE9rique).
    4. +
    5. Réduction des DM : Ajouter la RD sur la fiche 5/genre, où genre peut être magique ou un des types d'attaque (feu, acide, poison, etc...).
    6. +
    7. Vitalité surnaturelle : ajouter un prédicat vitaliteSurnaturelle, de valeur le nombre de PV régénéré par tour. Si la régénération doit continuer même à la mort du personnage, ajoutez un + à la fin de la valeur. Si un type de dégât empêche la régénération, faites suivre la valeur de régénération d'un / suivi du type (attention, ça ne peut pas être le type drain). Si plusieurs types de dégâts, les séparer par une virgule (et dans ce cas, penser à utiliser la syntaxe avec ::. Par exemple, un troll aura un prédicat vitaliteSurnaturelle:: 5+ / feu, acide, en faisant attention à ne rien mettre ensuite sur la même ligne. Si vous voulez réinitialiser les dégâts qui ne peuvent pas se régénérer sur un personnage, vous pouvez utiliser des soins normaux (!cof-soin), et si vous avez augmenté à la main les PVs, vous pouvez effacer les attributs DMSuivistype qui ont été créés par le script. Pour empêcher la régénération même mort, le mieux est d'enlever le token de la page (ou de le mettre en token générique).
    -

    Voie des cr\xE9atures volantes

    -

    On peut mettre un pr\xE9dicat volant pour immuniser la cr\xE9ature \xE0 certains effets qui ne peuvent affecter que des cr\xE9atures terrestres, comme l'arm\xE9e des morts ou le croc-en-jambe.

    +

    Voie des créatures volantes

    +

    On peut mettre un prédicat volant pour immuniser la créature à certains effets qui ne peuvent affecter que des créatures terrestres, comme l'armée des morts ou le croc-en-jambe.

      -
    1. Vol rapide : simplement faire une variante de l'attaque avec les options --bonusAttaque 5 --plus 1d6 \xE0 utiliser le premier tour de combat si a cr\xE9ature est en vol et attaque une cr\xE9ature au sol. Ne pas oublier l'action de mouvement suppl\xE9mentaire en vol.
    2. -
    3. Agripper : ajouter un pr\xE9dicat agripper (ne fera agripper que sur les attaques de contact).
    4. +
    5. Vol rapide : simplement faire une variante de l'attaque avec les options --bonusAttaque 5 --plus 1d6 à utiliser le premier tour de combat si a créature est en vol et attaque une créature au sol. Ne pas oublier l'action de mouvement supplémentaire en vol.
    6. +
    7. Agripper : ajouter un prédicat agripper (ne fera agripper que sur les attaques de contact).

    Voie de la magie de combat

    1. Attaque magique : simplement une attaque, avec les options --sortilege --magique --fx beam-magic. Pour la version de zone, utiliser les options --disque 5 --auto --psave DEX 10.
    2. Armure magique : utiliser !cof-effet-combat armureMagique
    -

    Voie de la magie de gu\xE9rison

    +

    Voie de la magie de guérison

    1. Soigner : !cof-soin @{selected|token_id} @{target|target1|token_id} [[ceil(@{target|target1|PV|max}/2)]] --limiteCibleParJour 1
    2. -
    3. Gu\xE9rir : !cof-guerir @{selected|token_id} @{target|token_id} --portee 0
    4. +
    5. Guérir : !cof-guerir @{selected|token_id} @{target|token_id} --portee 0
    -

    Voie de la magie mal\xE9fique

    +

    Voie de la magie maléfique

    1. Vampirisation :
        -
      • Ajouter une attaque magique avec les DMs de vampirisation, faisant des d\xE9g\xE2ts de type drain. (En objet, on utilisera les options --sortilege et --drain).
      • -
      • Ajouter un pr\xE9dicat siphonDesAmes, de valeur de NC de la cr\xE9ature (ou sans valeur, si le NC est 0). Si vous voulez que ce siphon emp\xEAche un autre siphon des \xE2mes, rajoutez un pr\xE9dicat siphonDesAmesPrioritaire de valeur un nombre positif et sup\xE9rieur \xE0 ceux sur lequel il est prioritaire.
      • +
      • Ajouter une attaque magique avec les DMs de vampirisation, faisant des dégâts de type drain. (En objet, on utilisera les options --sortilege et --drain).
      • +
      • Ajouter un prédicat siphonDesAmes, de valeur de NC de la créature (ou sans valeur, si le NC est 0). Si vous voulez que ce siphon empêche un autre siphon des âmes, rajoutez un prédicat siphonDesAmesPrioritaire de valeur un nombre positif et supérieur à ceux sur lequel il est prioritaire.
    2. -
    3. Animer un cadavre : !cof-animer-cadavre @{selected|token_id} @{target|token_id}. Au cas o\xF9 vous auriez besoin d'enlever l'\xE9tat de cadavre, il suffit d'enlever l'attribut nomm\xE9 cadavreAnime.
    4. +
    5. Animer un cadavre : !cof-animer-cadavre @{selected|token_id} @{target|token_id}. Au cas où vous auriez besoin d'enlever l'état de cadavre, il suffit d'enlever l'attribut nommé cadavreAnime.
    6. Injonction Mortelle : !cof-injonction-mortelle @{selected|token_id} @{target|token_id}

    Voie de la meute

      -
    1. Intergeanchables : Utiliser un pr\xE9dicat interchangeable, avec comme valeur le nombre d'opposants \xE0 partir duquel les cibles peuvent \xEAtre interverties. Par d\xE9faut, cela va donner un bonus de +2 en DEF et +3 an attaque. Pour retrouver la valeur normale de +5 en DEF, utilisez !cof-options.
    2. -
    3. Attaque en tra\xEEtre : Au MJ de d\xE9cider si une attaque est en tra\xEEtre ou pas. Pour une attaque en tra\xEEtre, rajouter les arguments --sournoise 2 --bonusAttaque 5.
    4. +
    5. Intergeanchables : Utiliser un prédicat interchangeable, avec comme valeur le nombre d'opposants à partir duquel les cibles peuvent être interverties. Par défaut, cela va donner un bonus de +2 en DEF et +3 an attaque. Pour retrouver la valeur normale de +5 en DEF, utilisez !cof-options.
    6. +
    7. Attaque en traître : Au MJ de décider si une attaque est en traître ou pas. Pour une attaque en traître, rajouter les arguments --sournoise 2 --bonusAttaque 5.
    -

    Voie du PNJ r\xE9current

    +

    Voie du PNJ récurrent

      -
    1. Instinct de survie : ajouter un pr\xE9dicat instinctDeSurvie avec comme valeur le nombre de PV en-dessous duquel le PNJ gagne un bonus de DEF. les autres effets sont \xE0 faire par le MJ.
    2. -
    3. Chair \xE0 canon : ajouter un pr\xE9dicat chairACanon. Ajouter ensuite \xE0 tous ses sous-fifres un pr\xE9dicat chairACanonDe de valeur le nom exact du token du PNJ. On peut y mettre plusieurs noms s\xE9par\xE9s par des virgules. Attention, dans ce cas (et aussi si le nom de token contient des espaces ou virgules, etc) pensez \xE0 utiliser :: au lieu de : pour le pr\xE9dicat.
    4. +
    5. Instinct de survie : ajouter un prédicat instinctDeSurvie avec comme valeur le nombre de PV en-dessous duquel le PNJ gagne un bonus de DEF. les autres effets sont à faire par le MJ.
    6. +
    7. Chair à canon : ajouter un prédicat chairACanon. Ajouter ensuite à tous ses sous-fifres un prédicat chairACanonDe de valeur le nom exact du token du PNJ. On peut y mettre plusieurs noms séparés par des virgules. Attention, dans ce cas (et aussi si le nom de token contient des espaces ou virgules, etc) pensez à utiliser :: au lieu de : pour le prédicat.
    -

    Voie du pr\xE9dateur

    +

    Voie du prédateur

      -
    1. Embuscade : S\xE9lectionner les ennemis du pr\xE9dateurs, et utiliser !cof-surprise. Par exemple, contre une \xE9quipe de joueurs dans le handout Equipe joueurs (cf la m\xE9thode de s\xE9lection de groupes), on pourra utiliser l'ability !cof-surprise [[15 + @{selected|DEX}]] --equipe joueurs. Pour les bonus en discr\xE9tion et init, reporter sur la fiche (et \xE0 un pr\xE9dicat discr\xE9tion), pour l'attaque en embuscade sur une cible surprise, rajouter \xE0 une attaque les options --sournoise 1 --if moins FOR --etat renverse --endif.
    2. -
    3. D\xE9vorer : ajouter un pr\xE9dicat devorer.
    4. -
    5. Gober : ajouter un pr\xE9dicat gober. Le script ne v\xE9rifie pas que le personnage fait son jet de force avant d'attaquer (mais il propose un bouton pour le faire), ni que l'arme utilis\xE9e n'est pas plus grande qu'une dague.
    6. +
    7. Embuscade : Sélectionner les ennemis du prédateurs, et utiliser !cof-surprise. Par exemple, contre une équipe de joueurs dans le handout Equipe joueurs (cf la méthode de sélection de groupes), on pourra utiliser l'ability !cof-surprise [[15 + @{selected|DEX}]] --equipe joueurs. Pour les bonus en discrétion et init, reporter sur la fiche (et à un prédicat discrétion), pour l'attaque en embuscade sur une cible surprise, rajouter à une attaque les options --sournoise 1 --if moins FOR --etat renverse --endif.
    8. +
    9. Dévorer : ajouter un prédicat devorer.
    10. +
    11. Gober : ajouter un prédicat gober. Le script ne vérifie pas que le personnage fait son jet de force avant d'attaquer (mais il propose un bouton pour le faire), ni que l'arme utilisée n'est pas plus grande qu'une dague.

    Voie du tueur

      -
    1. Attaque mortelle : donner la possibilit\xE9 de faire une attaque avec les options --bonusAttaque 5 --sournoise rang*2. Rajouter un pr\xE9dicat discr\xE9tion avec comme valeur 5.
    2. -
    3. Disparition : donner la possibilit\xE9 de faire une attaque avec les options --disparition rang*2.
    4. -
    5. Assassinat : rajouter --if etatCible surpris --etat mort --save CON 15 --endif \xE0 l'Attaque mortelle.
    6. +
    7. Attaque mortelle : donner la possibilité de faire une attaque avec les options --bonusAttaque 5 --sournoise rang*2. Rajouter un prédicat discrétion avec comme valeur 5.
    8. +
    9. Disparition : donner la possibilité de faire une attaque avec les options --disparition rang*2.
    10. +
    11. Assassinat : rajouter --if etatCible surpris --etat mort --save CON 15 --endif à l'Attaque mortelle.

    4.4 Autres sorts

    Sorts qui ne sont pas dans des voies, mais peuvent venir du grimoire (dans le compagnon) ou d'effets de parchemins.
      -
    • Animation des objets : !cof-animation-des-objets @{selected|token_id} ?{Taille d'objet|tabouret ou coffret,1|chaise ou coffre,2|meuble bas ou table,4|grande table,7|grosse armoire,10} On peut ajouter un troisi\xE8me argument, @{target|token_id} pour animer un token d'objet sur la carte.
    • -
    • Armure d'eau : !cof-effet-combat armureDEau. Le script automatise l'immunit\xE9 aux \xE9treintes (pas aux enveloppements) et \xE0 la capacit\xE9 Agripper des cr\xE9atures volantes.
    • -
    • Choc : Faire une attaque de port\xE9e 20 m, de type Sortil\xE8ge, DM contondants, port\xE9e 20 m, et avec les options --etat renverse --save FOR 10.
    • +
    • Animation des objets : !cof-animation-des-objets @{selected|token_id} ?{Taille d'objet|tabouret ou coffret,1|chaise ou coffre,2|meuble bas ou table,4|grande table,7|grosse armoire,10} On peut ajouter un troisième argument, @{target|token_id} pour animer un token d'objet sur la carte.
    • +
    • Armure d'eau : !cof-effet-combat armureDEau. Le script automatise l'immunité aux étreintes (pas aux enveloppements) et à la capacité Agripper des créatures volantes.
    • +
    • Choc : Faire une attaque de portée 20 m, de type Sortilège, DM contondants, portée 20 m, et avec les options --etat renverse --save FOR 10.
    • Coup au but : !cof-effet-temp bonusAttaqueTemp 1 --valeur 10 --lanceur @{selected|token_id} --portee 10 --mana 0 --target @{target|token_id}.
    • -
    • Force de g\xE9ant : !cof-effet-temp forceDeGeant 10. Le bonus est de 2 par d\xE9faut, mais peut \xEAtre modifi\xE9 en utilisant l'option --valeur.
    • -
    • Mur de vent : !cof-mur-de-force vent. Par d\xE9faut, la dur\xE9e sera de 5+mod. d'INT, mais on peut donner une autre valeur en argument, apr\xE8s vent. On peut aussi changer le rayon du mur en utilisant --portee. Cela ne g\xE8re ni les immunit\xE9s, ni le jet de force pour passer le mur.
    • -
    • Nu\xE9e de scorpions : ajouter une attaque magique, de port\xE9e 20 m, type Sortil\xE8ge, modificateur --pasDeDmg et option --effet nueeDeScorpions 10. Pas de support particulier pour les DM de zone qui d\xE9truisent la nu\xE9e (enlever l'attribut nueeDeScorpions sur la cible dans ce cas).
    • -
    • R\xE9sistance \xE0 la magie : pour l'augmentation de la DEF contre la magie, utiliser un pr\xE9dicat DEF_magie et pour le bonus aux tests, resistanceALaMagie
    • +
    • Force de géant : !cof-effet-temp forceDeGeant 10. Le bonus est de 2 par défaut, mais peut être modifié en utilisant l'option --valeur.
    • +
    • Mur de vent : !cof-mur-de-force vent. Par défaut, la durée sera de 5+mod. d'INT, mais on peut donner une autre valeur en argument, après vent. On peut aussi changer le rayon du mur en utilisant --portee. Cela ne gère ni les immunités, ni le jet de force pour passer le mur.
    • +
    • Nuée de scorpions : ajouter une attaque magique, de portée 20 m, type Sortilège, modificateur --pasDeDmg et option --effet nueeDeScorpions 10. Pas de support particulier pour les DM de zone qui détruisent la nuée (enlever l'attribut nueeDeScorpions sur la cible dans ce cas).
    • +
    • Résistance à la magie : pour l'augmentation de la DEF contre la magie, utiliser un prédicat DEF_magie et pour le bonus aux tests, resistanceALaMagie
    • Simulacre de vie : !cof-set-attribute PVTemporaires [[1d10 + @{selected|niveau}]] --message simulacre de vie
    • -
    • Sixi\xE8me sens : !cof-effet sixiemeSens true. Pour mettre fin \xE0 l'effet du sort (qui a une dur\xE9e en heures), on peut effacer l'attribut sixiemeSens, ou mieux encore, s\xE9lectionner le token et faire !cof-effet sixiemeSens false.
    • +
    • Sixième sens : !cof-effet sixiemeSens true. Pour mettre fin à l'effet du sort (qui a une durée en heures), on peut effacer l'attribut sixiemeSens, ou mieux encore, sélectionner le token et faire !cof-effet sixiemeSens false.
    • Toiles : !cof-effet-temp toiles [[5+@{selected|SAG}]] --saveActifParTour FOR [[10+@{selected|SAG}]] --lanceur @{selected|token_id} --disque @{target|token_id} 5 20 --saufAllies --mana 0.
    -

    4.5 Capacit\xE9s diverses

    +

    4.5 Capacités diverses

      -
    • Absorption d'\xE9nergie (spectres et vampires) : ajouter un pr\xE9dicat absorptionEnergie de valeur la valeur du soin accord\xE9 \xE0 l'attaquant \xE0 chaque fois qu'il endommage une cible (5 par d\xE9faut, si vous ne mettez aucune valeur). Pour l'absorption des vampires, ajouter un pr\xE9dicat vampire.
    • -
    • Action libre : ajouter un pr\xE9dicat actionLibre.
    • -
    • Agripper (d\xE9mon dans Noirbois) : !cof-agripper-de-demon @{selected|token_id} @{target|token_id}
    • -
    • Apparition : un pr\xE9dicat apparition immunise \xE0 tous les DMs, sauf ceux de canalisation (voir plus bas), ou les attaques avec l'option energiePositive.
    • -
    • Armes de l'\xE9t\xE9 (Les seigneurs de l'hiver) : pour le bonus d\xE9fensif contre le seigneur de l'hivers, ajoutez sur les arme un pr\xE9dicat armeDeLEte et sur la cr\xE9ature qui attaque (a priori seulement le seigneur de l'hiver) le pr\xE9dicat creatureDeLHiver. Pour la Flamme de l'\xE9t\xE9, on peut rajouter dans les options --if predicatCible CreatureDeLHiver --incrDmgCoef 3 --incrCritCoef 3 --else --plus 1d6 --feu --enflamme --endif, et pour la Lance de l'aubre, --if predicatCible CreatureDeLHiver --incrDmgCoef 1 --incrCritCoef 1 --else --plus 1d6 --feu --enflamme --endif
    • -
    • Attaque en meute : ajouter un pr\xE9dicat attaqueEnMeute de valeur le bonus d'attaque (2 pour un gobelin). Cela conf\xE8re le bonus pour toutes les attaques de personnages avec ce pr\xE9dicat suivant une effectu\xE9e par un autre personnage avec ce pr\xE9dicat, jusqu'au prochain tour de ce personnage. Ainsi, si 2 cr\xE9atures continuent d'attaquer la m\xEAme cible, elles b\xE9n\xE9ficieront du bonus tout le temps, sauf la toute premi\xE8re attaque.
    • -
    • Attaque violente (Invicible) : ajouter un pr\xE9dicat attaqueViolente.
    • -
    • Auras : pour les capacit\xE9s qui font un effet permanent \xE0 une certaine port\xE9e, comme l'aura glaciale des spectres, utiliser un attribut nomm\xE9 aura, de valeur courante la port\xE9e en m\xE8tres de l'aura, et de valeur maximale l'effet \xE0 appliquer. Si cet effet contient la cha\xEEne de caract\xE8re $TOKEN, cette cha\xEEne sera remplac\xE9e par le nom du token \xE0 l'origine de l'aura. Pour un exemple d'utilisation, voyez la ligne Aura glaciale en dessous.
    • -
    • Aura glaciale : ajouter un attribut aura, de valeur courante 5, et de valeur maximale !cof-effet-temp ralenti [[1d6]] --save CON 12 --magique --seulementVivant --message une aura de froid intense \xE9mane de $TOKEN.
    • -
    • Aura de profanation : ajouter un pr\xE9dicat auraDeProfanation.
    • -
    • Baroud d'honneur : ajouter un pr\xE9dicat baroudHonneur (Quand le personnage arrive \xE0 0 PV, il ne meurt pas jusqu'\xE0 sa prochaine attaque, qui se fait avec un bonus de +5)
    • -
    • B\xE2ton des runes mortes (Invincible) : ajoutez dans les pr\xE9dicats de l'arme le pr\xE9dicat batonDesRunesMortes. Dans la fiche de Swarathnak, ajoutez le pr\xE9dicat ennemiDuBatonDesRunesMortes.
    • -
    • Bonus \xE0 l'attaque magique : utiliser un pr\xE9dicat bonusAttaqueMagique de valeur le bonus permet d'ajouter ce bonus aux attaques magiques. Utile en particulier en pr\xE9dicat d'arme.
    • -
    • Boutefeu (Invincible) : utilisez un pr\xE9dicat boutefeu. -
    • Canalisation : !cof-canaliser type o\xF9 type peut \xEAtre positif ou n\xE9gatif, selon le type d'\xE9nergie canalis\xE9e. Il faut au moins soit une option --soin expr ou --dm expr (il est possible d'avoir les deux), pour exprimer le montant des soins ou des d\xE9g\xE2ts. Si vous souhaitez avoir un certain nombre de d\xE9g\xE2ts par point de mana d\xE9pens\xE9, vous pouvez utiliser un pr\xE9dicat deCanalisation contenant l'expression des d\xE9g\xE2ts (ou soins) par point de mana, et utiliser la syntaxe --soin n pm.
    • -
    • Ch\xE2timent du m\xE2le : utiliser un pr\xE9dicat chatimentDuMale.
    • -
    • Cibles multiples (nu\xE9es) : ajouter un pr\xE9dicat ciblesMultiples.
    • +
    • Absorption d'énergie (spectres et vampires) : ajouter un prédicat absorptionEnergie de valeur la valeur du soin accordé à l'attaquant à chaque fois qu'il endommage une cible (5 par défaut, si vous ne mettez aucune valeur). Pour l'absorption des vampires, ajouter un prédicat vampire.
    • +
    • Action libre : ajouter un prédicat actionLibre.
    • +
    • Agripper (démon dans Noirbois) : !cof-agripper-de-demon @{selected|token_id} @{target|token_id}
    • +
    • Apparition : un prédicat apparition immunise à tous les DMs, sauf ceux de canalisation (voir plus bas), ou les attaques avec l'option energiePositive.
    • +
    • Armes de l'été (Les seigneurs de l'hiver) : pour le bonus défensif contre le seigneur de l'hivers, ajoutez sur les arme un prédicat armeDeLEte et sur la créature qui attaque (a priori seulement le seigneur de l'hiver) le prédicat creatureDeLHiver. Pour la Flamme de l'été, on peut rajouter dans les options --if predicatCible CreatureDeLHiver --incrDmgCoef 3 --incrCritCoef 3 --else --plus 1d6 --feu --enflamme --endif, et pour la Lance de l'aubre, --if predicatCible CreatureDeLHiver --incrDmgCoef 1 --incrCritCoef 1 --else --plus 1d6 --feu --enflamme --endif
    • +
    • Attaque en meute : ajouter un prédicat attaqueEnMeute de valeur le bonus d'attaque (2 pour un gobelin). Cela confère le bonus pour toutes les attaques de personnages avec ce prédicat suivant une effectuée par un autre personnage avec ce prédicat, ou un de leurs alliés, jusqu'au prochain tour de ce personnage. Ainsi, si 2 créatures continuent d'attaquer la même cible, elles bénéficieront du bonus tout le temps, sauf la toute première attaque.
    • +
    • Attaque violente (Invicible) : ajouter un prédicat attaqueViolente.
    • +
    • Auras : pour les capacités qui font un effet permanent à une certaine portée, comme l'aura glaciale des spectres, utiliser un attribut nommé aura, de valeur courante la portée en mètres de l'aura, et de valeur maximale l'effet à appliquer. Si cet effet contient la chaîne de caractère $TOKEN, cette chaîne sera remplacée par le nom du token à l'origine de l'aura. Pour un exemple d'utilisation, voyez la ligne Aura glaciale en dessous.
    • +
    • Aura glaciale : ajouter un attribut aura, de valeur courante 5, et de valeur maximale !cof-effet-temp ralenti [[1d6]] --save CON 12 --magique --seulementVivant --message une aura de froid intense émane de $TOKEN.
    • +
    • Aura de profanation : ajouter un prédicat auraDeProfanation.
    • +
    • Baroud d'honneur : ajouter un prédicat baroudHonneur (Quand le personnage arrive à 0 PV, il ne meurt pas jusqu'à sa prochaine attaque, qui se fait avec un bonus de +5)
    • +
    • Bâton des runes mortes (Invincible) : ajoutez dans les prédicats de l'arme le prédicat batonDesRunesMortes. Dans la fiche de Swarathnak, ajoutez le prédicat ennemiDuBatonDesRunesMortes.
    • +
    • Bonus à l'attaque magique : utiliser un prédicat bonusAttaqueMagique de valeur le bonus permet d'ajouter ce bonus aux attaques magiques. Utile en particulier en prédicat d'arme.
    • +
    • Boutefeu (Invincible) : utilisez un prédicat boutefeu. +
    • Canalisation : !cof-canaliser typetype peut être positif ou négatif, selon le type d'énergie canalisée. Il faut au moins soit une option --soin expr ou --dm expr (il est possible d'avoir les deux), pour exprimer le montant des soins ou des dégâts. Si vous souhaitez avoir un certain nombre de dégâts par point de mana dépensé, vous pouvez utiliser un prédicat deCanalisation contenant l'expression des dégâts (ou soins) par point de mana, et utiliser la syntaxe --soin n pm.
    • +
    • Châtiment du mâle : utiliser un prédicat chatimentDuMale.
    • +
    • Cibles multiples (nuées) : ajouter un prédicat ciblesMultiples.
    • Clignotement : !cof-effet-temp clignotement [[1d6+2]].
    • -
    • Cr\xE9ature non-vivante : ajouter un pr\xE9dicat nonVivant.
    • -
    • Cr\xE9ature v\xE9g\xE9tative : ajouter un pr\xE9dicat vegetatif.
    • -
    • Cyclone (pour les \xE9lementaires) : !cof-effet-temp cyclone [[1d4+1]] --limiteParCombat 1. Cela va proposer une attaque Traverser dans les actions de l'\xE9l\xE9mentaire, qui ne peut fonctionner que si le personnage a au moins une attaque sur sa fiche. Par d\xE9faut, l'attaque utilis\xE9e en traversant est l'attaque de label 1, mais on peut pr\xE9ciser un autre label en utilisant l'option --valeur.
    • -
    • D\xE9g\xE2ts si touch\xE9 au contact (\xE9l\xE9mentaire de feu,...) : ajouter un pr\xE9dicat nomm\xE9 dmSiToucheContact, de valeur les d\xE9g\xE2ts, suivis de -- et du type si besoin. Par exemple, pour un \xE9l\xE9mentaire de feu, le pr\xE9dicat dmSiToucheContact:: 1d6 --feu, en fin de ligne (rien ne doit suivre sur cette ligne).
    • -
    • Drain de force (pour la campagne Invincible) : ajouter un pr\xE9dicat auraDrainDeForce
    • -
    • \xC9craser (pour la campagne Invincible) : ajouter un pr\xE9dicat ecraser de valeur le label de l'attaque utilis\xE9e pour \xE9craser.
    • -
    • Effroi (dragons) : !cof-peur [[10+@{selected|FOR}]] 1d4 --effroi --ralenti --disque @{selected|token_id} 50 \xE0 utiliser au premier tour de jeu.
    • -
    • \xC9nergie de la mort (pour la campagne Vengeance) : ajouter un pr\xE9dicat energieDeLaMort. Le MJ devra \xEAtre attentif au message indiquant le retour \xE0 la vie, car c'est lui qui devra enlever l'\xE9tat mort et ajuster les PVs.
    • -
    • Enveloppement (cube g\xE9latineux) : ajouter l'option --enveloppe, puis quand le bouton appara\xEEt si l'attaque r\xE9ussit, cliquer dessus. En cas d'enveloppement, la cible ne peut plus bouger et se d\xE9place avec le cube (d\xE9placer le cube met la cible dans le cube), et au tour du cube, il faut presser les boutons de d\xE9g\xE2ts pour les infliger aux cibles envelopp\xE9es.
    • -
    • \xC9treinte (serpents) : ajouter l'option --etreinte difficulte, puis quand le bouton appara\xEEt si l'attaque r\xE9ussit, cliquer dessus. En cas d'\xE9treinte r\xE9ussie, la cible ne peut plus bouger et se d\xE9place avec le serpent, et au tour du serpent, il faut presser les boutons de d\xE9g\xE2ts pour les infliger aux cibles \xE9treintes.
    • -
    • \xC9treinte (scorpions) : ajouter l'option --etreinteScorpion. Le script prend le parti de ne pas \xE9tourdir la cible, mais le -5 en DEF, le jet de FOR et les d\xE9g\xE2ts sont automatis\xE9s. La cible est lib\xE9r\xE9e automatiquement \xE0 la mort du scorpion.
    • -
    • \xC9treinte avec immolation (d\xE9mon gardien) : pour l'attaque limit\xE9e qui immole, ajouter l'option --etreinteImmole. Cette attaque r\xE9ussira automatiquement contre une cible qui est d\xE9j\xE0 \xE9treinte.
    • -
    • Faucheuse de g\xE9ants: ajouter le modifcateur tueurDeGrands aux attaques.
    • -
    • Fi\xE8vre du ch\xEAne : pour ajouter encore une RD de 5 contre le feu, ajouter un pr\xE9dicat fievreChene.
    • -
    • Fi\xE9vreux : !cof-effet fievreux donne -2 en attaque, au d\xE9g\xE2ts et aux tests.
    • -
    • 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\xE9faut (13) par un autre jet de d\xE9s. Un deuxi\xE8me 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\xE9 Foudre (avec la majuscule), le son sera jou\xE9 \xE0 chaque fois que la foudre frappera. Finalement, !cof-effet-chaque-d20 foudresDuTemps fin met fin aux foudres du temps.
    • -
    • Fr\xE9n\xE9sie : Ajouter un pr\xE9dicat frenesie avec comme valeur le nombre de PV en-dessous duquel la cr\xE9ature devient fr\xE9n\xE9tique (+2 aus jets d'attaque).
    • -
    • Hors de port\xE9e : ajouter un pr\xE9dicat horsDePortee
    • -
    • Huile de fort assaut : !cof-effet-temp dmgArme(L) 10 --valeur 1d6 o\xF9 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\xF4mes, !cof-peur 12 1d6 --titre Hurlement terrible --immuniseSiResiste hurlement --disque 10 --saufAllies.
    • -
    • Illusion : Pour les illusions qui disparaissent et r\xE9apparaissent un peu plus loin quand on essaie de les toucher, ajouter un pr\xE9dicat estUneIllusion.
    • -
    • Immunit\xE9 aux armes : ajouter un pr\xE9dicat immuniteAuxArmes. \xC0 noter qu'il est possible de sp\xE9cifier le niveau de magie d'une attaque en donnant un argument \xE0 l'option --magique. Ainsi une arme de niveau magique 3 aura en argument --magique 3.
    • -
    • Immunit\xE9 aux attaques non magiques : ajouter un pr\xE9dicat immunite_nonMagique
    • -
    • Immunit\xE9 aux critiques : ajouter un pr\xE9dicat immuniteAuxCritiques.
    • -
    • Ind\xE9racinable : ajouter un pr\xE9dicat inderacinable.
    • -
    • Insensible : ajouter un pr\xE9dicat insensibleAffaibli.
    • -
    • Intangible (\xE0 la Pathfinder 1) : ajouter un un pr\xE9dicat creatureIntangible pour l'immunit\xE9 aux armes non-magiques et la division des autres d\xE9g\xE2ts.
    • -
    • Invisible : passer le personnage invisible (!cof-set-state invisible true, ou mettre directment le statut sur le token). Si il peut rester invisible en combat, lui ajouter un pr\xE9dicat invisibleEnCombat. Si il est attaqu\xE9 autrement qu'avec tir en aveugle par quelqu'un qui ne voit pas l'invisble (\xE0 vous de montrer au moins temporairement le token), un malus de +5 en DEF au contact et +10 \xE0 distance sera appliqu\xE9, de m\xEAme que le bonus de +5 en attaque contre ceux qui ne voient pas l'invisible. Le script suppose toujours qu'un personnage qui dispose de tir aveugle utilise sa capacit\xE9 contre les cibles invisibles: \xE0 vous de v\xE9rifier qu'il ne cumule pas \xE7a avec une capacit\xE9 limit\xE9e.
    • -
    • Langage sombre : en plus de comprendre les elfes noirs, j'ai d\xE9cid\xE9 d'octroyer un bonus de +1 en DEF et +1 aux DM contre les elfes noirs, bonus justifi\xE9 par la meilleure compr\xE9hension de leur culture et de leurs tactiques. Pour cela, j'utiliser un pr\xE9dicat langageSombreHetre.
    • -
    • Message en cas de coup critique re\xE7u : on peut utiliser un pr\xE9dicat messageSiCritique avec en valeur un message \xE0 afficher en cas d'echec critique subit. Pensez \xE0 bien utiliser la syntaxe avec ::.
    • +
    • Créature non-vivante : ajouter un prédicat nonVivant.
    • +
    • Créature végétative : ajouter un prédicat vegetatif.
    • +
    • Cyclone (pour les élementaires) : !cof-effet-temp cyclone [[1d4+1]] --limiteParCombat 1. Cela va proposer une attaque Traverser dans les actions de l'élémentaire, qui ne peut fonctionner que si le personnage a au moins une attaque sur sa fiche. Par défaut, l'attaque utilisée en traversant est l'attaque de label 1, mais on peut préciser un autre label en utilisant l'option --valeur.
    • +
    • Dégâts si touché au contact (élémentaire de feu,...) : ajouter un prédicat nommé dmSiToucheContact, de valeur les dégâts, suivis de -- et du type si besoin. Par exemple, pour un élémentaire de feu, le prédicat dmSiToucheContact:: 1d6 --feu, en fin de ligne (rien ne doit suivre sur cette ligne).
    • +
    • Drain de force (pour la campagne Invincible) : ajouter un prédicat auraDrainDeForce
    • +
    • Écraser (pour la campagne Invincible) : ajouter un prédicat ecraser de valeur le label de l'attaque utilisée pour écraser.
    • +
    • Effroi (dragons) : !cof-peur [[10+@{selected|FOR}]] 1d4 --effroi --ralenti --disque @{selected|token_id} 50 à utiliser au premier tour de jeu.
    • +
    • Énergie de la mort (pour la campagne Vengeance) : ajouter un prédicat energieDeLaMort. Le MJ devra être attentif au message indiquant le retour à la vie, car c'est lui qui devra enlever l'état mort et ajuster les PVs.
    • +
    • Enveloppement (cube gélatineux) : ajouter l'option --enveloppe, puis quand le bouton apparaît si l'attaque réussit, cliquer dessus. En cas d'enveloppement, la cible ne peut plus bouger et se déplace avec le cube (déplacer le cube met la cible dans le cube), et au tour du cube, il faut presser les boutons de dégâts pour les infliger aux cibles enveloppées.
    • +
    • Étreinte (serpents) : ajouter l'option --etreinte difficulte, puis quand le bouton apparaît si l'attaque réussit, cliquer dessus. En cas d'étreinte réussie, la cible ne peut plus bouger et se déplace avec le serpent, et au tour du serpent, il faut presser les boutons de dégâts pour les infliger aux cibles étreintes.
    • +
    • Étreinte (scorpions) : ajouter l'option --etreinteScorpion. Le script prend le parti de ne pas étourdir la cible, mais le -5 en DEF, le jet de FOR et les dégâts sont automatisés. La cible est libérée automatiquement à la mort du scorpion.
    • +
    • Étreinte avec immolation (démon gardien) : pour l'attaque limitée qui immole, ajouter l'option --etreinteImmole. Cette attaque réussira automatiquement contre une cible qui est déjà étreinte.
    • +
    • Faucheuse de géants: ajouter le modifcateur tueurDeGrands aux attaques.
    • +
    • Fièvre du chêne : pour ajouter encore une RD de 5 contre le feu, ajouter un prédicat fievreChene.
    • +
    • Fiévreux : !cof-effet fievreux donne -2 en attaque, au dégâts et aux tests.
    • +
    • 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).
    • +
    • Hors de portée : ajouter un prédicat horsDePortee
    • +
    • Huile de fort assaut : !cof-effet-temp dmgArme(L) 10 --valeur 1d6L 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.
    • +
    • Illusion : Pour les illusions qui disparaissent et réapparaissent un peu plus loin quand on essaie de les toucher, ajouter un prédicat estUneIllusion.
    • +
    • Immunité aux armes : ajouter un prédicat immuniteAuxArmes. À noter qu'il est possible de spécifier le niveau de magie d'une attaque en donnant un argument à l'option --magique. Ainsi une arme de niveau magique 3 aura en argument --magique 3.
    • +
    • Immunité aux attaques non magiques : ajouter un prédicat immunite_nonMagique
    • +
    • Immunité aux critiques : ajouter un prédicat immuniteAuxCritiques.
    • +
    • Indéracinable : ajouter un prédicat inderacinable.
    • +
    • Insensible : ajouter un prédicat insensibleAffaibli.
    • +
    • Intangible (à la Pathfinder 1) : ajouter un un prédicat creatureIntangible pour l'immunité aux armes non-magiques et la division des autres dégâts.
    • +
    • Invisible : passer le personnage invisible (!cof-set-state invisible true, ou mettre directment le statut sur le token). Si il peut rester invisible en combat, lui ajouter un prédicat invisibleEnCombat. Si il est attaqué autrement qu'avec tir en aveugle par quelqu'un qui ne voit pas l'invisble (à vous de montrer au moins temporairement le token), un malus de +5 en DEF au contact et +10 à distance sera appliqué, de même que le bonus de +5 en attaque contre ceux qui ne voient pas l'invisible. Le script suppose toujours qu'un personnage qui dispose de tir aveugle utilise sa capacité contre les cibles invisibles: à vous de vérifier qu'il ne cumule pas ça avec une capacité limitée.
    • +
    • Langage sombre : en plus de comprendre les elfes noirs, j'ai décidé d'octroyer un bonus de +1 en DEF et +1 aux DM contre les elfes noirs, bonus justifié par la meilleure compréhension de leur culture et de leurs tactiques. Pour cela, j'utiliser un prédicat langageSombreHetre.
    • +
    • Message en cas de coup critique reçu : on peut utiliser un prédicat messageSiCritique avec en valeur un message à afficher en cas d'echec critique subit. Pensez à bien utiliser la syntaxe avec ::.
    • Mot de pouvoir qui immobilise : !cof-mot-de-pouvoir-immobilise --lanceur @{selected|token_id} --enVue --saufAllies
    • -
    • N'abandonne jamais : ajouter un pr\xE9dicat nAbandonnejamais.
    • -
    • Noirbois : \xC0 l'entr\xE9e dans des t\xE9n\xE8bres magiques, utiliser la commande !cof-tenebres-magiques. \xC0 la sortie ou la fin de ces t\xE9n\xE8bres, faire !cof-tenebres-magiques fin. Pour allumer la fiole de lumi\xE8re, s\xE9lectionner un token est faire !cof-fiole-de-lumiere d o\xF9 d est la distance \xE0 laquelle la fiole \xE9claire. On peut ajouter un troisi\xE8me argument, qui est la distance \xE0 laquelle la lumi\xE8re devient moins brillante (pas d'effet sur la m\xE9canique de jeu). Pour \xE9teindre la lumi\xE8re, il faut mettre utiliser !cof-fiole-de-lumiere fin.
    • -
    • Noyade (plante carnivore) : il existe un effet de combat nomm\xE9 noyade (pas de dur\xE9e, il dure par d\xE9faut tout le combat) qui fait perdre 1d6 PV par tour, sauf \xE0 r\xE9ussir un test de CON difficult\xE9 15, et qui impose un malus de -3 aux attaques et aux DMs.
    • -
    • Ondes corruptrices (Anathazer\xEFn) : Pour simplement le premier effet, faire !cof-effet ondesCorruptrices 2, puis pour augmeter l'effet !cof-effet ondesCorruptrices +2. L'effet peut \xEAtre annul\xE9 avec !cof-effet ondesCorruptrices 0. Pour le porteur du bouclier de Grabuge, on peut mettre un pr\xE9dicat porteurDuBouclierDeGrabuge.
    • -
    • Paralysie des goules : ajouter \xE0 l'attaque de morsure --effet paralyseGoule [[1d6]] --save CON 10.
    • -
    • Perte de substance (Invincible) : Ajouter pour tous les personnages concern\xE9s un pr\xE9dicat perteDeSubstance. Le changement de jour va augmenter un compteur, \xE0 condition que les tokens des joueurs soient sur la page, et soit on ne s\xE9lectionne aucun token quand on lance la commande de changement de jour, soit on s\xE9lectionne au moins tous les tokens des joueurs. Le test de CHA n'est pas automatis\xE9, mais le script en rappelle la difficult\xE9. Pour les ancres, ajouter un pr\xE9dicat ancreInvincible (par exemple dans les pr\xE9dicats de l'arme). Pour la r\xE9duction des d\xE9g\xE2ts, ajouter au dragon un pr\xE9dicat dragonInvincible. Pour les DM indirects, il faudra g\xE9rer \xE0 la main la r\xE9duction de DM.
    • -
    • Phylact\xE8re de canalisation : ajouter un pr\xE9dicat phylacterePositif pour un phylact\xE8re de canalisation positive, ou phylactereNegatif pour un phylact\xE8re de canalisation n\xE9gative. Associez \xE0 ce pr\xE9dicat la valeur ajout\xE9e pour chaque PM d\xE9pens\xE9 (n\xE9cessite l'utilisation du pr\xE9dicat deCanalisation). Une valeur de 1d4 semble adapt\xE9e pour le phylact\xE8re de canalisation de Pathfinder 1.
    • -
    • Piq\xFBres d'insectes : Rajouter un pr\xE9dicat piquresDInsectes avec comme valeur la r\xE9sistance aux d\xE9g\xE2ts \xE0 distance appropri\xE9e
    • +
    • N'abandonne jamais : ajouter un prédicat nAbandonnejamais.
    • +
    • Noirbois : À l'entrée dans des ténèbres magiques, utiliser la commande !cof-tenebres-magiques. À la sortie ou la fin de ces ténèbres, faire !cof-tenebres-magiques fin. Pour allumer la fiole de lumière, sélectionner un token est faire !cof-fiole-de-lumiere dd est la distance à laquelle la fiole éclaire. On peut ajouter un troisième argument, qui est la distance à laquelle la lumière devient moins brillante (pas d'effet sur la mécanique de jeu). Pour éteindre la lumière, il faut mettre utiliser !cof-fiole-de-lumiere fin.
    • +
    • Noyade (plante carnivore) : il existe un effet de combat nommé noyade (pas de durée, il dure par défaut tout le combat) qui fait perdre 1d6 PV par tour, sauf à réussir un test de CON difficulté 15, et qui impose un malus de -3 aux attaques et aux DMs.
    • +
    • Ondes corruptrices (Anathazerïn) : Pour simplement le premier effet, faire !cof-effet ondesCorruptrices 2, puis pour augmeter l'effet !cof-effet ondesCorruptrices +2. L'effet peut être annulé avec !cof-effet ondesCorruptrices 0. Pour le porteur du bouclier de Grabuge, on peut mettre un prédicat porteurDuBouclierDeGrabuge.
    • +
    • Paralysie des goules : ajouter à l'attaque de morsure --effet paralyseGoule [[1d6]] --save CON 10.
    • +
    • Perte de substance (Invincible) : Ajouter pour tous les personnages concernés un prédicat perteDeSubstance. Le changement de jour va augmenter un compteur, à condition que les tokens des joueurs soient sur la page, et soit on ne sélectionne aucun token quand on lance la commande de changement de jour, soit on sélectionne au moins tous les tokens des joueurs. Le test de CHA n'est pas automatisé, mais le script en rappelle la difficulté. Pour les ancres, ajouter un prédicat ancreInvincible (par exemple dans les prédicats de l'arme). Pour la réduction des dégâts, ajouter au dragon un prédicat dragonInvincible. Pour les DM indirects, il faudra gérer à la main la réduction de DM.
    • +
    • 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 \xEAtre que rapide ou affaiblissant. Pour un poison rapide, force est une expression pour les d\xE9g\xE2ts (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\xE9e en heures, \xE0 g\xE9rer par le MJ). save est la difficult\xE9 du jet de CON pour r\xE9sister 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 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 :
        -
      • --testINT n: fixe la difficult\xE9 du jet d'INT pour r\xE9ussir \xE0 poser le poison. La difficult\xE9 par d\xE9faut 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\xE9d\xE9es.
      • +
      • --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.
      - Il est aussi possible d'enduire de poison des munitions. Pour ce faire, remplacer le label de l'attaque par munition_L o\xF9 L est le label de la munition. Le script suppose que toute munition lanc\xE9e perd son poison. + Il est aussi possible d'enduire de poison des munitions. Pour ce faire, remplacer le label de l'attaque par munition_LL est le label de la munition. Le script suppose que toute munition lancée perd son poison.

      Il existe les effets suivants pour simuler directement des poisons affaiblissants :

      • poisonAffaiblissant est un effet qui rend affaibli pendant tout un combat.
      • -
      • poisonAffaiblissantLong, le m\xEAme effet mais sans limite de dur\xE9e (\xE0 g\xE9rer par le MJ).
      • -
      • poisonAffaiblissantLatent est un effet \xE0 dur\xE9e en tours. Quand l'effet prend fin, le personnage devient empoisonn\xE9 et affaibli.
      • +
      • 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.
    • -
    • Potion de sang de l'Arbre-Coeur : !cof-effet sangDeLArbreCoeur true, \xE0 enlever quand les 24h sont pass\xE9es.
    • -
    • Protection contre les souffles et d\xE9g\xE2ts de zone : ajouter un pr\xE9dicat protectionDMZone. Pour une protection contre un seul \xE9l\xE9ment (feu, froid, etc), ajouter _ et le nom de l'\xE9l\xE9ment. Par exemple, contre le feu, on aura un pr\xE9dicat protectionDMZone_feu. On peut aussi avoir une protection contre les souffles de dragons uniquement, mais qui annule les DM en cas de succ\xE8s au test de DEX, avec le pr\xE9dicat protectionSouffleDeDragon. On peut aussi donner une RD contre les souffles de dragons avec un pr\xE9dicat num\xE9rique rdSouffleDeDragon.
    • -
    • Putr\xE9faction : ajouter \xE0 l'attaque --effet putrefaction 5 --save CON 14 (pour les donn\xE9es des momies)
    • +
    • Potion de sang de l'Arbre-Coeur : !cof-effet sangDeLArbreCoeur true, à enlever quand les 24h sont passées.
    • +
    • Protection contre les souffles et dégâts de zone : ajouter un prédicat protectionDMZone. Pour une protection contre un seul élément (feu, froid, etc), ajouter _ et le nom de l'élément. Par exemple, contre le feu, on aura un prédicat protectionDMZone_feu. On peut aussi avoir une protection contre les souffles de dragons uniquement, mais qui annule les DM en cas de succès au test de DEX, avec le prédicat protectionSouffleDeDragon. On peut aussi donner une RD contre les souffles de dragons avec un prédicat numérique rdSouffleDeDragon.
    • +
    • Putréfaction : ajouter à l'attaque --effet putrefaction 5 --save CON 14 (pour les données des momies)
    • Rage (pour la campagne Invincible) : pour entrer en rage, faire !cof-effet-combat rage. On peut par exemple mettre cette commande dans une ability.
    • -
    • R\xE9action allergique : il existe un effet reactionAllergique qui fait le malus en DEX et CHA et dispara\xEEt en cas de soin magique. Pour une attaque, on peut par exemple mettre --effet reactionAllergique --save CON 11.
    • -
    • R\xE9sistant (insectes) : ajouter un pr\xE9dicat durACuire.
    • -
    • Regard p\xE9trifiant : ajouter un pr\xE9dicat regardPetrifiant. Comme il est difficile de savoir qui est affect\xE9 et quand, le pr\xE9dicat g\xE9n\xE8re juste une action pour la cr\xE9ature et le MJ doit d\xE9cider \xE0 qui l'appliquer et quand. \xC0 noter qu'on peut associer une valeur au pr\xE9dicat pour changer la difficult\xE9 de 16 par d\xE9faut (-4 quand un adversaire est conscient du pouvoir et \xE9vite de croiser le regard). Pour d\xE9tourner le regard d'une cible, utiliser !cof-effet-combat detournerLeRegard. Pour fermer les yeux, !cof-effet-combat detournerLeRegard --valeur 5. Pour arr\xEAter de d\xE9tourner le regard !cof-effet-combat detournerLeRegard fin. Si vous souhaitez enlever un effet de p\xE9trification, vous pouvez utiliser la commande !cof-effet petrifie false.
    • -
    • Saisir et broyer : ajouter un pr\xE9dicat saisirEtBroyer
    • -
    • Sang de fer : ajouter un pr\xE9dicat sangDeFerIf.
    • -
    • Sans esprit : ajouter un pr\xE9dicat sansEsprit permet la r\xE9ussite automatique des jets de r\xE9sistance bas\xE9s sur INT, SAG ou CHA.
    • -
    • Sph\xE8re de feu : !cof-sphere-de-feu.
    • -
    • Tremblements de terre : !cof-effet-chaque-d20 tremblementsDeTerre permet d'activer les tremblements de terre. On peut donner un argument pour remplacer la valeur par d\xE9faut (13) par un autre jet de d\xE9s. Un deuxi\xE8me argument permet de faire trembler la terre pour tout jet entre les deux valeurs. Si votre jeu contient un son (ou playlist) nomm\xE9 TremblementTerre (avec la majuscule), le son sera jou\xE9 \xE0 chaque fois que la terre tremblera. Finalement, !cof-effet-chaque-d20 tremblementsDeTerre fin met fin aux tremblements de terre.
    • +
    • Réaction allergique : il existe un effet reactionAllergique qui fait le malus en DEX et CHA et disparaît en cas de soin magique. Pour une attaque, on peut par exemple mettre --effet reactionAllergique --save CON 11.
    • +
    • Résistant (insectes) : ajouter un prédicat durACuire.
    • +
    • Regard pétrifiant : ajouter un prédicat regardPetrifiant. Comme il est difficile de savoir qui est affecté et quand, le prédicat génère juste une action pour la créature et le MJ doit décider à qui l'appliquer et quand. À noter qu'on peut associer une valeur au prédicat pour changer la difficulté de 16 par défaut (-4 quand un adversaire est conscient du pouvoir et évite de croiser le regard). Pour détourner le regard d'une cible, utiliser !cof-effet-combat detournerLeRegard. Pour fermer les yeux, !cof-effet-combat detournerLeRegard --valeur 5. Pour arrêter de détourner le regard !cof-effet-combat detournerLeRegard fin. Si vous souhaitez enlever un effet de pétrification, vous pouvez utiliser la commande !cof-effet petrifie false.
    • +
    • Saisir et broyer : ajouter un prédicat saisirEtBroyer
    • +
    • Sang de fer : ajouter un prédicat sangDeFerIf.
    • +
    • Sans esprit : ajouter un prédicat sansEsprit permet la réussite automatique des jets de résistance basés sur INT, SAG ou CHA.
    • +
    • Sphère de feu : !cof-sphere-de-feu.
    • +
    • Tremblements de terre : !cof-effet-chaque-d20 tremblementsDeTerre permet d'activer les tremblements de terre. 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 trembler la terre pour tout jet entre les deux valeurs. Si votre jeu contient un son (ou playlist) nommé TremblementTerre (avec la majuscule), le son sera joué à chaque fois que la terre tremblera. Finalement, !cof-effet-chaque-d20 tremblementsDeTerre fin met fin aux tremblements de terre.
    • Vision nocturne : on peut utiliser !cof-vision-nocturne 18 pour un effet de potion de vision nocturne. Attention, pour remettre la vision habituelle, il faut encore effacer le token et remettre le token du personnage depuis la fiche.
    • -
    • Vuln\xE9rabilit\xE9 aux coups critiques : si la cr\xE9ature poss\xE8de un pr\xE9dicat vulnerableCritique, le script interpr\xE8te la valeur de ce pr\xE9dicat comme les chances (sur 100) qu'un coup critique tue directment la cr\xE9ature. Par exemple, la valeur sera de 25 pour un esprit du givre.
    • -
    • Vuln\xE9rabilit\xE9 \xE0 un type de d\xE9g\xE2ts : ajouter un pr\xE9dicat vulnerableA_type, pour augmenter de 50% les d\xE9g\xE2ts re\xE7us de ce type.
    • +
    • Vulnérabilité aux coups critiques : si la créature possède un prédicat vulnerableCritique, le script interprète la valeur de ce prédicat comme les chances (sur 100) qu'un coup critique tue directment la créature. Par exemple, la valeur sera de 25 pour un esprit du givre.
    • +
    • Vulnérabilité à un type de dégâts : ajouter un prédicat vulnerableA_type, pour augmenter de 50% les dégâts reçus de ce type.

    5. Terres d'Arran

    -

    Le script determine s'il doit utiliser les r\xE8gles par d\xE9faut des Terres d'Arran ou celles de COF g\xE9n\xE9rique en fonction des fiches de personnages pr\xE9sentes sur la partie. Pour que toutes vox fiches soient bien adapt\xE9es au setting des Terres d'Arran, assurez-vous de bien s\xE9lectionner ce setting dans les r\xE9glages du jeu (accessibles avant de lancer la partie "Options de jeu" ou "Game Settings".

    +

    Le script determine s'il doit utiliser les règles par défaut des Terres d'Arran ou celles de COF générique en fonction des fiches de personnages présentes sur la partie. Pour que toutes vox fiches soient bien adaptées au setting des Terres d'Arran, assurez-vous de bien sélectionner ce setting dans les réglages du jeu (accessibles avant de lancer la partie "Options de jeu" ou "Game Settings".

    -

    Le fait d'\xEAtre dans ce mode de r\xE8gles change le calcul de l'initiative et des mods d'attaque.

    +

    Le fait d'être dans ce mode de règles change le calcul de l'initiative et des mods d'attaque.

    5.1 Les peuples d'Arran

    5.1.1 Elfes

    Voie du peuple des Elfes
      -
    1. Gr\xE2ce Elfique : Ajouter le bonus au jets de charisme sur la fiche, et une comp\xE9tence discr\xE9tion pour les d\xE9placements silencieux.
    2. -
    3. Essence magique : ajouter un pr\xE9dicat DEF_magie de valeur 2, et un pr\xE9dicat resistanceALaMagie de valeur 2 aussi. Passer ces valeurs \xE0 4 au rang 4 dans la voie.
    4. -
    5. Ma\xEEtrise des armes elfiques : Pas de support pour l'instant
    6. +
    7. Grâce Elfique : Ajouter le bonus au jets de charisme sur la fiche, et une compétence discrétion pour les déplacements silencieux.
    8. +
    9. Essence magique : ajouter un prédicat DEF_magie de valeur 2, et un prédicat resistanceALaMagie de valeur 2 aussi. Passer ces valeurs à 4 au rang 4 dans la voie.
    10. +
    11. Maîtrise des armes elfiques : Pas de support pour l'instant
    12. Empathie elfique : Pas de support
    13. -
    14. Immortalit\xE9 :TODO
    15. +
    16. Immortalité :TODO
    Voie culturelle des elfes blancs
      -
    1. M\xE9moire du monde : En Attente
    2. -
    3. Pr\xE9dispositions magiques : En Attente
    4. -
    5. Lancier d\x2019\xE9lite : En Attente
    6. -
    7. Blancheur immacul\xE9e : En Attente
    8. +
    9. Mémoire du monde : En Attente
    10. +
    11. Prédispositions magiques : En Attente
    12. +
    13. Lancier d’élite : En Attente
    14. +
    15. Blancheur immaculée : En Attente
    16. Parangon elfe blanc : En Attente
    Voie culturelle des elfes bleus
      -
    1. \xC9quilibre parfait : Ajouter une comp\xE9tence \xE9quilibre avec le bonus.
    2. -
    3. Natif d\x2019Els\xE9mur : voir la capacit\xE9 choisie.
    4. +
    5. Équilibre parfait : Ajouter une compétence équilibre avec le bonus.
    6. +
    7. Natif d’Elsémur : voir la capacité choisie.
    8. Imperturbable : En Attente
    9. -
    10. Les enseignements de l\x2019eau : En Attente
    11. +
    12. Les enseignements de l’eau : En Attente
    13. Parangon elfe bleu : En Attente
    Voie culturelle des elfes noirs
      -
    1. Artiste de l\x2019ombre : En Attente
    2. +
    3. Artiste de l’ombre : En Attente
    4. Apprenti de Slurce : En Attente
    5. -
    6. Armes secr\xE8tes : En Attente
    7. +
    8. Armes secrètes : En Attente
    9. Noir comme le sang : En Attente
    10. Parangon elfe noir : En Attente
    Voie culturelle des elfes sylvains
    1. Le chant de la Terre : En Attente
    2. -
    3. Enfant de la for\xEAt : voir la capacit\xE9 choisie
    4. -
    5. Archer \xE9m\xE9rite : ajuster les chances de critique pour les attaques utilisant les arcs.
    6. -
    7. Compagnon animal sup\xE9rieur : En Attente
    8. +
    9. Enfant de la forêt : voir la capacité choisie
    10. +
    11. Archer émérite : ajuster les chances de critique pour les attaques utilisant les arcs.
    12. +
    13. Compagnon animal supérieur : En Attente
    14. Parangon elfe vert : En Attente
    @@ -2535,21 +2548,21 @@

    5.1.2 Nains

    Voie du peuple des Nains
      -
    1. R\xE9sistance : En Attente
    2. +
    3. Résistance : En Attente
    4. Solide comme un roc : En Attente
    5. -
    6. Ma\xEEtrise des armes runiques : En Attente
    7. -
    8. R\xE9sistance \xE0 la magie : En Attente
    9. -
    10. T\xE9nacit\xE9 naine : En Attente
    11. +
    12. Maîtrise des armes runiques : En Attente
    13. +
    14. Résistance à la magie : En Attente
    15. +
    16. Ténacité naine : En Attente
    -
    Voie culturelle de l\x2019ordre de la Forge
    +
    Voie culturelle de l’ordre de la Forge
    1. Artisan de la forge : En Attente
    2. Forgeron runique : En Attente
    3. -
    4. Marteler le m\xE9tal : En Attente
    5. -
    6. Runes de d\xE9fense : En Attente
    7. -
    8. Ma\xEEtre artisan : En Attente
    9. +
    10. Marteler le métal : En Attente
    11. +
    12. Runes de défense : En Attente
    13. +
    14. Maître artisan : En Attente
    -
    Voie culturelle de l\x2019ordre du Talion
    +
    Voie culturelle de l’ordre du Talion
    1. Plein aux as : En Attente
    2. Le sens des affaires : En Attente
    3. @@ -2557,15 +2570,15 @@
      Voie culturelle de l\x2019ordre du Talion
    4. La Loge noire : En Attente
    5. Seigneur du Talion : En Attente
    -
    Voie culturelle de l\x2019ordre du Temple
    +
    Voie culturelle de l’ordre du Temple
      -
    1. Grosse t\xEAte : En Attente
    2. +
    3. Grosse tête : En Attente
    4. Enseigne du Temple : En Attente
    5. -
    6. Invention \xE9trange : En Attente
    7. -
    8. Rites fun\xE9raires (L) : En Attente
    9. -
    10. Ma\xEEtre du temple : En Attente
    11. +
    12. Invention étrange : En Attente
    13. +
    14. Rites funéraires (L) : En Attente
    15. +
    16. Maître du temple : En Attente
    -
    Voie culturelle de l\x2019ordre du Bouclier
    +
    Voie culturelle de l’ordre du Bouclier
    1. Combat en phalange : En Attente
    2. Formation militaire : En Attente
    3. @@ -2573,13 +2586,13 @@
      Voie culturelle de l\x2019ordre du Bouclier
    4. Fuite interdite : En Attente
    5. Veilleur du roi : En Attente
    -
    Voie culturelle de l\x2019ordre des Errants
    +
    Voie culturelle de l’ordre des Errants
    1. Moins que rien : En Attente
    2. -
    3. Pass\xE9 r\xE9volu : En Attente
    4. +
    5. Passé révolu : En Attente
    6. Paysan aguerri : En Attente
    7. -
    8. Solidarit\xE9 des Errants : En Attente
    9. -
    10. Volont\xE9 h\xE9ro\xEFque : En Attente
    11. +
    12. Solidarité des Errants : En Attente
    13. +
    14. Volonté héroïque : En Attente
    @@ -2591,7 +2604,7 @@
    Voie du peuple des Humains
  • Loup parmi les loups : En Attente
  • Enseignement exotique : En Attente
  • Versatile : En Attente
  • -
  • D\xE9passement : En Attente
  • +
  • Dépassement : En Attente
  • Voie culturelle des ruines nordiques
      @@ -2599,28 +2612,28 @@
      Voie culturelle des ruines nordiques
    1. Barbare : En Attente
    2. Expertise des haches : En Attente
    3. Homme des clans : En Attente
    4. -
    5. Conqu\xE9ran: En Attente
    6. +
    7. Conquéran: En Attente
    Voie culturelle du Mitan
      -
    1. Homme des cit\xE9s : En Attente
    2. -
    3. Entre tradition et progr\xE8s : En Attente
    4. +
    5. Homme des cités : En Attente
    6. +
    7. Entre tradition et progrès : En Attente
    8. Modernisme : En Attente
    9. Conspirateur : En Attente
    10. -
    11. Ma\xEEtre marchand : En Attente
    12. +
    13. Maître marchand : En Attente
    Voie culturelle des empires austraux
      -
    1. \xC9rudition : En Attente
    2. -
    3. \xC9tudes arcaniques : En Attente
    4. -
    5. Autorit\xE9 culturelle : En Attente
    6. -
    7. Pr\xE9dispositions arcaniques : En Attente
    8. +
    9. Érudition : En Attente
    10. +
    11. Études arcaniques : En Attente
    12. +
    13. Autorité culturelle : En Attente
    14. +
    15. Prédispositions arcaniques : En Attente
    16. Mage : En Attente
    Voie culturelle des Terres orientales
    1. Connaissances cosmopolites : En Attente
    2. -
    3. Rejeton de la cit\xE9 des Sang-m\xEAl\xE9s : En Attente
    4. +
    5. Rejeton de la cité des Sang-mêlés : En Attente
    6. Sentir la magie : En Attente
    7. Chevaucheur de dragons : En Attente
    8. Expert en filouterie : En Attente
    9. @@ -2630,16 +2643,16 @@

      5.1.3 Peaux Vertes

      Voie du peuple des Peaux Vertes
        -
      1. Pour l\x2019honneur : En Attente
      2. -
      3. Frappe d\xE9loyale : En Attente
      4. -
      5. Ma\xEEtrise des armes sauvages : En Attente
      6. -
      7. Croyances pa\xEFennes : En Attente
      8. -
      9. H\xE9ros tribal : En Attente
      10. +
      11. Pour l’honneur : En Attente
      12. +
      13. Frappe déloyale : En Attente
      14. +
      15. Maîtrise des armes sauvages : En Attente
      16. +
      17. Croyances païennes : En Attente
      18. +
      19. Héros tribal : En Attente
      Voie culturelle des Ogres
        -
      1. \xC9norme : En Attente
      2. +
      3. Énorme : En Attente
      4. Brute : En Attente
      5. Attaque massive (L) : En Attente
      6. Intuable : En Attente
      7. @@ -2668,80 +2681,80 @@

        5.2 Voies de la f

        Voie du bastion

          -
        1. Prot\xE9ger un alli\xE9 : !cof-proteger-un-allie @{selected|token_id} @{target|token_id}. Fonctionne aussi si on remplace le target par un nom de token. Le script ne v\xE9rifie pas que le combattant ne change pas d'alli\xE9 plus d'une fois par tour. Pour la capacit\xE9 avanc\xE9e, ajouter un pr\xE9dicat protegerUnAllieAvance.
        2. +
        3. Protéger un allié : !cof-proteger-un-allie @{selected|token_id} @{target|token_id}. Fonctionne aussi si on remplace le target par un nom de token. Le script ne vérifie pas que le combattant ne change pas d'allié plus d'une fois par tour. Pour la capacité avancée, ajouter un prédicat protegerUnAllieAvance.
        4. Absorber un coup (L) :
            -
          • utiliser !cof-effet-temp absorberUnCoup 1 pour se mettre en position. Attention, \xE7a ne v\xE9rifie pas si le combattant porte son bouclier.
          • -
          • le script propose un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le combattant est en position.
          • +
          • utiliser !cof-effet-temp absorberUnCoup 1 pour se mettre en position. Attention, ça ne vérifie pas si le combattant porte son bouclier.
          • +
          • le script propose un bouton à activer en cas d'attaque réussie alors que le combattant est en position.
        5. -
        6. Coup de bouclier : faire une attaque de bouclier, de type Arme gauche, avec le modificateur avecd12crit. Pour que cette attaque soit propos\xE9e dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un pr\xE9dicat attaqueAuBouclier de valeur le label de l'attaque.
        7. +
        8. Coup de bouclier : faire une attaque de bouclier, de type Arme gauche, avec le modificateur avecd12crit. Pour que cette attaque soit proposée dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un prédicat attaqueAuBouclier de valeur le label de l'attaque.
        9. Absorber un sort (L) :
            -
          • utiliser !cof-effet-temp absorberUnSort 1 pour se mettre en position. Attention, \xE7a ne v\xE9rifie pas si le combattant porte son bouclier.
          • -
          • le script propose un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le combattant est en position.
          • +
          • utiliser !cof-effet-temp absorberUnSort 1 pour se mettre en position. Attention, ça ne vérifie pas si le combattant porte son bouclier.
          • +
          • le script propose un bouton à activer en cas d'attaque réussie alors que le combattant est en position.
        10. -
        11. Armure lourde : Noter l'armure sur la feuille du personnage, et ajouter un pr\xE9dicat armureLourdeGuerrier au personnage. L'annulation du critique ne se produira que si l'armure est port\xE9e et que la valeur totale du bonus de d\xE9fense sup\xE9rieure ou \xE9gale \xE0 7 (le bonus de DEF d'une armure de plaques compl\xE8te).
        12. +
        13. Armure lourde : Noter l'armure sur la feuille du personnage, et ajouter un prédicat armureLourdeGuerrier au personnage. L'annulation du critique ne se produira que si l'armure est portée et que la valeur totale du bonus de défense supérieure ou égale à 7 (le bonus de DEF d'une armure de plaques complète).

        Voie de la bravoure

        1. Robustesse : rajouter les PVs sur la fiche.
        2. Armure naturelle : rajouter la DEF sur la fiche
        3. -
        4. Prouesse : ajouter un pr\xE9dicat prouesse (on peut y associer un nombre, si on souhaite plus d'une utilisation par tour). Le script g\xE9n\xE9rera automatiquement les boutons Prouesse sur les test appropri\xE9s.
        5. -
        6. Dernier rempart (L) : pas de support particulier, le MJ doit g\xE9rer les attaques suppl\xE9mentaires.
        7. -
        8. Constitution h\xE9ro\xEFque : reporter les bonus sur la fiche.
        9. +
        10. Prouesse : ajouter un prédicat prouesse (on peut y associer un nombre, si on souhaite plus d'une utilisation par tour). Le script générera automatiquement les boutons Prouesse sur les test appropriés.
        11. +
        12. Dernier rempart (L) : pas de support particulier, le MJ doit gérer les attaques supplémentaires.
        13. +
        14. Constitution héroïque : reporter les bonus sur la fiche.
        -

        Voie du combat \xE0 deux armes

        +

        Voie du combat à deux armes

          -
        1. Combat \xE0 deux armes (L) : mettre une des attaques de type arme gauche, et y ajouter le modificateur avecd12crit. Pas encore de support pour la capacit\xE9 avanc\xE9e : dans ce cas, ajoutez le +1 dans la barre 3 du token ou sur les attaques.
        2. -
        3. Parade crois\xE9e (L) : !cof-effet-temp paradeCroisee 1 --valeur 2 --montreActions. Pour la capacit\xE9 avanc\xE9e, !cof-effet-temp paradeCroisee 1 --valeur 4 --montreActions.
        4. -
        5. Sym\xE9trie : En Attente
        6. +
        7. Combat à deux armes (L) : mettre une des attaques de type arme gauche, et y ajouter le modificateur avecd12crit. Pas encore de support pour la capacité avancée : dans ce cas, ajoutez le +1 dans la barre 3 du token ou sur les attaques.
        8. +
        9. Parade croisée (L) : !cof-effet-temp paradeCroisee 1 --valeur 2 --montreActions. Pour la capacité avancée, !cof-effet-temp paradeCroisee 1 --valeur 4 --montreActions.
        10. +
        11. Symétrie : En Attente
        12. Double peine : En Attente
        13. -
        14. Combat \xE0 deux armes parfait : En Attente
        15. +
        16. Combat à deux armes parfait : En Attente
        -

        Voie du combat mont\xE9

        +

        Voie du combat monté

          -
        1. Fid\xE8le monture : Faire un personnage pour la monture, avec un pr\xE9dicat monture. Pour monter sur la monture, on peut utiliser une ability de type token action, avec !cof-en-selle @{selected|token_id} nom_de_la_monture. Pour en descendre, il suffit de cliquer \xE0 nouveau sur le bouton de l'ability. Si vous souhaitez \xE9viter que la monture apparaisse dans le turn tracker, vous pouvez ajouter un pr\xE9dicat aucuneActionCombat \xE0 la monture.
        2. -
        3. Cavalier \xE9m\xE9rite : Ajouter au combattant un pr\xE9dicat cavalierEmerite:2. Pour la d\xE9fense de la monture, ajouter \xE0 cellle-ci un pr\xE9dicat defDeriveeDe de valeur le nom du combattant (exactement tel qu'il appara\xEEt sur la fiche, il est possible que cela demande d'utiliser la syntaxe avec ::). Attention, cela suppose que le combattant a une meilleure DEF que sa monture. Si ce n'est pas le cas, faire les ajustements sur la fiche du combattant.
        4. -
        5. Massacrer la pi\xE9taille : En Attente
        6. -
        7. Charge : pas de support pour le d\xE9placement, mais +
        8. Fidèle monture : Faire un personnage pour la monture, avec un prédicat monture. Pour monter sur la monture, on peut utiliser une ability de type token action, avec !cof-en-selle @{selected|token_id} nom_de_la_monture. Pour en descendre, il suffit de cliquer à nouveau sur le bouton de l'ability. Si vous souhaitez éviter que la monture apparaisse dans le turn tracker, vous pouvez ajouter un prédicat aucuneActionCombat à la monture.
        9. +
        10. Cavalier émérite : Ajouter au combattant un prédicat cavalierEmerite:2. Pour la défense de la monture, ajouter à cellle-ci un prédicat defDeriveeDe de valeur le nom du combattant (exactement tel qu'il apparaît sur la fiche, il est possible que cela demande d'utiliser la syntaxe avec ::). Attention, cela suppose que le combattant a une meilleure DEF que sa monture. Si ce n'est pas le cas, faire les ajustements sur la fiche du combattant.
        11. +
        12. Massacrer la piétaille : En Attente
        13. +
        14. Charge : pas de support pour le déplacement, mais
          • Pour l'attaque : utiliser --m2d20 --plus 1d6
          • -
          • Pour les cr\xE9atures sur la trajectoire, utiliser !cof-jet FOR 18, et en cas de succ\xE8s, infliger les DM (!cof-dmg 1d6)
          • +
          • Pour les créatures sur la trajectoire, utiliser !cof-jet FOR 18, et en cas de succès, infliger les DM (!cof-dmg 1d6)
        15. -
        16. Monture fantastique : faire un personnage pour la monture, avec un pr\xE9dicat monture.
        17. +
        18. Monture fantastique : faire un personnage pour la monture, avec un prédicat monture.

        Voie du commandement

          -
        1. Action concert\xE9e : utiliser !cof-echange-init @{selected|token_id} @{target|token_id} n o\xF9 n peut valoir 0, 1, 2 ou 3 selon le rang dans la voie et si la capacit\xE9 est avanc\xE9e.
        2. -
        3. \xC0 couvert (L) : !cof-a-couvert @{selected|token_id} @{target|token_id} le target est l'alli\xE9 qui se d\xE9place avec l'arquebusier. Se s\xE9lectionner soi-m\xEAme si pas d'alli\xE9. Pas encore de support pour la capacit\xE9 avanc\xE9e.
        4. -
        5. Exemplaire : faire !cof-exemplaire, juste apr\xE8s l'attaque rat\xE9e.
        6. +
        7. Action concertée : utiliser !cof-echange-init @{selected|token_id} @{target|token_id} nn peut valoir 0, 1, 2 ou 3 selon le rang dans la voie et si la capacité est avancée.
        8. +
        9. À couvert (L) : !cof-a-couvert @{selected|token_id} @{target|token_id} le target est l'allié qui se déplace avec l'arquebusier. Se sélectionner soi-même si pas d'allié. Pas encore de support pour la capacité avancée.
        10. +
        11. Exemplaire : faire !cof-exemplaire, juste après l'attaque ratée.
        12. Ordre de bataille : pas de support
        13. Charge fantastique (L) : !cof-charge-fantastique @{selected|token_id} --alliesEnVue --self --limiteParCombat 1
        -

        Voie de la f\xE9rocit\xE9

        +

        Voie de la férocité

        1. Cri de guerre : !cof-effet-combat criDeGuerre
        2. -
        3. Charge (L) : #Attaque -1 --bonusAttaque 2 --plus 1d6. Le d\xE9placement n'est pas encore g\xE9r\xE9.
        4. -
        5. Rage du berserk (L) : utiliser !cof-rage-du-berserk, \xE0 la fois pour entrer en rage et pour tenter d'en sortir avant la fin du combat. Si le MJ souhaite mettre fin \xE0 la rage \xE0 cause d'un effet ext\xE9rieur, il peut utiliser la commande !cof-effet-combat rageDuBerserk fin.
        6. -
        7. M\xEAme pas mal : ajouter un pr\xE9dicat memePasMal. Le joueur doit lui-m\xEAme activer la rage ou le furie si il souhaite en profiter.
        8. +
        9. Charge (L) : #Attaque -1 --deplaceDe 5 20 --bonusAttaque 2 --plus 1d6.
        10. +
        11. Rage du berserk (L) : utiliser !cof-rage-du-berserk, à la fois pour entrer en rage et pour tenter d'en sortir avant la fin du combat. Si le MJ souhaite mettre fin à la rage à cause d'un effet extérieur, il peut utiliser la commande !cof-effet-combat rageDuBerserk fin.
        12. +
        13. Même pas mal : ajouter un prédicat memePasMal. Le joueur doit lui-même activer la rage ou le furie si il souhaite en profiter.
        14. Attaque tourbillon (L) : !cof-explosion -1 --auto --disque 5 --saufAllies --limiteParCombat 1 tourbillon.

        Voie de la guerre

          -
        1. Posture de combat : !cof-posture-de-combat bonus attr1 attr2, o\xF9 les deux attr peuvent \xEAtre soit DEF soit ATT soit DM, et le bonus est retir\xE9 au premier attribut pour \xEAtre ajout\xE9 au second. Le bonus peut \xEAtre limit\xE9 si le combattant a un pr\xE9dicat voieDuSoldat qui indique son rang dans la voie. Exemple d'utilisation : !cof-posture-de-combat ?{Bonus|1|2|3|4|5} ?{Baisser|D\xE9fense,DEF|Attaque,ATT|D\xE9g\xE2ts,DM} ?{Augmenter|D\xE9fense,DEF|Attaque,ATT|D\xE9g\xE2ts,DM}. Normalement, la r\xE8gle fait d\xE9cider de sa posture au combattant \xE0 chaque tour, mais en pratique, il en change assez rarement. Une posture de combat reste donc active jusqu'\xE0 la fin du combat ou jusqu'\xE0 ce qu'on en change (elle est neutre si on a le m\xEAme attribut \xE0 buffer et d\xE9buffer).
        2. -
        3. D\xE9sarmer (L) : !cof-desarmer @{selected|token_id} @{target|token_id}.
        4. -
        5. Double attaque (L) : faire deux attaques, avec l'option suppl\xE9mentaire --bonusAttaque -2.
        6. -
        7. Attaque circulaire (L) : faire les attaques normalement, ce n'est pas consid\xE9r\xE9 comme une aoe.
        8. +
        9. Posture de combat : !cof-posture-de-combat bonus attr1 attr2, où les deux attr peuvent être soit DEF soit ATT soit DM, et le bonus est retiré au premier attribut pour être ajouté au second. Le bonus peut être limité si le combattant a un prédicat voieDuSoldat qui indique son rang dans la voie. Exemple d'utilisation : !cof-posture-de-combat ?{Bonus|1|2|3|4|5} ?{Baisser|Défense,DEF|Attaque,ATT|Dégâts,DM} ?{Augmenter|Défense,DEF|Attaque,ATT|Dégâts,DM}. Normalement, la règle fait décider de sa posture au combattant à chaque tour, mais en pratique, il en change assez rarement. Une posture de combat reste donc active jusqu'à la fin du combat ou jusqu'à ce qu'on en change (elle est neutre si on a le même attribut à buffer et débuffer).
        10. +
        11. Désarmer (L) : !cof-desarmer @{selected|token_id} @{target|token_id}.
        12. +
        13. Double attaque (L) : faire deux attaques, avec l'option supplémentaire --bonusAttaque -2.
        14. +
        15. Attaque circulaire (L) : faire les attaques normalement, ce n'est pas considéré comme une aoe.
        16. Attaque puissante : #Attaque -1 --avecd12crit --plus 2d6 --seulementContact.
        -

        Voie de la ma\xEEtrise des armes

        +

        Voie de la maîtrise des armes

          -
        1. Arme de pr\xE9dilection : il est possible de pr\xE9ciser une famille d'armes de pr\xE9dilection (un peu plus large que dans les r\xE8gles), parmis arc, arbalete, fronde, hache, epee, marteau, masse, sabre, epieu, poudre, baton et rapiere. Si cela vous convient, ajoutez un pr\xE9dicat armeDePredilection de valeur une de ces familles. Sinon, simplement ajouter le bonus sur les attaques dans la fiche.
        2. +
        3. Arme de prédilection : il est possible de préciser une famille d'armes de prédilection (un peu plus large que dans les règles), parmis arc, arbalete, fronde, hache, epee, marteau, masse, sabre, epieu, poudre, baton et rapiere. Si cela vous convient, ajoutez un prédicat armeDePredilection de valeur une de ces familles. Sinon, simplement ajouter le bonus sur les attaques dans la fiche.
        4. Science du critique : En Attente
        5. -
        6. Sp\xE9cialisation : En Attente
        7. +
        8. Spécialisation : En Attente
        9. Attaque parfaite (L) : En Attente
        10. Riposte : En Attente
        @@ -2749,61 +2762,61 @@

        Voie du pugilat

        1. Poings de fer : En Attente
        2. Peau de pierre : En Attente
        3. -
        4. Peau d\x2019acier : En Attente
        5. -
        6. D\xE9luge de coups (L) : En Attente
        7. -
        8. Force h\xE9ro\xEFque : En Attente
        9. +
        10. Peau d’acier : En Attente
        11. +
        12. Déluge de coups (L) : En Attente
        13. +
        14. Force héroïque : En Attente

        Voie de la puissance

        1. Argument de taille : En Attente
        2. Tour de force : En Attente
        3. Attaque brutale (L) : En Attente
        4. -
        5. Briseur d\x2019os : En Attente
        6. -
        7. Vitalit\xE9 d\xE9bordante : En Attente
        8. +
        9. Briseur d’os : En Attente
        10. +
        11. Vitalité débordante : En Attente

        5.3 Voies de la famille des aventuriers

        -

        Voie de l\x2019acrobatie

        +

        Voie de l’acrobatie

        1. Acrobate : En Attente
        2. -
        3. Gr\xE2ce f\xE9line : En Attente
        4. +
        5. Grâce féline : En Attente
        6. Lanceur de couteau : En Attente
        7. Esquive acrobatique : En Attente
        8. -
        9. Dext\xE9rit\xE9 h\xE9ro\xEFque : En Attente
        10. +
        11. Dextérité héroïque : En Attente
        -

        Voie de l\x2019arbal\xE8trie

        +

        Voie de l’arbalètrie

        1. Joli coup! : En Attente
        2. Cadence de tir : En Attente
        3. Tir double (L) : En Attente
        4. -
        5. As de la g\xE2chette : En Attente
        6. +
        7. As de la gâchette : En Attente
        8. Tir mortel : En Attente
        -

        Voie de l\x2019archerie

        +

        Voie de l’archerie

          -
        1. Sens aff\xFBt\xE9s : En Attente
        2. +
        3. Sens affûtés : En Attente
        4. Tir aveugle (L) : En Attente
        5. Tir rapide (L) : En Attente
        6. -
        7. Fl\xE8che de mort (L) : En Attente
        8. +
        9. Flèche de mort (L) : En Attente
        10. Dans le mille : En Attente
        -

        Voie de l\x2019assassinat

        +

        Voie de l’assassinat

          -
        1. Discr\xE9tion : En Attente
        2. +
        3. Discrétion : En Attente
        4. Attaque sournoise (L) : En Attente
        5. Frappe chirurgicale : En Attente
        6. Surprise : En Attente
        7. -
        8. Botte secr\xE8te : En Attente
        9. +
        10. Botte secrète : En Attente
        -

        Voie du boh\xE8me

        +

        Voie du bohème

          -
        1. Rumeurs et l\xE9gendes : En Attente
        2. +
        3. Rumeurs et légendes : En Attente
        4. Argumenter : En Attente
        5. -
        6. D\xE9brouillard : En Attente
        7. -
        8. D\xE9guisement : En Attente
        9. -
        10. Touche-\xE0-tout : En Attente
        11. +
        12. Débrouillard : En Attente
        13. +
        14. Déguisement : En Attente
        15. +
        16. Touche-à-tout : En Attente

        Voie du charme

          @@ -2811,15 +2824,15 @@

          Voie du charme

        1. Provocation (L) : En Attente
        2. Attaque flamboyante (L) : En Attente
        3. Suggestion (L) : En Attente
        4. -
        5. Charisme h\xE9ro\xEFque : En Attente
        6. +
        7. Charisme héroïque : En Attente

        Voie de la chasse

        1. Proche de la nature : En Attente
        2. -
        3. Nature nourrici\xE8re : En Attente
        4. -
        5. Attaque \xE9clair (L) : En Attente
        6. -
        7. Ennemis jur\xE9s : En Attente
        8. -
        9. Perception h\xE9ro\xEFque : En Attente
        10. +
        11. Nature nourricière : En Attente
        12. +
        13. Attaque éclair (L) : En Attente
        14. +
        15. Ennemis jurés : En Attente
        16. +
        17. Perception héroïque : En Attente

        Voie du compagnon animal

          @@ -2829,7 +2842,7 @@

          Voie du compagnon animal

        1. Empathie animale : En Attente
        2. Animal fabuleux : En Attente
        -

        Voie de l\x2019escrime

        +

        Voie de l’escrime

        1. Attaque en finesse : En Attente
        2. Intelligence du combat : En Attente
        3. @@ -2840,10 +2853,10 @@

          Voie de l\x2019escrime

          Voie de la fourberie

          1. Doigts agiles : En Attente
          2. -
          3. D\xE9tecter les pi\xE8ges : En Attente
          4. +
          5. Détecter les pièges : En Attente
          6. Croc-en-jambe : En Attente
          7. Attaque paralysante (L) : En Attente
          8. -
          9. Attaque en tra\xEEtre : En Attente
          10. +
          11. Attaque en traître : En Attente
        @@ -2851,193 +2864,193 @@

        5.4 Voies de la fam

        Talents magiques

          -
        • D\xE9tection de la magie : pas de support.
        • +
        • Détection de la magie : pas de support.
        • Flamme : Faire une attaque magique de type feu pour l'attaque au contact. Pour l'illumination, !cof-lumiere @{selected|token_id} 5 1 --mana 0.
        • -
        • Inspiration : !cof-effet-temp inspiration [[2+@{selected|SAG}]] --target @{target|token_id} --lanceur @{selected|token_id} --portee 10. Pour l'instant le script ne v\xE9rifie pas que le sort n'est pas actif sur trop de cibles \xE0 la fois.
        • -
        • Lumi\xE8res dansantes : !cof-lumiere @{selected|token_id} 20 15 --mana 0. Le script ne g\xE8re pas encore l'annulation de l'effet au moindre choc.
        • +
        • Inspiration : !cof-effet-temp inspiration [[2+@{selected|SAG}]] --target @{target|token_id} --lanceur @{selected|token_id} --portee 10. Pour l'instant le script ne vérifie pas que le sort n'est pas actif sur trop de cibles à la fois.
        • +
        • Lumières dansantes : !cof-lumiere @{selected|token_id} 20 15 --mana 0. Le script ne gère pas encore l'annulation de l'effet au moindre choc.
        • Projectile de force : - Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4, port\xE9e 50, type Sortil\xE8ge, modificateur auto d\xE9g\xE2ts contondants, option --mana 0. + Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4, portée 50, type Sortilège, modificateur auto dégâts contondants, option --mana 0.
        -

        Voie de l\x2019alchimie

        -

        Pour cr\xE9er ou juste voir ses \xE9lixirs, utiliser la commande !cof-elixirs. Pour cela, il faut aussi un pr\xE9dicat voieDeLAlchimie avec comme valeur le rang dans la voie. Noter que la commande !cof-elixirs affiche une liste d'\xE9lixirs, et que pour effectivement cr\xE9er un \xE9lixir, il faut cliquer sur le bouton correspondant dans cette liste.

        +

        Voie de l’alchimie

        +

        Pour créer ou juste voir ses élixirs, utiliser la commande !cof-elixirs. Pour cela, il faut aussi un prédicat voieDeLAlchimie avec comme valeur le rang dans la voie. Noter que la commande !cof-elixirs affiche une liste d'élixirs, et que pour effectivement créer un élixir, il faut cliquer sur le bouton correspondant dans cette liste.

          -
        1. Fortifiant : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables. Pour la version avanc\xE9e, ajouter un pr\xE9dicat fortiviantAvance
        2. -
        3. Feu gr\xE9geois : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables. Pas de support pour la version avanc\xE9e pour l'instant : utiliser !cof-dmg rang --feu pour les personnages qui auraient rat\xE9 leur jet de DEX.
        4. -
        5. Huile instable : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
        6. -
        7. \xC9lixir de gu\xE9rison : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
        8. -
        9. \xC9lixirs de Protection : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
        10. +
        11. Fortifiant : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables. Pour la version avancée, ajouter un prédicat fortiviantAvance
        12. +
        13. Feu grégeois : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables. Pas de support pour la version avancée pour l'instant : utiliser !cof-dmg rang --feu pour les personnages qui auraient raté leur jet de DEX.
        14. +
        15. Huile instable : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
        16. +
        17. Élixir de guérison : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
        18. +
        19. Élixirs de Protection : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.

        Voie des arts druidiques

        1. Langage des animaux : En Attente
        2. -
        3. Nu\xE9e d\x2019insectes* : En Attente
        4. +
        5. Nuée d’insectes* : En Attente
        6. Le guetteur : En Attente
        7. -
        8. Masque du pr\xE9dateur* : En Attente
        9. -
        10. Sagesse h\xE9ro\xEFque : En Attente
        11. +
        12. Masque du prédateur* : En Attente
        13. +
        14. Sagesse héroïque : En Attente

        Voie de la divination

          -
        1. Sixi\xE8me sens : ajouter le bonus en DEF divers et initiative divers, ajouter une comp\xE9tence vigilance, de valeur 5 (le bonus aux jet de surprise).
        2. -
        3. D\xE9tection de l\x2019invisible* : En Attente
        4. +
        5. Sixième sens : ajouter le bonus en DEF divers et initiative divers, ajouter une compétence vigilance, de valeur 5 (le bonus aux jet de surprise).
        6. +
        7. Détection de l’invisible* : En Attente
        8. Clairvoyance* : En Attente
        9. Prescience* : En Attente
        10. Hyperconscience : En Attente
        -

        Voie de l\x2019envo\xFBtement

        +

        Voie de l’envoûtement

        1. Injonction* : En Attente
        2. Sommeil* : En Attente
        3. Confusion* : En Attente
        4. -
        5. Amiti\xE9* : En Attente
        6. +
        7. Amitié* : En Attente
        8. Domination* : En Attente
        -

        Voie des for\xEAts

        +

        Voie des forêts

          -
        1. Peau d\x2019\xE9corce* : - !cof-effet-temp peauDEcorce [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 1|\xC9conome (L),--mana 0|\xC9tendue (L),--puissant duree --mana 1}. Si le personnage a un pr\xE9dicat voieDesForets de valeur 4 ou plus, le bonus sera de +4 en DEF. Ajouter un pr\xE9dicat peauDEcorceAvancee pour la version en capacit\xE9 avanc\xE9e.
        2. -
        3. Prison v\xE9g\xE9tale* : En Attente
        4. +
        5. Peau d’écorce* : + !cof-effet-temp peauDEcorce [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 1|Économe (L),--mana 0|Étendue (L),--puissant duree --mana 1}. Si le personnage a un prédicat voieDesForets de valeur 4 ou plus, le bonus sera de +4 en DEF. Ajouter un prédicat peauDEcorceAvancee pour la version en capacité avancée.
        6. +
        7. Prison végétale* : En Attente
        8. Baies magiques* : En Attente
        9. -
        10. Animation d\x2019un arbre* : En Attente
        11. -
        12. R\xE9g\xE9n\xE9ration* : En Attente
        13. +
        14. Animation d’un arbre* : En Attente
        15. +
        16. Régénération* : En Attente

        Voie des illusions

          -
        1. Image d\xE9cal\xE9e* : !cof-effet-temp imageDecalee [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 1|\xC9conome (L),--mana 0|\xC9tendue (L),--puissant duree --mana 1}. Pour la version avanc\xE9e de la capacit\xE9, ajouter un pr\xE9dicat imageDecaleeAvancee.
        2. +
        3. Image décalée* : !cof-effet-temp imageDecalee [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 1|Économe (L),--mana 0|Étendue (L),--puissant duree --mana 1}. Pour la version avancée de la capacité, ajouter un prédicat imageDecaleeAvancee.
        4. Mirage* : En Attente
        5. Imitation* : En Attente
        6. -
        7. D\xE9doublement* : En Attente
        8. +
        9. Dédoublement* : En Attente
        10. Tueur fantasmagorique* : En Attente
        -

        Voie de la magie \xE9l\xE9mentaliste

        +

        Voie de la magie élémentaliste

        1. Brumes* : - !cof-tenebres @{selected|token_id} @{target|token_id} --brumes --mana 1. La commande pose un token de brouillard pour visualiser la zone. Tous les tokens pr\xE9sents dans la zone au lancement du sort sont automatiquement dans l'\xE9tat p\xE9nombre. Au MJ ensuite d'enlever l'\xE9tat p\xE9nombre quand les cibles sortent de la zone. A la fin de la dur\xE9e du sort, ou \xE0 la fin du combat, la zone et les \xE9tats p\xE9nombre restant disparaissent automatiquement. Il est aussi possible de changer les valeurs par d\xE9faut du sort (port\xE9e 20m, rayon 20m) avec les options --portee X et --rayon X. En r\xE8gle custom, l'option puissant permet de doubler la superficie couverte (le script calcule le rayon appropri\xE9 si custom).
        2. + !cof-tenebres @{selected|token_id} @{target|token_id} --brumes --mana 1. La commande pose un token de brouillard pour visualiser la zone. Tous les tokens présents dans la zone au lancement du sort sont automatiquement dans l'état pénombre. Au MJ ensuite d'enlever l'état pénombre quand les cibles sortent de la zone. A la fin de la durée du sort, ou à la fin du combat, la zone et les états pénombre restant disparaissent automatiquement. Il est aussi possible de changer les valeurs par défaut du sort (portée 20m, rayon 20m) avec les options --portee X et --rayon X. En règle custom, l'option puissant permet de doubler la superficie couverte (le script calcule le rayon approprié si custom).
        3. Sous tension* :
            -
          • !cof-effet-temp sousTension [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 2|\xC9conome (L),--mana 0|\xC9tendue (L),--puissant duree --mana 2|Puissante (L),--puissant --mana 2} pour lancer le sort et mettre le personnage sous tension
          • -
          • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, port\xE9e 10, type Sortil\xE8ge, d\xE9g\xE2ts \xE9lectriques, options --si etat sousTension --fx beam-holy.
          • -
          • Utiliser un pr\xE9dicat voieDeLaMagieElementaliste de valeur le rang dans la voie pour le passage des d\xE9g\xE2ts \xE0 2d6 quand le personnage est touch\xE9.
          • -
          • Pas de support particulier pour la version avanc\xE9e.
          • +
          • !cof-effet-temp sousTension [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 2|Économe (L),--mana 0|Étendue (L),--puissant duree --mana 2|Puissante (L),--puissant --mana 2} pour lancer le sort et mettre le personnage sous tension
          • +
          • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, portée 10, type Sortilège, dégâts électriques, options --si etat sousTension --fx beam-holy.
          • +
          • Utiliser un prédicat voieDeLaMagieElementaliste de valeur le rang dans la voie pour le passage des dégâts à 2d6 quand le personnage est touché.
          • +
          • Pas de support particulier pour la version avancée.
        4. Armure de terre* : - bien utiliser un pr\xE9dicat voieDeLaMagieElementaliste avec comme valeur le rang dans la voie. Pour lancer le sort, faire !cof-effet-temp protectionContreLesElements [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 3|\xC9conome (L),--mana 1|\xC9tendue (L),--puissant duree --mana 3}.
        5. + bien utiliser un prédicat voieDeLaMagieElementaliste avec comme valeur le rang dans la voie. Pour lancer le sort, faire !cof-effet-temp protectionContreLesElements [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 3|Économe (L),--mana 1|Étendue (L),--puissant duree --mana 3}.
        6. Boule de feu* : En Attente
        7. -
        8. Intelligence h\xE9ro\xEFque : En Attente
        9. +
        10. Intelligence héroïque : En Attente

        Voie de la magie runique

          -
        1. Forgeron* : Il faut un pr\xE9dicat voieDuMetal pour conna\xEEtre le rang (ou utiliser l'option --valeur). Lancer le sort avec !cof-effet-temp forgeron(L) [[5+@{selected|SAG}]] o\xF9 L est le label d'une attaque. Ensuite, chaque fois que cette attaque sera utilis\xE9e, les d\xE9g\xE2ts seront ajout\xE9s. Limitations : si deux attaques utilisent la m\xEAme arme, il faut faire deux fois l'action, une pour chaque attaque.
        2. -
        3. Rune d\x2019\xE9nergie* : En Attente
        4. +
        5. Forgeron* : Il faut un prédicat voieDuMetal pour connaître le rang (ou utiliser l'option --valeur). Lancer le sort avec !cof-effet-temp forgeron(L) [[5+@{selected|SAG}]]L est le label d'une attaque. Ensuite, chaque fois que cette attaque sera utilisée, les dégâts seront ajoutés. Limitations : si deux attaques utilisent la même arme, il faut faire deux fois l'action, une pour chaque attaque.
        6. +
        7. Rune d’énergie* : En Attente
        8. Rune de puissance* : En Attente
        9. Rune de garde* : En Attente
        10. Rune de tradition : En Attente

        Voie du mysticisme

          -
        1. B\xE9n\xE9diction* : En Attente
        2. +
        3. Bénédiction* : En Attente
        4. Protection contre le mal* : En Attente
        5. -
        6. D\xE9livrance* : En Attente
        7. +
        8. Délivrance* : En Attente
        9. Sanctuaire* : En Attente
        10. Rituel de puissance : En Attente

        Voie des sombres savoirs

        1. Saignements* : En Attente
        2. -
        3. Mal\xE9diction* : En Attente
        4. +
        5. Malédiction* : En Attente
        6. Pacte sanglant* : En Attente
        7. -
        8. H\xE9morragie* : En Attente
        9. -
        10. Invocation d\x2019un d\xE9mon* : En Attente
        11. +
        12. Hémorragie* : En Attente
        13. +
        14. Invocation d’un démon* : En Attente

        5.4 Voies de prestige

        -

        6. Markers Personnalis\xE9s

        -

        6.1 Pr\xE9sentation

        +

        6. Markers Personnalisés

        +

        6.1 Présentation

        -

        Roll20 peut \xEAtre d\xE9routant lors des premi\xE8res utilisations pour des joueurs plus habitu\xE9s au Jeu de R\xF4le sur table. Il introduit des notions peu courantes du fait que les combats vont se d\xE9rouler sur des "battlemaps" quadrill\xE9es ou non. Aussi on va prendre quelques minutes pour expliquer deux notions importantes : les tokens et les tokens markers (plus simplement appel\xE9s markers par la suite).

        -

        Le token : Un token est la repr\xE9sentation graphique d'un personnage (PJ ou PNJ) sur la battlemap. Gr\xE2ce au token on sait \xE0 tout moment o\xF9 se trouve le personnage, s'il subit un sort \xE0 effet de zone ou si sa ligne de tir est d\xE9gag\xE9e par exemple.

        -

        Le marker : Un marker est forc\xE9ment attach\xE9 \xE0 un token. Il repr\xE9sente un "\xE9tat" qui affecte le personnage (liste des \xE9tats). Il se mat\xE9rialise par une ic\xF4ne dans le coin en haut \xE0 doite du token. Un token peut afficher plusieurs markers au m\xEAme moment. Ils repr\xE9sentent plusieurs \xE9tats qui se cumulent pour ce personnage. +

        Roll20 peut être déroutant lors des premières utilisations pour des joueurs plus habitués au Jeu de Rôle sur table. Il introduit des notions peu courantes du fait que les combats vont se dérouler sur des "battlemaps" quadrillées ou non. Aussi on va prendre quelques minutes pour expliquer deux notions importantes : les tokens et les tokens markers (plus simplement appelés markers par la suite).

        +

        Le token : Un token est la représentation graphique d'un personnage (PJ ou PNJ) sur la battlemap. Grâce au token on sait à tout moment où se trouve le personnage, s'il subit un sort à effet de zone ou si sa ligne de tir est dégagée par exemple.

        +

        Le marker : Un marker est forcément attaché à un token. Il représente un "état" qui affecte le personnage (liste des états). Il se matérialise par une icône dans le coin en haut à doite du token. Un token peut afficher plusieurs markers au même moment. Ils représentent plusieurs états qui se cumulent pour ce personnage.

        -

        Dans l'image ci-dessus le token c'est le personnage \xE0 la cape bleue qui repr\xE9sente un PJ et le marker c'est le petit escargot qui signifie que ce m\xEAme PJ est "ralenti". Le script g\xE8re les \xE9tats des PJ et PNJ et il mat\xE9rialisera leurs \xE9tats gr\xE2ce aux markers. Par exemple le MJ va demande un jet de surprise, le script effectue les jets de d\xE9s n\xE9cessaire et mat\xE9rialise l'\xE9tat "surpris" gr\xE2ce \xE0 un marker pour les personnages qui ont rat\xE9 leur jet de d\xE9. Le script applique automatiquement le malus -5 \xE0 la DEF. Au bout d'un tour l'\xE9tat "surpris" et le marker seront retir\xE9s automatiquement par le script. Le MJ peut aussi mettre directement un \xE9tat \xE0 un personnage. Par exemple s'il consid\xE8re que ses PJs voyagent trop charg\xE9s il peut ajouter le marker "encombr\xE9" qui lui rappelera que dor\xE9navant les jets de DEX se font sur un d12 et plus sur un d20.

        -

        Il existe des markers qui ne repr\xE9sentent pas un \xE9tat mais ils sont rares. On peut souligner les ronds de couleurs qui permmettent au joueur de retrouver son token plus facilement. De la m\xEAme mani\xE8re dans les markers cof il y existent deux marqueurs cof-init... qui permettent de rep\xE9rer le prochain joueur pendant les combats. Ce n'est pas un \xE9tat.

        +

        Dans l'image ci-dessus le token c'est le personnage à la cape bleue qui représente un PJ et le marker c'est le petit escargot qui signifie que ce même PJ est "ralenti". Le script gère les états des PJ et PNJ et il matérialisera leurs états grâce aux markers. Par exemple le MJ va demande un jet de surprise, le script effectue les jets de dés nécessaire et matérialise l'état "surpris" grâce à un marker pour les personnages qui ont raté leur jet de dé. Le script applique automatiquement le malus -5 à la DEF. Au bout d'un tour l'état "surpris" et le marker seront retirés automatiquement par le script. Le MJ peut aussi mettre directement un état à un personnage. Par exemple s'il considère que ses PJs voyagent trop chargés il peut ajouter le marker "encombré" qui lui rappelera que dorénavant les jets de DEX se font sur un d12 et plus sur un d20.

        +

        Il existe des markers qui ne représentent pas un état mais ils sont rares. On peut souligner les ronds de couleurs qui permmettent au joueur de retrouver son token plus facilement. De la même manière dans les markers cof il y existent deux marqueurs cof-init... qui permettent de repérer le prochain joueur pendant les combats. Ce n'est pas un état.

        -

        6.2 R\xE9cup\xE9ration des markers d\xE9di\xE9s COF

        +

        6.2 Récupération des markers dédiés COF

        -

        Roll20 poss\xE8de des markers par d\xE9faut mais ils ne sont pas toujours adapt\xE9s pour Chroniques Oubli\xE9es Fantasy. La communaut\xE9 a vot\xE9 pour choisir les tokens les plus pertinents dans le contexte COF. Voici le lien vers le post dans le forum BBE. N'h\xE9sitez pas \xE0 venir poser vos questions ou proposer vos talents de graphiste \xE0 la communaut\xE9.

        -

        Avant de pouvoir cr\xE9er votre propre jeu de markers sur Roll20, vous devez pr\xE9alablement t\xE9l\xE9charger ceux mis \xE0 disposition par la communaut\xE9 depuis le repository GitHub du projet. Proc\xE9dez comme suit :

        +

        Roll20 possède des markers par défaut mais ils ne sont pas toujours adaptés pour Chroniques Oubliées Fantasy. La communauté a voté pour choisir les tokens les plus pertinents dans le contexte COF. Voici le lien vers le post dans le forum BBE. N'hésitez pas à venir poser vos questions ou proposer vos talents de graphiste à la communauté.

        +

        Avant de pouvoir créer votre propre jeu de markers sur Roll20, vous devez préalablement télécharger ceux mis à disposition par la communauté depuis le repository GitHub du projet. Procédez comme suit :

        -

        Une fois le fichier t\xE9l\xE9charg\xE9 sur votre PC d\xE9zippez le r\xE9pertoire cof-marker-set et son sous-r\xE9pertoire

        +

        Une fois le fichier téléchargé sur votre PC dézippez le répertoire cof-marker-set et son sous-répertoire

        6.3 Importation des markers dans Roll20

        -

        Dans le r\xE9pertoire cof-marker-set vous trouverez tous les markers qui ont \xE9t\xE9 choisis par la communaut\xE9. Dans le r\xE9pertoire markers-alternatifs vous trouverez les glorieux seconds au vote que vous pouvez utiliser en lieu et place du marker choisi s'il vous pla\xEEt plus. Il vous suffit alors de glisser-d\xE9poser le fichier dans le r\xE9pertoire principal et de confirmer l'\xE9crasement de l'autre marker. Vous pouvez aussi choisir vos propres markers dans cette g\xE9niale biblioth\xE9que d'ic\xF4nes. Vous pouvez aussi d\xE9ssiner vos propre marker. Les limites sont que la taille de l'image doit \xEAtre exactement de 512x512 px. Un fichier PNG est pr\xE9f\xE9rable pour g\xE9rer la transparence. Enfin votre fichier doit porter exactement le m\xEAme nom qu'indiqu\xE9 dans cette documentation.

        +

        Dans le répertoire cof-marker-set vous trouverez tous les markers qui ont été choisis par la communauté. Dans le répertoire markers-alternatifs vous trouverez les glorieux seconds au vote que vous pouvez utiliser en lieu et place du marker choisi s'il vous plaît plus. Il vous suffit alors de glisser-déposer le fichier dans le répertoire principal et de confirmer l'écrasement de l'autre marker. Vous pouvez aussi choisir vos propres markers dans cette géniale bibliothéque d'icônes. Vous pouvez aussi déssiner vos propre marker. Les limites sont que la taille de l'image doit être exactement de 512x512 px. Un fichier PNG est préférable pour gérer la transparence. Enfin votre fichier doit porter exactement le même nom qu'indiqué dans cette documentation.

        Dans Roll20 rendez-vous dans le menu "Outils" puis "Token Marker Library". Appuyez sur "Create Set". Puis renseignez le nom du marker set. "cof markers" par exemple. Appuyez sur "Create Set".

        -

        Vous arrivez alors sur la fen\xEAtre suivante o\xF9 il suffit de d\xE9poser les fichiers pour qu'ils soient upload\xE9s sur Roll20

        +

        Vous arrivez alors sur la fenêtre suivante où il suffit de déposer les fichiers pour qu'ils soient uploadés sur Roll20

        -

        A ce moment il y a deux \xE9coles de vie : ceux qui l\xE2chent tous leurs markers en m\xEAme temps et qui laisse le soin aux serveurs de Roll20 de d\xE9cider dans quel ordre ils verront appara\xEEtre les markers dans leur interface pour le restant de leur jour. Et ceux qui posent les fichiers un par un pour que l'ordre qu'ils souhaitent soit respect\xE9 par Roll20. Quand tout est pr\xEAt cliquez sur "Upload". Vous avez un message "Fichiers en cours de traitement" pendant 1 \xE0 2 minutes. Ensuite Roll20 vous propose de renommer vos tokens. Ne changez rien et fa\xEEtes "Save". Ca y est, vos markers personnalis\xE9s sont enfin pr\xEAts !

        +

        A ce moment il y a deux écoles de vie : ceux qui lâchent tous leurs markers en même temps et qui laisse le soin aux serveurs de Roll20 de décider dans quel ordre ils verront apparaître les markers dans leur interface pour le restant de leur jour. Et ceux qui posent les fichiers un par un pour que l'ordre qu'ils souhaitent soit respecté par Roll20. Quand tout est prêt cliquez sur "Upload". Vous avez un message "Fichiers en cours de traitement" pendant 1 à 2 minutes. Ensuite Roll20 vous propose de renommer vos tokens. Ne changez rien et faîtes "Save". Ca y est, vos markers personnalisés sont enfin prêts !

        -

        6.4 Activation et V\xE9rification

        +

        6.4 Activation et Vérification

        -

        Mais ce n'est pas fini il vous faut encore affecter vos markers \xE0 votre campagne. Cela se passe sur la page d'acceuil de votre campagne:

        +

        Mais ce n'est pas fini il vous faut encore affecter vos markers à votre campagne. Cela se passe sur la page d'acceuil de votre campagne:

        -

        Lancez votre campagne et v\xE9rifiez que les nouveaux markers apparaissent bien. Lancez ensuite la commande !cof-options pour cocher "Markers Personnalises". Enfin comme dernier contr\xF4le allez dans la console des API, fa\xEEtes "restart API sandbox" et v\xE9rifiez que le message "Markers personnalis\xE9s activ\xE9s" est bien pr\xE9sent. Si ce n'est pas le cas vous avez probablement oubli\xE9 des markers "obligatoires" et le script n'a pas pu activer les markers cof pour cette raison. La liste des markers manquants devrait appara\xEEtre dans la console.

        +

        Lancez votre campagne et vérifiez que les nouveaux markers apparaissent bien. Lancez ensuite la commande !cof-options pour cocher "Markers Personnalises". Enfin comme dernier contrôle allez dans la console des API, faîtes "restart API sandbox" et vérifiez que le message "Markers personnalisés activés" est bien présent. Si ce n'est pas le cas vous avez probablement oublié des markers "obligatoires" et le script n'a pas pu activer les markers cof pour cette raison. La liste des markers manquants devrait apparaître dans la console.

        7. Console API

        -

        7.1 G\xE9n\xE9ralit\xE9s sur la Console

        +

        7.1 Généralités sur la Console

        -

        Il est recommand\xE9 quand vous jouez de garder un onglet de votre navigateur ouvert sur la Console API de votre campagne (Param\xE8tres -> Scripts API). En cas d'absence de r\xE9ponse du jeu il vous permet de facilement prendre connaissance d'une \xE9ventuelle erreur et de prendre rapidement les actions correctives n\xE9cessaires.

        -

        Un message bloquant est \xE9crit dans un bloc rouge en dehors de la fen\xEAtre API Output Console et ressemble \xE0 l'image suivante :

        +

        Il est recommandé quand vous jouez de garder un onglet de votre navigateur ouvert sur la Console API de votre campagne (Paramètres -> Scripts API). En cas d'absence de réponse du jeu il vous permet de facilement prendre connaissance d'une éventuelle erreur et de prendre rapidement les actions correctives nécessaires.

        +

        Un message bloquant est écrit dans un bloc rouge en dehors de la fenêtre API Output Console et ressemble à l'image suivante :

        -

        Lorsqu'un message rouge comme celui-ci interrompt votre partie v\xE9rifiez s'il poss\xE8de une solution identifi\xE9e dans le paragraphe ci-dessous. "Restart API sandbox" permet de relancer le script mais les m\xEAmes causes provoqueront la m\xEAme erreur. Si le message d'erreur n'est pas encore r\xE9f\xE9renc\xE9 ou ne propose pas de solution, essayez de comprendre quelle est votre derni\xE8re action ou quel bouton provoque cette erreur et terminez votre s\xE9ance en \xE9vitant de l'utiliser. Retestez plus tard et si l'erreur se reproduit expliquez-nous votre probl\xE8me sur ce post dans le forum BBE. Essayez d'\xEAtre le plus exhaustif possible dans vos explications car malheureusement les messages de Roll20 ne sont pas pr\xE9cis du tout quant au contexte de l'erreur. Par exemple le num\xE9ro de la ligne de code incrimin\xE9e ne nous est pas connue et l'on a donc besoin de toutes les pr\xE9cisions possibles pour comprendre le probl\xE8me et \xEAtre en capacit\xE9 de le reproduire afin de le corriger.

        -

        Les messages qui sont \xE0 l'interieur de la fen\xEAtre API Output Console sont des messages d'information ou d'alerte comme sur l'image suivante :

        +

        Lorsqu'un message rouge comme celui-ci interrompt votre partie vérifiez s'il possède une solution identifiée dans le paragraphe ci-dessous. "Restart API sandbox" permet de relancer le script mais les mêmes causes provoqueront la même erreur. Si le message d'erreur n'est pas encore référencé ou ne propose pas de solution, essayez de comprendre quelle est votre dernière action ou quel bouton provoque cette erreur et terminez votre séance en évitant de l'utiliser. Retestez plus tard et si l'erreur se reproduit expliquez-nous votre problème sur ce post dans le forum BBE. Essayez d'être le plus exhaustif possible dans vos explications car malheureusement les messages de Roll20 ne sont pas précis du tout quant au contexte de l'erreur. Par exemple le numéro de la ligne de code incriminée ne nous est pas connue et l'on a donc besoin de toutes les précisions possibles pour comprendre le problème et être en capacité de le reproduire afin de le corriger.

        +

        Les messages qui sont à l'interieur de la fenêtre API Output Console sont des messages d'information ou d'alerte comme sur l'image suivante :

        -

        Malgr\xE9 la gravit\xE9 apparente de certains de ces messages (SyntaxError) ils n'emp\xEAchent jamais le bon fonctionnement du script. Seuls les messages bloquants apparaissants en rouge emp\xEAche le bon fonctionnement du script. Nous n'avons pas compl\xE9tement la main sur l'apparition de ces messages d'alerte et nous travaillons activement avec Roll20 pour les \xE9liminer. Des messages d'informations sont aussi pr\xE9sents comme par exemple le num\xE9ro de version du script que vous utilisez actuellement.

        +

        Malgré la gravité apparente de certains de ces messages (SyntaxError) ils n'empêchent jamais le bon fonctionnement du script. Seuls les messages bloquants apparaissants en rouge empêche le bon fonctionnement du script. Nous n'avons pas complétement la main sur l'apparition de ces messages d'alerte et nous travaillons activement avec Roll20 pour les éliminer. Des messages d'informations sont aussi présents comme par exemple le numéro de version du script que vous utilisez actuellement.

        7.2 Principaux messages bloquants

          -
        • There was an error communicating with the QuantumRoll server Erreur Roll20 courante. "Restart API Sandbox" r\xE8gle normalement ce probl\xE8me.
        • -
        • docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host? Erreur Roll20. "Restart API Sandbox" r\xE8gle normalement ce probl\xE8me.
        • -
        • SyntaxError: Invalid or unexpected token ... Erreur dans le code. Pas de solution \xE9vidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • -
        • SyntaxError: Unexpected token ... Erreur dans le code. Pas de solution \xE9vidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • -
        • TypeError: Cannot read property '...' of undefined Erreur dans le code. Pas de solution \xE9vidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • +
        • There was an error communicating with the QuantumRoll server Erreur Roll20 courante. "Restart API Sandbox" règle normalement ce problème.
        • +
        • docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host? Erreur Roll20. "Restart API Sandbox" règle normalement ce problème.
        • +
        • SyntaxError: Invalid or unexpected token ... Erreur dans le code. Pas de solution évidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • +
        • SyntaxError: Unexpected token ... Erreur dans le code. Pas de solution évidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • +
        • TypeError: Cannot read property '...' of undefined Erreur dans le code. Pas de solution évidente. Le signaler uniquement si c'est un message bloquant (rouge).

        7.3 Principaux messages d'information et d'alerte

          -
        • COFantasy X.XX loaded Information : Le script a correctement d\xE9marr\xE9. Vous indique le num\xE9ro de version utilis\xE9.
        • -
        • Markers personnalis\xE9s activ\xE9s Information : Succ\xE8s de l'activation des Markers Personnalis\xE9s.
        • +
        • COFantasy X.XX loaded Information : Le script a correctement démarré. Vous indique le numéro de version utilisé.
        • +
        • Markers personnalisés activés Information : Succès de l'activation des Markers Personnalisés.
        • API sandbox shutdown due to campaign inactivity Information : "Restart API Sandbox" ou l'utilisation de la campagne remet en route la sandbox.
        • -
        • XXX dans l'\xE9quipe XXX est inconnu Alerte : Erreur dans le handout servant de s\xE9lection d'\xE9quipe. V\xE9rifiez l'orthographe de vos personnages.
        • -
        • Markers personnalis\xE9s manquants -> Retour aux markers standards Roll20. Voir erreur(s) ci-dessus. Alerte : Impossibilit\xE9 d'activer les Markers Personnalis\xE9s pour cause d'un marker obligatoire absent.
        • -
        • Marker cof-XXX introuvable Alerte : Erreur dans le nom d'un marker. Voir Markers Personnalis\xE9s ou liste des \xE9tats.
        • -
        • Comp\xE9tences sans caract\xE9ristique associ\xE9eAlerte : Erreur de d\xE9claration dans le handout de jets de caract\xE9ristique.
        • +
        • XXX dans l'équipe XXX est inconnu Alerte : Erreur dans le handout servant de sélection d'équipe. Vérifiez l'orthographe de vos personnages.
        • +
        • Markers personnalisés manquants -> Retour aux markers standards Roll20. Voir erreur(s) ci-dessus. Alerte : Impossibilité d'activer les Markers Personnalisés pour cause d'un marker obligatoire absent.
        • +
        • Marker cof-XXX introuvable Alerte : Erreur dans le nom d'un marker. Voir Markers Personnalisés ou liste des états.
        • +
        • Compétences sans caractéristique associéeAlerte : Erreur de déclaration dans le handout de jets de caractéristique.
        -

        7.4 Purger les variables d'\xE9tat du jeu

        +

        7.4 Purger les variables d'état du jeu

        -

        Pour son bon fonctionnement, le script stoque des donn\xE9es, parfois complexes, et il peut arriver que ces donn\xE9es soient corrompues. Dans ce cas, le script peut planter de mani\xE8re syst\xE9matique, m\xEAme sur des actions simples. Si vous soup\xE7onnez une corruption des donn\xE9es, vous pouvez tenter de lancer la commande !cof-clean-global-state. +

        Pour son bon fonctionnement, le script stoque des données, parfois complexes, et il peut arriver que ces données soient corrompues. Dans ce cas, le script peut planter de manière systématique, même sur des actions simples. Si vous soupçonnez une corruption des données, vous pouvez tenter de lancer la commande !cof-clean-global-state.

        8. Utiliser des personnages Pathfinder

        -

        Il existe un support basique des fiches Roll20 venant du syst\xE8me Pathfinder 1. La fonction !cof-pathfinder1 se lance en s\xE9lectionnant un ou plusieurs tokens li\xE9s \xE0 des fiches Pathfinder (par exemple obtenues en achetant des aventures Pathfinder sur le marketplace de Roll20). L'effet est d'une part de transformer une partie des attributs de la fiche en attributs compris par la fiche COF et le script COFantasy, de changer un peu le token associ\xE9 \xE0 la fiche, mais surtout d'effacer les attributs inutiles pour COF. En effet, le script est relativement sensible au nombre total d'attributs en jeu, et les fiches Pathfinder ont tendence \xE0 en avoir vraiment beaucoup. Tout ce qui n'est pas compris par le script se retrouve dans un attribut Attributs Pathfinder. Mais le mieux est de compl\xE9ter la fiche COF en se basant sur la fiche Pathfinder ouverte dans une autre partie.

        +

        Il existe un support basique des fiches Roll20 venant du système Pathfinder 1. La fonction !cof-pathfinder1 se lance en sélectionnant un ou plusieurs tokens liés à des fiches Pathfinder (par exemple obtenues en achetant des aventures Pathfinder sur le marketplace de Roll20). L'effet est d'une part de transformer une partie des attributs de la fiche en attributs compris par la fiche COF et le script COFantasy, de changer un peu le token associé à la fiche, mais surtout d'effacer les attributs inutiles pour COF. En effet, le script est relativement sensible au nombre total d'attributs en jeu, et les fiches Pathfinder ont tendence à en avoir vraiment beaucoup. Tout ce qui n'est pas compris par le script se retrouve dans un attribut Attributs Pathfinder. Mais le mieux est de compléter la fiche COF en se basant sur la fiche Pathfinder ouverte dans une autre partie.

        9. Statistiques

        Il est possible d'activer la collecte de statistiques en utilisant la commande !cof-demarrer-statistiques.

        -

        On peut arr\xEAter la collecte avec !cof-arreter-statistiques, et la mettre en pause avec !cof-pause-statistiques.
        - Si on red\xE9marre apr\xE8s une mise en pause, on reprend les statistiques comme elles \xE9taient au moment de la pause. Si on red\xE9marre des statistiques en court, cela remet les statistiques \xE0 z\xE9ro. +

        On peut arrêter la collecte avec !cof-arreter-statistiques, et la mettre en pause avec !cof-pause-statistiques.
        + Si on redémarre après une mise en pause, on reprend les statistiques comme elles étaient au moment de la pause. Si on redémarre des statistiques en court, cela remet les statistiques à zéro.

    -

    Ce site utilise des marques d\xE9pos\xE9es et des droits d\x2019auteurs qui sont la propri\xE9t\xE9 de Black Book Editions comme l\x2019y autorisent les conditions d\x2019utilisation de Black Book Editions. Ce site n\x2019est pas publi\xE9 par Black Book Editions et n\x2019a pas re\xE7u son aval ni une quelconque approbation de sa part. Pour de plus amples informations sur Black Book Editions, consultez www.black-book-editions.fr.

    +

    Ce site utilise des marques déposées et des droits d’auteurs qui sont la propriété de Black Book Editions comme l’y autorisent les conditions d’utilisation de Black Book Editions. Ce site n’est pas publié par Black Book Editions et n’a pas reçu son aval ni une quelconque approbation de sa part. Pour de plus amples informations sur Black Book Editions, consultez www.black-book-editions.fr.

    diff --git a/COFantasy/COFantasy.js b/COFantasy/COFantasy.js index 686a34728..7d63d0529 100644 --- a/COFantasy/COFantasy.js +++ b/COFantasy/COFantasy.js @@ -37,49 +37,49 @@ const generateUUID = (function() { }; //--------------- end generateRowID ---------------------------------------- -const COF_BETA = true; +const COF_BETA = false; let COF_loaded = false; -// Le script utilise la partie COFantasy de la variable d'état state -// Pour plus de facilité, on utilise stateCOF = state.COFantasy -// Champs utilisés: +// Le script utilise la partie COFantasy de la variable d'\xE9tat state +// Pour plus de facilit\xE9, on utilise stateCOF = state.COFantasy +// Champs utilis\xE9s: // - options : les options de jeu -// - setting_arran : toutes les fiches utilisent les règles Terres d'Arran +// - setting_arran : toutes les fiches utilisent les r\xE8gles Terres d'Arran // - setting_mixte : on a un mixte de fiches classiques et Terres d'Arran -// - roundMarkerId : l'id du token utilisé pour l'aura d'initiative -// - combat : défini si le jeu est en mode tour par tour, contient : +// - roundMarkerId : l'id du token utilis\xE9 pour l'aura d'initiative +// - combat : d\xE9fini si le jeu est en mode tour par tour, contient : // - pageId : la pageid du combat // - activeTokenId : id du token dont c'est le tour -// - activeTokenName : nom du token dont c'est le tour, au cas où l'id change -// - tour : numéro de tour dans le combat +// - activeTokenName : nom du token dont c'est le tour, au cas o\xF9 l'id change +// - tour : num\xE9ro de tour dans le combat // - init : niveau d'initiative courant // - armeesDesMorts : map de token id vers perso // - auras : liste des auras actives // - aurasCounts : computeur pour id des auras // - usureOff : on ne compte plus l'usure du combat -// - personnageCibleCree : pour savoir si on a créé un personnage cible (avec 0 PV pour centrer les aoe) -// - tablesCrees : pour savoir si on a créé les tables par défaut -// - gameMacros : la liste des macros créées par le script +// - personnageCibleCree : pour savoir si on a cr\xE9\xE9 un personnage cible (avec 0 PV pour centrer les aoe) +// - tablesCrees : pour savoir si on a cr\xE9\xE9 les tables par d\xE9faut +// - gameMacros : la liste des macros cr\xE9\xE9es par le script // - chargeFantastique : tout ce dont on a besoin pour une charge fantastique en cours (TODO: passer sous combat) // - eventId : compteur d'events pour avoir une id unique -// - tokensTemps : liste de tokens à durée de vie limitée, effacés à la fin du combat -// - effetAuD20 : les effets qui se produisent à chaque jet de dé. -// chaque effet est déterminé par un champ, puis pour chaque champ, -// - min: valeur minimale du dé pour déclencher -// - max: valeur maximale du dé pour déclencher -// - fct: nom de la fonction à appeler -// - nomFin: nom à afficher pour le statut et mettre fin aux événements +// - tokensTemps : liste de tokens \xE0 dur\xE9e de vie limit\xE9e, effac\xE9s \xE0 la fin du combat +// - effetAuD20 : les effets qui se produisent \xE0 chaque jet de d\xE9. +// chaque effet est d\xE9termin\xE9 par un champ, puis pour chaque champ, +// - min: valeur minimale du d\xE9 pour d\xE9clencher +// - max: valeur maximale du d\xE9 pour d\xE9clencher +// - fct: nom de la fonction \xE0 appeler +// - nomFin: nom \xE0 afficher pour le statut et mettre fin aux \xE9v\xE9nements // par exemple, foudreDuTemps pour les foudres du temps -// - tenebresMagiques : état général de ténèbres magiques -// - jetsEnCours : pour laisser le MJ montrer ou non un jet qui lui a été montré à lui seul +// - tenebresMagiques : \xE9tat g\xE9n\xE9ral de t\xE9n\xE8bres magiques +// - jetsEnCours : pour laisser le MJ montrer ou non un jet qui lui a \xE9t\xE9 montr\xE9 \xE0 lui seul // - currentAttackDisplay : pour pouvoir remontrer des display aux joueurs // - pause : le jeu est en pause -// - prescience : un personnage sur la carte de combat a la capacité prescience (TODO: passer sous combat) +// - prescience : un personnage sur la carte de combat a la capacit\xE9 prescience (TODO: passer sous combat) // - nextPrescience : pour le changement de tour car prescience ne revient que d'un tour -// - afterDisplay : données à afficher après un display -// - version : la version du script en cours, pour détecter qu'on change de version -// statistiques : des statistiques pour les jets de dés +// - afterDisplay : donn\xE9es \xE0 afficher apr\xE8s un display +// - version : la version du script en cours, pour d\xE9tecter qu'on change de version +// statistiques : des statistiques pour les jets de d\xE9s // statistiquesEnPause var COFantasy = COFantasy || function() { @@ -97,6 +97,7 @@ var COFantasy = COFantasy || function() { const BS_LABEL_DANGER = 'background-color: #d9534f;'; const DEFAULT_DYNAMIC_INIT_IMG = 'https://s3.amazonaws.com/files.d20.io/images/4095816/086YSl3v0Kz3SlDAu245Vg/thumb.png?1400535580'; const IMG_INVISIBLE = 'https://s3.amazonaws.com/files.d20.io/images/24377109/6L7tn91HZLAQfrLKQI7-Ew/thumb.png?1476950708'; + const IMG_BOMB = 'https://s3.amazonaws.com/files.d20.io/images/361033841/dmwnChkZNCI9a0_uKfGcNg/thumb.png?1695976505'; let markerCatalog = {}; let eventHistory = []; @@ -120,7 +121,7 @@ var COFantasy = COFantasy || function() { const defaultOptions = { regles: { - explications: "Options qui influent sur les règles du jeu", + explications: "Options qui influent sur les r\xE8gles du jeu", type: 'options', val: { divers: { @@ -128,105 +129,105 @@ var COFantasy = COFantasy || function() { type: 'options', val: { forme_d_arbre_amelioree: { - explications: "+50% à l'effet de la peau d'écorce en forme d'arbre.", + explications: "+50% \xE0 l'effet de la peau d'\xE9corce en forme d'arbre.", val: true, type: 'bool' }, poudre_explosif: { - explications: "Les armes à poudre font des dégâts explosifs", + explications: "Les armes \xE0 poudre font des d\xE9g\xE2ts explosifs", val: true, type: 'bool' }, interchangeable_attaque: { - explications: "La capacité interchangeable donne moins de DEF mais plus d'attaque", + explications: "La capacit\xE9 interchangeable donne moins de DEF mais plus d'attaque", val: true, type: 'bool' }, coups_critiques_etendus: { - explications: "Coup critique à une attaque dès qu'elle dépasse DEF + 10", + explications: "Coup critique \xE0 une attaque d\xE8s qu'elle d\xE9passe DEF + 10", val: false, type: 'bool' }, echec_critique_boule_de_feu: { - explications: "Nombre de mètre dont le centre d'une boule de feu peut être déplacé de manière aléatoire en cas d'échec critique. La probabilité est inversement proportionelle à la distance.", + explications: "Nombre de m\xE8tre dont le centre d'une boule de feu peut \xEAtre d\xE9plac\xE9 de mani\xE8re al\xE9atoire en cas d'\xE9chec critique. La probabilit\xE9 est inversement proportionelle \xE0 la distance.", val: 12, type: 'int' } } }, dommages: { - explications: "Règles optionnelles sur les dommages", + explications: "R\xE8gles optionnelles sur les dommages", type: 'options', val: { blessures_graves: { - explications: "Si on arrive à 0 PV, on perd 1PR, et si on a plus de PR, on a une blessure grave.", + explications: "Si on arrive \xE0 0 PV, on perd 1PR, et si on a plus de PR, on a une blessure grave.", val: true, type: 'bool' }, degats_importants: { - explications: "Si les DMs dépassent CON+niveau en une attaque, on applique aussi la règle de blessure grave. Si la valeur de cette option est 0, la règles n'est pas appliquée. Sinon, la règle n'est appliquée que si, de plus, les DMs dépassent maxPV / valeur.", + explications: "Si les DMs d\xE9passent CON+niveau en une attaque, on applique aussi la r\xE8gle de blessure grave. Si la valeur de cette option est 0, la r\xE8gles n'est pas appliqu\xE9e. Sinon, la r\xE8gle n'est appliqu\xE9e que si, de plus, les DMs d\xE9passent maxPV / valeur.", val: 3, type: 'int' }, dm_minimum: { - explications: "Dégâts minimum d'une attaque ou autre source de DM.", + explications: "D\xE9g\xE2ts minimum d'une attaque ou autre source de DM.", val: 0, type: 'int' }, crit_elementaire: { - explications: "Les DMs constants d'un autre type que celui de l'arme sont aussi multipliés en cas de critique", + explications: "Les DMs constants d'un autre type que celui de l'arme sont aussi multipli\xE9s en cas de critique", val: false, type: 'bool' }, max_rune_protection: { - explications: "Les DMs qu'une rune de protection est capable d'absorber sont limités à 10x le rang du forgesort dans la voie des runes", + explications: "Les DMs qu'une rune de protection est capable d'absorber sont limit\xE9s \xE0 10x le rang du forgesort dans la voie des runes", val: true, type: 'bool' }, dm_explosifs: { - explications: "Tous les dés de DM sont explosifs", + explications: "Tous les d\xE9s de DM sont explosifs", val: false, type: 'bool' } } }, haute_DEF: { - explications: "Options de jeu pour gérer la haute DEF", + explications: "Options de jeu pour g\xE9rer la haute DEF", type: 'options', val: { usure_DEF: { - explications: "Malus de -2 en DEF tous les n tours. Mettre à 0 pour ne pas avoir de malus d'usure", + explications: "Malus de -2 en DEF tous les n tours. Mettre \xE0 0 pour ne pas avoir de malus d'usure", val: 6, type: 'int' }, bonus_attaque_groupe: { - explications: "Lors d'une attaque de groupe, bonus à la touche par créature supplémentaire", + explications: "Lors d'une attaque de groupe, bonus \xE0 la touche par cr\xE9ature suppl\xE9mentaire", val: 2, type: 'int' }, crit_attaque_groupe: { - explications: "Lors d'une attaque de groupe, si le jet de touche dépasse DEF + cette valeur, les dommages sont doublés (0 = jamais)", + explications: "Lors d'une attaque de groupe, si le jet de touche d\xE9passe DEF + cette valeur, les dommages sont doubl\xE9s (0 = jamais)", val: 5, type: 'int' } } }, initiative: { - explications: "Options qui influent sur les règles du jeu", + explications: "Options qui influent sur les r\xE8gles du jeu", type: 'options', val: { initiative_variable: { - explications: "Ajoute 1d6 à l'initiative, lancé une fois par combat par type de créature", + explications: "Ajoute 1d6 \xE0 l'initiative, lanc\xE9 une fois par combat par type de cr\xE9ature", val: false, type: 'bool' }, initiative_variable_individuelle: { - explications: "Lancer l'initiative variable pour chaque créature (nécessite d'activer l'Initiative variable)", + explications: "Lancer l'initiative variable pour chaque cr\xE9ature (n\xE9cessite d'activer l'Initiative variable)", val: false, type: 'bool' }, joueurs_lancent_init: { - explications: "Fait apparaître un bouton pour que les joueurs lancent leur initiative (nécessite d'activer l'Initiative variable)", + explications: "Fait appara\xEEtre un bouton pour que les joueurs lancent leur initiative (n\xE9cessite d'activer l'Initiative variable)", val: false, type: 'bool' } @@ -237,12 +238,12 @@ var COFantasy = COFantasy || function() { type: 'options', val: { mana_totale: { - explications: "Tous les sorts ont un coût, celui des tempêtes de mana est multiplié par 3", + explications: "Tous les sorts ont un co\xFBt, celui des temp\xEAtes de mana est multipli\xE9 par 3", val: false, type: 'bool' }, contrecoup: { - explications: "Avec la Mana Totale, permet au lanceur de sort de payer un déficit de PM en PV (COF p. 181)", + explications: "Avec la Mana Totale, permet au lanceur de sort de payer un d\xE9ficit de PM en PV (COF p. 181)", val: false, type: 'bool' }, @@ -252,7 +253,7 @@ var COFantasy = COFantasy || function() { type: 'bool' }, elixirs_sorts: { - explications: "Toutes fabrications d'élixir sont considérées comme des sorts (qui peuvent coûter de la mana)", + explications: "Toutes fabrications d'\xE9lixir sont consid\xE9r\xE9es comme des sorts (qui peuvent co\xFBter de la mana)", val: true, type: 'bool' }, @@ -265,17 +266,17 @@ var COFantasy = COFantasy || function() { type: 'options', val: { MJ_voit_actions: { - explications: "À chaque nouveau personnage en combat, montre le choix d'actions au MJ, même pour les PJs.", + explications: "\xC0 chaque nouveau personnage en combat, montre le choix d'actions au MJ, m\xEAme pour les PJs.", val: false, type: 'bool' }, MJ_valide_affichage_attaques: { - explications: "Les résultats des attaques sont d'abord montrées au MJ seul, qui peut ensuite les montrer aux joueurs", + explications: "Les r\xE9sultats des attaques sont d'abord montr\xE9es au MJ seul, qui peut ensuite les montrer aux joueurs", val: false, type: 'bool' }, MJ_valide_affichage_jets: { - explications: "Les résultats des jets de caractéristiques sont d'abord montrées au MJ seul, qui peut ensuite les montrer aux joueurs", + explications: "Les r\xE9sultats des jets de caract\xE9ristiques sont d'abord montr\xE9es au MJ seul, qui peut ensuite les montrer aux joueurs", val: false, type: 'bool' }, @@ -300,96 +301,96 @@ var COFantasy = COFantasy || function() { type: 'bool' }, duree_effets: { - explications: "Le script indique la durée des effets associés aux tokens", + explications: "Le script indique la dur\xE9e des effets associ\xE9s aux tokens", val: false, type: 'bool' }, init_dynamique: { - explications: "Fait apparaître une aura dynamique sur le token qui a l'initiative", + explications: "Fait appara\xEEtre une aura dynamique sur le token qui a l'initiative", val: true, type: 'bool' }, markers_personnalises: { - explications: "Utilisation des markers personnalisés commençant par cof", + explications: "Utilisation des markers personnalis\xE9s commen\xE7ant par cof", val: true, type: 'bool' }, table_crit: { - explications: "Utilisation d'une table de critiques nommée Echec-Critique-Contact", + explications: "Utilisation d'une table de critiques nomm\xE9e Echec-Critique-Contact", val: false, type: 'bool' }, depense_mana: { - explications: "Le script précise la quantité de mana utilisée dans le chat à chaque fois", + explications: "Le script pr\xE9cise la quantit\xE9 de mana utilis\xE9e dans le chat \xE0 chaque fois", val: false, type: 'bool' } } }, images: { - explications: "Images par défaut", + explications: "Images par d\xE9faut", type: 'options', val: { image_init: { - explications: "Image utilisée pour indiquer le personnage dont c'est le tour", + explications: "Image utilis\xE9e pour indiquer le personnage dont c'est le tour", type: 'image', val: DEFAULT_DYNAMIC_INIT_IMG }, image_double: { - explications: 'Image utilisée pour la capacité dédoublement', + explications: 'Image utilis\xE9e pour la capacit\xE9 d\xE9doublement', type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/33854984/q10B3KtWsCxcMczLo4BSUw/thumb.png?1496303265" }, image_ombre: { - explications: "Image utilisée pour l'ombre mortelle", + explications: "Image utilis\xE9e pour l'ombre mortelle", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/2781735/LcllgIHvqvu0HAbWdXZbJQ/thumb.png?13900368485" }, image_arbre: { - explications: "Image utilisée pour la forme d'arbre", + explications: "Image utilis\xE9e pour la forme d'arbre", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/52767134/KEGYUXeKnxZr5dbDwQEO4Q/thumb.png?15248300835" }, image_mur_de_force: { - explication: "Image utilisée pour un mur de force sphérique", + explication: "Image utilis\xE9e pour un mur de force sph\xE9rique", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/33213510/5r3NGSso1QBJMJewTEKv0A/thumb.png?1495195634" }, image_mur_de_vent: { - explication: "Image utilisée pour un mur de vent sphérique", + explication: "Image utilis\xE9e pour un mur de vent sph\xE9rique", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/308931095/X5zH4itb9QI9La8O7KfMBQ/thumb.png?1665585092" }, prison_vegetale: { - explication: "Image utilisée pour la prison végétale", + explication: "Image utilis\xE9e pour la prison v\xE9g\xE9tale", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/254738719/c97DFw6JlEePDVXBf-MPsA/thumb.png?1636471250" }, zone_de_vie: { - explication: "Image utilisée pour les zones de vie", + explication: "Image utilis\xE9e pour les zones de vie", type: 'image', val: "https://s3.amazonaws.com/files.d20.io/images/349749304/q3q75jWu9Izlci5YB688WA/thumb.png?1689005544" } } }, sons: { - explications: "Sons par défaut", + explications: "Sons par d\xE9faut", type: 'options', val: { attaque_echec_critique: { - explication: "Son utilisé pour les échecs critiques d'attaques", + explication: "Son utilis\xE9 pour les \xE9checs critiques d'attaques", type: 'son', val: '' }, attaque_reussite_critique: { - explication: "Son utilisé pour les réussites critiques d'attaques", + explication: "Son utilis\xE9 pour les r\xE9ussites critiques d'attaques", type: 'son', val: '' } } }, macros_a_jour: { - explications: "Met automatiquement les macros à jour", + explications: "Met automatiquement les macros \xE0 jour", type: 'bool', val: true } @@ -416,43 +417,43 @@ var COFantasy = COFantasy || function() { } } - //Liste de tables par défaut + //Liste de tables par d\xE9faut const gameTables = [{ name: "Echec-Critique-Contact", showplayers: false, items: [{ - name: "FOR - Bousculé : le personnage est renversé par son adversaire. Il subit un dé malus au test de FOR si l’adversaire " + - "est d’une catégorie de taille supérieure et bénéficie d’un dé bonus dans le cas inverse. " + - "Il subit une attaque gratuite de la part d’un adversaire pendant qu’il est étalé au sol (-5 en DEF).", + name: "FOR - Bouscul\xE9 : le personnage est renvers\xE9 par son adversaire. Il subit un d\xE9 malus au test de FOR si l\x2019adversaire " + + "est d\x2019une cat\xE9gorie de taille sup\xE9rieure et b\xE9n\xE9ficie d\x2019un d\xE9 bonus dans le cas inverse. " + + "Il subit une attaque gratuite de la part d\x2019un adversaire pendant qu\x2019il est \xE9tal\xE9 au sol (-5 en DEF).", weight: 1, }, { - name: "DEX - Maladresse : le personnage laisse tomber au sol l'objet avec lequel il attaque. S’il essaye de le ramasser, " + + name: "DEX - Maladresse : le personnage laisse tomber au sol l'objet avec lequel il attaque. S\x2019il essaye de le ramasser, " + "il subit une attaque gratuite.", weight: 1, }, { - name: "CON - Coup de mou: le personnage subit l’état affaibli pendant 3 rounds. Ou il peut annuler cet état en reprenant" + - "son souffle par une action limitée.", + name: "CON - Coup de mou: le personnage subit l\x2019\xE9tat affaibli pendant 3 rounds. Ou il peut annuler cet \xE9tat en reprenant" + + "son souffle par une action limit\xE9e.", weight: 1, }, { - name: "INT - Erreur tactique : le personnage subit une attaque (gratuite) d’un adversaire à son contact.", + name: "INT - Erreur tactique : le personnage subit une attaque (gratuite) d\x2019un adversaire \xE0 son contact.", weight: 1, }, { name: "SAG - Distrait : le personnage se laisse distraire et ne voit pas venir la prochaine attaque, " + - "l’adversaire bénéficiera d’un bonus de +10.", + "l\x2019adversaire b\xE9n\xE9ficiera d\x2019un bonus de +10.", weight: 1, }, { - name: "CHA - Ridicule : le personnage fait un faux mouvement à la fois douloureux et ridicule, il subit " + - "l’état étourdi pendant un round pour reprendre contenance.", + name: "CHA - Ridicule : le personnage fait un faux mouvement \xE0 la fois douloureux et ridicule, il subit " + + "l\x2019\xE9tat \xE9tourdi pendant un round pour reprendre contenance.", weight: 1, }, { - name: "Votre arme se brise. S’il s’agit d’une arme magique, le dé DM est simplement réduit d'une catégorie " + - "(2d6/d12=>d10=>d8=>d6=>d4=>d3) jusqu’à la fin du combat.", + name: "Votre arme se brise. S\x2019il s\x2019agit d\x2019une arme magique, le d\xE9 DM est simplement r\xE9duit d'une cat\xE9gorie " + + "(2d6/d12=>d10=>d8=>d6=>d4=>d3) jusqu\x2019\xE0 la fin du combat.", weight: 1, }, { - name: "Une pièce d’armure bouge et elle devient plus gênante que protectrice : malus en DEF et en attaque pour le reste du combat. Cuir : -1, Maille : -2, Plaque -3.", + name: "Une pi\xE8ce d\x2019armure bouge et elle devient plus g\xEAnante que protectrice : malus en DEF et en attaque pour le reste du combat. Cuir : -1, Maille : -2, Plaque -3.", weight: 1, }, { - name: "Simple échec de l'attaque", + name: "Simple \xE9chec de l'attaque", weight: 12, }, ], }, ]; @@ -536,7 +537,7 @@ var COFantasy = COFantasy || function() { return false; } - // Attention, def, la valeur par défaut, doit être la même que sur la fiche + // Attention, def, la valeur par d\xE9faut, doit \xEAtre la m\xEAme que sur la fiche // personnage peut ne pas avoir de token function ficheAttribute(personnage, name, def) { let attr = charAttribute(personnage.charId, name, { @@ -555,7 +556,7 @@ var COFantasy = COFantasy || function() { return attrAsInt(attr, def, defPresent); } - //Il faut une valeur par défaut, qui correspond à celle de la fiche + //Il faut une valeur par d\xE9faut, qui correspond \xE0 celle de la fiche function ficheAttributeAsBool(personnage, name, def) { let attr = charAttribute(personnage.charId, name, { caseInsensitive: true @@ -564,7 +565,7 @@ var COFantasy = COFantasy || function() { return attrAsBool(attr); } - //Attention à ne pas utiliser si l'attribut ne dépend pas du token + //Attention \xE0 ne pas utiliser si l'attribut ne d\xE9pend pas du token //defPresent est optionnel //personnage peut ne pas avoir de token function attributeAsInt(personnage, name, def, defPresent) { @@ -661,7 +662,7 @@ var COFantasy = COFantasy || function() { function charPredicateAsBool(charId, name) { let pred = stateCOF.predicats[charId]; - if (pred) return pred; + if (pred) return pred[name]; let raw = ''; let attr = charAttribute(charId, 'predicats_script', { caseInsensitive: true @@ -705,8 +706,8 @@ var COFantasy = COFantasy || function() { } - //Problème : ça ne peut pas marcher pour les boucliers en main gauche - //car ça utilise lui-même un bouclier... + //Probl\xE8me : \xE7a ne peut pas marcher pour les boucliers en main gauche + //car \xE7a utilise lui-m\xEAme un bouclier... function getPredicates(perso) { if (perso.predicates === undefined) { const estMook = perso.token && perso.token.get('bar1_link') === ''; @@ -720,12 +721,12 @@ var COFantasy = COFantasy || function() { raw += '\n' + perso.arme.predicats; if (perso.armeGauche && perso.armeGauche.predicats) raw += '\n' + perso.armeGauche.predicats; - } else if (perso.arme) { //possible si appelé depuis armesEnMain + } else if (perso.arme) { //possible si appel\xE9 depuis armesEnMain if (perso.arme.predicats) raw += '\n' + perso.arme.predicats; - } else { //il faut chercher les prédicats des armes en main - //On n'appelle pas armesEnMain pour éviter la récursion - //et pour éviter trop de calcul + } else { //il faut chercher les pr\xE9dicats des armes en main + //On n'appelle pas armesEnMain pour \xE9viter la r\xE9cursion + //et pour \xE9viter trop de calcul let attrArmes = tokenAttribute(perso, 'armeEnMain'); if (attrArmes.length > 0) { let att; @@ -813,7 +814,7 @@ var COFantasy = COFantasy || function() { caseInsensitive: true }); if (typePerso.length > 0 && typePerso[0].get('current') == 'PNJ') - return; //Les fiches de PNJ sont les mêmes + return; //Les fiches de PNJ sont les m\xEAmes let setting = charAttribute(c.id, 'option_setting', { caseInsensitive: true }); @@ -825,7 +826,7 @@ var COFantasy = COFantasy || function() { else charsGenerique.push(c); }); if (charsArran.length <= charsGenerique.length) { - log("Utilisation des règles COF génériques"); + log("Utilisation des r\xE8gles COF g\xE9n\xE9riques"); if (charsArran.length > 0) { error("Attention, des personnages suivent les options de jeu des Terres d'Arran (voir le log pour la liste)", charsArran); charsArran.forEach(function(c) { @@ -837,7 +838,7 @@ var COFantasy = COFantasy || function() { } return; } - log("Utilisation des règles des Terres d'Arran"); + log("Utilisation des r\xE8gles des Terres d'Arran"); if (charsGenerique.length > 0) { error("Attention, des personnages ne suivent pas les options de jeu des Terres d'Arran (voir le log pour la liste)", charsGenerique); charsGenerique.forEach(function(c) { @@ -871,7 +872,7 @@ var COFantasy = COFantasy || function() { effet_de_marker[m.tag] = effet; } else if (ms) { if (effet_de_marker[ms] && effet_de_marker[ms] != effet) { - sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le même icone"); + sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le m\xEAme icone"); } effet_de_marker[ms] = effet; } else { @@ -882,7 +883,7 @@ var COFantasy = COFantasy || function() { function splitIdName(idn) { let pos = idn.indexOf(' '); if (pos < 1 || pos >= idn.length) { - error("idName mal formé", idn); + error("idName mal form\xE9", idn); return; } let name = idn.substring(pos + 1); @@ -892,8 +893,8 @@ var COFantasy = COFantasy || function() { }; } - //Renvoie le token et le charId. Si l'id ne correspond à rien, cherche si - //on trouve un nom de token, sur la page passée en argument (ou sinon + //Renvoie le token et le charId. Si l'id ne correspond \xE0 rien, cherche si + //on trouve un nom de token, sur la page pass\xE9e en argument (ou sinon //sur la page active de la campagne) function persoOfId(id, name, pageId, allPages) { let token = getObj('graphic', id); @@ -928,14 +929,14 @@ var COFantasy = COFantasy || function() { } else return undefined; } if (tokens.length > 1) { - error("Ambigüité sur le choix d'un token : il y a " + - tokens.length + " tokens nommés " + name, tokens); + error("Ambig\xFCit\xE9 sur le choix d'un token : il y a " + + tokens.length + " tokens nomm\xE9s " + name, tokens); } token = tokens[0]; } let charId = token.get('represents'); if (charId === '') { - error("le token sélectionné ne représente pas de personnage", token); + error("le token s\xE9lectionn\xE9 ne repr\xE9sente pas de personnage", token); return undefined; } return { @@ -944,7 +945,7 @@ var COFantasy = COFantasy || function() { }; } - //Retourne le perso correspondant à un token id suivi du nom de token + //Retourne le perso correspondant \xE0 un token id suivi du nom de token //Permet d'avoir une information robuste en cas d'interruption du script //peuple tokName function persoOfIdName(idn, pageId, allPages) { @@ -952,7 +953,7 @@ var COFantasy = COFantasy || function() { if (sp === undefined) return; let perso = persoOfId(sp.id, sp.name, pageId, allPages); if (perso === undefined) { - log("Impossible de trouver le personnage correspondant à " + sp.name); + log("Impossible de trouver le personnage correspondant \xE0 " + sp.name); return; } perso.tokName = perso.token.get('name'); @@ -989,16 +990,17 @@ var COFantasy = COFantasy || function() { roundMarker.remove(); roundMarker = undefined; stateCOF.roundMarkerId = undefined; - } else if (stateCOF.roundMarkerId) { + } else { + stateCOF.roundMarkerId = undefined; let roundMarkers = findObjs({ _type: 'graphic', represents: '', name: 'Init marker', + layer: 'map', }); roundMarkers.forEach(function(rm) { rm.remove(); }); - stateCOF.roundMarkerId = undefined; } } @@ -1010,7 +1012,7 @@ var COFantasy = COFantasy || function() { } if (sync != threadSync) return; if (token) { - // Cas spéciaux du cavaliers + // Cas sp\xE9ciaux du cavaliers let pageId = token.get('pageid'); let personnage = persoOfId(token.id); let monteSur = tokenAttribute(personnage, 'monteSur'); @@ -1049,7 +1051,7 @@ var COFantasy = COFantasy || function() { return false; }); } catch (uriError) { - log("Erreur de décodage URI dans la note GM de " + token.get('name') + " : " + gmNotes); + log("Erreur de d\xE9codage URI dans la note GM de " + token.get('name') + " : " + gmNotes); } roundMarker = createObj('graphic', roundMarkerSpec); if (roundMarker === undefined && localImage) { @@ -1063,12 +1065,12 @@ var COFantasy = COFantasy || function() { roundMarker = createObj('graphic', roundMarkerSpec); } if (roundMarker === undefined) { - error("Impossible de créer le token pour l'aura dynamique", roundMarkerSpec); + error("Impossible de cr\xE9er le token pour l'aura dynamique", roundMarkerSpec); return false; } stateCOF.roundMarkerId = roundMarker.id; if (roundMarkerSpec.layer === 'map') toFront(roundMarker); - // Ne pas amener une monture montée en avant pour éviter de cacher le cavalier + // Ne pas amener une monture mont\xE9e en avant pour \xE9viter de cacher le cavalier if (cavalier && monture) { toFront(monture.token); toFront(cavalier.token); @@ -1096,7 +1098,7 @@ var COFantasy = COFantasy || function() { token.set('aura2_radius', ''); token.set('showplayers_aura2', false); } else { - // Cas des tokens personnalisés + // Cas des tokens personnalis\xE9s if (statusForInitEnemy && statusForInitAlly) { token.set(statusForInitAlly, false); token.set(statusForInitEnemy, false); @@ -1104,14 +1106,75 @@ var COFantasy = COFantasy || function() { } } - //Appelé au lancement du script, mise à jour de certaines variables globales + function trouveOuCreeCible() { + let persos = findObjs({ + _type: 'character', + name: 'Cible', + controlledby: 'all' + }); + if (persos.length > 0) return persos[0]; + let pages = findObjs({ + _type: 'page' + }); + if (pages.length > 0) { + let pageId = pages[0].id; + let charCible = createObj('character', { + name: 'Cible', + controlledby: 'all', + inplayerjournals: 'all', + avatar: 'https://s3.amazonaws.com/files.d20.io/images/33041174/5JdDVh-34C-kZglTE1aq-w/max.png?1494837870', + }); + if (charCible) { + let attrPV = charAttribute(charCible.id, 'PV', { + caseInsensitive: true + }); + if (attrPV.length > 0) attrPV = attrPV[0]; + else attrPV = createObj('attribute', { + name: 'PV', + characterid: charCible.id, + current: 0, + max: 0 + }); + let attrType = charAttribute(charCible.id, 'type_personnage', { + caseInsensitive: true + }); + if (attrType.length > 0) { + attrType[0].setWithWorker('current', 'PNJ'); + } else { + attrType = createObj('attribute', { + name: 'type_personnage', + characterid: charCible.id, + current: 'PJ', + }); + attrType.setWithWorker('current', 'PNJ'); + } + let tokenCible = createObj('graphic', { + name: 'Cible', + layer: 'objects', + _pageid: pageId, + imgsrc: 'https://s3.amazonaws.com/files.d20.io/images/33041174/5JdDVh-34C-kZglTE1aq-w/thumb.png?1494837870', + represents: charCible.id, + width: PIX_PER_UNIT, + height: PIX_PER_UNIT, + bar1_link: attrPV ? attrPV.id : '' + }); + if (tokenCible) { + setDefaultTokenForCharacter(charCible, tokenCible); + tokenCible.remove(); + } + return charCible; + } + } + } + + //Appel\xE9 au lancement du script, mise \xE0 jour de certaines variables globales function setStateCOF() { stateCOF = state.COFantasy; - stateCOF.predicats = {}; //prédicats par charId. + stateCOF.predicats = {}; //pr\xE9dicats par charId. if (stateCOF.roundMarkerId) { roundMarker = getObj('graphic', stateCOF.roundMarkerId); if (roundMarker === undefined) { - log("Le marqueur d'init a changé d'id"); + log("Le marqueur d'init a chang\xE9 d'id"); let roundMarkers = findObjs({ _type: 'graphic', represents: '', @@ -1141,68 +1204,10 @@ var COFantasy = COFantasy || function() { } } if (!stateCOF.personnageCibleCree) { - //On cherche si un personnage cible existe déjà - let persos = findObjs({ - _type: 'character', - name: 'Cible', - controlledby: 'all' - }); - if (persos.length === 0) { - let pages = findObjs({ - _type: 'page' - }); - if (pages.length > 0) { - let pageId = pages[0].id; - let charCible = createObj('character', { - name: 'Cible', - controlledby: 'all', - inplayerjournals: 'all', - avatar: 'https://s3.amazonaws.com/files.d20.io/images/33041174/5JdDVh-34C-kZglTE1aq-w/max.png?1494837870', - }); - if (charCible) { - let attrPV = charAttribute(charCible.id, 'PV', { - caseInsensitive: true - }); - if (attrPV.length > 0) attrPV = attrPV[0]; - else attrPV = createObj('attribute', { - name: 'PV', - characterid: charCible.id, - current: 0, - max: 0 - }); - let attrType = charAttribute(charCible.id, 'type_personnage', { - caseInsensitive: true - }); - if (attrType.length > 0) { - attrType[0].setWithWorker('current', 'PNJ'); - } else { - attrType = createObj('attribute', { - name: 'type_personnage', - characterid: charCible.id, - current: 'PJ', - }); - attrType.setWithWorker('current', 'PNJ'); - } - let tokenCible = createObj('graphic', { - name: 'Cible', - layer: 'objects', - _pageid: pageId, - imgsrc: 'https://s3.amazonaws.com/files.d20.io/images/33041174/5JdDVh-34C-kZglTE1aq-w/thumb.png?1494837870', - represents: charCible.id, - width: PIX_PER_UNIT, - height: PIX_PER_UNIT, - bar1_link: attrPV ? attrPV.id : '' - }); - if (tokenCible) { - setDefaultTokenForCharacter(charCible, tokenCible); - tokenCible.remove(); - } - } - } - } + trouveOuCreeCible(); stateCOF.personnageCibleCree = true; } - //Création des tables par défaut + //Cr\xE9ation des tables par d\xE9faut if (!stateCOF.tablesCrees) { let allTables = findObjs({ _type: 'rollabletable', @@ -1259,7 +1264,7 @@ var COFantasy = COFantasy || function() { m.set('visibleto', ngm.visibleto); if (ngm.istokenaction != gm.istokenaction && m.get('istokenaction') == gm.istokenaction) m.set('istokenaction', ngm.istokenaction); - sendChat('COF', '/w GM Macro ' + ngm.name + ' mise à jour.'); + sendChat('COF', '/w GM Macro ' + ngm.name + ' mise \xE0 jour.'); }); } else { ngm = gameMacros.find(function(ngm) { @@ -1278,14 +1283,14 @@ var COFantasy = COFantasy || function() { m.set('visibleto', ngm.visibleto); if (ngm.istokenaction != gm.istokenaction && m.get('istokenaction') == gm.istokenaction) m.set('istokenaction', ngm.istokenaction); - sendChat('COF', '/w GM Macro ' + ngm.name + ' mise à jour.'); + sendChat('COF', '/w GM Macro ' + ngm.name + ' mise \xE0 jour.'); }); } else { macros.forEach(function(m) { if (m.get('name') != gm.name) return; if (m.get('action') != gm.action) return; m.remove(); - sendChat('COF', '/w GM Macro ' + gm.name + ' effacée.'); + sendChat('COF', '/w GM Macro ' + gm.name + ' effac\xE9e.'); }); } } @@ -1301,7 +1306,7 @@ var COFantasy = COFantasy || function() { return macro.get('name') == ngm.name; }); if (prev === undefined) { - sendChat('COF', '/w GM Macro ' + ngm.name + ' créée.'); + sendChat('COF', '/w GM Macro ' + ngm.name + ' cr\xE9\xE9e.'); if (ngm.inBar) inBar.push(ngm.name); mjs.forEach(function(playerId, i) { if (i === 0 || ngm.visibleto === '') { @@ -1313,10 +1318,10 @@ var COFantasy = COFantasy || function() { } }); } else { - //Peut-être la première fois, vérifier les macros + //Peut-\xEAtre la premi\xE8re fois, v\xE9rifier les macros if (stateCOF.macros) { - //ancienne version, et on avait copié les macros - //on enlève juste Escalier, et on remplace par Monter et Descendre + //ancienne version, et on avait copi\xE9 les macros + //on enl\xE8ve juste Escalier, et on remplace par Monter et Descendre let mesc = macros.find(function(m) { return m.get('name') == 'Escalier'; }); @@ -1346,7 +1351,7 @@ var COFantasy = COFantasy || function() { return macro.get('name') == m.name; }); if (prev === undefined) { - sendChat('COF', '/w GM Macro ' + m.name + ' créée.'); + sendChat('COF', '/w GM Macro ' + m.name + ' cr\xE9\xE9e.'); if (m.inBar) inBar.push(m.name); mjs.forEach(function(playerId, i) { if (i === 0 || m.visibleto === '') { @@ -1359,16 +1364,16 @@ var COFantasy = COFantasy || function() { } } if (inBar.length > 0) { - sendChat('COF', "/w GM Macros à mettre dans la barre d'action du MJ : " + inBar.join(', ')); + sendChat('COF', "/w GM Macros \xE0 mettre dans la barre d'action du MJ : " + inBar.join(', ')); } stateCOF.gameMacros = gameMacros; } - // Récupération des token Markers attachés à la campagne image, nom, tag, Id + // R\xE9cup\xE9ration des token Markers attach\xE9s \xE0 la campagne image, nom, tag, Id const markers = JSON.parse(Campaign().get('token_markers')); markers.forEach(function(m) { markerCatalog[m.name] = m; }); - // Option Markers personnalisés activé + // Option Markers personnalis\xE9s activ\xE9 if (stateCOF.options.affichage.val.markers_personnalises.val) { const cof_states_perso = { assomme: 'status_cof-assomme', @@ -1386,10 +1391,10 @@ var COFantasy = COFantasy || function() { blesse: 'status_cof-blesse', encombre: 'status_cof-encombre', penombre: 'status_cof-penombre', - //enseveli: 'status_edge-crack' -> À dessiner + //enseveli: 'status_edge-crack' -> \xC0 dessiner chef: 'status_cof-chef', }; - // On boucle sur la liste des états pour vérifier que les markers sont bien présents ! + // On boucle sur la liste des \xE9tats pour v\xE9rifier que les markers sont bien pr\xE9sents ! let markersAbsents = []; let ancientSet = true; for (let etat in cof_states_perso) { @@ -1431,7 +1436,7 @@ var COFantasy = COFantasy || function() { default: if (ms) { if (effet_de_marker[ms] && effet_de_marker[ms] != effet) { - sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le même icone"); + sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le m\xEAme icone"); } effet_de_marker[ms] = effet; } @@ -1447,7 +1452,7 @@ var COFantasy = COFantasy || function() { default: if (ms) { if (effet_de_marker[ms] && effet_de_marker[ms] != effet) { - sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le même icone"); + sendChat('COF', effet_de_marker[ms] + " et " + effet + " ont le m\xEAme icone"); } effet_de_marker[ms] = effet; } @@ -1457,9 +1462,9 @@ var COFantasy = COFantasy || function() { markersAbsents.forEach(function(m) { log("Marker " + m + " introuvable"); }); - log("Markers personnalisés activés."); + log("Markers personnalis\xE9s activ\xE9s."); } else { - log("Utilisation des markers par défaut"); + log("Utilisation des markers par d\xE9faut"); } } //Construction de la table markers => etat @@ -1478,7 +1483,7 @@ var COFantasy = COFantasy || function() { return res; } - // retourne un tableau contenant la liste des ID de joueurs connectés controllant le personnage lié au Token + // retourne un tableau contenant la liste des ID de joueurs connect\xE9s controllant le personnage li\xE9 au Token function getPlayerIds(perso) { let character = getObj('character', perso.charId); if (character === undefined) return; @@ -1527,7 +1532,7 @@ var COFantasy = COFantasy || function() { return res; } - //PNJ au sens de la fiche utilisée, pas forcément en jeu + //PNJ au sens de la fiche utilis\xE9e, pas forc\xE9ment en jeu //perso peut ne pas avoir de token function persoEstPNJ(perso) { if (perso.pnj) return true; @@ -1588,7 +1593,7 @@ var COFantasy = COFantasy || function() { return true; } - //Met le champ field à value du token dans evt, pour permettre le undo + //Met le champ field \xE0 value du token dans evt, pour permettre le undo //Retourne evt.affectes[token.id] function affectToken(token, field, value, evt) { evt.affectes = evt.affectes || {}; @@ -1658,7 +1663,7 @@ var COFantasy = COFantasy || function() { sendChat(dest, msg); } - //Chuchote le message à tous les joueurs présents qui controllent le + //Chuchote le message \xE0 tous les joueurs pr\xE9sents qui controllent le //personnage, plus le MJ function whisperChar(charId, msg) { let character = getObj('character', charId); @@ -1785,7 +1790,7 @@ var COFantasy = COFantasy || function() { // resultatDesSeuls (rempli par la fonction si true) //Renvoie 1dk + bonus, avec le texte //champs val et roll - //de peut être un nombre > 0 ou bien le résultat de parseDice + //de peut \xEAtre un nombre > 0 ou bien le r\xE9sultat de parseDice function rollDePlus(de, options) { options = options || {}; options.nbDes = options.nbDes || 1; @@ -1846,7 +1851,7 @@ var COFantasy = COFantasy || function() { return res; } - //Si evt est défini, alors on considère qu'il faut y mettre la valeur actuelle + //Si evt est d\xE9fini, alors on consid\xE8re qu'il faut y mettre la valeur actuelle function updateCurrentBar(perso, barNumber, val, evt, maxVal) { let token = perso.token; let prevToken; @@ -1893,7 +1898,7 @@ var COFantasy = COFantasy || function() { if (maxVal) aset.max = maxVal; attr.setWithWorker(aset); if (HTdeclared) HealthColors.Update(token, prevToken); - //Gestion du lien des PVs entre familier et son maître + //Gestion du lien des PVs entre familier et son ma\xEEtre if (barNumber == 1) { let nomPersoLie = predicateAsBool(perso, 'PVPartagesAvec'); if (nomPersoLie) { @@ -2046,6 +2051,7 @@ var COFantasy = COFantasy || function() { light_losangle: token.get('light_losangle'), light_multiplier: token.get('light_multiplier'), adv_fow_view_distance: token.get('adv_fow_view_distance'), + gmnotes: token.get('gmnotes'), }; } @@ -2054,7 +2060,7 @@ var COFantasy = COFantasy || function() { case 'FOR': return 'force'; case 'DEX': - if (accent) return 'dextérité'; + if (accent) return 'dext\xE9rit\xE9'; return 'dexterite'; case 'CON': return 'constitution'; @@ -2073,9 +2079,9 @@ var COFantasy = COFantasy || function() { return 'pnj_' + m.toLowerCase(); } - //Retourne le mod de la caractéristque entière. + //Retourne le mod de la caract\xE9ristque enti\xE8re. //si carac n'est pas une carac, retourne 0 - //perso peut ne pas avoir de token ou être juste un charId + //perso peut ne pas avoir de token ou \xEAtre juste un charId function modCarac(perso, carac) { if (perso.charId === undefined) perso = { charId: perso @@ -2133,11 +2139,11 @@ var COFantasy = COFantasy || function() { } //options peut contenir - // msg: un message à afficher + // msg: un message \xE0 afficher // maxVal: la valeur max de l'attribut - // secret: le message n'est pas affiché pour tout le monde. - // charAttr: si présent, on utilise un attribut de personnage - // renvoie l'attribut créé ou mis à jour + // secret: le message n'est pas affich\xE9 pour tout le monde. + // charAttr: si pr\xE9sent, on utilise un attribut de personnage + // renvoie l'attribut cr\xE9\xE9 ou mis \xE0 jour function setTokenAttr(personnage, attribute, value, evt, options) { let charId = personnage.charId; let token = personnage.token; @@ -2157,7 +2163,7 @@ var COFantasy = COFantasy || function() { }; let name = 'inconnu'; if (token) name = token.get('name'); - error("Création d'un attribut undefined pour " + name, args); + error("Cr\xE9ation d'un attribut undefined pour " + name, args); return; } let attr = findObjs({ @@ -2185,7 +2191,7 @@ var COFantasy = COFantasy || function() { let taille = taillePersonnage(personnage, 4); if (taille == 5) { arme.deuxMains = false; - sendPerso(personnage, "peut maintenant tenir " + arme.name + " à une main"); + sendPerso(personnage, "peut maintenant tenir " + arme.name + " \xE0 une main"); degainerArme(personnage, arme.label, evt); } } @@ -2199,11 +2205,11 @@ var COFantasy = COFantasy || function() { token.set('height', height); break; case 'formeDArbre': - //On copie les PVs pour pouvoir les restaurer à la fin de l'effet + //On copie les PVs pour pouvoir les restaurer \xE0 la fin de l'effet setTokenAttr(personnage, 'anciensPV', token.get('bar1_value'), evt, { maxVal: token.get('bar1_max') }); - //On va créer une copie de token, mais avec une image d'arbre + //On va cr\xE9er une copie de token, mais avec une image d'arbre let tokenFields = getTokenFields(token, pageId, personnage.charId); let tokenArbre; let imageArbre = predicateAsBool(personnage, 'tokenFormeDArbre'); @@ -2218,7 +2224,7 @@ var COFantasy = COFantasy || function() { if (tokenArbre) { evt.tokens = evt.tokens || []; evt.tokens.push(tokenArbre); - //On met l'ancien token dans le gmlayer, car si l'image vient du marketplace, il est impossible de le recréer depuis l'API + //On met l'ancien token dans le gmlayer, car si l'image vient du marketplace, il est impossible de le recr\xE9er depuis l'API setToken(token, 'layer', 'gmlayer', evt); setTokenAttr(personnage, 'changementDeToken', true, evt); replaceInTurnTracker(token.id, tokenArbre.id, evt); @@ -2316,7 +2322,7 @@ var COFantasy = COFantasy || function() { return attr; } - // evt peut être undefined + // evt peut \xEAtre undefined // options peut avoir les champs msg et secret function removeTokenAttr(personnage, attribute, evt, options) { attribute = fullAttributeName(personnage, attribute, options); @@ -2353,8 +2359,8 @@ var COFantasy = COFantasy || function() { }); } - //cherche l'attribut attribute de valeur par défaut def - //et lui ajoute la valeur val. Crée l'attribut si besoin + //cherche l'attribut attribute de valeur par d\xE9faut def + //et lui ajoute la valeur val. Cr\xE9e l'attribut si besoin //retourne la nouvelle valeur de l'attribut function addToAttributeAsInt(perso, attribute, def, val, evt) { evt.attributes = evt.attributes || []; @@ -2400,11 +2406,11 @@ var COFantasy = COFantasy || function() { //options: //fromTemp si on est en train de supprimer un effet temporaire - //affectToken si on a déjà changé le statusmarkers (on vient donc d'un changement à la main d'un marker + //affectToken si on a d\xE9j\xE0 chang\xE9 le statusmarkers (on vient donc d'un changement \xE0 la main d'un marker function setState(personnage, etat, value, evt, options) { let token = personnage.token; if (value && predicateAsBool(personnage, 'immunite_' + etat)) { - sendPerso(personnage, 'ne peut pas être ' + stringOfEtat(etat, personnage)); + sendPerso(personnage, 'ne peut pas \xEAtre ' + stringOfEtat(etat, personnage)); return false; } options = options || {}; @@ -2458,7 +2464,7 @@ var COFantasy = COFantasy || function() { } } } - if (!value) { //On enlève le save si il y en a un + if (!value) { //On enl\xE8ve le save si il y en a un removeTokenAttr(personnage, etat + 'Save', evt); removeTokenAttr(personnage, etat + 'SaveParTour', evt); } @@ -2484,7 +2490,7 @@ var COFantasy = COFantasy || function() { token.set('light_losangle', 0); } //Normalement, ne peut plus suivre personne ? - //Si il peut parce qu'il touche ou tient une corde, réutiliser la macro + //Si il peut parce qu'il touche ou tient une corde, r\xE9utiliser la macro //pour suivre nePlusSuivre(personnage, pageId, evt); } else { @@ -2501,7 +2507,7 @@ var COFantasy = COFantasy || function() { let attrInvisible = tokenAttribute(personnage, 'tokenInvisible'); if (value) { if (attrInvisible.length === 0) { - //On va créer une copie de token, mais avec une image invisible et aura visible seulement de ceux qui contrôlent le token + //On va cr\xE9er une copie de token, mais avec une image invisible et aura visible seulement de ceux qui contr\xF4lent le token let tokenFields = getTokenFields(token, pageId, personnage.charId); tokenFields.layer = 'objects'; tokenFields.aura1_radius = 0; @@ -2522,7 +2528,7 @@ var COFantasy = COFantasy || function() { } evt.tokens = evt.tokens || []; evt.tokens.push(tokenInvisible); - //On met l'ancien token dans le gmlayer, car si l'image vient du marketplace, il est impossible de le recréer depuis l'API + //On met l'ancien token dans le gmlayer, car si l'image vient du marketplace, il est impossible de le recr\xE9er depuis l'API setToken(token, 'layer', 'gmlayer', evt); setTokenAttr(personnage, 'tokenInvisible', token.id, evt, { maxVal: tokenInvisible.id @@ -2536,7 +2542,7 @@ var COFantasy = COFantasy || function() { } } } - } else { //On enlève l'état invisible + } else { //On enl\xE8ve l'\xE9tat invisible if (attrInvisible.length > 0) { let tokenOriginel = getObj('graphic', attrInvisible[0].get('current')); if (!tokenOriginel) { @@ -2553,7 +2559,7 @@ var COFantasy = COFantasy || function() { }); if (tokenOriginel.length > 0) tokenOriginel = tokenOriginel[0]; else { - error("Impossible de retrouver le token de départ de " + token.get('name') + " quand on enlève l'état invisible", attrInvisible); + error("Impossible de retrouver le token de d\xE9part de " + token.get('name') + " quand on enl\xE8ve l'\xE9tat invisible", attrInvisible); tokenOriginel = false; } } @@ -2573,7 +2579,7 @@ var COFantasy = COFantasy || function() { }); if (tokenCourant.length > 0) tokenCourant = tokenCourant[0]; else { - error("Impossible de retrouver le token visible de " + token.get('name') + " quand on enlève l'état invisible", attrInvisible); + error("Impossible de retrouver le token visible de " + token.get('name') + " quand on enl\xE8ve l'\xE9tat invisible", attrInvisible); tokenCourant = false; } } @@ -2613,7 +2619,7 @@ var COFantasy = COFantasy || function() { switch (etat) { case 'mort': { - //On s'assure de mettre les PV de la cible à 0 (pour les insta kills sans dommages) + //On s'assure de mettre les PV de la cible \xE0 0 (pour les insta kills sans dommages) if (token.get('bar1_value') > 0) updateCurrentBar(personnage, 1, 0, evt); nePlusSuivre(personnage, pageId, evt); lockToken(personnage, evt); @@ -2632,14 +2638,14 @@ var COFantasy = COFantasy || function() { removeTokenAttr(personnage, 'estMontePar', evt); removeTokenAttr(personnage, 'positionSurMonture', evt); } - //On libère les personnages enveloppés, si il y en a. + //On lib\xE8re les personnages envelopp\xE9s, si il y en a. let attrEnveloppe = tokenAttribute(personnage, 'enveloppe'); attrEnveloppe.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); if (cible) { let envDM = a.get('max'); if (envDM.startsWith('etreinte')) { - //On a une étreinte, on enlève donc l'état immobilisé + //On a une \xE9treinte, on enl\xE8ve donc l'\xE9tat immobilis\xE9 setState(cible, 'immobilise', false, evt); } evt.deletedAttributes = evt.deletedAttributes || []; @@ -2650,7 +2656,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); } else if (cube.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + cube.tokName); + sendPerso(cible, 'se lib\xE8re de ' + cube.tokName); toFront(cible.token); evt.deletedAttributes.push(a); a.remove(); @@ -2661,14 +2667,14 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //Si le mort est enveloppé, il est relaché + //Si le mort est envelopp\xE9, il est relach\xE9 attrEnveloppe = tokenAttribute(personnage, 'enveloppePar'); attrEnveloppe.forEach(function(a) { let cube = persoOfIdName(a.get('current'), pageId); if (cube) { let envDiff = a.get('max'); if (envDiff.startsWith('etreinte')) { - //On a une étreinte, on enlève donc l'état immobilisé + //On a une \xE9treinte, on enl\xE8ve donc l'\xE9tat immobilis\xE9 setState(personnage, 'immobilise', false, evt); } evt.deletedAttributes = evt.deletedAttributes || []; @@ -2688,7 +2694,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages agrippés, si il y en a. + //On lib\xE8re les personnages agripp\xE9s, si il y en a. let attrAgrippe = tokenAttribute(personnage, 'agrippe'); attrAgrippe.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2698,7 +2704,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); if (a.get('max')) setState(cible, 'immobilise', false, evt); evt.deletedAttributes.push(a); @@ -2710,7 +2716,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages dévorés, si il y en a. + //On lib\xE8re les personnages d\xE9vor\xE9s, si il y en a. let attrDevore = tokenAttribute(personnage, 'devore'); attrDevore.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2720,7 +2726,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); setState(cible, 'immobilise', false, evt); evt.deletedAttributes.push(a); @@ -2731,7 +2737,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages écrasés, si il y en a. + //On lib\xE8re les personnages \xE9cras\xE9s, si il y en a. let attrEcrase = tokenAttribute(personnage, 'ecrase'); attrEcrase.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2741,7 +2747,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); evt.deletedAttributes.push(a); a.remove(); @@ -2751,7 +2757,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages avalés, si il y en a. + //On lib\xE8re les personnages aval\xE9s, si il y en a. let attrGobe = tokenAttribute(personnage, 'aGobe'); attrGobe.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2772,7 +2778,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages sous étreinte et immolation + //On lib\xE8re les personnages sous \xE9treinte et immolation let attrEtreinteImmole = tokenAttribute(personnage, 'etreinteImmole'); attrEtreinteImmole.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2782,7 +2788,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); setState(cible, 'immobilise', false, evt); evt.deletedAttributes.push(a); @@ -2793,7 +2799,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(a); a.remove(); }); - //On libère les personnages sous étreinte de scorpion + //On lib\xE8re les personnages sous \xE9treinte de scorpion let attrEtreinteScorpion = tokenAttribute(personnage, 'etreinteScorpionSur'); attrEtreinteScorpion.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); @@ -2804,7 +2810,7 @@ var COFantasy = COFantasy || function() { attrCible.forEach(function(a) { let agrippant = persoOfIdName(a.get('current', pageId)); if (agrippant.token.id == personnage.token.id) { - sendPerso(cible, 'se libère de ' + agrippant.tokName); + sendPerso(cible, 'se lib\xE8re de ' + agrippant.tokName); toFront(cible.token); evt.deletedAttributes.push(a); a.remove(); @@ -2852,7 +2858,7 @@ var COFantasy = COFantasy || function() { attaqueExplosion(msg); } } - //On termine les effets temporaires liés au personnage + //On termine les effets temporaires li\xE9s au personnage let etlAttr = tokenAttribute(personnage, 'effetsTemporairesLies'); if (etlAttr.length > 0) { etlAttr = etlAttr[0]; @@ -2875,7 +2881,7 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes.push(etlAttr); etlAttr.remove(); } - //On enlève les auras + //On enl\xE8ve les auras if (stateCOF.combat && (predicateAsBool(personnage, 'auraDrainDeForce') || attributeAsBool(personnage, 'aura')) ) { @@ -2895,7 +2901,7 @@ var COFantasy = COFantasy || function() { } else if (charAttributeAsBool(personnage, 'armeeConjuree')) { removeFromTurnTracker(personnage, evt); deleteTokenWithUndo(personnage.token, evt); - sendPerso(personnage, 'disparaît'); + sendPerso(personnage, 'dispara\xEEt'); let armeeChar = getObj('character', personnage.charId); if (armeeChar) { evt.deletedCharacters = evt.deletedCharacters || []; @@ -2915,7 +2921,7 @@ var COFantasy = COFantasy || function() { armeeChar.remove(); } } else if (!estNonVivant(personnage)) { - //Cherche si certains peuvent siphoner l'âme + //Cherche si certains peuvent siphoner l'\xE2me let allToks = findObjs({ _type: 'graphic', @@ -2923,7 +2929,7 @@ var COFantasy = COFantasy || function() { _subtype: 'token', layer: 'objects' }); - //On cherche d'abord si un siphon des âmes est prioritaire + //On cherche d'abord si un siphon des \xE2mes est prioritaire let prioriteSiphon = []; allToks = allToks.filter(function(tok) { if (tok.id == token.id) return false; @@ -2948,7 +2954,7 @@ var COFantasy = COFantasy || function() { let jetSiphon = "(1d6"; if (bonus > 0) jetSiphon += '+' + bonus; jetSiphon += ")"; - sendChat('COF', "/w GM " + personnage.token.get('name') + " est un personnage joueur, possible qu'il ne soit pas vraiment mort mais juste inconscient. S'il est vraiment mort, faire le siphon des âmes par " + siphoneur.token.get('name') + " à la main " + jetSiphon); + sendChat('COF', "/w GM " + personnage.token.get('name') + " est un personnage joueur, possible qu'il ne soit pas vraiment mort mais juste inconscient. S'il est vraiment mort, faire le siphon des \xE2mes par " + siphoneur.token.get('name') + " \xE0 la main " + jetSiphon); } else { prioriteSiphon.sort(function(a, b) { return b.priorite - a.priorite; @@ -2963,7 +2969,7 @@ var COFantasy = COFantasy || function() { } let p = x.perso; if (fractionPriorite < 1) { - whisperChar(p.charId, "ne réussit pas à siphoner l'âme de " + token.get('name') + " un autre pouvoir l'a siphonée avant lui"); + whisperChar(p.charId, "ne r\xE9ussit pas \xE0 siphoner l'\xE2me de " + token.get('name') + " un autre pouvoir l'a siphon\xE9e avant lui"); return true; } let bonus = predicateAsInt(p, 'siphonDesAmes', 0); @@ -2973,7 +2979,7 @@ var COFantasy = COFantasy || function() { nbDes }); let soinTotal = soin.val; - //Le montant total des soins ne peut excéder les pv max du personnage qui vient de mourrir. + //Le montant total des soins ne peut exc\xE9der les pv max du personnage qui vient de mourrir. let display = true; if (soinTotal > pvMax) { soinTotal = pvMax; @@ -2982,12 +2988,12 @@ var COFantasy = COFantasy || function() { if (soinTotal < 1) soinTotal = 1; soin.val = soinTotal; soin.val = Math.ceil(soin.val * fractionPriorite / 100); - //Cherche si il y a un perso lié + //Cherche si il y a un perso li\xE9 let lie = personnageAmeLiee(p, pageId, allToks); soigneToken(p, soin.val, evt, function(s) { - let siphMsg = "siphone l'âme de " + token.get('name') + - ". " + onGenre(p, 'Il', 'Elle') + " récupère "; + let siphMsg = "siphone l'\xE2me de " + token.get('name') + + ". " + onGenre(p, 'Il', 'Elle') + " r\xE9cup\xE8re "; if (s == soinTotal) { if (display) siphMsg += soin.roll + " pv."; else siphMsg += s + " pv (jet " + soin.roll + ")."; @@ -3002,8 +3008,8 @@ var COFantasy = COFantasy || function() { let soin2 = soinTotal - s + Math.floor(s / 5); soigneToken(lie, soin2, evt, function(s) { let siphMsg = - "récupère une partie de l'âme de " + token.get('name') + - " siphonée par " + nomPerso(p) + ". " + onGenre(lie, 'Il', 'Elle') + " récupère " + s + " pv."; + "r\xE9cup\xE8re une partie de l'\xE2me de " + token.get('name') + + " siphon\xE9e par " + nomPerso(p) + ". " + onGenre(lie, 'Il', 'Elle') + " r\xE9cup\xE8re " + s + " pv."; if (s == soin2) { fraction = 0; } else { @@ -3012,15 +3018,15 @@ var COFantasy = COFantasy || function() { pvMax -= s; whisperChar(lie.charId, siphMsg); }, function() { - whisperChar(lie.charId, "sent qu'" + onGenre(lie, 'il', 'elle') + " aurait pu bénéficier d'une âme"); + whisperChar(lie.charId, "sent qu'" + onGenre(lie, 'il', 'elle') + " aurait pu b\xE9n\xE9ficier d'une \xE2me"); }); } }, function() { if (lie) { soigneToken(lie, soin.val, evt, function(s) { - let siphMsg = "siphone l'âme de " + token.get('name') + - " grâce à " + nomPerso(p) + ". " + onGenre(lie, 'Il', 'Elle') + " récupère "; + let siphMsg = "siphone l'\xE2me de " + token.get('name') + + " gr\xE2ce \xE0 " + nomPerso(p) + ". " + onGenre(lie, 'Il', 'Elle') + " r\xE9cup\xE8re "; if (s == soinTotal) { siphMsg += soin.roll + " pv."; fraction = 0; @@ -3032,11 +3038,11 @@ var COFantasy = COFantasy || function() { whisperChar(lie.charId, siphMsg); }, function() { whisperChar(p.charId, - "est déjà au maximum de point de vie. " + onGenre(p, 'Il', 'Elle') + " laisse échapper l'âme de " + token.get('name')); + "est d\xE9j\xE0 au maximum de point de vie. " + onGenre(p, 'Il', 'Elle') + " laisse \xE9chapper l'\xE2me de " + token.get('name')); }); } else { whisperChar(p.charId, - "est déjà au maximum de point de vie. " + onGenre(p, 'Il', 'Elle') + " laisse échapper l'âme de " + token.get('name')); + "est d\xE9j\xE0 au maximum de point de vie. " + onGenre(p, 'Il', 'Elle') + " laisse \xE9chapper l'\xE2me de " + token.get('name')); } }); }); @@ -3076,7 +3082,7 @@ var COFantasy = COFantasy || function() { } //fonction avec callback, mais synchrone - // n'ajoute pas evt à l'historique + // n'ajoute pas evt \xE0 l'historique function soigneToken(perso, soins, evt, callTrue, callMax, options) { options = options || {}; let token = perso.token; @@ -3113,7 +3119,7 @@ var COFantasy = COFantasy || function() { let ds = parseInt(a.get('current')); if (ds > 0) { if (an[0].length < 2) { - error("Match non trouvé pour les soins", an); + error("Match non trouv\xE9 pour les soins", an); return; } if (soinsImpossible.has(an[1])) { @@ -3181,7 +3187,7 @@ var COFantasy = COFantasy || function() { } } } - // On cherche si il y a des DM temporaires à soigner + // On cherche si il y a des DM temporaires \xE0 soigner if (bar1 > pvmax) { let hasMana = (ficheAttributeAsInt(perso, 'PM', 0) > 0); let dmgTemp; @@ -3226,7 +3232,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(perso, 'reactionAllergique')) { removeTokenAttr(perso, 'reactionAllergique', evt, { - msg: ": les soins mettent fin à la réaction allergique" + msg: ": les soins mettent fin \xE0 la r\xE9action allergique" }); } } @@ -3263,7 +3269,7 @@ var COFantasy = COFantasy || function() { return scale; } - // si le token est plus grand que thresh, réduit la distance + // si le token est plus grand que thresh, r\xE9duit la distance function tokenSize(tok, thresh) { let size = (tok.get('width') + tok.get('height')) / 2; if (size > thresh) return ((size - thresh) / 2); @@ -3309,7 +3315,7 @@ var COFantasy = COFantasy || function() { } //Distance en pixels entre un token et un segment - //le segment est donné par ses extrémités, sous forme de {x, y} + //le segment est donn\xE9 par ses extr\xE9mit\xE9s, sous forme de {x, y} function distancePixTokenSegment(token, pt1, pt2) { let pt = pointOfToken(token); let seg = { @@ -3319,26 +3325,26 @@ var COFantasy = COFantasy || function() { let vec = { x: pt.x - pt1.x, y: pt.y - pt1.y - }; //vecteur de pt1 à pt - //On regarde d'abord si le projeté de token sur (pt1, pt2) est dans le segment + }; //vecteur de pt1 \xE0 pt + //On regarde d'abord si le projet\xE9 de token sur (pt1, pt2) est dans le segment let ps = seg.x * vec.x + seg.y * vec.y; if (ps <= 0) { //On est avant pt1 return Math.sqrt(vec.x * vec.x + vec.y * vec.y); } let dseg = seg.x * seg.x + seg.y * seg.y; - if (ps >= dseg) { //On est après pt2, on retourne donc la distance pt pt2 + if (ps >= dseg) { //On est apr\xE8s pt2, on retourne donc la distance pt pt2 let x = pt.x - pt2.x; let y = pt.y - pt2.y; return Math.sqrt(x * x + y * y); } - //On calcule le déterminant de vec et seg + //On calcule le d\xE9terminant de vec et seg let det = vec.x * seg.y - vec.y * seg.x; //Et on divise par la longueur du segment return Math.abs(det) / Math.sqrt(dseg); } //options peut avoir les champs: - // - strict1 = true si on considère que tok1 doit avoir une taille nulle + // - strict1 = true si on consid\xE8re que tok1 doit avoir une taille nulle // - strict2 // - allonge function distanceCombat(tok1, tok2, pageId, options) { @@ -3346,7 +3352,7 @@ var COFantasy = COFantasy || function() { pageId = tok1.get('pageid'); } options = options || {}; - //perso montés + //perso mont\xE9s let pseudoTok1 = tok1; if (!options.strict1) { let perso1 = persoOfToken(tok1); @@ -3379,7 +3385,7 @@ var COFantasy = COFantasy || function() { } //Attention, seulement faire pour les tokens avec une image dans la librairie - //C'est toujours le cas pour un token créé par le script + //C'est toujours le cas pour un token cr\xE9\xE9 par le script function deleteTokenWithUndo(token, evt) { let tokenFields = getTokenFields(token); evt.deletedTokens = evt.deletedTokens || []; @@ -3387,8 +3393,8 @@ var COFantasy = COFantasy || function() { token.remove(); } - //L'argument effetC doit être le nom complet, pas la base - //evt.deletedAttributes doit être défini + //L'argument effetC doit \xEAtre le nom complet, pas la base + //evt.deletedAttributes doit \xEAtre d\xE9fini function enleverEffetAttribut(charId, effetC, attrName, extension, evt) { let attrSave = attributeExtending(charId, attrName, effetC, extension); attrSave. @@ -3398,14 +3404,14 @@ var COFantasy = COFantasy || function() { }); } - function finDEffet(attr, effet, attrName, charId, evt, options) { //L'effet arrive en fin de vie, doit être supprimé + function finDEffet(attr, effet, attrName, charId, evt, options) { //L'effet arrive en fin de vie, doit \xEAtre supprim\xE9 options = options || {}; evt.deletedAttributes = evt.deletedAttributes || []; let res; let newInit = []; let efComplet = effetComplet(effet, attrName); - //Si on a un attrSave, alors on a déjà imprimé le message de fin d'effet - if (options.attrSave) { //on a un attribut associé à supprimer) + //Si on a un attrSave, alors on a d\xE9j\xE0 imprim\xE9 le message de fin d'effet + if (options.attrSave) { //on a un attribut associ\xE9 \xE0 supprimer) evt.deletedAttributes.push(options.attrSave); options.attrSave.remove(); } else if (options.gardeAutresAttributs === undefined) { //On cherche si il y en a un @@ -3426,7 +3432,7 @@ var COFantasy = COFantasy || function() { let character; let combat = stateCOF.combat; switch (effet) { - case 'affecteParAura': //voir si l'aura est toujours là + case 'affecteParAura': //voir si l'aura est toujours l\xE0 if (combat && combat.auras && efComplet.length > 15) { let id = efComplet.substring(15, efComplet.length - 1); let aura = combat.auras.find(function(a) { @@ -3476,7 +3482,7 @@ var COFantasy = COFantasy || function() { if (arme && arme.armeDeGrand) { let taille = taillePersonnage(perso, 4); if (taille == 4 && arme.label != perso.attrArmeEnMain.get('max')) { - sendPerso(perso, "ne peut plus tenir " + arme.name + " à une main"); + sendPerso(perso, "ne peut plus tenir " + arme.name + " \xE0 une main"); degainerArme(perso, arme.label, evt, { deuxMains: true }); @@ -3675,22 +3681,22 @@ var COFantasy = COFantasy || function() { function(s) { options.print = function(m) {}; //Pour ne pas afficher le message final. let tempsEffectif = Math.ceil(s / regen); - sendPerso(perso, "récupère encore " + s + " PV en " + tempsEffectif + " tours."); + sendPerso(perso, "r\xE9cup\xE8re encore " + s + " PV en " + tempsEffectif + " tours."); }); } - //Régénération d'une carac physique affaiblie de 1d4, si il y en a. + //R\xE9g\xE9n\xE9ration d'une carac physique affaiblie de 1d4, si il y en a. if (attributeAsInt(perso, 'affaiblissementdeconstitution', 0) > 0) { let d4 = rollDePlus(4); diminueAffaiblissement(perso, 'constitution', d4.val, evt); - sendPerso(perso, "récupère " + d4.roll + " points de constitution"); + sendPerso(perso, "r\xE9cup\xE8re " + d4.roll + " points de constitution"); } else if (attributeAsInt(perso, 'affaiblissementdeforce', 0) > 0) { let d4 = rollDePlus(4); diminueAffaiblissement(perso, 'force', d4.val, evt); - sendPerso(perso, "récupère " + d4.roll + " points de force"); + sendPerso(perso, "r\xE9cup\xE8re " + d4.roll + " points de force"); } else if (attributeAsInt(perso, 'affaiblissementdedexterite', 0) > 0) { let d4 = rollDePlus(4); diminueAffaiblissement(perso, 'dexterite', d4.val, evt); - sendPerso(perso, "récupère " + d4.roll + " points de dextérité"); + sendPerso(perso, "r\xE9cup\xE8re " + d4.roll + " points de dext\xE9rit\xE9"); } }); break; @@ -3699,7 +3705,7 @@ var COFantasy = COFantasy || function() { case 'arbreAnime': case 'objetAnime': case 'degradationZombie': //effacer le personnage - //Dans le cas d'un Zombie, diminuer la limite du nécromant si nécessaire + //Dans le cas d'un Zombie, diminuer la limite du n\xE9cromant si n\xE9cessaire if (effet == 'degradationZombie') { let attrNecromant = charAttribute(charId, 'necromant'); if (attrNecromant.length > 0) { @@ -3811,7 +3817,7 @@ var COFantasy = COFantasy || function() { abilities: charAbilities, allies: [] }; - // Retrait du perso de toutes les listes d'alliés + // Retrait du perso de toutes les listes d'alli\xE9s for (const [perso, alliesPerso] of Object.entries(alliesParPerso)) { if (alliesPerso.has(charId)) { deletedChar.allies.push(perso); @@ -3903,7 +3909,7 @@ var COFantasy = COFantasy || function() { if (pv == 0) { //jshint ignore:line mort(perso, undefined, evt); } else { - //On note qu'il l'a déjà fait pour qu'il ne puisse le refaire dans le combat + //On note qu'il l'a d\xE9j\xE0 fait pour qu'il ne puisse le refaire dans le combat setTokenAttr(perso, 'aAgiAZeroPV', true, evt); } }); @@ -3947,7 +3953,7 @@ var COFantasy = COFantasy || function() { }; if (getState(perso, 'mort')) return; if (!combat) { - sendChat('', "Il restait un effet retardé " + effetRetarde + " qui devait se déclencher pour " + token.get('name')); + sendChat('', "Il restait un effet retard\xE9 " + effetRetarde + " qui devait se d\xE9clencher pour " + token.get('name')); return; } let duree = getIntValeurOfEffet(perso, efComplet, 1); @@ -3979,7 +3985,7 @@ var COFantasy = COFantasy || function() { charId: charId }; if (getState(perso, 'mort')) return; - whisperChar(charId, "Le poison commence à faire effet !"); + whisperChar(charId, "Le poison commence \xE0 faire effet !"); setTokenAttr(perso, 'poisonAffaiblissantLong', true, evt, {}); }); break; @@ -3988,7 +3994,7 @@ var COFantasy = COFantasy || function() { let messageRetarde = efComplet.substring(15, efComplet.length - 1); iterTokensOfAttribute(charId, options.pageId, efComplet, attrName, function(token) { whisperChar(charId, messageRetarde); - //Puis on regarde si il y a une valeur à afficher + //Puis on regarde si il y a une valeur \xE0 afficher let perso = { token: token, charId: charId @@ -4001,7 +4007,7 @@ var COFantasy = COFantasy || function() { break; case 'tenebres': iterTokensOfAttribute(charId, options.pageId, efComplet, attrName, function(token) { - //Puis on regarde si il y a une valeur à afficher + //Puis on regarde si il y a une valeur \xE0 afficher let perso = { token: token, charId: charId @@ -4013,7 +4019,7 @@ var COFantasy = COFantasy || function() { break; case 'brumes': iterTokensOfAttribute(charId, options.pageId, efComplet, attrName, function(token) { - //Puis on regarde si il y a une valeur à afficher + //Puis on regarde si il y a une valeur \xE0 afficher let perso = { token: token, charId: charId @@ -4106,7 +4112,7 @@ var COFantasy = COFantasy || function() { } evt.deletedAttributes.push(attr); attr.remove(); - //Débloque les tokens si l'effet les immobilisait + //D\xE9bloque les tokens si l'effet les immobilisait switch (effet) { case 'bloqueManoeuvre': case 'prisonVegetale': @@ -4133,7 +4139,7 @@ var COFantasy = COFantasy || function() { } } - //retourne le personnage du compagnon s'il est présent et actif + //retourne le personnage du compagnon s'il est pr\xE9sent et actif function compagnonPresent(personnage, nomCompagnon) { let compagnon = predicateAsBool(personnage, nomCompagnon); if (compagnon) { @@ -4201,7 +4207,7 @@ var COFantasy = COFantasy || function() { } //Pour savoir si un personnage est un personnage joueur - // -> fiche de PJ + dé de vie + token lié + controllé par au moins un joueur. + // -> fiche de PJ + d\xE9 de vie + token li\xE9 + controll\xE9 par au moins un joueur. function estPJ(perso) { if (persoEstPNJ(perso)) return false; let dv = ficheAttributeAsInt(perso, 'DV', 0); @@ -4221,50 +4227,50 @@ var COFantasy = COFantasy || function() { }); }*/ - /* Événements, utilisés pour les undo, en particulier undo pour refaire - * une action quand une règle le permet (utilisation de points de chance, etc..) - * Champ d'un événement (variables evt en général dans le code): + /* \xC9v\xE9nements, utilis\xE9s pour les undo, en particulier undo pour refaire + * une action quand une r\xE8gle le permet (utilisation de points de chance, etc..) + * Champ d'un \xE9v\xE9nement (variables evt en g\xE9n\xE9ral dans le code): * id : identificateur unique (int) - * type : description de l'événement (string) - * affectes : liste de tokens affectés par l'événement - * tokens : liste des tokens créés - * deletedTokens : liste de tokens effacés - * !!!!! -> ne garde pas les tokens effacés si on n'est pas sûr que son image est au bon endroit. Typiquement, on ne va le faire que pour les tokens crées dans le script - * attributes : liste de attributs créés ou modifiés - * deletesAttributes: lites des attributs effacés - * characters : liste des personnages créés + * type : description de l'\xE9v\xE9nement (string) + * affectes : liste de tokens affect\xE9s par l'\xE9v\xE9nement + * tokens : liste des tokens cr\xE9\xE9s + * deletedTokens : liste de tokens effac\xE9s + * !!!!! -> ne garde pas les tokens effac\xE9s si on n'est pas s\xFBr que son image est au bon endroit. Typiquement, on ne va le faire que pour les tokens cr\xE9es dans le script + * attributes : liste de attributs cr\xE9\xE9s ou modifi\xE9s + * deletesAttributes: lites des attributs effac\xE9s + * characters : liste des personnages cr\xE9\xE9s * characterNames : liste de character * name - * defaultTokens : liste de tokens par défaut (objet) + * defaultTokens : liste de tokens par d\xE9faut (objet) * (character, defaultToken) - * deletedCharacters: liste des personnages effacés - * combat : valeur de la variable d'état combat + * deletedCharacters: liste des personnages effac\xE9s + * combat : valeur de la variable d'\xE9tat combat * updateNextInitSet: valeur de l'ensemble des tokens dont il faut recalculer l'init - * turnorder : le turnorder (si il a changé) + * turnorder : le turnorder (si il a chang\xE9) * initiativepage : true si le turnorder est actif - * personnage : le perso qui 'fait' l'événement - * succes : stoque si l'attaque était un succès (bool) - * action : sauvegarde des paramètres de l'evt, pour la rejouer - * - caracteristique : carac testée (pour un jet) + * personnage : le perso qui 'fait' l'\xE9v\xE9nement + * succes : stoque si l'attaque \xE9tait un succ\xE8s (bool) + * action : sauvegarde des param\xE8tres de l'evt, pour la rejouer + * - caracteristique : carac test\xE9e (pour un jet) * - titre : titre du jet - * - playerId : id du joueur qui a lancé l'action - * - selected : cibles sélectionnés des l'action + * - playerId : id du joueur qui a lanc\xE9 l'action + * - selected : cibles s\xE9lectionn\xE9s des l'action * - attaquant: personnage attaquant (TODO: voir si doublon avec personnage) * - cibles: liste des cibles d'attaque, avec leurs tags - * - weaponStats: stats de l'arme (ou attaque) utilisée - * - rolls: les jets de l'action, pour les avoir à l'identique - * les dégâts sont stoqués dans chaque cible, dans cible.rollsDmg + * - weaponStats: stats de l'arme (ou attaque) utilis\xE9e + * - rolls: les jets de l'action, pour les avoir \xE0 l'identique + * les d\xE9g\xE2ts sont stoqu\xE9s dans chaque cible, dans cible.rollsDmg * - attack: les jets de l'attaque - * - etat_e_index_targetid: save pour entrer dans l'état e + * - etat_e_index_targetid: save pour entrer dans l'\xE9tat e * - effet_e_index_targetid: save pour l'effet e - * - attaquant_pietinement_targetid: jet de l'attaquant pour le piétinement - * - defenseur_pietinement_targetid: jet de du défenseur pour le piétinement + * - attaquant_pietinement_targetid: jet de l'attaquant pour le pi\xE9tinement + * - defenseur_pietinement_targetid: jet de du d\xE9fenseur pour le pi\xE9tinement * - options : options de l'action - * attenteResultat : permet de savoir que le jet est en attente de décision pour savoir si c'est un succès ou non (quand il n'y a pas de difficulté donnée et que le personnage est sous l'emprise d'une malédiction) + * attenteResultat : permet de savoir que le jet est en attente de d\xE9cision pour savoir si c'est un succ\xE8s ou non (quand il n'y a pas de difficult\xE9 donn\xE9e et que le personnage est sous l'emprise d'une mal\xE9diction) */ function addEvent(evt) { if (evt.id) { - error("Tentative d'ajouter un événement déjà dans l'historique", evt); + error("Tentative d'ajouter un \xE9v\xE9nement d\xE9j\xE0 dans l'historique", evt); return; } evt.id = stateCOF.eventId++; @@ -4304,11 +4310,11 @@ var COFantasy = COFantasy || function() { } } - //Si evt n'est pas défini, annule le dernier evt + //Si evt n'est pas d\xE9fini, annule le dernier evt function undoEvent(evt) { if (evt === undefined) { if (eventHistory.length === 0) { - sendChat('COF', "/w GM Historique d'évènements vide"); + sendChat('COF', "/w GM Historique d'\xE9v\xE8nements vide"); return; } evt = eventHistory.pop(); @@ -4346,7 +4352,7 @@ var COFantasy = COFantasy || function() { } if (evt.defaultTokens) { evt.defaultTokens.forEach(function(dt) { - //On cherche d'abord un token qui représente dt.character + //On cherche d'abord un token qui repr\xE9sente dt.character let tokens = findObjs({ _type: 'graphic', represents: dt.character.id @@ -4431,7 +4437,7 @@ var COFantasy = COFantasy || function() { }); }); } - // On le remet chez ses alliés + // On le remet chez ses alli\xE9s if (character.allies.length > 0) { Object.values(character.allies).forEach(function(allie) { let alliesPerso = alliesParPerso[allie] || new Set(); @@ -4499,7 +4505,7 @@ var COFantasy = COFantasy || function() { } if (_.has(evt, 'combat')) { let combat = stateCOF.combat; - //regarde si le token actif a changé + //regarde si le token actif a chang\xE9 if (evt.combat && (!combat || evt.combat.activeTokenId != combat.activeTokenId) && stateCOF.options.affichage.val.init_dynamique.val) { @@ -4529,24 +4535,27 @@ var COFantasy = COFantasy || function() { stateCOF.tokensTemps.push(tt); }); } - if (evt.tokensTemps) { //ceux pour lesquels on a diminué la durée + if (evt.tokensTemps) { //ceux pour lesquels on a diminu\xE9 la dur\xE9e evt.tokensTemps.forEach(function(tt) { if (tt.tt) tt.tt.duree = tt.ancienneDuree; }); } } - //origin peut être un message ou un nom de joueur + //origin peut \xEAtre un message ou un nom de joueur function sendPlayer(origin, msg, playerId) { let dest = origin; - if (origin.who) { - playerId = playerId || getPlayerIdFromMsg(origin); - if (playerIsGM(playerId)) dest = 'GM'; - else dest = origin.who; + if (origin.who !== undefined) { + if (origin.who === '') dest = 'GM'; + else { + playerId = playerId || getPlayerIdFromMsg(origin); + if (playerId == 'API' || playerIsGM(playerId)) dest = 'GM'; + else dest = origin.who; + } } if (dest.includes('"')) { sendChat('COF', msg); - log("Impossible d'envoyer des messages privés à " + dest + " car le nom contient des guillemets"); + log("Impossible d'envoyer des messages priv\xE9s \xE0 " + dest + " car le nom contient des guillemets"); } sendChat('COF', '/w "' + dest + '" ' + msg); } @@ -4576,7 +4585,7 @@ var COFantasy = COFantasy || function() { case 'FOR': return "de force"; case 'DEX': - return "de dextérité"; + return "de dext\xE9rit\xE9"; case 'CON': return "de constitution"; case 'SAG': @@ -4590,7 +4599,7 @@ var COFantasy = COFantasy || function() { } } - //msg peut être un message ou un playerId + //msg peut \xEAtre un message ou un playerId function peutController(msg, perso) { if (msg === undefined) return true; let playerId = getPlayerIdFromMsg(msg); @@ -4623,12 +4632,12 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let action = evt.action; if (action === undefined) { - error("Erreur interne du bouton de confirmation: l'évènement n'a pas d'action", cmd); + error("Erreur interne du bouton de confirmation: l'\xE9v\xE8nement n'a pas d'action", cmd); return; } let options = action.currentOptions || {}; @@ -4669,7 +4678,7 @@ var COFantasy = COFantasy || function() { let prev = aff.prev; let tok = aff.affecte; if (prev === undefined || tok === undefined) { - error("Pas d'état précédant", aff); + error("Pas d'\xE9tat pr\xE9c\xE9dant", aff); return; } let prevTok; @@ -4678,7 +4687,7 @@ var COFantasy = COFantasy || function() { tok.set(key, val); }); if (HTdeclared) HealthColors.Update(tok, prevTok); - sendChat("COF", "État de " + tok.get("name") + " restauré."); + sendChat("COF", "\xC9tat de " + tok.get("name") + " restaur\xE9."); }); } @@ -4695,7 +4704,7 @@ var COFantasy = COFantasy || function() { return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string } - //Remplace une macro ou ability par sa définition (récursivement) + //Remplace une macro ou ability par sa d\xE9finition (r\xE9cursivement) function replaceAction(action, perso, macros, abilities) { let remplacement = false; if (action.indexOf('#') >= 0) { @@ -4712,7 +4721,7 @@ var COFantasy = COFantasy || function() { if (!remplacement) macros = macros.filter(function(m, k) { return (k != i); - }); //Pour éviter la récursion + }); //Pour \xE9viter la r\xE9cursion remplacement = true; } }); @@ -4728,7 +4737,7 @@ var COFantasy = COFantasy || function() { let daName = '%' + aName; if (action.indexOf(daName) >= 0) { action = action.replace(daName, a.get('action')); - if (!remplacement) abilities = abilities.splice(i); //Pour éviter la récursion + if (!remplacement) abilities = abilities.splice(i); //Pour \xE9viter la r\xE9cursion remplacement = true; } daName = '%{selected|' + aName + '}'; @@ -4737,7 +4746,7 @@ var COFantasy = COFantasy || function() { if (!remplacement) abilities = abilities.filter(function(m, k) { return (k != i); - }); //Pour éviter la récursion + }); //Pour \xE9viter la r\xE9cursion remplacement = true; } }); @@ -4818,7 +4827,8 @@ var COFantasy = COFantasy || function() { weaponStats.modificateurs = fieldAsString(att, 'armemodificateurs', ''); weaponStats.typeDegats = fieldAsString(att, 'armetypedegats', 'tranchant'); weaponStats.options = fieldAsString(att, 'armeoptions', ''); - weaponStats.options = weaponStats.options.trim(); + //On remplace les \n par des blancs pour l'affichage, sinon \xE7a bug + weaponStats.options = weaponStats.options.replace(/\n/g, ' ').trim(); weaponStats.predicats = fieldAsString(att, 'armepredicats', ''); switch (weaponStats.typeAttaque) { case 'Naturel': @@ -4849,7 +4859,7 @@ var COFantasy = COFantasy || function() { armeDeCreatureFeerique(perso, weaponStats, 3); break; default: - //On cherche si c'est une arme à 2 mains + //On cherche si c'est une arme \xE0 2 mains //Ne devrait pas servir, on a toujours un type, maintenant let t = weaponStats.name.toLowerCase(); if (t.includes('2 mains') || t.includes('deux mains')) { @@ -4864,19 +4874,19 @@ var COFantasy = COFantasy || function() { } } } - //Informations dans le champ spécial + //Informations dans le champ sp\xE9cial let champDivers = weaponStats.divers; if (champDivers === '') champDivers = weaponStats.predicats; else if (weaponStats.predicats !== '') champDivers += '\n' + weaponStats.predicats; let pred = predicateOfRaw(champDivers); - //On transfert les prédicats connus dans weaponStats + //On transfert les pr\xE9dicats connus dans weaponStats if (pred.charge) weaponStats.charge = toInt(pred.charge, 1); weaponStats.eclaire = toInt(pred.eclaire); weaponStats.eclaireFaible = toInt(pred.eclaireFaible); weaponStats.batarde = pred.batarde; if (weaponStats.batarde && weaponStats.deuxMains) { - error("L'arme " + weaponStats.name + " est déclarée comme batârde, il faudrait en faire une arme à une main par défaut", weaponStats); + error("L'arme " + weaponStats.name + " est d\xE9clar\xE9e comme bat\xE2rde, il faudrait en faire une arme \xE0 une main par d\xE9faut", weaponStats); weaponStats.deuxMains = undefined; } if (pred.armeDeGrand) { @@ -4885,22 +4895,26 @@ var COFantasy = COFantasy || function() { if (taille < 5) weaponStats.deuxMains = true; else weaponStats.deuxMains = false; } - //Identification des catégories d'armes utilisées en jeu + //Identification des cat\xE9gories d'armes utilis\xE9es en jeu identifierArme(weaponStats, pred, 'arc', /\barc\b/i); - identifierArme(weaponStats, pred, 'arbalete', /\barbal[eè]te\b/i); - identifierArme(weaponStats, pred, 'baton', /\bb[aâ]ton\b/i); + identifierArme(weaponStats, pred, 'arbalete', /\barbal[e\xE8]te\b/i); + identifierArme(weaponStats, pred, 'baton', /\bb[a\xE2]ton\b/i); identifierArme(weaponStats, pred, 'hache', /\bhache\b/i); - identifierArme(weaponStats, pred, 'epee', /\b[eé]p[eé]e\b/i); - identifierArme(weaponStats, pred, 'epieu', /\b[eé]pieu\b/i); + identifierArme(weaponStats, pred, 'epee', /\b[e\xE9]p[e\xE9]e\b/i); + identifierArme(weaponStats, pred, 'epieu', /\b[e\xE9]pieu\b/i); identifierArme(weaponStats, pred, 'fronde', /\bfronde\b/i); identifierArme(weaponStats, pred, 'marteau', /\bmarteau\b/i); identifierArme(weaponStats, pred, 'masse', /\bmasse\b/i); - identifierArme(weaponStats, pred, 'rapiere', /\brapi[eè]re\b/i); + identifierArme(weaponStats, pred, 'rapiere', /\brapi[e\xE8]re\b/i); identifierArme(weaponStats, pred, 'poudre', /\bpoudre\b/i); identifierArme(weaponStats, pred, 'sabre', /\b(katana|wakizachi|boken|demi-lame|vivelame|sabre)\b/i); if (weaponStats.arc && predicateAsBool(perso, 'arcDeMaitre')) { weaponStats.portee += 20; } + if (weaponStats.poudre && predicateAsBool(perso, 'poudrePuissante')) { + weaponStats.portee += 10; + weaponStats.attDMBonusCommun += 2; + } return weaponStats; } @@ -4928,8 +4942,8 @@ var COFantasy = COFantasy || function() { bar2 = parseInt(token.get('bar2_value')); if (isNaN(bar2)) { if (token.get('bar1_link') === '') bar2 = 0; - else { //devrait être lié à la mana courante - sendPerso(personnage, "*** Attention, la barre de mana du token n'est pas liée à la mana de la fiche ***"); + else { //devrait \xEAtre li\xE9 \xE0 la mana courante + sendPerso(personnage, "*** Attention, la barre de mana du token n'est pas li\xE9e \xE0 la mana de la fiche ***"); bar2 = parseInt(manaAttr[0].get('current')); } } @@ -4972,7 +4986,7 @@ var COFantasy = COFantasy || function() { } //depasse est un string qui commence par --depasseLimite - //args doit être défini et contient des valeur à modifier : + //args doit \xEAtre d\xE9fini et contient des valeur \xE0 modifier : // - mana // - text function peutDepasserLimite(depasse, perso, attrName, args) { @@ -5014,6 +5028,8 @@ var COFantasy = COFantasy || function() { if (condition.valeur === undefined) return !attributeAsBool(perso, condition.attribute); return testAttribut(perso, condition.attrbute, condition.valeur, condition); + case 'premiereAttaque': + return attributeAsBool(perso, 'attributDeCombat_premiereAttaque'); } return false; case 'mana': @@ -5026,7 +5042,10 @@ var COFantasy = COFantasy || function() { case 'limiteParJour': if (cmd.length < 2) return false; let limiteParJour = parseInt(cmd[1]); - if (isNaN(limiteParJour) || limiteParJour < 1) return false; + if (isNaN(limiteParJour)) { + limiteParJour = predicateAsInt(perso, cmd[1], 0, 1); + } + if (limiteParJour < 1) return false; let ressourceParJour = defResource; if (cmd.length > 2) { cmd.splice(0, 2); @@ -5036,7 +5055,7 @@ var COFantasy = COFantasy || function() { if (attributeAsInt(perso, ressourceParJour, limiteParJour) > 0) { return false; } - //Reste le cas où on peut dépasser cette limite par jour + //Reste le cas o\xF9 on peut d\xE9passer cette limite par jour let depasse = options.find(function(o) { return o.startsWith('depasseLimite '); }); @@ -5057,7 +5076,10 @@ var COFantasy = COFantasy || function() { case 'limiteParCombat': if (cmd.length < 2) return false; let limiteParCombat = parseInt(cmd[1]); - if (isNaN(limiteParCombat) || limiteParCombat < 1) return false; + if (isNaN(limiteParCombat)) { + limiteParCombat = predicateAsInt(perso, cmd[1], 0, 1); + } + if (limiteParCombat < 1) return false; let ressourceParCombat = defResource; if (cmd.length > 2) { cmd.splice(0, 2); @@ -5074,13 +5096,15 @@ var COFantasy = COFantasy || function() { if (cmd.length < 2) return false; let armeAssociee = getWeaponStats(perso, cmd[1]); return armeAssociee && armeAssociee.armeDeJet && armeAssociee.nbArmesDeJet < 1; + case 'traquenard': + return attributeAsBool(perso, 'attributDeCombat_premiereAttaque'); } return false; }); return ai; } - //Enlève les chaînes de type ?{..} pour être sûr que l'action est impossible + //Enl\xE8ve les cha\xEEnes de type ?{..} pour \xEAtre s\xFBr que l'action est impossible function removeUserInputs(act) { let m = act.match(/\?\{[^\}]*\}/g); if (!m) return act; @@ -5102,7 +5126,7 @@ var COFantasy = COFantasy || function() { if (labelArmePrincipale) perso.arme = getWeaponStats(perso, labelArmePrincipale); let labelArmeGauche = attr[0].get('max'); if (labelArmeGauche) { - if (labelArmeGauche == labelArmePrincipale) { //arme tenue à 2 mains + if (labelArmeGauche == labelArmePrincipale) { //arme tenue \xE0 2 mains perso.arme.deuxMains = true; } else { perso.armeGauche = getWeaponStats(perso, labelArmeGauche); @@ -5120,7 +5144,7 @@ var COFantasy = COFantasy || function() { function listAllMunitions(perso) { if (perso.munitions) return perso.munitions; let rawList = extractRepeating(perso, 'munitions'); - let liste = {}; //liste triée par label de munition + let liste = {}; //liste tri\xE9e par label de munition for (let pref in rawList) { let ra = rawList[pref]; if (ra.labelmunition === undefined) ra.labelmunition = 0; @@ -5135,11 +5159,11 @@ var COFantasy = COFantasy || function() { return liste; } - //Les options de l'arme doivent déjà être dans act + //Les options de l'arme doivent d\xE9j\xE0 \xEAtre dans act function demandeMunition(perso, weaponStats, options, act) { if (act.includes('--munition')) return act; let typeMunition; - if (weaponStats.arc) typeMunition = 'Flèche'; + if (weaponStats.arc) typeMunition = 'Fl\xE8che'; else if (weaponStats.arbalete) typeMunition = 'Carreau'; else if (weaponStats.poudre) typeMunition = 'Balle'; else if (weaponStats.fronde) typeMunition = 'Autre'; //TODO: ajouter le type bille sur la fiche @@ -5148,7 +5172,7 @@ var COFantasy = COFantasy || function() { let munitionsDeType = []; for (let label in munitions) { let munition = munitions[label]; - let tm = fieldAsString(munition, 'typemunition', 'Flèche'); + let tm = fieldAsString(munition, 'typemunition', 'Fl\xE8che'); if (tm != typeMunition) return; let nb = fieldAsInt(munition, 'qtemunition', 1); if (nb > 0) munitionsDeType.push(munition); @@ -5163,12 +5187,19 @@ var COFantasy = COFantasy || function() { return act + demande + '}'; } + //arm doit \xEAtre le r\xE9sultat de getWeaponStats + function armeDechargee(perso, arme) { + if (!arme.charge) return false; + let currentCharge = attributeAsInt(perso, 'charge_' + arme.label, arme.charge); + return currentCharge === 0; + } + //options peut avoir les champs: // - ressource, un attribut // - overlay // - buttonStyle // - attackStats - // et la fonction peut écrire actionImpossible = true dans options. + // et la fonction peut \xE9crire actionImpossible = true dans options. function bouton(action, text, perso, options) { if (action === undefined || action.trim() === '') return text; else action = action.trim(); @@ -5181,12 +5212,12 @@ var COFantasy = COFantasy || function() { if (character) perso.name = character.get('name'); else perso.name = nomPerso(perso); } - //Cas de plusieurs actions après expansion + //Cas de plusieurs actions apr\xE8s expansion let actions = action.split('\n'); //Cherche le picto et le style let style = ''; let picto = ''; - let groupe; //Pour générer un bouton d'attaque de groupe. À revoir + let groupe; //Pour g\xE9n\xE9rer un bouton d'attaque de groupe. \xC0 revoir actions = actions.map(function(act) { act = act.trim(); if (act.startsWith("/as ")) { @@ -5197,7 +5228,7 @@ var COFantasy = COFantasy || function() { let actSansChoix = removeUserInputs(act); const args = actSansChoix.split(' --'); let defRessource = ''; - if (act.startsWith('!cof-guerison ')) defRessource = 'guérison'; + if (act.startsWith('!cof-guerison ')) defRessource = 'gu\xE9rison'; let dai = { text }; @@ -5205,13 +5236,13 @@ var COFantasy = COFantasy || function() { options.actionImpossible = true; else text = dai.text; if (!options.actionImpossible) { - if (act.startsWith('!cof-soin ') && !actSansChoix.includes('--limitePar') && !actSansChoix.includes('--dose')) { //Limitations spéficiques + if (act.startsWith('!cof-soin ') && !actSansChoix.includes('--limitePar') && !actSansChoix.includes('--dose')) { //Limitations sp\xE9ficiques let rangSoin = predicateAsInt(perso, 'voieDesSoins', 0); let cmd = args[0].split(' '); if (cmd.includes('leger')) { let soinsLegers = attributeAsInt(perso, 'soinsLegers', 0); if (soinsLegers >= rangSoin) { - //Peut-être qu'on peut encore dépasser la limite + //Peut-\xEAtre qu'on peut encore d\xE9passer la limite let depasse = actSansChoix.indexOf('--depasseLimite '); if (depasse > 0) { let dp = { @@ -5226,7 +5257,7 @@ var COFantasy = COFantasy || function() { } else if (cmd.includes('modere')) { let soinsModeres = attributeAsInt(perso, 'soinsModeres', 0); if (soinsModeres >= rangSoin) { - //Peut-être qu'on peut encore dépasser la limite + //Peut-\xEAtre qu'on peut encore d\xE9passer la limite let depasse = actSansChoix.indexOf('--depasseLimite '); if (depasse > 0) { let dp = { @@ -5245,7 +5276,7 @@ var COFantasy = COFantasy || function() { let attackLabel = cmd[1]; let arme = getWeaponStats(perso, attackLabel); if (arme !== undefined && arme.charge) { - let currentCharge = attributeAsInt(perso, 'charge_' + attackLabel, 0); + let currentCharge = attributeAsInt(perso, 'charge_' + arme.label, arme.charge); if (currentCharge >= arme.charge) options.actionImpossible = true; } @@ -5253,7 +5284,7 @@ var COFantasy = COFantasy || function() { } else if (act.startsWith('!cof-attack ')) { let cmd = act.split(' '); if (cmd.length > 3 && cmd[3] == '-1') { - //Selon l'arme en main, une action peut être possible ou non + //Selon l'arme en main, une action peut \xEAtre possible ou non let weaponStats = armesEnMain(perso); if (weaponStats) { options.attackStats = options.attackStats || weaponStats; @@ -5261,6 +5292,8 @@ var COFantasy = COFantasy || function() { (weaponStats.deuxMains && attributeAsBool(perso, 'espaceExigu')) || (weaponStats.portee && (cmd.includes('--attaqueFlamboyante') || cmd.includes('--seulementContact'))) || + (!cmd.includes('--semonce') && !cmd.includes('--tirDeBarrage') && armeDechargee(perso, weaponStats)) || + (cmd.includes('--semonce') && attributeAsInt(perso, 'attaqueADistanceRatee', 0) != 1) || (cmd.includes('--ricochets') && !(weaponStats.armeDeJet || weaponStats.options.includes('--aussiArmeDeJet'))); } } @@ -5305,7 +5338,7 @@ var COFantasy = COFantasy || function() { } act = demandeMunition(perso, attackStats, options, act); } - //On cherche la portée dans les options (ça a la priorité) + //On cherche la port\xE9e dans les options (\xE7a a la priorit\xE9) args.forEach(function(o) { if (o.startsWith('portee ')) { let p = parseInt(o.substring(7)); @@ -5426,13 +5459,13 @@ var COFantasy = COFantasy || function() { } } if (act.indexOf('@{selected') !== -1) { - // cas spécial pour @{selected|token_id} où l'on remplace toutes les occurences par token.id + // cas sp\xE9cial pour @{selected|token_id} o\xF9 l'on remplace toutes les occurences par token.id act = act.replace(new RegExp(escapeRegExp('@{selected|token_id}'), 'g'), tid); act = act.replace(new RegExp(escapeRegExp('@{selected|token_name}'), 'g'), nomPerso(perso)); let tmp = act.split('@{selected'); tmp.forEach(function(elem) { if (elem.startsWith('|')) { - // attribut demandé + // attribut demand\xE9 let attribute_name = elem.substring(0, elem.indexOf("}")).substr(1); let carac = caracOfMod(attribute_name); let replacement; @@ -5470,12 +5503,12 @@ var COFantasy = COFantasy || function() { act.indexOf('--enVue') == -1 && act.indexOf('--disque') == -1 && act.indexOf('--target ' + tid) == -1) { - //Si on n'a pas de cible, on fait comme si le token était sélectionné. + //Si on n'a pas de cible, on fait comme si le token \xE9tait s\xE9lectionn\xE9. let add_token = " --target " + tid; if (act.indexOf(' --allie') >= 0) { if (act.indexOf('--lanceur') == -1) add_token = " --lanceur " + tid; - else add_token = ""; //La cible sont les alliés de --lanceur. + else add_token = ""; //La cible sont les alli\xE9s de --lanceur. } if (act.indexOf(' --message ') != -1) act = act.replace(' --message ', add_token + ' --message '); else act += add_token; @@ -5511,8 +5544,8 @@ var COFantasy = COFantasy || function() { } } - //Fonction séparée pour pouvoir envoyer un frame à plusieurs joueurs - // playerId peut être undefined (en particulier pour envoyer au mj) + //Fonction s\xE9par\xE9e pour pouvoir envoyer un frame \xE0 plusieurs joueurs + // playerId peut \xEAtre undefined (en particulier pour envoyer au mj) function addFramedHeader(display, playerId, chuchote) { let perso1 = display.perso1; let perso2 = display.perso2; @@ -5650,9 +5683,9 @@ var COFantasy = COFantasy || function() { display.header = res; } - //Si options.chuchote est vrai, la frame est chuchotée au joueur qui fait l'action - //Si options.chuchote est un nom, on chuchote la frame à ce nom - //Pour retarder la décision sur la cible de chuchotement, utiliser options.retarder + //Si options.chuchote est vrai, la frame est chuchot\xE9e au joueur qui fait l'action + //Si options.chuchote est un nom, on chuchote la frame \xE0 ce nom + //Pour retarder la d\xE9cision sur la cible de chuchotement, utiliser options.retarder function startFramedDisplay(playerId, action, perso, options) { options = options || {}; if (options.secret) { @@ -5723,7 +5756,7 @@ var COFantasy = COFantasy || function() { display.output += ""; } - //newLine indique qu'on commence une nouvelle rangée + //newLine indique qu'on commence une nouvelle rang\xE9e function addCellInFramedDisplay(display, cell, size, newLine, fond) { size = size || 100; if (display.endColumn) { @@ -5763,7 +5796,7 @@ var COFantasy = COFantasy || function() { nomLimite += 'Jour'; break; default: - error("Unité d'utilisation de capacité " + capa + " non reconnue", unite); + error("Unit\xE9 d'utilisation de capacit\xE9 " + capa + " non reconnue", unite); return; } return nomLimite + '__' + capa; @@ -5796,14 +5829,14 @@ var COFantasy = COFantasy || function() { expliquer("Perte de substance : -10 aux interactions sociales"); bonus -= 10; if (perteDeSubstance >= 15) { - expliquer("Perte de substance : faire un test de CHA 15 pour se faire remarquer à chaque tour"); + expliquer("Perte de substance : faire un test de CHA 15 pour se faire remarquer \xE0 chaque tour"); } } } return bonus; } - //expliquer est optionnel, et si présent, il faut msg + //expliquer est optionnel, et si pr\xE9sent, il faut msg function malusArmure(personnage, expliquer, msg) { let malusArmure = 0; if (personnage.malusArmure === undefined) { @@ -5828,7 +5861,7 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'graceFelineVoleur')) { let bonusGraceFeline = modCarac(personnage, 'charisme'); if (bonusGraceFeline > 0) { - expliquer("Grâce féline : +" + bonusGraceFeline + " en acrobaties"); + expliquer("Gr\xE2ce f\xE9line : +" + bonusGraceFeline + " en acrobaties"); bonus += bonusGraceFeline; } } @@ -5838,14 +5871,13 @@ var COFantasy = COFantasy || function() { } let a = predicateAsInt(personnage, 'ameFeline', 0); if (a > 0) { - expliquer("Âme féline : +" + a + " en acrobaties"); + expliquer("\xC2me f\xE9line : +" + a + " en acrobaties"); bonus += a; } break; } case 'baratiner': case 'bluffer': - case 'convaincre': bonus += bonusInteractionsSociales(personnage, expliquer); break; case 'course': @@ -5853,18 +5885,18 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'graceFelineVoleur')) { let bonusGraceFeline = modCarac(personnage, 'charisme'); if (bonusGraceFeline > 0) { - expliquer("Grâce féline : +" + bonusGraceFeline + " en course"); + expliquer("Gr\xE2ce f\xE9line : +" + bonusGraceFeline + " en course"); bonus += bonusGraceFeline; } } let a = predicateAsInt(personnage, 'ameFeline', 0); if (a > 0) { - expliquer("Âme féline : +" + a + " en course"); + expliquer("\xC2me f\xE9line : +" + a + " en course"); bonus += a; } a = predicateAsInt(personnage, 'vitesseDuFelin', 0); if (a > 0) { - expliquer("Vitesse du félin : +" + a + " en course"); + expliquer("Vitesse du f\xE9lin : +" + a + " en course"); bonus += a; } break; @@ -5875,10 +5907,10 @@ var COFantasy = COFantasy || function() { bonus += 5; } break; - case 'discrétion': + case 'discr\xE9tion': case 'discretion': if (attributeAsBool(personnage, 'foretVivanteEnnemie')) { - expliquer("Forêt hostile : -5 en discrétion"); + expliquer("For\xEAt hostile : -5 en discr\xE9tion"); bonus -= 5; } let perteDeSubstance = 0; @@ -5886,31 +5918,39 @@ var COFantasy = COFantasy || function() { perteDeSubstance = attributeAsInt(personnage, 'perteDeSubstance', 0); if (perteDeSubstance >= 5) { if (perteDeSubstance < 7) { - expliquer("Perte de substance : +2 en discrétion"); + expliquer("Perte de substance : +2 en discr\xE9tion"); bonus += 2; } else if (perteDeSubstance < 10) { - expliquer("Perte de substance : +5 en discrétion"); + expliquer("Perte de substance : +5 en discr\xE9tion"); bonus += 5; } else { - expliquer("Perte de substance : +10 en discrétion"); + expliquer("Perte de substance : +10 en discr\xE9tion"); bonus += 10; } } if (predicateAsBool(personnage, 'toutPetit') && !attributeAsBool(personnage, 'grandeTaille')) { - expliquer("Tout petit : +5 en discrétion"); + expliquer("Tout petit : +5 en discr\xE9tion"); bonus += 5; + } else if (predicateAsBool(personnage, 'petiteTaille')) { + expliquer("Petite taille : +2 en discr\xE9tion"); + bonus += 2; + } + let rapideCommeSonOmbre = predicateAsInt(personnage, 'rapideCommeSonOmbre', 0, 3); + if (rapideCommeSonOmbre > 0) { + expliquer("Rapide comme son ombre : +" + rapideCommeSonOmbre + " en discr\xE9tion"); + bonus += rapideCommeSonOmbre; } break; case 'intimidation': bonus += bonusArgumentDeTaille(personnage, expliquer); if (predicateAsBool(personnage, 'ordreDuChevalierDragon') && attributeAsBool(personnage, 'monteSur')) { - expliquer("Chevalier Dragon monté : +5 en intimidation"); + expliquer("Chevalier Dragon mont\xE9 : +5 en intimidation"); bonus += 5; } bonus += bonusInteractionsSociales(personnage, expliquer); if (predicateAsBool(personnage, 'batonDesRunesMortes') && (attributeAsBool(personnage, 'runeLizura') || attributeAsBool(personnage, 'runeMitrah'))) { - expliquer("Recouvert" + eForFemale(personnage) + " de la boue noire du bâton : +5 aux tests d'intimidation"); + expliquer("Recouvert" + eForFemale(personnage) + " de la boue noire du b\xE2ton : +5 aux tests d'intimidation"); bonus += 5; } break; @@ -5919,18 +5959,18 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'graceFelineVoleur')) { let bonusGraceFeline = modCarac(personnage, 'charisme'); if (bonusGraceFeline > 0) { - expliquer("Grâce féline : +" + bonusGraceFeline + " en escalade"); + expliquer("Gr\xE2ce f\xE9line : +" + bonusGraceFeline + " en escalade"); bonus += bonusGraceFeline; } } let a = predicateAsInt(personnage, 'ameFeline', 0); if (a > 0) { - expliquer("Âme féline : +" + a + " en escalade"); + expliquer("\xC2me f\xE9line : +" + a + " en escalade"); bonus += a; } a = predicateAsInt(personnage, 'vitesseDuFelin', 0); if (a > 0) { - expliquer("Vitesse du félin : +" + a + " en escalade"); + expliquer("Vitesse du f\xE9lin : +" + a + " en escalade"); bonus += a; } break; @@ -5938,20 +5978,20 @@ var COFantasy = COFantasy || function() { case 'mentir': bonus += bonusInteractionsSociales(personnage, expliquer); break; - case 'négociation': + case 'n\xE9gociation': case 'negociation': bonus += bonusArgumentDeTaille(personnage, expliquer); bonus += bonusInteractionsSociales(personnage, expliquer); break; case 'orientation': if (attributeAsBool(personnage, 'foretVivanteEnnemie')) { - expliquer("Forêt hostile : -5 en orientation"); + expliquer("For\xEAt hostile : -5 en orientation"); bonus -= 5; } break; case 'perception': if (attributeAsBool(personnage, 'foretVivanteEnnemie')) { - expliquer("Forêt hostile : -5 en perception"); + expliquer("For\xEAt hostile : -5 en perception"); bonus -= 5; } if (compagnonPresent(personnage, 'guetteur')) { @@ -5965,9 +6005,10 @@ var COFantasy = COFantasy || function() { } break; case 'persuasion': + case 'convaincre': bonus += bonusArgumentDeTaille(personnage, expliquer); if (predicateAsBool(personnage, 'ordreDuChevalierDragon') && attributeAsBool(personnage, 'monteSur')) { - expliquer("Chevalier Dragon monté : +5 en persuasion"); + expliquer("Chevalier Dragon mont\xE9 : +5 en persuasion"); bonus += 5; } bonus += bonusInteractionsSociales(personnage, expliquer); @@ -5978,25 +6019,25 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'graceFelineVoleur')) { let bonusGraceFeline = modCarac(personnage, 'charisme'); if (bonusGraceFeline > 0) { - expliquer("Grâce féline : +" + bonusGraceFeline + " en saut"); + expliquer("Gr\xE2ce f\xE9line : +" + bonusGraceFeline + " en saut"); bonus += bonusGraceFeline; } } let a = predicateAsInt(personnage, 'ameFeline', 0); if (a > 0) { - expliquer("Âme féline : +" + a + " en saut"); + expliquer("\xC2me f\xE9line : +" + a + " en saut"); bonus += a; } a = predicateAsInt(personnage, 'vitesseDuFelin', 0); if (a > 0) { - expliquer("Vitesse du félin : +" + a + " en saut"); + expliquer("Vitesse du f\xE9lin : +" + a + " en saut"); bonus += a; } break; } case 'survie': if (attributeAsBool(personnage, 'foretVivanteEnnemie')) { - expliquer("Forêt hostile : -5 en survie"); + expliquer("For\xEAt hostile : -5 en survie"); bonus -= 5; } break; @@ -6024,7 +6065,7 @@ var COFantasy = COFantasy || function() { let bonusChantDesHeros = getIntValeurOfEffet(personnage, 'chantDesHeros', 1); let chantDesHerosIntense = attributeAsInt(personnage, 'chantDesHerosTempeteDeManaIntense', 0); bonusChantDesHeros += chantDesHerosIntense; - expliquer("Chant des héros : +" + bonusChantDesHeros + " au jet"); + expliquer("Chant des h\xE9ros : +" + bonusChantDesHeros + " au jet"); bonus += bonusChantDesHeros; if (chantDesHerosIntense && evt) removeTokenAttr(personnage, 'chantDesHerosTempeteDeManaIntense', evt); @@ -6033,7 +6074,7 @@ var COFantasy = COFantasy || function() { let bonusBenediction = getIntValeurOfEffet(personnage, 'benediction', 1); let benedictionIntense = attributeAsInt(personnage, 'benedictionTempeteDeManaIntense', 0); bonusBenediction += benedictionIntense; - expliquer("Bénédiction : +" + bonusBenediction + " au jet"); + expliquer("B\xE9n\xE9diction : +" + bonusBenediction + " au jet"); bonus += bonusBenediction; if (benedictionIntense && evt) removeTokenAttr(personnage, 'benedictionTempeteDeManaIntense', evt); @@ -6048,7 +6089,7 @@ var COFantasy = COFantasy || function() { removeTokenAttr(personnage, 'inspirationTempeteDeManaIntense', evt); } if (attributeAsBool(personnage, 'lameDeLigneePerdue')) { - expliquer("Lame de lignée perdue : -1 au jet"); + expliquer("Lame de lign\xE9e perdue : -1 au jet"); bonus -= 1; } if (attributeAsBool(personnage, 'strangulation')) { @@ -6059,7 +6100,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'nueeDInsectes')) { let malusNuee = 2 + attributeAsInt(personnage, 'nueeDInsectesTempeteDeManaIntense', 0); - expliquer("Nuée d\'insectes : -" + malusNuee + " au jet"); + expliquer("Nu\xE9e d\'insectes : -" + malusNuee + " au jet"); bonus -= malusNuee; if (malusNuee > 2 && evt) removeTokenAttr(personnage, 'nueeDInsectesTempeteDeManaIntense', evt); @@ -6067,13 +6108,13 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(personnage, 'nueeDeCriquets')) { let malusNueeCriquets = 3 + attributeAsInt(personnage, 'nueeDeCriquetsTempeteDeManaIntense', 0); - expliquer("Nuée de criquets : -" + malusNueeCriquets + " au jet"); + expliquer("Nu\xE9e de criquets : -" + malusNueeCriquets + " au jet"); bonus -= malusNueeCriquets; if (malusNueeCriquets > 3 && evt) removeTokenAttr(personnage, 'nueeDeCriquetsTempeteDeManaIntense', evt); } if (attributeAsBool(personnage, 'nueeDeScorpions')) { - expliquer("Nuée de scorpions : -3 au jet"); + expliquer("Nu\xE9e de scorpions : -3 au jet"); bonus -= 3; } if (attributeAsBool(personnage, 'etatExsangue')) { @@ -6081,12 +6122,12 @@ var COFantasy = COFantasy || function() { bonus -= 2; } if (attributeAsBool(personnage, 'putrefactionOutrTombe')) { - expliquer("Putréfié : -2 au jet"); + expliquer("Putr\xE9fi\xE9 : -2 au jet"); bonus -= 2; } let fortifie = attributeAsInt(personnage, 'fortifie', 0); if (fortifie > 0) { - expliquer("Fortifié : +3 au jet"); + expliquer("Fortifi\xE9 : +3 au jet"); bonus += 3; if (evt) { fortifie--; @@ -6101,18 +6142,18 @@ var COFantasy = COFantasy || function() { !predicateAsBool(personnage, 'porteurDuBouclierDeGrabuge') && !attributeAsBool(personnage, 'sangDeLArbreCoeur')) { let malusOndesCorruptrices = attributeAsInt(personnage, 'ondesCorruptrices', 2); - let msgOndesCorruptrices = "Nauséeu" + onGenre(personnage, "x", "se"); + let msgOndesCorruptrices = "Naus\xE9eu" + onGenre(personnage, "x", "se"); msgOndesCorruptrices += " : -" + malusOndesCorruptrices; expliquer(msgOndesCorruptrices + " aux tests"); bonus -= malusOndesCorruptrices; } if (attributeAsBool(personnage, 'fievreux')) { bonus -= 2; - expliquer("Fiévreu" + onGenre(personnage, 'x', 'se') + " : -2 aux tests"); + expliquer("Fi\xE9vreu" + onGenre(personnage, 'x', 'se') + " : -2 aux tests"); } if (attributeAsBool(personnage, 'secoue')) { bonus -= 2; - expliquer("Secoué" + eForFemale(personnage) + " : -2 aux tests"); + expliquer("Secou\xE9" + eForFemale(personnage) + " : -2 aux tests"); } let bonusCondition = attributeAsInt(personnage, 'modificateurTests', 0); if (bonusCondition != 0) { @@ -6120,7 +6161,7 @@ var COFantasy = COFantasy || function() { if (bonusCondition > 0) { expliquer("Bonus de condition : +" + bonusCondition); } else { - expliquer("Pénalité de condition : " + bonusCondition); + expliquer("P\xE9nalit\xE9 de condition : " + bonusCondition); } } if (attributeAsBool(personnage, 'sensDuDevoir')) { @@ -6152,7 +6193,7 @@ var COFantasy = COFantasy || function() { options.bonusPreds.forEach(function(pred) { let bonusPred = predicateAsInt(personnage, pred, 0); if (bonusPred !== 0) { - expliquer("Prédicat " + pred + " : " + ((bonusPred < 0) ? "-" : "+") + bonusPred); + expliquer("Pr\xE9dicat " + pred + " : " + ((bonusPred < 0) ? "-" : "+") + bonusPred); bonus += bonusPred; } }); @@ -6209,12 +6250,12 @@ var COFantasy = COFantasy || function() { } //retourne un entier - // evt n'est défini que si la caractéristique est effectivement utilisée + // evt n'est d\xE9fini que si la caract\xE9ristique est effectivement utilis\xE9e function bonusTestCarac(carac, personnage, options, testId, evt, explications) { const expliquer = function(msg) { if (explications) explications.push(msg); }; - // D'abord la partie qui dépend de la caractéristique + // D'abord la partie qui d\xE9pend de la caract\xE9ristique let bonus = modCarac(personnage, caracOfMod(carac)); if (!persoEstPNJ(personnage)) { bonus += ficheAttributeAsInt(personnage, carac + "_BONUS", 0); @@ -6238,11 +6279,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'aspectDuDemon')) { bonusAspectDuDemon = getIntValeurOfEffet(personnage, 'aspectDuDemon', 2); - expliquer("Aspect du démon : +" + bonusAspectDuDemon + " au jet de DEX"); + expliquer("Aspect du d\xE9mon : +" + bonusAspectDuDemon + " au jet de DEX"); bonus += bonusAspectDuDemon; } if (attributeAsBool(personnage, 'osBrises')) { - expliquer("Des os sont brisés : -2 au jet de DEX"); + expliquer("Des os sont bris\xE9s : -2 au jet de DEX"); bonus -= 2; } if (attributeAsBool(personnage, 'espaceExigu')) { @@ -6255,19 +6296,19 @@ var COFantasy = COFantasy || function() { bonus -= 1; } if (attributeAsBool(personnage, 'reactionAllergique')) { - expliquer("Démangeaisons : -2 au jet de DEX"); + expliquer("D\xE9mangeaisons : -2 au jet de DEX"); bonus -= 2; } let conditions = attributeAsInt(personnage, 'conditionsHostiles', 0, 2); if (conditions > 0 && (!predicateAsBool(personnage, 'marcheSylvestre') || conditions > 4)) { let msgConditions = "Conditions "; if (conditions < 5) msgConditions += "hostiles"; - else msgConditions += "extrêmes"; + else msgConditions += "extr\xEAmes"; msgConditions += " : -" + conditions + " au jet de DEX"; expliquer(msgConditions); bonus -= conditions; } - if (expertiseSpecialisee == 'dex' || expertiseSpecialisee == 'dexterite' || expertiseSpecialisee == 'dextérité') { + if (expertiseSpecialisee == 'dex' || expertiseSpecialisee == 'dexterite' || expertiseSpecialisee == 'dext\xE9rit\xE9') { expliquer("Expertise : +5 aux jets de DEX"); bonus += 5; } @@ -6286,11 +6327,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'aspectDuDemon')) { bonusAspectDuDemon = getIntValeurOfEffet(personnage, 'aspectDuDemon', 2); - expliquer("Aspect du démon : +" + bonusAspectDuDemon + " au jet de FOR"); + expliquer("Aspect du d\xE9mon : +" + bonusAspectDuDemon + " au jet de FOR"); bonus += bonusAspectDuDemon; } if (attributeAsBool(personnage, 'osBrises')) { - expliquer("Des os sont brisés : -2 au jet de FOR"); + expliquer("Des os sont bris\xE9s : -2 au jet de FOR"); bonus -= 2; } if (attributeAsBool(personnage, 'espaceExigu')) { @@ -6311,7 +6352,7 @@ var COFantasy = COFantasy || function() { bonusInt += ficheAttributeAsInt(personnage, "INT_BONUS", 0); } if (bonusInt > bonusCarac) { - let msgGrosseTete = "Grosse tête : "; + let msgGrosseTete = "Grosse t\xEAte : "; if (bonusInt > 0) msgGrosseTete += '+'; msgGrosseTete += bonusInt + " au lieu de "; if (bonusCarac > 0) msgGrosseTete += '+'; @@ -6324,7 +6365,7 @@ var COFantasy = COFantasy || function() { if (conditions > 0 && (!predicateAsBool(personnage, 'marcheSylvestre') || conditions > 4)) { let msgConditions = "Conditions "; if (conditions < 5) msgConditions += "hostiles"; - else msgConditions += "extrêmes"; + else msgConditions += "extr\xEAmes"; msgConditions += " : -" + conditions + " au jet de FOR"; expliquer(msgConditions); bonus -= conditions; @@ -6339,7 +6380,7 @@ var COFantasy = COFantasy || function() { { if (attributeAsBool(personnage, 'secretsDeLAuDela')) { bonus += 5; - expliquer("Secrets de l'au-delà : +5"); + expliquer("Secrets de l'au-del\xE0 : +5"); } if (expertiseSpecialisee == 'int' || expertiseSpecialisee == 'intelligence') { expliquer("Expertise : +5 aux jets d'INT"); @@ -6361,7 +6402,7 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'batonDesRunesMortes') && (attributeAsBool(personnage, 'runeLizura') || attributeAsBool(personnage, 'runeMitrah'))) { if (!options.competence || options.competence.trim().toLowerCase() != 'intimidation') { - expliquer("Recouvert" + eForFemale(personnage) + " de la boue noire du bâton : -10 aux tests de CHA"); + expliquer("Recouvert" + eForFemale(personnage) + " de la boue noire du b\xE2ton : -10 aux tests de CHA"); bonus -= 10; } } @@ -6380,13 +6421,13 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(personnage, 'controleDuMetabolisme')) { let mod = modCarac(personnage, 'charisme'); if (mod > 0) { - expliquer("Controle du métabolisme : +" + mod + " au jet de CON"); + expliquer("Controle du m\xE9tabolisme : +" + mod + " au jet de CON"); bonus += mod; } } if (attributeAsBool(personnage, 'aspectDuDemon')) { bonusAspectDuDemon = getIntValeurOfEffet(personnage, 'aspectDuDemon', 2); - expliquer("Aspect du démon : +" + bonusAspectDuDemon + " au jet de CON"); + expliquer("Aspect du d\xE9mon : +" + bonusAspectDuDemon + " au jet de CON"); bonus += bonusAspectDuDemon; } if (expertiseSpecialisee == 'con' || expertiseSpecialisee == 'constitution') { @@ -6435,15 +6476,13 @@ var COFantasy = COFantasy || function() { } } } else { - let msgComp = "Compétence " + options.competence + " : "; - if (bonusCompetence === 0) { - msgComp += 0; - } else { + if (bonusCompetence !== 0) { + let msgComp = "Comp\xE9tence " + options.competence + " : "; bonus += bonusCompetence; if (bonusCompetence > 0) msgComp += "+" + bonusCompetence; else msgComp += bonusCompetence; + expliquer(msgComp); } - expliquer(msgComp); let malus = fieldAsString(competenceTrouvee, 'comp_malus', ''); if (malus == 'armure') { bonus -= malusArmure(personnage, expliquer, ''); @@ -6465,7 +6504,7 @@ var COFantasy = COFantasy || function() { // Puis la partie commune options = options || {}; bonus += bonusTestToutesCaracs(personnage, options, testId, evt, expliquer); - //Pas besoin de mettre la valeur de caractéristique si c'est le seul bonus + //Pas besoin de mettre la valeur de caract\xE9ristique si c'est le seul bonus if (explications && explications.length == 1) explications.pop(); return bonus; } @@ -6527,7 +6566,7 @@ var COFantasy = COFantasy || function() { fct = tremblementDeTerre; break; default: - error("Impossible de trouver la fonction liée à l'effet " + e, ev); + error("Impossible de trouver la fonction li\xE9e \xE0 l'effet " + e, ev); return; } } @@ -6543,34 +6582,34 @@ var COFantasy = COFantasy || function() { let pl = getPlayerIds(perso); if (pl === undefined) return; let playerId; - if (pl.length > 0) playerId = pl[0]; //Utilisé juste pour la couleur + if (pl.length > 0) playerId = pl[0]; //Utilis\xE9 juste pour la couleur let display = startFramedDisplay(playerId, titre, perso, { chuchote: 'GM' }); switch (d6.val) { case 1: { - let commande = '!cof-dmg 4d6 --psave DEX 15 --titre Éboulement majeur'; - addLineToFramedDisplay(display, "Éboulement majeur : sélectionnez les tokens dans la zone et " + boutonSimple(commande, 'cliquez ici')); + let commande = '!cof-dmg 4d6 --psave DEX 15 --titre \xC9boulement majeur'; + addLineToFramedDisplay(display, "\xC9boulement majeur : s\xE9lectionnez les tokens dans la zone et " + boutonSimple(commande, 'cliquez ici')); break; } case 2: case 3: { - let commande = '!cof-dmg 2d6 --psave DEX 15 --titre Éboulement mineur'; - addLineToFramedDisplay(display, "Éboulement mineur : choisissez un personnage au hasard et " + boutonSimple(commande, 'cliquez ici')); + let commande = '!cof-dmg 2d6 --psave DEX 15 --titre \xC9boulement mineur'; + addLineToFramedDisplay(display, "\xC9boulement mineur : choisissez un personnage au hasard et " + boutonSimple(commande, 'cliquez ici')); break; } case 6: { let commande = '!cof-set-state renverse true --save DEX 12'; - addLineToFramedDisplay(display, "Le sol tremble et se fissure : sélectionnez les personnages dans une zone d'environ 10 mètres et " + boutonSimple(commande, 'cliquez ici')); + addLineToFramedDisplay(display, "Le sol tremble et se fissure : s\xE9lectionnez les personnages dans une zone d'environ 10 m\xE8tres et " + boutonSimple(commande, 'cliquez ici')); break; } default: // 4 ou 5 { let commande = '!cof-effet-temp tremblementMineur 1'; - addLineToFramedDisplay(display, "Tremblement mineur : sélectionnez les personnages dans la zone et " + boutonSimple(commande, 'cliquez ici')); + addLineToFramedDisplay(display, "Tremblement mineur : s\xE9lectionnez les personnages dans la zone et " + boutonSimple(commande, 'cliquez ici')); break; } } @@ -6585,14 +6624,14 @@ var COFantasy = COFantasy || function() { let pl = getPlayerIds(perso); if (pl === undefined) return; let playerId; - if (pl.length > 0) playerId = pl[0]; //Utilisé juste pour la couleur + if (pl.length > 0) playerId = pl[0]; //Utilis\xE9 juste pour la couleur let display = startFramedDisplay(playerId, titre, perso); let explications = []; let np = nomPerso(perso); switch (d6.val) { case 1: { - addLineToFramedDisplay(display, np + " est frappé" + eForFemale(perso) + " de plein fouet !"); + addLineToFramedDisplay(display, np + " est frapp\xE9" + eForFemale(perso) + " de plein fouet !"); let options = { partialSave: { carac: 'DEX', @@ -6624,7 +6663,7 @@ var COFantasy = COFantasy || function() { dmg.display = buildinline(dmg.roll.inlinerolls[dmgRollNumber], dmg.type); dealDamage(perso, dmg, [], evt, false, options, explications, function(dmgDisplay, dmgFinal) { addLineToFramedDisplay(display, - np + " reçoit " + dmgDisplay + " DM"); + np + " re\xE7oit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); @@ -6642,7 +6681,7 @@ var COFantasy = COFantasy || function() { save: { carac: 'FOR', seuil: 10, - msgPour: "pour ne pas être tomber" + msgPour: "pour ne pas \xEAtre tomber" } }; let evt = { @@ -6658,7 +6697,7 @@ var COFantasy = COFantasy || function() { addEvent(evt); let saveOpts = { msgPour: options.msgPour, - msgRate: ", raté.", + msgRate: ", rat\xE9.", }; let expliquer = function(s) { explications.push(s); @@ -6671,7 +6710,7 @@ var COFantasy = COFantasy || function() { textDist = distance.val / 2; seuil = 2; } - textDist += distance.val > seuil ? ' mètres' : ' mètre'; + textDist += distance.val > seuil ? ' m\xE8tres' : ' m\xE8tre'; sendChat('', '[[2d6]]', function(resDmg) { let afterEvaluateDmg = resDmg[0].content.split(' '); let dmgRollNumber = rollNumber(afterEvaluateDmg[0]); @@ -6681,12 +6720,12 @@ var COFantasy = COFantasy || function() { type: 'electrique' }; dealDamage(perso, dmg, [], evt, false, options, explications, function(dmgDisplay, dmgFinal) { - addLineToFramedDisplay(display, np + " est projeté" + eForFemale(perso) + " de " + textDist + " par la foudre, et subit " + dmgDisplay + " DM"); + addLineToFramedDisplay(display, np + " est projet\xE9" + eForFemale(perso) + " de " + textDist + " par la foudre, et subit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); if (reussite) { - addLineToFramedDisplay(display, np + " résiste, la distance de projection passe de " + distance.roll + " à " + (distance.val / 2)); + addLineToFramedDisplay(display, np + " r\xE9siste, la distance de projection passe de " + distance.roll + " \xE0 " + (distance.val / 2)); } else { setState(perso, 'renverse', true, evt); } @@ -6707,7 +6746,7 @@ var COFantasy = COFantasy || function() { save: { carac: 'CON', seuil: 10, - msgPour: ' pour ne pas être affaibli' + eForFemale(perso) + msgPour: ' pour ne pas \xEAtre affaibli' + eForFemale(perso) } }; const evt = { @@ -6735,17 +6774,17 @@ var COFantasy = COFantasy || function() { return ficheAttributeAsInt(perso, 'pc', 3); } - // Test de caractéristique + // Test de caract\xE9ristique // options : bonusAttrs, bonusPreds, bonus, roll - // Après le test, lance callback(testRes, explications - // testRes.texte est l'affichage du jet de dé - // testRes.reussite indique si le jet est réussi + // Apr\xE8s le test, lance callback(testRes, explications + // testRes.texte est l'affichage du jet de d\xE9 + // testRes.reussite indique si le jet est r\xE9ussi // testRes.echecCritique, testRes.critique pour le type // testRes.valeur pour la valeur totale du jet - // testRes.rerolls pour le texte avec les boutons de rerolls adaptés. - // testRes.modifiers pour les boutons qui peuvent être activés sur le roll, qu'il soit réussi ou non. - // Pour que les boutons de rerolls fonctionnent, le type d'évènement doit être supporté par redoEvent() - // ne rajoute pas evt à l'historique + // testRes.rerolls pour le texte avec les boutons de rerolls adapt\xE9s. + // testRes.modifiers pour les boutons qui peuvent \xEAtre activ\xE9s sur le roll, qu'il soit r\xE9ussi ou non. + // Pour que les boutons de rerolls fonctionnent, le type d'\xE9v\xE8nement doit \xEAtre support\xE9 par redoEvent() + // ne rajoute pas evt \xE0 l'historique function testCaracteristique(personnage, carac, seuil, testId, options, evt, callback) { //asynchrone options = options || {}; let testRes = {}; @@ -6849,10 +6888,10 @@ var COFantasy = COFantasy || function() { boutonSimple("!cof-bouton-chance " + evt.id + " " + testId, "Chance") + " (reste " + pc + " PC)"; } - if (stateCOF.combat && attributeAsBool(personnage, 'runeForgesort_énergie') && - attributeAsInt(personnage, 'limiteParCombat_runeForgesort_énergie', 1) > 0 && + if (stateCOF.combat && attributeAsBool(personnage, 'runeForgesort_\xE9nergie') && + attributeAsInt(personnage, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0 && (carac == 'FOR' || carac == 'CON' || carac == 'DEX')) { - testRes.rerolls += '
    ' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'énergie"); + testRes.rerolls += '
    ' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'\xE9nergie"); } if (stateCOF.combat && capaciteDisponible(personnage, 'petitVeinard', 'combat')) { testRes.rerolls += '
    ' + boutonSimple("!cof-bouton-petit-veinard " + evt.id + " " + testId, "Petit veinard"); @@ -6873,18 +6912,18 @@ var COFantasy = COFantasy || function() { testRes.modifiers += "
    " + boutonSimple("!cof-pacte-sanglant " + evt.id + " 5 " + testId, "Pacte sanglant (+5)"); } } - if (jetCache) sendChat('COF', "/w GM Jet caché : " + buildinline(roll) + bonusText); + if (jetCache) sendChat('COF', "/w GM Jet cach\xE9 : " + buildinline(roll) + bonusText); callback(testRes, explications); }); } catch (e) { - error("Erreur pendant l'évaluation de " + rollExpr + " dans un test de caractéristiques"); + error("Erreur pendant l'\xE9valuation de " + rollExpr + " dans un test de caract\xE9ristiques"); log(e.name + ": " + e.message); } } //callback peut prendre en argument une structure avec les champs: // - texte: Le texte du jet - // - total : Le résultat total du jet + // - total : Le r\xE9sultat total du jet // - echecCritique, critique pour indiquer si 1 ou 20 // - roll: le inlineroll function jetCaracteristique(personnage, carac, options, testId, evt, callback) { @@ -6925,15 +6964,15 @@ var COFantasy = COFantasy || function() { total: d20roll + bonusCarac, }; if (d20roll <= plageEC) { - rtext += " -> échec critique"; + rtext += " -> \xE9chec critique"; rt.echecCritique = true; } else if (d20roll == 20) { - rtext += " -> réussite critique"; + rtext += " -> r\xE9ussite critique"; rt.critique = true; } else if (bonusCarac !== 0 && !jetCache) rtext += " = " + rt.total; rt.texte = rtext; rt.roll = roll; - if (jetCache) sendChat('COF', "/w GM Jet caché de caractéristique : " + buildinline(roll) + bonusText); + if (jetCache) sendChat('COF', "/w GM Jet cach\xE9 de caract\xE9ristique : " + buildinline(roll) + bonusText); callback(rt, explications); }); } @@ -6986,7 +7025,7 @@ var COFantasy = COFantasy || function() { let dest = joueurJ.get('displayname'); if (dest.includes('"')) { sendChat('COF', display.action); - log("Impossible d'envoyer des messages privés à " + dest + " car le nom contient des guillemets"); + log("Impossible d'envoyer des messages priv\xE9s \xE0 " + dest + " car le nom contient des guillemets"); } sendChat('COF', '/w "' + dest + '" ' + display.action); } @@ -7024,12 +7063,12 @@ var COFantasy = COFantasy || function() { if (difficulte === undefined) { jetCaracteristique(perso, caracteristique, options, testId, evt, function(rt, explications) { - addLineToFramedDisplay(display, "Résultat : " + rt.texte); + addLineToFramedDisplay(display, "R\xE9sultat : " + rt.texte); explications.forEach(function(m) { addLineToFramedDisplay(display, m, 80); }); addStatistics(playerId, ["Jet de carac", caracteristique], rt.roll); - // Maintenant, on diminue la malédiction si le test est un échec + // Maintenant, on diminue la mal\xE9diction si le test est un \xE9chec let attrMalediction = tokenAttribute(perso, 'malediction'); if (attrMalediction.length > 0) { if (rt.echecCritique) @@ -7037,8 +7076,8 @@ var COFantasy = COFantasy || function() { else if (!rt.critique) { let action = "!cof-resultat-jet " + evt.id; let ligne = "L'action est-elle "; - ligne += bouton(action + " reussi", "réussie", perso); - ligne += " ou " + bouton(action + " rate", "ratée", perso); + ligne += bouton(action + " reussi", "r\xE9ussie", perso); + ligne += " ou " + bouton(action + " rate", "rat\xE9e", perso); ligne += " ?"; addLineToFramedDisplay(display, ligne); evt.attenteResultat = true; @@ -7051,10 +7090,10 @@ var COFantasy = COFantasy || function() { '
    ' + boutonSimple("!cof-bouton-chance " + evt.id + " " + testId, "Chance") + " (reste " + pc + " PC)"; } - if (stateCOF.combat && attributeAsBool(perso, 'runeForgesort_énergie') && - attributeAsInt(perso, 'limiteParCombat_runeForgesort_énergie', 1) > 0 && + if (stateCOF.combat && attributeAsBool(perso, 'runeForgesort_\xE9nergie') && + attributeAsInt(perso, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0 && (caracteristique == 'FOR' || caracteristique == 'CON' || caracteristique == 'DEX')) { - boutonsReroll += '
    ' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'énergie"); + boutonsReroll += '
    ' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'\xE9nergie"); } if (stateCOF.combat && capaciteDisponible(perso, 'petitVeinard', 'combat')) { boutonsReroll += '
    ' + boutonSimple("!cof-bouton-petit-veinard " + evt.id + " " + testId, "Petit veinard"); @@ -7080,15 +7119,15 @@ var COFantasy = COFantasy || function() { } else { testCaracteristique(perso, caracteristique, difficulte, testId, options, evt, function(tr, explications) { - addLineToFramedDisplay(display, "Résultat : " + tr.texte); + addLineToFramedDisplay(display, "R\xE9sultat : " + tr.texte); explications.forEach(function(m) { addLineToFramedDisplay(display, m, 80); }); if (tr.reussite) { - let msgReussite = options.messageSiSucces || "C'est réussi."; + let msgReussite = options.messageSiSucces || "C'est r\xE9ussi."; addLineToFramedDisplay(display, msgReussite + tr.modifiers); } else { - let msgRate = "C'est raté." + tr.rerolls + tr.modifiers; + let msgRate = "C'est rat\xE9." + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, msgRate); } sendDisplayJetPerso(display, playerId, options); @@ -7101,8 +7140,8 @@ var COFantasy = COFantasy || function() { function boutonsCompetences(display, perso, carac, msg, fond) { let action = msg.content; action = action.replace(/ --competences /, ''); - action = action.replace(/ --competences/, ''); //au cas où ce serait le dernier argument - let args = action.substring(9); //on enlève !cof-jet + action = action.replace(/ --competences/, ''); //au cas o\xF9 ce serait le dernier argument + let args = action.substring(9); //on enl\xE8ve !cof-jet if (!args.startsWith(carac)) action = "!cof-jet " + carac + " " + args; let overlay; switch (carac) { @@ -7110,7 +7149,7 @@ var COFantasy = COFantasy || function() { overlay = 'Force'; break; case 'DEX': - overlay = 'Dextérité'; + overlay = 'Dext\xE9rit\xE9'; break; case 'CON': overlay = 'Constitution'; @@ -7157,8 +7196,8 @@ var COFantasy = COFantasy || function() { addCellInFramedDisplay(display, cell, 80, false, fond); } - // prend une distance en mètre et retourne une distance dans l'unité - // utilisée sur la page du personnage + // prend une distance en m\xE8tre et retourne une distance dans l'unit\xE9 + // utilis\xE9e sur la page du personnage function scaleDistance(perso, distance) { if (perso.scale) return distance * perso.scale; let pageId = perso.pageId; @@ -7192,7 +7231,7 @@ var COFantasy = COFantasy || function() { perso.scale = 39.3701; break; default: - sendChat('COF', "Attention, unité de mesure de la page (" + unit + ") non reconnue"); + sendChat('COF', "Attention, unit\xE9 de mesure de la page (" + unit + ") non reconnue"); perso.scale = 1; } return distance * perso.scale; @@ -7214,9 +7253,9 @@ var COFantasy = COFantasy || function() { return pageId; } - // si défini, callback est appelé à chaque élément de selected + // si d\xE9fini, callback est appel\xE9 \xE0 chaque \xE9l\xE9ment de selected // qui n'est pas un personnage - // iter seulement sur les élément qui correspondent à des personnages + // iter seulement sur les \xE9l\xE9ment qui correspondent \xE0 des personnages function iterSelected(selected, iter, callback) { selected.forEach(function(sel) { let token = getObj('graphic', sel._id); @@ -7253,9 +7292,9 @@ var COFantasy = COFantasy || function() { return true; } - //traduction des coordonées de path en coordonées réelles sur la carte + //traduction des coordon\xE9es de path en coordon\xE9es r\xE9elles sur la carte function translatePathCoordinates(x, y, p) { - //D'abord on calcule les coordonnées relatives au centre + //D'abord on calcule les coordonn\xE9es relatives au centre x -= p.width / 2; y -= p.height / 2; //Puis on applique le scale @@ -7266,7 +7305,7 @@ var COFantasy = COFantasy || function() { let s = Math.sin(p.angle); x = c * x + s * y; y = c * y - s * x; - //Et finalement on ajoute les coordonnées du centre + //Et finalement on ajoute les coordonn\xE9es du centre x += p.left; y += p.top; return { @@ -7301,7 +7340,7 @@ var COFantasy = COFantasy || function() { }); return chemin; }); - //On rajoute les portes fermées. + //On rajoute les portes ferm\xE9es. let doors = findObjs({ _type: 'door', _pageid: pageId, @@ -7323,7 +7362,7 @@ var COFantasy = COFantasy || function() { return murs; } - //vérifie si de la nouvelle position on peut voir le suivi + //v\xE9rifie si de la nouvelle position on peut voir le suivi function obstaclePresent(nsx, nsy, pt, murs) { if (nsx == pt.x && nsy == pt.y) return false; let ps = { @@ -7442,7 +7481,7 @@ var COFantasy = COFantasy || function() { if (saufAllies) allies = (new Set(allies)).add(actif.charId); } else { if (msg.selected === undefined || msg.selected.length === 0) { - error("Pas d'allié car pas de token sélectionné", msg); + error("Pas d'alli\xE9 car pas de token s\xE9lectionn\xE9", msg); return; } iterSelected(msg.selected, function(personnage) { @@ -7471,7 +7510,7 @@ var COFantasy = COFantasy || function() { let ci = tok.get('represents'); if (ci === '') return; if (!allies.has(ci)) return; - //On enlève le token actif, mais seulement pour allies + //On enl\xE8ve le token actif, mais seulement pour allies if (cmdSplit[0] == 'allies') { if (actives.indexOf(function(perso) { return perso.charId == ci; @@ -7502,7 +7541,7 @@ var COFantasy = COFantasy || function() { return; case 'target': if (cmdSplit.length < 2) { - error("Il manque l'id de la cible (après --target)", cmd); + error("Il manque l'id de la cible (apr\xE8s --target)", cmd); return; } selected.push({ @@ -7512,50 +7551,57 @@ var COFantasy = COFantasy || function() { case 'disque': case 'disquePasseMur': if (options.ignoreDisque) return; - let centre; + let tokenCentre; let rayon; if (cmdSplit.length < 3) { if (actif && cmdSplit.length > 1) { - centre = actif; + tokenCentre = actif.token; rayon = parseInt(cmdSplit[1]); } else { - error("Pas assez d'arguments pour définir un disque", cmdSplit); + error("Pas assez d'arguments pour d\xE9finir un disque", cmdSplit); return; } } else { - centre = persoOfId(cmdSplit[1], cmdSplit[1], pageId); - if (centre === undefined) { - error("le premier argument du disque n'est pas un token valide", cmdSplit); - return; + tokenCentre = getObj('graphic', cmdSplit[1]); + if (!tokenCentre) { + let centre = persoOfId(cmdSplit[1], cmdSplit[1], pageId); + if (centre === undefined) { + error("le premier argument du disque n'est pas un token valide", cmdSplit); + return; + } + tokenCentre = centre.token; } + pageId = tokenCentre.get('pageid'); rayon = parseInt(cmdSplit[2]); } if (isNaN(rayon) || rayon < 0) { - error("Rayon du disque mal défini", cmdSplit); + error("Rayon du disque mal d\xE9fini", cmdSplit); return; } - let tokenCentre = centre.token; let portee = 0; if (cmdSplit.length > 3) { portee = parseInt(cmdSplit[3]); if (isNaN(portee) || portee < 0) { - error("La portée du disque est mal formée", cmdSplit); + error("La port\xE9e du disque est mal form\xE9e", cmdSplit); return; } if (actif === undefined) { - error("Pas de token sélectionné pour calculer la distance du disque", msg); + error("Pas de token s\xE9lectionn\xE9 pour calculer la distance du disque", msg); return; } if (distanceCombat(tokenCentre, actif.token, pageId, { strict1: true }) > portee) { - sendPerso(actif, "Le centre de l'effet est placé trop loin (portée " + portee + " m)"); + sendPerso(actif, "Le centre de l'effet est plac\xE9 trop loin (port\xE9e " + portee + " m)"); return; } } aoe = aoe || {}; aoe.type = 'disque'; - aoe.centre = tokenCentre; + aoe.centre = { + left: tokenCentre.get('left'), + top: tokenCentre.get('top') + }; aoe.rayon = rayon; page = page || getObj("page", pageId); if (cmdSplit[0] == 'disque') @@ -7575,7 +7621,7 @@ var COFantasy = COFantasy || function() { layer: 'objects' }); allToksDisque.forEach(function(obj) { - if (actif && portee === 0 && obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-même + if (actif && portee === 0 && obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-m\xEAme let objCharId = obj.get('represents'); if (objCharId === '') return; if (getState({ @@ -7600,8 +7646,8 @@ var COFantasy = COFantasy || function() { spawnFx(tokenCentre.get('left'), tokenCentre.get('top'), options.targetFx, pageId); } if (tokenCentre.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir le disque - tokenCentre.remove(); //On l'enlève, normalement plus besoin + //C'est juste un token utilis\xE9 pour d\xE9finir le disque + tokenCentre.remove(); //On l'enl\xE8ve, normalement plus besoin delete options.targetFx; } return; @@ -7611,7 +7657,7 @@ var COFantasy = COFantasy || function() { observateur = persoOfId(cmdSplit[1], cmdSplit[1], pageId); } if (observateur === undefined) { - error("Impossible de trouver la personne à partir de laquelle on sélectionne les tokens en vue", msg); + error("Impossible de trouver la personne \xE0 partir de laquelle on s\xE9lectionne les tokens en vue", msg); return; } page = page || getObj("page", pageId); @@ -7629,7 +7675,7 @@ var COFantasy = COFantasy || function() { layer: 'objects' }); tokensEnVue.forEach(function(obj) { - if (actif && obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-même + if (actif && obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-m\xEAme let objCharId = obj.get('represents'); if (objCharId === '') return; if (obj.get('bar1_max') == 0) return; // jshint ignore:line @@ -7645,12 +7691,12 @@ var COFantasy = COFantasy || function() { return; case 'alliesEnVue': if (actif === undefined) { - error("Impossible de trouver la personne dont on sélectionne les lliés en vue", msg); + error("Impossible de trouver la personne dont on s\xE9lectionne les lli\xE9s en vue", msg); return; } let alliesEnVue = alliesParPerso[actif.charId]; if (alliesEnVue === undefined) { - log("Personnage sans allié", actif); + log("Personnage sans alli\xE9", actif); return; } page = page || getObj("page", pageId); @@ -7668,7 +7714,7 @@ var COFantasy = COFantasy || function() { layer: 'objects' }); tokensAlliesEnVue.forEach(function(obj) { - if (obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-même + if (obj.id == actif.token.id) return; //on ne se cible pas si le centre de l'aoe est soi-m\xEAme let objCharId = obj.get('represents'); if (objCharId === '') return; if (!alliesEnVue.has(objCharId)) return; @@ -7708,7 +7754,7 @@ var COFantasy = COFantasy || function() { } } - //msg peut être directement le playerId ou un message + //msg peut \xEAtre directement le playerId ou un message function getPlayerIdFromMsg(msg) { if (msg.playerid === undefined) return msg; let playerId = msg.playerid; @@ -7727,7 +7773,7 @@ var COFantasy = COFantasy || function() { name: nom }); if (characters.length === 0) { - error("Impossible de trouver l'id du joueur " + nom, msg); + //error("Impossible de trouver l'id du joueur " + nom, msg); return playerId; } let pids = characters[0].get('controlledby'); @@ -7745,7 +7791,7 @@ var COFantasy = COFantasy || function() { //!cof-jet [carac] [difficulte] // - carac : FOR, DEX, CON, INT, SAG, CHA - // Les tokens sélectionnés sont ceux qui doivent faire le jet + // Les tokens s\xE9lectionn\xE9s sont ceux qui doivent faire le jet function jet(msg) { let opts = msg.content.split(' --'); let cmd = opts.shift().split(' '); @@ -7758,13 +7804,13 @@ var COFantasy = COFantasy || function() { switch (args[0]) { case 'nom': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } args.shift(); let nom = args.join(' '); if (options.nom && options.nom != nom) { - error("Nom du jet défini deux fois !", options.nom); + error("Nom du jet d\xE9fini deux fois !", options.nom); } options.nom = nom; if (options.competence) { @@ -7774,26 +7820,26 @@ var COFantasy = COFantasy || function() { return; case 'attribut': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } options.bonusAttrs.push(args[1]); return; case 'predicat': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } options.bonusPreds.push(args[1]); return; case 'bonus': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } let bonus = parseInt(args[1]); if (isNaN(bonus)) { - error("Le bonus doit être un nombre", opts); + error("Le bonus doit \xEAtre un nombre", opts); return; } options.bonus = (options.bonus || 0) + bonus; @@ -7804,12 +7850,12 @@ var COFantasy = COFantasy || function() { return; case 'plageEchecCritique': if (args.length < 2) { - error("Il manque un argument à l'option " + args[0], opts); + error("Il manque un argument \xE0 l'option " + args[0], opts); return; } let plageEC = parseInt(args[1]); if (isNaN(plageEC) || plageEC < 0 || plageEC > 19) { - error("La plage d'échecs critqiques doit être un nombre positif inférieur à 19", opts); + error("La plage d'\xE9checs critqiques doit \xEAtre un nombre positif inf\xE9rieur \xE0 19", opts); return; } options.plageEchecCritique = plageEC; @@ -7821,17 +7867,17 @@ var COFantasy = COFantasy || function() { }); getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Utilisation de !cof-jet sans sélection de token", playerId); + sendPlayer(msg, "Utilisation de !cof-jet sans s\xE9lection de token", playerId); return; } - if (cmd.length < 2) { //On demande la carac et la compétence, si définies dans un handout Compétence + if (cmd.length < 2) { //On demande la carac et la comp\xE9tence, si d\xE9finies dans un handout Comp\xE9tence if (options.nom) { - error("Il manque la caractéristique à utiliser pour la compétence " + options.nom, msg.content); + error("Il manque la caract\xE9ristique \xE0 utiliser pour la comp\xE9tence " + options.nom, msg.content); return; } let fond = listeCompetences.nombre > 25; iterSelected(selected, function(perso) { - let display = startFramedDisplay(playerId, "Jet de caractéristique", perso, { + let display = startFramedDisplay(playerId, "Jet de caract\xE9ristique", perso, { chuchote: true }); startTableInFramedDisplay(display); @@ -7856,7 +7902,7 @@ var COFantasy = COFantasy || function() { let display = startFramedDisplay(playerId, "Jet " + deCarac(caracteristique), perso, { chuchote: true }); - addLineToFramedDisplay(display, "Choisissez la compétence"); + addLineToFramedDisplay(display, "Choisissez la comp\xE9tence"); startTableInFramedDisplay(display); boutonsCompetences(display, perso, caracteristique, msg); endTableInFramedDisplay(display); @@ -7895,7 +7941,7 @@ var COFantasy = COFantasy || function() { } if (options.bonus) titre += " (" + ((options.bonus > 0) ? '+' : '') + options.bonus + ")"; - if (difficulte !== undefined) titre += " difficulté " + difficulte; + if (difficulte !== undefined) titre += " difficult\xE9 " + difficulte; iterSelected(selected, function(perso) { jetPerso(perso, caracteristique, difficulte, titre, playerId, options); }); //fin de iterSelected @@ -7910,7 +7956,7 @@ var COFantasy = COFantasy || function() { } const evt = findEvent(args[1]); if (evt === undefined) { - error("Le jet est trop ancien ou éte annulé", args); + error("Le jet est trop ancien ou \xE9te annul\xE9", args); return; } if (evt.personnage === undefined) { @@ -7921,12 +7967,12 @@ var COFantasy = COFantasy || function() { let message = evt.type + " "; if (args[2] == 'rate') { diminueMalediction(evt.personnage, evt); - message += "raté."; - } else message += "réussi."; + message += "rat\xE9."; + } else message += "r\xE9ussi."; sendPerso(evt.personnage, message); delete evt.attenteResultat; } else { - sendPlayer(msg, "Résultat déjà décidé"); + sendPlayer(msg, "R\xE9sultat d\xE9j\xE0 d\xE9cid\xE9"); } } @@ -7946,7 +7992,7 @@ var COFantasy = COFantasy || function() { function optionsDeTempeteDeMana(msg) { if (tempeteDeManaCourante.vide) { - error("Pas de tempête de mana en cours", tempeteDeManaCourante); + error("Pas de temp\xEAte de mana en cours", tempeteDeManaCourante); return; } let perso = tempeteDeManaCourante.perso; @@ -7996,7 +8042,7 @@ var COFantasy = COFantasy || function() { tempeteDeManaCourante.intense = it; } } - let title = "Tempête de mana"; + let title = "Temp\xEAte de mana"; if (tempeteDeManaCourante.cout) { title += " de puissance " + tempeteDeManaCourante.cout; } @@ -8011,14 +8057,14 @@ var COFantasy = COFantasy || function() { if (tempeteDeManaCourante.dureeDeBase && tempeteDeManaCourante.dm === undefined && tempeteDeManaCourante.soins === undefined) - ajouterOptionTempete(display, "duree", "Durée", restant); + ajouterOptionTempete(display, "duree", "Dur\xE9e", restant); if (tempeteDeManaCourante.porteeDeBase) - ajouterOptionTempete(display, "portee", "Portée", restant); + ajouterOptionTempete(display, "portee", "Port\xE9e", restant); ajouterOptionTempete(display, "rapide", "Rapide", restant); if (tempeteDeManaCourante.altruistePossible) { let la = 'Magie altruiste : '; if (restant || tempeteDeManaCourante.altruiste) { - let tla = "Sélectionner"; + let tla = "S\xE9lectionner"; if (tempeteDeManaCourante.altruiste) { tla = nomPerso(tempeteDeManaCourante.altruiste); } @@ -8077,7 +8123,7 @@ var COFantasy = COFantasy || function() { if (max === undefined || max > niveau - (mana / cout_par_effet)) max = Math.floor(niveau - (mana / cout_par_effet)); if (max < 1) { - sendPerso(perso, "ne peut pas dépenser plus de mana en tempête de mana (niveau " + niveau + ", mana déjà dépensée " + mana + ")"); + sendPerso(perso, "ne peut pas d\xE9penser plus de mana en temp\xEAte de mana (niveau " + niveau + ", mana d\xE9j\xE0 d\xE9pens\xE9e " + mana + ")"); return; } tempeteDeManaCourante.max = max; @@ -8126,7 +8172,7 @@ var COFantasy = COFantasy || function() { } else { let intensite = parseInt(ta); if (isNaN(ta) || ta <= 0) { - error("Option de tempête de mana " + ta + " non reconnue", cmd); + error("Option de temp\xEAte de mana " + ta + " non reconnue", cmd); break; } options.tempeteDeManaIntense = options.tempeteDeManaIntense || 0; @@ -8142,12 +8188,13 @@ var COFantasy = COFantasy || function() { } function parseCondition(args) { - if (args.length > 0 && (args[0] == 'crit' || args[0] == 'critique')) { - return { - type: 'critique' - }; - } + if (args.length === 0) return; switch (args[0]) { + case 'crit': + case 'critique': + return { + type: 'critique' + }; case 'etat': if (args.length < 2) { error("condition non reconnue", args); @@ -8233,7 +8280,7 @@ var COFantasy = COFantasy || function() { } case 'predicatCible': if (args.length < 2) { - error("Il manque le prédicat de la cible", args); + error("Il manque le pr\xE9dicat de la cible", args); return; } let valeur; @@ -8254,6 +8301,10 @@ var COFantasy = COFantasy || function() { race: args[1], text: args[1] }; + case 'premiereAttaque': + return { + type: 'premiereAttaque' + }; case 'deAttaque': if (args.length < 2) { error("condition non reconnue", args); @@ -8261,8 +8312,8 @@ var COFantasy = COFantasy || function() { } let valeurDeAttaque = parseInt(args[1]); if (isNaN(valeurDeAttaque)) { - error("La condition de dé d'attaque doit être un nombre", args); - // on continue exprès pour tomber dans le cas par défaut + error("La condition de d\xE9 d'attaque doit \xEAtre un nombre", args); + // on continue expr\xE8s pour tomber dans le cas par d\xE9faut } else { return { type: 'deAttaque', @@ -8290,7 +8341,7 @@ var COFantasy = COFantasy || function() { function getFx(cmd, argName, obj, funName) { if (cmd.length < 2) { - let errMsg = "Il manque un argument à l'option --" + argName; + let errMsg = "Il manque un argument \xE0 l'option --" + argName; if (funName) errMsg += " de " + funName; sendChat("COF", errMsg); return; @@ -8323,7 +8374,7 @@ var COFantasy = COFantasy || function() { dm.nbDe = parseInt(exprDM.substring(0, indexD)); if (isNaN(dm.nbDe) || dm.nbDe < 0) { if (msg) - error("Expression de " + msg + ' ' + exprDM + " mal formée", expr); + error("Expression de " + msg + ' ' + exprDM + " mal form\xE9e", expr); return; } exprDM = exprDM.substring(indexD + 1); @@ -8372,12 +8423,12 @@ var COFantasy = COFantasy || function() { } const res = parseCarac(cmd[1]); if (res === undefined) { - error("Le premier argument de save n'est pas une caractéristique", cmd); + error("Le premier argument de save n'est pas une caract\xE9ristique", cmd); return; } res.seuil = parseInt(cmd[2]); if (isNaN(res.seuil)) { - error("Le deuxième argument de --psave n'est pas un nombre", cmd); + error("Le deuxi\xE8me argument de --psave n'est pas un nombre", cmd); return; } if (cmd.length > 3) { @@ -8389,24 +8440,23 @@ var COFantasy = COFantasy || function() { case 'carac': case 'carac2': case 'seuil': - error("Argument supplémentaire de save inconnu", cmd); + error("Argument suppl\xE9mentaire de save inconnu", cmd); return; case 'tempete': let ti = 1; if (oa.length > 1) { - ti = parseInt(oa[1]); - if (isNaN(ti)) ti = 1; + ti = toInt(oa[1], 1); } res.tempete = ti; return; case 'contact': if (oa.length < 2) { - error("Il manque la difficulté pour les cibles au contact"); + error("Il manque la difficult\xE9 pour les cibles au contact"); return; } let diff = parseInt(oa[1]); if (isNaN(diff)) { - error("La difficulté pour les cibles au contact n'est pas un nombre"); + error("La difficult\xE9 pour les cibles au contact n'est pas un nombre"); return; } res.contact = diff; @@ -8419,9 +8469,33 @@ var COFantasy = COFantasy || function() { return res; } + // Pour les limites par jour, combat ou tour, + // cmd[1] est la valeur ou un pr\xE9dicat + // cmd[2] est la ressource + function parseLimite(cmd, type) { + let l = parseInt(cmd[1]); + if (isNaN(l)) { + l = { + predicat: cmd[1] + }; + } else if (l < 1) { + error("La limite " + type + " doit \xEAtre un nombre positif", cmd); + return; + } else { + l = { + val: l + }; + } + if (cmd.length > 2) { + cmd.splice(0, 2); + l.ressource = cmd.join('_'); + } + return l; + } + //juste le traitement d'une liste d'options - // lastEtat : dernier de etats et effets, pour savoir à quoi appliquer --save - // lastType : dernier type de dégâts infligés + // lastEtat : dernier de etats et effets, pour savoir \xE0 quoi appliquer --save + // lastType : dernier type de d\xE9g\xE2ts inflig\xE9s // scope : pour les conditionnelles function parseAttackOptions(attaquant, optArgs, lastEtat, lastType, scope, playerId, msg, targetToken, attackLabel, weaponStats, options) { optArgs.forEach(function(arg) { @@ -8492,7 +8566,7 @@ var COFantasy = COFantasy || function() { case 'tirDeBarrage': case 'test': case 'traquenard': - case 'tueurDeGeants': //obsolète + case 'tueurDeGeants': //obsol\xE8te case 'tueurDeGrands': case 'grenaille': case 'attaqueArmeeConjuree': @@ -8510,7 +8584,7 @@ var COFantasy = COFantasy || function() { return; case 'aussiArmeDeJet': if (cmd.length < 2) { - error("Il faut préciser l'arme associée à celle-ci pour --aussiArmeDeJet", cmd); + error("Il faut pr\xE9ciser l'arme associ\xE9e \xE0 celle-ci pour --aussiArmeDeJet", cmd); return; } options.aussiArmeDeJet = cmd[1]; @@ -8520,7 +8594,7 @@ var COFantasy = COFantasy || function() { options.avantage = options.avantage || 1; options.avantage++; return; - case 'désavantage': + case 'd\xE9savantage': case 'desavantage': options.avantage = options.avantage || 1; options.avantage--; @@ -8541,7 +8615,7 @@ var COFantasy = COFantasy || function() { case 'nom': case 'special': if (cmd.length < 1) { - error("Il manque le nom après l'option --" + cmd[0], cmd); + error("Il manque le nom apr\xE8s l'option --" + cmd[0], cmd); return; } options[cmd[0]] = cmd.slice(1).join(' ').trim(); @@ -8549,7 +8623,7 @@ var COFantasy = COFantasy || function() { case 'toucher': case 'modifiePortee': if (cmd.length < 1) { - error("Il manque la valeur après l'option --" + cmd[0], cmd); + error("Il manque la valeur apr\xE8s l'option --" + cmd[0], cmd); return; } let intArg = parseInt(cmd[1]); @@ -8561,7 +8635,7 @@ var COFantasy = COFantasy || function() { return; case 'crit': if (cmd.length < 1) { - error("Il manque la valeur après l'option --crit", cmd); + error("Il manque la valeur apr\xE8s l'option --crit", cmd); return; } let crit = parseInt(cmd[1]); @@ -8575,15 +8649,15 @@ var COFantasy = COFantasy || function() { return; case 'dm': if (cmd.length < 1) { - error("Il manque la valeur après l'option --dm", cmd); + error("Il manque la valeur apr\xE8s l'option --dm", cmd); return; } - let dm = parseDice(cmd.slice(1).join(''), 'dégâts'); + let dm = parseDice(cmd.slice(1).join(''), 'd\xE9g\xE2ts'); if (dm) options.dm = dm; return; case 'portee': if (cmd.length < 1) { - error("Il manque la valeur après l'option --portee", cmd); + error("Il manque la valeur apr\xE8s l'option --portee", cmd); return; } let portee = parseInt(cmd[1]); @@ -8603,7 +8677,7 @@ var COFantasy = COFantasy || function() { return; case 'attaqueMagiqueDe': if (cmd.length < 1) { - error("Il manque le nom du personnage après l'option --attaqueMagiqueDe", cmd); + error("Il manque le nom du personnage apr\xE8s l'option --attaqueMagiqueDe", cmd); return; } let attaqueMagiqueDe = cmd.slice(1).join(' '); @@ -8612,22 +8686,22 @@ var COFantasy = COFantasy || function() { name: attaqueMagiqueDe }); if (ficheAttaqueMagique.length === 0) { - error("Il n'existe pas de personnage nommé " + attaqueMagiqueDe, cmd); + error("Il n'existe pas de personnage nomm\xE9 " + attaqueMagiqueDe, cmd); return; } if (ficheAttaqueMagique.length > 1) { - error("Attention, il existe plus d'un pesonnage nommé " + attaqueMagiqueDe, cmd); + error("Attention, il existe plus d'un pesonnage nomm\xE9 " + attaqueMagiqueDe, cmd); } let amCid = { charId: ficheAttaqueMagique[0].id }; let toucher = computeArmeAtk(amCid, '@{ATKMAG}'); if (isNaN(toucher)) { - error("Impossible de déterminer l'attaque de " + attaqueMagiqueDe, toucher); + error("Impossible de d\xE9terminer l'attaque de " + attaqueMagiqueDe, toucher); return; } if (options.toucher !== undefined) { - error("Attention, on a à la fois une option toucher et une option attaqueMagiqueDe. On ignore l'option --toucher", optArgs); + error("Attention, on a \xE0 la fois une option toucher et une option attaqueMagiqueDe. On ignore l'option --toucher", optArgs); } options.toucher = toucher; return; @@ -8648,14 +8722,14 @@ var COFantasy = COFantasy || function() { } scope.ignoreRD = parseInt(cmd[1]); if (isNaN(scope.ignoreRD) || scope.ignoreRD < 1) { - log("Pas un nombre positif après --ignoreRD, interprété comme ignore toute la RD"); + log("Pas un nombre positif apr\xE8s --ignoreRD, interpr\xE9t\xE9 comme ignore toute la RD"); scope.ignoreRD = undefined; scope.ignoreTouteRD = true; } return; case 'tueurDe': if (cmd.length < 2) { - log("Il faut préciser --tueurDe quoi"); + log("Il faut pr\xE9ciser --tueurDe quoi"); return; } options.tueurDe = options.tueurDe || []; @@ -8666,7 +8740,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { niveauMagie = parseInt(cmd[1]); if (isNaN(niveauMagie) || niveauMagie < 1) { - error("Le niveau de magie doit être au moins 1", cmd); + error("Le niveau de magie doit \xEAtre au moins 1", cmd); niveauMagie = 1; } } @@ -8677,16 +8751,16 @@ var COFantasy = COFantasy || function() { return; case 'tempsRecharge': if (cmd.length < 3) { - error("Il manque un argument à l'option --tempsRecharge de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --tempsRecharge de !cof-attack", cmd); return; } if (!estEffetTemp(cmd[1])) { - error("Le premier argument de l'option --tempsRecharge doit être un effet temporaire répertorié", cmd); + error("Le premier argument de l'option --tempsRecharge doit \xEAtre un effet temporaire r\xE9pertori\xE9", cmd); return; } let tr = parseInt(cmd[2]); if (isNaN(tr)) { - error("Le deuxième argument de l'option --tempsRecharge doit être un nombre", cmd); + error("Le deuxi\xE8me argument de l'option --tempsRecharge doit \xEAtre un nombre", cmd); return; } options.tempsRecharge = { @@ -8696,7 +8770,7 @@ var COFantasy = COFantasy || function() { return; case 'plus': if (cmd.length < 2) { - error("Il manque un argument à l'option --plus de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --plus de !cof-attack", cmd); return; } let val = arg.substring(arg.indexOf(' ') + 1); @@ -8708,7 +8782,7 @@ var COFantasy = COFantasy || function() { break; case 'plusCrit': if (cmd.length < 2) { - error("Il manque un argument à l'option --plusCrit de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --plusCrit de !cof-attack", cmd); return; } let valCrit = arg.substring(arg.indexOf(' ') + 1); @@ -8721,7 +8795,7 @@ var COFantasy = COFantasy || function() { case 'dmSiRate': case 'dmCible': if (cmd.length < 2) { - error("Il manque un argument à l'option --" + cmd[0] + " de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --" + cmd[0] + " de !cof-attack", cmd); return; } let valDm = arg.substring(arg.indexOf(' ') + 1); @@ -8732,7 +8806,7 @@ var COFantasy = COFantasy || function() { break; case 'effet': if (cmd.length < 2) { - error("Il manque un argument à l'option --effet de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --effet de !cof-attack", cmd); return; } let effet = cmd[1]; @@ -8745,7 +8819,7 @@ var COFantasy = COFantasy || function() { duree = parseInt(cmd[2]); if (isNaN(duree) || duree < 1) { error( - "Le deuxième argument de --effet doit être un nombre positif", + "Le deuxi\xE8me argument de --effet doit \xEAtre un nombre positif", cmd); return; } @@ -8771,7 +8845,7 @@ var COFantasy = COFantasy || function() { typeDmg: lastType }; } else { - error(cmd[1] + " n'est pas un effet temporaire répertorié", cmd); + error(cmd[1] + " n'est pas un effet temporaire r\xE9pertori\xE9", cmd); return; } scope.effets = scope.effets || []; @@ -8779,7 +8853,7 @@ var COFantasy = COFantasy || function() { return; case 'valeur': if (cmd.length < 2) { - error("Il manque un argument à l'option --valeur de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --valeur de !cof-attack", cmd); return; } if (scope.effets === undefined || scope.effets.length === 0) { @@ -8825,10 +8899,10 @@ var COFantasy = COFantasy || function() { case 'etatSi': case 'etat': if (cmd.length < 3 && cmd[0] == 'etatSi') { - error("Il manque un argument à l'option --etatSi de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --etatSi de !cof-attack", cmd); return; } else if (cmd.length < 2) { - error("Il manque un argument à l'option --etat de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --etat de !cof-attack", cmd); return; } let etat = cmd[1]; @@ -8850,7 +8924,7 @@ var COFantasy = COFantasy || function() { if (cmd[0] == 'etat' && cmd.length > 3) { if (!isCarac(cmd[2]) && (cmd[2].length != 6 || !isCarac(cmd[2].substring(0, 3)) || !isCarac(cmd[2].substring(3, 6)))) { - error("Caractéristique du jet de sauvegarde incorrecte", cmd); + error("Caract\xE9ristique du jet de sauvegarde incorrecte", cmd); return; } lastEtat.saveCarac = cmd[2]; @@ -8860,7 +8934,7 @@ var COFantasy = COFantasy || function() { } else { lastEtat.saveDifficulte = parseInt(cmd[3]); if (isNaN(lastEtat.saveDifficulte)) { - error("Difficulté du jet de sauvegarde incorrecte", cmd); + error("Difficult\xE9 du jet de sauvegarde incorrecte", cmd); delete lastEtat.saveCarac; delete lastEtat.saveDifficulte; } @@ -8870,7 +8944,7 @@ var COFantasy = COFantasy || function() { return; case 'peur': if (cmd.length < 3) { - error("Il manque un argument à l'option --peur de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --peur de !cof-attack", cmd); return; } scope.peur = { @@ -8878,10 +8952,10 @@ var COFantasy = COFantasy || function() { duree: parseInt(cmd[2]) }; if (isNaN(scope.peur.seuil)) { - error("Le premier argument de --peur doit être un nombre (le seuil)", cmd); + error("Le premier argument de --peur doit \xEAtre un nombre (le seuil)", cmd); } if (isNaN(scope.peur.duree) || scope.peur.duree <= 0) { - error("Le deuxième argument de --peur doit être un nombre positif (la durée)", cmd); + error("Le deuxi\xE8me argument de --peur doit \xEAtre un nombre positif (la dur\xE9e)", cmd); } return; case 'feu': @@ -8912,7 +8986,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { vampirise = parseInt(cmd[1]); if (isNaN(vampirise)) { - error("Il faut un pourcentage entier comme argument à --vampirise", cmd); + error("Il faut un pourcentage entier comme argument \xE0 --vampirise", cmd); vampirise = 100; } } @@ -8943,7 +9017,7 @@ var COFantasy = COFantasy || function() { break; case 'disparition': if (cmd.length < 2) { - error("Il manque un argument à l'option --disparition de !cof-attack", cmd); + error("Il manque un argument \xE0 l'option --disparition de !cof-attack", cmd); return; } let disparition = parseInt(cmd[1]); @@ -8995,7 +9069,7 @@ var COFantasy = COFantasy || function() { case 'save': if (lastEtat) { if (lastEtat.save) { - error("Redéfinition de la condition de save pour un effet", optArgs); + error("Red\xE9finition de la condition de save pour un effet", optArgs); } let saveParams = parseSave(cmd); if (saveParams) { @@ -9013,7 +9087,7 @@ var COFantasy = COFantasy || function() { case 'saveParJour': if (lastEtat) { if (lastEtat[cmd[0]]) { - error("Redéfinition de la condition de save pour un effet", optArgs); + error("Red\xE9finition de la condition de save pour un effet", optArgs); } let saveParTourParams = parseSave(cmd); if (saveParTourParams) { @@ -9034,12 +9108,12 @@ var COFantasy = COFantasy || function() { case 'mana': { if (cmd.length < 2) { - error("Usage : --mana coût", cmd); + error("Usage : --mana co\xFBt", cmd); return; } let mana = parseInt(cmd[1]); if (isNaN(mana) || mana < 0) { - error("Le coût en mana doit être un nombre positif"); + error("Le co\xFBt en mana doit \xEAtre un nombre positif"); return; } if (scope.mana === undefined) scope.mana = 0; @@ -9053,7 +9127,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { cout = parseInt(cmd[1]); if (isNaN(cout) || cout < 0) { - error("Le coût de la magie rapide n'est pas un entier positif", cmd); + error("Le co\xFBt de la magie rapide n'est pas un entier positif", cmd); cout = 1; } } @@ -9071,7 +9145,7 @@ var COFantasy = COFantasy || function() { } else { let base = parseInt(cmd[1]); if (isNaN(base)) { - error("L'argument de --magieEnArmure doit être un nombre ou mana", cmd); + error("L'argument de --magieEnArmure doit \xEAtre un nombre ou mana", cmd); return; } options.magieEnArmure = { @@ -9089,7 +9163,7 @@ var COFantasy = COFantasy || function() { } let rang = parseInt(cmd[1]); if (isNaN(rang) || rang < 1) { - error("Le rang doit être un nombre positif"); + error("Le rang doit \xEAtre un nombre positif"); return; } scope.rang = rang; @@ -9103,7 +9177,7 @@ var COFantasy = COFantasy || function() { } let bAtt = parseInt(cmd[1]); if (isNaN(bAtt)) { - error("Le bonus (" + cmd[0] + ") doit être un nombre"); + error("Le bonus (" + cmd[0] + ") doit \xEAtre un nombre"); return; } if (scope[cmd[0]] === undefined) scope[cmd[0]] = 0; @@ -9117,7 +9191,7 @@ var COFantasy = COFantasy || function() { } let b2Att = parseInt(cmd[1]); if (isNaN(b2Att)) { - error("Le bonus (" + cmd[0] + ") doit être un nombre"); + error("Le bonus (" + cmd[0] + ") doit \xEAtre un nombre"); return; } if (options[cmd[0]] === undefined) options[cmd[0]] = 0; @@ -9163,12 +9237,12 @@ var COFantasy = COFantasy || function() { } return; case 'munition': - if (options.munition) { //on évite la récursion - error("Plusieurs options --munition. Seule la première est prise en compte", cmd); + if (options.munition) { //on \xE9vite la r\xE9cursion + error("Plusieurs options --munition. Seule la premi\xE8re est prise en compte", cmd); return; } if (cmd.length < 2) { - error("Pour les munitions, il faut préciser le label de la munition", cmd); + error("Pour les munitions, il faut pr\xE9ciser le label de la munition", cmd); return; } let labelMunition = cmd[1]; @@ -9198,13 +9272,13 @@ var COFantasy = COFantasy || function() { } return; } - sendPlayer(msg, "Utilisez plutôt les munitions définies sur la fiche", playerId); - //Compatibilité avec ancienne version: - let tauxPertes = 100; //Par défaut, les munitions sont perdues + sendPlayer(msg, "Utilisez plut\xF4t les munitions d\xE9finies sur la fiche", playerId); + //Compatibilit\xE9 avec ancienne version: + let tauxPertes = 100; //Par d\xE9faut, les munitions sont perdues if (cmd.length > 2) tauxPertes = parseInt(cmd[2]); if (isNaN(tauxPertes) || tauxPertes < 0 || tauxPertes > 100) { - error("Le taux de pertes des munitions doit être un nombre entre 0 et 100"); + error("Le taux de pertes des munitions doit \xEAtre un nombre entre 0 et 100"); tauxPertes = 100; } options.munition = { @@ -9214,7 +9288,7 @@ var COFantasy = COFantasy || function() { return; case "ligne": if (options.aoe) { - error("Deux options pour définir une aoe", optArgs); + error("Deux options pour d\xE9finir une aoe", optArgs); return; } options.aoe = { @@ -9223,7 +9297,7 @@ var COFantasy = COFantasy || function() { return; case 'disque': if (options.aoe) { - error("Deux options pour définir une aoe", optArgs); + error("Deux options pour d\xE9finir une aoe", optArgs); return; } if (cmd.length < 2) { @@ -9244,14 +9318,14 @@ var COFantasy = COFantasy || function() { return; case 'cone': if (options.aoe) { - error("Deux options pour définir une aoe", optArgs); + error("Deux options pour d\xE9finir une aoe", optArgs); return; } let angle = 90; if (cmd.length > 1) { angle = parseInt(cmd[1]); if (isNaN(angle) || angle < 0 || angle > 360) { - error("Paramètre d'angle du cone incorrect", cmd); + error("Param\xE8tre d'angle du cone incorrect", cmd); angle = 90; } } @@ -9267,7 +9341,7 @@ var COFantasy = COFantasy || function() { } let targetS = persoOfId(cmd[1]); if (targetS === undefined) { - error("Cible supplémentaire invalide", cmd); + error("Cible suppl\xE9mentaire invalide", cmd); return; } if (targetToken.id == targetS.token.id) return; @@ -9322,63 +9396,45 @@ var COFantasy = COFantasy || function() { } return; case 'limiteParJour': - if (cmd.length < 2) { - error("Il manque la limite journalière", cmd); - return; - } - let limiteParJour = parseInt(cmd[1]); - if (isNaN(limiteParJour) || limiteParJour < 1) { - error("La limite journalière doit être un nombre positif", cmd); + { + if (cmd.length < 2) { + error("Il manque la limite journali\xE8re", cmd); + return; + } + let limiteParJour = parseLimite(cmd, "journali\xE8re"); + if (limiteParJour) scope.limiteParJour = limiteParJour; return; } - scope.limiteParJour = limiteParJour; - if (cmd.length > 2) { - cmd.splice(0, 2); - scope.limiteParJourRessource = cmd.join('_'); - } - return; case 'limiteParCombat': - if (cmd.length < 2) { - scope.limiteParCombat = 1; - return; - } - let limiteParCombat = parseInt(cmd[1]); - if (isNaN(limiteParCombat) || limiteParCombat < 1) { - error("La limite par combat doit être un nombre positif", cmd); + { + if (cmd.length < 2) { + scope.limiteParCombat = 1; + return; + } + let limiteParCombat = parseLimite(cmd, "par combat"); + if (limiteParCombat) scope.limiteParCombat = limiteParCombat; return; } - scope.limiteParCombat = limiteParCombat; - if (cmd.length > 2) { - cmd.splice(0, 2); - scope.limiteParCombatRessource = cmd.join('_'); - } - return; case 'limiteParTour': - if (cmd.length < 2) { - scope.limiteParTour = 1; - return; - } - let limiteParTour = parseInt(cmd[1]); - if (isNaN(limiteParTour) || limiteParTour < 1) { - error("La limite par tour doit être un nombre positif", cmd); + { + if (cmd.length < 2) { + scope.limiteParTour = 1; + return; + } + let limiteParTour = parseLimite(cmd, "par tour"); + if (limiteParTour) scope.limiteParTour = limiteParTour; return; } - scope.limiteParTour = limiteParTour; - if (cmd.length > 2) { - cmd.splice(0, 2); - scope.limiteParTourRessource = cmd.join('_'); - } - return; case 'decrAttribute': if (cmd.length < 2) { - error("Erreur interne d'une commande générée par bouton", cmd); + error("Erreur interne d'une commande g\xE9n\xE9r\xE9e par bouton", cmd); return; } let attr = getObj('attribute', cmd[1]); if (attr === undefined) { attr = tokenAttribute(attaquant, cmd[1]); if (attr.length === 0) { - log("Attribut à changer perdu"); + log("Attribut \xE0 changer perdu"); log(cmd); return; } @@ -9388,7 +9444,7 @@ var COFantasy = COFantasy || function() { return; case 'decrLimitePredicatParTour': if (cmd.length < 2) { - error("Erreur interne d'une commande générée par bouton", cmd); + error("Erreur interne d'une commande g\xE9n\xE9r\xE9e par bouton", cmd); return; } scope.decrLimitePredicatParTour = cmd[1]; @@ -9400,7 +9456,7 @@ var COFantasy = COFantasy || function() { } let forceMin = parseInt(cmd[1]); if (isNaN(forceMin)) { - error("La force minimum doit être un nombre", cmd); + error("La force minimum doit \xEAtre un nombre", cmd); return; } scope.forceMinimum = forceMin; @@ -9412,7 +9468,7 @@ var COFantasy = COFantasy || function() { } let arcComposite = parseInt(cmd[1]); if (isNaN(arcComposite)) { - error("Le bonus d'arc composite doit être un nombre", cmd); + error("Le bonus d'arc composite doit \xEAtre un nombre", cmd); return; } scope.arcComposite = arcComposite; @@ -9428,7 +9484,7 @@ var COFantasy = COFantasy || function() { scope.dmgCoef += incrDmgCoef; return; } - scope.dmgCoef++; //Par défaut, incrémente de 1 + scope.dmgCoef++; //Par d\xE9faut, incr\xE9mente de 1 return; case 'toucheDoubleDmg': options.toucheDoubleDmg = true; @@ -9446,7 +9502,7 @@ var COFantasy = COFantasy || function() { scope.diviseDmg *= divise; return; } - scope.diviseDmg *= 2; //Par défaut, divise par 2 + scope.diviseDmg *= 2; //Par d\xE9faut, divise par 2 return; case 'divisePortee': scope.divisePortee = (scope.divisePortee || 1); @@ -9459,7 +9515,7 @@ var COFantasy = COFantasy || function() { scope.divisePortee *= divise; return; } - scope.divisePortee *= 2; //Par défaut, divise par 2 + scope.divisePortee *= 2; //Par d\xE9faut, divise par 2 return; case 'incrCritCoef': scope.critCoef = (scope.critCoef || 1); @@ -9472,7 +9528,7 @@ var COFantasy = COFantasy || function() { scope.critCoef += incrCritCoef; return; } - scope.critCoef++; //Par défaut, incrémente de 1 + scope.critCoef++; //Par d\xE9faut, incr\xE9mente de 1 return; case 'if': let ifCond = parseCondition(cmd.slice(1)); @@ -9523,7 +9579,7 @@ var COFantasy = COFantasy || function() { } let iteL = psElse.ite[psElse.ite.length - 1]; if (iteL.else) { - error("Il y a déjà un --else pour ce --if", cmd); + error("Il y a d\xE9j\xE0 un --else pour ce --if", cmd); return; } delete scope.parentScope; @@ -9536,7 +9592,7 @@ var COFantasy = COFantasy || function() { } case 'message': if (cmd.length < 2) { - error("Il manque le message après --message", cmd); + error("Il manque le message apr\xE8s --message", cmd); return; } scope.messages = scope.messages || []; @@ -9544,11 +9600,11 @@ var COFantasy = COFantasy || function() { return; case 'allonge': if (cmd.length < 2) { - error("Il manque le message après --allonge", cmd); + error("Il manque le message apr\xE8s --allonge", cmd); return; } if (options.allonge !== undefined) { - log("Redéfinition de l'allong"); + log("Red\xE9finition de l'allong"); } options.allonge = parseFloat(cmd[1]); if (isNaN(options.allonge)) { @@ -9571,7 +9627,7 @@ var COFantasy = COFantasy || function() { scope.enveloppe.expression = cmd[3]; } if (scope.enveloppe.expression === undefined) { - error("Il n'est pas encore possible d'utiliser l'option --enveloppe sans expression si le label de l'attaque n'est pas défini", cmd); + error("Il n'est pas encore possible d'utiliser l'option --enveloppe sans expression si le label de l'attaque n'est pas d\xE9fini", cmd); scope.enveloppe = undefined; } return; @@ -9598,7 +9654,7 @@ var COFantasy = COFantasy || function() { case 'imgAttackSuccesChampion': case 'imgAttackSuccesCritique': if (cmd.length < 1) { - error("Il manque une image après --" + cmd[0], cmd); + error("Il manque une image apr\xE8s --" + cmd[0], cmd); return; } options[cmd[0]] = cmd[1]; @@ -9611,12 +9667,12 @@ var COFantasy = COFantasy || function() { case 'soundAttackSuccesChampion': case 'soundAttackSuccesCritique': if (cmd.length < 1) { - error("Il manque le son après --" + cmd[0], cmd); + error("Il manque le son apr\xE8s --" + cmd[0], cmd); return; } options[cmd[0]] = cmd.slice(1).join(' '); return; - //Anciennes variantes, gardées pour la compatibilité + //Anciennes variantes, gard\xE9es pour la compatibilit\xE9 case 'img-attack-echec-critique': case 'img-attack-echec': case 'img-attack-echec-clignotement': @@ -9626,7 +9682,7 @@ var COFantasy = COFantasy || function() { case 'img-attack-succes-champion': case 'img-attack-succes-critique': if (cmd.length < 1) { - error("Il manque une image après --" + cmd[0], cmd); + error("Il manque une image apr\xE8s --" + cmd[0], cmd); return; } let imgCmd = @@ -9644,7 +9700,7 @@ var COFantasy = COFantasy || function() { case 'sound-attack-succes-champion': case 'sound-attack-succes-critique': if (cmd.length < 2) { - error("Il manque le son après --" + cmd[0], cmd); + error("Il manque le son apr\xE8s --" + cmd[0], cmd); return; } let soundCmd = cmd[0].replace('-a', 'A').replace('-e', 'E').replace('-c', 'C').replace('-n', 'N').replace('-s', 'S').replace('-t', 'T'); @@ -9670,7 +9726,7 @@ var COFantasy = COFantasy || function() { case 'FOR': carac = 'force'; break; - case 'dextérité': + case 'dext\xE9rit\xE9': case 'DEX': carac = 'dexterite'; break; @@ -9691,12 +9747,12 @@ var COFantasy = COFantasy || function() { carac = 'random'; break; default: - error("Le premier argument de affaiblirCarac n'est pas une caractéristique", cmd); + error("Le premier argument de affaiblirCarac n'est pas une caract\xE9ristique", cmd); return; } let valAff = parseDice(cmd[2]); if (!valAff || !dePositif(valAff)) { - error("Le deuxième argument de --affaiblirCarac doit être un nombre", cmd); + error("Le deuxi\xE8me argument de --affaiblirCarac doit \xEAtre un nombre", cmd); return; } if (valAff === 0) return; @@ -9709,12 +9765,12 @@ var COFantasy = COFantasy || function() { return; case 'difficulteCarac': if (cmd.length < 2) { - error("Il manque la caractéristique à laquelle mesurer le jet d'attaque", cmd); + error("Il manque la caract\xE9ristique \xE0 laquelle mesurer le jet d'attaque", cmd); return; } options.difficulteCarac = parseCarac(cmd[1]); if (options.difficulteCarac === undefined) { - error("L'argument de --difficulteCarac n'est pas une caractéristique", cmd); + error("L'argument de --difficulteCarac n'est pas une caract\xE9ristique", cmd); } return; case 'attackId': @@ -9724,6 +9780,54 @@ var COFantasy = COFantasy || function() { } options.attackId = cmd[1]; return; + case 'terrainDifficile': + { + let terrainDifficile = options.terrainDifficile || { + duree: 1, + imgsrc: IMG_INVISIBLE, + nom: "Terrain difficile" + }; + if (cmd.length > 1) { //le premier argument est la dur\xE9e de l'effet + terrainDifficile.duree = toInt(cmd[1], 1); + if (cmd.length > 2) { //le second argument est le nom du terrain + terrainDifficile.nom = cmd[2].replace(/_/g, ' '); + if (cmd.length > 3) { //le troisi\xE8me argument est l'url de l'image + let imgsrc = cmd[3].replace(':', ':'); + terrainDifficile.imgsrc = normalizeTokenImg(imgsrc); + } + } + } + options.terrainDifficile = terrainDifficile; + return; + } + case 'deplaceDe': + { + if (cmd.length < 2) { + error("Il faut pr\xE9ciser une distance maximale pour --deplaceDe", cmd); + return; + } + let deplaceDe = {}; + deplaceDe.max = parseInt(cmd[1]); + if (isNaN(deplaceDe.max) || deplaceDe.max < 0) { + error("Distance de deplacement incorrect", cmd); + return; + } + if (cmd.length > 2) { + if (cmd[2] == 'saut') deplaceDe.saut = true; + else { + let dmax = parseInt(cmd[2]); + if (isNaN(dmax) || dmax < deplaceDe.max) { + error("Argument de d\xE9placement " + cmd[2] + " non reconnu", cmd); + } else { + deplaceDe.min = deplaceDe.max; + deplaceDe.max = dmax; + } + if (cmd.length > 3 && cmd[3] == 'saut') deplaceDe.saut = true; + } + } + options.deplaceDe = deplaceDe; + return; + } default: let armeMagique = cmd[0].match(/^\+([0-9]+)$/); if (armeMagique && armeMagique.length > 0) { @@ -9747,7 +9851,7 @@ var COFantasy = COFantasy || function() { } } }); - closeIte(scope); //pour fermer les endif mal formés et éviter les boucles + closeIte(scope); //pour fermer les endif mal form\xE9s et \xE9viter les boucles return { lastEtat, lastType, @@ -9779,7 +9883,7 @@ var COFantasy = COFantasy || function() { } let pageId = attaquant.token.get('pageid'); let targetToken = getObj('graphic', args[2]); - if (targetToken === undefined) { //reste la possibilité de trouver un token de ce nom + if (targetToken === undefined) { //reste la possibilit\xE9 de trouver un token de ce nom let tokens = findObjs({ _type: 'graphic', _subtype: 'token', @@ -9787,12 +9891,12 @@ var COFantasy = COFantasy || function() { name: args[2] }); if (tokens.length == 0) { - error("le second argument de !cof-attack doit être un token", args[2]); + error("le second argument de !cof-attack doit \xEAtre un token", args[2]); return; } if (tokens.length > 1) { - error("Ambigüité sur le choix d'un token : il y a " + - tokens.length + " tokens nommés " + args[2], tokens); + error("Ambig\xFCit\xE9 sur le choix d'un token : il y a " + + tokens.length + " tokens nomm\xE9s " + args[2], tokens); } targetToken = tokens[0]; } @@ -9803,7 +9907,7 @@ var COFantasy = COFantasy || function() { let weaponStats; let attaqueArray; try { - attaqueArray = JSON.parse(attackLabel); //plus documenté depuis 2020 + attaqueArray = JSON.parse(attackLabel); //plus document\xE9 depuis 2020 } catch (e) {} if (Array.isArray(attaqueArray) && attaqueArray.length > 4 && attaqueArray[1].length > 1 && attaqueArray[3].length > 3) { @@ -9850,10 +9954,10 @@ var COFantasy = COFantasy || function() { return; } if (weaponStats.deuxMains && attributeAsBool(attaquant, 'espaceExigu')) { - sendPerso(attaquant, "ne peut pas utiliser d'arme à deux mains dans un espace aussi exigu."); + sendPerso(attaquant, "ne peut pas utiliser d'arme \xE0 deux mains dans un espace aussi exigu."); return; } - //Si c'est aussi une arme de jet, et que le personnage attaque à distance, on va utiliser la version arme de jet de l'attaque. + //Si c'est aussi une arme de jet, et que le personnage attaque \xE0 distance, on va utiliser la version arme de jet de l'attaque. let msgIndex = msg.content; let indexAussiJet = msgIndex.indexOf('--aussiArmeDeJet '); if (indexAussiJet == -1 && weaponStats.options) { @@ -9879,7 +9983,7 @@ var COFantasy = COFantasy || function() { } //Ajout des options de l'arme let wo = weaponStats.options.trim(); - //Pour la partie options, il est possible qu'elle soit déjà passée en ligne de commande + //Pour la partie options, il est possible qu'elle soit d\xE9j\xE0 pass\xE9e en ligne de commande if (wo !== '' && ((optArgs.length < 1 || !optArgs[0].startsWith('attaqueOptions'))) || indexAussiJet > 0) { wo = ' ' + wo; wo.split(' --').reverse().forEach(function(o) { @@ -9923,7 +10027,7 @@ var COFantasy = COFantasy || function() { break; case 'magique': options.magique = true; - options.type = 'energie'; //Les dégâts magiques sans type associé sont supposés de type énergie, l'équivalent de force dans PF1 + options.type = 'energie'; //Les d\xE9g\xE2ts magiques sans type associ\xE9 sont suppos\xE9s de type \xE9nergie, l'\xE9quivalent de force dans PF1 break; case 'tranchant': case 'percant': @@ -9932,7 +10036,7 @@ var COFantasy = COFantasy || function() { break; } let lastEtat; //dernier de etats et effets - let lastType = options.type; //dernier type de dégâts infligés + let lastType = options.type; //dernier type de d\xE9g\xE2ts inflig\xE9s let scope = options; //Pour les conditionnelles parseAttackOptions(attaquant, optArgs, lastEtat, lastType, scope, playerId, msg, targetToken, attackLabel, weaponStats, options); let bene = predicateAsInt(attaquant, 'benedictionSuperieure', 0); @@ -9946,7 +10050,7 @@ var COFantasy = COFantasy || function() { options.additionalDmg = options.additionalDmg || []; if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, rang: options.rang, @@ -9972,7 +10076,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -9989,7 +10093,7 @@ var COFantasy = COFantasy || function() { } } else { if (options.tempeteDeManaDuree) { - sendPlayerAndGM(msg, playerId, "Attention, l'option tempête de mana pour la durée n'est pas prise en compte. Utiliser l'option --pasDeDmg si le sort ne fait pas de DM"); + sendPlayerAndGM(msg, playerId, "Attention, l'option temp\xEAte de mana pour la dur\xE9e n'est pas prise en compte. Utiliser l'option --pasDeDmg si le sort ne fait pas de DM"); options.tempeteDeManaDuree = false; if (options.tempeteDeMana && options.tempeteDeMana.cout) options.tempeteDeMana.cout--; @@ -10019,30 +10123,30 @@ var COFantasy = COFantasy || function() { if (f) f(evt); } - // Fait dépenser de la mana, dep doit contenir une dépense possible + // Fait d\xE9penser de la mana, dep doit contenir une d\xE9pense possible function depenseMana(perso, dep, msg, evt) { if (!dep || dep.cout_null) return; updateCurrentBar(perso, 2, dep.pm, evt); msg = msg || ''; if (dep.depense_pv) { - let source = reglesOptionelles.mana.val.brulure_de_magie.val ? "de la Brûlure de Magie" : "du Contrecoup"; + let source = reglesOptionelles.mana.val.brulure_de_magie.val ? "de la Br\xFBlure de Magie" : "du Contrecoup"; updateCurrentBar(perso, 1, dep.pv, evt); let pre = 'p'; if (stateCOF.options.affichage.val.depense_mana.val && dep.depense_pm > 0) - pre = "dépense " + dep.depense_pm + " PM et p"; - sendPerso(perso, pre + "erd " + dep.depense_pv + " PV à cause " + source + " pour " + msg); + pre = "d\xE9pense " + dep.depense_pm + " PM et p"; + sendPerso(perso, pre + "erd " + dep.depense_pv + " PV \xE0 cause " + source + " pour " + msg); } else { if (stateCOF.options.affichage.val.depense_mana.val) - sendPerso(perso, "dépense " + dep.depense_pm + " PM pour " + msg); + sendPerso(perso, "d\xE9pense " + dep.depense_pm + " PM pour " + msg); } let niveau = ficheAttributeAsInt(perso, 'niveau', 1); if (reglesOptionelles.mana.val.mana_totale.val) { if (dep.depense_pm > niveau * 3) { - sendPerso(perso, "Attention, la dépense totale de mana est supérieure au niveau * 3"); + sendPerso(perso, "Attention, la d\xE9pense totale de mana est sup\xE9rieure au niveau * 3"); } } else { if (dep.depense_pm > niveau) { - sendPerso(perso, "Attention, la dépense totale de mana est supérieure au niveau"); + sendPerso(perso, "Attention, la d\xE9pense totale de mana est sup\xE9rieure au niveau"); } } return; @@ -10071,7 +10175,7 @@ var COFantasy = COFantasy || function() { case 'animal': return estAnimal(perso); case 'demon': - case 'démon': + case 'd\xE9mon': return estDemon(perso); case 'dragon': return estDraconique(perso); @@ -10079,9 +10183,9 @@ var COFantasy = COFantasy || function() { case 'elfe-noir': return estElfeNoir(perso); case 'fee': - case 'fée': + case 'f\xE9e': return estFee(perso); - case 'géant': + case 'g\xE9ant': case 'geant': return estGeant(perso); case 'gobelin': @@ -10097,7 +10201,7 @@ var COFantasy = COFantasy || function() { } } - //Si l'attribut est un mod. de caractéristique, va chercher le + //Si l'attribut est un mod. de caract\xE9ristique, va chercher le //bon attribut, selon que perso est un PNJ ou nom function valAttribute(perso, originalAttr, caracAttr) { if (caracAttr) { @@ -10109,10 +10213,10 @@ var COFantasy = COFantasy || function() { return charAttributeAsInt(perso, originalAttr, 0); } - //test si l'attribut est présent et si sa valeur est bonne + //test si l'attribut est pr\xE9sent et si sa valeur est bonne // options peut contenir - // fiche : si on cherche un attribut de fiche, et dans ce cas, le champ def donne la valeur par défaut - // local : si c'est un attribut différent selon le mook + // fiche : si on cherche un attribut de fiche, et dans ce cas, le champ def donne la valeur par d\xE9faut + // local : si c'est un attribut diff\xE9rent selon le mook function testAttribut(perso, attrName, valeur, options) { let attr; if (options.fiche) { @@ -10130,7 +10234,7 @@ var COFantasy = COFantasy || function() { if (cond == 'toujoursVrai') return true; switch (cond.type) { case 'moins': - // Au cas où on utilise les MOD au lieu de l'attribut de base: + // Au cas o\xF9 on utilise les MOD au lieu de l'attribut de base: let caracAttr = caracOfMod(cond.attribute); let attackerAttr = valAttribute(attaquant, cond.attribute, caracAttr); let resMoins = true; @@ -10188,13 +10292,13 @@ var COFantasy = COFantasy || function() { case 'deAttaque': if (options && options.auto) return false; if (deAttaque === undefined) { - error("Condition de dé d'attaque non supportée ici", cond); + error("Condition de d\xE9 d'attaque non support\xE9e ici", cond); return true; } return deAttaque >= cond.seuil; case 'echecCritique': if (deAttaque === undefined) { - error("Condition de dé d'attaque non supportée ici", cond); + error("Condition de d\xE9 d'attaque non support\xE9e ici", cond); return true; } return deAttaque == 1; @@ -10206,6 +10310,8 @@ var COFantasy = COFantasy || function() { return cibles.every(function(target) { return target.critique; }); + case 'premiereAttaque': + return !attributeAsBool(attaquant, 'attributDeCombat_premiereAttaque'); default: error("Condition non reconnue", cond); } @@ -10238,7 +10344,7 @@ var COFantasy = COFantasy || function() { case 'mana': case 'bonusAttaque': case 'bonusContreArmure': - case 'bonusContreBouclier': //numériques additives + case 'bonusContreBouclier': //num\xE9riques additives opt[field] = opt[field] || 0; opt[field] += branch[field]; break; @@ -10285,11 +10391,11 @@ var COFantasy = COFantasy || function() { attr.set('current', oldval - 1); break; case 'decrLimitePredicatParTour': - //Ne fait que diminuer l'attribut, n'empêche pas l'attaque + //Ne fait que diminuer l'attribut, n'emp\xEAche pas l'attaque let pred = branch.decrLimitePredicatParTour; let test = testLimiteUtilisationsCapa(attaquant, pred, 'tour', "ne peut plus utiliser " + pred + " ce tour", - "Attaque impossible, pas de prédicat " + pred); + "Attaque impossible, pas de pr\xE9dicat " + pred); if (test === undefined) break; utiliseCapacite(attaquant, test, evt); break; @@ -10308,7 +10414,7 @@ var COFantasy = COFantasy || function() { if (etat.aTraiter === 0) callback(); } - //Evaluation récursive des if-then-else + //Evaluation r\xE9cursive des if-then-else function evalITE(attaquant, target, deAttaque, options, phase, evt, explications, scope, callback, inTarget, etatParent) { etatParent = etatParent || {}; if (scope.ite === undefined || scope.ite.length < 1) { @@ -10324,6 +10430,7 @@ var COFantasy = COFantasy || function() { switch (ite.condition.type) { case 'etat': case 'attribut': + case 'premiereAttaque': resCondition = testCondition(ite.condition, attaquant, [], deAttaque); break; case 'deAttaque': @@ -10377,7 +10484,7 @@ var COFantasy = COFantasy || function() { callIfAllDone(etatParent, callback); return true; } - let msgPour = " pour résister à un effet"; + let msgPour = " pour r\xE9sister \xE0 un effet"; let msgRate = ", " + nomPerso(target) + " rate son jet de sauvegarde"; let saveOpts = { msgPour: msgPour, @@ -10391,7 +10498,7 @@ var COFantasy = COFantasy || function() { }; const saveId = condInTarget ? 'ifSave_' + etatParent.aTraiter + '_' + target.token.id : 'ifSave_' + etatParent.aTraiter + '_' + attaquant.token.id; - if (phase > 0) { //le save a déjà été résolu + if (phase > 0) { //le save a d\xE9j\xE0 \xE9t\xE9 r\xE9solu condInTarget = true; resCondition = target.saveResults && target.saveResults[saveId]; break; @@ -10407,7 +10514,7 @@ var COFantasy = COFantasy || function() { branch = ite.else; target.saveResults[saveId] = true; } else { - branch = ite.then; //on teste si le save est raté + branch = ite.then; //on teste si le save est rat\xE9 target.saveResults[saveId] = false; } if (branch === undefined) { @@ -10430,7 +10537,7 @@ var COFantasy = COFantasy || function() { else branch = ite.else; if (branch === undefined) { callIfAllDone(etatParent, callback); - return condInTarget; //On garde l'ite si on dépend de la cible + return condInTarget; //On garde l'ite si on d\xE9pend de la cible } //On copie les champs de scope dans options ou dans target if (phase === 0) @@ -10443,7 +10550,7 @@ var COFantasy = COFantasy || function() { }); } - // Retourne tous les attributs dans attrs, de nom name ou commençant par name_ + // Retourne tous les attributs dans attrs, de nom name ou commen\xE7ant par name_ function allAttributesNamed(attrs, name) { let reg = new RegExp("^" + name + "($|_|\\()"); return attrs.filter(function(obj) { @@ -10559,7 +10666,7 @@ var COFantasy = COFantasy || function() { already = already || new Set(); let pid = [perso.charId, perso.token.id]; if (already.has(pid)) { - error("Il y a un cycle d'initiatives dérivées les unes des autres impliquant " + nomPerso(perso), already); + error("Il y a un cycle d'initiatives d\xE9riv\xE9es les unes des autres impliquant " + nomPerso(perso), already); return perso; } let persoD = initDerivee(perso, already); @@ -10590,7 +10697,7 @@ var COFantasy = COFantasy || function() { // retourne undefined sinon } - //ne rajoute pas evt à l'historique + //ne rajoute pas evt \xE0 l'historique function persoInit(perso, evt, already) { let persoD = initDerivee(perso); if (persoD) perso = persoD; @@ -10604,13 +10711,13 @@ var COFantasy = COFantasy || function() { init += ficheAttributeAsInt(perso, 'mod_initiative', 0); } if (attributeAsBool(perso, 'formeDArbre')) init = 7; - //Règle optionelle : +1d6, à lancer en entrant en combat + //R\xE8gle optionelle : +1d6, \xE0 lancer en entrant en combat if (reglesOptionelles.initiative.val.initiative_variable.val) { let bonusVariable; let jetPartage; if (reglesOptionelles.initiative.val.initiative_variable_individuelle.val) { // Un jet par perso mook bonusVariable = attributeAsInt(perso, 'bonusInitVariable', 0); - } else { //Un seul pour tous les mook du même personnage + } else { //Un seul pour tous les mook du m\xEAme personnage bonusVariable = charAttributeAsInt(perso, 'bonusInitVariable', 0); jetPartage = true; } @@ -10624,7 +10731,7 @@ var COFantasy = COFantasy || function() { let msgSecret = perso.token.get('layer') == 'gmlayer'; if (!jetCache) { msg += onGenre(perso, 'Il', 'Elle') + " fait " + rollD6.roll; - msg += " à son jet d'initiative"; + msg += " \xE0 son jet d'initiative"; } setTokenAttr(perso, 'bonusInitVariable', bonusVariable, evt, { msg: msg, @@ -10639,9 +10746,9 @@ var COFantasy = COFantasy || function() { init += attributeAsInt(perso, 'bonusInitEmbuscade', 0); // Familier if (compagnonPresent(perso, 'familier')) init += 2; - // Sixième sens en sort + // Sixi\xE8me sens en sort if (attributeAsBool(perso, 'sixiemeSens')) init += 2; - // Voie du chef d'armée rangs 2 et 3 (Capitaine) + // Voie du chef d'arm\xE9e rangs 2 et 3 (Capitaine) let bonusCapitaine = aUnCapitaine(perso, evt); if (bonusCapitaine) init += parseInt(bonusCapitaine); if (predicateAsBool(perso, 'graceFeline')) { @@ -10668,19 +10775,20 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(perso, 'intelligenceDuCombat')) { init += modCarac(perso, 'intelligence'); } - // Réflexes felins de la Voie du pourfendeur + // R\xE9flexes felins de la Voie du pourfendeur init += predicateAsInt(perso, 'reflexesFelins', 0); - // Âme féline (félis) + // \xC2me f\xE9line (f\xE9lis) init += predicateAsInt(perso, 'ameFeline', 0); init += predicateAsInt(perso, 'vitesseDuFelin', 0); init += predicateAsInt(perso, 'espritVide', 0, 3); init += predicateAsInt(perso, 'pasDuVent', 0, 1); //Prescience de l'ensorceleur if (attributeAsBool(perso, 'prescienceUtilisee')) init += 10; - //Forêt vivante + //For\xEAt vivante if (attributeAsBool(perso, 'foretVivanteEnnemie')) { init -= 5; } + init += predicateAsInt(perso, 'rapideCommeSonOmbre', 0, 3); return init; } @@ -10701,12 +10809,12 @@ var COFantasy = COFantasy || function() { }); } - //ne rajoute pas evt à l'historique - //options: recompute : si pas encore agi, on remet à sa place dans le turn order - //already est là pour éviter les récursions infinies + //ne rajoute pas evt \xE0 l'historique + //options: recompute : si pas encore agi, on remet \xE0 sa place dans le turn order + //already est l\xE0 pour \xE9viter les r\xE9cursions infinies //boutonRoll: vient de l'utilisation d'un bouton de roll function initiative(selected, evt, recompute, already, boutonRoll) { //set initiative for selected tokens - // Toujours appelé quand on entre en combat + // Toujours appel\xE9 quand on entre en combat // Initialise le compteur de tour, si besoin // Assumption: all tokens that have not acted yet are those before the turn // counter. @@ -10716,7 +10824,7 @@ var COFantasy = COFantasy || function() { // Tokens appearing before the turn are sorted if (!Campaign().get('initiativepage')) evt.initiativepage = false; let debutCombat = false; - if (!stateCOF.combat) { //actions de début de combat + if (!stateCOF.combat) { //actions de d\xE9but de combat evt.combat = false; stateCOF.combat = { tour: 1, @@ -10731,7 +10839,7 @@ var COFantasy = COFantasy || function() { }]), initiativepage: true }); - removeAllAttributes('transeDeGuérison', evt); + removeAllAttributes('transeDeGu\xE9rison', evt); debutCombat = true; } const combat = stateCOF.combat; @@ -10739,7 +10847,7 @@ var COFantasy = COFantasy || function() { Campaign().set('initiativepage', true); } let to = getTurnOrder(combat, evt); - if (to.pasAgi.length === 0) { // Fin de tour, on met le tour à la fin et on retrie + if (to.pasAgi.length === 0) { // Fin de tour, on met le tour \xE0 la fin et on retrie to.pasAgi = to.dejaAgi; to.dejaAgi = []; } @@ -10749,7 +10857,7 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(perso) { let pageId = perso.token.get('pageid'); combat.pageId = pageId; - //Si besoin, on stoque les PVs de début de combat + //Si besoin, on stoque les PVs de d\xE9but de combat if (!attributeAsBool(perso, 'PVsDebutCombat')) { setTokenAttr(perso, 'PVsDebutCombat', perso.token.get('bar1_value'), evt); } @@ -10774,7 +10882,7 @@ var COFantasy = COFantasy || function() { } } let init = persoInit(perso, evt); - // On place le token à sa place dans la liste du tour + // On place le token \xE0 sa place dans la liste du tour let dejaIndex = to.dejaAgi.findIndex(function(elt) { return (elt.id == perso.token.id); @@ -10791,7 +10899,7 @@ var COFantasy = COFantasy || function() { updateNextInit(perso); return true; } else { - return false; //On enlève le perso des pasAgi + return false; //On enl\xE8ve le perso des pasAgi } } push = false; //Sinon, comme on ne recalcule pas, on le laisse @@ -10839,7 +10947,7 @@ var COFantasy = COFantasy || function() { }; addAura(perso, aura, aurasCreees, combat, evt); }); - //Les autres persos qui entrent en combat en même temps + //Les autres persos qui entrent en combat en m\xEAme temps let ajouterEnCombat = predicatesNamed(perso, 'entrerEnCombatAvec'); if (ajouterEnCombat.length > 0) { let aec = new Set(ajouterEnCombat); @@ -10871,7 +10979,7 @@ var COFantasy = COFantasy || function() { to.dejaAgi[dejaIndex].pr = init; } }); - if (debutCombat) { //On cherche si un des personnages de la carte a la capacité Prescience + if (debutCombat) { //On cherche si un des personnages de la carte a la capacit\xE9 Prescience let allToks = findObjs({ _type: 'graphic', @@ -10887,7 +10995,7 @@ var COFantasy = COFantasy || function() { }; return capaciteDisponible(perso, 'prescience', 'combat'); }); - if (prescience) { //Il faut stoquer les positions de tous les token pour le retour en arrière. + if (prescience) { //Il faut stoquer les positions de tous les token pour le retour en arri\xE8re. stateCOF.prescience = { evt: evt, dernieresPositions: [] @@ -10934,7 +11042,7 @@ var COFantasy = COFantasy || function() { function initiativeInterface(msg) { getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - error("Dans !cof-init : rien à faire, pas de token selectionné", msg); + error("Dans !cof-init : rien \xE0 faire, pas de token selectionn\xE9", msg); return; } aura_token_on_turn = msg.content.indexOf('--aura') !== -1; @@ -11060,7 +11168,7 @@ var COFantasy = COFantasy || function() { }); return r !== undefined; } catch (uriError) { - log("Erreur de décodage URI dans la note GM de " + token.get('name') + " : " + gmNotes); + log("Erreur de d\xE9codage URI dans la note GM de " + token.get('name') + " : " + gmNotes); } } return false; @@ -11070,9 +11178,9 @@ var COFantasy = COFantasy || function() { return false; } - // bonus d'attaque d'un token, indépendament des options + // bonus d'attaque d'un token, ind\xE9pendament des options // Mise en commun pour attack et attaque-magique - // options pour modifier éventuellement l'affichage si pas de DM et pour mettre à jour options.bonusDM si présent + // options pour modifier \xE9ventuellement l'affichage si pas de DM et pour mettre \xE0 jour options.bonusDM si pr\xE9sent function bonusDAttaque(personnage, explications, evt, options) { explications = explications || []; let tempAttkMod; // Utilise la barre 3 de l'attaquant @@ -11099,7 +11207,7 @@ var COFantasy = COFantasy || function() { attributeAsInt(personnage, 'chantDesHerosTempeteDeManaIntense', 0); bonusChantDesHeros += chantDesHerosIntense; attBonus += bonusChantDesHeros; - explications.push("Chant des héros => +" + bonusChantDesHeros + " en Attaque"); + explications.push("Chant des h\xE9ros => +" + bonusChantDesHeros + " en Attaque"); if (chantDesHerosIntense) removeTokenAttr(personnage, 'chantDesHerosTempeteDeManaIntense', evt); } @@ -11108,7 +11216,7 @@ var COFantasy = COFantasy || function() { let benedictionIntense = attributeAsInt(personnage, 'benedictionTempeteDeManaIntense', 0); bonusBenediction += benedictionIntense; attBonus += bonusBenediction; - explications.push("Bénédiction => +" + bonusBenediction + " en Attaque"); + explications.push("B\xE9n\xE9diction => +" + bonusBenediction + " en Attaque"); if (benedictionIntense) removeTokenAttr(personnage, 'benedictionTempeteDeManaIntense', evt); } @@ -11123,17 +11231,17 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'lameDeLigneePerdue')) { attBonus -= 1; - explications.push("Lame de lignée perdue => -1 en Attaque"); + explications.push("Lame de lign\xE9e perdue => -1 en Attaque"); } if (attributeAsBool(personnage, 'strangulation')) { let malusStrangulation = 1 + attributeAsInt(personnage, 'dureeStrangulation', 0); attBonus -= malusStrangulation; - explications.push("L'attaquant est étranglé => -" + malusStrangulation + " en Attaque"); + explications.push("L'attaquant est \xE9trangl\xE9 => -" + malusStrangulation + " en Attaque"); } if (getState(personnage, 'renverse')) { attBonus -= 5; - explications.push("Attaquant à terre => -5 en Attaque"); + explications.push("Attaquant \xE0 terre => -5 en Attaque"); } let attrPosture = tokenAttribute(personnage, 'postureDeCombat'); if (attrPosture.length > 0) { @@ -11156,7 +11264,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'cadavreAnime')) { attBonus -= 4; - explications.push("Cadavre animé => -2 en Attaque"); + explications.push("Cadavre anim\xE9 => -2 en Attaque"); } let bonusCapitaine = aUnCapitaine(personnage, evt); if (bonusCapitaine) { @@ -11171,13 +11279,13 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(personnage, 'forceDeGeant')) { let bonusForceDeGeant = getIntValeurOfEffet(personnage, 'forceDeGeant', 2); attBonus += bonusForceDeGeant; - explications.push("Force de géant => +" + bonusForceDeGeant + " en Attaque"); + explications.push("Force de g\xE9ant => +" + bonusForceDeGeant + " en Attaque"); } if (attributeAsBool(personnage, 'nueeDInsectes')) { let malusNuee = 2 + attributeAsInt(personnage, 'nueeDInsectesTempeteDeManaIntense', 0); attBonus -= malusNuee; - explications.push("Nuée d\'insectes => -" + malusNuee + " en Attaque"); + explications.push("Nu\xE9e d\'insectes => -" + malusNuee + " en Attaque"); if (malusNuee > 2) removeTokenAttr(personnage, 'nueeDInsectesTempeteDeManaIntense', evt); } @@ -11185,13 +11293,13 @@ var COFantasy = COFantasy || function() { let malusNueeCriquets = 3 + attributeAsInt(personnage, 'nueeDeCriquetsTempeteDeManaIntense', 0); attBonus -= malusNueeCriquets; - explications.push("Nuée de criquets => -" + malusNueeCriquets + " en Attaque"); + explications.push("Nu\xE9e de criquets => -" + malusNueeCriquets + " en Attaque"); if (malusNueeCriquets > 3) removeTokenAttr(personnage, 'nueeDeCriquetsTempeteDeManaIntense', evt); } if (attributeAsBool(personnage, 'nueeDeScorpions')) { attBonus -= 3; - explications.push("Nuée de scorpions => -3 en Attaque"); + explications.push("Nu\xE9e de scorpions => -3 en Attaque"); } if (attributeAsBool(personnage, 'etatExsangue')) { attBonus -= 2; @@ -11199,7 +11307,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'armeBrulante')) { attBonus -= 2; - explications.push("Arme brûlante => -2 en Attaque"); + explications.push("Arme br\xFBlante => -2 en Attaque"); } if (marcheSylvestreActive(personnage)) { attBonus += 2; @@ -11207,11 +11315,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(personnage, 'prisonVegetale')) { attBonus -= getIntValeurOfEffet(personnage, 'prisonVegetale', 2); - explications.push("Prison végétale : -2 en Attaque"); + explications.push("Prison v\xE9g\xE9tale : -2 en Attaque"); } if (attributeAsBool(personnage, 'toiles')) { attBonus -= getIntValeurOfEffet(personnage, 'toiles', 2); - explications.push("Entravé : -2 en Attaque"); + explications.push("Entrav\xE9 : -2 en Attaque"); } if (attributeAsBool(personnage, 'masqueDuPredateur')) { let bonusMasque = getIntValeurOfEffet(personnage, 'masqueDuPredateur', modCarac(personnage, 'sagesse')); @@ -11219,10 +11327,10 @@ var COFantasy = COFantasy || function() { bonusMasque += masqueIntense; attBonus += bonusMasque; if (options && options.bonusDM !== undefined) { - explications.push("Masque du prédateur : +" + bonusMasque + " en Attaque et DM"); + explications.push("Masque du pr\xE9dateur : +" + bonusMasque + " en Attaque et DM"); options.bonusDM += bonusMasque; } else { - explications.push("Masque du prédateur : +" + bonusMasque + " en Attaque"); + explications.push("Masque du pr\xE9dateur : +" + bonusMasque + " en Attaque"); } if (masqueIntense) removeTokenAttr(personnage, 'masqueDuPredateurTempeteDeManaIntense', evt); @@ -11231,15 +11339,15 @@ var COFantasy = COFantasy || function() { getIntValeurOfEffet(personnage, 'masqueDuPredateurAmeLiee', 1); attBonus += bonusMasque; if (options && options.bonusDM !== undefined) { - explications.push("Masque du prédateur lié : +" + bonusMasque + " en Attaque et DM"); + explications.push("Masque du pr\xE9dateur li\xE9 : +" + bonusMasque + " en Attaque et DM"); options.bonusDM += bonusMasque; } else { - explications.push("Masque du prédateur lié : +" + bonusMasque + " en Attaque"); + explications.push("Masque du pr\xE9dateur li\xE9 : +" + bonusMasque + " en Attaque"); } } if (attributeAsBool(personnage, 'armeSecreteBarde')) { attBonus -= 10; - explications.push("Déstabilisé par une action de charme => -10 en Attaque"); + explications.push("D\xE9stabilis\xE9 par une action de charme => -10 en Attaque"); } if (attributeAsBool(personnage, 'espaceExigu')) { let bonusForce = modCarac(personnage, 'force'); @@ -11251,28 +11359,28 @@ var COFantasy = COFantasy || function() { attBonus -= 1; } if (attributeAsBool(personnage, 'agrippeParUnDemon')) { - explications.push("agrippé : -3 en Attaque"); + explications.push("agripp\xE9 : -3 en Attaque"); attBonus -= 3; } if (attributeAsBool(personnage, 'ondesCorruptrices') && !attributeAsBool(personnage, 'sangDeLArbreCoeur') && !predicateAsBool(personnage, 'porteurDuBouclierDeGrabuge')) { let malus = attributeAsInt(personnage, 'ondesCorruptrices', 2); - explications.push("nauséeux : -" + malus + " aux tests"); + explications.push("naus\xE9eux : -" + malus + " aux tests"); attBonus -= malus; } if (attributeAsBool(personnage, 'inconfort')) { let inconfortValeur = attributeAsInt(personnage, 'inconfortValeur', 0); attBonus -= inconfortValeur; - explications.push("Gêne due à l'armure : -" + inconfortValeur); + explications.push("G\xEAne due \xE0 l'armure : -" + inconfortValeur); } if (attributeAsBool(personnage, 'putrefactionOutreTombe')) { attBonus -= 2; - explications.push("Putréfaction => -2 en Attaque"); + explications.push("Putr\xE9faction => -2 en Attaque"); } if (attributeAsBool(personnage, 'secoue')) { attBonus -= 2; - let msg = "Secoué" + eForFemale(personnage) + " => -2 en Attaque"; + let msg = "Secou\xE9" + eForFemale(personnage) + " => -2 en Attaque"; explications.push(msg); } if (attributeAsBool(personnage, 'bonusAttaqueTemp')) { @@ -11293,7 +11401,7 @@ var COFantasy = COFantasy || function() { let bonus = getIntValeurOfEffet(personnage, 'detournerLeRegard', 2); let msg; if (bonus < 5) { - msg = "Détourne le regard"; + msg = "D\xE9tourne le regard"; } else { msg = "Ferme les yeux"; } @@ -11324,8 +11432,8 @@ var COFantasy = COFantasy || function() { switch (ficheAttribute(perso, 'taille', '').trim().toLowerCase()) { case "minuscule": return 1; - case "très petit": - case "très petite": + case "tr\xE8s petit": + case "tr\xE8s petite": case "tres petit": return 2; case "petit": @@ -11339,14 +11447,15 @@ var COFantasy = COFantasy || function() { case "grand": case "grande": return 5; - case "énorme": + case "\xE9norme": case "enorme": return 6; case "colossal": case "colossale": return 7; - default: //On passe à la méthode suivante + default: //On passe \xE0 la m\xE9thode suivante } + if (predicateAsBool(perso, 'petiteTaille')) return 3; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.trim().toLowerCase(); @@ -11366,7 +11475,7 @@ var COFantasy = COFantasy || function() { case 'demi-orque': case 'orque': case 'gnome': - case 'âme-forgée': + case '\xE2me-forg\xE9e': return 4; case 'centaure': case 'demi-ogre': @@ -11379,11 +11488,11 @@ var COFantasy = COFantasy || function() { //Retourne un encodage des tailes : // 1 : minuscule - // 2 : très petit + // 2 : tr\xE8s petit // 3 : petit // 4 : moyen // 5 : grand - // 6 : énorme + // 6 : \xE9norme // 7 : colossal function taillePersonnage(perso, def) { if (perso.taille) return perso.taille; @@ -11393,7 +11502,7 @@ var COFantasy = COFantasy || function() { return taille; } - //tm doit être stateCOF.tenebresMagiques, et bien défini. + //tm doit \xEAtre stateCOF.tenebresMagiques, et bien d\xE9fini. function eclaireParFioleDeLumiere(perso, tm) { let fio = tm.fioleDeLumiere; if (fio === undefined || fio.porteur === undefined) return false; @@ -11423,7 +11532,7 @@ var COFantasy = COFantasy || function() { if (options.difficultePVmax) { let pvmax = parseInt(target.token.get('bar1_max')); if (isNaN(pvmax)) { - error("Points de vie de " + nomPerso(target) + " mal formés", + error("Points de vie de " + nomPerso(target) + " mal form\xE9s", target.token.get('bar1_max')); return 0; } @@ -11431,7 +11540,7 @@ var COFantasy = COFantasy || function() { } else if (options.difficultePV) { let pv = parseInt(target.token.get('bar1_value')); if (isNaN(pv)) { - error("Points de vie de " + nomPerso(target) + " mal formés", + error("Points de vie de " + nomPerso(target) + " mal form\xE9s", target.token.get('bar1_value')); return 0; } @@ -11493,7 +11602,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'armureDuMage')) { let bonusArmureDuMage = getIntValeurOfEffet(target, 'armureDuMage', 4); - if (defense > 12) defense += bonusArmureDuMage / 2; // On a déjà une armure physique, ça ne se cumule pas. + if (defense > 12) defense += bonusArmureDuMage / 2; // On a d\xE9j\xE0 une armure physique, \xE7a ne se cumule pas. else defense += bonusArmureDuMage; } defense += ficheAttributeAsInt(target, 'DEFDIV', 0); @@ -11503,7 +11612,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(target, 'inconfort')) { let inconfortValeur = attributeAsInt(target, "inconfortValeur", 0); defense -= inconfortValeur; - explications.push("L'adversaire est gêné par son armure : -" + inconfortValeur + " en DEF"); + explications.push("L'adversaire est g\xEAn\xE9 par son armure : -" + inconfortValeur + " en DEF"); } let formeDarbre; if (attributeAsBool(target, 'formeDArbre')) { @@ -11512,12 +11621,12 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'statueDeBois')) defense = 10; else if (attributeAsBool(target, 'petrifie')) defense = 5; - // Malus de défense global pour les longs combats + // Malus de d\xE9fense global pour les longs combats let combat = stateCOF.combat; if (combat && reglesOptionelles.haute_DEF.val.usure_DEF.val && !combat.usureOff && combat.tour > 1) defense -= (Math.floor((combat.tour - 1) / reglesOptionelles.haute_DEF.val.usure_DEF.val) * 2); - // Autres modificateurs de défense + // Autres modificateurs de d\xE9fense defense += attributeAsInt(target, 'defenseTotale', 0); let pacifisme = predicateAsInt(target, 'pacifisme', 0, 5); if (pacifisme > 0 && !attributeAsBool(target, 'attributDeCombat_pacifismeAnnule')) @@ -11538,14 +11647,14 @@ var COFantasy = COFantasy || function() { bonusPeau = Math.ceil(bonusPeau * 1.5); } defense += bonusPeau; - explications.push("Peau d'écorce : +" + bonusPeau + " en DEF"); + explications.push("Peau d'\xE9corce : +" + bonusPeau + " en DEF"); if (peauIntense && evt && !options.test) removeTokenAttr(target, 'peauDEcorceTempeteDeManaIntense', evt); } if (attributeAsBool(target, 'peauDEcorceAmeLiee')) { let bonus = getIntValeurOfEffet(target, 'peauDEcorceAmeLiee', 1); defense += bonus; - explications.push("Peau d'écorce liée : +" + bonus + " en DEF"); + explications.push("Peau d'\xE9corce li\xE9e : +" + bonus + " en DEF"); } if (attributeAsBool(target, 'champDeProtection')) { let bonusChamp = @@ -11565,13 +11674,13 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'sixiemeSens')) { defense += 2; - explications.push("Sixième sens : +2 DEF"); + explications.push("Sixi\xE8me sens : +2 DEF"); } if (getState(target, 'surpris')) defense -= 5; if (getState(target, 'renverse')) defense -= 5; if (getState(target, 'aveugle') || attributeAsBool(target, 'aveugleManoeuvre')) { if (options.contact && predicateAsBool(target, 'radarMental') && attaquant && !estNonVivant(attaquant)) { - explications.push(tokenName + " est aveugle, mais bénéficie de son radar mental"); + explications.push(tokenName + " est aveugle, mais b\xE9n\xE9ficie de son radar mental"); } else { defense -= 5; } @@ -11581,7 +11690,7 @@ var COFantasy = COFantasy || function() { if (getState(target, 'invisible') && attaquant && !attributeAsBool(attaquant, 'detectionDeLInvisible')) { if (options.distance) { if (options.tirAveugle) { - explications.push("Cible invisible, mais " + nomPerso(attaquant) + " sait tirer à l'aveugle"); + explications.push("Cible invisible, mais " + nomPerso(attaquant) + " sait tirer \xE0 l'aveugle"); } else { defense += 10; explications.push("Invisible : +10 en DEF"); @@ -11617,13 +11726,13 @@ var COFantasy = COFantasy || function() { defense += modCarac(target, 'intelligence'); } if (attributeAsBool(target, 'armeSecreteBarde')) { - explications.push(tokenName + " est déstabilisé par une action de charme => -10 en DEF"); + explications.push(tokenName + " est d\xE9stabilis\xE9 par une action de charme => -10 en DEF"); defense -= 10; } if (options.metal && attributeAsBool(target, 'magnetisme')) { let magnetisme = getIntValeurOfEffet(target, 'magnetisme', 5); defense += magnetisme; - explications.push(tokenName + " contrôle le magnétisme (+" + magnetisme + " DEF)"); + explications.push(tokenName + " contr\xF4le le magn\xE9tisme (+" + magnetisme + " DEF)"); } if (attributeAsBool(target, 'diversionManoeuvre')) { let diversion = getIntValeurOfEffet(target, 'diversionManoeuvre', -5); @@ -11632,7 +11741,7 @@ var COFantasy = COFantasy || function() { } if (options.attaqueMentale && predicateAsBool(target, 'bouclierPsi')) { defense += 5; - explications.push(tokenName + " bénéficie d'un bouclier psi => +5 DEF"); + explications.push(tokenName + " b\xE9n\xE9ficie d'un bouclier psi => +5 DEF"); } if (attributeAsBool(target, 'monteSur')) { if (predicateAsBool(target, 'montureLoyale')) { @@ -11641,7 +11750,7 @@ var COFantasy = COFantasy || function() { } if (options.contact && predicateAsBool(target, "horsDePortee")) { defense += 5; - explications.push(tokenName + " est hors de portée sur sa monture => +5 DEF"); + explications.push(tokenName + " est hors de port\xE9e sur sa monture => +5 DEF"); } } let attrsProtegePar = findObjs({ @@ -11657,20 +11766,20 @@ var COFantasy = COFantasy || function() { evt.deletedAttributes = evt.deletedAttributes || []; evt.deletedAttributes.push(attr); attr.remove(); - sendPerso(target, "n'est plus protégé : son protecteur n'est pas sur la page"); + sendPerso(target, "n'est plus prot\xE9g\xE9 : son protecteur n'est pas sur la page"); } return; } let nameProtecteur = nomPerso(protecteur); if (!isActive(protecteur)) { - explications.push(nameProtecteur + " n'est pas en état de protéger " + + explications.push(nameProtecteur + " n'est pas en \xE9tat de prot\xE9ger " + tokenName); return; } let distTargetProtecteur = distanceCombat(target.token, protecteur.token, pageId); if (distTargetProtecteur > 0) { explications.push(nameProtecteur + " est trop loin de " + - tokenName + " pour le protéger"); + tokenName + " pour le prot\xE9ger"); return; } if (ficheAttributeAsInt(protecteur, 'defbouclieron', 0) === 0) { @@ -11684,7 +11793,7 @@ var COFantasy = COFantasy || function() { if (persoEstPNJ(protecteur)) defBouclierProtecteur = 2; else defBouclierProtecteur = ficheAttributeAsInt(protecteur, 'defbouclier', 0) + predicateAsInt(protecteur, 'bouclierDeLaFoi', 0, 1); defense += defBouclierProtecteur; - explications.push(nameProtecteur + " protège " + + explications.push(nameProtecteur + " prot\xE8ge " + tokenName + " de son bouclier (+" + defBouclierProtecteur + " DEF)"); } }); @@ -11706,7 +11815,7 @@ var COFantasy = COFantasy || function() { let attaqueAOutrance = attributeAsInt(target, 'attaqueAOutrance', 0); if (attaqueAOutrance) { defense -= attaqueAOutrance; - explications.push("Attaque à outrance => -" + attaqueAOutrance + " DEF"); + explications.push("Attaque \xE0 outrance => -" + attaqueAOutrance + " DEF"); } let niveau = ficheAttributeAsInt(target, 'niveau', 1); let instinctSurvie = predicateAsInt(target, 'instinctDeSurvie', 0, niveau * 5); @@ -11720,7 +11829,7 @@ var COFantasy = COFantasy || function() { defense += predicateAsInt(target, 'DEF_magie', 0); if (predicateAsBool(target, 'chasseurDeSorciere')) { defense += 2; - explications.push("Chasseur de sorcière => +2 DEF"); + explications.push("Chasseur de sorci\xE8re => +2 DEF"); } } if (marcheSylvestreActive(target)) { @@ -11729,11 +11838,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'prisonVegetale')) { defense -= getIntValeurOfEffet(target, 'prisonVegetale', 2); - explications.push("Prison végétale => -2 DEF"); + explications.push("Prison v\xE9g\xE9tale => -2 DEF"); } if (attributeAsBool(target, 'toiles')) { defense -= getIntValeurOfEffet(target, 'toiles', 2); - explications.push("Entravé => -2 DEF"); + explications.push("Entrav\xE9 => -2 DEF"); } if (attributeAsBool(target, 'protectionContreLeMal') && (attaquant && estMauvais(attaquant))) { @@ -11759,7 +11868,7 @@ var COFantasy = COFantasy || function() { explications.push(msgRage + " du berserk => " + modRage + " DEF"); defense += modRage; } else if (attributeAsBool(target, 'frenesieMinotaure')) { - explications.push("Frenésie => -2 en DEF"); + explications.push("Fren\xE9sie => -2 en DEF"); defense -= 2; } let combatEnPhalange = predicateAsBool(target, 'combatEnPhalange'); @@ -11816,36 +11925,36 @@ var COFantasy = COFantasy || function() { defense += predicateAsInt(target, 'voieDesRunes', 0, 1); if (attributeAsBool(target, 'attaqueRisquee')) { defense -= 4; - explications.push("Suite à une attaque risquée, -4 en DEF"); + explications.push("Suite \xE0 une attaque risqu\xE9e, -4 en DEF"); } let armeTarget = armesEnMain(target); //peuple target.arme et armeGauche - //gestion de l'épieu + //gestion de l'\xE9pieu if (attaquant) { if (armeTarget && armeTarget.epieu && !armesEnMain(attaquant)) { defense += 2; - explications.push("Épieu contre une attaque sans arme => +2 DEF"); + explications.push("\xC9pieu contre une attaque sans arme => +2 DEF"); } } if (options.distance) { let bonusCouvert = attributeAsInt(target, 'bonusCouvert'); if (bonusCouvert) { if (attaquant && predicateAsBool(attaquant, 'joliCoup')) { - explications.push("Cible à couvert, mais " + nomPerso(attaquant) + " sait bien viser"); + explications.push("Cible \xE0 couvert, mais " + nomPerso(attaquant) + " sait bien viser"); } else { defense += bonusCouvert; - explications.push("Cible à couvert => +" + bonusCouvert + " DEF"); + explications.push("Cible \xE0 couvert => +" + bonusCouvert + " DEF"); } } if (attributeAsBool(target, 'progresserACouvert')) { if (attaquant && predicateAsBool(attaquant, 'joliCoup')) { - explications.push("Cible à couvert de bouclier, mais " + nomPerso(attaquant) + " sait bien viser"); + explications.push("Cible \xE0 couvert de bouclier, mais " + nomPerso(attaquant) + " sait bien viser"); } else { defense += 5; - explications.push("Cible à couvert de bouclier => +5 DEF"); + explications.push("Cible \xE0 couvert de bouclier => +5 DEF"); } } } - //Chair à canon + //Chair \xE0 canon if (capaciteDisponible(target, 'chairACanon', 'tour')) { let tokensChairACanon = findObjs({ _type: 'graphic', @@ -11887,15 +11996,15 @@ var COFantasy = COFantasy || function() { switch (taillePersonnage(attaquant, 4)) { case 5: defense += 2; - explications.push(nomPerso(target) + " réduit la distance => +2 en DEF"); + explications.push(nomPerso(target) + " r\xE9duit la distance => +2 en DEF"); break; case 6: defense += 3; - explications.push(nomPerso(target) + " réduit la distance => +3 en DEF"); + explications.push(nomPerso(target) + " r\xE9duit la distance => +3 en DEF"); break; case 7: defense += 4; - explications.push(nomPerso(target) + " réduit la distance => +4 en DEF"); + explications.push(nomPerso(target) + " r\xE9duit la distance => +4 en DEF"); } } if (attaquant && predicateAsBool(target, 'insignifiant')) { @@ -11912,11 +12021,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'etreinteImmole')) { defense -= 5; - explications.push(nomPerso(target) + " étreint quelqu'un => -5 en DEF"); + explications.push(nomPerso(target) + " \xE9treint quelqu'un => -5 en DEF"); } if (attributeAsBool(target, 'etreinteScorpionRatee')) { defense -= 5; - explications.push(nomPerso(target) + " est étreint par un scorpion => -5 DEF"); + explications.push(nomPerso(target) + " est \xE9treint par un scorpion => -5 DEF"); } if (attaquant && predicateAsBool(target, 'langageSombreHetre') && estElfeNoir(attaquant)) { defense += 1; @@ -11924,7 +12033,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'presenceGlaciale')) { let defenseGlaciale = getIntValeurOfEffet(target, 'presenceGlaciale', 4); - explications.push("Présence glaciale => +" + defenseGlaciale + " en DEF"); + explications.push("Pr\xE9sence glaciale => +" + defenseGlaciale + " en DEF"); defense += defenseGlaciale; } if (attributeAsBool(target, 'cyclone')) { @@ -11956,24 +12065,24 @@ var COFantasy = COFantasy || function() { defense += 10; } if (options.contact && attributeAsBool(target, 'tenirADistance')) { - explications.push("Tient l'ennemi à distance => +5 en DEF"); + explications.push("Tient l'ennemi \xE0 distance => +5 en DEF"); defense += 5; } let tm = stateCOF.tenebresMagiques; if (tm) { if (estDemon(target)) { if (eclaireParFioleDeLumiere(target, tm)) { - explications.push("Aveuglé par la fiole de lumière => -2 en DEF"); + explications.push("Aveugl\xE9 par la fiole de lumi\xE8re => -2 en DEF"); defense -= 2; } } else if (attaquant && !eclaireParFioleDeLumiere(attaquant, tm)) { - explications.push("Ténèbres magiques => -5 en DEF"); + explications.push("T\xE9n\xE8bres magiques => -5 en DEF"); defense -= 5; } } if (attributeAsBool(target, 'agrippeParUnDemon')) { - explications.push("agrippé => -3 en DEF"); + explications.push("agripp\xE9 => -3 en DEF"); defense -= 3; } if (estNecromancie(options) && attributeAsBool(target, 'sangDeLArbreCoeur')) { @@ -11981,7 +12090,7 @@ var COFantasy = COFantasy || function() { defense += 5; } if (predicateAsBool(target, 'liberateurDeDorn') && estGeant(attaquant)) { - explications.push('Libérateur de Dorn => +2 en DEF'); + explications.push('Lib\xE9rateur de Dorn => +2 en DEF'); defense += 2; } let pirouettes = predicateAsInt(target, 'pirouettes', 0); @@ -11999,14 +12108,14 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(target, 'paradeCroisee')) { let bonus = getIntValeurOfEffet(target, 'paradeCroisee', 2); - explications.push("Parade croisée => +" + bonus + " en DEF"); + explications.push("Parade crois\xE9e => +" + bonus + " en DEF"); defense += bonus; } let conditions = attributeAsInt(target, 'conditionsHostiles', 0, 2); if (conditions > 0 && (!predicateAsBool(target, 'marcheSylvestre') || conditions > 4)) { let msgConditions = "Conditions "; if (conditions < 5) msgConditions += "hostiles"; - else msgConditions += "extrêmes"; + else msgConditions += "extr\xEAmes"; msgConditions += " : -" + conditions + " en DEF"; explications.push(msgConditions); defense -= conditions; @@ -12026,7 +12135,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(target, 'detournerLeRegard')) { let bonus = getIntValeurOfEffet(target, 'detournerLeRegard', 2); if (bonus < 5) { - explications.push("Détourne le regard => -" + bonus + " en DEF"); + explications.push("D\xE9tourne le regard => -" + bonus + " en DEF"); } else { explications.push("Ferme les yeux => -" + bonus + " en DEF"); } @@ -12034,13 +12143,16 @@ var COFantasy = COFantasy || function() { } defense += predicateAsInt(target, 'DEF', 0); if (attaquant && predicateAsBool(target, 'armeDeLEte') && predicateAsBool(attaquant, 'creatureDeLHiver')) { - explications.push("Protégé par une arme de l'été => +25 en DEF"); + explications.push("Prot\xE9g\xE9 par une arme de l'\xE9t\xE9 => +25 en DEF"); defense += 25; } + if (predicateAsBool(target, 'petiteTaille') && !attributeAsBool(target, 'agrandissement')) { + defense += 1; + } return defense; } - // renvoie l'attribut créé ou mis à jour + // renvoie l'attribut cr\xE9\xE9 ou mis \xE0 jour function setAttrDuree(perso, attr, duree, evt, msg, secret) { let options = { maxVal: getInit(), @@ -12050,23 +12162,23 @@ var COFantasy = COFantasy || function() { return setTokenAttr(perso, attr, duree, evt, options); } - //Tous les bonus de DM normalement calculés dans bonusAttaqueA + //Tous les bonus de DM normalement calcul\xE9s dans bonusAttaqueA function bonusDMA(attaquant, weaponName, evt, explications, options) { if (options.pasDeDmg) return; options.bonusDM = 0; if (attributeAsBool(attaquant, 'baroudHonneurActif')) { - explications.push(nomPerso(attaquant) + " porte une dernière attaque et s'effondre"); + explications.push(nomPerso(attaquant) + " porte une derni\xE8re attaque et s'effondre"); mort(attaquant, function(m) { explications.push(m); }, evt); removeTokenAttr(attaquant, 'baroudHonneurActif', evt); } if (attributeAsBool(attaquant, 'reactionViolente')) { - explications.push("Réaction violente => +1d6 DM"); + explications.push("R\xE9action violente => +1d6 DM"); options.reactionViolente = true; } if (attributeAsBool(attaquant, 'drainDeForce')) { - explications.push("Force drainée => -2 aux DM"); + explications.push("Force drain\xE9e => -2 aux DM"); options.drainDeForce = true; } if (options.contact) { @@ -12077,11 +12189,11 @@ var COFantasy = COFantasy || function() { explications.push(msg); } if (attributeAsBool(attaquant, 'enrage')) { - explications.push("Enragé => +1d6 DM"); + explications.push("Enrag\xE9 => +1d6 DM"); options.enrage = true; } if (attributeAsBool(attaquant, 'rage')) { - explications.push("Enragé => +2 DM"); + explications.push("Enrag\xE9 => +2 DM"); options.rage = true; } let rageBerserk = tokenAttribute(attaquant, 'rageDuBerserk'); @@ -12095,7 +12207,7 @@ var COFantasy = COFantasy || function() { options.rageBerserk = 1; } } else if (attributeAsBool(attaquant, 'frenesieMinotaure')) { - explications.push("Frénésie : +1d6 aux DM"); + explications.push("Fr\xE9n\xE9sie : +1d6 aux DM"); options.rageBerserk = 1; } if (predicateAsBool(attaquant, 'ambidextreDuelliste')) { @@ -12165,7 +12277,7 @@ var COFantasy = COFantasy || function() { let gobant = persoOfIdName(attrGobe[0].get('current'), attaquant.token.get('pageid')); if (gobant === undefined) { - error("Attribut estGobePar mal formé", attrGobe[0].get('current')); + error("Attribut estGobePar mal form\xE9", attrGobe[0].get('current')); attrGobe[0].remove(); unlockToken(attaquant, evt); } else { @@ -12184,7 +12296,7 @@ var COFantasy = COFantasy || function() { let energieImpie = attributeAsInt(attaquant, 'energieImpie', 0); if (energieImpie) { options.bonusDM += energieImpie; - explications.push("Énergie impie => +" + energieImpie + " DM"); + explications.push("\xC9nergie impie => +" + energieImpie + " DM"); } if (options.arcComposite) { let force = modCarac(attaquant, 'force'); @@ -12199,7 +12311,7 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(attaquant, 'fievreux')) { options.fievreux = true; - explications.push("Fiévreu" + onGenre(attaquant, 'x', 'se') + " => -2 DM"); + explications.push("Fi\xE9vreu" + onGenre(attaquant, 'x', 'se') + " => -2 DM"); } if (options.expertDuCombatDM && !options.pasDeDmg) { let valDesExpert = options.rolls.expertDuCombatDM || rollDePlus(6); @@ -12226,7 +12338,7 @@ var COFantasy = COFantasy || function() { let masqueIntense = attributeAsInt(attaquant, 'masqueDuPredateurTempeteDeManaIntense', 0); bonusMasque += masqueIntense; options.bonusDM += bonusMasque; - explications.push("Masque du prédateur : +" + bonusMasque + " aux DM"); + explications.push("Masque du pr\xE9dateur : +" + bonusMasque + " aux DM"); if (masqueIntense) removeTokenAttr(attaquant, 'masqueDuPredateurTempeteDeManaIntense', evt); } else if (attributeAsBool(attaquant, 'masqueDuPredateurAmeLiee')) { @@ -12234,7 +12346,7 @@ var COFantasy = COFantasy || function() { getIntValeurOfEffet(attaquant, 'masqueDuPredateurAmeLiee', 1); if (bonusMasque > 0) { options.bonusDM += bonusMasque; - explications.push("Masque du prédateur lié : +" + bonusMasque + " aux DM"); + explications.push("Masque du pr\xE9dateur li\xE9 : +" + bonusMasque + " aux DM"); } } if (options.attaqueFlamboyante && options.contact) { @@ -12247,7 +12359,7 @@ var COFantasy = COFantasy || function() { let bonus = getIntValeurOfEffet(attaquant, 'detournerLeRegard', 2); let msg; if (bonus < 5) { - msg = "Détourne le regard"; + msg = "D\xE9tourne le regard"; } else { msg = "Ferme les yeux"; } @@ -12258,7 +12370,7 @@ var COFantasy = COFantasy || function() { return; } - //Bonus en Attaque qui ne dépendent pas du défenseur + //Bonus en Attaque qui ne d\xE9pendent pas du d\xE9fenseur //Remplit le champs options.bonusDM (en partant de 0) function bonusAttaqueA(attaquant, weaponName, evt, explications, options) { let attBonus = 0; @@ -12270,18 +12382,18 @@ var COFantasy = COFantasy || function() { attBonus += 2; if (options.tirDouble.stats && options.tirDouble.stats.name) { explications.push(nomPerso(attaquant) + " tire avec " + - weaponName + " et " + options.tirDouble.stats.name + " à la fois !"); + weaponName + " et " + options.tirDouble.stats.name + " \xE0 la fois !"); } else { explications.push(nomPerso(attaquant) + " tire avec 2 " + - weaponName + "s à la fois !"); + weaponName + "s \xE0 la fois !"); } } if (options.chance) { attBonus += options.chance; let pc = options.chance / 10; - explications.push(pc + " point" + ((pc > 1) ? "s" : "") + " de chance dépensé => +" + options.chance + " en Attaque"); + explications.push(pc + " point" + ((pc > 1) ? "s" : "") + " de chance d\xE9pens\xE9 => +" + options.chance + " en Attaque"); } - if (options.semonce) { + if (options.semonce && attributeAsInt(attaquant, 'attaqueADistanceRatee', 0) == 1) { attBonus += 5; } if (!options.pasDeDmg && !options.feinte) { @@ -12297,7 +12409,7 @@ var COFantasy = COFantasy || function() { } if (options.attaqueAssuree) { attBonus += 5; - explications.push("Attaque assurée => +5 en Attaque et DM/2"); + explications.push("Attaque assur\xE9e => +5 en Attaque et DM/2"); } if (ficheAttributeAsBool(attaquant, 'attaque_dm_temp_check')) { options.attaqueDmTemp = true; @@ -12321,11 +12433,11 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(attaquant, 'criDuPredateur')) { attBonus += 1; - explications.push("Cri du prédateur => +1 en attaque"); + explications.push("Cri du pr\xE9dateur => +1 en attaque"); } if (attributeAsBool(attaquant, 'baroudHonneurActif')) { attBonus += 5; - explications.push(nomPerso(attaquant) + " porte une dernière attaque et s'effondre"); + explications.push(nomPerso(attaquant) + " porte une derni\xE8re attaque et s'effondre"); mort(attaquant, function(m) { explications.push(m); }, evt); @@ -12340,7 +12452,7 @@ var COFantasy = COFantasy || function() { let cavalierEm = predicateAsInt(attaquant, 'cavalierEmerite'); if (cavalierEm) { attBonus += cavalierEm; - let explCavalierEmerite = "avalier émérite => +" + cavalierEm + " en Attaque"; + let explCavalierEmerite = "avalier \xE9m\xE9rite => +" + cavalierEm + " en Attaque"; if (options.displayName) { explCavalierEmerite = nomPerso(attaquant) + " est un c" + explCavalierEmerite; } else { @@ -12364,15 +12476,15 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(attaquant, 'reactionViolente')) { attBonus += 2; if (options.pasDeDmg) - explications.push("Réaction violente => +2 en Attaque"); + explications.push("R\xE9action violente => +2 en Attaque"); else { - explications.push("Réaction violente => +2 en Attaque et +1d6 DM"); + explications.push("R\xE9action violente => +2 en Attaque et +1d6 DM"); options.reactionViolente = true; } } if (attributeAsBool(attaquant, 'drainDeForce')) { attBonus -= 2; - let msg = "Force drainée => -2 en Attaque"; + let msg = "Force drain\xE9e => -2 en Attaque"; if (options.pasDeDmg || !options.contact) explications.push(msg); else explications.push(msg + " et aux DM"); options.drainDeForce = true; @@ -12380,7 +12492,7 @@ var COFantasy = COFantasy || function() { let energieImpie = attributeAsInt(attaquant, 'energieImpie', 0); if (energieImpie) { attBonus += energieImpie; - let msg = "Énergie impie => +" + energieImpie + " en Attaque"; + let msg = "\xC9nergie impie => +" + energieImpie + " en Attaque"; if (!options.pasDeDmg) { msg += " et aux DM"; options.bonusDM += energieImpie; @@ -12400,21 +12512,21 @@ var COFantasy = COFantasy || function() { attBonus += 5; options.enrage = true; if (options.pasDeDmg) - explications.push("Enragé => +5 en Attaque"); + explications.push("Enrag\xE9 => +5 en Attaque"); else - explications.push("Enragé => +5 en Attaque et +1d6 DM"); + explications.push("Enrag\xE9 => +5 en Attaque et +1d6 DM"); } if (attributeAsBool(attaquant, 'rage')) { attBonus += 2; if (options.pasDeDmg) - explications.push("Enragé => +2 en Attaque"); + explications.push("Enrag\xE9 => +2 en Attaque"); else - explications.push("Enragé => +2 en Attaque et +2 DM"); + explications.push("Enrag\xE9 => +2 en Attaque et +2 DM"); options.rage = true; } if (attributeAsBool(attaquant, 'aspectDuDemon')) { attBonus += getIntValeurOfEffet(attaquant, 'aspectDuDemon', 2); - explications.push("Aspect de démon => +2 en Attaque"); + explications.push("Aspect de d\xE9mon => +2 en Attaque"); } let rageBerserk = tokenAttribute(attaquant, 'rageDuBerserk'); if (rageBerserk.length > 0) { @@ -12441,9 +12553,9 @@ var COFantasy = COFantasy || function() { } else if (attributeAsBool(attaquant, 'frenesieMinotaure')) { attBonus += 2; if (options.pasDeDmg) - explications.push("Frénésie : +2 en Attaque"); + explications.push("Fr\xE9n\xE9sie : +2 en Attaque"); else - explications.push("Frénésie : +2 en Attaque et +1d6 aux DM"); + explications.push("Fr\xE9n\xE9sie : +2 en Attaque et +1d6 aux DM"); options.rageBerserk = 1; } if (ficheAttributeAsBool(attaquant, 'attaque_risquee_check')) { @@ -12451,7 +12563,7 @@ var COFantasy = COFantasy || function() { } if (options.attaqueRisquee) { attBonus += 2; - explications.push("Attaque risquée => +2 en Attaque"); + explications.push("Attaque risqu\xE9e => +2 en Attaque"); if (!options.test) { setAttrDuree(attaquant, 'attaqueRisquee', 1, evt); } @@ -12510,7 +12622,7 @@ var COFantasy = COFantasy || function() { pv = parseInt(attaquant.token.get('bar1_value')); if (pv <= frenesie) { attBonus += 2; - explications.push("Frénésie => +2 en Attaque"); + explications.push("Fr\xE9n\xE9sie => +2 en Attaque"); } } if (predicateAsBool(attaquant, 'hausserLeTon')) { @@ -12554,18 +12666,18 @@ var COFantasy = COFantasy || function() { } if (attributeAsBool(attaquant, 'enerve')) { attBonus -= 2; - explications.push("Attaquant énervé => -2 en Attaque"); + explications.push("Attaquant \xE9nerv\xE9 => -2 en Attaque"); } if (attributeAsBool(attaquant, 'osBrises')) { attBonus -= 2; - explications.push("Des os sont brisés => -2 en Attaque"); + explications.push("Des os sont bris\xE9s => -2 en Attaque"); } let attrGobe = tokenAttribute(attaquant, 'estGobePar'); if (attrGobe.length > 0) { let gobant = persoOfIdName(attrGobe[0].get('current'), attaquant.token.get('pageid')); if (gobant === undefined) { - error("Attribut estGobePar mal formé", attrGobe[0].get('current')); + error("Attribut estGobePar mal form\xE9", attrGobe[0].get('current')); attrGobe[0].remove(); unlockToken(attaquant, evt); } else { @@ -12607,7 +12719,7 @@ var COFantasy = COFantasy || function() { } if (actif) { attBonus += 1; - explications.push("Arme de prédiléction => +1 en Attaque"); + explications.push("Arme de pr\xE9dil\xE9ction => +1 en Attaque"); } } if (options.arcComposite) { @@ -12630,7 +12742,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(attaquant, 'fievreux')) { attBonus -= 2; options.fievreux = true; - explications.push("Fiévreu" + onGenre(attaquant, 'x', 'se') + " => -2 en Att. et DM"); + explications.push("Fi\xE9vreu" + onGenre(attaquant, 'x', 'se') + " => -2 en Att. et DM"); } if (options.expertDuCombatTouche) { let valDesExpert = options.rolls.expertDuCombatTouche || rollDePlus(6); @@ -12703,7 +12815,7 @@ var COFantasy = COFantasy || function() { if (conditions > 0 && (!predicateAsBool(attaquant, 'marcheSylvestre') || conditions > 4)) { let msgConditions = "Conditions "; if (conditions < 5) msgConditions += "hostiles"; - else msgConditions += "extrêmes"; + else msgConditions += "extr\xEAmes"; msgConditions += " : -" + conditions + " en attaque"; explications.push(msgConditions); attBonus -= conditions; @@ -12742,12 +12854,12 @@ var COFantasy = COFantasy || function() { return attBonus; } - //Tous les bonus de DM normalement calculés dans bonusAttaqueD + //Tous les bonus de DM normalement calcul\xE9s dans bonusAttaqueD function bonusDMD(attaquant, target, portee, pageId, evt, explications, options) { let chasseurEmerite = predicateAsBool(attaquant, 'chasseurEmerite') && estAnimal(target); if (chasseurEmerite) { - let explChasseurEmerite = "hasseur émérite => +2 aux DM"; + let explChasseurEmerite = "hasseur \xE9m\xE9rite => +2 aux DM"; if (options.displayName) { explChasseurEmerite = nomPerso(attaquant) + ' est un c' + explChasseurEmerite; } else { @@ -12766,7 +12878,7 @@ var COFantasy = COFantasy || function() { }); }); if (ennemiJure) { - let explEnnemiJure = "Attaque sur ennemi juré => + 1d6 aux DM"; + let explEnnemiJure = "Attaque sur ennemi jur\xE9 => + 1d6 aux DM"; if (options.aoe) explEnnemiJure += " contre " + nomPerso(target); explications.push(explEnnemiJure); target.ennemiJure = true; @@ -12792,7 +12904,7 @@ var COFantasy = COFantasy || function() { let attrFeinte = tokenAttribute(target, 'feinte_' + nomPerso(attaquant)); if (attrFeinte.length > 0 && attrFeinte[0].get('current')) { let niveauTouche = attrFeinte[0].get('max'); - if (niveauTouche > 0) { //La feinte avait touché cette cible + if (niveauTouche > 0) { //La feinte avait touch\xE9 cette cible let msgFeinte = "Feinte => "; let faireMouche = predicateAsInt(attaquant, 'faireMouche', 0); if (faireMouche > 0) { @@ -12817,7 +12929,7 @@ var COFantasy = COFantasy || function() { let cibleAgrippee = persoOfIdName(a.get('current'), pageId); if (cibleAgrippee && cibleAgrippee.id == target.id && !attributeAsBool(cibleAgrippee, 'agrippeParUnDemon')) { - explications.push("Cible agrippée => +1d6 DM"); + explications.push("Cible agripp\xE9e => +1d6 DM"); target.estAgrippee = true; } }); @@ -12840,15 +12952,15 @@ var COFantasy = COFantasy || function() { } } if (predicateAsBool(attaquant, 'liberateurDeDorn') && estGeant(target)) { - explications.push("Libérateur de Dorn => +2d6 DM"); + explications.push("Lib\xE9rateur de Dorn => +2d6 DM"); target.cibleLiberateurDeDorn = true; } if (predicateAsBool(attaquant, 'liberateurDeKerserac') && (estGeant(target) || estInsecte(target) || estElfeNoir(target))) { - explications.push("Libérateur de Kerserac => +1d6 DM"); + explications.push("Lib\xE9rateur de Kerserac => +1d6 DM"); target.cibleLiberateurDeKerserac = true; } if (predicateAsBool(attaquant, 'liberateurDAnathazerin') && (estInsecte(target) || estElfeNoir(target))) { - explications.push("Libérateur d'Anathazerïn => +2d6 DM"); + explications.push("Lib\xE9rateur d'Anathazer\xEFn => +2d6 DM"); target.cibleLiberateurDAnathazerin = true; } let attrMeneurCible = tokenAttribute(target, 'meneurDHommesCible'); @@ -12858,7 +12970,7 @@ var COFantasy = COFantasy || function() { if (meneurDHommes && alliesParPerso[meneurDHommes.charId] && alliesParPerso[meneurDHommes.charId].has(attaquant.charId)) { target.cibleMeneurDHommes = true; - explications.push(nomPerso(meneurDHommes) + " a désigné " + nomPerso(target) + + explications.push(nomPerso(meneurDHommes) + " a d\xE9sign\xE9 " + nomPerso(target) + " comme la cible des attaques du groupe : +1d6 DM"); } } @@ -12874,22 +12986,22 @@ var COFantasy = COFantasy || function() { return; } - //Bonus d'attaque qui dépendent de la cible + //Bonus d'attaque qui d\xE9pendent de la cible function bonusAttaqueD(attaquant, target, portee, pageId, evt, explications, options) { let attBonus = 0; if (target.bonusAttaque) attBonus += target.bonusAttaque; if (getState(attaquant, 'aveugle')) { if (options.distance) { if (options.tirAveugle) { - explications.push("Attaquant aveuglé, mais il sait tirer à l'aveugle"); + explications.push("Attaquant aveugl\xE9, mais il sait tirer \xE0 l'aveugle"); } else { attBonus -= 10; - explications.push("Attaquant aveuglé => -10 en Attaque à distance"); + explications.push("Attaquant aveugl\xE9 => -10 en Attaque \xE0 distance"); } } else { if (!predicateAsBool(attaquant, 'radarMental') || estNonVivant(target)) { attBonus -= 5; - explications.push("Attaquant aveuglé => -5 en Attaque"); + explications.push("Attaquant aveugl\xE9 => -5 en Attaque"); } } } else if (attributeAsBool(attaquant, 'aveugleManoeuvre')) { @@ -12897,24 +13009,24 @@ var COFantasy = COFantasy || function() { attBonus -= 5; options.aveugleManoeuvre = true; if (options.pasDeDmg) - explications.push("Attaquant aveuglé => -5 en Attaque"); + explications.push("Attaquant aveugl\xE9 => -5 en Attaque"); else - explications.push("Attaquant aveuglé => -5 en Attaque et aux DM"); + explications.push("Attaquant aveugl\xE9 => -5 en Attaque et aux DM"); } } else if (getState(attaquant, 'invisible') && !attributeAsBool(target, 'detectionDeLInvisible')) { attBonus += 5; explications.push("Attaque venant d'un personnage invisible => +5 en Attaque"); } else if (options.distance && getState(attaquant, 'penombre')) { if (options.tirAveugle) { - explications.push("Attaquant dans la pénombre, mais il sait tirer à l'aveugle"); + explications.push("Attaquant dans la p\xE9nombre, mais il sait tirer \xE0 l'aveugle"); } else { attBonus -= 5; - explications.push("Attaquant dans la pénombre => -5 en Attaque à distance"); + explications.push("Attaquant dans la p\xE9nombre => -5 en Attaque \xE0 distance"); } } if (options.mainsDEnergie) { - if (options.aoe) error("Mains d'énergie n'est pas compatible avec les AOE", options.aoe); - // On vérifie si la cible porte une armure + if (options.aoe) error("Mains d'\xE9nergie n'est pas compatible avec les AOE", options.aoe); + // On v\xE9rifie si la cible porte une armure let targetArmorDef = 0; if (persoEstPNJ(target)) { if (ficheAttributeAsBool(target, 'defarmureon', false)) targetArmorDef = 5; @@ -12923,11 +13035,11 @@ var COFantasy = COFantasy || function() { } if (isNaN(targetArmorDef) || targetArmorDef === 0) { attBonus += 2; - explications.push("Mains d'énergie => +2 en Attaque (cible sans armure)"); + explications.push("Mains d'\xE9nergie => +2 en Attaque (cible sans armure)"); } else { let bonusMain = Math.min(5, 2 + targetArmorDef); attBonus += bonusMain; - explications.push("Mains d'énergie => +" + bonusMain + " en Attaque"); + explications.push("Mains d'\xE9nergie => +" + bonusMain + " en Attaque"); } } if (options.aoe === undefined && options.auto === undefined && portee > 0) { @@ -12939,7 +13051,7 @@ var COFantasy = COFantasy || function() { predicateAsBool(attaquant, 'chasseurEmerite') && estAnimal(target); if (chasseurEmerite) { attBonus += 2; - let explChasseurEmerite = "hasseur émérite => +2 en Attaque"; + let explChasseurEmerite = "hasseur \xE9m\xE9rite => +2 en Attaque"; if (options.displayName) { explChasseurEmerite = nomPerso(attaquant) + ' est un c' + explChasseurEmerite; } else { @@ -12961,7 +13073,7 @@ var COFantasy = COFantasy || function() { if (ennemiJure) { let ejSag = modCarac(attaquant, 'sagesse'); attBonus += ejSag; - let explEnnemiJure = "Attaque sur ennemi juré => +" + ejSag + " en attaque"; + let explEnnemiJure = "Attaque sur ennemi jur\xE9 => +" + ejSag + " en attaque"; if (!options.pasDeDmg) explEnnemiJure += " et +1d6 aux DM"; if (options.aoe) explEnnemiJure += " contre " + nomPerso(target); explications.push(explEnnemiJure); @@ -12996,9 +13108,9 @@ var COFantasy = COFantasy || function() { if (options.tueurDeGeants && estGeant(target)) { attBonus += 2; if (options.pasDeDmg) - explications.push("Tueur de géant => +2 en Attaque"); + explications.push("Tueur de g\xE9ant => +2 en Attaque"); else - explications.push("Tueur de géant => +2 att. et 2d6 DM"); + explications.push("Tueur de g\xE9ant => +2 att. et 2d6 DM"); target.tueurDeGeants = true; } if (options.tueurDe) { @@ -13022,7 +13134,7 @@ var COFantasy = COFantasy || function() { attBonus += bonusFeinte; let msgFeinte = "Feinte => +" + bonusFeinte + " en attaque"; let niveauTouche = attrFeinte[0].get('max'); - if (niveauTouche > 0) { //La feinte avait touché cette cible + if (niveauTouche > 0) { //La feinte avait touch\xE9 cette cible let faireMouche = predicateAsInt(attaquant, 'faireMouche', 0); if (faireMouche > 0) { if (options.contact && !options.pasDeDmg) { @@ -13038,7 +13150,6 @@ var COFantasy = COFantasy || function() { if (options.attaqueFlamboyanteBonus) msgFeinte += "+" + options.attaqueFlamboyanteBonus; msgFeinte += " DM"; - } } } @@ -13052,7 +13163,7 @@ var COFantasy = COFantasy || function() { }); if (expose) { attBonus += 10; - explications.push("L'adversaire est exposé : +10"); + explications.push("L'adversaire est expos\xE9 : +10"); } } if (options.contact) { @@ -13061,7 +13172,7 @@ var COFantasy = COFantasy || function() { ficheAttributeAsInt(attaquant, 'force', 10) <= ficheAttributeAsInt(target, 'force', 10) && parseInt(attaquant.token.get("bar1_max")) <= parseInt(target.token.get("bar1_max"))) { attBonus -= 2; - explications.push("Effrayé => -2 en Attaque"); + explications.push("Effray\xE9 => -2 en Attaque"); } } let attrAgrippe = tokenAttribute(attaquant, 'agrippe'); @@ -13071,9 +13182,9 @@ var COFantasy = COFantasy || function() { !attributeAsBool(cibleAgrippee, 'agrippeParUnDemon')) { attBonus += 5; if (options.pasDeDmg) - explications.push("Cible agrippée => +5 em Attaque"); + explications.push("Cible agripp\xE9e => +5 em Attaque"); else - explications.push("Cible agrippée => +5 att. et 1d6 DM"); + explications.push("Cible agripp\xE9e => +5 att. et 1d6 DM"); target.estAgrippee = true; } }); @@ -13090,7 +13201,7 @@ var COFantasy = COFantasy || function() { _pageid: pageId, layer: 'objects' }); - //On compte les tokens au contact de l'attaquant et du défenseur et alliés de l'attaquant + //On compte les tokens au contact de l'attaquant et du d\xE9fenseur et alli\xE9s de l'attaquant let allies = alliesParPerso[attaquant.charId]; if (allies) { let alliesAuContact = 0; @@ -13112,7 +13223,7 @@ var COFantasy = COFantasy || function() { } } } - if (options.attaqueEnMeute) { + if (options.attaqueEnMeute || alliesDAttaqueEnMeute.has(attaquant.charId)) { let attaqueParMeute = tokenAttribute(target, 'attaqueParMeute'); if (attaqueParMeute.length > 0) { attaqueParMeute = attaqueParMeute[0]; @@ -13126,7 +13237,7 @@ var COFantasy = COFantasy || function() { } autreAttaquant = true; }); - if (autreAttaquant) { + if (autreAttaquant && options.attaqueEnMeute) { attBonus += options.attaqueEnMeute; explications.push("Attaque en meute => +" + options.attaqueEnMeute + " pour toucher"); } @@ -13148,7 +13259,7 @@ var COFantasy = COFantasy || function() { if (tm) { if (estDemon(attaquant)) { if (eclaireParFioleDeLumiere(attaquant, tm)) { - explications.push("Aveuglé par la fiole de lumière => -2 en Attaque"); + explications.push("Aveugl\xE9 par la fiole de lumi\xE8re => -2 en Attaque"); attBonus -= 2; } } else if (!eclaireParFioleDeLumiere(target, tm)) { @@ -13173,34 +13284,34 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(attaquant, 'liberateurDeDorn') && estGeant(target)) { attBonus += 2; if (options.pasDeDmg) { - explications.push("Libérateur de Dorn => +2 en attaque"); + explications.push("Lib\xE9rateur de Dorn => +2 en attaque"); } else { - explications.push("Libérateur de Dorn => +2 en attaque et +2d6 DM"); + explications.push("Lib\xE9rateur de Dorn => +2 en attaque et +2d6 DM"); target.cibleLiberateurDeDorn = true; } } if (predicateAsBool(attaquant, 'liberateurDeKerserac') && (estGeant(target) || estInsecte(target) || estElfeNoir(target))) { attBonus += 2; if (options.pasDeDmg) { - explications.push("Libérateur de Kerserac => +2 en attaque"); + explications.push("Lib\xE9rateur de Kerserac => +2 en attaque"); } else { - explications.push("Libérateur de Kerserac => +2 en attaque et +1d6 DM"); + explications.push("Lib\xE9rateur de Kerserac => +2 en attaque et +1d6 DM"); target.cibleLiberateurDeKerserac = true; } } if (predicateAsBool(attaquant, 'liberateurDAnathazerin') && (estInsecte(target) || estElfeNoir(target))) { attBonus += 2; if (options.pasDeDmg) { - explications.push("Libérateur d'Anathazerïn => +2 en attaque"); + explications.push("Lib\xE9rateur d'Anathazer\xEFn => +2 en attaque"); } else { - explications.push("Libérateur d'Anathazerïn => +2 en attaque et +2d6 DM"); + explications.push("Lib\xE9rateur d'Anathazer\xEFn => +2 en attaque et +2d6 DM"); target.cibleLiberateurDAnathazerin = true; } } if (predicateAsBool(attaquant, 'tenacite')) { let bonus = attributeAsInt(target, 'attributDeCombat_tenaciteDe' + nomPerso(attaquant), 0); if (bonus > 0) { - explications.push("Ténacité => +" + bonus + " en attaque"); + explications.push("T\xE9nacit\xE9 => +" + bonus + " en attaque"); attBonus += bonus; } } @@ -13212,7 +13323,7 @@ var COFantasy = COFantasy || function() { alliesParPerso[meneurDHommes.charId].has(attaquant.charId)) { attBonus += 2; if (!options.pasDeDmg) target.cibleMeneurDHommes = true; - explications.push(nomPerso(meneurDHommes) + " a désigné " + nomPerso(target) + + explications.push(nomPerso(meneurDHommes) + " a d\xE9sign\xE9 " + nomPerso(target) + " comme la cible des attaques du groupe : +2 attaque, +1d6 DM"); } } @@ -13278,14 +13389,14 @@ var COFantasy = COFantasy || function() { if (res.length === 0) { let ace = tokenAttribute(perso, classeEffet); if (ace.length > 0) { - error(nomPerso(perso) + " a une classe d'effets " + classeEffet + " mais pas d'effet associé", ace); + error(nomPerso(perso) + " a une classe d'effets " + classeEffet + " mais pas d'effet associ\xE9", ace); ace[0].remove(); } } return res; } - //Si le dépassement de limite est possible, renvoie un nouveau depMana, sinon renvoie false + //Si le d\xE9passement de limite est possible, renvoie un nouveau depMana, sinon renvoie false function depasseLimite(perso, nomAttr, msgImpossible, msg, evt, options) { if (options.depasseLimite) { options.mana = options.mana || 0; @@ -13302,8 +13413,84 @@ var COFantasy = COFantasy || function() { return false; } - //Retourne true si il existe une limite qui empêche de lancer le sort - //N'ajoute pas l'événement à l'historique + //Retourne false si il existe la limitePar+type qui emp\xEAche de faire l'action + // type peut \xEAtre Jour, Combat ou Tour + // si c'est ok, renvoie depMana, \xE9ventuellement mis \xE0 jour + function testLimitePar(perso, type, options, depMana, defRessource, msg, evt, explications) { + let nom = 'limitePar' + type; + let opt = options[nom]; + if (opt) { + let msgType = ''; + let temps = ''; + switch (type) { + case 'Jour': + msgType = "journali\xE8re"; + temps = "aujourd'hui"; + break; + case 'Combat': + if (!stateCOF.combat) { + sendPerso(perso, "ne peut pas faire cette action en dehors des combats", options.secret); + return false; + } + msgType = "par combat"; + temps = "pour ce combat"; + break; + case 'Tour': + if (!stateCOF.combat) { + sendPerso(perso, "ne peut pas faire cette action en dehors des combats", options.secret); + return false; + } + msgType = "par tour"; + temps = "durant ce tour"; + break; + } + if (!perso) { + error("Impossible de savoir \xE0 qui appliquer la limite " + msgType, options); + return false; + } + let ressource = nom + '_'; + if (opt.ressource) + ressource += opt.ressource; + else + ressource += defRessource; + let limite = 0; + if (opt.val) limite = opt.val; + else if (opt.predicat) + limite = predicateAsInt(perso, opt.predicat, 0, 1); + else { + error("Limite " + msgType + " mal form\xE9e", opt); + return false; + } + let utilisations = attributeAsInt(perso, ressource, limite); + if (utilisations === 0) { + depMana = depasseLimite(perso, ressource, "ne peut plus faire cette action " + temps, msg, evt, options); + if (depMana) utilisations = 1; + else return false; + } + setTokenAttr(perso, ressource, utilisations - 1, evt); + if (opt.ressource) { + let msgLimite = nomPerso(perso) + " "; + if (utilisations < 2) msgLimite += "ne pourra plus utiliser "; + else { + msgLimite += "pourra encore utiliser "; + if (utilisations == 2) msgLimite += "une fois "; + else msgLimite += (utilisations - 1) + " fois "; + } + msgLimite += opt.ressource + " " + temps; + if (explications) { + stateCOF.afterDisplay = stateCOF.afterDisplay || []; + stateCOF.afterDisplay.push({ + msg: msgLimite, + destinataire: perso + }); + } else sendPerso(perso, msgLimite, true); + } + } + return depMana; + } + + //Retourne true si il existe une limite qui emp\xEAche de lancer le sort + //N'ajoute pas l'\xE9v\xE9nement \xE0 l'historique //explications est optionnel function limiteRessources(personnage, options, defResource, msg, evt, explications) { let depMana = { @@ -13327,8 +13514,8 @@ var COFantasy = COFantasy || function() { } if (m > 0) { if (reglesOptionelles.mana.val.mana_totale.val) options.mana += m; - //Le plus cohérent avec la mana totale consiste à diviser ce malus par 3, - //arrondi au supérieur + //Le plus coh\xE9rent avec la mana totale consiste \xE0 diviser ce malus par 3, + //arrondi au sup\xE9rieur else options.mana += Math.ceil(m / 3); } } @@ -13337,127 +13524,17 @@ var COFantasy = COFantasy || function() { depMana = depenseManaPossible(personnage, options.mana, msg); if (!depMana) return true; } else { - error("Impossible de savoir qui doit dépenser de la mana", options); - return true; - } - } - let ressource = ''; - if (defResource !== undefined) ressource = defResource; - let utilisations; - if (options.limiteParJour) { - if (!personnage) { - error("Impossible de savoir à qui appliquer la limite journalière", options); - return true; - } - if (options.limiteParJourRessource) - ressource = "limiteParJour_" + options.limiteParJourRessource; - else - ressource = "limiteParJour_" + defResource; - utilisations = - attributeAsInt(personnage, ressource, options.limiteParJour); - if (utilisations === 0) { - depMana = depasseLimite(personnage, ressource, "ne peut plus faire cette action aujourd'hui", msg, evt, options); - if (depMana) utilisations = 1; - else return true; - } - setTokenAttr(personnage, ressource, utilisations - 1, evt); - if (options.limiteParJourRessource) { - let msgJour = nomPerso(personnage) + " "; - if (utilisations < 2) msgJour += "ne pourra plus utiliser "; - else { - msgJour += "pourra encore utiliser "; - if (utilisations == 2) msgJour += "une fois "; - else msgJour += (utilisations - 1) + " fois "; - } - msgJour += options.limiteParJourRessource + " aujourd'hui."; - if (explications) { - stateCOF.afterDisplay = stateCOF.afterDisplay || []; - stateCOF.afterDisplay.push({ - msg: msgJour, - destinataire: personnage - }); - } else sendPerso(personnage, msgJour, true); - } - } - if (options.limiteParCombat) { - if (personnage) { - if (!stateCOF.combat) { - sendPerso(personnage, "ne peut pas faire cette action en dehors des combats", options.secret); - return true; - } - if (options.limiteParCombatRessource) - ressource = "limiteParCombat_" + options.limiteParCombatRessource; - else - ressource = "limiteParCombat_" + defResource; - utilisations = - attributeAsInt(personnage, ressource, options.limiteParCombat); - if (utilisations === 0) { - let msgToSend = "ne peut plus faire cette action pour ce combat"; - sendPerso(personnage, msgToSend, options.secret); - return true; - } - setTokenAttr(personnage, ressource, utilisations - 1, evt); - if (options.limiteParCombatRessource) { - let msgCombat = nomPerso(personnage) + " "; - if (utilisations < 2) msgCombat += "ne pourra plus utiliser "; - else { - msgCombat += "pourra encore utiliser "; - if (utilisations == 2) msgCombat += "une fois "; - else msgCombat += (utilisations - 1) + " fois "; - } - msgCombat += options.limiteParCombatRessource + " durant ce combat."; - if (explications) { - stateCOF.afterDisplay = stateCOF.afterDisplay || []; - stateCOF.afterDisplay.push({ - msg: msgCombat, - destinataire: personnage - }); - } else sendPerso(personnage, msgCombat, true); - } - } else { - error("Impossible de savoir à qui appliquer la limite par combat", options); - return true; - } - } - if (options.limiteParTour) { - if (personnage) { - if (!stateCOF.combat) { - sendPerso(personnage, "ne peut pas faire cette action en dehors des combats", options.secret); - return true; - } - if (options.limiteParTourRessource) - ressource = "limiteParTour_" + options.limiteParTourRessource; - else - ressource = "limiteParTour_" + defResource; - utilisations = attributeAsInt(personnage, ressource, options.limiteParTour); - if (utilisations === 0) { - let msgToSend = "ne peut plus faire cette action pour ce tour"; - sendPerso(personnage, msgToSend, options.secret); - return true; - } - setTokenAttr(personnage, ressource, utilisations - 1, evt); - if (options.limiteParTourRessource) { - let msgCombat = nomPerso(personnage) + " "; - if (utilisations < 2) msgCombat += "ne pourra plus utiliser "; - else { - msgCombat += "pourra encore utiliser "; - if (utilisations == 2) msgCombat += "une fois "; - else msgCombat += (utilisations - 1) + " fois "; - } - msgCombat += options.limiteParTourRessource + " durant ce tour."; - if (explications) { - stateCOF.afterDisplay = stateCOF.afterDisplay || []; - stateCOF.afterDisplay.push({ - msg: msgCombat, - destinataire: personnage - }); - } else sendPerso(personnage, msgCombat, options.secret); - } - } else { - error("Impossible de savoir à qui appliquer la limite par tour", options); + error("Impossible de savoir qui doit d\xE9penser de la mana", options); return true; } } + depMana = testLimitePar(personnage, 'Jour', options, depMana, defResource, msg, evt, explications); + if (!depMana) return true; + depMana = testLimitePar(personnage, 'Combat', options, depMana, defResource, msg, evt, explications); + if (!depMana) return true; + if (!depMana) return true; + depMana = testLimitePar(personnage, 'Tour', options, depMana, defResource, msg, evt, explications); + if (!depMana) return true; if (options.tempsRecharge) { if (personnage) { if (attributeAsBool(personnage, options.tempsRecharge.effet)) { @@ -13468,7 +13545,7 @@ var COFantasy = COFantasy || function() { setAttrDuree(personnage, options.tempsRecharge.effet, options.tempsRecharge.duree, evt); } } else { - error("Impossible de savoir à qui s'applique le temps de recharge", options); + error("Impossible de savoir \xE0 qui s'applique le temps de recharge", options); return true; } } @@ -13482,7 +13559,7 @@ var COFantasy = COFantasy || function() { } setTokenAttr(personnage, 'dose_' + options.dose, doses - 1, evt); } else { - error("Impossible de savoir qui doit dépenser la dose", options); + error("Impossible de savoir qui doit d\xE9penser la dose", options); return true; } } @@ -13496,7 +13573,7 @@ var COFantasy = COFantasy || function() { } setTokenAttr(personnage, nomAttr, currentAttr + 1, evt); } else { - error("Impossible de savoir à qui appliquer la limitation", options); + error("Impossible de savoir \xE0 qui appliquer la limitation", options); return true; } } @@ -13526,11 +13603,11 @@ var COFantasy = COFantasy || function() { if (personnage) { let test = testLimiteUtilisationsCapa(personnage, pred, 'tour', "ne peut plus utiliser " + pred + " ce tour", - "Action impossible, pas de prédicat " + pred); + "Action impossible, pas de pr\xE9dicat " + pred); if (test === undefined) return true; utiliseCapacite(personnage, test, evt); } else { - error("Impossible de savoir à qui appliquer la limitation du prédicat " + pred, options); + error("Impossible de savoir \xE0 qui appliquer la limitation du pr\xE9dicat " + pred, options); return true; } } @@ -13540,8 +13617,8 @@ var COFantasy = COFantasy || function() { //asynchrone //callback(resultat, crit, roll1, roll2): - // resultat peut être 0, 1 ou 2 : 0 = match null, 1 le perso 1 gagne, 2 le perso 2 gagne. - // crit peut être 1 si un des deux perso a fait une réussite critique et pas l'autre, -1 si un des personnage a fait un échec critique et pas l'autre, et 0 sinon + // resultat peut \xEAtre 0, 1 ou 2 : 0 = match null, 1 le perso 1 gagne, 2 le perso 2 gagne. + // crit peut \xEAtre 1 si un des deux perso a fait une r\xE9ussite critique et pas l'autre, -1 si un des personnage a fait un \xE9chec critique et pas l'autre, et 0 sinon function testOppose(rollId, perso1, carac1, options1, perso2, carac2, options2, explications, evt, callback) { if (carac2 === undefined) carac2 = carac1; let nom1 = nomPerso(perso1); @@ -13581,9 +13658,9 @@ var COFantasy = COFantasy || function() { let texte1 = "Jet " + deCarac(carac1) + " de " + nom1 + " : " + rt1.texte; if (reussite == 2) { if ((carac1 == 'FOR' || carac1 == 'DEX' || carac1 == 'CON') && - attributeAsBool(perso1, 'runeForgesort_énergie') && - attributeAsInt(perso1, 'limiteParCombat_runeForgesort_énergie', 1) > 0) { - texte1 += "
    " + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + rollId + "_roll1", "Rune d'énergie"); + attributeAsBool(perso1, 'runeForgesort_\xE9nergie') && + attributeAsInt(perso1, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0) { + texte1 += "
    " + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + rollId + "_roll1", "Rune d'\xE9nergie"); } if (!rt1.echecCritique && !rt2.critique) { let pcPerso1 = pointsDeChance(perso1); @@ -13613,9 +13690,9 @@ var COFantasy = COFantasy || function() { let texte2 = "Jet " + deCarac(carac2) + " de " + nom2 + " : " + rt2.texte; if (reussite == 1) { if ((carac2 == 'FOR' || carac2 == 'DEX' || carac2 == 'CON') && - attributeAsBool(perso2, 'runeForgesort_énergie') && - attributeAsInt(perso2, 'limiteParCombat_runeForgesort_énergie', 1) > 0) { - texte2 += "
    " + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + rollId + "_roll2", "Rune d'énergie"); + attributeAsBool(perso2, 'runeForgesort_\xE9nergie') && + attributeAsInt(perso2, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0) { + texte2 += "
    " + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + rollId + "_roll2", "Rune d'\xE9nergie"); } if (!rt2.echecCritique && !rt1.critique) { let pcPerso2 = pointsDeChance(perso2); @@ -13643,16 +13720,15 @@ var COFantasy = COFantasy || function() { explications.push(m); }); callback(reussite, crit, rt1.roll, rt2.roll); - }); //Fin du jet du deuxième perso + }); //Fin du jet du deuxi\xE8me perso }); //Fin du jet du premier perso } function bonusPlusViteQueSonOmbre(perso, arme) { let p = predicateAsBool(perso, 'plusViteQueSonOmbre'); if (!p) return 0; - // L'arme doit être chargée - if (arme.charge && attributeAsInt(perso, 'charge_' + arme.label, 0) === 0) - return 0; + // L'arme doit \xEAtre charg\xE9e + if (armeDechargee(perso, arme)) return 0; if (p === true) { if (arme.poudre) return 10; return 0; @@ -13669,7 +13745,7 @@ var COFantasy = COFantasy || function() { return 0; } - // prend en compte l'unité de mesure utilisée sur la page + // prend en compte l'unit\xE9 de mesure utilis\xE9e sur la page function ajouteUneLumiere(perso, nomLumiere, radius, dimRadius, evt) { radius = scaleDistance(perso, radius); if (dimRadius !== '') dimRadius = scaleDistance(perso, dimRadius); @@ -13680,7 +13756,7 @@ var COFantasy = COFantasy || function() { let brightLight = radius; if (udl) { if (isNaN(brightLight) || brightLight < 0) { - error("Lumière avec un rayon négatif", radius); + error("Lumi\xE8re avec un rayon n\xE9gatif", radius); return; } } @@ -13688,7 +13764,7 @@ var COFantasy = COFantasy || function() { if (ct.get('bar1_link') === '') attrName += "_" + ct.get('name'); if (ct.get('bar1_max')) { let lumiereSurPerso; - //Cas particulier où le personnage est un vrai personnage qui ne fait pas de lumière + //Cas particulier o\xF9 le personnage est un vrai personnage qui ne fait pas de lumi\xE8re if (!udl && !ct.get('light_radius')) { lumiereSurPerso = true; setToken(ct, 'light_radius', radius, evt); @@ -13733,7 +13809,7 @@ var COFantasy = COFantasy || function() { name: nomLumiere, }); if (tokLumiere === undefined) { - error("Problème lors de la création du token de lumière", perso); + error("Probl\xE8me lors de la cr\xE9ation du token de lumi\xE8re", perso); return; } evt.tokens = [tokLumiere]; @@ -13755,7 +13831,7 @@ var COFantasy = COFantasy || function() { setToken(tokLumiere, 'light_dimradius', dimRadius, evt); setToken(tokLumiere, 'light_otherplayers', true, evt); } - if (ct.get('bar1_max')) { //Lumière liée à un token + if (ct.get('bar1_max')) { //Lumi\xE8re li\xE9e \xE0 un token let attr = createObj('attribute', { characterid: perso.charId, name: attrName, @@ -13765,14 +13841,14 @@ var COFantasy = COFantasy || function() { evt.attributes = [{ attribute: attr, }]; - } else { //cible temporaire, à effacer + } else { //cible temporaire, \xE0 effacer ct.remove(); } } - //renvoie le nom de l'arme si l'arme est déjà tenue en main + //renvoie le nom de l'arme si l'arme est d\xE9j\xE0 tenue en main // options.seulementDroite permet de ne rengainer que l'arme droite - // options.deuxMains permet de prendre une arme à 2 mains + // options.deuxMains permet de prendre une arme \xE0 2 mains function degainerArme(perso, labelArme, evt, options) { let pageId = perso.pageId; if (pageId === undefined) { @@ -13790,11 +13866,11 @@ var COFantasy = COFantasy || function() { nouvelleArme = getWeaponStats(perso, labelArme); if (nouvelleArme && nouvelleArme.armeGauche) options.gauche = true; let nouvelleArmeGauche; - let labelArmeGauche; //définie seulement si on dégaine l'arme gauche - // et toujours différent de labelArme + let labelArmeGauche; //d\xE9finie seulement si on d\xE9gaine l'arme gauche + // et toujours diff\xE9rent de labelArme if (options.armeGaucheLabel) { if (options.armeGaucheLabel == labelArme) { - sendPerso("ne peut dégainer la même arme dans les deux mains"); + sendPerso("ne peut d\xE9gainer la m\xEAme arme dans les deux mains"); return; } if (options.gauche) { @@ -13804,7 +13880,7 @@ var COFantasy = COFantasy || function() { options.gauche = false; //vrai seulement si on ne sort que l'arme gauche nouvelleArme = getWeaponStats(perso, options.armeGaucheLabel); if (nouvelleArme && nouvelleArme.armeGauche) { - sendPerso("ne peut dégainer 2 armes gauches à la fois"); + sendPerso("ne peut d\xE9gainer 2 armes gauches \xE0 la fois"); return; } } else { @@ -13836,7 +13912,7 @@ var COFantasy = COFantasy || function() { if (labelArmeActuelleGauche == labelArme) rienAFaire = true; else { changementDePrise = true; - message += "prend son arme à deux mains"; + message += "prend son arme \xE0 deux mains"; attrArmeActuelle.set('max', labelArme); } } @@ -13846,24 +13922,24 @@ var COFantasy = COFantasy || function() { if (labelArmeActuelle == labelArme) { if (labelArmeActuelleGauche == labelArme) { changementDePrise = true; - message += "prend son arme à une main"; + message += "prend son arme \xE0 une main"; if (!labelArmeGauche) { attrArmeActuelle.set('max', ''); } } else { - if (labelArmeGauche) //on dégaine 2 armes + if (labelArmeGauche) //on d\xE9gaine 2 armes rienAFaire = labelArmeActuelleGauche == labelArmeGauche; else rienAFaire = true; } } } if (rienAFaire) { - //Pas besoin de dégainer. + //Pas besoin de d\xE9gainer. if (options.weaponStats) return options.weaponStats.name; if (nouvelleArme) return nouvelleArme.name; return; } - //On dégaine une nouvelle arme, il faut rengainer l'ancienne + //On d\xE9gaine une nouvelle arme, il faut rengainer l'ancienne if (labelArmeActuelle) { //dans ce cas, pas options.gauche ancienneArme = getWeaponStats(perso, labelArmeActuelle); if (ancienneArme === undefined) { @@ -13911,8 +13987,8 @@ var COFantasy = COFantasy || function() { } } else attrArmeActuelle = undefined; const estMook = perso.token && perso.token.get('bar1_link') === ''; - //Puis on dégaine - //mais on vérifie que l'arme existe, sinon c'est juste un ordre de rengainer + //Puis on d\xE9gaine + //mais on v\xE9rifie que l'arme existe, sinon c'est juste un ordre de rengainer if (nouvelleArme === undefined) { if (attrArmeActuelle) { if (options.seulementDroite && labelArmeActuelleGauche) { @@ -13931,7 +14007,7 @@ var COFantasy = COFantasy || function() { } if (nouvelleArmeGauche) { if (ficheAttributeAsInt(perso, 'defbouclieron', 0)) { - sendPerso(perso, "enlève son bouclier", options.secret); + sendPerso(perso, "enl\xE8ve son bouclier", options.secret); setFicheAttr(perso, 'defbouclieron', 0, evt, { default: 0 }); @@ -13939,7 +14015,7 @@ var COFantasy = COFantasy || function() { } if (nouvelleArme.deuxMains || options.deuxMains) { if (ficheAttributeAsInt(perso, 'defbouclieron', 0)) { - sendPerso(perso, "enlève son bouclier", options.secret); + sendPerso(perso, "enl\xE8ve son bouclier", options.secret); setFicheAttr(perso, 'defbouclieron', 0, evt, { default: 0 }); @@ -13991,17 +14067,17 @@ var COFantasy = COFantasy || function() { } if (options.messages) { if (changementDePrise) { - if (nouvelleArmeGauche) message += ", et dégaine " + nouvelleArmeGauche.name; + if (nouvelleArmeGauche) message += ", et d\xE9gaine " + nouvelleArmeGauche.name; } else { - message += "dégaine " + nouvelleArme.name; + message += "d\xE9gaine " + nouvelleArme.name; if (nouvelleArmeGauche) message += " et " + nouvelleArmeGauche.name; } options.messages.push(message); } else { if (changementDePrise) { - if (nouvelleArmeGauche) message += ", et dégaine " + nouvelleArmeGauche.name; + if (nouvelleArmeGauche) message += ", et d\xE9gaine " + nouvelleArmeGauche.name; } else { - message = "dégaine " + nouvelleArme.name; + message = "d\xE9gaine " + nouvelleArme.name; if (nouvelleArmeGauche) message += " et " + nouvelleArmeGauche.name; } sendPerso(perso, message, options.secret); @@ -14047,7 +14123,7 @@ var COFantasy = COFantasy || function() { }); return !regenPossible; } - //On enlève les doublons de cibles qui partagent leurs PVs; + //On enl\xE8ve les doublons de cibles qui partagent leurs PVs; function enleveDoublonsPartagePV(cibles) { let ciblesAvecPVsPartages = new Set(); //va aussi peupler le champ name des cibles @@ -14066,9 +14142,9 @@ var COFantasy = COFantasy || function() { ciblesAvecPVsPartages.add(cp); }); } else if (persoEstPNJ(target)) { - //cible la moins prioritaire, on l'enlève si on trouve un autre représentant + //cible la moins prioritaire, on l'enl\xE8ve si on trouve un autre repr\xE9sentant let representantPresent = cibles.find(function(target2, index2) { - if (index2 <= index) return false; //déjà traité + if (index2 <= index) return false; //d\xE9j\xE0 trait\xE9 if (target2.name === undefined) { let target2Char = getObj('character', target2.charId); if (target2Char === undefined) return false; @@ -14083,7 +14159,7 @@ var COFantasy = COFantasy || function() { //N'a pas de familier mais n'est pas un PNJ //On cherche si il existe un autre perso plus prioritaire. let representantFamilier = cibles.find(function(target2, index2) { - if (index2 < index) return false; //déjà traité + if (index2 < index) return false; //d\xE9j\xE0 trait\xE9 if (target2.name === undefined) { let target2Char = getObj('character', target2.charId); if (target2Char === undefined) return false; @@ -14107,6 +14183,58 @@ var COFantasy = COFantasy || function() { return cibles; } + function tokensSurTrajet(token, ptCible, rayonToken, allToks, murs, saut) { + let pt = pointOfToken(token); + if (murs) { + if (obstaclePresent(pt.x, pt.y, ptCible, murs)) return ["mur"]; + } + let dp = distancePoints(pt, ptCible); + let liste_obstacles = []; + allToks.forEach(function(obj) { + if (obj.id == token.id) return; + let objCharId = obj.get('represents'); + let perso = { + token: obj, + charId: objCharId + }; + if (objCharId !== '' && + (getState(perso, 'mort') || + getState(perso, 'assomme') || getState(perso, 'endormi') || + (attributeAsBool(perso, 'intangible') && attributeAsInt(perso, 'intangibleValeur', 1)) || + (attributeAsBool(perso, 'intangibleInvisible') && attributeAsInt(perso, 'intangibleInvisibleValeur', 1)) + ) + ) + return; + //On regarde si le token est une monture de token + let attrMonte = tokenAttribute(perso, 'estMontePar'); + let estMonture = attrMonte.find(function(a) { + let sp = splitIdName(a.get('current')); + if (sp === undefined) return false; + return sp.id == token.id; + }); + if (estMonture) return; + let ptObj = pointOfToken(obj); + let obj_dist = distancePoints(ptCible, ptObj); + if (obj_dist > dp) return; + //Pour le point d'arriv\xE9e, il faut vraiment que ce soit libre + let rayonObjet = tokenSizeAsCircle(obj) / 2; + if (obj_dist < (rayonObjet + rayonToken) * 0.9) { + liste_obstacles.push(obj.get('name')); + return; + } + //On ignore les autres obstacles si on saute + if (saut) return; + obj_dist = distancePixToken(token, obj); + if (obj_dist > dp) return; + let distToTrajectory = distancePixTokenSegment(obj, pt, ptCible); + // On mod\xE9lise le token comme un disque + let rayonObj = tokenSizeAsCircle(obj) / 2; + if (distToTrajectory > rayonObj) return; + liste_obstacles.push(obj.get('name')); + }); + return liste_obstacles; + } + //targetToken est soit un token, soit une structure avec un champs cibles qui contient toutes les cibles function attack(playerName, playerId, attaquant, targetToken, weaponStats, options) { // Attacker and target infos @@ -14122,15 +14250,16 @@ var COFantasy = COFantasy || function() { } attaquant.name = attaquant.name || attacker.get("name"); let pageId = attackingToken.get('pageid'); + options.pageId = pageId; let weaponName = options.nom || weaponStats.name; //Options automatically set by some attributes if (attributeAsBool(attaquant, 'paralysieRoublard')) { if (attributeAsBool(attaquant, 'enrage')) { - sendPerso(attaquant, "est trop enragé pour sentir la douleur"); + sendPerso(attaquant, "est trop enrag\xE9 pour sentir la douleur"); } else if (predicateAsBool(attaquant, 'proprioception')) { - sendPerso(attaquant, "est immunisé à la douleur"); + sendPerso(attaquant, "est immunis\xE9 \xE0 la douleur"); } else { - sendPerso(attaquant, "ne peut pas attaquer car il est paralysé de douleur"); + sendPerso(attaquant, "ne peut pas attaquer car il est paralys\xE9 de douleur"); attackCallback(options); return; } @@ -14177,7 +14306,7 @@ var COFantasy = COFantasy || function() { weaponStats.attDice = options.dm.dice; weaponStats.attDMBonusCommun = options.dm.bonus; } else if (weaponStats.batarde && weaponStats.deuxMains) { - let dm = parseDice(weaponStats.batarde, 'dégâts'); + let dm = parseDice(weaponStats.batarde, 'd\xE9g\xE2ts'); if (dm) { weaponStats.attNbDices = dm.nbDe; weaponStats.attDice = dm.dice; @@ -14224,15 +14353,19 @@ var COFantasy = COFantasy || function() { if (stats2.divers && stats2.divers.includes('d3')) stats2.attDice = 3; options.tirDouble.stats = stats2; } - //Pour les explosions, la portée est 0 mais avec un disque + //Pour les explosions, la port\xE9e est 0 mais avec un disque if (options.explosion) { if (options.aoe === undefined) { options.aoe = { type: 'disque', - rayon: portee + rayon: portee, + centre: { + left: attackingToken.get('left'), + top: attackingToken.get('top') + }, }; } else if (options.aoe.type != 'disque') { - error("Option explosion ignorée, car l'attaque est une aoe qui n'est pas un disque", options); + error("Option explosion ignor\xE9e, car l'attaque est une aoe qui n'est pas un disque", options); } } if (portee > 0) { @@ -14259,9 +14392,9 @@ var COFantasy = COFantasy || function() { } options.contact = true; } - //Ce qui peut empêcher l'attaque quelles que soient les cibles + //Ce qui peut emp\xEAcher l'attaque quelles que soient les cibles if (options.avecd12 && ((estAffaibli(attaquant) && !predicateAsBool(attaquant, 'insensibleAffaibli')) || getState(attaquant, 'immobilise'))) { - sendPerso(attaquant, "ne peut pas utiliser cette capacité quand il est affaibli."); + sendPerso(attaquant, "ne peut pas utiliser cette capacit\xE9 quand il est affaibli."); attackCallback(options); return; } @@ -14276,30 +14409,12 @@ var COFantasy = COFantasy || function() { attackCallback(options); return; } - //Pour l'option grenaille implicite, il faut vérifier que toutes les charge de l'arme sont des charges de grenaille - let chargesArme = []; + //Pour l'option grenaille implicite, il faut v\xE9rifier que toutes les charges de l'arme sont des charges de grenaille let attackLabel = weaponStats.label; - if (attackLabel) { - chargesArme = findObjs({ - _type: 'attribute', - _characterid: attackingCharId, - name: 'charge_' + attackLabel - }); - if (!options.grenaille && chargesArme.length > 0) { - let chargesGrenaille = findObjs({ - _type: 'attribute', - _characterid: attackingCharId, - name: 'chargeGrenaille_' + attackLabel - }); - if (chargesGrenaille.length > 0) { - let chargesTotales = parseInt(chargesArme[0].get('current')); - if (!isNaN(chargesTotales)) { - let grenailles = parseInt(chargesGrenaille[0].get('current')); - if (!isNaN(grenailles) && grenailles >= chargesTotales) - options.grenaille = true; - } - } - } + if (attackLabel && weaponStats.charge && !options.grenaille) { + let currentCharges = attributeAsInt(attaquant, 'charge_' + attackLabel, weaponStats.charge); + if (currentCharges > 0) + options.grenaille = attributeAsInt(attaquant, 'chargeGrenaille_' + attackLabel, 0) >= currentCharges; } if (options.grenaille) { portee = portee / 10; @@ -14344,18 +14459,20 @@ var COFantasy = COFantasy || function() { options.fx = options.fx || effet.id; } if (options.eclairDEnergie && !options.redo) { - //On augmente le nombre de dés de 1 et on utilise l'attaque magique + //On augmente le nombre de d\xE9s de 1 et on utilise l'attaque magique weaponStats.attNbDices++; weaponStats.attSkill = '@{ATKMAG}'; options.contondant = undefined; options.type = 'energie'; options.messages = options.messages || []; - options.messages.push("Éclair d'énergie !"); + options.messages.push("\xC9clair d'\xE9nergie !"); } - //Détermination de la (ou des) cible(s) + //D\xE9termination de la (ou des) cible(s) let nomCiblePrincipale; //Utilise pour le cas mono-cible let cibles = []; - if (options.redo) { //Dans ce cas les cibles sont précisées dans targetToken + let murs; + let page; + if (options.redo) { //Dans ce cas les cibles sont pr\xE9cis\xE9es dans targetToken cibles = targetToken; if (cibles.length === 0) { error("Attaque sans cible", targetToken); @@ -14364,12 +14481,10 @@ var COFantasy = COFantasy || function() { } else if (cibles.length == 1) targetToken = cibles[0].token; nomCiblePrincipale = nomPerso(cibles[0]); } else { - let murs; let pc; - let page; nomCiblePrincipale = targetToken.get('name'); if (options.aoe) { - //cas de la boule de feu qui fait un échec critique : on déplace la cible si elle est artificielle + //cas de la boule de feu qui fait un \xE9chec critique : on d\xE9place la cible si elle est artificielle if (!options.redo && (options.demiAuto || options.toucheDoubleDmg) && (!options.triche || options.triche == 'echecCritique') && targetToken.get('bar1_max') == 0) { // jshint ignore:line @@ -14449,12 +14564,12 @@ var COFantasy = COFantasy || function() { }; } if (targetToken.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir la ligne + //C'est juste un token utilis\xE9 pour d\xE9finir la ligne if (options.fx) { spawnFxBetweenPoints(pta, ptt, options.fx, pageId); } cibles = []; - targetToken.remove(); //On l'enlève, normalement plus besoin + targetToken.remove(); //On l'enl\xE8ve, normalement plus besoin } let allToks = findObjs({ @@ -14471,7 +14586,7 @@ var COFantasy = COFantasy || function() { token: obj, charId: objCharId }; - if (nePeutPlusPrendreDM(cible, options)) return; //pas de dégâts aux morts + if (nePeutPlusPrendreDM(cible, options)) return; //pas de d\xE9g\xE2ts aux morts let distToTrajectory = distancePixTokenSegment(obj, pta, ptt); if (distToTrajectory > (obj.get('width') + obj.get('height')) / 4 + PIX_PER_UNIT / 4) return; @@ -14487,8 +14602,8 @@ var COFantasy = COFantasy || function() { { if (distanceTarget > portee) { sendPlayer(playerName, - "Le centre du disque visé est trop loin pour " + weaponName + - " (distance " + distanceTarget + ", portée " + portee + ")", + "Le centre du disque vis\xE9 est trop loin pour " + weaponName + + " (distance " + distanceTarget + ", port\xE9e " + portee + ")", playerId); attackCallback(options); return; @@ -14516,7 +14631,7 @@ var COFantasy = COFantasy || function() { } let t = attributeAsInt(cadavre, 'a0PVDepuis', 0); if (t < combat.tour - 1) { - sendPlayer(playerName, "La mort de " + nomPerso(cadavre) + " n'est pas assez récente", playerId); + sendPlayer(playerName, "La mort de " + nomPerso(cadavre) + " n'est pas assez r\xE9cente", playerId); attackCallback(options); return; } @@ -14525,18 +14640,22 @@ var COFantasy = COFantasy || function() { options.aoe.souffleDeMort.niveau = ficheAttributeAsInt(cadavre, 'niveau', 0); } - page = page || getObj("page", pageId); + options.aoe.centre = options.aoe.centre || { + left: targetToken.get('left'), + top: targetToken.get('top') + }; + page = page || getObj('page', pageId); murs = getWalls(page, pageId, murs); let allToksDisque = findObjs({ - _type: "graphic", + _type: 'graphic', _pageid: pageId, - _subtype: "token", - layer: "objects" + _subtype: 'token', + layer: 'objects' }); allToksDisque.forEach(function(obj) { if ((options.explosion || portee === 0) && - obj.id == tokenOrigine.id) return; //on ne se cible pas si le centre de l'aoe est soi-même + obj.id == tokenOrigine.id) return; //on ne se cible pas si le centre de l'aoe est soi-m\xEAme if (obj.get('bar1_max') == 0) return; // jshint ignore:line let objCharId = obj.get('represents'); if (objCharId === '') return; @@ -14544,7 +14663,7 @@ var COFantasy = COFantasy || function() { token: obj, charId: objCharId }; - if (nePeutPlusPrendreDM(cible, options)) return; //pas de dégâts aux morts + if (nePeutPlusPrendreDM(cible, options)) return; //pas de d\xE9g\xE2ts aux morts let distanceCentre = distanceCombat(targetToken, obj, pageId, { strict1: true @@ -14565,10 +14684,10 @@ var COFantasy = COFantasy || function() { cibles.push(cible); }); if (targetToken.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir le disque - targetToken.remove(); //On l'enlève, normalement plus besoin + //C'est juste un token utilis\xE9 pour d\xE9finir le disque + targetToken.remove(); //On l'enl\xE8ve, normalement plus besoin } - // La nouvelle portée (pour ne rien éliminer à l'étape suivante + // La nouvelle port\xE9e (pour ne rien \xE9liminer \xE0 l'\xE9tape suivante portee += options.aoe.rayon; break; } @@ -14579,12 +14698,12 @@ var COFantasy = COFantasy || function() { } let vecCentre = vecteurUnitaire(pta, ptt); let cosAngle = Math.cos(options.aoe.angle * Math.PI / 360.0); - //Pour éviter des artfacts d'arrondi: + //Pour \xE9viter des artfacts d'arrondi: cosAngle = (Math.floor(cosAngle * 1000000)) / 1000000; if (targetToken.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir le cone + //C'est juste un token utilis\xE9 pour d\xE9finir le cone cibles = []; - targetToken.remove(); //On l'enlève, normalement plus besoin + targetToken.remove(); //On l'enl\xE8ve, normalement plus besoin } page = page || getObj("page", pageId); murs = getWalls(page, pageId, murs); @@ -14603,12 +14722,12 @@ var COFantasy = COFantasy || function() { token: obj, charId: objCharId }; - if (nePeutPlusPrendreDM(cible, options)) return; //pas de dégâts aux morts + if (nePeutPlusPrendreDM(cible, options)) return; //pas de d\xE9g\xE2ts aux morts let pt = pointOfToken(obj); let vecObj = vecteurUnitaire(pta, pt); if (vecCentre.x * vecObj.x + vecCentre.y * vecObj.y < cosAngle) return; - // La distance sera comparée à la portée plus loin + // La distance sera compar\xE9e \xE0 la port\xE9e plus loin let objChar = getObj('character', objCharId); if (objChar === undefined) return; if (murs) { @@ -14626,16 +14745,16 @@ var COFantasy = COFantasy || function() { return; } } else { - if (tokenOrigine.id == targetToken.id && !options.echecTotal) { //même token pour attaquant et cible + if (tokenOrigine.id == targetToken.id && !options.echecTotal) { //m\xEAme token pour attaquant et cible sendPerso(attaquant, "s'attaque " + onGenre(attaquant, "lui", "elle") + - "-même ? Probablement une erreur à la sélection de la cible. On annule"); + "-m\xEAme ? Probablement une erreur \xE0 la s\xE9lection de la cible. On annule"); attackCallback(options); return; } let targetCharId = targetToken.get("represents"); if (targetCharId === "") { - error("Le token ciblé (" + nomCiblePrincipale + ") doit représenter un personnage ", targetToken); + error("Le token cibl\xE9 (" + nomCiblePrincipale + ") doit repr\xE9senter un personnage ", targetToken); attackCallback(options); return; } @@ -14661,7 +14780,7 @@ var COFantasy = COFantasy || function() { }); } } - //Les conditions qui peuvent empêcher l'attaque + //Les conditions qui peuvent emp\xEAcher l'attaque if (options.conditionAttaquant !== undefined) { if (!testCondition(options.conditionAttaquant, attaquant, cibles)) { sendPerso(attaquant, "ne peut pas utiliser " + weaponName); @@ -14669,7 +14788,7 @@ var COFantasy = COFantasy || function() { return; } } - //dernieresCiblesAttaquees contient en current les cibles attaquées, et en max les cibles sur lesquelles on a fait des ripostes + //dernieresCiblesAttaquees contient en current les cibles attaqu\xE9es, et en max les cibles sur lesquelles on a fait des ripostes let attrCiblesAttaquees = tokenAttribute(attaquant, 'dernieresCiblesAttaquees'); let ripostesDuTour = new Set(); if (attrCiblesAttaquees.length > 0) { @@ -14690,16 +14809,16 @@ var COFantasy = COFantasy || function() { return false; } if (options.seulementVivant && estNonVivant(target)) { - sendPlayer(playerName, "cette attaque n'affecte que les créatures vivantes", playerId); + sendPlayer(playerName, "cette attaque n'affecte que les cr\xE9atures vivantes", playerId); return false; } if (options.attaqueMentale) { if (predicateAsBool(target, 'sansEsprit')) { - sendPlayer(playerName, "cette attaque n'affecte que les créatures pensantes", playerId); + sendPlayer(playerName, "cette attaque n'affecte que les cr\xE9atures pensantes", playerId); return false; } if (predicateAsBool(target, 'vegetatif')) { - sendPlayer(playerName, "cette attaque n'affecte pas les créatures vég etatives", playerId); + sendPlayer(playerName, "cette attaque n'affecte pas les cr\xE9atures v\xE9g etatives", playerId); return false; } } @@ -14708,14 +14827,14 @@ var COFantasy = COFantasy || function() { return false; } if (attributeAsBool(attaquant, 'tenuADistanceManoeuvre(' + target.token.id + ')')) { - sendPerso(attaquant, "est tenu à distance de " + nomPerso(target) + ", " + onGenre(attaquant, "il", "elle") + " ne peut pas l'attaquer ce tour."); + sendPerso(attaquant, "est tenu \xE0 distance de " + nomPerso(target) + ", " + onGenre(attaquant, "il", "elle") + " ne peut pas l'attaquer ce tour."); return false; } if (charAttributeAsBool(target, 'armeeConjuree')) { return options.attaqueArmeeConjuree; } if (ripostesDuTour.has(target.token.id)) { - sendPerso(attaquant, "a déjà fait une riposte contre " + nomPerso(target)); + sendPerso(attaquant, "a d\xE9j\xE0 fait une riposte contre " + nomPerso(target)); return false; } if (options.ricochets) { @@ -14723,7 +14842,7 @@ var COFantasy = COFantasy || function() { return c.token.id == target.token.id; }); if (dejaTouche) { - sendPerso(attaquant, nomPerso(target) + " a déjà été touché par un précédent ricochet de cette attaque"); + sendPerso(attaquant, nomPerso(target) + " a d\xE9j\xE0 \xE9t\xE9 touch\xE9 par un pr\xE9c\xE9dent ricochet de cette attaque"); return false; } } @@ -14731,7 +14850,7 @@ var COFantasy = COFantasy || function() { }); if (cibles.length === 0) { if (options.aoe) { - sendPlayer(playerName, "aucune cible dans l'aire d'effet de " + weaponName + ", action annulée", + sendPlayer(playerName, "aucune cible dans l'aire d'effet de " + weaponName + ", action annul\xE9e", playerId); } attackCallback(options); @@ -14742,7 +14861,7 @@ var COFantasy = COFantasy || function() { let optDistance = {}; options.portee = portee; if (options.contact) optDistance.allonge = options.allonge; - // Si l'attaquant est monté, distance mesurée à partir de sa monture + // Si l'attaquant est mont\xE9, distance mesur\xE9e \xE0 partir de sa monture if (tokenOrigine.id == attackingToken.id) { let attrMonture = tokenAttribute(attaquant, 'monteSur'); if (attrMonture.length > 0) { @@ -14752,7 +14871,7 @@ var COFantasy = COFantasy || function() { } } cibles = cibles.filter(function(target) { - // Si la cible est montée, distance mesurée vers sa monture + // Si la cible est mont\xE9e, distance mesur\xE9e vers sa monture let pseudoTargetToken = target.token; let attrMonture = tokenAttribute(target, 'monteSur'); if (attrMonture.length > 0) { @@ -14763,11 +14882,17 @@ var COFantasy = COFantasy || function() { target.distance = distanceCombat(tokenOrigine, pseudoTargetToken, pageId, optDistance); if (options.intercepter || options.interposer) return true; - if (target.distance > portee && target.msgEsquiveFatale === undefined && !(target.chairACanon || target.intercepter)) { - if (options.aoe || options.auto) return false; //distance stricte - if (target.distance > (predicateAsBool(attaquant, 'tirParabolique') ? 3 : 2) * portee) return false; - // On peut aller jusqu'à 2x portee si unique cible et jet d'attaque, 3x si le personnage a Tir Parabolique - return true; + let porteeMax = portee; + if (!options.aoe) { + if (!options.auto) { + // On peut aller jusqu'\xE0 2x portee si unique cible et jet d'attaque, 3x si le personnage a Tir Parabolique + if (predicateAsBool(attaquant, 'tirParabolique')) porteeMax = 3 * portee; + else porteeMax = 2 * portee; + } + if (options.deplaceDe) porteeMax += options.deplaceDe.max; + } + if (target.distance > porteeMax && target.msgEsquiveFatale === undefined && !(target.chairACanon || target.intercepter)) { + return false; } if (target.distance === 0 && options.seulementDistance) { sendPerso(attaquant, "est trop proche de " + nomPerso(target) + " pour cette attaque"); @@ -14776,7 +14901,7 @@ var COFantasy = COFantasy || function() { return true; }); } - //On enlève les alliés si l'option saufAllies est active + //On enl\xE8ve les alli\xE9s si l'option saufAllies est active if (options.saufAllies) { let allies = new Set(); allies = alliesParPerso[attaquant.charId] || allies; @@ -14785,7 +14910,7 @@ var COFantasy = COFantasy || function() { return !(allies.has(target.charId)); }); } - //On vérifie que les cibles sont assez proches les unes des autres + //On v\xE9rifie que les cibles sont assez proches les unes des autres if (options.ciblesDansDisque && cibles.length > 1) { let l1, l2, t1, t2; cibles.forEach(function(target) { @@ -14798,7 +14923,7 @@ var COFantasy = COFantasy || function() { }); let maxpix = options.ciblesDansDisque * PIX_PER_UNIT / computeScale(pageId); if ((l2 - l1) > 2 * maxpix || (t2 - t1) > 2 * maxpix) { - sendPlayer(playerName, "Cibles trop éloignées les unes des autres"); + sendPlayer(playerName, "Cibles trop \xE9loign\xE9es les unes des autres"); attackCallback(options); return; } @@ -14809,14 +14934,14 @@ var COFantasy = COFantasy || function() { x: (l1 + l2) / 2, y: (t1 + t2) / 2 }; - //C'est approché, mais sûrement assez bon pour ce qui nous occupe + //C'est approch\xE9, mais s\xFBrement assez bon pour ce qui nous occupe let tropLoin = cibles.some(function(target) { let pt = pointOfToken(target.token); attackCallback(options); return (distancePoints(centre, pt) > maxpix + 1); }); if (tropLoin) { - sendPlayer(playerName, "Cibles trop éloignées les unes des autres"); + sendPlayer(playerName, "Cibles trop \xE9loign\xE9es les unes des autres"); attackCallback(options); return; } @@ -14824,17 +14949,112 @@ var COFantasy = COFantasy || function() { } if (cibles.length === 0) { if (options.aoe) { - sendPlayer(playerName, "aucune cible dans l'aire d'effet de " + weaponName + ", action annulée", + sendPlayer(playerName, "aucune cible dans l'aire d'effet de " + weaponName + ", action annul\xE9e", playerId); return; } if (!options.seulementDistance) { - sendPerso(attaquant, "est hors de portée de " + nomCiblePrincipale + " pour une attaque utilisant " + weaponName + ", action annulée"); + sendPerso(attaquant, "est hors de port\xE9e de " + nomCiblePrincipale + " pour une attaque utilisant " + weaponName + ", action annul\xE9e"); } return; } - //On enlève les doublons de cibles qui partagent leurs PVs; + //On enl\xE8ve les doublons de cibles qui partagent leurs PVs; cibles = enleveDoublonsPartagePV(cibles); + //On v\xE9rifie si le d\xE9placement est possible + if (options.deplaceDe && cibles.length == 1) { + let target = cibles[0]; + let deplaceDe = options.deplaceDe; + if (deplaceDe.min && deplaceDe.min > target.distance) { + sendPerso(attaquant, "est trop proche de sa cible pour cette action, on annule"); + return; + } + if (target.distance > 0) { + let rayonAttaquant = tokenSizeAsCircle(attackingToken) / 2; + let rayonTarget = tokenSizeAsCircle(target.token) / 2; + let distMin = rayonAttaquant + rayonTarget; + let dist = distancePixToken(attackingToken, target.token); + if (dist - distMin > portee) { + //On essaie 10 chemins : la position la plus proche, puis les 9 qui entourent la cible + let k = distMin / dist; + if (portee > 0 && dist - distMin > deplaceDe.max) { + //On ne peut pas d\xE9placer au contact, on va donc d\xE9placer \xE0 la limite de la port\xE9e + k = portee / dist; + } + let tx = target.token.get('left'); + let ty = target.token.get('top'); + let x = k * attackingToken.get('left') + (1 - k) * tx; + let y = k * attackingToken.get('top') + (1 - k) * ty; + let ptCible = { + x, + y + }; + //On regarde s'il existe un chemin possible sans passer par un token + let allToks = + findObjs({ + _type: 'graphic', + _pageid: pageId, + _subtype: 'token', + layer: 'objects' + }); + page = page || getObj('page', pageId); + murs = getWalls(page, pageId, murs); + let surTrajet = + tokensSurTrajet(attackingToken, ptCible, rayonAttaquant, allToks, murs, deplaceDe.saut); + if (surTrajet.length > 0) { + //On ne cherche les autres positions que pour les attaques au contact + if (options.contact) { + let diag = distMin / Math.SQRT2; + let positionsAlternatives = [{ + x: tx - diag, + y: ty - diag + }, { + x: tx, + y: ty - distMin + }, { + x: tx + diag, + y: ty - diag + }, { + x: tx - distMin, + y: ty + }, { + x: tx + distMin, + y: ty + }, { + x: tx - diag, + y: ty + diag + }, { + x: tx, + y: ty + distMin + }, { + x: tx + diag, + y: ty + diag + }]; + let pt = pointOfToken(attackingToken); + positionsAlternatives.sort(function(p1, p2) { + let d1 = distancePoints(pt, p1); + let d2 = distancePoints(pt, p2); + if (d1 < d2) return -1; + if (d2 < d1) return 1; + return 0; + }); + positionsAlternatives.forEach(function(ptCible) { + if (deplaceDe.positionFinale) return; + let ts = + tokensSurTrajet(attackingToken, ptCible, rayonAttaquant, allToks, murs, deplaceDe.saut); + if (ts.length === 0) deplaceDe.positionFinale = ptCible; + }); + } + if (!deplaceDe.positionFinale) { + let msg = "Il y a des obstacles sur le trajet : " + surTrajet.join(', '); + sendPerso(attaquant, msg); + return; + } + } else { + deplaceDe.positionFinale = ptCible; + } + } + } + } let evt = options.evt || { type: "Attaque", action: { @@ -14846,13 +15066,20 @@ var COFantasy = COFantasy || function() { options: options } }; + if (options.terrainDifficile && options.aoe && options.aoe.type == 'disque') { + ajouteTerrainDifficile(options, evt); + } if (options.attaqueArmeeConjuree) { setAttrDuree(attaquant, 'attaqueArmeeConjuree', 1, evt); } evt.action = evt.action || { options: JSON.parse(JSON.stringify(options)) //pour la chance etc. }; - //On met à jour l'arme en main, si nécessaire + if (options.deplaceDe && options.deplaceDe.positionFinale) { + let p = options.deplaceDe.positionFinale; + moveTokenWithUndo(attackingToken, p.x, p.y, evt); + } + //On met \xE0 jour l'arme en main, si n\xE9cessaire if (weaponStats.arme || weaponStats.armeGauche || (weaponStats.divers && weaponStats.divers.toLowerCase().includes('arme'))) { options.weaponStats = weaponStats; options.messages = options.messages || []; @@ -14863,16 +15090,16 @@ var COFantasy = COFantasy || function() { if (options.contact && weaponStats.arme && predicateAsBool(attaquant, 'frappeDuVide')) { if (attributeAsBool(attaquant, 'limiteParTour_frappeDuVidePossible')) options.frappeDuVide = true; - //Il faut noter la première attaque au contact + //Il faut noter la premi\xE8re attaque au contact setTokenAttr(attaquant, 'limiteParCombat_dejaFrappeContact', true, evt); } let riposte = predicateAsBool(attaquant, 'riposte'); - let attaqueEnMeute = predicateAsInt(attaquant, 'attaqueEnMeute', 0); + let attaqueEnMeute = predicateAsInt(attaquant, 'attaqueEnMeute', 0, 2); if (attaqueEnMeute > 0) options.attaqueEnMeute = attaqueEnMeute; options.lienEpique = predicateAsBool(attaquant, 'lienEpique'); - if (riposte || options.attaqueEnMeute || options.lienEpique) { - //Dans ce cas, il faut stoquer les cibles attaquées - //(dans le cas de riposte, pour ne pas les re-proposer en riposte + if (riposte || options.attaqueEnMeute || options.lienEpique || alliesDAttaqueEnMeute.has(attackingCharId)) { + //Dans ce cas, il faut stoquer les cibles attaqu\xE9es + //(dans le cas de riposte, pour ne pas les re-proposer en riposte) let listeCibles = cibles.map(function(target) { return target.token.id; @@ -14885,7 +15112,7 @@ var COFantasy = COFantasy || function() { } else { setTokenAttr(attaquant, 'dernieresCiblesAttaquees', listeCibles, evt); } - } else { //L'attribut existe déjà + } else { //L'attribut existe d\xE9j\xE0 attrCiblesAttaquees = attrCiblesAttaquees[0]; evt.attributes = evt.attributes || []; let attaquesDuTour = attrCiblesAttaquees.get('current'); @@ -14910,13 +15137,13 @@ var COFantasy = COFantasy || function() { let explications = []; if (options.messages) explications = [...options.messages]; if (options.magieRapide) explications.push("Magie rapide"); - //On fait les tests pour les cibles qui bénéficieraient d'un sanctuaire + //On fait les tests pour les cibles qui b\xE9n\xE9ficieraient d'un sanctuaire let ciblesATraiter = cibles.length; let cibleTraitee = function() { ciblesATraiter--; if (ciblesATraiter === 0) { evalITE(attaquant, undefined, undefined, options, 0, evt, explications, options, function() { - resoudreAttaque(attaquant, cibles, attackLabel, weaponName, weaponStats, playerId, pageId, evt, explications, options, chargesArme); + resoudreAttaque(attaquant, cibles, attackLabel, weaponName, weaponStats, playerId, pageId, evt, explications, options); }); } }; @@ -14932,10 +15159,10 @@ var COFantasy = COFantasy || function() { let testId = 'sanctuaire_' + cible.token.id; testCaracteristique(attaquant, 'SAG', 15, testId, options, evt, function(tr) { if (tr.reussite) { - cible.messages.push(nomPerso(attaquant) + " réussit à passer outre le sanctuaire de " + nomPerso(cible) + " (jet de SAG " + tr.texte + "≥15)" + tr.modifiers); + cible.messages.push(nomPerso(attaquant) + " r\xE9ussit \xE0 passer outre le sanctuaire de " + nomPerso(cible) + " (jet de SAG " + tr.texte + "≥15)" + tr.modifiers); cibleTraitee(); } else { - let msgRate = "ne peut se résoudre à attaquer " + nomPerso(cible) + " (sanctuaire, jet de SAG " + tr.texte + "< 15)" + tr.rerolls + tr.modifiers; + let msgRate = "ne peut se r\xE9soudre \xE0 attaquer " + nomPerso(cible) + " (sanctuaire, jet de SAG " + tr.texte + "< 15)" + tr.rerolls + tr.modifiers; sendPerso(attaquant, msgRate); attaqueImpossible = true; } @@ -14944,14 +15171,14 @@ var COFantasy = COFantasy || function() { cibleTraitee(); } }; - // Attaque de Disparition avec jet opposé + // Attaque de Disparition avec jet oppos\xE9 if (options.disparition) { - //L'immunité aux attaques sournoise est testée plus loin et ne devrait - //pas empêcher le bonus de +5 à l'attaque. + //L'immunit\xE9 aux attaques sournoise est test\xE9e plus loin et ne devrait + //pas emp\xEAcher le bonus de +5 \xE0 l'attaque. let rollId = 'disparition_' + cible.token.id; let options1 = {...options }; - options1.competence = 'discrétion'; + options1.competence = 'discr\xE9tion'; let options2 = {...options }; options2.competence = 'perception'; @@ -14959,13 +15186,13 @@ var COFantasy = COFantasy || function() { cible.messages, evt, function(resultat, crit, rt1, rt2) { if (resultat != 2) { - cible.messages.push(nomPerso(attaquant) + " réapparait à côté de " + nomPerso(cible) + " et lui porte une attaque mortelle !"); + cible.messages.push(nomPerso(attaquant) + " r\xE9apparait \xE0 c\xF4t\xE9 de " + nomPerso(cible) + " et lui porte une attaque mortelle !"); // rajout des bonus de sournoise options.bonusAttaque = (options.bonusAttaque || 0) + 5; options.sournoise = options.sournoise || 0; options.sournoise += options.disparition; } else { - cible.messages.push(nomPerso(cible) + " repère " + nomPerso(attaquant) + " à temps pour réagir."); + cible.messages.push(nomPerso(cible) + " rep\xE8re " + nomPerso(attaquant) + " \xE0 temps pour r\xE9agir."); } evalSanctuaire(); }); //fin de testOppose (asynchrone) @@ -14977,16 +15204,16 @@ var COFantasy = COFantasy || function() { explications.push("Tentative d'acrobatie pour surprendre " + nomPerso(cible)); testCaracteristique(attaquant, 'DEX', 15, rollId, rollOptions, evt, function(tr, expl) { - explications.push("Résultat : " + tr.texte + tr.modifiers); + explications.push("R\xE9sultat : " + tr.texte + tr.modifiers); expl.forEach(function(m) { explications.push(m); }); if (tr.reussite) { - explications.push("Réussite : " + nomPerso(attaquant) + " peut faire une attaque sournoise"); + explications.push("R\xE9ussite : " + nomPerso(attaquant) + " peut faire une attaque sournoise"); options.sournoise = options.sournoise || 0; options.sournoise += options.attaqueAcrobatique; } else { - explications.push("Raté, " + nomPerso(attaquant) + " réalise une attaque normale" + tr.rerolls); + explications.push("Rat\xE9, " + nomPerso(attaquant) + " r\xE9alise une attaque normale" + tr.rerolls); } evalSanctuaire(); }); @@ -14994,7 +15221,7 @@ var COFantasy = COFantasy || function() { }); } - // On affiche les options d'attaque à droite + // On affiche les options d'attaque \xE0 droite function afficherOptionsAttaque(perso, opt_display) { let action_opts = '!cof-options-d-attaque --target ' + perso.token.id; let text_opts = ''; @@ -15007,11 +15234,11 @@ var COFantasy = COFantasy || function() { } if (ficheAttributeAsInt(perso, 'attaque_risquee_check')) { if (text_opts !== '') text_opts += '
    '; - text_opts += "Risquée"; + text_opts += "Risqu\xE9e"; } if (ficheAttributeAsInt(perso, 'attaque_assuree_check')) { if (text_opts !== '') text_opts += '
    '; - text_opts += "Assurée"; + text_opts += "Assur\xE9e"; } if (ficheAttributeAsInt(perso, 'attaque_dm_temp_check')) { if (text_opts !== '') text_opts += '
    '; @@ -15048,7 +15275,7 @@ var COFantasy = COFantasy || function() { let rawList; if (persoEstPNJ(perso)) rawList = extractRepeating(perso, 'pnjatk'); else rawList = extractRepeating(perso, 'armes'); - let liste = {}; //liste triée par label d'attaque + let liste = {}; //liste tri\xE9e par label d'attaque for (let pref in rawList) { let ra = rawList[pref]; if (ra.armelabel === undefined) ra.armelabel = 0; @@ -15073,7 +15300,7 @@ var COFantasy = COFantasy || function() { let rang = parseInt(ra.actionrang); if (isNaN(rang) || rang < 0) rang = 0; if (actions[rang]) { - error("Plusieurs actions de même rang " + rang + " dans la liste d'actions du tour", ra); + error("Plusieurs actions de m\xEAme rang " + rang + " dans la liste d'actions du tour", ra); continue; } actions[rang] = ra; @@ -15082,11 +15309,11 @@ var COFantasy = COFantasy || function() { return actions; } - // on récupère la valeur de l'action dont chaque Macro #/Ability % est mis dans un tableau 'action' + // on r\xE9cup\xE8re la valeur de l'action dont chaque Macro #/Ability % est mis dans un tableau 'action' //Pour chaque action, on a une commande, un texte et des options. //On appelle f(commande, texte, macros, attackStats) - // le dernier argument est optionnel, et n'est là que pour éviter d'avoir à recalculer attackStats - //actionsDuTour peut être un nombre entre 0 et 4 (listes sur la fiche), ou + // le dernier argument est optionnel, et n'est l\xE0 que pour \xE9viter d'avoir \xE0 recalculer attackStats + //actionsDuTour peut \xEAtre un nombre entre 0 et 4 (listes sur la fiche), ou // une ability function treatActions(perso, actionsDuTour, abilities, f) { let actions; // La liste des actions @@ -15147,7 +15374,7 @@ var COFantasy = COFantasy || function() { } else { actionCode = action.trim(); if (actionCode === '') return; - if (actionCode.startsWith('//')) return; //Ligne commentée + if (actionCode.startsWith('//')) return; //Ligne comment\xE9e } let actionCommands = actionCode.split(' '); actionCommands = actionCommands.filter(function(c) { @@ -15224,7 +15451,7 @@ var COFantasy = COFantasy || function() { case '!options': found = true; if (actionCommands.length > 1) { - options = actionCode.substring(8); //démarre par ' ' + options = actionCode.substring(8); //d\xE9marre par ' ' } break; case '!attaques': @@ -15272,8 +15499,8 @@ var COFantasy = COFantasy || function() { if (found) { actionsAAfficher = true; } else { - // Si on n'a toujours rien trouvé, on ajoute un petit log - log('Ability et macro non trouvé : ' + actionCode); + // Si on n'a toujours rien trouv\xE9, on ajoute un petit log + log('Ability et macro non trouv\xE9 : ' + actionCode); } }); } @@ -15298,7 +15525,7 @@ var COFantasy = COFantasy || function() { } else if (action == 'Attaques en traitre') { actions = findListeActions(attaquant, 'AttaqueEnTraitre', abilities); if (actions === undefined) - actions = findListeActions(attaquant, 'Attaques en traître', abilities); + actions = findListeActions(attaquant, 'Attaques en tra\xEEtre', abilities); } } let actionsOpportunite = []; @@ -15322,7 +15549,7 @@ var COFantasy = COFantasy || function() { }); actionsOpportunite.reverse(); } else { - //On affiche l'attaque avec l'arme en main + les attaques naturelles cochées + //On affiche l'attaque avec l'arme en main + les attaques naturelles coch\xE9es let listeAttaques = listAllAttacks(attaquant); for (let label in listeAttaques) { let arme = listeAttaques[label]; @@ -15344,14 +15571,14 @@ var COFantasy = COFantasy || function() { retarde: true, }; afficherOptionsAttaque(attaquant, opt_display); - //On crée un display sans le header + //On cr\xE9e un display sans le header let display = startFramedDisplay(undefined, "Attaque " + type + " possible", attaquant, opt_display); cibles.forEach(function(target) { - if (target.name === undefined) { //TODO vérifier que c'est utile + if (target.name === undefined) { //TODO v\xE9rifier que c'est utile let targetChar = getObj('character', target.charId); if (targetChar === undefined) { - error('Impossible de trouver le personnage représentant ' + nomPerso(target), target); + error('Impossible de trouver le personnage repr\xE9sentant ' + nomPerso(target), target); return; } target.name = targetChar.get('name'); @@ -15373,7 +15600,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, bouton(cmd, action.text, attaquant)); }); }); - // on envoie la liste aux joueurs qui gèrent l'attaquant + // on envoie la liste aux joueurs qui g\xE8rent l'attaquant let playerIds = getPlayerIds(attaquant); playerIds.forEach(function(playerid) { addFramedHeader(display, playerid, true); @@ -15394,7 +15621,7 @@ var COFantasy = COFantasy || function() { x.dmgTotal += bonusCrit.val; } - function immuniseAuType(target, dmgType, attaquant) { + function immuniseAuType(target, dmgType, attaquant, options) { if (predicateAsBool(target, 'immunite_' + dmgType)) { if (dmgType == 'acide' && predicateAsBool(attaquant, 'batonDesRunesMortes') && predicateAsBool(target, 'ennemiDuBatonDesRunesMortes')) return false; return true; @@ -15406,6 +15633,7 @@ var COFantasy = COFantasy || function() { return false; case 'poison': if (estNonVivant(target)) return true; + if (estDemon(target) && !(options && options.magique)) return true; if (predicateAsBool(target, 'vegetatif')) return true; if (attributeAsBool(target, 'sangDeLArbreCoeur')) return true; if (predicateOrAttributeAsBool(target, 'controleSanguin')) return true; @@ -15418,6 +15646,7 @@ var COFantasy = COFantasy || function() { return attributeAsBool(target, 'presenceGlaciale'); case 'maladie': if (estNonVivant(target)) return true; + if (estDemon(target) && !(options && options.magique)) return true; if (predicateAsBool(target, 'vegetatif')) return true; return attributeAsBool(target, 'sangDeLArbreCoeur'); case 'drain': @@ -15429,15 +15658,15 @@ var COFantasy = COFantasy || function() { function immuniseAsphyxie(target, expliquer) { if (predicateAsBool(target, 'creatureArtificielle') || estNonVivant(target)) { - if (expliquer) expliquer("L'asphyxie est sans effet sur une créature non-vivante"); + if (expliquer) expliquer("L'asphyxie est sans effet sur une cr\xE9ature non-vivante"); return true; } if (estDemon(target)) { - if (expliquer) expliquer("L'asphyxie est sans effet sur un démon"); + if (expliquer) expliquer("L'asphyxie est sans effet sur un d\xE9mon"); return true; } if (predicateAsBool(target, 'vegetatif')) { - if (expliquer) expliquer("L'asphyxie est sans effet sur une créature végétative"); + if (expliquer) expliquer("L'asphyxie est sans effet sur une cr\xE9ature v\xE9g\xE9tative"); return true; } return false; @@ -15460,9 +15689,9 @@ var COFantasy = COFantasy || function() { // Fonction asynchrone // displayRes est optionnel, et peut avoir 2 arguments - // - un texte affichant le jet de dégâts - // - la valeur finale des dégâts infligés - // crit est un booléen, il augmente de 1 (ou options.critCoef) le coefficient (option.dmgCoef) et active certains effets + // - un texte affichant le jet de d\xE9g\xE2ts + // - la valeur finale des d\xE9g\xE2ts inflig\xE9s + // crit est un bool\xE9en, il augmente de 1 (ou options.critCoef) le coefficient (option.dmgCoef) et active certains effets function dealDamage(target, dmg, otherDmg, evt, crit, options, explications, displayRes) { if (options === undefined) options = {}; let expliquer = function(msg) { @@ -15478,7 +15707,7 @@ var COFantasy = COFantasy || function() { (options.aoe === undefined && attributeAsBool(target, 'formeGazeuse')) || (predicateAsBool(target, 'apparition') && !options.energiePositive)) { - expliquer("L'attaque passe à travers de " + nomPerso(target)); + expliquer("L'attaque passe \xE0 travers de " + nomPerso(target)); if (displayRes) displayRes('0', 0, 0); return 0; } @@ -15503,7 +15732,7 @@ var COFantasy = COFantasy || function() { options.aoe.type == 'cone' && predicateAsBool(options.attaquant, 'ennemiDuBatonDesRunesMortes') && predicateAsBool(target, 'batonDesRunesMortes') && attributeAsBool(target, 'runeLizura')) { - expliquer("Lizura => immunité au souffle de " + nomPerso(options.attaquant)); + expliquer("Lizura => immunit\xE9 au souffle de " + nomPerso(options.attaquant)); if (displayRes) displayRes('0', 0, 0); return 0; } @@ -15514,7 +15743,7 @@ var COFantasy = COFantasy || function() { if (target.diviseDmg) diviseDmg *= target.diviseDmg; if (options.attaquant && predicateAsBool(options.attaquant, 'creatureDeLHiver') && predicateAsBool(target, 'armeDeLEte')) { diviseDmg += 4; - expliquer("L'arme de l'été divise les dégâts de l'attaque"); + expliquer("L'arme de l'\xE9t\xE9 divise les d\xE9g\xE2ts de l'attaque"); } if (options.attaqueEnEtantGobe) diviseDmg *= 2; if (options.sortilege && predicateAsBool(target, 'esquiveDeLaMagie')) @@ -15532,25 +15761,25 @@ var COFantasy = COFantasy || function() { if (predicateAsBool(target, 'armureLourdeGuerrier') && ficheAttributeAsBool(target, 'defarmureon', false) && ficheAttributeAsInt(target, 'defarmure', 0) >= 7) { - expliquer("L'armure lourde de " + nomPerso(target) + " lui permet d'ignorer les dégâts critiques"); + expliquer("L'armure lourde de " + nomPerso(target) + " lui permet d'ignorer les d\xE9g\xE2ts critiques"); } else if (predicateAsBool(target, 'immuniteAuxCritiques')) { - expliquer("Le succès critique est sans effet"); + expliquer("Le succ\xE8s critique est sans effet"); } else { if (options.critCoef) critCoef = options.critCoef; if (target.critCoef) critCoef += target.critCoef; dmgCoef += critCoef; if (predicateAsBool(target, 'armureProtection') && ficheAttributeAsBool(target, 'defarmureon', false)) { - expliquer("L'armure de protection de " + nomPerso(target) + " le protège du critique"); + expliquer("L'armure de protection de " + nomPerso(target) + " le prot\xE8ge du critique"); diviseDmg++; } else if (predicateAsBool(target, 'bouclierProtection') && ficheAttributeAsInt(target, 'defbouclieron', 0)) { - expliquer("Le bouclier de protection de " + nomPerso(target) + " le protège du critique"); + expliquer("Le bouclier de protection de " + nomPerso(target) + " le prot\xE8ge du critique"); diviseDmg++; } else if (predicateAsBool(target, 'anneauProtection')) { - expliquer("L'anneau de protection de " + nomPerso(target) + " le protège du critique"); + expliquer("L'anneau de protection de " + nomPerso(target) + " le prot\xE8ge du critique"); diviseDmg++; } if (predicateAsBool(target, 'bouclierProtection') && ficheAttributeAsBool(target, 'defbouclieron', false)) { - expliquer("Le bouclier de protection de " + nomPerso(target) + " le protège du critique"); + expliquer("Le bouclier de protection de " + nomPerso(target) + " le prot\xE8ge du critique"); diviseDmg++; } } @@ -15616,16 +15845,17 @@ var COFantasy = COFantasy || function() { dmgTotal = x.dmgTotal; } addToDmgTotal(0, dmgTotal, dmg, expliquer, evt); - //On trie les DM supplémentaires selon leur type + //On trie les DM suppl\xE9mentaires selon leur type let dmgParType = {}; otherDmg.forEach(function(d) { if (_.has(dmgParType, d.type)) dmgParType[d.type].push(d); else dmgParType[d.type] = [d]; }); - // Dommages de même type que le principal, mais à part, donc non affectés par les critiques + // Dommages de m\xEAme type que le principal, mais \xE0 part, donc non affect\xE9s par les critiques let mainDmgType = dmg.type; let dmgExtra = dmgParType[mainDmgType]; - if (dmgExtra && dmgExtra.length > 0 && !immuniseAuType(target, mainDmgType, options.attaquant)) { + if (dmgExtra && dmgExtra.length > 0 && + !immuniseAuType(target, mainDmgType, options.attaquant, options)) { if (dmgCoef > 1) dmgDisplay = "(" + dmgDisplay + ")"; showTotal = true; let count = dmgExtra.length; @@ -15656,8 +15886,8 @@ var COFantasy = COFantasy || function() { // Effets quand on rentre en combat // attaquant est optionnel - // exlications doit être défini - // ne rajoute pas evt à l'historique + // exlications doit \xEAtre d\xE9fini + // ne rajoute pas evt \xE0 l'historique // revoie stateCOF.combat, garanti non false function entrerEnCombat(attaquant, cibles, explications, evt) { let selected = []; @@ -15700,7 +15930,7 @@ var COFantasy = COFantasy || function() { return initiative(selected, evt); //ne recalcule pas l'init } - //capa est le nom d'un prédicat. Si le prédicat est numérique, cela donne + //capa est le nom d'un pr\xE9dicat. Si le pr\xE9dicat est num\xE9rique, cela donne //la limite, sinon la limite est 1 // retourne // - utilisations: les nombre d'utilisations restantes, @@ -15722,7 +15952,7 @@ var COFantasy = COFantasy || function() { attribut = attribut[0]; utilisations = parseInt(attribut.get('current')); if (isNaN(utilisations)) { - error("Resource pour " + capa + " mal formée", attribut); + error("Resource pour " + capa + " mal form\xE9e", attribut); return; } } @@ -15912,7 +16142,7 @@ var COFantasy = COFantasy || function() { return attCar + ficheAttributeAsInt(attaquant, 'niveau', 1) + attDiv; } - //Retourne le label de l'attaque à l'arme de jet. + //Retourne le label de l'attaque \xE0 l'arme de jet. function estAussiArmeDeJet(options) { if (options.startsWith('-')) options = ' ' + options; options = options.split(' --'); @@ -16007,7 +16237,7 @@ var COFantasy = COFantasy || function() { }, }); } else { - let exprDuree = parseDice(value, 'durée'); + let exprDuree = parseDice(value, 'dur\xE9e'); let duree = randomInteger(6); if (exprDuree) { if (exprDuree.nbDe <= 0) { @@ -16034,7 +16264,7 @@ var COFantasy = COFantasy || function() { } else { error("Type de poison " + typePoison + " non reconnu.", poisonAttr); } - explications.push("L'arme est empoisonnée"); + explications.push("L'arme est empoisonn\xE9e"); return defPoison; } @@ -16047,7 +16277,7 @@ var COFantasy = COFantasy || function() { let nombreMunitionsEmpoisonnees = parseInt(infosPoisonMunitions.substring(index + 1)); if (!isNaN(seuil) && !isNaN(nombreMunitionsEmpoisonnees) && nombreMunitionsEmpoisonnees > 0) { let defPoison = effetPoison(poisonAttr, seuil, attaquant, explications, options); - explications.push("L'arme est empoisonnée"); + explications.push("L'arme est empoisonn\xE9e"); if (nombreMunitionsEmpoisonnees == 1) { evt.deletedAttributes = evt.deletedAttributes || []; evt.deletedAttributes.push(poisonAttr); @@ -16064,15 +16294,15 @@ var COFantasy = COFantasy || function() { } } - //N'ajoute pas evt à l'historique - function resoudreAttaque(attaquant, cibles, attackLabel, weaponName, weaponStats, playerId, pageId, evt, explications, options, chargesArme) { + //N'ajoute pas evt \xE0 l'historique + function resoudreAttaque(attaquant, cibles, attackLabel, weaponName, weaponStats, playerId, pageId, evt, explications, options) { let attackingCharId = attaquant.charId; let attackingToken = attaquant.token; let attackerTokName = nomPerso(attaquant); - attaquant.additionalDmg = [...options.additionalDmg]; // Reset du calcul des dommages additionnels liés à l'attaquant + attaquant.additionalDmg = [...options.additionalDmg]; // Reset du calcul des dommages additionnels li\xE9s \xE0 l'attaquant let sujetAttaquant = onGenre(attaquant, 'il', 'elle'); if (options.contact) { - //Prise en compte du corps élémentaire + //Prise en compte du corps \xE9l\xE9mentaire let typeCorpsElem = predicateAsBool(attaquant, 'corpsElementaire'); if (typeCorpsElem && typeCorpsElem !== true) { let nbDes = predicateAsInt(attaquant, 'nbCorpsElementaire', 1); @@ -16087,7 +16317,7 @@ var COFantasy = COFantasy || function() { // Les armes de jet if (weaponStats.armeDeJet && !estMook && !(options.ricochets && options.ricochets.cibles.length > 0)) { if (weaponStats.nbArmesDeJet < 1) { - sendPerso(attaquant, "plus de " + weaponName + " à lancer."); + sendPerso(attaquant, "plus de " + weaponName + " \xE0 lancer."); return; } let attrName = weaponStats.prefixe + 'armejetqte'; @@ -16103,12 +16333,12 @@ var COFantasy = COFantasy || function() { if (attr.length > 0) { attr = attr[0]; if (attr.length > 1) { - error("Plus d'un attribut pour la quantité d'armes de jet", attr); + error("Plus d'un attribut pour la quantit\xE9 d'armes de jet", attr); attr[1].remove(); } max = parseInt(attr.get('max')); if (isNaN(max) || max < 1) { - error("Maximum de " + weaponName + " mal formé, vérifier sur la fiche", attr); + error("Maximum de " + weaponName + " mal form\xE9, v\xE9rifier sur la fiche", attr); max = 1; } evt.attributes.push({ @@ -16127,19 +16357,19 @@ var COFantasy = COFantasy || function() { attribute: attr, }); } - //On cherche si l'arme de jet est empoisonée + //On cherche si l'arme de jet est empoison\xE9e let poisonAttr = tokenAttribute(attaquant, 'enduitDePoison_' + attackLabel); effetPoisonSurMunitions(poisonAttr, attaquant, explications, options, evt); let restant = weaponStats.nbArmesDeJet; if (randomInteger(100) < weaponStats.tauxDePerte) { if (weaponStats.tauxDePerte < 100) - explications.push(weaponName + " n'est pas récupérable"); + explications.push(weaponName + " n'est pas r\xE9cup\xE9rable"); attr.set('max', max - 1); options.armeDeJetPerdue = true; } restant--; attr.set('current', restant); - if (!options.armeDeJetPerdue) { //prépare pour un éventuel retour en main + if (!options.armeDeJetPerdue) { //pr\xE9pare pour un \xE9ventuel retour en main options.attrArmeDeJet = { attribute: attr, restant: restant @@ -16148,33 +16378,33 @@ var COFantasy = COFantasy || function() { if (restant === 0) { degainerArmeLancee(attaquant, attackLabel, evt); } - explications.push("Il reste " + restant + " " + weaponName + " à " + attackerTokName); + explications.push("Il reste " + restant + " " + weaponName + " \xE0 " + attackerTokName); } } if (options.aussiArmeDeJet && !estMook) { let armeAssociee = getWeaponStats(attaquant, options.aussiArmeDeJet); if (armeAssociee && armeAssociee.armeDeJet) { if (armeAssociee.nbArmesDeJet < 1) { - sendPerso(attaquant, "a déjà lancé tous ses " + weaponName); + sendPerso(attaquant, "a d\xE9j\xE0 lanc\xE9 tous ses " + weaponName); return; } } else { - error("L'arme de label " + options.aussiArmeDeJet + " n'est pas une arme de jet, option ignorée", armeAssociee); + error("L'arme de label " + options.aussiArmeDeJet + " n'est pas une arme de jet, option ignor\xE9e", armeAssociee); } } // Munitions if (options.munition) { if (estMook) { - error("Les munitions ne sont pas supportées pour les tokens qui ne sont pas liées à un personnage", attackingToken); + error("Les munitions ne sont pas support\xE9es pour les tokens qui ne sont pas li\xE9es \xE0 un personnage", attackingToken); } - if (options.munition.nom) { //Ancienne variante, obsolète depuis mars 2023 + if (options.munition.nom) { //Ancienne variante, obsol\xE8te depuis mars 2023 let munitionsAttr = findObjs({ _type: 'attribute', _characterid: attackingCharId, name: 'munition_' + options.munition.nom }); if (munitionsAttr.length === 0) { - sendPerso(attaquant, ": Pas de munition nommée " + options.munition.nom); + sendPerso(attaquant, ": Pas de munition nomm\xE9e " + options.munition.nom); return; } munitionsAttr = munitionsAttr[0]; @@ -16187,7 +16417,7 @@ var COFantasy = COFantasy || function() { } let munitionsMax = parseInt(munitionsAttr.get('max')); if (isNaN(munitionsMax)) { - error("Attribut de munitions mal formé", munitionsMax); + error("Attribut de munitions mal form\xE9", munitionsMax); return; } evt.attributes = evt.attributes || []; @@ -16196,7 +16426,7 @@ var COFantasy = COFantasy || function() { current: munitions, max: munitionsMax }); - //On cherche si la munition est empoisonnée + //On cherche si la munition est empoisonn\xE9e let poisonAttr = tokenAttribute(attaquant, 'enduitDePoison_munition_' + options.munition.nom); effetPoisonSurMunitions(poisonAttr, attaquant, explications, options, evt); munitions--; @@ -16206,12 +16436,12 @@ var COFantasy = COFantasy || function() { if (randomInteger(100) < options.munition.taux) munitionsMax--; } explications.push("Il reste " + munitions + " " + - options.munition.nom.replace(/_/g, ' ') + " à " + attackerTokName); + options.munition.nom.replace(/_/g, ' ') + " \xE0 " + attackerTokName); munitionsAttr.set('current', munitions); munitionsAttr.set('max', munitionsMax); } else { //Utilisation d'une munition de la fiche let m = options.munition; - let typeMunition = fieldAsString(m, 'typemunition', 'Flèche'); + let typeMunition = fieldAsString(m, 'typemunition', 'Fl\xE8che'); let nom = fieldAsString(m, 'nommunition', typeMunition); let munitions = fieldAsInt(m, 'qtemunition', 1); if (munitions < 1 || (options.tirDouble && munitions < 2)) { @@ -16221,7 +16451,7 @@ var COFantasy = COFantasy || function() { return; } let label = fieldAsString(m, 'labelmunition', '0'); - //On cherche si la munition est empoisonnée + //On cherche si la munition est empoisonn\xE9e let poisonAttr = tokenAttribute(attaquant, 'enduitDePoison_munition_' + label); effetPoisonSurMunitions(poisonAttr, attaquant, explications, options, evt); let munitionsMax = fieldAsInt(m, 'qtemunition_max', munitions); @@ -16245,8 +16475,8 @@ var COFantasy = COFantasy || function() { } else { msgm += "reste " + munitions + " "; } - msgm += nom + " à " + attackerTokName; - if (taux < 100 && perte > 0) msgm += ", et la munition utilisée n'est pas récupérable"; + msgm += nom + " \xE0 " + attackerTokName; + if (taux < 100 && perte > 0) msgm += ", et la munition utilis\xE9e n'est pas r\xE9cup\xE9rable"; explications.push(msgm); evt.attributes = evt.attributes || []; let name = m.prefixe + 'qtemunition'; @@ -16279,15 +16509,20 @@ var COFantasy = COFantasy || function() { } } } - // Armes chargées - if (options.semonce === undefined && options.tirDeBarrage === undefined) { + // Armes charg\xE9es + if ((!options.semonce || attributeAsInt(attaquant, 'attaqueADistanceRatee', 0) != 1) && !options.tirDeBarrage) { if (attackLabel && weaponStats && weaponStats.charge) { let currentCharge = 0; + let chargesArme = findObjs({ + _type: 'attribute', + _characterid: attackingCharId, + name: 'charge_' + attackLabel + }); if (chargesArme.length > 0) { currentCharge = parseInt(chargesArme[0].get('current')); } if (isNaN(currentCharge) || currentCharge < 1) { - sendPerso(attaquant, "ne peut pas attaquer avec " + weaponName + " car elle n'est pas chargée"); + sendPerso(attaquant, "ne peut pas attaquer avec " + weaponName + " car elle n'est pas charg\xE9e"); return; } if (options.tirDouble && @@ -16295,7 +16530,7 @@ var COFantasy = COFantasy || function() { currentCharge < 2) { sendPerso(attaquant, "ne peut pas faire de tir double avec ses" + weaponName + "s car " + - sujetAttaquant + " n'en a pas au moins 2 chargées"); + sujetAttaquant + " n'en a pas au moins 2 charg\xE9es"); return; } evt.attributes = evt.attributes || []; @@ -16304,7 +16539,7 @@ var COFantasy = COFantasy || function() { if (chargesGrenaille.length > 0) { let currentChargeGrenaille = parseInt(chargesGrenaille[0].get('current')); if (isNaN(currentChargeGrenaille) || currentChargeGrenaille < 1) { - sendPerso(attaquant, "ne peut pas attaquer avec " + weaponName + " car elle n'est pas chargée en grenaille"); + sendPerso(attaquant, "ne peut pas attaquer avec " + weaponName + " car elle n'est pas charg\xE9e en grenaille"); return; } if (options.tirDouble && @@ -16312,7 +16547,7 @@ var COFantasy = COFantasy || function() { currentChargeGrenaille < 2) { sendPerso(attaquant, "ne peut pas faire de tir double de grenaille avec ses" + weaponName + "s car " + - sujetAttaquant + " n'en a pas au moins 2 chargées de grenaille"); + sujetAttaquant + " n'en a pas au moins 2 charg\xE9es de grenaille"); return; } evt.attributes.push({ @@ -16333,7 +16568,7 @@ var COFantasy = COFantasy || function() { if (options.tirDouble && (!options.tirDouble.stats || options.tirDouble.label == attackLabel)) currentCharge -= 2; else currentCharge -= 1; - //Si l'arme n'est plus chargée, on peut perdre le bonus d'initiative + //Si l'arme n'est plus charg\xE9e, on peut perdre le bonus d'initiative if (currentCharge === 0 && bonusPlusViteQueSonOmbre(attaquant, weaponStats)) { updateNextInit(attaquant); @@ -16351,7 +16586,7 @@ var COFantasy = COFantasy || function() { if (chargesSecondeArme.length > 0) { let currentCharge2 = parseInt(chargesSecondeArme[0].get('current')); if (isNaN(currentCharge2) || currentCharge2 < 1) { - sendPerso(attaquant, "ne peut pas faire de tir double avec " + secondNom + " car ce n'est pas chargé"); + sendPerso(attaquant, "ne peut pas faire de tir double avec " + secondNom + " car ce n'est pas charg\xE9"); return; } evt.attributes = evt.attributes || []; @@ -16360,7 +16595,7 @@ var COFantasy = COFantasy || function() { if (chargesGrenaille2.length > 0) { let currentChargeGrenaille2 = parseInt(chargesGrenaille2[0].get('current')); if (isNaN(currentChargeGrenaille2) || currentChargeGrenaille2 < 1) { - sendPerso(attaquant, "ne peut pas faire de tir double avec " + secondNom + " car ce n'est pas chargé en grenaille"); + sendPerso(attaquant, "ne peut pas faire de tir double avec " + secondNom + " car ce n'est pas charg\xE9 en grenaille"); return; } evt.attributes.push({ @@ -16375,7 +16610,7 @@ var COFantasy = COFantasy || function() { attribute: chargesSecondeArme[0], current: currentCharge2 }); - chargesArme[0].set('current', currentCharge2 - 1); + chargesSecondeArme[0].set('current', currentCharge2 - 1); } } } @@ -16384,9 +16619,9 @@ var COFantasy = COFantasy || function() { } // Effets quand on rentre en combat entrerEnCombat(attaquant, cibles, explications, evt); - // On commence par le jet d'attaque de base : juste le ou les dés d'attaque - // et le modificateur d'arme et de caractéritiques qui apparaissent dans - // la description de l'attaque. Il faut quand même tenir compte des + // On commence par le jet d'attaque de base : juste le ou les d\xE9s d'attaque + // et le modificateur d'arme et de caract\xE9ritiques qui apparaissent dans + // la description de l'attaque. Il faut quand m\xEAme tenir compte des // chances de critique let crit = critEnAttaque(attaquant, weaponStats, options); let dice = 20; @@ -16402,7 +16637,7 @@ var COFantasy = COFantasy || function() { } } else if (getState(attaquant, 'immobilise')) { dice = 12; - explications.push("Attaquant immobilisé => D12 au lieu de D20 en Attaque"); + explications.push("Attaquant immobilis\xE9 => D12 au lieu de D20 en Attaque"); } else if (attributeAsBool(attaquant, 'mortMaisNAbandonnePas')) { dice = 12; explications.push("Attaquant mort mais n'abandonne pas => D12 au lieu de D20 en Attaque"); @@ -16426,7 +16661,7 @@ var COFantasy = COFantasy || function() { if (options.avantage !== undefined) { if (options.avantage > 0) nbDe = options.avantage; else { - nbDe = 2 - options.avantage; //désavantage + nbDe = 2 - options.avantage; //d\xE9savantage plusFort = false; } } @@ -16443,7 +16678,7 @@ var COFantasy = COFantasy || function() { // toEvaluateAttack inlines // 0: attack roll // 1: attack skill expression - // 2: dé de poudre + // 2: d\xE9 de poudre let toEvaluateAttack = attackExpression(attaquant, nbDe, dice, crit, plusFort, weaponStats); if (options.poudre) toEvaluateAttack += " [[1d20]]"; @@ -16482,17 +16717,17 @@ var COFantasy = COFantasy || function() { retarde: options.secret, auto: options.auto || options.ouvertureMortelle }); - // Cas des armes à poudre + // Cas des armes \xE0 poudre if (options.poudre && !predicateAsBool(attaquant, 'chimiste')) { let poudreNumber = rollNumber(afterEvaluateAttack[2]); let dePoudre = rollsAttack.inlinerolls[poudreNumber].results.total; explications.push( - "Dé de poudre : " + buildinline(rollsAttack.inlinerolls[poudreNumber])); + "D\xE9 de poudre : " + buildinline(rollsAttack.inlinerolls[poudreNumber])); if (dePoudre === 1) { evt.succes = false; if (d20roll === 1) { explications.push( - weaponName + " explose ! L'arme est complètement détruite"); + weaponName + " explose ! L'arme est compl\xE8tement d\xE9truite"); sendChat("", "[[2d6]]", function(res) { let rolls = res[0]; let explRoll = rolls.inlinerolls[0]; @@ -16513,7 +16748,7 @@ var COFantasy = COFantasy || function() { } else { explications.push( "La poudre explose dans " + weaponName + - ". L'arme est inutilisable jusqu'à la fin du combat"); + ". L'arme est inutilisable jusqu'\xE0 la fin du combat"); sendChat("", "[[1d6]]", function(res) { let rolls = res[0]; let explRoll = rolls.inlinerolls[0]; @@ -16550,7 +16785,7 @@ var COFantasy = COFantasy || function() { options.projection = true; } } - //Modificateurs en Attaque qui ne dépendent pas de la cible + //Modificateurs en Attaque qui ne d\xE9pendent pas de la cible let attBonusCommun = 0; if (!options.auto) { attBonusCommun = @@ -16560,36 +16795,36 @@ var COFantasy = COFantasy || function() { bonusDMA(attaquant, weaponName, evt, explications, options); } if (options.traquenard) { - if (attributeAsBool(attaquant, 'traquenardImpossible')) { - sendPerso(attaquant, "ne peut pas faire de traquenard, car ce n'est pas sa première attaque du combat"); + if (attributeAsBool(attaquant, 'attributDeCombat_premiereAttaque')) { + sendPerso(attaquant, "ne peut pas faire de traquenard, car ce n'est pas sa premi\xE8re attaque du combat"); return; } options.traquenard = persoInit(attaquant, evt); } - if (predicateAsBool(attaquant, 'traquenard') && !attributeAsBool(attaquant, 'traquenardImpossible')) { - setTokenAttr(attaquant, 'traquenardImpossible', true, evt); + if (!attributeAsBool(attaquant, 'attributDeCombat_premiereAttaque')) { + setTokenAttr(attaquant, 'attributDeCombat_premiereAttaque', true, evt); } - if (options.feinte) explications.push("Mais c'était une feinte..."); + if (options.feinte) explications.push("Mais c'\xE9tait une feinte..."); let mainDmgType = options.type || 'normal'; if (options.sortilege) options.ignoreObstacles = true; let echecCritique; - //Calcul des cibles touchées + //Calcul des cibles touch\xE9es //(et on ajuste le jet pour la triche) let ciblesTouchees = []; let count = cibles.length; cibles.forEach(function(target) { - // reset les champs de target qui vont être recalculés + // reset les champs de target qui vont \xEAtre recalcul\xE9s target.additionalDmg = []; target.effets = []; target.dmgCoef = 0; target.critCoef = 0; target.diviseDmg = 1; if (attributeAsBool(attaquant, 'menaceManoeuvre(' + target.token.id + ')')) { - explications.push(nomPerso(attaquant) + " attaque " + nomPerso(target) + " malgré la menace. " + nomPerso(target) + " a droit à une attaque au contact gratuite."); + explications.push(nomPerso(attaquant) + " attaque " + nomPerso(target) + " malgr\xE9 la menace. " + nomPerso(target) + " a droit \xE0 une attaque au contact gratuite."); removeTokenAttr(attaquant, 'menaceManoeuvre(' + target.token.id + ')', evt); setTokenAttr(attaquant, 'attaqueMalgreMenace(' + target.token.id + ')', 1, evt); } else if (attributeAsBool(attaquant, 'menaceManoeuvre(' + target.token.id + ',crit)')) { - explications.push(nomPerso(attaquant) + " attaque " + nomPerso(target) + " malgré la menace. " + nomPerso(target) + " a droit à une attaque au contact gratuite (DM x 2 !)."); + explications.push(nomPerso(attaquant) + " attaque " + nomPerso(target) + " malgr\xE9 la menace. " + nomPerso(target) + " a droit \xE0 une attaque au contact gratuite (DM x 2 !)."); removeTokenAttr(attaquant, 'menaceManoeuvre(' + target.token.id + ',crit)', evt); setTokenAttr(attaquant, 'attaqueMalgreMenace(' + target.token.id + ')', 2, evt); } @@ -16613,7 +16848,7 @@ var COFantasy = COFantasy || function() { target.percute = target.percute || options.percute; target.maxDmg = target.maxDmg || options.maxDmg; target.kiai = target.kiai || options.kiai; - //Les bonus d'attaque qui dépendent de la cible + //Les bonus d'attaque qui d\xE9pendent de la cible let bad = 0; if (!options.auto) bad = bonusAttaqueD(attaquant, target, weaponStats.portee, pageId, evt, target.messages, options); @@ -16622,7 +16857,7 @@ var COFantasy = COFantasy || function() { let amm = 'attaqueMalgreMenace(' + attaquant.token.id + ')'; if (options.contact && cibles.length == 1) { if (attributeAsBool(target, amm)) { - target.messages.push('Attaque automatique suite à une menace ignorée'); + target.messages.push('Attaque automatique suite \xE0 une menace ignor\xE9e'); options.auto = true; if (attributeAsInt(target, amm, 1) > 1) options.dmFoisDeux = true; target.additionalDmg.push({ @@ -16641,9 +16876,9 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '2' + options.d6 }); - target.messages.push(attackerTokName + " fait un traquenard à " + nomPerso(target)); + target.messages.push(attackerTokName + " fait un traquenard \xE0 " + nomPerso(target)); } else { - target.messages.push(attackerTokName + " n'est pas assez rapide pour faire un traquenard à " + nomPerso(target)); + target.messages.push(attackerTokName + " n'est pas assez rapide pour faire un traquenard \xE0 " + nomPerso(target)); } } let defautCuirasse = @@ -16676,7 +16911,7 @@ var COFantasy = COFantasy || function() { } let touche = true; let critique = false; - // Calcule si touché, et les messages de dégats et attaque + // Calcule si touch\xE9, et les messages de d\xE9gats et attaque if (options.auto) { addAttackSound("soundAttackSucces", weaponStats.divers, options); } else if (!options.interposer) { @@ -16684,7 +16919,7 @@ var COFantasy = COFantasy || function() { weaponStats.attaquePaire || weaponStats.attaqueImpaire; if (triche) { switch (triche) { - case "rate": + case 'rate': if (d20roll >= target.crit) { if (target.crit < 2) d20roll = 1; else d20roll = randomInteger(target.crit - 1); @@ -16696,7 +16931,7 @@ var COFantasy = COFantasy || function() { else d20roll = randomInteger(maxd20roll); } break; - case "touche": + case 'touche': if (d20roll == 1) d20roll = randomInteger(dice - 1) + 1; if ((d20roll + attSkill + attBonus) < defense) { let mind20roll = defense - attSkill - attBonus - 1; @@ -16740,7 +16975,7 @@ var COFantasy = COFantasy || function() { if (target.chatimentDuMale) { target.chatimentDuMaleRoll = target.chatimentDuMaleRoll || randomInteger(dice); target.chatimentDuMaleLowRoll = target.chatimentDuMaleRoll; - target.messages.push("Bénédiction de Maëdra => relance à " + target.chatimentDuMaleRoll + " du jet d'attaque contre un mâle"); + target.messages.push("B\xE9n\xE9diction de Ma\xEBdra => relance \xE0 " + target.chatimentDuMaleRoll + " du jet d'attaque contre un m\xE2le"); if (target.chatimentDuMaleRoll > targetd20roll) { targetd20roll = target.chatimentDuMaleRoll; target.chatimentDuMaleLowRoll = target.d20roll; @@ -16753,12 +16988,13 @@ var COFantasy = COFantasy || function() { if (getState(target, 'paralyse')) { paralyse = true; if (!options.attaqueAssuree) - target.messages.push("Cible paralysée => réussite critique automatique"); + target.messages.push("Cible paralys\xE9e => r\xE9ussite critique automatique"); } else if (getState(target, 'mort')) { paralyse = true; if (!options.attaqueAssuree) - target.messages.push("Cible inconsciente => réussite critique automatique"); + target.messages.push("Cible inconsciente => r\xE9ussite critique automatique"); } + target.margeDeToucher = attackRoll - defense; if (targetd20roll >= 15) { if (predicateAsBool(attaquant, 'champion')) options.champion = true; @@ -16776,13 +17012,13 @@ var COFantasy = COFantasy || function() { setTokenAttr(attaquant, 'etreinteImmole', idName(target), evt); setTokenAttr(target, 'etreinteImmolePar', idName(attaquant), evt); setState(target, 'immobilise', true, evt); - target.messages.push(nomPerso(attaquant) + " étreint " + nomPerso(target) + " et s'immole !"); + target.messages.push(nomPerso(attaquant) + " \xE9treint " + nomPerso(target) + " et s'immole !"); target.etreinteImmole = true; } if (options.etreinteScorpion) { setTokenAttr(attaquant, 'etreinteScorpionSur', idName(target), evt); setTokenAttr(target, 'etreinteScorpionPar', idName(attaquant), evt); - target.messages.push(nomPerso(attaquant) + " étreint " + nomPerso(target) + " !"); + target.messages.push(nomPerso(attaquant) + " \xE9treint " + nomPerso(target) + " !"); } if (targetd20roll >= 16 && options.contact) { let ecraser = predicateAsBool(attaquant, 'ecraser'); @@ -16803,7 +17039,7 @@ var COFantasy = COFantasy || function() { } let faireMouche; if (targetd20roll == 1 && options.chance === undefined) { - attackResult = " => échec critique"; + attackResult = " => \xE9chec critique"; attackResult += addAttackImg("imgAttackEchecCritique", weaponStats.divers, options); addAttackSound('soundAttackEchecCritique', weaponStats.divers, options); if (options.demiAuto) { @@ -16822,7 +17058,7 @@ var COFantasy = COFantasy || function() { } else if ((paralyse || options.ouvertureMortelle || targetd20roll == 20 || (targetd20roll >= target.crit && attackRoll >= defense) || (reglesOptionelles.divers.val.coups_critiques_etendus.val && attackRoll > defense + 9)) && !options.attaqueAssuree) { - attackResult = " => réussite critique"; + attackResult = " => r\xE9ussite critique"; attackResult += addAttackImg("imgAttackSuccesCritique", weaponStats.divers, options); addAttackSound('soundAttackSuccesCritique', weaponStats.divers, options); touche = true; @@ -16839,12 +17075,12 @@ var COFantasy = COFantasy || function() { } resetTenacite(attaquant, target, evt); } else if (options.champion || targetd20roll == 20 || paralyse) { - attackResult = " => succès"; + attackResult = " => succ\xE8s"; attackResult += addAttackImg("imgAttackSuccesChampion", weaponStats.divers, options); addAttackSound("soundAttackSuccesChampion", weaponStats.divers, options); resetTenacite(attaquant, target, evt); } else if (attackRoll < defense && targetd20roll < target.crit) { - attackResult = " => échec"; + attackResult = " => \xE9chec"; attackResult += addAttackImg("imgAttackEchec", weaponStats.divers, options); addAttackSound('soundAttackEchec', weaponStats.divers, options); evt.succes = false; @@ -16860,8 +17096,8 @@ var COFantasy = COFantasy || function() { } else touche = false; increaseTenacite(attaquant, target, evt); } else if (targetd20roll % 2 && attributeAsBool(target, 'clignotement')) { - target.messages.push(nomPerso(target) + " disparaît au moment où l'attaque aurait du l" + onGenre(target, 'e', 'a') + " toucher"); - attackResult = " => échec"; + target.messages.push(nomPerso(target) + " dispara\xEEt au moment o\xF9 l'attaque aurait du l" + onGenre(target, 'e', 'a') + " toucher"); + attackResult = " => \xE9chec"; attackResult += addAttackImg("imgAttackEchecClignotement", weaponStats.divers, options); addAttackSound('soundAttackEchecClignotement', weaponStats.divers, options); target.clignotement = true; @@ -16875,8 +17111,8 @@ var COFantasy = COFantasy || function() { target.dmgCoef--; evt.succes = false; } else touche = false; - } else { // Touché normal - attackResult = " => succès"; + } else { // Touch\xE9 normal + attackResult = " => succ\xE8s"; attackResult += addAttackImg("imgAttackSucces", weaponStats.divers, options); addAttackSound("soundAttackSucces", weaponStats.divers, options); resetTenacite(attaquant, target, evt); @@ -16889,7 +17125,7 @@ var COFantasy = COFantasy || function() { else if (attBonus < 0) bonusTexte += attBonus; if (ficheAttributeAsBool(attaquant, 'jets_caches', false)) { attRollValue = attackRoll; - sendChat('COF', "/w GM Jet caché d'attaque : " + buildinline(rollsAttack.inlinerolls[attRollNumber]) + bonusTexte); + sendChat('COF', "/w GM Jet cach\xE9 d'attaque : " + buildinline(rollsAttack.inlinerolls[attRollNumber]) + bonusTexte); } else { attRollValue = buildinline(rollsAttack.inlinerolls[attRollNumber]) + bonusTexte; } @@ -16945,7 +17181,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '2' + options.d6 }); - target.messages.push("Châtiment du mâle => +2d6 DM"); + target.messages.push("Ch\xE2timent du m\xE2le => +2d6 DM"); } } if (predicateAsBool(attaquant, 'batonDesRunesMortes') && attributeAsBool(attaquant, 'runeMelianil')) { @@ -16957,7 +17193,7 @@ var COFantasy = COFantasy || function() { target.messages.push("Melianil => +1d6 DM"); } if (attributeAsBool(target, 'momentDePerfection')) { - target.messages.push("Grâce à son instant de perfection, " + nomPerso(target) + " évite le coup !"); + target.messages.push("Gr\xE2ce \xE0 son instant de perfection, " + nomPerso(target) + " \xE9vite le coup !"); touche = false; evt.succes = false; } @@ -16970,7 +17206,7 @@ var COFantasy = COFantasy || function() { } } else { //Effet si on ne touche pas if (attributeAsBool(attaquant, 'momentDePerfection')) { - target.messages.push("Grâce à son instant de perfection, " + nomPerso(attaquant) + " touche !"); + target.messages.push("Gr\xE2ce \xE0 son instant de perfection, " + nomPerso(attaquant) + " touche !"); touche = true; evt.succes = true; } else { @@ -17002,6 +17238,11 @@ var COFantasy = COFantasy || function() { evt.succes = false; diminueMalediction(attaquant, evt); } + if (options.distance && predicateAsBool(attaquant, 'tirDeSemonce')) { + setTokenAttr(attaquant, 'attaqueADistanceRatee', 2, evt, { + maxVal: 1 + }); + } } } } @@ -17022,18 +17263,18 @@ var COFantasy = COFantasy || function() { let id = target.rollImageDecalee; if (id.val > 4) { target.touche = false; - target.messages.push(id.roll + ": l'attaque passe à travers l'image de " + nomPerso(target)); + target.messages.push(id.roll + ": l'attaque passe \xE0 travers l'image de " + nomPerso(target)); } else { - target.messages.push(id.roll + ": malgré l'image légèrement décalée de " + nomPerso(target) + " l'attaque touche"); + target.messages.push(id.roll + ": malgr\xE9 l'image l\xE9g\xE8rement d\xE9cal\xE9e de " + nomPerso(target) + " l'attaque touche"); } } else if (predicateAsBool(target, 'estUneIllusion')) { target.touche = false; - target.messages.push(nomPerso(target) + " disparait et se matérialise un peu plus loin"); + target.messages.push(nomPerso(target) + " disparait et se mat\xE9rialise un peu plus loin"); } } if (target.touche) { ciblesTouchees.push(target); - //Possibilités d'annuler l'attaque + //Possibilit\xE9s d'annuler l'attaque if (!options.pasDeDmg && isActive(target) && attributeAsBool(target, 'runeForgesort_protection') && attributeAsInt(target, 'limiteParCombat_runeForgesort_protection', 1) > 0) { @@ -17042,7 +17283,7 @@ var COFantasy = COFantasy || function() { options.preDmg[target.token.id].runeForgesort_protection = true; } if (!options.auto) { - //Seulement si elle n'est pas automatiquement réussie + //Seulement si elle n'est pas automatiquement r\xE9ussie if (isActive(target)) { if (!options.pasDeDmg && options.contact && !options.ignoreTouteRD) { @@ -17101,7 +17342,7 @@ var COFantasy = COFantasy || function() { } if (!options.aoe && capaciteDisponible(target, 'esquiveFatale', 'combat')) { if (target.ennemisAuContact === undefined) { - error(nomPerso(target) + " a la possibilité d'une esquive fatale, mais les ennemis au contact ne sont pas calculés", target); + error(nomPerso(target) + " a la possibilit\xE9 d'une esquive fatale, mais les ennemis au contact ne sont pas calcul\xE9s", target); } else { let ciblesEsquiveFatale = target.ennemisAuContact.filter(function(tok) { return (tok.id != attaquant.token.id); @@ -17157,7 +17398,7 @@ var COFantasy = COFantasy || function() { options.preDmg[target.token.id] = options.preDmg[target.token.id] || {}; options.preDmg[target.token.id].chairACanon = target.chairACanon; } - //Interception par un allié + //Interception par un alli\xE9 let alliesAvecInterception = []; if (target.alliesAuContact === undefined) { let allies = alliesParPerso[target.charId] || new Set(); @@ -17207,7 +17448,7 @@ var COFantasy = COFantasy || function() { alliesAvecInterception.push(perso); }); } - //On enlève les alliés qui sont cibles de l'attaque + //On enl\xE8ve les alli\xE9s qui sont cibles de l'attaque alliesAvecInterception = alliesAvecInterception.filter(function(p) { return cibles.every(function(c) { return c.token.id != p.token.id; @@ -17241,11 +17482,11 @@ var COFantasy = COFantasy || function() { } resolvePreDmgOptions(attaquant, ciblesTouchees, echecCritique, attackLabel, weaponStats, d20roll, display, options, evt, explications, pageId, cibles); } - }, true); //comme on est dans une boucle qui dépend de la cible, inTarget doit être vrai - }); //fin de détermination de toucher des cibles + }, true); //comme on est dans une boucle qui d\xE9pend de la cible, inTarget doit \xEAtre vrai + }); //fin de d\xE9termination de toucher des cibles }); // fin du jet d'attaque asynchrone } catch (e) { - error("Erreur pendant l'évaluation de " + toEvaluateAttack + " du test d'attaque", weaponStats); + error("Erreur pendant l'\xE9valuation de " + toEvaluateAttack + " du test d'attaque", weaponStats); log(e.name + ": " + e.message); } } @@ -17256,11 +17497,11 @@ var COFantasy = COFantasy || function() { function stringOfEtat(etat, perso) { if (etat == 'invisible') return etat; - else if (etat == 'penombre') return "dans la pénombre"; + else if (etat == 'penombre') return "dans la p\xE9nombre"; else if (etat == 'chef') return "est un leader"; let etext = etat; if (etat.endsWith('e')) { - etext = etat.substring(0, etat.length - 1) + 'é'; + etext = etat.substring(0, etat.length - 1) + '\xE9'; } if (perso === undefined) return etext; return etext + eForFemale(perso); @@ -17353,7 +17594,7 @@ var COFantasy = COFantasy || function() { function computeAttackDice(d, maxDmg, options) { if (isNaN(d) || d < 0) { - error("Dé d'attaque incorrect", d); + error("D\xE9 d'attaque incorrect", d); return 0; } let attDice = d; @@ -17412,7 +17653,7 @@ var COFantasy = COFantasy || function() { if (attCarBonus < 1) attCarBonus = ''; else attCarBonus = " +" + attCarBonus; } else { - target.messages.push(nomPerso(target) + " semble immunisé aux armes ordinaires"); + target.messages.push(nomPerso(target) + " semble immunis\xE9 aux armes ordinaires"); attNbDicesCible = 0; attCarBonus = ''; attDMBonus = ''; @@ -17423,7 +17664,7 @@ var COFantasy = COFantasy || function() { return addOrigin(attaquant.name, attNbDicesCible + symbde + attDiceCible + attCarBonus + attDMBonus); } - //retourne le mod de la caractéristique x, undefined si ce n'en est pas une + //retourne le mod de la caract\xE9ristique x, undefined si ce n'en est pas une function computeCarValue(perso, x) { switch (x) { case '@{FOR}': @@ -17497,7 +17738,7 @@ var COFantasy = COFantasy || function() { } sides = sides.split('|'); if (side < 0 || side >= sides.length) { - error("Le token de " + nomPerso(perso) + " n'a pas de face numéro " + side, sides); + error("Le token de " + nomPerso(perso) + " n'a pas de face num\xE9ro " + side, sides); return; } let oldSide = token.get('currentSide'); @@ -17509,40 +17750,40 @@ var COFantasy = COFantasy || function() { return oldSide; } - //Met un effet temporaire sur target. L'effet temporaire est spécifié dans ef + //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 être défini) - // - duree : true si c'est un effet à durée en tours - // - effetIndetermine : true si l'effet a une durée indéterminée (pas combat) - // - accumuleDuree : si la durée peut s'accumuler - // - typeDmg : le type de dégâts associé à l'effet, si pertinent + // - whisper : true si on doit chuchoter l'effet, undefined si on n'affiche pas (mais dans ce cas, target.messages doit \xEAtre d\xE9fini) + // - duree : true si c'est un effet \xE0 dur\xE9e en tours + // - effetIndetermine : true si l'effet a une dur\xE9e ind\xE9termin\xE9e (pas combat) + // - accumuleDuree : si la dur\xE9e peut s'accumuler + // - typeDmg : le type de d\xE9g\xE2ts associ\xE9 \xE0 l'effet, si pertinent // - message : la structure de messages (venant de messageEffetTemp ou autre) - // - dm : l'effet fait des dégâts + // - dm : l'effet fait des d\xE9g\xE2ts // - visible : l'effet est visible - // - prejudiciable : l'effet est préjudiciable (et donc cible de délivrance) - // - statusMarker : marker associé à l'effet + // - prejudiciable : l'effet est pr\xE9judiciable (et donc cible de d\xE9livrance) + // - statusMarker : marker associ\xE9 \xE0 l'effet // - pasDeMessageDActivation : pour ne pas afficher le message d'activation - // - image : lien d'une image à afficher - // - valeur : valeur associée à l'effet - // - valeurMax : champ max de l'attribut valeur associé à l'effet - // - saveParTour : caractéristiques du save par tour, si besoin. - // - saveActifParTour : caractéristiques du save actif par tour, si besoin. - // - attaquant : la personne à l'origine de l'effet - // - options : des options à mettre dans l'attribut d'options - // - tokenSide : change le côté du token à cette face + // - image : lien d'une image \xE0 afficher + // - valeur : valeur associ\xE9e \xE0 l'effet + // - valeurMax : champ max de l'attribut valeur associ\xE9 \xE0 l'effet + // - saveParTour : caract\xE9ristiques du save par tour, si besoin. + // - saveActifParTour : caract\xE9ristiques du save actif par tour, si besoin. + // - attaquant : la personne \xE0 l'origine de l'effet + // - options : des options \xE0 mettre dans l'attribut d'options + // - tokenSide : change le c\xF4t\xE9 du token \xE0 cette face function setEffetTemporaire(target, ef, duree, evt, options) { if (ef.effet == 'dedoublement') { if (attributeAsBool(target, 'dedouble') || attributeAsBool(target, 'dedoublement')) { if (ef.whisper !== undefined) { - whisperChar(target.charId, "a déjà été dédoublé pendant ce combat"); + whisperChar(target.charId, "a d\xE9j\xE0 \xE9t\xE9 d\xE9doubl\xE9 pendant ce combat"); } else { - target.messages.push(nomPerso(target) + " a déjà été dédoublé pendant ce combat"); + target.messages.push(nomPerso(target) + " a d\xE9j\xE0 \xE9t\xE9 d\xE9doubl\xE9 pendant ce combat"); } return; } let dedoubleMsg = - "Un double translucide de " + nomPerso(target) + " apparaît."; + "Un double translucide de " + nomPerso(target) + " appara\xEEt."; if (ef.attaquant) { dedoubleMsg += " Il est aux ordres de " + nomPerso(ef.attaquant); } @@ -17569,12 +17810,12 @@ var COFantasy = COFantasy || function() { if (estImmuniseAEffet(target, ef.effet)) { if (ef.whisper !== undefined) { if (ef.whisper === true) { - whisperChar(target.charId, "ne peut pas être affecté par l'effet de " + ef.effet); + whisperChar(target.charId, "ne peut pas \xEAtre affect\xE9 par l'effet de " + ef.effet); } else { - sendChar(target.charId, ef.whisper + "ne peut pas être affecté par l'effet de " + ef.effet); + sendChar(target.charId, ef.whisper + "ne peut pas \xEAtre affect\xE9 par l'effet de " + ef.effet); } } else { - target.messages.push(nomPerso(target) + " ne peut pas être affecté par l'effet de " + ef.effet); + target.messages.push(nomPerso(target) + " ne peut pas \xEAtre affect\xE9 par l'effet de " + ef.effet); } return; } @@ -17622,7 +17863,7 @@ var COFantasy = COFantasy || function() { accumuleAttr.set('current', duree + ',' + dureeAccumulee); } } - return; //Pas besoin de réappliquer, effet toujours en cours + return; //Pas besoin de r\xE9appliquer, effet toujours en cours } } let targetMsg = ''; @@ -17686,7 +17927,7 @@ var COFantasy = COFantasy || function() { setState(target, 'invisible', true, evt); break; case 'aspectDuDemon': - //On retire l'autre aspect du Nécromancien si il est présent + //On retire l'autre aspect du N\xE9cromancien si il est pr\xE9sent finDEffetDeNom(target, "aspectDeLaSuccube", evt); break; case 'aspectDeLaSuccube': @@ -17777,10 +18018,10 @@ var COFantasy = COFantasy || function() { } } - // Applique toutes les options de preDmg déjà sélectionnées - // Retourne vrai si l'option "continuer" a déjà été choisie + // Applique toutes les options de preDmg d\xE9j\xE0 s\xE9lectionn\xE9es + // Retourne vrai si l'option "continuer" a d\xE9j\xE0 \xE9t\xE9 choisie function resolvePreDmgOptions(attaquant, ciblesTouchees, echecCritique, attackLabel, weaponStats, d20roll, display, options, evt, explications, pageId, cibles) { - //Sauvegarde de l'état pour pouvoir relancer au niveau de cette fonction + //Sauvegarde de l'\xE9tat pour pouvoir relancer au niveau de cette fonction evt.action.currentOptions = options; evt.action.echecCritique = echecCritique; evt.action.attackLabel = attackLabel; @@ -17845,7 +18086,7 @@ var COFantasy = COFantasy || function() { if (preDmgToken.evitementGenerique && preDmgToken.evitementGenerique.length > 0) { let nbEvitementsGenerique = preDmgToken.evitementGenerique.length; let finaliseTargetPreDmg = function(msg, generalMsg) { - if (generalMsg !== '' && !continuer && !termineCible) { // rerolls uniquement si pas terminé + if (generalMsg !== '' && !continuer && !termineCible) { // rerolls uniquement si pas termin\xE9 explications.push(msg + generalMsg); } else { cible.messages.push(msg); @@ -17876,7 +18117,7 @@ var COFantasy = COFantasy || function() { }); if (regardPetrifiant && attributeAsBool(attaquant, 'detournerLeRegard') && getIntValeurOfEffet(attaquant, 'detournerLeRegard', 2) > 4) { - sendPerso(attaquant, "aperçoit " + nomPerso(regardPetrifiant) + " à travers ses paupières !"); + sendPerso(attaquant, "aper\xE7oit " + nomPerso(regardPetrifiant) + " \xE0 travers ses paupi\xE8res !"); let seuil = predicateAsInt(regardPetrifiant, 'regardPetrifiant', 0, 16) - 4; let commande = '!cof-effet petrifie --save CON ' + seuil + ' --lanceur ' + regardPetrifiant.token.id + ' --target ' + attaquant.token.id; @@ -17930,7 +18171,7 @@ var COFantasy = COFantasy || function() { let source = drains.find(function(d) { let sa = d.split(':'); if (sa.length != 2) { - log("Drain de sang mal formé : " + drains); + log("Drain de sang mal form\xE9 : " + drains); return false; } return attr.some(function(a) { @@ -17972,7 +18213,7 @@ var COFantasy = COFantasy || function() { }); let attackerTokName = nomPerso(attaquant); if (ciblesTouchees.length === 0 || options.test || options.feinte) { - //Évaluation finale pour le cas où l'attaque a raté + //\xC9valuation finale pour le cas o\xF9 l'attaque a rat\xE9 evalITE(attaquant, undefined, d20roll, options, 1, evt, explications, options, function() { if (options.attrArmeDeJet) { if (options.retourneEnMain) { @@ -17990,7 +18231,7 @@ var COFantasy = COFantasy || function() { options.attrArmeDeJet.attribute.set('current', options.attrArmeDeJet.restant + 1); explications.push(attackerTokName + " rattrape " + weaponStats.name); } else { - explications.push("Raté ! Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " à " + attackerTokName); + explications.push("Rat\xE9 ! Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " \xE0 " + attackerTokName); if (options.attrArmeDeJet.restant === 0) { degainerArmeLancee(attaquant, attackLabel, evt); } @@ -18002,7 +18243,7 @@ var COFantasy = COFantasy || function() { options.attrArmeDeJet.attribute.set('current', options.attrArmeDeJet.restant + 1); explications.push(weaponStats.name + " retourne dans la main de son lanceur"); } else { - explications.push("Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " à " + attackerTokName); + explications.push("Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " \xE0 " + attackerTokName); if (options.attrArmeDeJet.restant === 0) { degainerArmeLancee(attaquant, attackLabel, evt); } @@ -18015,12 +18256,12 @@ var COFantasy = COFantasy || function() { const attackingCharId = attaquant.charId; const attackingToken = attaquant.token; options.attaquant = attaquant; - //Les dégâts - //Dégâts insrits sur la ligne de l'arme + //Les d\xE9g\xE2ts + //D\xE9g\xE2ts insrits sur la ligne de l'arme let mainDmgType = options.type || 'normal'; let attNbDices = weaponStats.attNbDices; if (isNaN(attNbDices) || attNbDices < 0) { - error("Dés de l'attaque incorrect", attNbDices); + error("D\xE9s de l'attaque incorrect", attNbDices); return; } if (attNbDices) { @@ -18037,7 +18278,7 @@ var COFantasy = COFantasy || function() { } } } - // Les autres modifications aux dégâts qui ne dépendent pas de la cible + // Les autres modifications aux d\xE9g\xE2ts qui ne d\xE9pendent pas de la cible let attDMBonusCommun = ''; if (options.armeMagiquePlus) { attDMBonusCommun += " + " + options.armeMagiquePlus; @@ -18110,7 +18351,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '1' + options.d6, }); - explications.push("Même pas mal => +1" + options.d6 + " DM"); + explications.push("M\xEAme pas mal => +1" + options.d6 + " DM"); } if (!options.auto && options.attaqueEnPuissance) { attaquant.additionalDmg.push({ @@ -18140,20 +18381,20 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '1' + options.d6 }); - explications.push("Attaque à outrance => +1d6 DM"); + explications.push("Attaque \xE0 outrance => +1d6 DM"); } else { attaquant.additionalDmg.push({ type: mainDmgType, value: '2' + options.d6 }); - explications.push("Attaque à outrance => +2d6 DM"); + explications.push("Attaque \xE0 outrance => +2d6 DM"); } } if (attaquant.bonusCapitaine) attDMBonusCommun += " +" + attaquant.bonusCapitaine; - // Les autres sources de dégâts + // Les autres sources de d\xE9g\xE2ts if (options.distance) { - if (options.semonce) { + if (options.semonce && attributeAsInt(attaquant, 'attaqueADistanceRatee', 0) == 1) { attaquant.additionalDmg.push({ type: mainDmgType, value: '1' + options.d6 @@ -18168,7 +18409,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(attaquant, 'forceDeGeant')) { let bonusForceDeGeant = getIntValeurOfEffet(attaquant, 'forceDeGeant', 2); attDMBonusCommun += "+" + bonusForceDeGeant; - explications.push("Force de géant => +" + bonusForceDeGeant + " aux DM"); + explications.push("Force de g\xE9ant => +" + bonusForceDeGeant + " aux DM"); } if (options.frappeDuVide) { attaquant.additionalDmg.push({ @@ -18257,7 +18498,7 @@ var COFantasy = COFantasy || function() { explications.push(msgChampion); } ///////////////////////////////////////////////////////////////// - //Tout ce qui dépend de la cible + //Tout ce qui d\xE9pend de la cible let ciblesCount = ciblesTouchees.length; //Pour l'asynchronie let attaquesEnTraitrePossibles = {}; let finCibles = function() { @@ -18274,7 +18515,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, expl, 80); }); if (target.osBrises) { - addLineToFramedDisplay(display, nomPerso(target) + " a des os brisés "); + addLineToFramedDisplay(display, nomPerso(target) + " a des os bris\xE9s "); setTokenAttr(target, 'osBrises', true, evt); } }); @@ -18282,16 +18523,16 @@ var COFantasy = COFantasy || function() { for (let vid in attaquesEnTraitrePossibles) { let voleur = persoOfId(vid); if (voleur === undefined) continue; - if (capaciteDisponible(voleur, 'attaqueEnTraitre')) { - displayAttaqueOpportunite(vid, attaquesEnTraitrePossibles[vid], "en traître", 'Attaques en traitre', '--decrLimitePredicatParTour attaqueEnTraitre'); + if (capaciteDisponible(voleur, 'attaqueEnTraitre', 'tour')) { + displayAttaqueOpportunite(vid, attaquesEnTraitrePossibles[vid], "en tra\xEEtre", 'Attaques en traitre', '--decrLimitePredicatParTour attaqueEnTraitre'); } } } }; - //Le lien épique (+1d6 DM si les 2 attaquent la même cible + //Le lien \xE9pique (+1d6 DM si les 2 attaquent la m\xEAme cible let attaqueParLienEpique = new Set(); if (options.lienEpique) { - //On cherche les autres personnages avec le même lien épique + //On cherche les autres personnages avec le m\xEAme lien \xE9pique let allChars = findObjs({ type: 'character' }); @@ -18308,7 +18549,7 @@ var COFantasy = COFantasy || function() { }); } ciblesTouchees.forEach(function(target) { - //l'évaluation finale des conditions quand on sait si l'attaque a touché. + //l'\xE9valuation finale des conditions quand on sait si l'attaque a touch\xE9. evalITE(attaquant, target, d20roll, options, 1, evt, explications, options, function() { target.attaquant = attaquant; if (options.attrArmeDeJet) { @@ -18316,7 +18557,7 @@ var COFantasy = COFantasy || function() { options.attrArmeDeJet.attribute.set('current', options.attrArmeDeJet.restant + 1); explications.push(weaponStats.name + " retourne dans la main de son lanceur"); } else { - explications.push("Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " à " + attackerTokName); + explications.push("Il reste " + options.attrArmeDeJet.restant + " " + weaponStats.name + " \xE0 " + attackerTokName); if (options.attrArmeDeJet.restant === 0) { degainerArmeLancee(attaquant, attackLabel, evt); } @@ -18325,7 +18566,7 @@ var COFantasy = COFantasy || function() { } if (options.enveloppe !== undefined) { if (options.enveloppe.type == 'etreinte' && attributeAsBool(target, 'armureDEau')) { - target.messages.push("L'armure d'eau empêche " + nomPerso(target) + " d'être étreint"); + target.messages.push("L'armure d'eau emp\xEAche " + nomPerso(target) + " d'\xEAtre \xE9treint"); } else { let ligneEnveloppe = nomPerso(attaquant) + " peut "; let commandeEnvelopper = @@ -18333,7 +18574,7 @@ var COFantasy = COFantasy || function() { options.enveloppe.difficulte + ' ' + options.enveloppe.type + ' ' + options.enveloppe.expression; let verbeEnv = 'envelopper'; - if (options.enveloppe.type == 'etreinte') verbeEnv = 'étreindre'; + if (options.enveloppe.type == 'etreinte') verbeEnv = '\xE9treindre'; ligneEnveloppe += boutonSimple(commandeEnvelopper, verbeEnv); ligneEnveloppe += nomPerso(target); target.messages.push(ligneEnveloppe); @@ -18341,7 +18582,7 @@ var COFantasy = COFantasy || function() { } if (options.agripper) { if (attributeAsBool(target, 'armureDEau')) { - target.messages.push("L'armure d'eau empêche " + nomPerso(target) + " d'être aggripé"); + target.messages.push("L'armure d'eau emp\xEAche " + nomPerso(target) + " d'\xEAtre aggrip\xE9"); } else { let immobilise = estAussiGrandQue(attaquant, target); setTokenAttr(attaquant, 'agrippe', idName(target), evt); @@ -18349,7 +18590,7 @@ var COFantasy = COFantasy || function() { maxVal: immobilise }); if (immobilise) setState(target, 'immobilise', true, evt); - target.messages.push("est agrippé"); + target.messages.push("est agripp\xE9"); } } if (options.devorer) { @@ -18358,13 +18599,13 @@ var COFantasy = COFantasy || function() { let cmdAttaqueGratuite = '!cof-attack ' + attaquant.token.id + ' ' + target.token.id + ' ' + attackLabel; target.messages.push(boutonSimple(cmdAttaqueGratuite, 'Attaque gratuite')); } else { - target.messages.push(nomPerso(attaquant) + " a droit à une attaque gratuite contre " + nomPerso(target)); + target.messages.push(nomPerso(attaquant) + " a droit \xE0 une attaque gratuite contre " + nomPerso(target)); } let attackerForce = valAttribute(attaquant, 'FOR', 'force'); let targetForce = valAttribute(target, 'FOR', 'force'); if (targetForce <= attackerForce) { if (attributeAsBool(target, 'armureDEau')) { - target.messages.push("L'armure d'eau empêche " + nomPerso(target) + " d'être saisi"); + target.messages.push("L'armure d'eau emp\xEAche " + nomPerso(target) + " d'\xEAtre saisi"); } else { setState(target, 'renverse', true, evt); setState(target, 'immobilise', true, evt); @@ -18374,7 +18615,7 @@ var COFantasy = COFantasy || function() { } } if (options.attaqueViolente) { - target.messages.push(nomPerso(attaquant) + " fait une attaque violente. Jet de force opposé pour voir si " + nomPerso(target) + " se fait projeter"); + target.messages.push(nomPerso(attaquant) + " fait une attaque violente. Jet de force oppos\xE9 pour voir si " + nomPerso(target) + " se fait projeter"); target.effets.push({ attaqueViolente: true, save: true @@ -18383,25 +18624,25 @@ var COFantasy = COFantasy || function() { if (options.ecraser) { target.messages.push(nomPerso(attaquant) + " saisit " + nomPerso(target) + " entre ses bras puissants"); if (options.ecraser === true) { - error("Il faudrait préciser un label pour écraser", options.ecraser); + error("Il faudrait pr\xE9ciser un label pour \xE9craser", options.ecraser); } else { let cmdEcraser = '!cof-attack ' + attaquant.token.id + ' ' + target.token.id + ' ' + options.ecraser; - target.messages.push("et l'" + boutonSimple(cmdEcraser, 'écrase') + "."); + target.messages.push("et l'" + boutonSimple(cmdEcraser, '\xE9crase') + "."); } if (attributeAsBool(target, 'armureDEau')) { - target.messages.push("L'armure d'eau empêche " + nomPerso(target) + " d'être saisi"); + target.messages.push("L'armure d'eau emp\xEAche " + nomPerso(target) + " d'\xEAtre saisi"); } else { setTokenAttr(attaquant, 'ecrase', idName(target), evt); setTokenAttr(target, 'estEcrasePar', idName(attaquant), evt); } } if (options.saisirEtBroyer) { - target.messages.push(nomPerso(attaquant) + " soulève " + nomPerso(target) + " gesticulant" + eForFemale(target)); + target.messages.push(nomPerso(attaquant) + " soul\xE8ve " + nomPerso(target) + " gesticulant" + eForFemale(target)); if (attackLabel) { let cmdAttaqueGratuiteSaisi = '!cof-attack ' + attaquant.token.id + ' ' + target.token.id + ' ' + attackLabel + ' --bonusAttaque 5'; target.messages.push(boutonSimple(cmdAttaqueGratuiteSaisi, 'Attaque gratuite')); } else { - target.messages.push(nomPerso(attaquant) + " a droit à une attaque gratuite contre " + nomPerso(target)); + target.messages.push(nomPerso(attaquant) + " a droit \xE0 une attaque gratuite contre " + nomPerso(target)); } if (valAttribute(target, 'FOR', 'force') < valAttribute(attaquant, 'FOR', 'force')) { options.rolls = options.rolls || []; @@ -18418,7 +18659,7 @@ var COFantasy = COFantasy || function() { type: 'normal', value: Math.floor(distanceSaisiProjete.val) }); - target.messages.push(nomPerso(target) + " est projeté" + eForFemale(target) + " sur " + distanceSaisiProjete.roll + " mètres"); + target.messages.push(nomPerso(target) + " est projet\xE9" + eForFemale(target) + " sur " + distanceSaisiProjete.roll + " m\xE8tres"); } } if (options.projection && taillePersonnage(attaquant, 4) > taillePersonnage(target, 4)) { @@ -18452,10 +18693,10 @@ var COFantasy = COFantasy || function() { type: 'normal', value: dmgProjection }); - target.messages.push(nomPerso(target) + " est projeté sur " + distanceProjetee + " mètres"); + target.messages.push(nomPerso(target) + " est projet\xE9 sur " + distanceProjetee + " m\xE8tres"); } if (options.gober && taillePersonnage(attaquant, 4) > taillePersonnage(target, 4)) { - //On utilise la liste d'effets pour pouvoir gérer les jets asynchrones + //On utilise la liste d'effets pour pouvoir g\xE9rer les jets asynchrones target.effets.push({ gober: true, save: true @@ -18470,14 +18711,14 @@ var COFantasy = COFantasy || function() { type: 'normal', value: '2d6' }); - target.messages.push("Éventration => +2d6 DM"); + target.messages.push("\xC9ventration => +2d6 DM"); } } else { setTokenAttr(attaquant, 'limiteParTour_eventrationReussie', target.token.id, evt); } } let attDMBonus = attDMBonusCommun; - //Les modificateurs de dégâts qui dépendent de la cible + //Les modificateurs de d\xE9g\xE2ts qui d\xE9pendent de la cible if (target.tempDmg) { let forceTarg = modCarac(target, 'force'); if (forceTarg < 0) { @@ -18489,7 +18730,7 @@ var COFantasy = COFantasy || function() { if (options.pressionMortelle || target.pressionMortelle) { let pMortelle = tokenAttribute(target, 'pressionMortelle'); if (pMortelle.length === 0) { - sendPerso(attaquant, "essaie une pression mortelle, mais aucun point vital de " + nomPerso(target) + " n'a encore été affecté"); + sendPerso(attaquant, "essaie une pression mortelle, mais aucun point vital de " + nomPerso(target) + " n'a encore \xE9t\xE9 affect\xE9"); ciblesCount--; return; } @@ -18502,7 +18743,7 @@ var COFantasy = COFantasy || function() { let modDex = modCarac(attaquant, 'dexterite'); if (target.distance <= 5 * modDex) { attDMBonus += " + " + tirPrecis; - target.messages.push("Tir précis : +" + tirPrecis + " DM"); + target.messages.push("Tir pr\xE9cis : +" + tirPrecis + " DM"); } } } @@ -18510,7 +18751,7 @@ var COFantasy = COFantasy || function() { if (target.sournoise) sournoise += target.sournoise; if (target.critique && sournoise === 0 && predicateAsBool(attaquant, 'botteSecrete')) { sournoise = predicateAsInt(attaquant, 'attaqueSournoise', 1); - target.messages.push("Botte secrète !"); + target.messages.push("Botte secr\xE8te !"); } if (sournoise) { let limiteSournoisesParTour = predicateAsInt(attaquant, 'sournoisesParTour', 1); @@ -18520,7 +18761,7 @@ var COFantasy = COFantasy || function() { } else { setTokenAttr(attaquant, 'limiteParTour_sournoises', nbSournoises - 1, evt); if (predicateAsBool(target, 'immuniteAuxSournoises')) { - target.messages.push(nomPerso(target) + " est immunisé" + eForFemale(target) + " aux attaques sournoises"); + target.messages.push(nomPerso(target) + " est immunis\xE9" + eForFemale(target) + " aux attaques sournoises"); } else { if (options.ouvertureMortelle) { target.messages.push("Ouverture mortelle => + 2 x " + sournoise + options.d6 + " DM"); @@ -18530,13 +18771,13 @@ var COFantasy = COFantasy || function() { } let valueSournoise = sournoise + options.d6; if (predicateAsBool(target, 'armureProtection') && ficheAttributeAsBool(target, 'defarmureon', false)) { - target.messages.push("L'armure de protection de " + nomPerso(target) + " réduit l'attaque sournoise"); + target.messages.push("L'armure de protection de " + nomPerso(target) + " r\xE9duit l'attaque sournoise"); valueSournoise = "ceil(" + valueSournoise + "/2)"; } else if (predicateAsBool(target, 'bouclierProtection') && ficheAttributeAsInt(target, 'defbouclieron', 0)) { - target.messages.push("Le bouclier de protection de " + nomPerso(target) + " réduit l'attaque sournoise"); + target.messages.push("Le bouclier de protection de " + nomPerso(target) + " r\xE9duit l'attaque sournoise"); valueSournoise = "ceil(" + valueSournoise + "/2)"; } else if (predicateAsBool(target, 'anneauProtection')) { - target.messages.push("L'anneau de protection de " + nomPerso(target) + " réduit l'attaque sournoise"); + target.messages.push("L'anneau de protection de " + nomPerso(target) + " r\xE9duit l'attaque sournoise"); valueSournoise = "ceil(" + valueSournoise + "/2)"; } target.additionalDmg.push({ @@ -18564,7 +18805,7 @@ var COFantasy = COFantasy || function() { } if (predicateAsBool(attaquant, 'chasseurDeSorciere') && predicateAsBool(target, 'necromancien')) { attDMBonus += "+2"; - target.messages.push("Chasseur de sorcière => +2 en DM"); + target.messages.push("Chasseur de sorci\xE8re => +2 en DM"); } if (target.ennemiJure) { target.additionalDmg.push({ @@ -18619,7 +18860,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '1' + options.d6 }); - target.messages.push("Lien épique => + 1" + options.d6 + " DM"); + target.messages.push("Lien \xE9pique => + 1" + options.d6 + " DM"); } if (target.feinte) { let value = target.feinte + options.d6; @@ -18643,7 +18884,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '2d6' }); - target.messages.push("Cible énorme => +2d6 DM"); + target.messages.push("Cible \xE9norme => +2d6 DM"); } } if (options.contact && weaponStats.deuxMains && targetTaille > 4) { @@ -18653,18 +18894,18 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: '1d6' }); - target.messages.push("Arme tenue à 2 mains => +1d6 DM"); + target.messages.push("Arme tenue \xE0 2 mains => +1d6 DM"); } else if (targetTaille > 5) { target.additionalDmg.push({ type: mainDmgType, value: '2d6' }); - target.messages.push("Arme tenue à 2 mains et cible énorme => +2d6 DM"); + target.messages.push("Arme tenue \xE0 2 mains et cible \xE9norme => +2d6 DM"); } } if (predicateAsBool(attaquant, 'grosMonstreGrosseArme')) { options.puissant = true; - target.messages.push("Gros Monstre, grosse arme => dégâts de base augmentés"); + target.messages.push("Gros Monstre, grosse arme => d\xE9g\xE2ts de base augment\xE9s"); } } if (attributeAsBool(target, 'hemorragie') && !options.sortilege && !options.armeNaturelle) { @@ -18674,7 +18915,7 @@ var COFantasy = COFantasy || function() { value: '1d6', drainDeSang: sourceDrain }); - target.messages.push("Hémorragie => +1d6 DM"); + target.messages.push("H\xE9morragie => +1d6 DM"); } if (!options.pasDeDmg) { let loupParmiLesLoups = predicateAsInt(attaquant, 'loupParmiLesLoups', 0); @@ -18695,7 +18936,7 @@ var COFantasy = COFantasy || function() { }); target.messages.push("Laissez-le moi ! => +1d6 DM"); } - //Bonus aux DMs dus au défi samouraï + //Bonus aux DMs dus au d\xE9fi samoura\xEF let defiSamouraiAttr = tokenAttribute(attaquant, 'defiSamourai'); if (defiSamouraiAttr.length > 0) { defiSamouraiAttr = defiSamouraiAttr[0]; @@ -18716,7 +18957,7 @@ var COFantasy = COFantasy || function() { type: mainDmgType, value: bonusDefi }); - target.messages.push(attackerTokName + " bénéficie d'un bonus de +" + bonusDefi + " aux DMs contre " + nomPerso(target)); + target.messages.push(attackerTokName + " b\xE9n\xE9ficie d'un bonus de +" + bonusDefi + " aux DMs contre " + nomPerso(target)); } } if (options.vicieux) { @@ -18749,7 +18990,7 @@ var COFantasy = COFantasy || function() { } //Additional damage let additionalDmg = attaquant.additionalDmg.concat(target.additionalDmg); - //On enlève les DM qui ne passent pas les conditions + //On enl\xE8ve les DM qui ne passent pas les conditions additionalDmg = additionalDmg.filter(function(dmSpec) { if (dmSpec.conditions === undefined) return true; return dmSpec.conditions.every(function(cond) { @@ -18800,7 +19041,7 @@ var COFantasy = COFantasy || function() { mainDmgRollExpr += " + " + dmSpec.value; return false; }); - // On ajoute le jet pour les dégâts de critiques supplémentaires + // On ajoute le jet pour les d\xE9g\xE2ts de critiques suppl\xE9mentaires if (target.critique && options.additionalCritDmg) { options.additionalCritDmg.forEach(function(dmSpec) { extraDmgRollExpr += " [[" + dmSpec.value + "]]"; @@ -18817,9 +19058,9 @@ var COFantasy = COFantasy || function() { value: mainDmgRollExpr }; // toEvaluateDmg inlines - // 0 : roll de dégâts principaux - // 1+ : les rolls de dégâts supplémentaires - // 1+nb dégâts supplémentaires + : rolls de dégâts critiques + // 0 : roll de d\xE9g\xE2ts principaux + // 1+ : les rolls de d\xE9g\xE2ts suppl\xE9mentaires + // 1+nb d\xE9g\xE2ts suppl\xE9mentaires + : rolls de d\xE9g\xE2ts critiques let toEvaluateDmg = "[[" + mainDmgRollExpr + "]]" + extraDmgRollExpr; sendChat('', toEvaluateDmg, function(resDmg) { let rollsDmg = target.rollsDmg || resDmg[0]; @@ -18841,8 +19082,8 @@ var COFantasy = COFantasy || function() { dmSpec.total = dmSpec.total || rRoll.results.total; let addDmType = dmSpec.type || 'normal'; dmSpec.display = dmSpec.display || buildinline(rRoll, addDmType, options.magique); - } else { //l'expression de DM additionel est mal formée - error("Expression de dégâts de critiques mal formée : " + options.additionalCritDmg[i].value, options.additionalCritDmg[i]); + } else { //l'expression de DM additionel est mal form\xE9e + error("Expression de d\xE9g\xE2ts de critiques mal form\xE9e : " + options.additionalCritDmg[i].value, options.additionalCritDmg[i]); } }); if (target.additionalCritDmg.length === 0) delete target.additionalCritDmg; @@ -18855,28 +19096,28 @@ var COFantasy = COFantasy || function() { dmSpec.total = dmSpec.total || rRoll.results.total; let addDmType = dmSpec.type; dmSpec.display = dmSpec.display || buildinline(rRoll, addDmType, options.magique); - } else { //l'expression de DM additionel est mal formée - error("Expression de dégâts supplémentaires mal formée : " + additionalDmg[i].value, additionalDmg[i]); + } else { //l'expression de DM additionel est mal form\xE9e + error("Expression de d\xE9g\xE2ts suppl\xE9mentaires mal form\xE9e : " + additionalDmg[i].value, additionalDmg[i]); } }); if (options.expertDuCombatDMSpec) { correctAdditionalDmg.push(options.expertDuCombatDMSpec); } additionalDmg = correctAdditionalDmg; - if (target.touche) { //Devrait être inutile ? + if (target.touche) { //Devrait \xEAtre inutile ? if (options.tirDeBarrage) - target.messages.push("Tir de barrage : undo si la cible décide de ne pas bouger"); + target.messages.push("Tir de barrage : undo si la cible d\xE9cide de ne pas bouger"); if (options.pointsVitaux) - target.messages.push(attackerTokName + " vise des points vitaux mais ne semble pas faire de dégâts"); + target.messages.push(attackerTokName + " vise des points vitaux mais ne semble pas faire de d\xE9g\xE2ts"); if (options.pressionMortelle || target.pressionMortelle) { removeTokenAttr(target, 'pressionMortelle', evt); - target.messages.push(attackerTokName + " libère la pression des points vitaux, l'effet est dévastateur !"); + target.messages.push(attackerTokName + " lib\xE8re la pression des points vitaux, l'effet est d\xE9vastateur !"); spawnFx(target.token.get('left'), target.token.get('top'), 'bomb-death', pageId); } - if (options.pasDeDmg === undefined) { //si l'attaque fait des DM, possibilité d'attaque en traître + if (options.pasDeDmg === undefined) { //si l'attaque fait des DM, possibilit\xE9 d'attaque en tra\xEEtre if (attaquant.alliesAvecAttaqueEnTraitre === undefined) { attaquant.alliesAvecAttaqueEnTraitre = []; - //On cherche tous les alliés ayant l'attaque en traitre + //On cherche tous les alli\xE9s ayant l'attaque en traitre const allies = alliesParPerso[attaquant.charId] || new Set(); allies.forEach(function(ci) { if (!charPredicateAsBool(ci, 'attaqueEnTraitre')) return; @@ -18909,7 +19150,7 @@ var COFantasy = COFantasy || function() { } }); } - // change l'état de la cible, si spécifié + // change l'\xE9tat de la cible, si sp\xE9cifi\xE9 if (target.enflamme) { let enflammePuissance = 1; if (options.puissant) enflammePuissance = 2; @@ -18939,7 +19180,7 @@ var COFantasy = COFantasy || function() { } // Draw effect, if any if (options.fx) { - //Pour les cones, on fait un seul effet, car c'est bien géré. + //Pour les cones, on fait un seul effet, car c'est bien g\xE9r\xE9. if (!options.aoe || options.aoe.type != 'cone') { let tokenOrigine = attackingToken; if (options.origineDeLAttaque) @@ -18960,9 +19201,9 @@ var COFantasy = COFantasy || function() { } target.rollsDmg = rollsDmg; // Compte le nombre de saves pour la synchronisation - // (On ne compte pas les psave, gérés dans dealDamage) + // (On ne compte pas les psave, g\xE9r\xE9s dans dealDamage) let saves = 0; - //ajoute les états sans save à la cible + //ajoute les \xE9tats sans save \xE0 la cible let etats = options.etats; if (target.etats) { if (etats) etats = etats.concat(target.etats); @@ -18989,9 +19230,9 @@ var COFantasy = COFantasy || function() { saves++; return; //on le fera plus tard } - if (ce.typeDmg && immuniseAuType(target, ce.typeDmg, attaquant)) { + if (ce.typeDmg && immuniseAuType(target, ce.typeDmg, attaquant, options)) { if (!target['msgImmunite_' + ce.typeDmg]) { - target.messages.push(nomPerso(target) + " ne semble pas affecté" + eForFemale(target) + " par " + stringOfType(ce.typeDmg)); + target.messages.push(nomPerso(target) + " ne semble pas affect\xE9" + eForFemale(target) + " par " + stringOfType(ce.typeDmg)); target['msgImmunite_' + ce.typeDmg] = true; } return; @@ -19000,7 +19241,7 @@ var COFantasy = COFantasy || function() { setState(target, ce.etat, true, evt); let msgEtat; if (ce.etat == 'mort') - msgEtat = 'tué' + eForFemale(target); + msgEtat = 'tu\xE9' + eForFemale(target); else msgEtat = stringOfEtat(ce.etat, target); target.messages.push(nomPerso(target) + " est " + msgEtat + " par l'attaque"); @@ -19017,14 +19258,14 @@ var COFantasy = COFantasy || function() { } else { if (ce.condition.type == "moins") { target.messages.push( - "Grâce à sa " + ce.condition.text + ", " + nomPerso(target) + + "Gr\xE2ce \xE0 sa " + ce.condition.text + ", " + nomPerso(target) + " n'est pas " + stringOfEtat(ce.etat, target)); } } }); } let savesEffets = 0; - // Ajoute les effets sans save à la cible + // Ajoute les effets sans save \xE0 la cible let effets = options.effets; if (target.effets) { if (effets) effets = effets.concat(target.effets); @@ -19058,7 +19299,7 @@ var COFantasy = COFantasy || function() { (estElfe(target) || (predicateAsInt(target, 'voieDeLArchange', 1) > 2 && attributeAsBool(target, 'formeDAnge'))) ) { - target.messages.push(nomPerso(target) + " est immunisé à la paralysie des goules"); + target.messages.push(nomPerso(target) + " est immunis\xE9 \xE0 la paralysie des goules"); return; } if (ef.effet == 'affaibliTemp' && estMortVivant(attaquant) && predicateAsInt(target, 'voieDeLArchange', 1) > 2 && attributeAsBool(target, 'formeDAnge')) { @@ -19070,9 +19311,9 @@ var COFantasy = COFantasy || function() { savesEffets++; return; //on le fera plus tard } - if (ef.typeDmg && immuniseAuType(target, ef.typeDmg, attaquant)) { + if (ef.typeDmg && immuniseAuType(target, ef.typeDmg, attaquant, options)) { if (!target['msgImmunite_' + ef.typeDmg]) { - target.messages.push(nomPerso(target) + " ne semble pas affecté par " + stringOfType(ef.typeDmg)); + target.messages.push(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(ef.typeDmg)); target['msgImmunite_' + ef.typeDmg] = true; } return; @@ -19107,17 +19348,17 @@ var COFantasy = COFantasy || function() { affaiblirCaracPerso(target, carac, aff.val, expliquer, evt); }); } - // Tout ce qui se passe après les saves (autres que saves de diminution des dmg + // Tout ce qui se passe apr\xE8s les saves (autres que saves de diminution des dmg let afterSaves = function() { if (saves > 0) return; //On n'a pas encore fait tous les saves if (target.utiliseRuneProtection) { target.messages.push(nomPerso(target) + " utilise sa Rune de Protection pour annuler les dommages"); addToAttributeAsInt(target, 'limiteParCombat_runeForgesort_protection', 1, -1, evt); - // Pas de dégâts, donc pas d'appel à dealDamage + // Pas de d\xE9g\xE2ts, donc pas d'appel \xE0 dealDamage finCibles(); } else if (options.pasDeDmg || (additionalDmg.length === 0 && mainDmgRoll.total === 0 && attNbDices === 0)) { - // Pas de dégâts, donc pas d'appel à dealDamage + // Pas de d\xE9g\xE2ts, donc pas d'appel \xE0 dealDamage finCibles(); } else { dealDamage(target, mainDmgRoll, additionalDmg, evt, target.critique, @@ -19128,12 +19369,12 @@ var COFantasy = COFantasy || function() { if (suce === 0) { setTokenAttr(attaquant, 'bufDEF', -3, evt); target.messages.push( - attackerTokName + " s'agrippe à " + nomPerso(target) + - " et commence à lui sucer le sang"); + attackerTokName + " s'agrippe \xE0 " + nomPerso(target) + + " et commence \xE0 lui sucer le sang"); } if (suce + dmg >= 6) { target.messages.push( - "Repus, " + attackerTokName + " se détache et s'envole"); + "Repus, " + attackerTokName + " se d\xE9tache et s'envole"); target.messages.push(nomPerso(target) + " se sent un peu faible..."); setState(target, 'affaibli', true, evt); let defbuf = attributeAsInt(attaquant, 'bufDEF', 0); @@ -19146,7 +19387,7 @@ var COFantasy = COFantasy || function() { setTokenAttr(attaquant, 'strigeSuce', suce + dmg, evt); if (suce > 0) target.messages.push( - attackerTokName + " continue à sucer le sang de " + nomPerso(target)); + attackerTokName + " continue \xE0 sucer le sang de " + nomPerso(target)); } } if (dmgDrain || (dmg > 0 && (options.vampirise || target.vampirise))) { @@ -19176,7 +19417,7 @@ var COFantasy = COFantasy || function() { if ((estMortVivant(attaquant) && predicateAsInt(target, 'voieDeLArchange', 1) > 2 && attributeAsBool(target, 'formeDAnge')) || (predicateAsBool(attaquant, 'vampire') && predicateAsBool(target, 'immuniteAbsorptionVampire')) ) { - target.messages.push(nomPerso(target) + "n'est pas affecté" + eForFemale(target) + " par l'absorption d'énergie"); + target.messages.push(nomPerso(target) + "n'est pas affect\xE9" + eForFemale(target) + " par l'absorption d'\xE9nergie"); } else { soigneToken(attaquant, absorptionEnergie, evt, function(soins) { target.messages.push( @@ -19200,7 +19441,7 @@ var COFantasy = COFantasy || function() { target.dmgMessage = "DM : "; if (ficheAttributeAsBool(attaquant, 'jets_caches', false)) { target.dmgMessage += dmg; - sendChat('COF', "/w GM Jet caché de dommages : " + dmgDisplay); + sendChat('COF', "/w GM Jet cach\xE9 de dommages : " + dmgDisplay); } else { target.dmgMessage += dmgDisplay; } @@ -19249,7 +19490,7 @@ var COFantasy = COFantasy || function() { target.messages, function(dmgDisplay, dmg, dmgDrain) { let dmgMsg = - "Décharge électrique sur " + attackerTokName + " : " + + "D\xE9charge \xE9lectrique sur " + attackerTokName + " : " + dmgDisplay; target.messages.push(dmgMsg); finCibles(); @@ -19296,7 +19537,7 @@ var COFantasy = COFantasy || function() { target.messages, function(dmgDisplay, dmg, dmgDrain) { let dmgMsg = - "" + attackerTokName + " est glacé : " + + "" + attackerTokName + " est glac\xE9 : " + dmgDisplay + " DM"; target.messages.push(dmgMsg); finCibles(); @@ -19360,17 +19601,17 @@ var COFantasy = COFantasy || function() { let expliquer = function(msg) { target.messages.push(msg); }; - //Ajoute les états avec save à la cible + //Ajoute les \xE9tats avec save \xE0 la cible let etatsAvecSave = function() { if (savesEffets > 0 || saveAffaiblissements > 0) return; //On n'a pas encore fini avec les effets et les affaiblissements if (etats && saves > 0) { etats.forEach(function(ce, index) { if (ce.save) { if (testCondition(ce.condition, attaquant, [target], d20roll, options)) { - let msgPour = " pour résister à un effet"; + let msgPour = " pour r\xE9sister \xE0 un effet"; let msgEtat; if (ce.etat == 'mort') - msgEtat = 'tué' + eForFemale(target); + msgEtat = 'tu\xE9' + eForFemale(target); else msgEtat = stringOfEtat(ce.etat, target); let msgRate = ", " + nomPerso(target) + " est " + msgEtat + " par l'attaque"; @@ -19405,7 +19646,7 @@ var COFantasy = COFantasy || function() { } else { if (ce.condition.type == "moins") { target.messages.push( - "Grâce à sa " + ce.condition.text + ", " + nomPerso(target) + + "Gr\xE2ce \xE0 sa " + ce.condition.text + ", " + nomPerso(target) + " n'est pas " + stringOfEtat(ce.etat, target)); } saves--; @@ -19415,7 +19656,7 @@ var COFantasy = COFantasy || function() { }); } else afterSaves(); }; - // Ajoute les effets avec save à la cible + // Ajoute les effets avec save \xE0 la cible let effetsAvecSave = function() { if (saveAffaiblissements > 0) return; //On n'a pas encore fini avec les affaiblissements if (effets && savesEffets > 0) { @@ -19427,13 +19668,13 @@ var COFantasy = COFantasy || function() { options, target.messages, evt, function(resultat, crit, rt1, rt2) { if (resultat == 2) { - target.messages.push(nomPerso(target) + " est entièrement avalé par " + attackerTokName); + target.messages.push(nomPerso(target) + " est enti\xE8rement aval\xE9 par " + attackerTokName); setTokenAttr(attaquant, 'aGobe', idName(target), evt); setTokenAttr(target, 'estGobePar', idName(attaquant), evt); moveTokenWithUndo(target.token, attaquant.token.get('left'), attaquant.token.get('top'), evt); } else { if (resultat === 0) diminueMalediction(attaquant, evt); - target.messages.push(nomPerso(target) + " n'est pas avalé."); + target.messages.push(nomPerso(target) + " n'est pas aval\xE9."); } saves--; savesEffets--; @@ -19446,14 +19687,14 @@ var COFantasy = COFantasy || function() { function(resultat, crit, rt1, rt2) { if (resultat == 2) { let distance = rollDePlus(6); - target.messages.push(nomPerso(target) + " est projeté" + eForFemale(target) + " à " + - distance.roll + " mètres et tombe au sol"); + target.messages.push(nomPerso(target) + " est projet\xE9" + eForFemale(target) + " \xE0 " + + distance.roll + " m\xE8tres et tombe au sol"); setState(target, 'renverse', true, evt); if (attackLabel) { let cmdAttaqueGratuite = '!cof-attack ' + attaquant.token.id + ' ' + target.token.id + ' ' + attackLabel; target.messages.push(boutonSimple(cmdAttaqueGratuite, 'Attaque gratuite')); } else { - target.messages.push(nomPerso(attaquant) + " a droit à une attaque gratuite contre " + nomPerso(target)); + target.messages.push(nomPerso(attaquant) + " a droit \xE0 une attaque gratuite contre " + nomPerso(target)); } } else { if (resultat === 0) diminueMalediction(attaquant, evt); @@ -19464,9 +19705,9 @@ var COFantasy = COFantasy || function() { etatsAvecSave(); }); } else { - if (ef.typeDmg && immuniseAuType(target, ef.typeDmg, attaquant)) { + if (ef.typeDmg && immuniseAuType(target, ef.typeDmg, attaquant, options)) { if (!target['msgImmunite_' + ef.typeDmg]) { - target.messages.push(nomPerso(target) + " ne semble pas affecté par " + stringOfType(ef.typeDmg)); + target.messages.push(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(ef.typeDmg)); target['msgImmunite_' + ef.typeDmg] = true; } saves--; @@ -19476,7 +19717,7 @@ var COFantasy = COFantasy || function() { } let msgPour = " pour "; if (ef.msgSave) msgPour += ef.msgSave; - else msgPour += "résister à un effet"; + else msgPour += "r\xE9sister \xE0 un effet"; let msgRate = ", " + nomPerso(target) + " "; if (ef.duree && ef.message) { msgRate += messageActivation(target, ef.message); @@ -19507,7 +19748,7 @@ var COFantasy = COFantasy || function() { if (reussite && duree && ef.save.demiDuree) { reussite = false; duree = Math.ceil(duree / 2); - if (stateCOF.options.affichage.val.duree_effets.val) expliquer("La durée est réduite à " + duree + " tours"); + if (stateCOF.options.affichage.val.duree_effets.val) expliquer("La dur\xE9e est r\xE9duite \xE0 " + duree + " tours"); } if (!reussite) { ef.attaquant = attaquant; @@ -19529,15 +19770,15 @@ var COFantasy = COFantasy || function() { options, target.messages, evt, function(resultat, crit, rt1, rt2) { if (resultat == 2) { - target.messages.push(nomPerso(target) + " est piétiné par " + attackerTokName + ", dommages doublés"); + target.messages.push(nomPerso(target) + " est pi\xE9tin\xE9 par " + attackerTokName + ", dommages doubl\xE9s"); setState(target, 'renverse', true, evt); target.dmgCoef = (target.dmgCoef || 0) + 1; target.touche++; if (target.percute) { - target.messages.push(nomPerso(target) + " est projeté à " + + target.messages.push(nomPerso(target) + " est projet\xE9 \xE0 " + rollDePlus(6, { bonus: 1 - }).roll + " mètres"); + }).roll + " m\xE8tres"); effets = effets || []; effets.push({ effet: 'etourdiTemp', @@ -19556,7 +19797,7 @@ var COFantasy = COFantasy || function() { } } else { if (resultat === 0) diminueMalediction(attaquant, evt); - target.messages.push(nomPerso(target) + " n'est pas piétiné."); + target.messages.push(nomPerso(target) + " n'est pas pi\xE9tin\xE9."); } effetsAvecSave(); }); @@ -19577,8 +19818,8 @@ var COFantasy = COFantasy || function() { carac = randomCaracForId(id, options); } let saveOpts = { - msgPour: " pour résister à un affaiblissement de " + carac, - msgRate: ", raté.", + msgPour: " pour r\xE9sister \xE0 un affaiblissement de " + carac, + msgRate: ", rat\xE9.", attaquant, rolls: options.rolls, sortilege: options.sortilege, @@ -19599,7 +19840,7 @@ var COFantasy = COFantasy || function() { }); } else effetPietinement(); }; - // Peut faire peur à la cible + // Peut faire peur \xE0 la cible if (options.peur) { peurOneToken(target, options.peur.seuil, options.peur.duree, { @@ -19628,12 +19869,12 @@ var COFantasy = COFantasy || function() { let msg; switch (d12roll) { case 1: - msg = "Échec total : "; + msg = "\xC9chec total : "; if (estMag) { - msg += "le lanceur de sort perd le contrôle de la magie qu'il canalise et subit 1d4 dommages en retour par rang du sort lancé. "; + msg += "le lanceur de sort perd le contr\xF4le de la magie qu'il canalise et subit 1d4 dommages en retour par rang du sort lanc\xE9. "; msg += boutonCritique("!cof-dmg ?{Rang du sort}d4 --ignoreRD"); } else { - msg += "l'attaquant se blesse lui-même et s'inflige la moitié des dégâts de son attaque. L'attaquant ne peut plus attaquer ce tour. "; + msg += "l'attaquant se blesse lui-m\xEAme et s'inflige la moiti\xE9 des d\xE9g\xE2ts de son attaque. L'attaquant ne peut plus attaquer ce tour. "; msg += boutonCritique("!cof-bouton-echec-total " + evt.id); } return msg; @@ -19647,38 +19888,38 @@ var COFantasy = COFantasy || function() { } else { difficulte = 12; } - msg = "Bousculé (FOR) : l'attaquant est déséquilibré par son attaque "; + msg = "Bouscul\xE9 (FOR) : l'attaquant est d\xE9s\xE9quilibr\xE9 par son attaque "; msg += boutonCritique("!cof-set-state renverse true --save FOR " + difficulte); return msg; case 3: if (avecArme) { - msg = "Maladresse (DEX) : l'attaquant laisse échapper son arme qui tombe hors de portée immédiate."; + msg = "Maladresse (DEX) : l'attaquant laisse \xE9chapper son arme qui tombe hors de port\xE9e imm\xE9diate."; msg += boutonCritique("!cof-degainer --save DEX 12"); return msg; } - msg = "Déséquilibré (DEX) : l'attaquant est Ralenti pendant 3 tours."; + msg = "D\xE9s\xE9quilibr\xE9 (DEX) : l'attaquant est Ralenti pendant 3 tours."; msg += boutonCritique("!cof-effet-temp ralentiTemp 3 --save DEX 12"); return msg; case 4: - msg = "Coup de mou (CON) : l'attaquant est affaibli pendant 3 tours, ou jusqu'à ce qu'il consacre un tour ou 1 PR pour se rétablir."; + msg = "Coup de mou (CON) : l'attaquant est affaibli pendant 3 tours, ou jusqu'\xE0 ce qu'il consacre un tour ou 1 PR pour se r\xE9tablir."; msg += boutonCritique("!cof-effet-temp affaibliTemp 3 --save CON 12"); return msg; case 5: if (estCac) { - msg = "Erreur tactique (INT) : le personnage provoque une attaque (gratuite) d’un adversaire à son contact."; + msg = "Erreur tactique (INT) : le personnage provoque une attaque (gratuite) d\x2019un adversaire \xE0 son contact."; msg += boutonCritique("!cof-jet INT 12"); } else if (estMag) { - msg = "Aveuglé (INT) : le personnage ne contrôle pas sa puissance et une partie de celle-ci émet un flash qui l'aveugle temporairement."; + msg = "Aveugl\xE9 (INT) : le personnage ne contr\xF4le pas sa puissance et une partie de celle-ci \xE9met un flash qui l'aveugle temporairement."; msg += boutonCritique("!cof-effet-temp aveugleTemp 3 --save INT 12 --saveParTour CON 12"); } else { - //TODO : Implémenter un bouton "mauvais calcul" réalisant une attaque automatique sur un des Obstacle - msg = "Mauvais calcul (INT) : le personnage a une chance de toucher une autre cible sur la trajectoire de son tir. Déterminer la cible au hasard et relancer une attaque sur cette nouvelle cible."; + //TODO : Impl\xE9menter un bouton "mauvais calcul" r\xE9alisant une attaque automatique sur un des Obstacle + msg = "Mauvais calcul (INT) : le personnage a une chance de toucher une autre cible sur la trajectoire de son tir. D\xE9terminer la cible au hasard et relancer une attaque sur cette nouvelle cible."; msg += boutonCritique("!cof-jet INT 12"); } return msg; case 6: if (estCac) { - msg = "Exposé (SAG) : l'adversaire dispose d'un bonus de +10 à la touche pendant un round."; + msg = "Expos\xE9 (SAG) : l'adversaire dispose d'un bonus de +10 \xE0 la touche pendant un round."; cibles.forEach(function(cible) { msg += boutonCritique("!cof-effet-temp expose 1 --valeur " + cible.token.id + " --save SAG 12"); }); @@ -19688,11 +19929,11 @@ var COFantasy = COFantasy || function() { } return msg; case 7: - msg = "Ridicule (CHA) : le personnage fait un faux mouvement à la fois douloureux et ridicule, il subit l’état étourdi pendant un round pour reprendre contenance. "; + msg = "Ridicule (CHA) : le personnage fait un faux mouvement \xE0 la fois douloureux et ridicule, il subit l\x2019\xE9tat \xE9tourdi pendant un round pour reprendre contenance. "; msg += boutonCritique("!cof-effet-temp etourdiTemp 1 --save CHA 12"); return msg; case 8: - msg = "Inconfort : Une pièce d’armure bouge et elle devient plus gênante que protectrice. Malus en DEF et en attaque pour le reste du combat => Cuir : -1, Maille : -2, Plaque -3. "; + msg = "Inconfort : Une pi\xE8ce d\x2019armure bouge et elle devient plus g\xEAnante que protectrice. Malus en DEF et en attaque pour le reste du combat => Cuir : -1, Maille : -2, Plaque -3. "; msg += boutonCritique("!cof-effet-combat inconfort --valeur ?{Malus ?|-1,1|-2,2|-3,3} --save CHA 12"); return msg; default: @@ -19706,13 +19947,13 @@ var COFantasy = COFantasy || function() { stateCOF.currentAttackDisplay = undefined; if (stateCOF.afterDisplay) { let ad = stateCOF.afterDisplay; - stateCOF.afterDisplay = undefined; //on efface avant au cas où le script crash + stateCOF.afterDisplay = undefined; //on efface avant au cas o\xF9 le script crash ad.forEach(function(d) { sendPerso(d.destinataire, d.msg, true); }); } } else { - sendPlayer(msg, "Pas de résultat d'attaque à montrer"); + sendPlayer(msg, "Pas de r\xE9sultat d'attaque \xE0 montrer"); } } @@ -19768,7 +20009,7 @@ var COFantasy = COFantasy || function() { } //Affichage final d'une attaque - // attaquant est optionnel, mais si il est présent, cibles doit être un tableau et options un objet + // attaquant est optionnel, mais si il est pr\xE9sent, cibles doit \xEAtre un tableau et options un objet function finaliseDisplay(display, explications, evt, attaquant, cibles, options, echecCritique) { echecCritique = echecCritique || false; explications.forEach(function(expl) { @@ -19796,7 +20037,7 @@ var COFantasy = COFantasy || function() { line += "
    " + boutonSimple( "!cof-devier-les-coups " + evt.id + ' --target ' + target.token.id, - "dévier les coups"); + "d\xE9vier les coups"); nbBoutons++; } if (preDmgToken.paradeDeProjectiles) { @@ -19837,7 +20078,7 @@ var COFantasy = COFantasy || function() { } if (preDmgToken.resistanceALaMagieBarbare && preDmgToken.resistanceALaMagieBarbare !== 'reroll') { action = "!cof-resister-a-la-magie " + target.token.id + ' ' + evt.id; - line += "
    " + boutonSimple(action, "tenter de résister à la magie"); + line += "
    " + boutonSimple(action, "tenter de r\xE9sister \xE0 la magie"); nbBoutons++; } if (preDmgToken.cercleDeProtection && preDmgToken.cercleDeProtectionDe && @@ -19856,7 +20097,7 @@ var COFantasy = COFantasy || function() { } if (preDmgToken.chairACanon) { preDmgToken.chairACanon.forEach(function(tok) { - line += "
    " + boutonSimple("!cof-chair-a-canon " + target.token.id + ' ' + tok.id + ' ' + evt.id, "utiliser " + tok.get('name') + " comme chair à canon"); + line += "
    " + boutonSimple("!cof-chair-a-canon " + target.token.id + ' ' + tok.id + ' ' + evt.id, "utiliser " + tok.get('name') + " comme chair \xE0 canon"); nbBoutons++; }); } @@ -19920,9 +20161,9 @@ var COFantasy = COFantasy || function() { if (pc > 0 && !echecCritique) { addLineToFramedDisplay(display, boutonSimple("!cof-bouton-chance " + evt.id, "Chance") + " (reste " + pc + " PC)"); } - if (attributeAsBool(perso, 'runeForgesort_énergie') && - attributeAsInt(perso, 'limiteParCombat_runeForgesort_énergie', 1) > 0) { - addLineToFramedDisplay(display, boutonSimple("!cof-bouton-rune-energie " + evt.id, "Rune d'énergie")); + if (attributeAsBool(perso, 'runeForgesort_\xE9nergie') && + attributeAsInt(perso, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0) { + addLineToFramedDisplay(display, boutonSimple("!cof-bouton-rune-energie " + evt.id, "Rune d'\xE9nergie")); } if (capaciteDisponible(perso, 'petitVeinard', 'combat')) { addLineToFramedDisplay(display, boutonSimple("!cof-bouton-petit-veinard " + evt.id, "Petit veinard")); @@ -19953,13 +20194,13 @@ var COFantasy = COFantasy || function() { boutonSimple("!cof-bouton-pousser-kiai " + evt.id, "Kiai")); } if (capaciteDisponible(perso, 'petitVeinard', 'combat')) { - addLineToFramedDisplay(display, boutonSimple("!cof-bouton-petit-veinard " + evt.id, "Petit veinard") + " pour relancer un dé"); + addLineToFramedDisplay(display, boutonSimple("!cof-bouton-petit-veinard " + evt.id, "Petit veinard") + " pour relancer un d\xE9"); } } if (options && options.contact && cibles && attaquant && predicateAsBool(attaquant, 'enchainement')) { let cibleMorte = cibles.find(function(target) { - return target.token.get('bar1_value') == 0; + return target.pvPerdus && target.token.get('bar1_value') == 0; }); if (cibleMorte) { if (attaquant.ennemisAuContact === undefined) { @@ -19987,7 +20228,7 @@ var COFantasy = COFantasy || function() { attaquant.ennemisAuContact = tokensEnnemis; } if (attaquant.ennemisAuContact.length > 0) { - let msgEnchainement = nomPerso(attaquant) + " a droit à une attaque au contact gratuite contre "; + let msgEnchainement = nomPerso(attaquant) + " a droit \xE0 une attaque au contact gratuite contre "; let sep = ""; let armeEnMain = tokenAttribute(attaquant, 'armeEnMain'); let act; @@ -20077,7 +20318,8 @@ var COFantasy = COFantasy || function() { return c.token.id == tok.id; }); if (dejaTouche) return false; - if (distanceCombat(cible.token, tok, evt.action.pageId) > options.portee) return false; + let dist = distanceCombat(cible.token, tok, evt.action.pageId); + if (dist === 0 || dist > options.portee) return false; return true; }); let distance = distanceCombat(cible.token, attaquant.token, evt.action.pageId); @@ -20087,14 +20329,21 @@ var COFantasy = COFantasy || function() { activateRoundMarker(threadSync, cible.token); } let restants = options.ricochets.restants - 1; - let action = "!cof-attack " + attaquant.token.id + " @{target|token_id} " + evt.action.attackLabel + " --ricochets " + restants; + let baseAction = '!cof-attack ' + attaquant.token.id + ' '; + let optionsAction = ' ' + evt.action.attackLabel + ' --ricochets ' + restants; options.ricochets.cibles.forEach(function(c) { - action += ' ' + c.token.id; + optionsAction += ' ' + c.token.id; }); - action += ' ' + cible.token.id; + optionsAction += ' ' + cible.token.id; let msg = "Faire un "; - if (restants < 1) msg += "dernier "; - msg += boutonSimple(action, 'ricochet'); + if (restants === 0) msg += "dernier "; + if (tokens.length < 2) { + let action = baseAction + tokens[0].id + optionsAction; + msg += boutonSimple(action, 'ricochet vers ' + tokens[0].get('name')); + } else { + let action = baseAction + '@{target|token_id}' + optionsAction; + msg += boutonSimple(action, 'ricochet'); + } if (distance > options.portee) { if (restants < 1) msg += " (trop loin pour un retour en main)"; } else { @@ -20111,7 +20360,7 @@ var COFantasy = COFantasy || function() { } sendPerso(attaquant, "Plus de cible sur laquelle ricocher et trop loin pour un retour en main", true); } - } else { //on a raté, il faut remettre le rounMarker à sa place + } else { //on a rat\xE9, il faut remettre le rounMarker \xE0 sa place if (stateCOF.options.affichage.val.init_dynamique.val) { threadSync++; activateRoundMarker(threadSync, attaquant.token); @@ -20130,7 +20379,7 @@ var COFantasy = COFantasy || function() { } } - // RD spécifique au type + // RD sp\xE9cifique au type function typeRD(rd, dmgType) { if (dmgType === undefined || dmgType == 'normal') return 0; return (rd[dmgType] || 0); @@ -20141,7 +20390,7 @@ var COFantasy = COFantasy || function() { let proba1 = probaSucces(de, seuil, 1); return 1 - (1 - proba1) * (1 - proba1); } - if (seuil < 2) seuil = 2; // 1 est toujours un échec + if (seuil < 2) seuil = 2; // 1 est toujours un \xE9chec else if (seuil > 20) seuil = 20; return ((de - seuil) + 1) / de; } @@ -20231,31 +20480,32 @@ var COFantasy = COFantasy || function() { perso.dansAuraDeProfanation = res; return res; } - //s représente le save, avec une carac, une carac2 optionnelle et un seuil + //s repr\xE9sente le save, avec une carac, une carac2 optionnelle et un seuil //expliquer est une fonction qui prend en argument un string et le publie // options peut contenir les champs : - // - msgPour : message d'explication à afficher avant le jet - // - msgReussite : message à afficher en cas de réussite - // - msgRate : message à afficher si l'action rate - // - silencieuxSiPasAffecte: ne rien afficher pour les cibles immunisées - // - regard: l'attaque vient d'un regard, on peut détourner les yeux + // - msgPour : message d'explication \xE0 afficher avant le jet + // - msgReussite : message \xE0 afficher en cas de r\xE9ussite + // - msgRate : message \xE0 afficher si l'action rate + // - silencieuxSiPasAffecte: ne rien afficher pour les cibles immunis\xE9es + // - regard: l'attaque vient d'un regard, on peut d\xE9tourner les yeux // - attaquant : le {charId, token} de l'attaquant contre lequel le save se fait (si il y en a un) - // - type : le type de dégâts contre lequel on fait le save + // - type : le type de d\xE9g\xE2ts contre lequel on fait le save // - hideSaveTitle : cache le titre du save // - bonus : bonus au jet de save // s peut contenir: - // - carac : la caractéristique à utiliser pour le save - // - carac2 : caractéristique alternative - // - seuil : la difficulté du jet de sauvegarde - // - contact : la difficulté si la cible est au contact de options.attaquant + // - carac : la caract\xE9ristique \xE0 utiliser pour le save + // - carac2 : caract\xE9ristique alternative + // - seuil : la difficult\xE9 du jet de sauvegarde + // - contact : la difficult\xE9 si la cible est au contact de options.attaquant // - fauchage // - entrave (pour les action qui immobilisent, ralentissent ou paralysent) // - necromancie // - sortilege + // - augmenteAvecMargeDeToucher function save(s, target, saveId, expliquer, options, evt, afterSave) { - if (options.type && immuniseAuType(target, options.type, options.attaquant)) { + if (options.type && immuniseAuType(target, options.type, options.attaquant, options)) { if (!target['msgImmunite_' + options.type] && !options.silencieuxSiPasAffecte) { - expliquer(nomPerso(target) + " ne semble pas affecté par " + stringOfType(options.type)); + expliquer(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(options.type)); target['msgImmunite_' + options.type] = true; } afterSave(true, ''); @@ -20271,7 +20521,7 @@ var COFantasy = COFantasy || function() { } if (predicateAsBool(target, 'vegetatif')) { if (!options.silencieuxSiPasAffecte) - expliquer(nomPerso(target) + " est une créature végétative."); + expliquer(nomPerso(target) + " est une cr\xE9ature v\xE9g\xE9tative."); afterSave(true, ''); return; } @@ -20286,12 +20536,12 @@ var COFantasy = COFantasy || function() { } if (s.fauchage) { if (s.fauchage <= taillePersonnage(target, 4)) { - expliquer(nomPerso(target) + " est trop grand pour être fauché."); + expliquer(nomPerso(target) + " est trop grand pour \xEAtre fauch\xE9."); afterSave(true, ''); return; } if (predicateAsBool(target, 'inderacinable')) { - expliquer(nomPerso(target) + " est indéracinable."); + expliquer(nomPerso(target) + " est ind\xE9racinable."); afterSave(true, ''); return; } @@ -20300,7 +20550,7 @@ var COFantasy = COFantasy || function() { if (getState(target, 'mort') || getState(target, 'assomme') || getState(target, 'paralyse') || getState(target, 'endormi')) { if (!options.silencieuxSiPasAffecte) - expliquer(nomPerso(target) + " n'est pas en état d'éviter l'effet."); + expliquer(nomPerso(target) + " n'est pas en \xE9tat d'\xE9viter l'effet."); afterSave(false, ''); } } @@ -20314,23 +20564,23 @@ var COFantasy = COFantasy || function() { } if (s.entrave && predicateAsBool(target, 'actionLibre')) { bonus += 5; - expliquer("Action libre => +5 pour résister aux entraves"); + expliquer("Action libre => +5 pour r\xE9sister aux entraves"); } if (options.necromancie && attributeAsBool(target, 'sangDeLArbreCoeur')) { bonus += 5; - expliquer("Sang de l'Arbre-Coeur => +5 pour résister à la nécromancie"); + expliquer("Sang de l'Arbre-Coeur => +5 pour r\xE9sister \xE0 la n\xE9cromancie"); } if (options.type == 'poison') { if (predicateAsBool(target, 'liberateurDAnathazerin')) { bonus += 2; - expliquer("Libérateur d'Anathazerïn => +2 pour résister au poison"); + expliquer("Lib\xE9rateur d'Anathazer\xEFn => +2 pour r\xE9sister au poison"); } if (predicateAsBool(target, 'peauDEcorceAvancee') && attributeAsBool(target, 'peauDEcorce')) { let bonusPeau = getIntValeurOfEffet(target, 'peauDEcorce', 2); if (bonusPeau == 2 && predicateAsInt(target, 'voieDesForets', 0) > 3) bonusPeau = 4; bonus += bonusPeau; - expliquer("Peau d'écorce améliorée => +" + bonusPeau + " pour résister au poison"); + expliquer("Peau d'\xE9corce am\xE9lior\xE9e => +" + bonusPeau + " pour r\xE9sister au poison"); } } let bonusAttrs = []; @@ -20339,6 +20589,9 @@ var COFantasy = COFantasy || function() { if (s.contact && options.attaquant && distanceCombat(options.attaquant.token, target.token) === 0) { seuil = s.contact; } + if (s.augmenteAvecMargeDeToucher && target.margeDeToucher && target.margeDeToucher > 0) { + seuil += target.margeDeToucher; + } if (options.regard) { if (getState(target, 'aveugle')) { expliquer(nomPerso(target) + " ne voit rien."); @@ -20349,13 +20602,13 @@ var COFantasy = COFantasy || function() { switch (getIntValeurOfEffet(target, 'detournerLeRegard', 2)) { case 1: seuil -= 3; - expliquer("détourne un peu le regard => -3 à la difficulté"); + expliquer("d\xE9tourne un peu le regard => -3 \xE0 la difficult\xE9"); break; case 2: case 3: case 4: seuil -= 6; - expliquer("détourne le regard => -6 à la difficulté"); + expliquer("d\xE9tourne le regard => -6 \xE0 la difficult\xE9"); break; default: expliquer(nomPerso(target) + " ferme les yeux"); @@ -20365,7 +20618,7 @@ var COFantasy = COFantasy || function() { } } let carac = s.carac; - //Cas où le save peut se faire au choix parmis 2 caracs + //Cas o\xF9 le save peut se faire au choix parmis 2 caracs if (s.carac2) { carac = meilleureCarac(carac, s.carac2, target, seuil); } @@ -20415,11 +20668,11 @@ var COFantasy = COFantasy || function() { smsg += '">' + tr.texte + ''; } if (tr.reussite) { - smsg += " => réussite"; + smsg += " => r\xE9ussite"; if (options.msgReussite) smsg += options.msgReussite; smsg += tr.modifiers; } else { - smsg += " => échec"; + smsg += " => \xE9chec"; if (options.msgRate) smsg += options.msgRate; smsg += tr.rerolls + tr.modifiers; } @@ -20450,7 +20703,7 @@ var COFantasy = COFantasy || function() { return; } if ((sav.carac == 'CON' || sav.carac2 == 'CON') && estNonVivant(target)) { - expliquer("Les créatures non-vivantes sont immnunisées aux attaques qui demandent un test de constitution"); + expliquer("Les cr\xE9atures non-vivantes sont immnunis\xE9es aux attaques qui demandent un test de constitution"); afterSave({ succes: true, dmgDisplay: '0', @@ -20470,8 +20723,8 @@ var COFantasy = COFantasy || function() { return; } let saveOpts = { - msgPour: " pour réduire les dégâts", - msgReussite: ", dégâts divisés par 2", + msgPour: " pour r\xE9duire les d\xE9g\xE2ts", + msgReussite: ", d\xE9g\xE2ts divis\xE9s par 2", attaquant: ps.attaquant, rolls: ps.rolls, chanceRollId: ps.chanceRollId, @@ -20479,8 +20732,8 @@ var COFantasy = COFantasy || function() { energiePositive: ps.energiePositive }; if (totalSave) { - saveOpts.msgPour = " pour éviter les dégâts"; - saveOpts.msgReussite = ", dégâts évités"; + saveOpts.msgPour = " pour \xE9viter les d\xE9g\xE2ts"; + saveOpts.msgReussite = ", d\xE9g\xE2ts \xE9vit\xE9s"; } let saveId = 'parseSave_' + target.token.id; save(sav, target, saveId, expliquer, saveOpts, evt, @@ -20539,7 +20792,7 @@ var COFantasy = COFantasy || function() { if (r === '') return; let rds; let index = r.indexOf(':'); - if (index > 0) { //RD à un type particulier + if (index > 0) { //RD \xE0 un type particulier let type = r.substring(0, index); if (type == 'rdt' || type == 'sauf') return; if (type == 'magie') type = 'magique'; @@ -20550,7 +20803,7 @@ var COFantasy = COFantasy || function() { return; } index = r.indexOf('/'); - if (index > 0) { //RD sauf à des types + if (index > 0) { //RD sauf \xE0 des types rds = parseInt(r.substring(0, index)); if (isNaN(rds) || rds === 0) return; let sauf = r.substring(index + 1); @@ -20625,7 +20878,7 @@ var COFantasy = COFantasy || function() { case 'acide': return "l'acide"; case 'electrique': - return "l'électricité"; + return "l'\xE9lectricit\xE9"; case 'soniqe': return "le son"; case 'maladie': @@ -20642,7 +20895,7 @@ var COFantasy = COFantasy || function() { case 'FOR': return "la force"; case 'DEX': - return "la dextérité"; + return "la dext\xE9rit\xE9"; case 'CON': return "la constitution"; case 'INT': @@ -20668,7 +20921,7 @@ var COFantasy = COFantasy || function() { (predicateAsBool(target, 'protectionDMZone') || predicateAsBool(target, 'protectionDMZone_' + dmgType))) { divide(); - expliquer(nomPerso(target) + " est protégé contre les dégâts de zone"); + expliquer(nomPerso(target) + " est prot\xE9g\xE9 contre les d\xE9g\xE2ts de zone"); } if (predicateOrAttributeAsBool(target, 'resistanceA_' + dmgType) || predicateAsBool(target, 'diviseEffet_' + dmgType)) { divide(); @@ -20720,7 +20973,7 @@ var COFantasy = COFantasy || function() { divide(); } if (options.vampirise && predicateOrAttributeAsBool(target, 'controleSanguin')) { - expliquer(nomPerso(target) + " contrôle parfaitement son sang"); + expliquer(nomPerso(target) + " contr\xF4le parfaitement son sang"); divide(); } } @@ -20730,9 +20983,9 @@ var COFantasy = COFantasy || function() { return options.aoe && !options.sortilege && options.aoe.type == 'cone' && options.attaquant && estDraconique(options.attaquant); } - //On a déterminé les DM du type principal(possiblement après save des dmgExtra, maintenant on applique les résistances, puis on ajoute les DM d'autres types + //On a d\xE9termin\xE9 les DM du type principal(possiblement apr\xE8s save des dmgExtra, maintenant on applique les r\xE9sistances, puis on ajoute les DM d'autres types function dealDamageAfterDmgExtra(target, mainDmgType, dmgTotal, dmgDisplay, showTotal, dmgParType, dmgExtra, crit, options, evt, expliquer, displayRes) { - if (options.pointsVitaux && dmgTotal > 0) { //dégâts retardés pour une pression mortelle + if (options.pointsVitaux && dmgTotal > 0) { //d\xE9g\xE2ts retard\xE9s pour une pression mortelle let pMortelle = tokenAttribute(target, 'pressionMortelle'); let dmgPMort = dmgTotal; let numberPMort = 1; @@ -20755,9 +21008,9 @@ var COFantasy = COFantasy || function() { if (v > 1) rdElems = 2 * v; } } - if (dmgTotal > 0 && immuniseAuType(target, mainDmgType, options.attaquant)) { + if (dmgTotal > 0 && immuniseAuType(target, mainDmgType, options.attaquant, options)) { if (expliquer && !target['msgImmunite_' + mainDmgType]) { - expliquer(nomPerso(target) + " ne semble pas affecté par " + stringOfType(mainDmgType)); + expliquer(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(mainDmgType)); target['msgImmunite_' + mainDmgType] = true; } dmgTotal = 0; @@ -20866,13 +21119,13 @@ var COFantasy = COFantasy || function() { else dmSuivis[tv] = 0; }); }); - // Autres sources de dégâts + // Autres sources de d\xE9g\xE2ts // On compte d'abord les autres sources, pour la synchronisation let count = 0; for (let dt in dmgParType) { - if (immuniseAuType(target, dt, options.attaquant)) { + if (immuniseAuType(target, dt, options.attaquant, options)) { if (expliquer && !target['msgImmunite_' + dt]) { - expliquer(nomPerso(target) + " ne semble pas affecté par " + stringOfType(dt)); + expliquer(nomPerso(target) + " ne semble pas affect\xE9 par " + stringOfType(dt)); target['msgImmunite_' + dt] = true; } delete dmgParType[dt]; @@ -20884,7 +21137,7 @@ var COFantasy = COFantasy || function() { if (dmgType == mainDmgType) { count -= dmgParType[dmgType].length; if (count === 0) dealDamageAfterOthers(target, crit, options, evt, expliquer, displayRes, dmgTotal, dmgDisplay, showTotal, dmSuivis); - return; //type principal déjà géré + return; //type principal d\xE9j\xE0 g\xE9r\xE9 } showTotal = true; let dm = 0; @@ -21004,15 +21257,15 @@ var COFantasy = COFantasy || function() { } } - //Appelé quand on met à 0 PV + //Appel\xE9 quand on met \xE0 0 PV function mort(personnage, expliquer, evt) { - if (getState(personnage, 'mort')) return; //déjà mort + if (getState(personnage, 'mort')) return; //d\xE9j\xE0 mort if (predicateAsBool(personnage, 'energieDeLaMort')) { let duree = rollDePlus(6, { bonus: 5 }); - sendChat('', '/w GM ' + nomPerso(personnage) + ' réapparaîtra dans ' + duree.roll + ' tours.'); - let effet = 'messageRetarde(réapparition)'; + sendChat('', '/w GM ' + nomPerso(personnage) + ' r\xE9appara\xEEtra dans ' + duree.roll + ' tours.'); + let effet = 'messageRetarde(r\xE9apparition)'; setAttrDuree(personnage, effet, duree.val - 1, evt); setToken(personnage.token, 'layer', 'gmlayer', evt); if (personnage.attaquant) { @@ -21028,9 +21281,9 @@ var COFantasy = COFantasy || function() { let explications = []; dealDamage(personnage.attaquant, dmg, [], evt, false, {}, explications, function(dmgDisplay, dmgFinal, dmgDrain) { - setTokenAttr(personnage, effet + 'Valeur', nomPerso(personnage) + " réapparait avec " + dmgFinal + " PV en plus.", evt); + setTokenAttr(personnage, effet + 'Valeur', nomPerso(personnage) + " r\xE9apparait avec " + dmgFinal + " PV en plus.", evt); let attName = nomPerso(personnage); - let msg = "se transforme en brume noire qui traverse " + attName + " de part en part avant de disparaître dans une paroi en poussant un hululement inhumain. le froid de la mort inflige " + dmgDisplay + " DM à " + attName; + let msg = "se transforme en brume noire qui traverse " + attName + " de part en part avant de dispara\xEEtre dans une paroi en poussant un hululement inhumain. le froid de la mort inflige " + dmgDisplay + " DM \xE0 " + attName; if (expliquer) { expliquer(nomPerso(personnage) + ' ' + msg); } else { @@ -21085,11 +21338,11 @@ var COFantasy = COFantasy || function() { switch (charRace) { case 'insecte': case 'ankheg': - case 'araignée': + case 'araign\xE9e': case 'araignee': - case 'guêpe': + case 'gu\xEApe': case 'libellule': - case 'scarabée': + case 'scarab\xE9e': case 'scorpion': case 'strige': return true; @@ -21098,8 +21351,8 @@ var COFantasy = COFantasy || function() { } } - // retourne les nombre de PR restant, undefined si les PR ne sont pas définis - // current, max, et si défini, attribut + // retourne les nombre de PR restant, undefined si les PR ne sont pas d\xE9finis + // current, max, et si d\xE9fini, attribut function pointsDeRecuperation(perso) { if (!ficheAttributeAsBool(perso, 'option_pr', true)) return; let attrPR = charAttribute(perso.charId, 'pr', { @@ -21133,7 +21386,7 @@ var COFantasy = COFantasy || function() { }; } - // pr doit être défini, et pr.current > 0 + // pr doit \xEAtre d\xE9fini, et pr.current > 0 function enleverPointDeRecuperation(perso, pr, evt) { evt.attributes = evt.attributes || []; let attrPR; @@ -21181,18 +21434,18 @@ var COFantasy = COFantasy || function() { let pr = pointsDeRecuperation(target); if (!pr) return; if (pr.current > 0) { - expliquer("Les dégâts sont si importants que " + nomPerso(target) + " perd 1 PR"); + expliquer("Les d\xE9g\xE2ts sont si importants que " + nomPerso(target) + " perd 1 PR"); enleverPointDeRecuperation(target, pr, evt); } else if (getState(target, 'blesse')) { if (getState(target, 'mort')) { - expliquer("Avec la blessure grave, c'est vraiment la fin, " + nomPerso(target) + " ne se relèvera plus..."); + expliquer("Avec la blessure grave, c'est vraiment la fin, " + nomPerso(target) + " ne se rel\xE8vera plus..."); } else { - expliquer("Les dégâts sont trop importants, et " + nomPerso(target) + " s'effondre"); + expliquer("Les d\xE9g\xE2ts sont trop importants, et " + nomPerso(target) + " s'effondre"); mort(target, expliquer, evt); } } else { setState(target, 'blesse', true, evt); - expliquer("Les dégâts occasionnent une blessure grave !"); + expliquer("Les d\xE9g\xE2ts occasionnent une blessure grave !"); } } } @@ -21227,7 +21480,7 @@ var COFantasy = COFantasy || function() { attrs[0].set('current', newCur); } - function finDEffetDeNom(perso, effet, evt, options) { //Supprime l'effet si présent + function finDEffetDeNom(perso, effet, evt, options) { //Supprime l'effet si pr\xE9sent let attrs = tokenAttribute(perso, effet); if (attrs.length === 0) return; attrs = attrs[0]; @@ -21249,9 +21502,9 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(args[2]); if (evt === undefined) { - error("Impossible de trouver l'événement qui a causé la mort", args); + error("Impossible de trouver l'\xE9v\xE9nement qui a caus\xE9 la mort", args); evt = { - type: "Mettre à 0 PV" + type: "Mettre \xE0 0 PV" }; addEvent(evt); } @@ -21271,13 +21524,13 @@ var COFantasy = COFantasy || function() { } updateCurrentBar(target, 1, 0, evt); if (predicateAsBool(target, 'baroudHonneur')) { - let msgBarroud = nomPerso(target) + " devrait être mort"; + let msgBarroud = nomPerso(target) + " devrait \xEAtre mort"; msgBarroud += eForFemale(target) + ", mais "; - msgBarroud += onGenre(target, 'il', 'elle') + " continue à se battre !"; + msgBarroud += onGenre(target, 'il', 'elle') + " continue \xE0 se battre !"; expliquer(msgBarroud); setTokenAttr(target, 'baroudHonneurActif', true, evt); } else if (predicateAsBool(target, 'increvable') && attributeAsInt(target, 'limiteParCombat__increvable', predicateAsInt(target, 'increvable', 1)) > 0) { - let msgIncrevable = nomPerso(target) + " devrait être mort"; + let msgIncrevable = nomPerso(target) + " devrait \xEAtre mort"; msgIncrevable += eForFemale(target) + ", mais "; msgIncrevable += onGenre(target, 'il', 'elle') + " est increvable !"; expliquer(msgIncrevable); @@ -21286,25 +21539,25 @@ var COFantasy = COFantasy || function() { setTokenAttr(target, 'increvableActif', true, evt); } else if ((attributeAsBool(target, 'enrage') || predicateAsBool(target, 'durACuire')) && !attributeAsBool(target, 'aAgiAZeroPV')) { - let msgAgitZ = nomPerso(target) + " devrait être mort"; + let msgAgitZ = nomPerso(target) + " devrait \xEAtre mort"; msgAgitZ += eForFemale(target) + ", mais "; - msgAgitZ += onGenre(target, 'il', 'elle') + " continue à se battre !"; + msgAgitZ += onGenre(target, 'il', 'elle') + " continue \xE0 se battre !"; expliquer(msgAgitZ); if (!attributeAsBool(target, 'agitAZeroPV')) setAttrDuree(target, 'agitAZeroPV', 1, evt); } else if (predicateAsBool(target, 'nAbandonneJamais')) { if (attributeAsBool(target, 'mortMaisNAbandonnePas')) { - expliquer(nomPerso(target) + " est dans un état lamentable, mais continue à bouger. Il faudrait une action limitée pour le réduire en miettes."); + expliquer(nomPerso(target) + " est dans un \xE9tat lamentable, mais continue \xE0 bouger. Il faudrait une action limit\xE9e pour le r\xE9duire en miettes."); } else { - expliquer(nomPerso(target) + " est pratiquement détruit, mais continue à bouger !"); + expliquer(nomPerso(target) + " est pratiquement d\xE9truit, mais continue \xE0 bouger !"); setTokenAttr(target, 'mortMaisNAbandonnePas', true, evt); setState(target, 'ralenti', true, evt); } } else if (predicateAsBool(target, 'exsangue') && !attributeAsBool(target, 'etatExsangue')) { let msg; if (expliquer) { - expliquer(nomPerso(target) + " continue à agir malgré son état"); - } else msg = "continue à agir malgré son état"; + expliquer(nomPerso(target) + " continue \xE0 agir malgr\xE9 son \xE9tat"); + } else msg = "continue \xE0 agir malgr\xE9 son \xE9tat"; setTokenAttr(target, 'etatExsangue', true, evt, { msg }); @@ -21323,7 +21576,7 @@ var COFantasy = COFantasy || function() { let defierLaMort = charAttributeAsInt(target, 'defierLaMort', 10); let rollId = 'defierLaMort_' + target.token.id; let saveOpts = { - msgPour: " pour défier la mort", + msgPour: " pour d\xE9fier la mort", msgReussite: ", conserve 1 PV", rolls: options.rolls, chanceRollId: options.chanceRollId @@ -21345,7 +21598,7 @@ var COFantasy = COFantasy || function() { } postBarUpdateForDealDamage(target, dmgTotal, pvPerdus, bar1, tempDmg, dmgDisplay, showTotal, dmDrains, displayRes, evt, expliquer); }); - //On arrête là, car tout le reste est fait dans la continuation du save. + //On arr\xEAte l\xE0, car tout le reste est fait dans la continuation du save. return; } mettreAZeroPV(target, pvMax, evt, expliquer); @@ -21393,7 +21646,7 @@ var COFantasy = COFantasy || function() { if (rd > 0 && !options.aoe && options.attaquant && predicateAsBool(options.attaquant, 'ventreMou')) { let taille = taillePersonnage(target, 4); if (taille > 4) { - if (target.messages) target.messages.push("Ventre mou => L'attaque ignore la RD dûe à la taille"); + if (target.messages) target.messages.push("Ventre mou => L'attaque ignore la RD d\xFBe \xE0 la taille"); rd -= 3 * (taille - 4); if (taille > 6) rd--; if (rd < 0) rd = 0; @@ -21414,7 +21667,7 @@ var COFantasy = COFantasy || function() { else if (attributeAsBool(target, 'petrifie')) rd += 20; if (attributeAsBool(target, 'mutationSilhouetteMassive')) rd += 3; if (crit) { - let rdCrit = predicateAsInt(target, 'RD_critique', 0); //pour la compatibilité + let rdCrit = predicateAsInt(target, 'RD_critique', 0); //pour la compatibilit\xE9 if (ficheAttributeAsBool(target, 'casque_on', false)) rdCrit += ficheAttributeAsInt(target, 'casque_rd', 0); rd += rdCrit; @@ -21447,7 +21700,7 @@ var COFantasy = COFantasy || function() { } if (target.extraRDBouclier) { rd += target.extraRDBouclier; - expliquer(nomPerso(target) + " dévie le coup avec son bouclier"); + expliquer(nomPerso(target) + " d\xE9vie le coup avec son bouclier"); } if (target.ignoreTouteRD) rd = 0; else if (target.ignoreMoitieRD) rd = parseInt(rd / 2); @@ -21468,17 +21721,17 @@ var COFantasy = COFantasy || function() { if (dmgTotal <= rd) expliquer("La rune de protection absorbe tous les dommages"); else expliquer("La rune de protection encaisse " + target.utiliseRuneProtectionMax + " dommages"); } - //RD PeauDePierre à prendre en compte en dernier + //RD PeauDePierre \xE0 prendre en compte en dernier if (!target.defautCuirasse && !target.ignoreTouteRD && rd < dmgTotal && attributeAsBool(target, 'peauDePierreMag')) { let peauDePierreMagValeur = tokenAttribute(target, 'peauDePierreMagValeur'); if (peauDePierreMagValeur.length === 0) { - error("compteur de Peau de Pierre non trouvé", target); + error("compteur de Peau de Pierre non trouv\xE9", target); } else { peauDePierreMagValeur = peauDePierreMagValeur[0]; let rdPeauDePierreMax = parseInt(peauDePierreMagValeur.get('current')); let peauDePierreAbsorbe = parseInt(peauDePierreMagValeur.get('max')); if (isNaN(rdPeauDePierreMax) || isNaN(peauDePierreAbsorbe) || rdPeauDePierreMax < 1 || peauDePierreAbsorbe < 1) { - error("compteur de Peau de Pierre mal formé", peauDePierreMagValeur); + error("compteur de Peau de Pierre mal form\xE9", peauDePierreMagValeur); finDEffetDeNom(target, "peauDePierreMag", evt); } else { let rdPeauDePierreMag = rdPeauDePierreMax; @@ -21531,7 +21784,7 @@ var COFantasy = COFantasy || function() { }); } if (predicateAsBool(target, 'commandant')) { - //On cherche si il y a au moins 4 créatures sous ses ordres à moins de 10 m + //On cherche si il y a au moins 4 cr\xE9atures sous ses ordres \xE0 moins de 10 m let pageId = target.token.get('pageid'); let tokens = findObjs({ @@ -21588,7 +21841,7 @@ var COFantasy = COFantasy || function() { options.memePasMal += dmgTotal; dmgTotal = 0; } - expliquer("Même pas mal : ignore " + options.memePasMal + " PVs et peut enrager"); + expliquer("M\xEAme pas mal : ignore " + options.memePasMal + " PVs et peut enrager"); let mpm = attributeAsInt(target, 'memePasMalIgnore', 0); setTokenAttr(target, 'memePasMalIgnore', mpm + options.memePasMal, evt); setAttrDuree(target, 'memePasMalBonus', 3, evt); @@ -21606,7 +21859,7 @@ var COFantasy = COFantasy || function() { } let hasMana = (ficheAttributeAsInt(target, 'PM', 0) > 0); let tempDmg = 0; - const estMook = token.get("bar1_link") === ''; + const estMook = token.get('bar1_link') === ''; if (hasMana) { if (estMook) tempDmg = attributeAsInt(target, 'DMTEMP', 0); else tempDmg = ficheAttributeAsInt(target, 'DMTEMP', 0); @@ -21648,7 +21901,7 @@ var COFantasy = COFantasy || function() { showTotal = true; dmgTotal = 1; if (dmSuivis.drain && dmSuivis.drain > 0) dmSuivis.drain = 1; - expliquer("La nuée est constituée de très nombreuses cibles, l'attaque ne lui fait qu'1 DM"); + expliquer("La nu\xE9e est constitu\xE9e de tr\xE8s nombreuses cibles, l'attaque ne lui fait qu'1 DM"); } if (options.attaquant && options.arme && dmgTotal > 0 && predicateAsBool(options.attaquant, 'blessureSanglante') && @@ -21674,9 +21927,9 @@ var COFantasy = COFantasy || function() { }; let sujet = onGenre(target, 'il', 'elle'); let saveOpts = { - msgPour: " pour se libérer de la domination", - msgReussite: ", " + sujet + " se libère de la domination", - msgRate: ", " + sujet + " reste sous domination malgré les dégâts", + msgPour: " pour se lib\xE9rer de la domination", + msgReussite: ", " + sujet + " se lib\xE8re de la domination", + msgRate: ", " + sujet + " reste sous domination malgr\xE9 les d\xE9g\xE2ts", rolls: options.rolls, chanceRollId: options.chanceRollId }; @@ -21702,7 +21955,7 @@ var COFantasy = COFantasy || function() { } enlevePVStatueDeBois(target, pvPerdus, evt); } else { - //On enlève les points de vie + //On enl\xE8ve les points de vie let pvTemporaires = attributeAsInt(target, 'PVTemporaires', 0); if (bar1 > 0 && bar1 + pvTemporaires <= dmgTotal && predicateAsBool(target, 'instinctDeSurvieHumain')) { @@ -21717,7 +21970,7 @@ var COFantasy = COFantasy || function() { dmgDisplay += " / 2"; showTotal = true; } - expliquer("L'instinct de survie aide à réduire une attaque fatale"); + expliquer("L'instinct de survie aide \xE0 r\xE9duire une attaque fatale"); } pvPerdus = dmgTotal; if (pvTemporaires > 0) { @@ -21732,18 +21985,18 @@ var COFantasy = COFantasy || function() { } else { bar1 = bar1 - dmgTotal; } - if (crit) { //Vulnérabilité aux critiues + if (crit) { //Vuln\xE9rabilit\xE9 aux critiues let vulnerableCritique = predicateAsInt(target, 'vulnerableCritique', 0); if (vulnerableCritique > 0) { if (randomInteger(100) <= vulnerableCritique) { - expliquer("Le coup critique le fait voler en éclats"); + expliquer("Le coup critique le fait voler en \xE9clats"); if (bar1 > 0) { dmgTotal += bar1; pvPerdus += bar1; bar1 = 0; } } else { - expliquer("Le coup critique fait vibrer l'adversaire, mais il résiste."); + expliquer("Le coup critique fait vibrer l'adversaire, mais il r\xE9siste."); } } } @@ -21751,7 +22004,7 @@ var COFantasy = COFantasy || function() { predicateAsBool(target, 'peutEnrager') && !attributeAsBool(target, 'enrage')) { setTokenAttr(target, 'enrage', true, evt); - expliquer(nomPerso(target) + " devient enragé" + eForFemale(target) + "."); + expliquer(nomPerso(target) + " devient enrag\xE9" + eForFemale(target) + "."); finDEffetDeNom(target, 'apeureTemp', evt); finDEffetDeNom(target, 'peurEtourdi', evt); setState(target, 'apeure', false, evt); @@ -21796,7 +22049,7 @@ var COFantasy = COFantasy || function() { if (bar1 <= 0) { if (predicateAsBool(target, 'sergent') && !attributeAsBool(target, 'attributDeCombat_sergentUtilise')) { - expliquer(nomPerso(target) + " évite l'attaque in-extremis"); + expliquer(nomPerso(target) + " \xE9vite l'attaque in-extremis"); setTokenAttr(target, 'attributDeCombat_sergentUtilise', true, evt); pvPerdus = 0; } else if (target.attackRoll && @@ -21819,8 +22072,8 @@ var COFantasy = COFantasy || function() { } else { weaponStatsIncrevable = enMain; } - } else { //attaque à distance - weaponStatsIncrevable.name = "Attaque à distance"; + } else { //attaque \xE0 distance + weaponStatsIncrevable.name = "Attaque \xE0 distance"; weaponStatsIncrevable.attSkill = '@{ATKTIR}'; } let optionsIncrevable = {...options @@ -21839,7 +22092,7 @@ var COFantasy = COFantasy || function() { } } else if (getState(target, 'immobilise')) { dice = 12; - expliquer(nomPerso(target) + " immobilisé => D12 au lieu de D20 en Attaque"); + expliquer(nomPerso(target) + " immobilis\xE9 => D12 au lieu de D20 en Attaque"); } else if (attributeAsBool(target, 'mortMaisNAbandonnePas')) { dice = 12; expliquer(nomPerso(target) + " mort mais n'abandonne pas => D12 au lieu de D20 en Attaque"); @@ -21877,12 +22130,12 @@ var COFantasy = COFantasy || function() { let msgIncrevable = "Increvable : " + nomPerso(target) + " fait " + attRollValue; //TODO: afficher les explications de calcul des bonus d'attaque ? if (attackRollAttaquant < target.attackRoll) { - expliquer(msgIncrevable + " < " + target.attackRoll + " => échec "); + expliquer(msgIncrevable + " < " + target.attackRoll + " => \xE9chec "); prendreUnCoupMortel(target, dmgTotal, pvPerdus, bar1, pvmax, tempDmg, dmgDisplay, showTotal, dmSuivis.drain, displayRes, options, evt, expliquer); return; } - //L'attaque est évitée - expliquer(msgIncrevable + " > " + target.attackRoll + " => l'attaque est évitée ! "); + //L'attaque est \xE9vit\xE9e + expliquer(msgIncrevable + " > " + target.attackRoll + " => l'attaque est \xE9vit\xE9e ! "); postBarUpdateForDealDamage(target, dmgTotal, 0, bar1, tempDmg, dmgDisplay, showTotal, dmSuivis.drain, displayRes, evt, expliquer); }); @@ -21904,7 +22157,8 @@ var COFantasy = COFantasy || function() { } function postBarUpdateForDealDamage(target, dmgTotal, pvPerdus, bar1, tempDmg, dmgDisplay, showTotal, dmDrains, displayRes, evt, expliquer) { - if (bar1 > 0 && tempDmg >= bar1) { //assommé + target.pvPerdus = target.pvPerdus || pvPerdus; + if (bar1 > 0 && tempDmg >= bar1) { //assomm\xE9 setState(target, 'assomme', true, evt); } let attrsLienDeSang = tokenAttribute(target, "lienDeSangVers"); @@ -21918,7 +22172,7 @@ var COFantasy = COFantasy || function() { }; let personnageLie = persoOfId(attrsLienDeSang[0].get("current")); if (personnageLie) { - expliquer("Le lien de sang inflige " + lienDuSangDmg + " dégâts à " + personnageLie.token.get("name")); + expliquer("Le lien de sang inflige " + lienDuSangDmg + " d\xE9g\xE2ts \xE0 " + personnageLie.token.get("name")); dealDamage(personnageLie, r, [], evt, false); } } @@ -22118,8 +22372,8 @@ var COFantasy = COFantasy || function() { return toEvaluate.replace(/@{/g, "@{" + name + "|"); } - // Retourne le diamètre d'un disque inscrit dans un carré de surface - // équivalente à celle du token + // Retourne le diam\xE8tre d'un disque inscrit dans un carr\xE9 de surface + // \xE9quivalente \xE0 celle du token function tokenSizeAsCircle(token) { const surface = token.get('width') * token.get('height'); return Math.sqrt(surface); @@ -22150,6 +22404,8 @@ var COFantasy = COFantasy || function() { let mObstacle = 0; let dp = distancePixToken(tok1, tok2); let liste_obstacles = []; + let pt1 = pointOfToken(tok1); + let pt2 = pointOfToken(tok2); allToks.forEach(function(obj) { if (obj.id == tok1.id || obj.id == tok2.id) return; let objCharId = obj.get('represents'); @@ -22177,14 +22433,12 @@ var COFantasy = COFantasy || function() { if (obj_dist > dp) return; obj_dist = distancePixToken(tok2, obj); if (obj_dist > dp) return; - let pt1 = pointOfToken(tok1); - let pt2 = pointOfToken(tok2); let distToTrajectory = distancePixTokenSegment(obj, pt1, pt2); - // On modélise le token comme un disque + // On mod\xE9lise le token comme un disque let rayonObj = tokenSizeAsCircle(obj) / 2; if (distToTrajectory > rayonObj) return; liste_obstacles.push(obj.get("name")); - // On calcule un malus proportionnel à l'arc à traverser + // On calcule un malus proportionnel \xE0 l'arc \xE0 traverser // Pour l'instant, malus = 1 si distance = PIX_PER_UNIT let longueurArc = 2 * Math.sqrt(rayonObj * rayonObj - distToTrajectory * distToTrajectory); let mToken = longueurArc / PIX_PER_UNIT; @@ -22199,7 +22453,7 @@ var COFantasy = COFantasy || function() { else mObstacle = Math.round(mObstacle); let res = mPortee + mObstacle; if (mObstacle > 0) { - log("Obstacle" + ((liste_obstacles.length > 1) ? "s" : "") + " trouvé : " + liste_obstacles.join(', ')); + log("Obstacle" + ((liste_obstacles.length > 1) ? "s" : "") + " trouv\xE9 : " + liste_obstacles.join(', ')); let msgObstacles = 'Obstacle' + ((liste_obstacles.length > 1) ? 's' : '') + ' sur le trajet => -' + mObstacle + ' en Attaque
    '; if (liste_obstacles.length > 0) msgObstacles += '' + liste_obstacles.join(', ') + ''; @@ -22229,12 +22483,12 @@ var COFantasy = COFantasy || function() { }); } - // Fait foo sur tous les tokens représentant charId, ayant l'effet donné, et correspondant au nom d'attribut. Pour le cas où le token doit être lié au personnage, on ne prend qu'un seul token, sauf si les options indiquent autrement (soit option.tousLesTokens, soit une fonction options.filterAffected) + // Fait foo sur tous les tokens repr\xE9sentant charId, ayant l'effet donn\xE9, et correspondant au nom d'attribut. Pour le cas o\xF9 le token doit \xEAtre li\xE9 au personnage, on ne prend qu'un seul token, sauf si les options indiquent autrement (soit option.tousLesTokens, soit une fonction options.filterAffected) // Ne fonctionne correctement que pour les attributs sans _ function iterTokensOfAttribute(charId, pageId, attrName, attrNameComplet, foo, options) { options = options || {}; - let total = 1; //Nombre de tokens affectés, pour gérer l'asynchronie si besoin - if (attrNameComplet == attrName) { //token lié au character + let total = 1; //Nombre de tokens affect\xE9s, pour g\xE9rer l'asynchronie si besoin + if (attrNameComplet == attrName) { //token li\xE9 au character let tokens; if (pageId) { tokens = @@ -22279,7 +22533,7 @@ var COFantasy = COFantasy || function() { if (options.filterAffected(tok)) foo(tok, total); }); } else foo(tokens[0], 1); - } else { //token non lié au character + } else { //token non li\xE9 au character let tokenName = attrNameComplet.substring(attrNameComplet.indexOf('_') + 1); let tNames; if (pageId) { @@ -22326,7 +22580,7 @@ var COFantasy = COFantasy || function() { let character = getObj('character', charId); let charName = "d'id " + charId; if (character) charName = character.get('name'); - error("Attention, il y a plusieurs tokens nommés " + tokenName, total); + error("Attention, il y a plusieurs tokens nomm\xE9s " + tokenName, total); log(" tokens instances du personnage " + charName, total); } } @@ -22357,7 +22611,7 @@ var COFantasy = COFantasy || function() { token.set('showplayers_aura2', true); } else { let status = ''; - // Cas des tokens personnalisés + // Cas des tokens personnalis\xE9s if (statusForInitEnemy && statusForInitAlly) { // ennemi => rouge status = statusForInitEnemy; @@ -22370,7 +22624,7 @@ var COFantasy = COFantasy || function() { } } - //Ne rajoute pas evt à l'historique + //Ne rajoute pas evt \xE0 l'historique function setActiveToken(combat, tokenId, evt) { let pageId; if (combat) pageId = combat.pageId; @@ -22415,10 +22669,10 @@ var COFantasy = COFantasy || function() { if (tokenId) { let perso = persoOfId(tokenId, tokenId); if (perso) { - //On remet à 0 la liste des cibles attaquées par le personnage + //On remet \xE0 0 la liste des cibles attaqu\xE9es par le personnage removeDernieresCiblesAttaquees(perso, evt); let token = perso.token; - // personnage lié au Token + // personnage li\xE9 au Token affectToken(token, 'statusmarkers', token.get('statusmarkers'), evt); affectToken(token, 'aura2_radius', token.get('aura2_radius'), evt); affectToken(token, 'aura2_color', token.get('aura2_color'), evt); @@ -22435,7 +22689,7 @@ var COFantasy = COFantasy || function() { onGenre(perso, 'Il', 'Elle') + " ne fait rien ce tour"); removeTokenFlagAura(token); } else { - //Trouver la créature la plus proche + //Trouver la cr\xE9ature la plus proche let closestToken; pageId = token.get('pageid'); let toksOnPage = findObjs({ @@ -22480,7 +22734,7 @@ var COFantasy = COFantasy || function() { } } } - //On enlève aussi les états qui ne durent qu'un tour + //On enl\xE8ve aussi les \xE9tats qui ne durent qu'un tour let defenseTotale = tokenAttribute(perso, 'defenseTotale'); if (defenseTotale.length > 0) { defenseTotale = defenseTotale[0]; @@ -22508,7 +22762,7 @@ var COFantasy = COFantasy || function() { const charId = a.get('characterid'); let m = parseInt(a.get('max')); if (isNaN(m) || m < 0) { - error("Erreur dans les quantités d'arme de jet", a); + error("Erreur dans les quantit\xE9s d'arme de jet", a); a.remove(); return; } @@ -22521,7 +22775,7 @@ var COFantasy = COFantasy || function() { }); if (!msgAffiche.has(charId)) { msgAffiche.add(charId); - whisperChar(charId, "récupère ses armes de jet"); + whisperChar(charId, "r\xE9cup\xE8re ses armes de jet"); } a.set('current', m); } @@ -22538,7 +22792,7 @@ var COFantasy = COFantasy || function() { const charId = a.get('characterid'); let m = parseInt(a.get('max')); if (isNaN(m) || m < 0) { - error("Erreur dans les quantités de munitions", a); + error("Erreur dans les quantit\xE9s de munitions", a); a.remove(); return; } @@ -22551,23 +22805,96 @@ var COFantasy = COFantasy || function() { }); if (!msgAffiche.has(charId)) { msgAffiche.add(charId); - whisperChar(charId, "récupère ses munitions"); + whisperChar(charId, "r\xE9cup\xE8re ses munitions"); } a.set('current', m); } }); } + function dmExplosion(id, effet) { + let action = "!cof-dmg " + effet.dm + " --disque " + id + " " + effet.portee; + if (effet.typeBombe == 'piege') action += " --psave DEX 15"; + log(action); + sendChat('', action); + } + + function getTokenTemp(tt) { + let token = getObj('graphic', tt.tid); + if (!token) { + if (!tt.name) return; + token = findObjs({ + _type: 'graphic', + name: tt.name + }); + if (token.length === 0) return; + token = token[0]; + } + return token; + } + + //Peut faire des effets asynchrones + function deleteTokenTemp(tt, evt) { + let token = getTokenTemp(tt); + if (!token) return; + if (!tt.pasDExplosion) { + let gmNotes = token.get('gmnotes'); + try { + if (gmNotes.startsWith('{')) { + let effet = JSON.parse(gmNotes); + //{typeBombe, portee, message, dm, tempsDePose, duree, intrusion} + if (effet && effet.typeBombe) { + let pageId = token.get('pageid'); + if (effet.message) sendChat('', effet.message); + let left = token.get('left'); + let top = token.get('top'); + spawnFx(left, top, 'explode-fire', pageId); + playSound('Explosion'); + if (effet.dm) { + let charCible = trouveOuCreeCible(); + if (charCible) { + charCible.get('_defaulttoken', function(normalToken) { + if (normalToken === '') { + dmExplosion(tt.id, effet); + return; + } + normalToken = JSON.parse(normalToken); + normalToken._pageid = pageId; + normalToken.left = left; + normalToken.top = top; + normalToken.imgsrc = normalizeTokenImg(normalToken.imgsrc); + let tokenCible = createObj('graphic', normalToken); + if (tokenCible) dmExplosion(tokenCible.id, effet); + else { + log("Impossible de cr\xE9er le token cible"); + log(normalToken); + dmExplosion(tt.id, effet); + } + }); + } else dmExplosion(tt.id, effet); + } + } + } + } catch (parseError) {} + } + let ett = {...tt + }; + ett.deletedToken = getTokenFields(token); + evt.deletedTokensTemps = evt.deletedTokensTemps || []; + evt.deletedTokensTemps.push(ett); + token.remove(); + } + function sortirDuCombat() { stateCOF.prescience = undefined; stateCOF.nextPrescience = undefined; let combat = stateCOF.combat; if (!combat) { log("Pas en combat"); - sendChat("GM", "/w GM Le combat est déjà terminé"); + sendChat('GM', "/w GM Le combat est d\xE9j\xE0 termin\xE9"); return; } - sendChat("GM", "Le combat est terminé"); + sendChat('GM', "Le combat est termin\xE9"); let evt = { type: 'fin_combat', initiativepage: Campaign().get('initiativepage'), @@ -22586,7 +22913,6 @@ var COFantasy = COFantasy || function() { }); // Fin des effets qui durent pour le combat attrs = removeAllAttributes('attributDeCombat', evt, attrs); - attrs = removeAllAttributes('protegerUnAllie', evt, attrs); attrs = removeAllAttributes('protegePar', evt, attrs); attrs = removeAllAttributes('interposer', evt, attrs); attrs = removeAllAttributes('defenseTotale', evt, attrs); @@ -22613,23 +22939,22 @@ var COFantasy = COFantasy || function() { attrs = removeAllAttributes('increvableHumainUtilise', evt, attrs); attrs = removeAllAttributes('resistanceRaillerie', evt, attrs); attrs = removeAllAttributes('defierLaMort', evt, attrs); - attrs = removeAllAttributes('traquenardImpossible', evt, attrs); attrs = removeAllAttributes('niveauDesObjetsAnimes', evt, attrs); attrs = removeAllAttributes('meneurDHommesCible', evt, attrs); attrs = removeAllAttributes('energieImpie', evt, attrs); // Autres attributs - // On récupère les munitions récupérables - resetAttr(attrs, 'munition', evt, "récupère ses munitions"); //obsolète depuis mars 2023. + // On r\xE9cup\xE8re les munitions r\xE9cup\xE9rables + resetAttr(attrs, 'munition', evt, "r\xE9cup\xE8re ses munitions"); //obsol\xE8te depuis mars 2023. recupererMunitions(attrs, evt); recupererArmesDeJet(attrs, evt); - //Utilisation automatique de second souffle, si pas utilisé + //Utilisation automatique de second souffle, si pas utilis\xE9 let tokens = findObjs({ // Les tokens sur la page du combat _type: 'graphic', _subtype: 'token', _pageid: combat.pageId, }); - let persosDuCombat = []; //peuplé la première fois qu'on regarde les tokens - let persoParCharId = {}; //Pour ne garder qu'un jeu de prédicat par charId + let persosDuCombat = []; //peupl\xE9 la premi\xE8re fois qu'on regarde les tokens + let persoParCharId = {}; //Pour ne garder qu'un jeu de pr\xE9dicat par charId tokens.forEach(function(token) { let charId = token.get('represents'); if (charId === '' || charId === undefined) return; @@ -22656,11 +22981,11 @@ var COFantasy = COFantasy || function() { let jetSoins = rollDePlus(10, { bonus: bonus }); - let msg = ' reprend son souffle et récupère '; + let msg = ' reprend son souffle et r\xE9cup\xE8re '; let soins = jetSoins.val; if (pv + soins > pvDebut) { soins = pvDebut - pv; - msg += soins + " PV (le jet était " + jetSoins.roll + ")"; + msg += soins + " PV (le jet \xE9tait " + jetSoins.roll + ")"; } else { msg += jetSoins.roll + " PVs"; } @@ -22671,11 +22996,11 @@ var COFantasy = COFantasy || function() { }); attrs = removeAllAttributes('secondSouffleUtilise', evt, attrs); attrs = removeAllAttributes('PVsDebutCombat', evt, attrs); - // On diminue l'ébriété des personnages sous vapeurs éthyliques + // On diminue l'\xE9bri\xE9t\xE9 des personnages sous vapeurs \xE9thyliques allAttributesNamed(attrs, 'vapeursEthyliques').forEach(function(attr) { let veCharId = attr.get('characterid'); if (veCharId === undefined || veCharId === '') { - error("Attribut sans personnage associé", attr); + error("Attribut sans personnage associ\xE9", attr); return; } iterTokensOfAttribute(veCharId, combat.pageId, @@ -22686,7 +23011,7 @@ var COFantasy = COFantasy || function() { token: tok }; removeTokenAttr(perso, 'niveauEbriete', evt, { - msg: "désaoûle" + msg: "d\xE9sao\xFBle" }); }); }); @@ -22698,7 +23023,7 @@ var COFantasy = COFantasy || function() { degainerArme(perso, '', evt); } }); - // On remet en main l'arme par défaut si elle est précisée + // On remet en main l'arme par d\xE9faut si elle est pr\xE9cis\xE9e persosDuCombat.forEach(function(perso) { if (!isActive(perso)) return; let persoTest = persoParCharId[perso.charId]; @@ -22716,8 +23041,9 @@ var COFantasy = COFantasy || function() { let attaques = listAllAttacks(perso); for (let label in attaques) { let att = attaques[label]; - if (att.armespec) { - let predicats = predicateOfRaw(att.armespec); + let rawArme = fieldAsString(att, 'armepredicats', ''); + if (rawArme) { + let predicats = predicateOfRaw(rawArme); if (predicats.charge) { let chargeMax = predicats.charge; if (chargeMax === true) chargeMax = 1; @@ -22736,7 +23062,7 @@ var COFantasy = COFantasy || function() { ilds.forEach(function(ild) { let douleur = parseInt(ild.get('current')); if (isNaN(douleur)) { - error("La douleur ignorée n'est pas un nombre", douleur); + error("La douleur ignor\xE9e n'est pas un nombre", douleur); return; } let charId = ild.get('characterid'); @@ -22760,7 +23086,7 @@ var COFantasy = COFantasy || function() { pvAttr = pvAttr[0]; let pv = parseInt(pvAttr.get('current')); if (isNaN(pv)) { - error("PV mal formés ", pvAttr); + error("PV mal form\xE9s ", pvAttr); return; } evt.attributes.push({ @@ -22771,13 +23097,13 @@ var COFantasy = COFantasy || function() { if (newPv < 0) newPv = 0; pvAttr.set('current', newPv); if (pv > 0 && newPv === 0) { - sendChar(charId, "s'écroule. Il semble sans vie. La douleur qu'il avait ignorée l'a finalement rattrapé...", true); + sendChar(charId, "s'\xE9croule. Il semble sans vie. La douleur qu'il avait ignor\xE9e l'a finalement rattrap\xE9...", true); } else { let tempDmg = ficheAttributeAsInt(charId, 'DMTEMP', 0); if (pv > tempDmg && newPv <= tempDmg) { - sendChar(charId, "s'écroule, assommé. La douleur qu'il avait ignorée l'a finalement rattrapé...", true); + sendChar(charId, "s'\xE9croule, assomm\xE9. La douleur qu'il avait ignor\xE9e l'a finalement rattrap\xE9...", true); } else { - sendChar(charId, "subit le contrecoup de la douleur qu'il avait ignorée", true); + sendChar(charId, "subit le contrecoup de la douleur qu'il avait ignor\xE9e", true); } } } else { // ignorer la douleur d'un token @@ -22789,11 +23115,11 @@ var COFantasy = COFantasy || function() { name: tokName }); if (tokensIld.length === 0) { - error("Pas de token nommé " + tokName + " qui aurait ignoré la douleur", ild); + error("Pas de token nomm\xE9 " + tokName + " qui aurait ignor\xE9 la douleur", ild); return; } if (tokensIld.length > 1) { - sendChar(charId, "a plusieurs tokens nommés " + tokName + ". Un seul d'entre eux subira l'effet d'ignorer la douleur", true); + sendChar(charId, "a plusieurs tokens nomm\xE9s " + tokName + ". Un seul d'entre eux subira l'effet d'ignorer la douleur", true); } let tokPv = parseInt(tokensIld[0].get('bar1_value')); let tokNewPv = tokPv - douleur; @@ -22820,7 +23146,7 @@ var COFantasy = COFantasy || function() { } //Attributs qu'on veut enlever en dernier let removedLaterAttrs = []; - // fin des effets temporaires (durée en tours, ou durée = combat) + // fin des effets temporaires (dur\xE9e en tours, ou dur\xE9e = combat) attrs.forEach(function(obj) { let attrName = obj.get('name'); let charId = obj.get('characterid'); @@ -22874,7 +23200,7 @@ var COFantasy = COFantasy || function() { }, { tousLesTokens: true }); - //Pas besoin de détruire l'attribut, ce sera fait plus loin + //Pas besoin de d\xE9truire l'attribut, ce sera fait plus loin } evt.deletedAttributes.push(obj); obj.remove(); @@ -22907,14 +23233,8 @@ var COFantasy = COFantasy || function() { if (stateCOF.tokensTemps) { evt.deletedTokensTemps = []; stateCOF.tokensTemps.forEach(function(tt) { - let token = getObj('graphic', tt.tid); - if (token) { - let ett = {...tt - }; - ett.deletedToken = getTokenFields(token); - evt.deletedTokensTemps.push(ett); - token.remove(); - } + if (tt.intrusion) tt.pasDExplosion = true; + deleteTokenTemp(tt, evt); }); delete stateCOF.tokensTemps; } @@ -22937,7 +23257,7 @@ var COFantasy = COFantasy || function() { } //Asynchrone - // ne rajoute pas evt à l'historique + // ne rajoute pas evt \xE0 l'historique function soinsEcuyers(ecuyers, manquePV, playerId, evt) { ecuyers.forEach(function(ec) { const ecuyer = ec.perso; @@ -22947,11 +23267,11 @@ var COFantasy = COFantasy || function() { name: ecuyerDe }); if (charChevalier.length === 0) { - error("Pas de chevalier " + ecuyerDe + " pour l'écuyer " + nomPerso(ecuyer), ec); + error("Pas de chevalier " + ecuyerDe + " pour l'\xE9cuyer " + nomPerso(ecuyer), ec); return; } if (charChevalier.length > 1) { - error("Plusieurs personnages nommés " + ecuyerDe + ". Attention aux ambiguités."); + error("Plusieurs personnages nomm\xE9s " + ecuyerDe + ". Attention aux ambiguit\xE9s."); } charChevalier = charChevalier[0].id; let maxASoigner = modCarac(charChevalier, 'charisme') + 1; @@ -22975,13 +23295,13 @@ var COFantasy = COFantasy || function() { } alliesASoigner.push(cible); } - }); //fin de détermination des cibles + }); //fin de d\xE9termination des cibles if (chevalier === undefined && monture === undefined && - (maxASoigner < 1 || alliesASoigner.length === 0)) { //Personne à soigner + (maxASoigner < 1 || alliesASoigner.length === 0)) { //Personne \xE0 soigner return; } - //TODO: utiliser l'id d'un player qui contrôle le chevalier - let display = startFramedDisplay(playerId, "Services d'écuyer", ecuyer); + //TODO: utiliser l'id d'un player qui contr\xF4le le chevalier + let display = startFramedDisplay(playerId, "Services d'\xE9cuyer", ecuyer); let finSoin = function() { nbCibles--; if (nbCibles === 0) { @@ -22997,17 +23317,17 @@ var COFantasy = COFantasy || function() { if (c.token.id == ecuyer.token.id) { msgSoin = 'se soigne de '; } else { - msgSoin = nomPerso(c) + " récupère "; + msgSoin = nomPerso(c) + " r\xE9cup\xE8re "; } if (s < soins) - msgSoin += s + " PV. (Le résultat du jet était " + soinTxt + ")"; + msgSoin += s + " PV. (Le r\xE9sultat du jet \xE9tait " + soinTxt + ")"; else msgSoin += soinTxt + " PV."; addLineToFramedDisplay(display, msgSoin); }; soigneToken(c, soins, evt, printTrue); finSoin(); }); //fin du sendChat - }; // fin de définition de soigneCible + }; // fin de d\xE9finition de soigneCible let peutToutSoigner = (alliesASoigner.length <= maxASoigner); if (peutToutSoigner) nbCibles += alliesASoigner.length; else if (maxASoigner > 0) nbCibles++; //pour ne pas finir avant d'imprimer les boutons @@ -23027,7 +23347,7 @@ var COFantasy = COFantasy || function() { }); finSoin(); } - }); //fin iteration sur les écuyers + }); //fin iteration sur les \xE9cuyers } function parseOptions(msg) { @@ -23035,7 +23355,7 @@ var COFantasy = COFantasy || function() { if (msg.selected && msg.selected.length > 0) { let firstSelected = getObj('graphic', msg.selected[0]._id); if (firstSelected === undefined) { - error("Un token sélectionné n'est pas trouvé en interne", msg.selected); + error("Un token s\xE9lectionn\xE9 n'est pas trouv\xE9 en interne", msg.selected); return; } pageId = firstSelected.get('pageid'); @@ -23069,7 +23389,7 @@ var COFantasy = COFantasy || function() { break; case 'lanceur': if (cmd.length < 2) { - error("Il faut préciser l'id ou le nom du lanceur", arg); + error("Il faut pr\xE9ciser l'id ou le nom du lanceur", arg); return; } options.lanceur = persoOfId(cmd[1], cmd[1], pageId); @@ -23117,7 +23437,7 @@ var COFantasy = COFantasy || function() { cout = parseInt(cmd[1]); } if (isNaN(cout) || cout < 0) { - error("Coût en mana incorrect", cmd); + error("Co\xFBt en mana incorrect", cmd); return; } options.mana = options.mana || 0; @@ -23132,7 +23452,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { cout = parseInt(cmd[1]); if (isNaN(cout) || cout < 0) { - error("Le coût de la magie rapide n'est pas un entier positif", cmd); + error("Le co\xFBt de la magie rapide n'est pas un entier positif", cmd); cout = 1; } } @@ -23151,47 +23471,39 @@ var COFantasy = COFantasy || function() { } let rang = parseInt(cmd[1]); if (isNaN(rang) || rang < 1) { - error("Le rang doit être un nombre positif"); + error("Le rang doit \xEAtre un nombre positif"); return; } options.rang = rang; break; case 'limiteParJour': if (cmd.length < 2) { - error("Il manque la limite journalière", cmd); + error("Il manque la limite journali\xE8re", cmd); return; } - let limiteParJour = parseInt(cmd[1]); - if (isNaN(limiteParJour) || limiteParJour < 1) { - error("La limite journalière doit être un nombre positif", cmd); - return; - } - options.limiteParJour = limiteParJour; - if (cmd.length > 2) { - cmd.splice(0, 2); - options.limiteParJourRessource = cmd.join('_'); - } + let limiteParJour = parseLimite(cmd, "journali\xE8re"); + if (limiteParJour) options.limiteParJour = limiteParJour; return; case 'depasseLimite': if (cmd.length < 2) { - error("Il manque le coût en mana pour depasser la limite", cmd); + error("Il manque le co\xFBt en mana pour depasser la limite", cmd); return; } let depasse = parseInt(cmd[1]); if (isNaN(depasse) || depasse < 1) { - error("Le coût de dépassement doit être un nombre positif", cmd); + error("Le co\xFBt de d\xE9passement doit \xEAtre un nombre positif", cmd); return; } options.depasseLimite = depasse; return; case 'limiteSoinsParJour': if (cmd.length < 2) { - error("Il manque la limite de soins journalière", cmd); + error("Il manque la limite de soins journali\xE8re", cmd); return; } let limiteSoinsParJour = parseInt(cmd[1]); if (isNaN(limiteSoinsParJour) || limiteSoinsParJour < 1) { - error("La limite de soins journalière doit être un nombre positif", cmd); + error("La limite de soins journali\xE8re doit \xEAtre un nombre positif", cmd); return; } options.limiteSoinsParJour = limiteSoinsParJour; @@ -23202,12 +23514,12 @@ var COFantasy = COFantasy || function() { return; case 'limiteCibleParJour': if (cmd.length < 2) { - error("Il manque la limite journalière", cmd); + error("Il manque la limite journali\xE8re", cmd); return; } let limiteCibleParJour = parseInt(cmd[1]); if (isNaN(limiteCibleParJour) || limiteCibleParJour < 1) { - error("La limite journalière doit être un nombre positif", cmd); + error("La limite journali\xE8re doit \xEAtre un nombre positif", cmd); return; } options.limiteCibleParJour = limiteCibleParJour; @@ -23221,29 +23533,21 @@ var COFantasy = COFantasy || function() { options.limiteParCombat = 1; return; } - let limiteParCombat = parseInt(cmd[1]); - if (isNaN(limiteParCombat) || limiteParCombat < 1) { - error("La limite par combat doit être un nombre positif", cmd); - return; - } - options.limiteParCombat = limiteParCombat; - if (cmd.length > 2) { - cmd.splice(0, 2); - options.limiteParCombatRessource = cmd.join('_'); - } + let limiteParCombat = parseLimite(cmd, "par combat"); + if (limiteParCombat) options.limiteParCombat = limiteParCombat; return; case 'tempsRecharge': if (cmd.length < 3) { - error("Il manque un argument à l'option --tempsRecharge", cmd); + error("Il manque un argument \xE0 l'option --tempsRecharge", cmd); return; } if (!estEffetTemp(cmd[1])) { - error("Le premier argument de l'option --tempsRecharge doit être un effet temporaire répertorié", cmd); + error("Le premier argument de l'option --tempsRecharge doit \xEAtre un effet temporaire r\xE9pertori\xE9", cmd); return; } let tr = parseInt(cmd[2]); if (isNaN(tr)) { - error("Le deuxième argument de l'option --tempsRecharge doit être un nombre", cmd); + error("Le deuxi\xE8me argument de l'option --tempsRecharge doit \xEAtre un nombre", cmd); return; } options.tempsRecharge = { @@ -23268,7 +23572,7 @@ var COFantasy = COFantasy || function() { portee = parseInt(cmd[1]); } if (isNaN(portee) || portee < 0) { - error("Portée incorrecte", cmd); + error("Port\xE9e incorrecte", cmd); return; } options.portee = portee; @@ -23291,21 +23595,21 @@ var COFantasy = COFantasy || function() { return; case 'decrAttribute': if (cmd.length < 2) { - error("Erreur interne d'une commande générée par bouton", opts); + error("Erreur interne d'une commande g\xE9n\xE9r\xE9e par bouton", opts); return; } let attr = getObj('attribute', cmd[1]); if (attr === undefined && options.lanceur) { attr = tokenAttribute(options.lanceur, cmd[1]); if (attr.length === 0) { - log("Attribut à changer perdu"); + log("Attribut \xE0 changer perdu"); log(cmd); return; } attr = attr[0]; } if (attr === undefined) { - log("Attribut à changer perdu"); + log("Attribut \xE0 changer perdu"); log(cmd); return; } @@ -23356,14 +23660,14 @@ var COFantasy = COFantasy || function() { break; case "classeEffet": if (cmd.length < 2) { - sendChat("COF", "Il manque un argument à l'option --classeEffet"); + sendChat("COF", "Il manque un argument \xE0 l'option --classeEffet"); return; } options.classeEffet = cmd[1]; return; case 'message': if (cmd.length < 2) { - error("Il manque le message après --message", cmd); + error("Il manque le message apr\xE8s --message", cmd); return; } options.messages = options.messages || []; @@ -23371,7 +23675,7 @@ var COFantasy = COFantasy || function() { return; case 'messageMJ': if (cmd.length < 2) { - error("Il manque le message après --messageMJ", cmd); + error("Il manque le message apr\xE8s --messageMJ", cmd); return; } options.messagesMJ = options.messagesMJ || []; @@ -23379,14 +23683,14 @@ var COFantasy = COFantasy || function() { return; case 'image': if (cmd.length < 2) { - error("Il manque le nom de l'imageaprès --image", cmd); + error("Il manque le nom de l'imageapr\xE8s --image", cmd); return; } options.image = cmd[1].replace(':', ':'); return; case 'son': if (cmd.length < 2) { - error("Il manque le nom du son après --son", cmd); + error("Il manque le nom du son apr\xE8s --son", cmd); return; } options.son = cmd.slice(1).join(' '); @@ -23412,7 +23716,7 @@ var COFantasy = COFantasy || function() { return; case 'etat': if (cmd.length < 2) { - error("Il manque le nom de l'état et sa valeur après --etat", cmd); + error("Il manque le nom de l'\xE9tat et sa valeur apr\xE8s --etat", cmd); return; } options.etats = options.etats || {}; @@ -23432,7 +23736,7 @@ var COFantasy = COFantasy || function() { case 'dm': let t = cmd[0]; if (options[t]) { - error(t + " déjà défini", opts); + error(t + " d\xE9j\xE0 d\xE9fini", opts); return; } if (cmd.length < 2) { @@ -23455,7 +23759,7 @@ var COFantasy = COFantasy || function() { } else { let base = parseInt(cmd[1]); if (isNaN(base)) { - error("L'argument de --magieEnArmure doit être un nombre ou mana", cmd); + error("L'argument de --magieEnArmure doit \xEAtre un nombre ou mana", cmd); return; } options.magieEnArmure = { @@ -23468,16 +23772,36 @@ var COFantasy = COFantasy || function() { return; case 'tokenSide': if (cmd.length < 2) { - error("Il faut préciser le coté de token à utiliser", cmd); + error("Il faut pr\xE9ciser le cot\xE9 de token \xE0 utiliser", cmd); return; } let side = parseInt(cmd[1]); if (isNaN(side) || side < 0) { - error("Le coté de token doit être un nombre positif", cmd); + error("Le cot\xE9 de token doit \xEAtre un nombre positif", cmd); return; } options.tokenSide = side; return; + case 'terrainDifficile': + { + let terrainDifficile = options.terrainDifficile || { + duree: 1, + imgsrc: IMG_INVISIBLE, + nom: "Terrain difficile" + }; + if (cmd.length > 1) { //le premier argument est la dur\xE9e de l'effet + terrainDifficile.duree = toInt(cmd[1], 1); + if (cmd.length > 2) { //le second argument est le nom du terrain + terrainDifficile.nom = cmd[2].replace(/_/g, ' '); + if (cmd.length > 3) { //le troisi\xE8me argument est l'url de l'image + let imgsrc = cmd[3].replace(':', ':'); + terrainDifficile.imgsrc = normalizeTokenImg(imgsrc); + } + } + } + options.terrainDifficile = terrainDifficile; + return; + } default: return; } @@ -23485,11 +23809,11 @@ var COFantasy = COFantasy || function() { return options; } - //Si il y a des effets à durée indéterminées, les rappeler au MJ, avec un bouton pour facilement y mettre fin si nécessaire + //Si il y a des effets \xE0 dur\xE9e ind\xE9termin\xE9es, les rappeler au MJ, avec un bouton pour facilement y mettre fin si n\xE9cessaire function proposerFinEffetsIndetermines() { - //On commence par les états globaux + //On commence par les \xE9tats globaux if (stateCOF.tenebresMagiques) { - sendPlayer('GM', boutonSimple("!cof-tenebres-magiques fin", "Mettre fin") + "aux ténèbres magiques ?"); + sendPlayer('GM', boutonSimple("!cof-tenebres-magiques fin", "Mettre fin") + "aux t\xE9n\xE8bres magiques ?"); } if (stateCOF.effetAuD20) { for (let ev in stateCOF.effetAuD20) { @@ -23505,7 +23829,7 @@ var COFantasy = COFantasy || function() { estEffetIndetermine(name); }); if (attrs.length === 0) return; - const display = startFramedDisplay(undefined, "Effets à durée indéterminée actifs", undefined, { + const display = startFramedDisplay(undefined, "Effets \xE0 dur\xE9e ind\xE9termin\xE9e actifs", undefined, { chuchote: 'gm' }); let attrsParPerso = {}; @@ -23569,7 +23893,7 @@ var COFantasy = COFantasy || function() { } attrsParPerso[charId].effets.push(ef); return; - } // on a un attribut de token non lié + } // on a un attribut de token non li\xE9 let pn = attrName.indexOf('_'); if (pn < 1) return; ef.nom = attrName.substring(0, pn - 1); @@ -23626,8 +23950,8 @@ var COFantasy = COFantasy || function() { sendFramedDisplay(display); } - // Remise à zéro de toutes les limites journalières - // N'ajoute pas evt à l'historique + // Remise \xE0 z\xE9ro de toutes les limites journali\xE8res + // N'ajoute pas evt \xE0 l'historique function jour(persos, evt, options) { let attrs; attrs = removeAllAttributes('pressionMortelle', evt); @@ -23641,14 +23965,14 @@ var COFantasy = COFantasy || function() { attrs = removeAllAttributes('immunise24HA', evt, attrs); attrs = removeAllAttributes('testsRatesDuTour', evt, attrs); attrs = removeAllAttributes('pointsDeViolence', evt, attrs); - //Les élixirs + //Les \xE9lixirs attrs = removeAllAttributes('elixirsACreer', evt, attrs); attrs = proposerRenouveauElixirs(evt, attrs, options); //Les runes attrs = proposerRenouveauRunes(evt, attrs, options); - //Les plantes médicinales - attrs = removeAllAttributes('dose_Plante médicinale', evt, attrs); - attrs = removeConsommables('Plante médicinale', evt, attrs); + //Les plantes m\xE9dicinales + attrs = removeAllAttributes('dose_Plante m\xE9dicinale', evt, attrs); + attrs = removeConsommables('Plante m\xE9dicinale', evt, attrs); //La perte de substance persos.forEach(function(perso) { if (predicateAsBool(perso, 'perteDeSubstance')) { @@ -23656,8 +23980,8 @@ var COFantasy = COFantasy || function() { let msg = nomPerso(perso) + " a maintenant " + perteDeSubstance; msg += " jour" + ((perteDeSubstance > 1) ? 's' : '') + " de perte de substance.
    "; if (!predicateAsBool(perso, 'ancreInvincible')) { - msg += " Demander un jet de CHA difficulté " + perteDeSubstance; - msg += " ou " + onGenre(perso, 'il', 'elle') + " disparaît pendant "; + msg += " Demander un jet de CHA difficult\xE9 " + perteDeSubstance; + msg += " ou " + onGenre(perso, 'il', 'elle') + " dispara\xEEt pendant "; let nj = rollDePlus(6); msg += nj.roll + " heure" + ((nj.val > 1) ? 's' : '') + '.'; } @@ -23690,13 +24014,13 @@ var COFantasy = COFantasy || function() { let attrName = attr.get('name'); let carac = attr.get('current'); if (!isCarac(carac)) { - error("Save par jour " + attrName + " mal formé", carac); + error("Save par jour " + attrName + " mal form\xE9", carac); finalize(); return; } let seuil = parseInt(attr.get('max')); if (isNaN(seuil)) { - error("Save par jour " + attrName + " mal formé", seuil); + error("Save par jour " + attrName + " mal form\xE9", seuil); finalize(); return; } @@ -23728,7 +24052,7 @@ var COFantasy = COFantasy || function() { name: attrName }); if (attrEffet === undefined || attrEffet.length === 0) { - error("Save sans effet associé " + attrName, attr); + error("Save sans effet associ\xE9 " + attrName, attr); findObjs({ _type: 'attribute', _characterid: charId, @@ -23747,11 +24071,11 @@ var COFantasy = COFantasy || function() { let sujet = onGenre(perso, 'il', 'elle'); let met = messageEffetIndetermine[effetC]; if (met === undefined) met = { - fin: "résiste à l'effet", + fin: "r\xE9siste \xE0 l'effet", actf: "reste sous l'emprise de l'effet" }; let saveOpts = { - msgPour: " pour ne plus être sous l'effet " + effetC, + msgPour: " pour ne plus \xEAtre sous l'effet " + effetC, msgReussite: ", " + sujet + ' ' + messageFin(perso, met), msgRate: ", " + sujet + ' ' + messageActif(perso, met), rolls: options.rolls, @@ -23782,7 +24106,7 @@ var COFantasy = COFantasy || function() { }); //fin boucle attrSave } - //La caractéristique sans affaiblissement + //La caract\xE9ristique sans affaiblissement function caracNormale(perso, carac) { let res = ficheAttributeAsInt(perso, carac, 10); if (!persoEstPNJ(perso)) return res; @@ -23818,7 +24142,7 @@ var COFantasy = COFantasy || function() { attributeAsInt(perso, 'affaiblissementde' + carac, 0); } - //N'ajoute pas evt à l'historique + //N'ajoute pas evt \xE0 l'historique function diminueAffaiblissement(perso, carac, valeur, evt, malus) { if (valeur < 1) return; let nomAttr = 'affaiblissementde' + carac; @@ -23846,7 +24170,7 @@ var COFantasy = COFantasy || function() { } let pvMaxNormaux = attributeAsInt(perso, 'pvMaxNormaux', 0); if (pvMaxNormaux < pvmax) { - error("Les PV max sont inférieurs à la valeur normale", pvMaxNormaux); + error("Les PV max sont inf\xE9rieurs \xE0 la valeur normale", pvMaxNormaux); return; } if (valeur == malus || (valeur == malus - 1 && caracNormale(perso, 'consititution') % 2 == 1)) { @@ -23873,7 +24197,7 @@ var COFantasy = COFantasy || function() { } } } else if (valeur == malus) { - //Au cas où, on vérifie le pv max + //Au cas o\xF9, on v\xE9rifie le pv max let pvMaxNormaux = attributeAsInt(perso, 'pvMaxNormaux', 0); if (pvMaxNormaux > 0) { let pvmax = parseInt(perso.token.get("bar1_max")); @@ -23931,7 +24255,7 @@ var COFantasy = COFantasy || function() { let speaksAs = player.get('speakingas'); if (speaksAs !== '') fromMsg = speaksAs; } - sendChat(fromMsg, "Un nouveau jour se lève"); + sendChat(fromMsg, "Un nouveau jour se l\xE8ve"); if (stateCOF.combat) sortirDuCombat(); jour(persos, evt, options); if (options.repos) { @@ -23948,8 +24272,8 @@ var COFantasy = COFantasy || function() { if (msg.content.includes(' --reposLong')) reposLong = true; getSelected(msg, function(selection, playerId) { if (selection.length === 0) { - sendPlayer(msg, "!cof-recuperer sans sélection de tokens", playerId); - log("!cof-recuperer requiert des tokens sélectionnés"); + sendPlayer(msg, "!cof-recuperer sans s\xE9lection de tokens", playerId); + log("!cof-recuperer requiert des tokens s\xE9lectionn\xE9s"); return; } let persos = []; @@ -23977,8 +24301,8 @@ var COFantasy = COFantasy || function() { let allCaracs = ['force', 'dexterite', 'constitution', 'intelligence', 'sagesse', 'charisme']; - //Asynchrone (jets de dés) - // ne rajoute pas evt à l'historique + //Asynchrone (jets de d\xE9s) + // ne rajoute pas evt \xE0 l'historique function recuperation(persos, reposLong, playerId, evt, options) { options = options || {}; let manquePV = []; @@ -24025,7 +24349,7 @@ var COFantasy = COFantasy || function() { let hasMana = false; let dmTemp = bar2; let estMook = token.get('bar1_link') === ''; - if (manaAttr.length > 0) { // Récupération des points de mana + if (manaAttr.length > 0) { // R\xE9cup\xE9ration des points de mana let manaMax = parseInt(manaAttr[0].get('max')); hasMana = !isNaN(manaMax) && manaMax > 0; if (hasMana) { @@ -24036,7 +24360,7 @@ var COFantasy = COFantasy || function() { } } } - if (!isNaN(dmTemp) && dmTemp > 0) { // récupération de DM temp + if (!isNaN(dmTemp) && dmTemp > 0) { // r\xE9cup\xE9ration de DM temp if (reposLong) dmTemp = 0; else dmTemp = Math.max(0, dmTemp - 10); if (hasMana) { @@ -24052,18 +24376,18 @@ var COFantasy = COFantasy || function() { return; } if (bar1 >= pvmax && !reposLong) { - //Plus rien à faire si pas un repos long + //Plus rien \xE0 faire si pas un repos long sendPerso(perso, "n'a pas besoin de repos"); finalize(); return; } if (reposLong) { - //Récupération des affaiblissements de carac si repos long + //R\xE9cup\xE9ration des affaiblissements de carac si repos long allCaracs.forEach(function(carac) { let malus = attributeAsInt(perso, 'affaiblissementde' + carac, 0); if (malus > 0) { diminueAffaiblissement(perso, carac, 1, evt, malus); - sendPerso(perso, "récupère un point " + deCarac(carac)); + sendPerso(perso, "r\xE9cup\xE8re un point " + deCarac(carac)); } }); if (bar1 >= pvmax && (!pr || pr.current == pr.max)) { @@ -24071,19 +24395,19 @@ var COFantasy = COFantasy || function() { return; } if (bar1 < pvmax && predicateAsBool(perso, 'montureMagique')) { - //La monture magique récupère tous ses PV durant la nuit + //La monture magique r\xE9cup\xE8re tous ses PV durant la nuit updateCurrentBar(perso, 1, pvmax, evt); - sendPerso(perso, "récupère tous ses PV"); + sendPerso(perso, "r\xE9cup\xE8re tous ses PV"); finalize(); return; } } - //La récupération de PV ou de PR + //La r\xE9cup\xE9ration de PV ou de PR let dVie = ficheAttributeAsInt(perso, "DV", 0); if (dVie < 4) { if (bar1 < pvmax) manquePV.push(perso); finalize(); - return; //Si pas de dé de vie, alors pas de PR. + return; //Si pas de d\xE9 de vie, alors pas de PR. } if (limiteRessources(perso, options, 'repos', 'repos', evt)) { if (bar1 < pvmax) manquePV.push(perso); @@ -24091,18 +24415,18 @@ var COFantasy = COFantasy || function() { return; } let message; - if (reposLong && pr && pr.current < pr.max) { // on récupère un PR + if (reposLong && pr && pr.current < pr.max) { // on r\xE9cup\xE8re un PR //Sauf si on a une blessure gave if (getState(perso, 'blesse')) { - let testId = 'guérir_blessure_' + perso.token.id; + let testId = 'gu\xE9rir_blessure_' + perso.token.id; testCaracteristique(perso, 'CON', 8, testId, options, evt, function(tr) { - sendPerso(perso, "fait un jet de CON pour guérir de sa blessure"); + sendPerso(perso, "fait un jet de CON pour gu\xE9rir de sa blessure"); let m = "/direct " + onGenre(perso, 'Il', 'Elle') + " fait " + tr.texte; if (tr.reussite) { - sendChar(charId, m + "≥ 8, son état s'améliore nettement." + tr.modifiers, true); + sendChar(charId, m + "≥ 8, son \xE9tat s'am\xE9liore nettement." + tr.modifiers, true); setState(perso, 'blesse', false, evt); } else { - let msgRate = m + "< 8, son état reste préoccupant." + tr.rerolls + tr.modifiers; + let msgRate = m + "< 8, son \xE9tat reste pr\xE9occupant." + tr.rerolls + tr.modifiers; sendChar(charId, msgRate, true); } finalize(); @@ -24111,27 +24435,26 @@ var COFantasy = COFantasy || function() { } let affAttr = rajouterPointDeRecuperation(perso, evt, pr); if (affAttr === undefined) { - error("Pas de point de récupération à rajouter et pourtant pas au max", token); + error("Pas de point de r\xE9cup\xE9ration \xE0 rajouter et pourtant pas au max", token); finalize(); return; } message = - "Au cours de la nuit, les points de récupération de " + nomPerso(perso) + - " passent de " + (pr.current - 1) + " à " + pr.current; + "Au cours de la nuit, les points de r\xE9cup\xE9ration de " + nomPerso(perso) + + " passent de " + (pr.current - 1) + " \xE0 " + pr.current; sendChar(charId, message, true); if (bar1 < pvmax) manquePV.push(perso); finalize(); return; } if (!reposLong && pr) { - if (pr.current === 0) { //pas possible de récupérer - message = " a besoin d'une nuit complète pour récupérer"; + if (pr.current === 0) { //pas possible de r\xE9cup\xE9rer + message = " a besoin d'une nuit compl\xE8te pour r\xE9cup\xE9rer"; sendPerso(perso, message); finalize(); return; - } else { //dépense d'un PR + } else { //d\xE9pense d'un PR enleverPointDeRecuperation(perso, pr, evt); - pr.current--; } } let conMod = modCarac(perso, 'constitution'); @@ -24164,16 +24487,17 @@ var COFantasy = COFantasy || function() { if (reposLong) { message = "Au cours de la nuit, "; } else { - message = "Après 5 minutes de repos, "; + message = "Apr\xE8s 5 minutes de repos, "; } - message += "récupère " + buildinline(roll) + "+" + bonus + " PV."; - if (pr) message += " Il lui reste " + pr.current + " points de récupération"; + message += "r\xE9cup\xE8re " + buildinline(roll) + "+" + bonus + " PV."; + if (pr) message += " Il lui reste " + pr.current + " points de r\xE9cup\xE9ration"; sendPerso(perso, message); finalize(); }); }); } + //!cof-recharger label [--grenaille] function recharger(msg) { let cmd = msg.content.split(' '); if (cmd.length < 2) { @@ -24187,15 +24511,12 @@ var COFantasy = COFantasy || function() { }; let grenaille = false; if (msg.content.includes(' --grenaille')) grenaille = true; - let options = {}; - if (msg.content.includes(' --son')) { - options = parseOptions(msg); - options = options || {}; - } + let options = parseOptions(msg); + options = options || {}; getSelected(msg, function(selected, playerId) { if (selected === undefined) { - sendPlayer(msg, "!cof-recharger sans sélection de tokens", playerId); - log("!cof-recharger requiert des tokens sélectionnés"); + sendPlayer(msg, "!cof-recharger sans s\xE9lection de tokens", playerId); + log("!cof-recharger requiert des tokens s\xE9lectionn\xE9s"); return; } iterSelected(selected, function(perso) { @@ -24222,7 +24543,7 @@ var COFantasy = COFantasy || function() { attrs = attrs[0]; currentCharge = parseInt(attrs.get('current')); if (isNaN(currentCharge)) { - error("charge mal formée", attrs); + error("charge mal form\xE9e", attrs); currentCharge = 0; } } @@ -24244,10 +24565,11 @@ var COFantasy = COFantasy || function() { } else attrGrenaille = attrGrenaille[0]; currentChargeGrenaille = parseInt(attrGrenaille.get('current')); if (isNaN(currentChargeGrenaille)) { - error("charge de grenaille mal formée", attrGrenaille); + error("charge de grenaille mal form\xE9e", attrGrenaille); return; } - if (currentChargeGrenaille > currentCharge) currentChargeGrenaille = currentCharge; + if (currentChargeGrenaille > currentCharge) + currentChargeGrenaille = currentCharge; evt.attributes.push({ attribute: attrGrenaille, current: currentChargeGrenaille @@ -24277,7 +24599,7 @@ var COFantasy = COFantasy || function() { } else attrGrenaille = attrGrenaille[0]; currentChargeGrenaille = parseInt(attrGrenaille.get('current')); if (isNaN(currentChargeGrenaille)) { - error("charge de grenaille mal formée", attrGrenaille); + error("charge de grenaille mal form\xE9e", attrGrenaille); return; } if (currentChargeGrenaille < currentCharge) { @@ -24293,7 +24615,7 @@ var COFantasy = COFantasy || function() { attrGrenaille = attrGrenaille[0]; currentChargeGrenaille = parseInt(attrGrenaille.get('current')); if (isNaN(currentChargeGrenaille)) { - error("charge de grenaille mal formée", attrGrenaille); + error("charge de grenaille mal form\xE9e", attrGrenaille); return; } if (currentChargeGrenaille > 0) { @@ -24308,12 +24630,12 @@ var COFantasy = COFantasy || function() { } } if (maxCharge == 1) { - sendPerso(perso, arme.name + " est déjà chargé"); + sendPerso(perso, arme.name + " est d\xE9j\xE0 charg\xE9"); } else { - sendPerso(perso, "a déjà tous ses " + arme.name + " chargés"); + sendPerso(perso, "a d\xE9j\xE0 tous ses " + arme.name + " charg\xE9s"); } }); - }); + }, options); addEvent(evt); } @@ -24326,12 +24648,12 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let action = evt.action; if (!action) { - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); return; } let perso = evt.personnage; @@ -24339,7 +24661,7 @@ var COFantasy = COFantasy || function() { if (args.length > 2) { let roll = action.rolls[args[2]]; if (roll === undefined) { - error("Erreur interne du bouton de chance : roll non identifié", args); + error("Erreur interne du bouton de chance : roll non identifi\xE9", args); return; } if (roll.token === undefined) { @@ -24350,7 +24672,7 @@ var COFantasy = COFantasy || function() { rollId = args[2]; } if (perso === undefined) { - error("Erreur interne du bouton de chance : l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton de chance : l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24359,7 +24681,7 @@ var COFantasy = COFantasy || function() { } let chance = pointsDeChance(perso); if (chance <= 0) { - sendPerso(perso, "n'a plus de point de chance à dépenser..."); + sendPerso(perso, "n'a plus de point de chance \xE0 d\xE9penser..."); return; } let evtChance = { @@ -24369,7 +24691,7 @@ var COFantasy = COFantasy || function() { chance--; undoEvent(evt); setFicheAttr(perso, 'pc', chance, evtChance, { - msg: " a dépensé un point de chance. Il lui en reste " + chance + msg: " a d\xE9pens\xE9 un point de chance. Il lui en reste " + chance }); action.options = action.options || {}; if (rollId) { @@ -24379,7 +24701,7 @@ var COFantasy = COFantasy || function() { action.options.chance = (action.options.chance + 10) || 10; } if (!redoEvent(evt, action, perso)) - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); addEvent(evtChance); } @@ -24392,19 +24714,19 @@ var COFantasy = COFantasy || function() { } const evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let perso = evt.personnage; let rollId; if (args.length > 2) { if (!evt.action) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let roll = evt.action.rolls[args[2]]; if (roll === undefined) { - error("Erreur interne du bouton de chance : roll non identifié", args); + error("Erreur interne du bouton de chance : roll non identifi\xE9", args); return; } if (roll.token === undefined) { @@ -24415,7 +24737,7 @@ var COFantasy = COFantasy || function() { rollId = args[2]; } if (perso === undefined) { - error("Erreur interne du bouton de prouesse : l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton de prouesse : l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24451,7 +24773,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evtProuesse, false, {}, explications, function(dmgDisplay, dmg) { - sendPerso(perso, "réalise une prouesse et perd " + dmgDisplay + " PV"); + sendPerso(perso, "r\xE9alise une prouesse et perd " + dmgDisplay + " PV"); explications.forEach(function(expl) { sendPerso(perso, expl); }); @@ -24465,7 +24787,7 @@ var COFantasy = COFantasy || function() { } if (redoEvent(evt, action, perso)) return; } - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); } //!cof-pacte-sanglant [evt.id] [3|5] [rollId] @@ -24477,7 +24799,7 @@ var COFantasy = COFantasy || function() { } const evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let bonus = parseInt(args[2]); @@ -24489,12 +24811,12 @@ var COFantasy = COFantasy || function() { let rollId; if (args.length > 3) { if (!evt.action) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let roll = evt.action.rolls[args[3]]; if (roll === undefined) { - error("Erreur interne du bouton de pacte sanglant : roll non identifié", args); + error("Erreur interne du bouton de pacte sanglant : roll non identifi\xE9", args); return; } if (roll.token === undefined) { @@ -24505,7 +24827,7 @@ var COFantasy = COFantasy || function() { rollId = args[3]; } if (perso === undefined) { - error("Erreur interne du bouton de pacte sanglant : l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton de pacte sanglant : l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24514,7 +24836,7 @@ var COFantasy = COFantasy || function() { } let valPacteSanglant = predicateAsInt(perso, 'pacteSanglant', 0); if (valPacteSanglant < bonus) { - sendPerso(perso, "ne peut pas faire ça !"); + sendPerso(perso, "ne peut pas faire \xE7a !"); return; } let action = evt.action; @@ -24543,7 +24865,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evtPacteSanglant, false, {}, explications, function(dmgDisplay, dmg) { - sendPerso(perso, "réalise un Pacte sanglant et perd " + dmgDisplay + " PV"); + sendPerso(perso, "r\xE9alise un Pacte sanglant et perd " + dmgDisplay + " PV"); explications.forEach(function(expl) { sendPerso(perso, expl); }); @@ -24556,7 +24878,7 @@ var COFantasy = COFantasy || function() { } if (redoEvent(evt, action, perso)) return; } - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); } //!cof-pacte-sanglant [evt.id] [3|5] [targetId] @@ -24568,11 +24890,11 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } if (!evt.action) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let bonus = parseInt(args[2]); @@ -24582,7 +24904,7 @@ var COFantasy = COFantasy || function() { } let perso = persoOfId([args[3]]); if (perso === undefined) { - error("Erreur interne du bouton de pacte sanglant (DEF) : pas de cible trouvée", args); + error("Erreur interne du bouton de pacte sanglant (DEF) : pas de cible trouv\xE9e", args); return; } if (!peutController(msg, perso)) { @@ -24591,7 +24913,7 @@ var COFantasy = COFantasy || function() { } let valPacteSanglant = predicateAsInt(perso, 'pacteSanglant', 0); if (valPacteSanglant < bonus) { - sendPerso(perso, "ne peut pas faire ça !"); + sendPerso(perso, "ne peut pas faire \xE7a !"); return; } let action = evt.action; @@ -24619,7 +24941,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evtPacteSanglant, false, {}, explications, function(dmgDisplay, dmg) { - sendPerso(perso, "réalise un Pacte sanglant et perd " + dmgDisplay + " PV"); + sendPerso(perso, "r\xE9alise un Pacte sanglant et perd " + dmgDisplay + " PV"); explications.forEach(function(expl) { sendPerso(perso, expl); }); @@ -24628,7 +24950,7 @@ var COFantasy = COFantasy || function() { options.pacteSanglantDef[perso.token.id] = (options.pacteSanglantDef[perso.token.id] + bonus) || bonus; if (redoEvent(evt, action, perso)) return; } - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); } //!cof-tour-force [evt.id] [rollId] @@ -24640,19 +24962,19 @@ var COFantasy = COFantasy || function() { } const evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let perso = evt.personnage; let rollId; if (args.length > 2) { if (!evt.action) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let roll = evt.action.rolls[args[2]]; if (roll === undefined) { - error("Erreur interne du bouton de tour de force : roll non identifié", args); + error("Erreur interne du bouton de tour de force : roll non identifi\xE9", args); return; } if (roll.token === undefined) { @@ -24663,7 +24985,7 @@ var COFantasy = COFantasy || function() { rollId = args[2]; } if (perso === undefined) { - error("Erreur interne du bouton de tour de force : l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton de tour de force : l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24672,7 +24994,7 @@ var COFantasy = COFantasy || function() { } let attrTourDeForce = predicateAsBool(perso, 'tourDeForce'); if (!attrTourDeForce) { - sendPerso(perso, "ne peut pas faire ça !"); + sendPerso(perso, "ne peut pas faire \xE7a !"); return; } let action = evt.action; @@ -24699,7 +25021,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evtTourDeForce, false, {}, explications, function(dmgDisplay, dmg) { - sendPerso(perso, "réalise un Tour de force et perd " + dmgDisplay + " PV"); + sendPerso(perso, "r\xE9alise un Tour de force et perd " + dmgDisplay + " PV"); explications.forEach(function(expl) { sendPerso(perso, expl); }); @@ -24712,7 +25034,7 @@ var COFantasy = COFantasy || function() { } if (redoEvent(evt, action, perso)) return; } - error("Type d'évènement pas encore géré pour la chance", evt); + error("Type d'\xE9v\xE8nement pas encore g\xE9r\xE9 pour la chance", evt); } //Renvoie true si redo possible, false sinon @@ -24771,7 +25093,7 @@ var COFantasy = COFantasy || function() { action.testINT, action.infosAdditionelles, options); return true; case 'enveloppement': - case 'étreinte': + case '\xE9treinte': doEnveloppement(action.attaquant, action.cible, action.difficulte, action.type, action.exprDM, options); return true; case 'injonction': @@ -24863,12 +25185,12 @@ var COFantasy = COFantasy || function() { } let evt = findEvent(args[1]); if (evt === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let perso = evt.personnage; if (perso === undefined) { - error("Erreur interne du bouton d'échec total: l'évenement n'a pas de personnage", evt); + error("Erreur interne du bouton d'\xE9chec total: l'\xE9venement n'a pas de personnage", evt); return; } if (!peutController(msg, perso)) { @@ -24877,14 +25199,14 @@ var COFantasy = COFantasy || function() { } let action = evt.action; if (!action || evt.type != "Attaque") { - error("Erreur interne du bouton d'échec total: l'évènement n'est pas une attaque", evt); + error("Erreur interne du bouton d'\xE9chec total: l'\xE9v\xE8nement n'est pas une attaque", evt); return; } let evtEchecTotal = { type: 'echecTotal' }; addEvent(evtEchecTotal); - // Attaquer avec les mêmes options, vider redo et preDmg éventuels + // Attaquer avec les m\xEAmes options, vider redo et preDmg \xE9ventuels let options = action.options; options.auto = true; options.echecTotal = true; @@ -24904,13 +25226,17 @@ var COFantasy = COFantasy || function() { else if (rangExpertDuCombat > 2) limiteParTour = 2; else limiteParTour = 1; if (limiteRessources(perso, { - limiteParCombat: rangExpertDuCombat * 2, - limiteParTour: limiteParTour - }, "expertDuCombat", "a atteint sa limite de dé d'expert du combat", evt)) { + limiteParCombat: { + val: rangExpertDuCombat * 2 + }, + limiteParTour: { + val: limiteParTour + } + }, "expertDuCombat", "a atteint sa limite de d\xE9 d'expert du combat", evt)) { addEvent(evt); return false; } - sendPerso(perso, "utilise un dé d'expert du combat"); + sendPerso(perso, "utilise un d\xE9 d'expert du combat"); return true; } @@ -24919,19 +25245,19 @@ var COFantasy = COFantasy || function() { //!cof-expert-combat-dm function expertDuCombat(msg) { if (!stateCOF.combat) { - sendPlayer(msg, "On ne peut utiliser les dés d'expert du combat qu'en combat"); + sendPlayer(msg, "On ne peut utiliser les d\xE9s d'expert du combat qu'en combat"); return; } let cmd = msg.content.split(' '); let evtARefaire; const evt = { - type: "Dé d'expert du combat (touche)", + type: "D\xE9 d'expert du combat (touche)", attributes: [] }; - if (cmd.length > 1) { //On relance pour un événement particulier + if (cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; @@ -24941,7 +25267,7 @@ var COFantasy = COFantasy || function() { return; } if (perso === undefined) { - error("Erreur interne du bouton expert de combat : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton expert de combat : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -24957,11 +25283,11 @@ var COFantasy = COFantasy || function() { else if (cmd[0].includes("-dm")) action.options.expertDuCombatDM = action.options.expertDuCombatDM + 1 || 1; if (!redoEvent(evtARefaire, action, perso)) - error("Type d'évènement pas supporté par le bouton Rune d'Energie", evt); - } else { //Juste pour vérifier l'attribut et le diminuer + error("Type d'\xE9v\xE8nement pas support\xE9 par le bouton Rune d'Energie", evt); + } else { //Juste pour v\xE9rifier l'attribut et le diminuer getSelected(msg, function(selection) { if (selection.length === 0) { - sendPlayer(msg, 'Pas de token sélectionné pour !cof-bouton-expert-combat-touche'); + sendPlayer(msg, 'Pas de token s\xE9lectionn\xE9 pour !cof-bouton-expert-combat-touche'); return; } iterSelected(selection, function(perso) { @@ -24981,17 +25307,17 @@ var COFantasy = COFantasy || function() { } let evtARefaire = findEvent(args[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou éte annulée", args); + error("L'action est trop ancienne ou \xE9te annul\xE9e", args); return; } let action = evtARefaire.action; if (action === undefined) { - error("Le dernier évènement n'est pas une action", args); + error("Le dernier \xE9v\xE8nement n'est pas une action", args); return; } let perso = persoOfId([args[2]]); if (perso === undefined) { - error("Erreur interne du bouton d'expert du combat (DEF) : pas de cible trouvée", args); + error("Erreur interne du bouton d'expert du combat (DEF) : pas de cible trouv\xE9e", args); return; } if (!peutController(msg, perso)) { @@ -25012,37 +25338,39 @@ var COFantasy = COFantasy || function() { } function persoUtiliseRuneEnergie(perso, evt) { - let attr = tokenAttribute(perso, 'runeForgesort_énergie'); + let attr = tokenAttribute(perso, 'runeForgesort_\xE9nergie'); if (attr.length < 1 || attr[0].get('current') < 1) { - sendPerso(perso, "n'a pas de rune d'énergie"); + sendPerso(perso, "n'a pas de rune d'\xE9nergie"); return false; } if (limiteRessources(perso, { - limiteParCombat: 1 - }, "runeForgesort_énergie", "a déjà utilisé sa rune d'énergie durant ce combat", evt)) { + limiteParCombat: { + val: 1 + } + }, "runeForgesort_\xE9nergie", "a d\xE9j\xE0 utilis\xE9 sa rune d'\xE9nergie durant ce combat", evt)) { addEvent(evt); return false; } - sendPerso(perso, "utilise sa rune d'énergie pour relancer un d20 sur un test d'attaque, de FOR, DEX ou CON"); + sendPerso(perso, "utilise sa rune d'\xE9nergie pour relancer un d20 sur un test d'attaque, de FOR, DEX ou CON"); return true; } //!cof-bouton-rune-energie function runeEnergie(msg) { if (!stateCOF.combat) { - sendPlayer(msg, "On ne peut utiliser les runes d'énergie qu'en combat"); + sendPlayer(msg, "On ne peut utiliser les runes d'\xE9nergie qu'en combat"); return; } let cmd = msg.content.split(' '); let evtARefaire; const evt = { - type: "Rune d'énergie", + type: "Rune d'\xE9nergie", attributes: [] }; - if (cmd.length > 1) { //On relance pour un événement particulier + if (cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; @@ -25055,7 +25383,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 2) { let roll = action.rolls[cmd[2]]; if (roll === undefined) { - error("Erreur interne du bouton de chance : roll non identifié", cmd); + error("Erreur interne du bouton de chance : roll non identifi\xE9", cmd); return; } if (roll.token === undefined) { @@ -25067,7 +25395,7 @@ var COFantasy = COFantasy || function() { evt.rollId = rollId; } if (perso === undefined) { - error("Erreur interne du bouton de rune d'énergie : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton de rune d'\xE9nergie : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -25076,7 +25404,7 @@ var COFantasy = COFantasy || function() { } let carac = action.caracteristque; if (carac == 'SAG' || carac == 'INT' || carac == 'CHA') { - sendPerso(perso, "ne peut pas utiliser la rune d'énergie pour un test " + deCarac(carac)); + sendPerso(perso, "ne peut pas utiliser la rune d'\xE9nergie pour un test " + deCarac(carac)); return; } if (!persoUtiliseRuneEnergie(perso, evt)) return; @@ -25085,11 +25413,11 @@ var COFantasy = COFantasy || function() { if (rollId) delete action.rolls[rollId]; else if (action.rolls && action.rolls.attack) delete action.rolls.attack; if (!redoEvent(evtARefaire, action, perso)) - error("Type d'évènement pas supporté par le bouton Rune d'Energie", evt); - } else { //Juste pour vérifier l'attribut et le diminuer + error("Type d'\xE9v\xE8nement pas support\xE9 par le bouton Rune d'Energie", evt); + } else { //Juste pour v\xE9rifier l'attribut et le diminuer getSelected(msg, function(selection) { if (selection.length === 0) { - sendPlayer(msg, 'Pas de token sélectionné pour !cof-rune-energie'); + sendPlayer(msg, 'Pas de token s\xE9lectionn\xE9 pour !cof-rune-energie'); return; } iterSelected(selection, function(perso) { @@ -25104,7 +25432,7 @@ var COFantasy = COFantasy || function() { let attrName = permanent ? 'runeDePuissance' + labelArme : "runeForgesort_puissance(" + labelArme + ")"; let arme = getAttackName(labelArme, perso); if (arme === undefined) { - error(perso.tokNname + " n'a pas d'arme associée au label " + labelArme, perso); + error(perso.tokNname + " n'a pas d'arme associ\xE9e au label " + labelArme, perso); return false; } if (!permanent && tokenAttribute(perso, attrName).length === 0) { @@ -25112,8 +25440,10 @@ var COFantasy = COFantasy || function() { return false; } if (limiteRessources(perso, { - limiteParCombat: 1 - }, attrName, "a déjà utilisé sa rune de puissance durant ce combat", evt)) { + limiteParCombat: { + val: 1 + } + }, attrName, "a d\xE9j\xE0 utilis\xE9 sa rune de puissance durant ce combat", evt)) { addEvent(evt); return false; } @@ -25130,7 +25460,7 @@ var COFantasy = COFantasy || function() { } let cmd = msg.content.split(' '); if (cmd.length < 2) { - error("Il faut spécifier le label de l'arme sur laquelle la rune de puissance est inscrite", cmd); + error("Il faut sp\xE9cifier le label de l'arme sur laquelle la rune de puissance est inscrite", cmd); return; } let labelArme = cmd[1]; @@ -25139,15 +25469,15 @@ var COFantasy = COFantasy || function() { type: "Rune de puissance", attributes: [] }; - if (cmd.length > 2) { //On relance pour un événement particulier + if (cmd.length > 2) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[2]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; if (perso === undefined) { - error("Erreur interne du bouton de rune de puissance : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton de rune de puissance : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -25180,10 +25510,10 @@ var COFantasy = COFantasy || function() { default: return; } - } else { //Juste pour vérifier l'attribut et le diminuer + } else { //Juste pour v\xE9rifier l'attribut et le diminuer getSelected(msg, function(selection, playerId) { if (selection.length === 0) { - sendPlayer(msg, 'Pas de token sélectionné pour !cof-rune-puissance', playerId); + sendPlayer(msg, 'Pas de token s\xE9lectionn\xE9 pour !cof-rune-puissance', playerId); return; } iterSelected(selection, function(perso) { @@ -25207,12 +25537,12 @@ var COFantasy = COFantasy || function() { } let evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; if (perso === undefined) { - error("Erreur interne du bouton de kiai : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton de kiai : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -25254,7 +25584,7 @@ var COFantasy = COFantasy || function() { } } - //Devrait être appelé seulement depuis un bouton + //Devrait \xEAtre appel\xE9 seulement depuis un bouton //!cof-esquive-fatale evtid target_id function doEsquiveFatale(msg) { let cmd = msg.content.split(' '); @@ -25264,12 +25594,12 @@ var COFantasy = COFantasy || function() { attributes: [] }; if (cmd.length < 3) { - error("Il manque des arguments à !cof-esquive-fatale", cmd); + error("Il manque des arguments \xE0 !cof-esquive-fatale", cmd); return; } evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'attaque est trop ancienne ou a été annulée", cmd); + error("L'attaque est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let action = evtARefaire.action; @@ -25279,7 +25609,7 @@ var COFantasy = COFantasy || function() { } let perso = action.cibles[0]; if (perso === undefined) { - error("Erreur interne du bouton de 'esquive fatale : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton de 'esquive fatale : l'\xE9venement n'a pas de personnage", evtARefaire); return; } let adversaire = persoOfId(cmd[2]); @@ -25298,7 +25628,7 @@ var COFantasy = COFantasy || function() { } let ennemisAuContact = perso.ennemisAuContact; if (ennemisAuContact === undefined) { - error("Ennemis au contact non définis", perso); + error("Ennemis au contact non d\xE9finis", perso); } else { let i = ennemisAuContact.find(function(tok) { return (tok.id == adversaire.token.id); @@ -25312,12 +25642,12 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "pas le droit d'utiliser ce bouton"); return; } - let testEsquiveFatale = testLimiteUtilisationsCapa(perso, 'esquiveFatale', 'combat', "a déjà fait une esquive fatale durant ce combat", "ne sait pas faire d'esquive fatale"); + let testEsquiveFatale = testLimiteUtilisationsCapa(perso, 'esquiveFatale', 'combat', "a d\xE9j\xE0 fait une esquive fatale durant ce combat", "ne sait pas faire d'esquive fatale"); if (testEsquiveFatale === undefined) { return; } utiliseCapacite(perso, testEsquiveFatale, evt); - //On va refaire complètement l'attaque + //On va refaire compl\xE8tement l'attaque undoEvent(evtARefaire); addEvent(evt); adversaire.msgEsquiveFatale = nomPerso(perso) + " esquive l'attaque qui touche " + nomPerso(adversaire); @@ -25327,21 +25657,21 @@ var COFantasy = COFantasy || function() { redoEvent(evtARefaire, action); } - //Soit juste !cof-intercepter (en sélectionnant le chevalier) + //Soit juste !cof-intercepter (en s\xE9lectionnant le chevalier) //Soit depuis un bouton !cof-intercepter evtid cibleid function intercepter(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } let fromEvtId; if (cmd.length > 1) { fromEvtId = cmd[1]; //Appel depuis le bouton if (cmd.length < 3) { - error("Bouton d'interception mal formé", cmd); + error("Bouton d'interception mal form\xE9", cmd); return; } } @@ -25349,10 +25679,10 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(chevalier) { let character = getObj('character', chevalier.charId); if (character === undefined) { - error("L'argument de !cof-intercepter n'est pas une id de token valide (personnage non défini)", msg.content); + error("L'argument de !cof-intercepter n'est pas une id de token valide (personnage non d\xE9fini)", msg.content); return; } - let test = testLimiteUtilisationsCapa(chevalier, 'intercepter', 'tour', "a déjà intercepté une attaque ce tour", "ne sait pas utiliser intercepter les attaques"); + let test = testLimiteUtilisationsCapa(chevalier, 'intercepter', 'tour', "a d\xE9j\xE0 intercept\xE9 une attaque ce tour", "ne sait pas utiliser intercepter les attaques"); if (test === undefined) { return; } @@ -25360,7 +25690,7 @@ var COFantasy = COFantasy || function() { let attaque; let originalTarget; let evtARefaire; - if (fromEvtId) { //On a utilisé un bouton + if (fromEvtId) { //On a utilis\xE9 un bouton if (!peutController(msg, chevalier)) { sendPlayer(msg, "pas le droit d'utiliser ce bouton"); return; @@ -25394,15 +25724,15 @@ var COFantasy = COFantasy || function() { attaque = evtARefaire.action; } if (attaque === undefined) { - sendPlayer(msg, "La dernière action trouvée n'est pas une attaque, impossible d'intercepter"); + sendPlayer(msg, "La derni\xE8re action trouv\xE9e n'est pas une attaque, impossible d'intercepter"); return; } if (attaque.cibles.length === 0) { - sendPlayer(msg, "la dernière attaque n'a touché aucune cible, impossible d'intercepter"); + sendPlayer(msg, "la derni\xE8re attaque n'a touch\xE9 aucune cible, impossible d'intercepter"); return; } if (attaque.cibles.length > 1) { - sendPlayer(msg, "la dernière attaque a touché plus d'une cible, impossible d'intercepter"); + sendPlayer(msg, "la derni\xE8re attaque a touch\xE9 plus d'une cible, impossible d'intercepter"); return; } originalTarget = attaque.cibles[0]; @@ -25426,22 +25756,22 @@ var COFantasy = COFantasy || function() { removePreDmg(attaque.options, originalTarget); redoEvent(evtARefaire, attaque); }); - }); + }, options); } - //simplement prendre les DM à la place d'un autre + //simplement prendre les DM \xE0 la place d'un autre function interposer(msg) { getSelected(msg, function(selected, playerId) { iterSelected(selected, function(cible) { let charId = cible.charId; let character = getObj('character', charId); if (character === undefined) { - error("L'argument de !cof-interposer n'est pas une id de token valide (personnage non défini)", msg.content); + error("L'argument de !cof-interposer n'est pas une id de token valide (personnage non d\xE9fini)", msg.content); return; } cible.name = character.get('name'); //TODO: utile ? if (attributeAsBool(cible, 'interposer')) { - sendPerso(cible, " a déjà intercepté une attaque ce tour"); + sendPerso(cible, " a d\xE9j\xE0 intercept\xE9 une attaque ce tour"); return; } let attaque; @@ -25450,20 +25780,20 @@ var COFantasy = COFantasy || function() { attaque = lastAct.action; } if (attaque === undefined) { - sendPlayer(msg, "la dernière action trouvée n'est pas une attaque, impossible d'intercepter"); + sendPlayer(msg, "la derni\xE8re action trouv\xE9e n'est pas une attaque, impossible d'intercepter"); return; } if (attaque.cibles.length === 0) { - sendPlayer(msg, "la dernière attaque n'a touché aucune cible, impossible de s'interposer"); + sendPlayer(msg, "la derni\xE8re attaque n'a touch\xE9 aucune cible, impossible de s'interposer"); return; } if (attaque.cibles.length > 1) { - sendPlayer(msg, "la dernière attaque a touché plus d'une cible, impossible de s'interposer en utilisant le script"); + sendPlayer(msg, "la derni\xE8re attaque a touch\xE9 plus d'une cible, impossible de s'interposer en utilisant le script"); return; } let target = attaque.cibles[0]; if (target === undefined) { - error("Le token de la dernière attaque est indéfini", attaque); + error("Le token de la derni\xE8re attaque est ind\xE9fini", attaque); return; } let targetName = nomPerso(target); @@ -25480,7 +25810,7 @@ var COFantasy = COFantasy || function() { let pvApres = target.token.get('bar1_value'); // On annule l'ancienne action undoEvent(); - // On calcule ensuite les pv perdus, et on les applique au défenseur + // On calcule ensuite les pv perdus, et on les applique au d\xE9fenseur let pvPerdus = target.token.get('bar1_value') - pvApres; // Puis on refait en changeant la cible let options = attaque.options; @@ -25498,7 +25828,7 @@ var COFantasy = COFantasy || function() { getSelected(msg, function(selected, playerId) { iterSelected(selected, function(cible) { if (attributeAsBool(cible, 'exemplaire')) { - sendPerso(cible, " a déjà montré l'exemple à ce tour"); + sendPerso(cible, " a d\xE9j\xE0 montr\xE9 l'exemple \xE0 ce tour"); return; } let attaque; @@ -25509,20 +25839,20 @@ var COFantasy = COFantasy || function() { } } if (attaque === undefined) { - sendPlayer(msg, "la dernière action trouvée n'est pas une attaque ratée, impossible de montrer l'exemple", + sendPlayer(msg, "la derni\xE8re action trouv\xE9e n'est pas une attaque rat\xE9e, impossible de montrer l'exemple", playerId); return; } let attackerName = nomPerso(attaque.attaquant); if (attackerName === undefined) { - error("Le token de la dernière attaque est indéfini", attaque); + error("Le token de la derni\xE8re attaque est ind\xE9fini", attaque); return; } const evt = { type: "Montrer l'exemple" }; setTokenAttr(cible, 'exemplaire', true, evt, { - msg: "montre l'exemple à " + attackerName + msg: "montre l'exemple \xE0 " + attackerName }); // On annule l'ancienne action undoEvent(); @@ -25545,16 +25875,16 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2 || (cmd[1] != "rate" && cmd[1] != "touche")) { - error("Il manque l'option rate ou touche à Intervention Divine", msg); + error("Il manque l'option rate ou touche \xE0 Intervention Divine", msg); return; } getSelected(msg, function(selected) { iterSelected(selected, function(pretre) { - let testIntervention = testLimiteUtilisationsCapa(pretre, 'interventionDivine', 'combat', "a déjà fait une intervention divine ce combat", "ne sait pas faire d'intervention divine"); + let testIntervention = testLimiteUtilisationsCapa(pretre, 'interventionDivine', 'combat', "a d\xE9j\xE0 fait une intervention divine ce combat", "ne sait pas faire d'intervention divine"); if (testIntervention === undefined) { return; } @@ -25589,12 +25919,12 @@ var COFantasy = COFantasy || function() { attack(action.playerName, action.playerId, action.attaquant, action.cibles, action.weaponStats, optionsRedo); return; }); - }); + }, options); } - //!cof-petit-veinard (avec un token sélectionné) + //!cof-petit-veinard (avec un token s\xE9lectionn\xE9) //!cof-bouton-petit-veinard evtid - //sans argument, diminue juste l'attribut, sinon relance l'événement + //sans argument, diminue juste l'attribut, sinon relance l'\xE9v\xE9nement function petitVeinard(msg) { if (!stateCOF.combat) { sendPlayer(msg, "On ne peut utiliser petit veinard qu'en combat"); @@ -25604,7 +25934,7 @@ var COFantasy = COFantasy || function() { if (msgOptions === undefined) return; let cmd = msgOptions.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } let evtARefaire; @@ -25612,22 +25942,22 @@ var COFantasy = COFantasy || function() { type: "Petit veinard", attributes: [] }; - if (cmd.length > 1) { //On relance pour un événement particulier + if (cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let perso = evtARefaire.personnage; let rollId; if (cmd.length > 2) { if (!evtARefaire.action) { - error("Le dernier évènement n'est pas une action", msg.content); + error("Le dernier \xE9v\xE8nement n'est pas une action", msg.content); return; } let roll = evtARefaire.action.rolls[cmd[2]]; if (roll === undefined) { - error("Erreur interne du bouton de chance : roll non identifié", msg.content); + error("Erreur interne du bouton de chance : roll non identifi\xE9", msg.content); return; } if (roll.token === undefined) { @@ -25638,7 +25968,7 @@ var COFantasy = COFantasy || function() { rollId = cmd[2]; } if (perso === undefined) { - error("Erreur interne du bouton petit veinard : l'évenement n'a pas de personnage", evtARefaire); + error("Erreur interne du bouton petit veinard : l'\xE9venement n'a pas de personnage", evtARefaire); return; } if (!peutController(msg, perso)) { @@ -25650,7 +25980,7 @@ var COFantasy = COFantasy || function() { error("Impossible de relancer l'action", evtARefaire); return; } - let testPetitVeinard = testLimiteUtilisationsCapa(perso, 'petitVeinard', 'combat', "a déjà tenté sa chance pour ce combat", "n'est pas un petit veinard"); + let testPetitVeinard = testLimiteUtilisationsCapa(perso, 'petitVeinard', 'combat', "a d\xE9j\xE0 tent\xE9 sa chance pour ce combat", "n'est pas un petit veinard"); if (testPetitVeinard === undefined) { return; } @@ -25660,19 +25990,19 @@ var COFantasy = COFantasy || function() { if (rollId) delete action.rolls[rollId]; else if (action.rolls && action.rolls.attack) delete action.rolls.attack; if (!redoEvent(evtARefaire, action, perso)) - error("Type d'évènement pas supporté par le bouton Petit Veinard", evt); - } else { //Juste pour vérifier l'attribut et le diminuer + error("Type d'\xE9v\xE8nement pas support\xE9 par le bouton Petit Veinard", evt); + } else { //Juste pour v\xE9rifier l'attribut et le diminuer getSelected(msg, function(selection, playerId) { if (selection.length === 0) { - sendPlayer(msg, 'Pas de token sélectionné pour !cof-petit-veinard', playerId); + sendPlayer(msg, 'Pas de token s\xE9lectionn\xE9 pour !cof-petit-veinard', playerId); return; } iterSelected(selection, function(perso) { - let testPetitVeinard = testLimiteUtilisationsCapa(perso, 'petitVeinard', 'combat', "a déjà tenté sa chance pour ce combat", "n'est pas un petit veinard"); + let testPetitVeinard = testLimiteUtilisationsCapa(perso, 'petitVeinard', 'combat', "a d\xE9j\xE0 tent\xE9 sa chance pour ce combat", "n'est pas un petit veinard"); if (testPetitVeinard === undefined) { return; } - sendPerso(perso, "peut relancer un dé"); + sendPerso(perso, "peut relancer un d\xE9"); utiliseCapacite(perso, testPetitVeinard, evt); }); //fin iterSelected addEvent(evt); @@ -25685,7 +26015,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } let testSurprise; @@ -25697,8 +26027,8 @@ var COFantasy = COFantasy || function() { let ciblesSelectionnees; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "!cof-surprise sans sélection de token", playerId); - log("!cof-surprise requiert de sélectionner des tokens"); + sendPlayer(msg, "!cof-surprise sans s\xE9lection de token", playerId); + log("!cof-surprise requiert de s\xE9lectionner des tokens"); return; } ciblesSelectionnees = selected; @@ -25708,11 +26038,11 @@ var COFantasy = COFantasy || function() { } cibles.push(perso); }); - }); + }, options); if (cibles.length > 0) { doSurprise(cibles, testSurprise, ciblesSelectionnees, options); } else { - error("Pas de cible valable sélectionnée pour la surprise", msg.content); + error("Pas de cible valable s\xE9lectionn\xE9e pour la surprise", msg.content); } } @@ -25735,7 +26065,7 @@ var COFantasy = COFantasy || function() { if (testSurprise === undefined) { display = startFramedDisplay(options.playerId, "Surprise !"); } else { - display = startFramedDisplay(options.playerId, "Test de surprise difficulté " + testSurprise); + display = startFramedDisplay(options.playerId, "Test de surprise difficult\xE9 " + testSurprise); } let tokensToProcess = cibles.length; let sendEvent = function() { @@ -25756,12 +26086,12 @@ var COFantasy = COFantasy || function() { if (compagnonPresent(perso, 'surveillance')) { bonusSurprise += 5; setTokenAttr(perso, 'bonusInitEmbuscade', 5, evt); - bonusMessages.push(name + " garde un temps d'avance grâce à son compagnon animal : +5"); + bonusMessages.push(name + " garde un temps d'avance gr\xE2ce \xE0 son compagnon animal : +5"); initPerso(perso, evt, true); } if (attributeAsBool(perso, 'sixiemeSens')) { bonusSurprise += 5; - bonusMessages.push(name + " a un sixième sens : +5"); + bonusMessages.push(name + " a un sixi\xE8me sens : +5"); } if (testSurprise !== undefined) { let testId = 'surprise_' + perso.token.id; @@ -25774,9 +26104,9 @@ var COFantasy = COFantasy || function() { testCaracteristique(perso, 'SAG', testSurprise, testId, optionsTest, evt, function(tr, explications) { let result; - if (tr.reussite) result = "réussi." + tr.modifiers; + if (tr.reussite) result = "r\xE9ussi." + tr.modifiers; else { - result = "raté, " + name + " est surpris"; + result = "rat\xE9, " + name + " est surpris"; result += eForFemale(perso); result += tr.rerolls + tr.modifiers; setState(perso, 'surpris', true, evt); @@ -25799,7 +26129,7 @@ var COFantasy = COFantasy || function() { }); } - function interchangeable(attackingToken, target, pageId) { //détermine si il y a assez de tokens + function interchangeable(attackingToken, target, pageId) { //d\xE9termine si il y a assez de tokens let token = target.token; let res = { result: false, @@ -25827,7 +26157,7 @@ var COFantasy = COFantasy || function() { let d = distanceCombat(attackingToken, tok); return (d === 0); }); - } else { // cible à distance, on garde celles au contact de la cible + } else { // cible \xE0 distance, on garde celles au contact de la cible res.targets = tokens.filter(function(tok) { let d = distanceCombat(token, tok); return (d === 0); @@ -25837,6 +26167,7 @@ var COFantasy = COFantasy || function() { } let alliesParPerso = {}; + let alliesDAttaqueEnMeute = new Set(); let listeCompetences = { FOR: { list: [], @@ -25864,21 +26195,26 @@ var COFantasy = COFantasy || function() { }, nombre: 0 }; - // Appelé uniquement après le "ready" et lorsqu'on modifie un handout (fonctionne après l'ajout et la destruction d'un handout) - // Du coup, alliesParPerso est toujours à jour + + function recomputeAllies() { + const handouts = findObjs({ + _type: 'handout' + }); + alliesParPerso = {}; + alliesDAttaqueEnMeute = new Set(); + handouts.forEach(parseHandout); + } + // Appel\xE9 uniquement apr\xE8s le "ready" et lorsqu'on modifie un handout (fonctionne apr\xE8s l'ajout et la destruction d'un handout) + // Du coup, alliesParPerso est toujours \xE0 jour function changeHandout(hand, prev) { if (prev && prev.name && prev.name.startsWith("Equipe ")) { - const handouts = findObjs({ - _type: 'handout' - }); - alliesParPerso = {}; - handouts.forEach(parseHandout); + recomputeAllies(); } else if (hand) { parseHandout(hand); } } - //pour se débarasser des balises html + //pour se d\xE9barasser des balises html // et avoir un tableau de lignes function linesOfNote(note) { note = note.trim(); @@ -25903,7 +26239,7 @@ var COFantasy = COFantasy || function() { return c.get('name').trim() == name; }); if (charsWithName.length === 0) { - log(name + " dans l'équipe " + nomEquipe + " est inconnu"); + log(name + " dans l'\xE9quipe " + nomEquipe + " est inconnu"); return; } if (charsWithName.length > 1) { @@ -25912,7 +26248,7 @@ var COFantasy = COFantasy || function() { }); if (nonArch.length > 0) charsWithName = nonArch; if (charsWithName.length > 1) { - log(name + " dans l'équipe " + nomEquipe + " est en double"); + log(name + " dans l'\xE9quipe " + nomEquipe + " est en double"); } } charsWithName.forEach(function(character) { @@ -25927,7 +26263,9 @@ var COFantasy = COFantasy || function() { if (handName.startsWith("Equipe ")) { hand.get('notes', function(note) { // asynchronous const persos = charactersInHandout(note, handName); + let attaqueEnMeute = false; persos.forEach(function(charId) { + attaqueEnMeute = attaqueEnMeute || charPredicateAsBool(charId, 'attaqueEnMeute'); let ancien = alliesParPerso[charId]; if (ancien === undefined) { ancien = new Set(); @@ -25939,8 +26277,13 @@ var COFantasy = COFantasy || function() { }); //On ajoute les familiers }); + if (attaqueEnMeute) { + persos.forEach(function(charId) { + alliesDAttaqueEnMeute.add(charId); + }); + } }); //end hand.get('notes') - } else if (handName == 'Compétences' || handName == 'Competences') { + } else if (handName == 'Comp\xE9tences' || handName == 'Competences') { listeCompetences = { FOR: { list: [], @@ -25969,7 +26312,7 @@ var COFantasy = COFantasy || function() { nombre: 0 }; hand.get('notes', function(note) { // asynchronous - let carac; //La carac dont on spécifie les compétences actuellement + let carac; //La carac dont on sp\xE9cifie les comp\xE9tences actuellement let lignes = linesOfNote(note); lignes.forEach(function(ligne) { ligne = ligne.trim(); @@ -25982,7 +26325,7 @@ var COFantasy = COFantasy || function() { } if (ligne.length === 0) return; if (carac === undefined) { - error("Compétences sans caractéristique associée", note); + error("Comp\xE9tences sans caract\xE9ristique associ\xE9e", note); return; } let comps = ligne.split(/, |\/| /); @@ -26018,7 +26361,7 @@ var COFantasy = COFantasy || function() { } //options peut contenir: - // - ligneOptions : une chaîne de caractères à ajouter aux attaques + // - ligneOptions : une cha\xEEne de caract\xE8res \xE0 ajouter aux attaques // - target : l'id de la cible des attaques // - nePasAfficherArmes : quand on affiche plus tard l'arme en main function listeAttaquesVisibles(perso, options) { @@ -26026,7 +26369,7 @@ var COFantasy = COFantasy || function() { let ligneOptions = options.ligneOptions || ''; let target = options.target || '@{target|token_id}'; let ligne = ''; - //Cherche toutes les attaques à afficher + //Cherche toutes les attaques \xE0 afficher let attaques = listAllAttacks(perso); let attaquesTriees = []; let attaquesNonTriees = {}; @@ -26034,7 +26377,7 @@ var COFantasy = COFantasy || function() { let att = attaques[attLabel]; if (fieldAsInt(att, 'armeactionvisible', 1) === 0) continue; if (options.nePasAfficherArmes && estArme(att)) continue; - //Vérification que des options n'empêchent pas l'utilisation de l'attaque + //V\xE9rification que des options n'emp\xEAchent pas l'utilisation de l'attaque let attackOptions = ' ' + fieldAsString(att, 'armeoptions', ''); if (actionImpossible(perso, attackOptions.split(' --'), attLabel)) continue; //On regarde aussi si c'est une arme de jet @@ -26053,14 +26396,14 @@ var COFantasy = COFantasy || function() { for (let label in attaquesNonTriees) { ligne += attaquesNonTriees[label] + '
    '; } - //On ajoute aussi les lancers de feu grégeois, si il y en a - let attrFeuxGregeois = tokenAttribute(perso, 'elixir_feu_grégeois'); + //On ajoute aussi les lancers de feu gr\xE9geois, si il y en a + let attrFeuxGregeois = tokenAttribute(perso, 'elixir_feu_gr\xE9geois'); if (attrFeuxGregeois.length > 0) { attrFeuxGregeois = attrFeuxGregeois[0]; let feuxGregeois = parseInt(attrFeuxGregeois.get('current')); if (feuxGregeois > 0) { let command = attrFeuxGregeois.get('max').trim(); - ligne += bouton(command, 'Feu grégeois', perso, { + ligne += bouton(command, 'Feu gr\xE9geois', perso, { ressource: attrFeuxGregeois }); ligne += " (reste " + feuxGregeois + ")
    "; @@ -26123,13 +26466,13 @@ var COFantasy = COFantasy || function() { return res; } - //Si listActions est fourni, ça peut faire référence à une ability + //Si listActions est fourni, \xE7a peut faire r\xE9f\xE9rence \xE0 une ability //dont le nom commence et termine par #, contenant une liste d'actions - //à afficher - //sinon, fait référence à une des listes d'action de la fiche + //\xE0 afficher + //sinon, fait r\xE9f\xE9rence \xE0 une des listes d'action de la fiche function turnAction(perso, playerId, listActions) { const pageId = perso.token.get('pageid'); - // Toutes les Abilities du personnage lié au Token + // Toutes les Abilities du personnage li\xE9 au Token const abilities = findObjs({ _type: 'ability', _characterid: perso.charId, @@ -26156,7 +26499,7 @@ var COFantasy = COFantasy || function() { if (actionsDuTour === 0) { if (!isActive(perso)) { if (!getState(perso, 'surpris') || !compagnonPresent(perso, 'surveillance')) { - sendPerso(perso, "ne peut pas agir à ce tour"); + sendPerso(perso, "ne peut pas agir \xE0 ce tour"); return true; } } @@ -26172,23 +26515,23 @@ var COFantasy = COFantasy || function() { } } } - //actionDuTour peut être undefined, pour la liste par défaut + //actionDuTour peut \xEAtre undefined, pour la liste par d\xE9faut let actionsAAfficher; let ligne = ''; let command = ''; if (actionsParDefaut && !stateCOF.chargeFantastique && attributeAsBool(perso, 'hate')) { - ligne += "Effet de hâte : une action d'attaque ou de mouvement en plus
    "; + ligne += "Effet de h\xE2te : une action d'attaque ou de mouvement en plus
    "; } if (actionsParDefaut && !stateCOF.chargeFantastique && attributeAsBool(perso, 'reactionViolente')) { - ligne += "Crise de folie : doit attaquer la personne qui l'a provoqué et ceux qui l'en empêchent.
    "; + ligne += "Crise de folie : doit attaquer la personne qui l'a provoqu\xE9 et ceux qui l'en emp\xEAchent.
    "; ligne += boutonSimple('!cof-fin-reaction-violente ' + perso.token.id, "Prendre sur soi"); } - //Les dégâts aux personnages enveloppés par perso + //Les d\xE9g\xE2ts aux personnages envelopp\xE9s par perso let attrs_enveloppe = tokenAttribute(perso, 'enveloppe'); attrs_enveloppe.forEach(function(a) { let cible = persoOfIdName(a.get('current'), pageId); if (cible === undefined) { - error("Attribut d'enveloppe mal formé ou obsolète", a.get('current')); + error("Attribut d'enveloppe mal form\xE9 ou obsol\xE8te", a.get('current')); a.remove(); return; } @@ -26202,23 +26545,23 @@ var COFantasy = COFantasy || function() { command = abEnveloppe.get('action').trim(); command = replaceAction(command, perso); command = command.replace(new RegExp(escapeRegExp('@{target|token_id}'), 'g'), cible.token.id); - ligne += bouton(command, "Infliger DMS à " + nomPerso(cible), perso) + '
    '; + ligne += bouton(command, "Infliger DMS \xE0 " + nomPerso(cible), perso) + '
    '; } } else if (enveloppeDM.startsWith('label ')) { actionsAAfficher = true; command = '!cof-attack ' + perso.token.id + ' ' + cible.token.id + ' ' + enveloppeDM.substring(6) + ' --auto --acide --effet paralyseTemp [[2d6]] --save CON 15'; - ligne += bouton(command, "Infliger DMs à " + nomPerso(cible), perso) + '
    '; + ligne += bouton(command, "Infliger DMs \xE0 " + nomPerso(cible), perso) + '
    '; } else if (enveloppeDM.startsWith('etreinte ')) { actionsAAfficher = true; enveloppeDM = enveloppeDM.substring(9); - command = '!cof-attack ' + perso.token.id + ' ' + cible.token.id + ' --dm ' + enveloppeDM + ' --auto --nom étreinte '; - ligne += bouton(command, "Infliger DMs à " + nomPerso(cible), perso) + '
    '; + command = '!cof-attack ' + perso.token.id + ' ' + cible.token.id + ' --dm ' + enveloppeDM + ' --auto --nom \xE9treinte '; + ligne += bouton(command, "Infliger DMs \xE0 " + nomPerso(cible), perso) + '
    '; } //else pas reconnu - //On ajoute aussi un bouton pour libérer + //On ajoute aussi un bouton pour lib\xE9rer command = '!cof-echapper-enveloppement libere --target ' + cible.token.id; - ligne += boutonSimple(command, "Libérer " + nomPerso(cible)) + '
    '; + ligne += boutonSimple(command, "Lib\xE9rer " + nomPerso(cible)) + '
    '; }); - //Bouton pour libérer une personne qu'on agrippe + //Bouton pour lib\xE9rer une personne qu'on agrippe let attrs_agrippe = tokenAttribute(perso, 'agrippe'); attrs_agrippe = attrs_agrippe.concat( @@ -26232,7 +26575,7 @@ var COFantasy = COFantasy || function() { return; } command = '!cof-liberer-agrippe ' + cible.token.id + ' libere'; - ligne += boutonSimple(command, "Libérer " + nomPerso(cible)) + '
    '; + ligne += boutonSimple(command, "Lib\xE9rer " + nomPerso(cible)) + '
    '; }); let gobePar; let attrGobePar = tokenAttribute(perso, 'estGobePar'); @@ -26245,18 +26588,18 @@ var COFantasy = COFantasy || function() { if (!gobePar && attributeAsBool(perso, 'enveloppePar')) { actionsAAfficher = true; command = '!cof-echapper-enveloppement --target ' + perso.token.id; - ligne += boutonSimple(command, 'Se libérer') + '
    '; + ligne += boutonSimple(command, 'Se lib\xE9rer') + '
    '; } else if (getState(perso, 'enseveli')) { actionsAAfficher = true; ligne += boutonSaveState(perso, 'enseveli') + '
    '; } else if (!gobePar && attributeAsBool(perso, 'etreinteScorpionPar')) { actionsAAfficher = true; command = '!cof-liberer-agrippe ' + perso.token.id; - ligne += boutonSimple(command, 'Se libérer') + "de l'étreinte du scorpion
    "; + ligne += boutonSimple(command, 'Se lib\xE9rer') + "de l'\xE9treinte du scorpion
    "; } else if (!gobePar && attributeAsBool(perso, 'estEcrasePar')) { actionsAAfficher = true; command = '!cof-liberer-ecrase ' + perso.token.id; - ligne += boutonSimple(command, 'Se libérer') + "de l'étreinte
    "; + ligne += boutonSimple(command, 'Se lib\xE9rer') + "de l'\xE9treinte
    "; } else { //On affiche les actions normales if (stateCOF.combat && stateCOF.combat.armeesDesMorts && !gobePar) { let combattreArmee = false; @@ -26264,7 +26607,7 @@ var COFantasy = COFantasy || function() { if (aid == perso.token.id) continue; let persoArmee = stateCOF.combat.armeesDesMorts[aid]; if (!persoArmee || !persoArmee.token) { - error("Erreur dans l'armée des morts", stateCOF.combat.armeesDesMorts); + error("Erreur dans l'arm\xE9e des morts", stateCOF.combat.armeesDesMorts); delete stateCOF.combat.armeesDesMorts[aid]; continue; } @@ -26286,12 +26629,12 @@ var COFantasy = COFantasy || function() { if (!gobePar && (attributeAsBool(perso, 'estAgrippePar') || attributeAsBool(perso, 'estDevorePar'))) { actionsAAfficher = true; command = '!cof-liberer-agrippe ' + perso.token.id; - ligne += bouton(command, 'Se libérer', perso) + '(action de mvt)
    '; + ligne += bouton(command, 'Se lib\xE9rer', perso) + '(action de mvt)
    '; } if (!gobePar && attributeAsBool(perso, 'etreinteImmolePar')) { actionsAAfficher = true; command = '!cof-liberer-agrippe ' + perso.token.id; - ligne += bouton(command, 'Se libérer', perso) + ' (action limitée)
    '; + ligne += bouton(command, 'Se lib\xE9rer', perso) + ' (action limit\xE9e)
    '; } //Actions pour les saves actifs let attrs = findObjs({ @@ -26330,7 +26673,7 @@ var COFantasy = COFantasy || function() { let cible = persoOfIdName(a.get('current')); if (cible) { let commande = "!cof-attack " + perso.token.id + ' ' + cible.token.id + ' ' + ecraser; - ligne += boutonSimple(commande, 'Écraser') + ' ' + nomPerso(cible) + '
    '; + ligne += boutonSimple(commande, '\xC9craser') + ' ' + nomPerso(cible) + '
    '; } else { a.remove(); } @@ -26359,7 +26702,7 @@ var COFantasy = COFantasy || function() { c = command + " Morsure --toucher " + atk + " --dm 1d6+" + force; ligne += bouton(c, 'Morsure', perso) + '
    '; } - //On cherche si il y a une armée conjurée à attaquer + //On cherche si il y a une arm\xE9e conjur\xE9e \xE0 attaquer let attrs_armee = findObjs({ _type: 'attribute', @@ -26394,42 +26737,42 @@ var COFantasy = COFantasy || function() { if (allies.has(perso.charId)) return; allTokens.forEach(function(t) { if (t.get('represents') == aacid) { - //teste si dans un carré de 20 m de coté autour de l'armée. + //teste si dans un carr\xE9 de 20 m de cot\xE9 autour de l'arm\xE9e. let tx = t.get('left'); let ty = t.get('top'); if (tx < pxp && tx > pxm && ty < pyp && ty > pym) { command = '!cof-attack ' + perso.token.id + ' ' + t.id + - " Attaque de l'armée --dm " + + " Attaque de l'arm\xE9e --dm " + (ficheAttributeAsInt(perso, 'niveau', 1) + 1) + " --auto --attaqueArmeeConjuree --allonge 20"; - ligne += bouton(command, "Attaque de l'armée", perso) + '
    '; + ligne += bouton(command, "Attaque de l'arm\xE9e", perso) + '
    '; } } }); }); } - //Les soins pour les élémentaires + //Les soins pour les \xE9l\xE9mentaires if (predicateAsBool(perso, 'corpsElementaire')) { command = '!cof-soin 5'; - ligne += bouton(command, "Régénération", perso) + " si source élémentaire proche
    "; + ligne += bouton(command, "R\xE9g\xE9n\xE9ration", perso) + " si source \xE9l\xE9mentaire proche
    "; } - //Regard pétrifiant + //Regard p\xE9trifiant let regardPetrifiant = predicateAsInt(perso, 'regardPetrifiant', 0, 16); if (regardPetrifiant) { let c = '!cof-effet petrifie --lanceur ' + perso.token.id + ' --target @{target|token_id} --regard --save CON '; - ligne += boutonSimple(c + (regardPetrifiant - 4), "Regard pétrifiant") + + ligne += boutonSimple(c + (regardPetrifiant - 4), "Regard p\xE9trifiant") + boutonSimple(c + regardPetrifiant, "(inconscient)") + '
    '; } - //Violence ciblée + //Violence cibl\xE9e if (predicateAsBool(perso, 'violenceCiblee') && !attributeAsBool(perso, 'reactionViolente')) { let pointsDeViolence = attributeAsInt(perso, 'pointsDeViolence', 0); if (pointsDeViolence > 0) { let attr = tokenAttribute(perso, 'pointsDeViolence')[0]; command = "!cof-effet-temp reactionViolente [[1d4]] --decrAttribute " + attr.id + " --target " + perso.token.id; - ligne += boutonSimple(command, 'Violence ciblée') + '
    '; + ligne += boutonSimple(command, 'Violence cibl\xE9e') + '
    '; } } - //Les attaques de la fiche à afficher dans la liste d'actions + //Les attaques de la fiche \xE0 afficher dans la liste d'actions const montrerAttaques = ficheAttributeAsInt(perso, 'montrerattaques', 1); const afficherAttaquesFiche = actionsParDefaut || @@ -26442,7 +26785,7 @@ var COFantasy = COFantasy || function() { attackOptions.nePasAfficherArmes = true; ligne += listeAttaquesVisibles(perso, attackOptions); } - //L'arme en main et dégainer, si besoin + //L'arme en main et d\xE9gainer, si besoin if (montrerArmeEnMain && armesAutorisees) { let { listeAttaques, @@ -26473,7 +26816,7 @@ var COFantasy = COFantasy || function() { else nomCommande += ' (1M)'; } if (attributeAsBool(perso, 'paradeCroisee')) { - //On connaîtra vraiment l'arme au moment de faire l'attaque + //On conna\xEEtra vraiment l'arme au moment de faire l'attaque command += '-1'; if (labelArmeGauche && listeAttaques[labelArmeGauche]) { @@ -26482,6 +26825,7 @@ var COFantasy = COFantasy || function() { } } else { command += labelArmePrincipale; + if (armeDechargee(perso, armePrincipale)) nomCommande += ' (vide)'; } ligneArmePrincipale = bouton(command, nomCommande, perso); } else if (!possedeAttaqueNaturelle) { @@ -26493,13 +26837,15 @@ var COFantasy = COFantasy || function() { } } if (perso.armeGauche) { - ligneArmeGauche = bouton("!cof-attack @{selected|token_id} @{target|token_id} " + labelArmeGauche, perso.armeGauche.name, perso); + let nomCommande = perso.armeGauche.name; + if (armeDechargee(perso, perso.armeGauche)) nomCommande += ' (vide)'; + ligneArmeGauche = bouton("!cof-attack @{selected|token_id} @{target|token_id} " + labelArmeGauche, nomCommande, perso); } - //Maintenant on propose de dégainer + //Maintenant on propose de d\xE9gainer if (armeVisible) { let degainer = "!cof-degainer ?{Arme?|"; let armeADegainer; - //Prise en compte des prédicats pour ce qu'on veut voir en premier + //Prise en compte des pr\xE9dicats pour ce qu'on veut voir en premier let i = 1; let labelsVus = new Set(); while (true) { @@ -26513,12 +26859,12 @@ var COFantasy = COFantasy || function() { if (label == labelArmePrincipale || labelGauche == labelArmeGauche) continue; let arme = armes[label]; if (arme === undefined) { - error("Impossible de trouver l'arme de label " + label + " mentionnée dans le prédicat actionDegainer" + (i - 1), armes); + error("Impossible de trouver l'arme de label " + label + " mentionn\xE9e dans le pr\xE9dicat actionDegainer" + (i - 1), armes); continue; } let armeGauche = armes[labelGauche]; if (armeGauche === undefined) { - error("Impossible de trouver l'arme de label " + labelGauche + " mentionnée dans le prédicat actionDegainer" + (i - 1), armes); + error("Impossible de trouver l'arme de label " + labelGauche + " mentionn\xE9e dans le pr\xE9dicat actionDegainer" + (i - 1), armes); continue; } degainer += arme.armenom + " et " + armeGauche.armenom + "," + label + ' ' + labelGauche + "|"; @@ -26532,7 +26878,7 @@ var COFantasy = COFantasy || function() { if (labels == labelArmePrincipale || labels == labelArmeGauche) continue; let arme = armes[labels]; if (arme === undefined) { - error("Impossible de trouver l'arme de label " + labels + " mentionnée dans le prédicat actionDegainer" + (i - 1), armes); + error("Impossible de trouver l'arme de label " + labels + " mentionn\xE9e dans le pr\xE9dicat actionDegainer" + (i - 1), armes); continue; } labelsVus.add(labels); @@ -26562,9 +26908,13 @@ var COFantasy = COFantasy || function() { } else if (l != labelArmePrincipale && l != labelArmeGauche && !labelsVus.has(l)) { degainer += armes[l].armenom; let pred = armes[l].armepredicats; - if (pred && pred.includes('batarde')) { - degainer += " (2M)," + l + " 2mains|" + - armes[l].armenom + " (1M)"; + if (pred) { + if (pred.includes('batarde')) { + degainer += " (2M)," + l + " 2mains|" + + armes[l].armenom + " (1M)"; + } + if (pred.includes('charge') && attributeAsInt(perso, 'charge_' + l, 1) === 0) + degainer += ' (vide)'; } degainer += "," + l + "|"; if (armeADegainer) armeADegainer.unique = undefined; @@ -26584,7 +26934,7 @@ var COFantasy = COFantasy || function() { else degainer += "son arme"; degainer += ",&#32;}"; } else if (armeADegainer.unique) { - //Dans ce cas, pas de choix, juste une arme à dégainer + //Dans ce cas, pas de choix, juste une arme \xE0 d\xE9gainer degainer = '!cof-degainer ' + armeADegainer.label; } else { degainer = degainer.substr(0, degainer.length - 1) + '}'; @@ -26593,7 +26943,7 @@ var COFantasy = COFantasy || function() { if (ligneArmePrincipale) ligneArmePrincipale += bouton(degainer, ';', perso); else - ligneArmePrincipale = bouton(degainer, 'Dégainer', perso); + ligneArmePrincipale = bouton(degainer, 'D\xE9gainer', perso); if (armeADegainer.unique && !labelArmePrincipale && !labelArmeGauche) ligneArmePrincipale += armeADegainer.nom; } else { @@ -26602,6 +26952,13 @@ var COFantasy = COFantasy || function() { } if (ligneArmePrincipale) ligne += ligneArmePrincipale + '
    '; if (ligneArmeGauche) ligne += ligneArmeGauche + '
    '; + // Le tir de semonce, si disponible et qu'on tient une arme \xE0 distance + if (predicateAsBool(perso, 'tirDeSemonce') && armePrincipale && + armePrincipale.portee > 0 && + attributeAsInt(perso, 'attaqueADistanceRatee', 0) == 1) { + command = '!cof-attack ' + perso.token.id + ' @{target|token_id} -1 --semonce'; + ligne += bouton(command, "Tir de semonce (L)", perso) + '
    '; + } } //L'action de traverser pour un cyclone if (attributeAsBool(perso, 'cyclone')) { @@ -26620,29 +26977,32 @@ var COFantasy = COFantasy || function() { ligne += bouton(command, 'Second souffle', perso) + '
    '; } } - //Changement de phase pour intangibilité avec changement de phase + //Changement de phase pour intangibilit\xE9 avec changement de phase if (attributeAsBool(perso, 'intangiblePuissant')) { if (attributeAsInt(perso, 'intangibleValeur', 1)) { command = "!cof-set-attribute intangibleValeur 0 --target " + perso.token.id + " --message redevient tangible"; ligne += boutonSimple(command, "Redevenir tangible") + '
    '; } else { - command = "!cof-set-attribute intangibleValeur 1 --target " + perso.token.id + " --message devient légèrement translucide"; + command = "!cof-set-attribute intangibleValeur 1 --target " + perso.token.id + " --message devient l\xE9g\xE8rement translucide"; ligne += boutonSimple(command, "Redevenir intangible") + '
    '; } } if (attributeAsBool(perso, 'intangibleInvisiblePuissant')) { if (attributeAsInt(perso, 'intangibleInvisibleValeur', 1)) { - command = "!cof-set-attribute intangibleInvisibleValeur 0 --etat invisible false --target " + perso.token.id + " --message réapparaît"; + command = "!cof-set-attribute intangibleInvisibleValeur 0 --etat invisible false --target " + perso.token.id + " --message r\xE9appara\xEEt"; ligne += boutonSimple(command, "Redevenir tangible") + '
    '; } else { - command = "!cof-set-attribute intangibleInvisibleValeur 1 --etat invisible true --target " + perso.token.id + " --message disparaît"; + command = "!cof-set-attribute intangibleInvisibleValeur 1 --etat invisible true --target " + perso.token.id + " --message dispara\xEEt"; ligne += boutonSimple(command, "Redevenir intangible") + '
    '; } } //La liste d'action proprement dite actionsAAfficher = treatActions(perso, actionsDuTour, abilities, function(command, text, macros, attackStats) { if (command == 'liste des attaques') { - let attackOptions = {}; + //Dans ce cas, attackStats est une chaine d'options \xE0 ajouter + let attackOptions = { + ligneOptions: attackStats + }; if (gobePar) attackOptions.target = gobePar.token.id; ligne += listeAttaquesVisibles(perso, attackOptions); } else { @@ -26663,7 +27023,7 @@ var COFantasy = COFantasy || function() { if (caracDM > 0) command += '+' + caracDM; else if (caracDM < 0) command += caracDM; command += "--energie --magique --limiteParTour 1 runeIsulys --effet affaibli 1"; - ligne += bouton(command, "Rayon d'énergie", perso) + '
    '; + ligne += bouton(command, "Rayon d'\xE9nergie", perso) + '
    '; } command = "!cof-gerer-runes-mortes " + perso.token.id; ligne += boutonSimple(command, "Gestion des runes mortes") + '
    '; @@ -26673,8 +27033,8 @@ var COFantasy = COFantasy || function() { command = "!cof-attendre ?{Nouvelle initiative}"; ligne += bouton(command, 'Attendre', perso) + '
    '; if (!gobePar && !charAttributeAsBool(perso, 'armeeConjuree')) { - command = "!cof-action-defensive ?{Action défensive|simple|totale}"; - ligne += bouton(command, 'Se défendre', perso) + '
    '; + command = "!cof-action-defensive ?{Action d\xE9fensive|simple|totale}"; + ligne += bouton(command, 'Se d\xE9fendre', perso) + '
    '; let manoeuvreDuelliste = predicateAsBool(perso, 'manoeuvreDuelliste'); if (manoeuvreDuelliste) { command = "!cof-manoeuvre @{selected|token_id} @{target|token_id} ?{Manoeuvre?|bloquer|desarmer|renverser|tenirADistance|repousser}"; @@ -26700,9 +27060,9 @@ var COFantasy = COFantasy || function() { } } if (actionsAAfficher) { - // on envoie la liste aux joueurs qui gèrent le personnage dont le token est lié + // on envoie la liste aux joueurs qui g\xE8rent le personnage dont le token est li\xE9 let lastPlayerid; - // on récupère les players_ids qui controllent le Token + // on r\xE9cup\xE8re les players_ids qui controllent le Token let playerIds; if (playerId) playerIds = [playerId]; else playerIds = getPlayerIds(perso); @@ -26743,17 +27103,17 @@ var COFantasy = COFantasy || function() { let actions = turnAction(perso, playerId, liste); if (!actions) { let l = liste || ''; - sendPerso(perso, "n'a pas de liste d'actions " + l + " définie"); + sendPerso(perso, "n'a pas de liste d'actions " + l + " d\xE9finie"); } }); - }); + }, options); } function removeDernieresCiblesAttaquees(perso, evt) { let attrDernieresCibles = tokenAttribute(perso, 'dernieresCiblesAttaquees'); if (attrDernieresCibles.length > 0) { attrDernieresCibles = attrDernieresCibles[0]; - if (predicateAsBool(perso, 'attaqueEnMeute')) { + if (predicateAsBool(perso, 'attaqueEnMeute') || alliesDAttaqueEnMeute.has(perso.charId)) { let dernieresCibles = attrDernieresCibles.get('current'); let cibles = new Set(dernieresCibles.split(' ')); cibles.forEach(function(ci) { @@ -26832,7 +27192,7 @@ var COFantasy = COFantasy || function() { return res; } - //ne rajoute pas evt à l'historique + //ne rajoute pas evt \xE0 l'historique function setTurnOrder(to, evt) { if (to.pasAgi.length > 0) { to.pasAgi.sort(function(a, b) { @@ -26840,8 +27200,8 @@ var COFantasy = COFantasy || function() { if (b.id == "-1") return -1; if (a.pr < b.pr) return 1; if (b.pr < a.pr) return -1; - // Priorité aux joueurs - // Premier critère : la barre de PV des joueurs est liée + // Priorit\xE9 aux joueurs + // Premier crit\xE8re : la barre de PV des joueurs est li\xE9e let tokenA = getObj('graphic', a.id); if (tokenA === undefined) return 1; let tokenB = getObj('graphic', b.id); @@ -26851,7 +27211,7 @@ var COFantasy = COFantasy || function() { return 1; } if (tokenB.get('bar1_link') === '') return -1; - // Deuxième critère : les joueurs ont un DV + // Deuxi\xE8me crit\xE8re : les joueurs ont un DV let charIdA = tokenA.get('represents'); if (charIdA === '') return 1; let charIdB = tokenB.get('represents'); @@ -26871,7 +27231,7 @@ var COFantasy = COFantasy || function() { return 1; } if (dvB === 0) return -1; - //Entre joueurs, priorité à la plus grosse sagesse + //Entre joueurs, priorit\xE9 \xE0 la plus grosse sagesse let sagA = caracCourante(persoA, 'sagesse'); let sagB = caracCourante(persoB, 'sagesse'); if (sagA < sagB) return 1; @@ -26893,17 +27253,17 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected) { if (selected === undefined || selected.length === 0) { - error("La fonction !cof-attendre : rien à faire, pas de token selectionné", msg); + error("La fonction !cof-attendre : rien \xE0 faire, pas de token selectionn\xE9", msg); return; } let cmd = msg.content.split(' '); if (cmd.length < 2) { - error("Attendre jusqu'à quelle initiative ?", cmd); + error("Attendre jusqu'\xE0 quelle initiative ?", cmd); return; } let newInit = parseInt(cmd[1]); if (isNaN(newInit) || newInit < 1) { - error("On ne peut attendre que jusqu'à une initiative de 1", cmd); + error("On ne peut attendre que jusqu'\xE0 une initiative de 1", cmd); newInit = 1; } let evt = { @@ -26918,7 +27278,7 @@ var COFantasy = COFantasy || function() { return (elt.id == token.id); }); if (tokenPos == -1) { // token ne peut plus agir - sendPerso(perso, " a déjà agit ce tour"); + sendPerso(perso, " a d\xE9j\xE0 agit ce tour"); return; } if (newInit < to.pasAgi[tokenPos].pr) { @@ -26926,7 +27286,7 @@ var COFantasy = COFantasy || function() { sendPerso(perso, " attend un peu avant d'agir..."); updateNextInit(perso); } else { - sendPerso(perso, " a déjà une initiative inférieure à " + newInit); + sendPerso(perso, " a d\xE9j\xE0 une initiative inf\xE9rieure \xE0 " + newInit); } }); setTurnOrder(to, evt); @@ -26934,22 +27294,22 @@ var COFantasy = COFantasy || function() { }); } - // Affiche des informations sur le personnage sélectionné + // Affiche des informations sur le personnage s\xE9lectionn\xE9 function statut(msg) { getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Dans !cof-statut : rien à faire, pas de token selectionné", msg); + error("Dans !cof-statut : rien \xE0 faire, pas de token selectionn\xE9", msg); return; } iterSelected(selected, function(perso) { - //Au cas où + //Au cas o\xF9 unlockToken(perso); const token = perso.token; const charId = perso.charId; const name = nomPerso(perso); let lie = true; if (token.get('bar1_link') === '') lie = false; - const display = startFramedDisplay(playerId, "État de " + name, perso, { + const display = startFramedDisplay(playerId, "\xC9tat de " + name, perso, { chuchote: true }); const estPNJ = persoEstPNJ(perso); @@ -26969,7 +27329,7 @@ var COFantasy = COFantasy || function() { hasMana = !isNaN(manaMax) && manaMax > 0; } let dmTemp = parseInt(token.get('bar2_value')); - if (hasMana) { //ne peut pas être un PNJ + if (hasMana) { //ne peut pas \xEAtre un PNJ if (lie) { dmTemp = ficheAttributeAsInt(perso, 'DMTEMP', 0); } else { @@ -26988,7 +27348,7 @@ var COFantasy = COFantasy || function() { } let douleurIgnoree = attributeAsInt(perso, 'douleurIgnoree', 0); if (douleurIgnoree > 0) { - line = "a ignoré " + douleurIgnoree + " pv dans ce combat."; + line = "a ignor\xE9 " + douleurIgnoree + " pv dans ce combat."; addLineToFramedDisplay(display, line); } let aDV = ficheAttributeAsInt(perso, 'DV', 0); @@ -26996,7 +27356,7 @@ var COFantasy = COFantasy || function() { let pr = pointsDeRecuperation(perso); if (pr) { line = - "Points de récupération : " + pr.current + " / " + pr.max; + "Points de r\xE9cup\xE9ration : " + pr.current + " / " + pr.max; addLineToFramedDisplay(display, line); } if (ficheAttributeAsInt(perso, 'option_pc', 1)) { @@ -27042,7 +27402,7 @@ var COFantasy = COFantasy || function() { if (att.armespec && predicateOfRaw(att.armespec).charge) { let charge = attributeAsInt(perso, 'charge_' + armeLabel, 0); if (charge === 0) { - line = nomArme + " n'est pas chargé"; + line = nomArme + " n'est pas charg\xE9"; } else { let na = fullAttributeName(perso, 'chargeGrenaille_' + armeLabel); let grenaille = attrsChar.find(function(a) { @@ -27053,7 +27413,7 @@ var COFantasy = COFantasy || function() { if (isNaN(grenaille) || grenaille < 0) grenaille = 0; } else grenaille = 0; if (charge == 1) { - line = nomArme + " est chargé"; + line = nomArme + " est charg\xE9"; if (grenaille) line += " de grenaille"; } else if (charge > 1) { line = nomArme + " contient encore " + charge + " charges"; @@ -27068,7 +27428,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, line); } else if (armeEnMain == armeLabel) { if (armeEnMainGauche == armeLabel) { - addLineToFramedDisplay(display, "tient " + nomArme + " à 2 mains."); + addLineToFramedDisplay(display, "tient " + nomArme + " \xE0 2 mains."); } else { addLineToFramedDisplay(display, "tient " + nomArme + " en main."); } @@ -27086,8 +27446,8 @@ var COFantasy = COFantasy || function() { if (attrEnveloppe.length > 0) { let cube = persoOfIdName(attrEnveloppe[0].get('current')); if (cube) { - let actE = "est enveloppé dans "; - if ((attrEnveloppe[0].get('max') + '').startsWith('etreinte')) actE = "est prisonnier de l'étreinte de "; + let actE = "est envelopp\xE9 dans "; + if ((attrEnveloppe[0].get('max') + '').startsWith('etreinte')) actE = "est prisonnier de l'\xE9treinte de "; addLineToFramedDisplay(display, actE + cube.tokName); } } @@ -27098,7 +27458,7 @@ var COFantasy = COFantasy || function() { let defenseMontree; let bufDef = attributeAsInt(perso, 'bufDEF', 0); if (bufDef > 0) { - addLineToFramedDisplay(display, "Défense temporairement modifiée de " + bufDef + " (DEF " + defense + ")"); + addLineToFramedDisplay(display, "D\xE9fense temporairement modifi\xE9e de " + bufDef + " (DEF " + defense + ")"); defenseMontree = true; } for (let etat in cof_states) { @@ -27118,13 +27478,13 @@ var COFantasy = COFantasy || function() { let possedeArmure = ficheAttributeAsInt(perso, 'defarmure', 0) > 0; if (possedeArmure) addLineToFramedDisplay(display, "Ne porte pas son armure"); if (predicateAsInt(perso, 'vetementsSacres', 0) > 0) { - if (possedeArmure) addLineToFramedDisplay(display, " mais bénéficie de ses vêtements sacrés (DEF " + defense + ")"); - else addLineToFramedDisplay(display, "porte des vêtements sacrés (DEF " + defense + ")"); + if (possedeArmure) addLineToFramedDisplay(display, " mais b\xE9n\xE9ficie de ses v\xEAtements sacr\xE9s (DEF " + defense + ")"); + else addLineToFramedDisplay(display, "porte des v\xEAtements sacr\xE9s (DEF " + defense + ")"); defenseMontree = true; } if (predicateAsInt(perso, 'armureDeVent', 0) > 0) { - if (possedeArmure) addLineToFramedDisplay(display, " mais bénéficie de son armure de vent (DEF " + defense + ")"); - else addLineToFramedDisplay(display, "bénéficie de son armure de vent (DEF " + defense + ")"); + if (possedeArmure) addLineToFramedDisplay(display, " mais b\xE9n\xE9ficie de son armure de vent (DEF " + defense + ")"); + else addLineToFramedDisplay(display, "b\xE9n\xE9ficie de son armure de vent (DEF " + defense + ")"); defenseMontree = true; } } @@ -27133,7 +27493,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, "Ne porte pas son bouclier"); if (ficheAttributeAsInt(perso, 'casque_rd', 0)) { if (ficheAttributeAsBool(perso, 'casque_on', false)) { - let b = boutonSimple('!cof-set-attribute casque_on false --message enlève son casque --target ' + perso.token.id, "l'enlever"); + let b = boutonSimple('!cof-set-attribute casque_on false --message enl\xE8ve son casque --target ' + perso.token.id, "l'enlever"); addLineToFramedDisplay(display, "Porte son casque :" + b); } else { let b = boutonSimple('!cof-set-attribute casque_on true --message met son casque --target ' + perso.token.id, "le mettre"); @@ -27190,7 +27550,7 @@ var COFantasy = COFantasy || function() { } let perteDeSubstance = parseInt(attr.get('current')); if (isNaN(perteDeSubstance) || perteDeSubstance < 1) { - error("Attribut de perte de substance mal formé", attr); + error("Attribut de perte de substance mal form\xE9", attr); return; } if (playerIsGM(playerId)) { @@ -27199,21 +27559,21 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, m); } if (perteDeSubstance < 3) { - addLineToFramedDisplay(display, "Dans le noir, on peut distinguer les lumières vives au travers de son corps"); + addLineToFramedDisplay(display, "Dans le noir, on peut distinguer les lumi\xE8res vives au travers de son corps"); } else if (perteDeSubstance < 5) { - addLineToFramedDisplay(display, "Le soleil diffuse à travers le corps à contre-jour"); + addLineToFramedDisplay(display, "Le soleil diffuse \xE0 travers le corps \xE0 contre-jour"); } else if (perteDeSubstance < 7) { - addLineToFramedDisplay(display, "On peut distinguer les objets à travers ses mains, et sa couleur s'estompe"); + addLineToFramedDisplay(display, "On peut distinguer les objets \xE0 travers ses mains, et sa couleur s'estompe"); } else if (perteDeSubstance < 10) { addLineToFramedDisplay(display, "Est translucide comme une eau sale"); } else if (perteDeSubstance < 15) { addLineToFramedDisplay(display, "Est aussi transparent que de l'eau et n'a plus faim ni soif"); } else { - addLineToFramedDisplay(display, "A perdu sa substance : impossible de tenir un objet et possibilité de passer à travers des obstacles"); + addLineToFramedDisplay(display, "A perdu sa substance : impossible de tenir un objet et possibilit\xE9 de passer \xE0 travers des obstacles"); } } }); - //ancienne version de munitions, obsolète depuis mars 2023 + //ancienne version de munitions, obsol\xE8te depuis mars 2023 allAttributesNamed(attrsChar, 'munition').forEach(function(attr) { let attrName = attr.get('name'); let underscore = attrName.indexOf('_'); @@ -27228,7 +27588,7 @@ var COFantasy = COFantasy || function() { let postureMsg = "a une posture "; switch (posture.substr(-3, 3)) { case 'DEF': - postureMsg += "défensive"; + postureMsg += "d\xE9fensive"; break; case 'ATT': postureMsg += "offensive"; @@ -27241,10 +27601,10 @@ var COFantasy = COFantasy || function() { postureMsg += " mais "; switch (posture.substr(0, 3)) { case 'DEF': - postureMsg += "risquée"; + postureMsg += "risqu\xE9e"; break; case 'ATT': - postureMsg += "moins précise"; + postureMsg += "moins pr\xE9cise"; break; case 'DM_': postureMsg += "moins puissante"; @@ -27255,7 +27615,7 @@ var COFantasy = COFantasy || function() { } let attaqueAOutrance = attributeAsInt(perso, 'attaqueAOutrance', 0); if (attaqueAOutrance) { - let attaqueAOutranceMsg = "attaque à outrance "; + let attaqueAOutranceMsg = "attaque \xE0 outrance "; switch (attaqueAOutrance) { case 2: attaqueAOutranceMsg += "(-2 DEF, +1D6 DM)"; @@ -27276,10 +27636,10 @@ var COFantasy = COFantasy || function() { if (soinsLegers < rangSoin) { soinsRestants = rangSoin - soinsLegers; if (soinsRestants > 1) soins = 's'; - msgSoins = "peut encore faire " + soinsRestants + " soin" + soins + " léger" + soins; + msgSoins = "peut encore faire " + soinsRestants + " soin" + soins + " l\xE9ger" + soins; addLineToFramedDisplay(display, msgSoins); } else { - addLineToFramedDisplay(display, "ne peut plus faire de soin léger aujourd'hui"); + addLineToFramedDisplay(display, "ne peut plus faire de soin l\xE9ger aujourd'hui"); } if (rangSoin > 1) { let soinsModeres = attributeAsInt(perso, 'soinsModeres', 0); @@ -27287,18 +27647,18 @@ var COFantasy = COFantasy || function() { soinsRestants = rangSoin - soinsModeres; if (soinsRestants > 1) soins = 's'; else soins = ''; - msgSoins = "peut encore faire " + soinsRestants + " soin" + soins + " modéré" + soins; + msgSoins = "peut encore faire " + soinsRestants + " soin" + soins + " mod\xE9r\xE9" + soins; addLineToFramedDisplay(display, msgSoins); } else { - addLineToFramedDisplay(display, "ne peut plus faire de soin modéré aujourd'hui"); + addLineToFramedDisplay(display, "ne peut plus faire de soin mod\xE9r\xE9 aujourd'hui"); } } if (rangSoin > 3) { - let soinsGuerison = attributeAsInt(perso, 'limiteParJour_guérison', 1); + let soinsGuerison = attributeAsInt(perso, 'limiteParJour_gu\xE9rison', 1); if (soinsGuerison > 0) { - addLineToFramedDisplay(display, "peut encore faire " + soinsGuerison + " guérison" + (soinsGuerison > 1 ? 's' : '') + " aujourd'hui"); + addLineToFramedDisplay(display, "peut encore faire " + soinsGuerison + " gu\xE9rison" + (soinsGuerison > 1 ? 's' : '') + " aujourd'hui"); } else { - addLineToFramedDisplay(display, "ne peut plus faire de guérison aujourd'hui"); + addLineToFramedDisplay(display, "ne peut plus faire de gu\xE9rison aujourd'hui"); } } } @@ -27308,7 +27668,7 @@ var COFantasy = COFantasy || function() { } let bonusCouvert = attributeAsInt(perso, 'bonusCouvert'); if (bonusCouvert) { - addLineToFramedDisplay(display, "est à couvert (+" + bonusCouvert + " DEF)"); + addLineToFramedDisplay(display, "est \xE0 couvert (+" + bonusCouvert + " DEF)"); } if (!defenseMontree) { let defenseAffichee = 10; @@ -27321,7 +27681,7 @@ var COFantasy = COFantasy || function() { defenseAffichee += modCarac(perso, 'dexterite'); } if (defense != defenseAffichee) - addLineToFramedDisplay(display, "Défense actuelle : " + defense); + addLineToFramedDisplay(display, "D\xE9fense actuelle : " + defense); } let predicatExpertDuCombat = predicateAsInt(perso, "expertDuCombat", 0); if (stateCOF.combat && predicatExpertDuCombat > 0) { @@ -27333,11 +27693,11 @@ var COFantasy = COFantasy || function() { else nbDesExpertDuCombat_tour_max = 1; let nbDesExpertDuCombat_tour = Math.min(nbDesExpertDuCombat_combat, attributeAsInt(perso, "limiteParTour_expertDuCombat", nbDesExpertDuCombat_tour_max)); - addLineToFramedDisplay(display, "Dés d'expertise du combat :
    " + + addLineToFramedDisplay(display, "D\xE9s d'expertise du combat :
    " + "Tour : " + nbDesExpertDuCombat_tour + "/" + nbDesExpertDuCombat_tour_max + "
    " + "Combat : " + nbDesExpertDuCombat_combat + "/" + nbDesExpertDuCombat_combat_max + "
    "); } - //Affaiblissements de caractéristiques + //Affaiblissements de caract\xE9ristiques allCaracs.forEach(function(carac) { let malus = attributeAsInt(perso, 'affaiblissementde' + carac, 0); if (malus > 0) { @@ -27346,7 +27706,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, ligne); } }); - //Violence ciblée + //Violence cibl\xE9e if (predicateAsBool(perso, 'violenceCiblee')) { let pointsDeViolence = attributeAsInt(perso, 'pointsDeViolence', 0); if (pointsDeViolence > 0) { @@ -27354,7 +27714,7 @@ var COFantasy = COFantasy || function() { } } if (attributeAsBool(perso, 'lumiere')) { - addLineToFramedDisplay(display, "éclaire ou fait de la lumière"); + addLineToFramedDisplay(display, "\xE9claire ou fait de la lumi\xE8re"); } let autresAttributs = predicatesNamed(perso, 'attributsDeStatut'); autresAttributs.forEach(function(attr) { @@ -27376,7 +27736,7 @@ var COFantasy = COFantasy || function() { }); } - //retourne l'id du suivant si le token actuel était en tête de liste + //retourne l'id du suivant si le token actuel \xE9tait en t\xEAte de liste function removeFromTurnTracker(perso, evt) { removeDernieresCiblesAttaquees(perso, evt); let tokenId = perso.token.id; @@ -27460,14 +27820,14 @@ var COFantasy = COFantasy || function() { } if (buf === 0) return; let message = ""; - if (buf > 0) message = "voit sa défense augmenter"; - else message = "voit sa défense baisser"; + if (buf > 0) message = "voit sa d\xE9fense augmenter"; + else message = "voit sa d\xE9fense baisser"; let evt = { type: 'other' }; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour !cof--buf-def", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof--buf-def", playerId); } iterSelected(selected, function(perso) { setTokenAttr(perso, 'bufDEF', buf, evt, { @@ -27476,7 +27836,7 @@ var COFantasy = COFantasy || function() { setToken(perso.token, 'status_blue', buf, evt); }); if (evt.attributes.length === 0) { - error("Pas de cible valide sélectionnée pour !cod-buf-def", msg); + error("Pas de cible valide s\xE9lectionn\xE9e pour !cod-buf-def", msg); return; } addEvent(evt); @@ -27489,11 +27849,11 @@ var COFantasy = COFantasy || function() { }; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour !cof-remove-buf-def", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof-remove-buf-def", playerId); } iterSelected(selected, function(perso) { removeTokenAttr(perso, 'bufDEF', evt, { - msg: "retrouve sa défense normale" + msg: "retrouve sa d\xE9fense normale" }); setToken(perso.token, 'status_blue', false, evt); }); @@ -27565,7 +27925,7 @@ var COFantasy = COFantasy || function() { if (opt.length > 1) { vampirise = parseInt(opt[1]); if (isNaN(vampirise)) { - error("Il faut un pourcentage entier comme argument à --vampirise", opt); + error("Il faut un pourcentage entier comme argument \xE0 --vampirise", opt); vampirise = 100; } } @@ -27579,7 +27939,7 @@ var COFantasy = COFantasy || function() { } options.ignoreRD = parseInt(opt[1]); if (isNaN(options.ignoreRD) || options.ignoreRD < 1) { - log("Pas un nombre positif après --ignoreRD, interprété comme ignore toute la RD"); + log("Pas un nombre positif apr\xE8s --ignoreRD, interpr\xE9t\xE9 comme ignore toute la RD"); options.ignoreRD = undefined; options.ignoreTouteRD = true; } @@ -27587,7 +27947,7 @@ var COFantasy = COFantasy || function() { case 'attaquant': { if (opt.length < 2) { - error("Manque l'id de l'attaquant, option ignorée", optArgs); + error("Manque l'id de l'attaquant, option ignor\xE9e", optArgs); return; } const attaquant = persoOfId(opt[1]); @@ -27595,12 +27955,12 @@ var COFantasy = COFantasy || function() { options.attaquant = attaquant; return; } - error("Attaquant non trouvé", opt); + error("Attaquant non trouv\xE9", opt); return; } case 'titre': if (opt.length < 2) { - error("Il manque le message après --message", text); + error("Il manque le message apr\xE8s --message", text); return; } options.titre = opt.slice(1).join(' '); @@ -27615,13 +27975,13 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("cof-dmg prend les dégats en argument, avant les options", + error("cof-dmg prend les d\xE9gats en argument, avant les options", msg.content); return; } getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "pas de cible trouvée, action annulée", playerId); + sendPlayer(msg, "pas de cible trouv\xE9e, action annul\xE9e", playerId); return; } options.aoe = true; @@ -27632,7 +27992,7 @@ var COFantasy = COFantasy || function() { }); cibles = enleveDoublonsPartagePV(cibles); if (options.return) return; - //L'expression à lancer est tout ce qui est entre le premier blanc et le premier -- + //L'expression \xE0 lancer est tout ce qui est entre le premier blanc et le premier -- let debutDmgRollExpr = msg.content.indexOf(' ') + 1; let dmgRollExpr = msg.content.substring(debutDmgRollExpr); let finDmgRollExpr = msg.content.indexOf(' --'); @@ -27674,7 +28034,7 @@ var COFantasy = COFantasy || function() { addEvent(evt); } evt.action = { - titre: "Dégâts", + titre: "D\xE9g\xE2ts", playerId: playerId, playerName: playerName, cibles: cibles, @@ -27682,12 +28042,12 @@ var COFantasy = COFantasy || function() { options: options }; if (options.lanceur && limiteRessources(options.lanceur, options, 'dmg', 'dmg', evt)) return; - let action = "Dégâts. "; + let action = "D\xE9g\xE2ts. "; if (options.titre) action += options.titre + "
    "; if (options.partialSave) { action += - " Jet de " + options.partialSave.carac + " difficulté " + options.partialSave.seuil + - " pour réduire les dégâts"; + " Jet de " + options.partialSave.carac + " difficult\xE9 " + options.partialSave.seuil + + " pour r\xE9duire les d\xE9g\xE2ts"; } let display = startFramedDisplay(playerId, action); let tokensToProcess = cibles.length; @@ -27697,45 +28057,47 @@ var COFantasy = COFantasy || function() { if (someDmgDone) { sendFramedDisplay(display); } else { - sendPlayer(playerName, "Aucune cible valide n'a été sélectionée"); + sendPlayer(playerName, "Aucune cible valide n'a \xE9t\xE9 s\xE9lection\xE9e"); } } tokensToProcess--; }; - try { - sendChat('', '[[' + dmg.value + ']]', function(resDmg) { - dmg.roll = dmg.roll || resDmg[0]; - let afterEvaluateDmg = dmg.roll.content.split(' '); - let dmgRollNumber = rollNumber(afterEvaluateDmg[0]); - dmg.total = dmg.roll.inlinerolls[dmgRollNumber].results.total; - dmg.display = buildinline(dmg.roll.inlinerolls[dmgRollNumber], dmg.type, options.magique); - cibles.forEach(function(perso) { - if (getState(perso, 'mort')) { //pas de dégâts aux morts - finalDisplay(); - return; - } - if (options.mortsVivants && !(estMortVivant(perso))) { - sendPlayer(playerName, nomPerso(perso) + " n'est pas un mort-vivant"); - finalDisplay(); - return; - } - let name = nomPerso(perso); - let explications = []; - copyDmgOptionsToTarget(perso, options); + dmg.rolls = dmg.rolls || []; + cibles.forEach(function(perso) { + if (getState(perso, 'mort')) { //pas de d\xE9g\xE2ts aux morts + finalDisplay(); + return; + } + if (options.mortsVivants && !(estMortVivant(perso))) { + sendPlayer(playerName, nomPerso(perso) + " n'est pas un mort-vivant"); + finalDisplay(); + return; + } + let name = nomPerso(perso); + let explications = []; + copyDmgOptionsToTarget(perso, options); + try { + sendChat('', '[[' + dmg.value + ']]', function(resDmg) { + dmg.rolls[perso.token.id] = dmg.rolls[perso.token.id] || resDmg[0]; + let roll = dmg.rolls[perso.token.id]; + let afterEvaluateDmg = roll.content.split(' '); + let dmgRollNumber = rollNumber(afterEvaluateDmg[0]); + dmg.total = roll.inlinerolls[dmgRollNumber].results.total; + dmg.display = buildinline(roll.inlinerolls[dmgRollNumber], dmg.type, options.magique); dealDamage(perso, dmg, [], evt, false, options, explications, function(dmgDisplay, dmgFinal) { someDmgDone = true; addLineToFramedDisplay(display, - name + " reçoit " + dmgDisplay + " DM"); + name + " re\xE7oit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); finalDisplay(); }); - }); //fin forEach - }); //fin du jet de dés - } catch (rollError) { - error("Jet " + dmg.value + " mal formé", dmg); - } + }); //fin du jet de d\xE9s + } catch (rollError) { + error("Jet " + dmg.value + " mal form\xE9", dmg); + } + }); //fin forEach } function estElementaire(t) { @@ -27756,12 +28118,12 @@ var COFantasy = COFantasy || function() { if (valeur == 'false' || valeur == '0' || valeur == 'non' || valeur == 'no') valeur = false; if (valeur == 'true' || valeur == 'oui' || valeur == 'yes') valeur = true; if (!_.has(cof_states, etat)) { - error("Le premier argument de !cof-set-state n'est pas un état valide", cmd); + error("Le premier argument de !cof-set-state n'est pas un \xE9tat valide", cmd); return; } if (isCarac(cmd[2])) { if (cmd.length < 4) { - error("Il manque la difficulté du jet de sauvegarde.", cmd); + error("Il manque la difficult\xE9 du jet de sauvegarde.", cmd); return; } valeur = true; @@ -27774,20 +28136,21 @@ var COFantasy = COFantasy || function() { } else { options.saveActifParTour.difficulte = parseInt(cmd[3]); if (isNaN(options.saveActifParTour.difficulte)) { - error("Difficulté du jet de sauvegarde incorrecte", cmd); + error("Difficult\xE9 du jet de sauvegarde incorrecte", cmd); return; } } } let cibles = []; - getSelected(msg, function(selected, playerId) { + getSelected(msg, function(selected, playerId, aoe) { if (selected === undefined || selected.length === 0) { - error("Pas de cible pour le changement d'état", msg); + error("Pas de cible pour le changement d'\xE9tat", msg); return; } + options.aoe = aoe; iterSelected(selected, function(perso) { if (options.seulementVivant && estNonVivant(perso)) { - sendPlayer(msg, "cet effet n'affecte que les créatures vivantes", playerId); + sendPlayer(msg, "cet effet n'affecte que les cr\xE9atures vivantes", playerId); return; } switch (etat) { @@ -27829,7 +28192,7 @@ var COFantasy = COFantasy || function() { } cibles.push(perso); }); - }); + }, options); doSetState(cibles, etat, valeur, options); } @@ -27845,6 +28208,9 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); + if (options.terrainDifficile && options.aoe && options.aoe.type == 'disque') { + ajouteTerrainDifficile(options, evt); + } let lanceur = options.lanceur; if (lanceur === undefined && cibles.length == 1) lanceur = persoOfId(cibles[0].token.id); if (limiteRessources(lanceur, options, etat, etat, evt)) return; @@ -27887,8 +28253,8 @@ var COFantasy = COFantasy || function() { }; if (options.save) { let saveOpts = { - msgPour: " pour résister à l'effet " + stringOfEtat(etat), - msgRate: ", raté.", + msgPour: " pour r\xE9sister \xE0 l'effet " + stringOfEtat(etat), + msgRate: ", rat\xE9.", rolls: options.rolls, chanceRollId: options.chanceRollId, type: options.type @@ -27911,7 +28277,7 @@ var COFantasy = COFantasy || function() { function textOfSaveState(etat, perso) { switch (etat) { case 'immobilise': - return "se libérer"; + return "se lib\xE9rer"; case 'aveugle': return "retrouver la vue"; case 'etourdi': @@ -27921,13 +28287,13 @@ var COFantasy = COFantasy || function() { case 'renverse': return "se relever"; case 'endormi': - return "se réveiller"; + return "se r\xE9veiller"; case 'apeure': return "retrouver du courage"; case 'enseveli': return "sortir de terre"; default: - return "ne plus être " + stringOfEtat(etat, perso); + return "ne plus \xEAtre " + stringOfEtat(etat, perso); } } @@ -27936,7 +28302,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 4 || !_.has(cof_states, cmd[1])) { - error("Paramètres de !cof-save-state incorrects", cmd); + error("Param\xE8tres de !cof-save-state incorrects", cmd); return; } let etat = cmd[1]; @@ -27947,17 +28313,17 @@ var COFantasy = COFantasy || function() { carac2 = carac.substring(3, 6); carac = carac.substring(0, 3); if (!isCarac(carac) || !isCarac(carac)) { - error("Paramètres de !cof-save-state incorrects", cmd); + error("Param\xE8tres de !cof-save-state incorrects", cmd); return; } } else { - error("Paramètres de !cof-save-state incorrects", cmd); + error("Param\xE8tres de !cof-save-state incorrects", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Pas de token sélectionné", msg.content); + error("Pas de token s\xE9lectionn\xE9", msg.content); return; } let pageId = options.pageId; @@ -27980,7 +28346,7 @@ var COFantasy = COFantasy || function() { } else { let seuil = parseInt(cmd[3]); if (isNaN(seuil)) { - error("La difficulté n'est pas un nombre", cmd); + error("La difficult\xE9 n'est pas un nombre", cmd); return; } iterSelected(selected, function(perso) { @@ -27992,7 +28358,7 @@ var COFantasy = COFantasy || function() { doSaveState(playerId, perso, etat, carac, options, undefined, seuil); }); } - }); + }, options); } function doSaveState(playerId, perso, etat, carac, options, opposant, seuil) { @@ -28058,13 +28424,13 @@ var COFantasy = COFantasy || function() { } //!cof-save-effet token_id attr_id - // où attr_id est l'id de l'attribut de save + // o\xF9 attr_id est l'id de l'attribut de save function parseSaveEffet(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 3) { - error("Paramètres de !cof-save-effet incorrects", cmd); + error("Param\xE8tres de !cof-save-effet incorrects", cmd); return; } let perso = persoOfId(cmd[1]); @@ -28082,7 +28448,7 @@ var COFantasy = COFantasy || function() { let effetC = attrName.substring(0, indexSave); let effetTemp = estEffetTemp(effetC); if (!effetTemp && !estEffetCombat(effetC)) { - error("Impossible de trouver l'effet correspondant à " + effetC, attrName); + error("Impossible de trouver l'effet correspondant \xE0 " + effetC, attrName); return; } attrName = effetC + attrName.substr(indexSave + 16); @@ -28092,19 +28458,19 @@ var COFantasy = COFantasy || function() { let msgPour = " pour "; if (met.msgSave) msgPour += met.msgSave; else { - msgPour += "ne plus être sous l'effet de "; + msgPour += "ne plus \xEAtre sous l'effet de "; if (effetC.startsWith('dotGen(')) msgPour += effetC.substring(7, effetC.indexOf(')')); else msgPour += effetC; } let carac = attr.get('current'); if (!isCarac(carac)) { - error("Save par tour " + attrName + " mal formé", carac); + error("Save par tour " + attrName + " mal form\xE9", carac); return; } let seuil = parseInt(attr.get('max')); if (isNaN(seuil)) { - error("Save par tour " + attrName + " mal formé", seuil); + error("Save par tour " + attrName + " mal form\xE9", seuil); return; } let attrEffet = findObjs({ @@ -28205,7 +28571,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("commande non formée", msg.content); + error("commande non form\xE9e", msg.content); return; } let armeLabel = ''; @@ -28218,13 +28584,13 @@ var COFantasy = COFantasy || function() { let personnages = []; getSelected(msg, function(selected) { if (selected === undefined || selected.length === 0) { - error("Qui doit dégainer ?", msg); + error("Qui doit d\xE9gainer ?", msg); return; } iterSelected(selected, function(perso) { personnages.push(perso); }); - }); + }, options); doDegainer(personnages, armeLabel, options); } @@ -28243,14 +28609,14 @@ var COFantasy = COFantasy || function() { persos.forEach(function(perso) { function afterSave() { let nomArme = degainerArme(perso, labelArme, evt, options); - if (nomArme) sendPerso(perso, "a déjà " + nomArme + " en main"); + if (nomArme) sendPerso(perso, "a d\xE9j\xE0 " + nomArme + " en main"); else if (options.montreActions && persos.length === 1) turnAction(perso); } if (options.save) { let saveOpts = { msgPour: " pour garder son arme en main", - msgRate: ", raté.", + msgRate: ", rat\xE9.", rolls: options.rolls, chanceRollId: options.chanceRollId }; @@ -28272,7 +28638,7 @@ var COFantasy = COFantasy || function() { function echangeInit(msg) { let combat = stateCOF.combat; if (!combat) { - error("Échange d'intiative en dehors du combat", msg); + error("\xC9change d'intiative en dehors du combat", msg); return; } let options = parseOptions(msg); @@ -28297,7 +28663,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3) { attackBonus = parseInt(cmd[3]); if (isNaN(attackBonus)) { - error("Le troisième argument n'est pas un nombre", cmd[3]); + error("Le troisi\xE8me argument n'est pas un nombre", cmd[3]); return; } } @@ -28312,23 +28678,23 @@ var COFantasy = COFantasy || function() { return (t.id == perso2.token.id); }); if (tourTok1 < 0) { - sendPerso(perso1, "a déjà agit, pas moyen d'échanger son initiative"); + sendPerso(perso1, "a d\xE9j\xE0 agit, pas moyen d'\xE9changer son initiative"); return; } if (tourTok2 < 0) { - sendPerso(perso2, "a déjà agit, pas moyen d'échanger son initiative"); + sendPerso(perso2, "a d\xE9j\xE0 agit, pas moyen d'\xE9changer son initiative"); return; } let pr1 = to.pasAgi[tourTok1].pr; let pr2 = to.pasAgi[tourTok2].pr; if (pr1 == pr2) { - sendPerso(perso1, "a la même initiative que " + nomPerso(perso2)); + sendPerso(perso1, "a la m\xEAme initiative que " + nomPerso(perso2)); return; } if (pr1 > pr2) { if (attackBonus) { setTokenAttr(perso1, 'actionConcertee', attackBonus, evt, { - msg: "gagne un bonus de " + attackBonus + " à ses attaques et en DEF pour ce tour" + msg: "gagne un bonus de " + attackBonus + " \xE0 ses attaques et en DEF pour ce tour" }); } setActiveToken(combat, perso2.token.id, evt); @@ -28367,7 +28733,7 @@ var COFantasy = COFantasy || function() { return arg == '--secret'; }); setTokenAttr(perso1, 'aCouvert', 1, evt, { - msg: "reste à couvert", + msg: "reste \xE0 couvert", maxVal: init, secret: secret }); @@ -28380,9 +28746,9 @@ var COFantasy = COFantasy || function() { } if (perso2.token.id == perso1.token.id) { if (secret) { - whisperChar(perso1.charId, "s'est ciblé " + onGenre(perso1, 'lui', 'elle') + "-même, il est donc le seul à couvert"); + whisperChar(perso1.charId, "s'est cibl\xE9 " + onGenre(perso1, 'lui', 'elle') + "-m\xEAme, il est donc le seul \xE0 couvert"); } else { - sendPerso(perso1, "s'est ciblé " + onGenre(perso1, 'lui', 'elle') + "-même, il est donc le seul à couvert"); + sendPerso(perso1, "s'est cibl\xE9 " + onGenre(perso1, 'lui', 'elle') + "-m\xEAme, il est donc le seul \xE0 couvert"); } addEvent(evt); return; @@ -28390,13 +28756,13 @@ var COFantasy = COFantasy || function() { let d = distanceCombat(perso1.token, perso2.token); if (d > 0) { if (secret) { - whisperChar(perso2.charId, "est trop éloigné de " + nomPerso(perso1) + " pour rester à couvert avec lui"); + whisperChar(perso2.charId, "est trop \xE9loign\xE9 de " + nomPerso(perso1) + " pour rester \xE0 couvert avec lui"); } else { - sendPerso(perso2, "est trop éloigné de " + nomPerso(perso1) + " pour rester à couvert avec lui"); + sendPerso(perso2, "est trop \xE9loign\xE9 de " + nomPerso(perso1) + " pour rester \xE0 couvert avec lui"); } } else { setTokenAttr(perso2, 'aCouvert', 1, evt, { - msg: "suit " + nomPerso(perso1) + " et reste à couvert", + msg: "suit " + nomPerso(perso1) + " et reste \xE0 couvert", maxVal: init, secret: secret }); @@ -28427,20 +28793,20 @@ var COFantasy = COFantasy || function() { effet += 'Temp'; } if (effet == 'forgeron' || effet == 'armeEnflammee' || effet == 'armeGlacee') { - //Compléter description de l'effet + //Compl\xE9ter description de l'effet if (!lanceur) { error("Pas de lanceur pour " + effet, msg.content); return; } let armeActuelle = tokenAttribute(lanceur, 'armeEnMain'); if (armeActuelle.length === 0) { - whisperChar(charId, "Pas d'arme en main, impossible de savoir à quoi appliquer " + effet); + whisperChar(charId, "Pas d'arme en main, impossible de savoir \xE0 quoi appliquer " + effet); return; } let labelArme = armeActuelle[0].get('current'); effet = effet + '(' + labelArme + ')'; } else if (!estEffetTemp(effet)) { - error(effet + " n'est pas un effet temporaire répertorié", msg.content); + error(effet + " n'est pas un effet temporaire r\xE9pertori\xE9", msg.content); return; } if (lanceur && options.mana !== undefined && attributeAsBool(lanceur, 'frappeDesArcanes')) { @@ -28461,7 +28827,7 @@ var COFantasy = COFantasy || function() { if (options.puissantDuree || options.tempeteDeManaDuree) duree = duree * 2; getSelected(msg, function(selected, playerId, aoe) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour l'effet", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour l'effet", playerId); return; } options.aoe = aoe; @@ -28480,7 +28846,7 @@ var COFantasy = COFantasy || function() { } if (lanceur && options.tempeteDeMana) { if (duree > 0 && options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, dm: mEffet.dm, @@ -28494,7 +28860,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPlayer(msg, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayer(msg, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } if (selected.length == 1 && options.tempeteDeMana.altruiste) { selected[0]._id = options.tempeteDeMana.altruiste.token.id; @@ -28514,7 +28880,7 @@ var COFantasy = COFantasy || function() { } if ((mEffet.seulementVivant || options.seulementVivant) && estNonVivant(perso)) { - sendPlayer(msg, "cet effet n'affecte que les créatures vivantes", playerId); + sendPlayer(msg, "cet effet n'affecte que les cr\xE9atures vivantes", playerId); return; } if (predicateAsBool(perso, 'liberteDAction') && @@ -28556,7 +28922,40 @@ var COFantasy = COFantasy || function() { }, options); } - //Si display est défini, l'envoie dans le chat à la fin de l'appel + //Si options.terrainDifficile, doit avoir des champs imgsrc, nom et duree + function ajouteTerrainDifficile(options, evt) { + if (!options.aoe || !options.aoe.rayon) return; + let terrainDifficile = options.terrainDifficile; + if (!terrainDifficile || terrainDifficile.done) return; + terrainDifficile.done = true; + let diametre = options.aoe.rayon * 2 * PIX_PER_UNIT / computeScale(options.pageId); + let t = createObj('graphic', { + _pageid: options.pageId, + imgsrc: terrainDifficile.imgsrc, + represents: '', + left: options.aoe.centre.left, + top: options.aoe.centre.top, + width: diametre, + height: diametre, + layer: 'map', + isDrawing: true, + name: terrainDifficile.nom, + gmnotes: 'terrainDifficile:disque ' + Math.floor(diametre) + }); + if (t) { + toFront(t); + evt.tokens = evt.tokens || []; + evt.tokens.push(t); + stateCOF.tokensTemps = stateCOF.tokensTemps || []; + stateCOF.tokensTemps.push({ + tid: t.id, + duree: terrainDifficile.duree, + init: getInit() + }); + } + } + + //Si display est d\xE9fini, l'envoie dans le chat \xE0 la fin de l'appel function activerEffetTemporaire(lanceur, cibles, effet, mEffet, duree, options, evt, whisper, explications, display) { let ef = { effet: effet, @@ -28612,7 +29011,7 @@ var COFantasy = COFantasy || function() { ressource = "limiteParJour_" + ressource; let utilisations = attributeAsInt(perso, ressource, options.limiteCibleParJour); if (utilisations === 0) { - expliquer("ne peut plus bénéficier de " + effet + " aujourd'hui"); + expliquer("ne peut plus b\xE9n\xE9ficier de " + effet + " aujourd'hui"); return; } setTokenAttr(perso, ressource, utilisations - 1, evt); @@ -28626,37 +29025,18 @@ var COFantasy = COFantasy || function() { combat = entrerEnCombat(undefined, ini, explications, evt); } if (options.aoe && options.pageId && effet == 'prisonVegetale' && options.aoe.type == 'disque') { - let diametre = options.aoe.rayon * 2 * PIX_PER_UNIT / computeScale(options.pageId); - let t = createObj('graphic', { - _pageid: options.pageId, - imgsrc: stateCOF.options.images.val.prison_vegetale.val, - represents: '', - left: options.aoe.centre.get('left'), - top: options.aoe.centre.get('top'), - width: diametre, - height: diametre, - layer: 'map', - isDrawing: true, - name: 'Prison végétale', - gmnotes: 'terrainDifficile:disque ' + Math.floor(diametre) - }); - if (t) { - toFront(t); - evt.tokens = evt.tokens || []; - evt.tokens.push(t); - stateCOF.tokensTemps = stateCOF.tokensTemps || []; - stateCOF.tokensTemps.push({ - tid: t.id, - duree, - init: getInit() - }); - } + options.terrainDifficile = options.terrainDifficile || { + duree, + nom: "Prison v\xE9g\xE9tale", + imgsrc: stateCOF.options.images.val.prison_vegetale.val + }; + ajouteTerrainDifficile(options, evt); } let renew = attributeAsBool(perso, effet); setEffetTemporaire(perso, ef, d, evt, options); if (!renew) { if (effet.startsWith('forgeron(')) { - //Il faut dégainer l'arme si elle n'est pas en main, et ajouter une lumière + //Il faut d\xE9gainer l'arme si elle n'est pas en main, et ajouter une lumi\xE8re let labelArmeForgeron = effet.substring(9, effet.indexOf(')')); degainerArme(perso, labelArmeForgeron, evt); let feu = getIntValeurOfEffet(perso, effet, 1, 'voieDuMetal'); @@ -28714,15 +29094,15 @@ var COFantasy = COFantasy || function() { if (display) perso.messages.push(s); else sendPerso(perso, s); }; - if (options.type && immuniseAuType(perso, options.type, lanceur)) { - expliquer("ne semble pas affecté par " + stringOfType(options.type)); + if (options.type && immuniseAuType(perso, options.type, lanceur, options)) { + expliquer("ne semble pas affect\xE9 par " + stringOfType(options.type)); finalize(); return; } if (options.save) { let saveOpts = { - msgPour: options.save.msgPour || " pour résister à l'effet " + effet, - msgRate: ", raté.", + msgPour: options.save.msgPour || " pour r\xE9sister \xE0 l'effet " + effet, + msgRate: ", rat\xE9.", attaquant: lanceur, rolls: options.rolls, chanceRollId: options.chanceRollId, @@ -28739,7 +29119,7 @@ var COFantasy = COFantasy || function() { } if (reussite) { if (effet == 'reactionViolente' && predicateAsBool(perso, 'violenceCiblee')) { - expliquer("résiste à la provocation, mais emmagasine de la violence"); + expliquer("r\xE9siste \xE0 la provocation, mais emmagasine de la violence"); addToAttributeAsInt(perso, 'pointsDeViolence', 0, 1, evt); } finalize(); @@ -28761,7 +29141,7 @@ var COFantasy = COFantasy || function() { return (2 * magieEnArmure < defa + ma); } - //options doit être défini + //options doit \xEAtre d\xE9fini function effetTemporaire(playerId, cibles, effet, mEffet, duree, options) { const evt = { type: 'effetTemp', @@ -28808,7 +29188,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, line); activerEffetTemporaire(lanceur, cibles, effet, mEffet, duree, options, evt, whisper, explications, display); } else { - line += '< ' + difficulte + ", le sort est raté"; + line += '< ' + difficulte + ", le sort est rat\xE9"; addLineToFramedDisplay(display, line); sendFramedDisplay(display); } @@ -28816,7 +29196,7 @@ var COFantasy = COFantasy || function() { } else { activerEffetTemporaire(lanceur, cibles, effet, mEffet, duree, options, evt, whisper, explications); } - } else { //On met fin à l'effet + } else { //On met fin \xE0 l'effet explications.forEach(function(e) { sendChat('', e); }); @@ -28855,7 +29235,7 @@ var COFantasy = COFantasy || function() { case 'oui': case 'Oui': case 'true': - case 'début': + case 'd\xE9but': case 'debut': valeur = true; activer = true; @@ -28894,7 +29274,7 @@ var COFantasy = COFantasy || function() { } let effet = cmd[1]; if (!estEffetCombat(effet)) { - error(effet + " n'est pas un effet de combat répertorié", msg.content); + error(effet + " n'est pas un effet de combat r\xE9pertori\xE9", msg.content); return; } const evt = { @@ -28920,7 +29300,7 @@ var COFantasy = COFantasy || function() { } } if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour l'effet", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour l'effet", playerId); return; } if (lanceur === undefined) { @@ -28935,7 +29315,7 @@ var COFantasy = COFantasy || function() { } if (lanceur && options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, dm: messageEffetCombat[effet].dm, @@ -28948,7 +29328,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(lanceur, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort", options.secret); + sendPerso(lanceur, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort", options.secret); } if (selected.length == 1 && options.tempeteDeMana.altruiste) { selected[0]._id = options.tempeteDeMana.altruiste.token.id; @@ -29020,7 +29400,7 @@ var COFantasy = COFantasy || function() { setTokenAttr(perso, effet + 'TokenSide', oldSide, evt); } }); - } else { //on désactive + } else { //on d\xE9sactive iterSelected(selected, function(perso) { let actMsg = messageFin(perso, mEffet) + extraImg; removeTokenAttr(perso, effet, evt, { @@ -29081,7 +29461,7 @@ var COFantasy = COFantasy || function() { }); } } - }); + }, options); } function parseEffetIndetermine(msg) { @@ -29102,7 +29482,7 @@ var COFantasy = COFantasy || function() { effetCombat(msg); return; } - error(effet + " n'est pas un effet répertorié", msg.content); + error(effet + " n'est pas un effet r\xE9pertori\xE9", msg.content); return; } let av = activeOuValeur(cmd, options); @@ -29116,7 +29496,7 @@ var COFantasy = COFantasy || function() { if (lanceur) charId = lanceur.charId; getSelected(msg, function(selected, playerId, aoe) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour l'effet", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour l'effet", playerId); return; } if (lanceur === undefined) { @@ -29134,7 +29514,7 @@ var COFantasy = COFantasy || function() { } if (lanceur && options.tempeteDeMana) { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPlayer(msg, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayer(msg, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } if (selected.length == 1 && options.tempeteDeMana.altruiste) { selected[0]._id = options.tempeteDeMana.altruiste.token.id; @@ -29163,12 +29543,12 @@ var COFantasy = COFantasy || function() { } if (activer === undefined) { if (cibles.length > 1) { - sendPlayer(msg, "On ne peut sélectionner qu'un token si on ne précise pas si il faut activer ou désactiver l'effet"); + sendPlayer(msg, "On ne peut s\xE9lectionner qu'un token si on ne pr\xE9cise pas si il faut activer ou d\xE9sactiver l'effet"); return; } let perso = persoOfId(selected[0]._id); if (!perso) { - error("Token sélectionné non valide", selected); + error("Token s\xE9lectionn\xE9 non valide", selected); return; } activer = !attributeAsBool(perso, effet); @@ -29192,7 +29572,7 @@ var COFantasy = COFantasy || function() { normalToken = JSON.parse(normalToken); let nw = normalToken.width; let nh = normalToken.height; - //Rien à faire si le token occupe déjà une case + //Rien \xE0 faire si le token occupe d\xE9j\xE0 une case if (nw >= PIX_PER_UNIT || nh >= PIX_PER_UNIT) return; setTokenAttr(perso, 'tailleDeTokenNormale', nw, evt, { maxVal: nh @@ -29226,7 +29606,7 @@ var COFantasy = COFantasy || function() { let nw = parseInt(attr.get('current')); let nh = parseInt(attr.get('max')); if (isNaN(nw) || isNaN(nh)) { - error("La taille de token sauvegardée n'est pas correcte", attr); + error("La taille de token sauvegard\xE9e n'est pas correcte", attr); attr.remove(); } let character = getObj('character', perso.charId); @@ -29371,11 +29751,11 @@ var COFantasy = COFantasy || function() { if (!msgPour) { msgPour = " pour "; if (mEffet.msgSave) msgPour += mEffet.msgSave; - else msgPour += "résister à l'effet " + effet; + else msgPour += "r\xE9sister \xE0 l'effet " + effet; } let saveOpts = { msgPour, - msgRate: ", raté.", + msgRate: ", rat\xE9.", silencieuxSiPasAffecte: options.silencieuxSiPasAffecte, attaquant: lanceur, rolls: options.rolls, @@ -29453,7 +29833,7 @@ var COFantasy = COFantasy || function() { let classeEffet = cmd[1]; getSelected(msg, function(selected) { if (selected === undefined || selected.length === 0) { - error("Pas de cible sélectionnée pour la fin d'une classe d'effets", msg); + error("Pas de cible s\xE9lectionn\xE9e pour la fin d'une classe d'effets", msg); return; } const evt = { @@ -29491,16 +29871,16 @@ var COFantasy = COFantasy || function() { predicateAsBool(target, 'sansEsprit') || attributeAsBool(target, 'enrage') || predicateAsBool(target, 'liberteDAction')) { - messages.push(targetName + " est insensible à la peur !"); + messages.push(targetName + " est insensible \xE0 la peur !"); callback(); return; } if (options.immuniseSiResiste && attributeAsBool(target, options.immuniseSiResiste)) { - messages.push(targetName + " a déjà résisté à cet effet, " + onGenre(target, 'il', 'elle') + " n'y est plus sensible"); + messages.push(targetName + " a d\xE9j\xE0 r\xE9sist\xE9 \xE0 cet effet, " + onGenre(target, 'il', 'elle') + " n'y est plus sensible"); callback(); return; } - let carac = 'SAG'; //carac pour résister + let carac = 'SAG'; //carac pour r\xE9sister if (options.resisteAvecForce) carac = meilleureCarac('SAG', 'FOR', target, difficulte); //chercher si un partenaire a sansPeur pour appliquer le bonus @@ -29512,7 +29892,7 @@ var COFantasy = COFantasy || function() { let allTokens; allies.forEach(function(cid) { if (charPredicateAsBool(cid, 'sansPeur')) { - //On cherche si l'allié est présent sur la même page + //On cherche si l'alli\xE9 est pr\xE9sent sur la m\xEAme page allTokens = allTokens || findObjs({ _type: "graphic", @@ -29531,7 +29911,7 @@ var COFantasy = COFantasy || function() { charId: cid, token: alliePresent }; - msgAllieSansPeur = nomPerso(allie) + " a donné +" + bonusAllie + " au jet"; + msgAllieSansPeur = nomPerso(allie) + " a donn\xE9 +" + bonusAllie + " au jet"; } } } @@ -29547,7 +29927,7 @@ var COFantasy = COFantasy || function() { let line = targetName + " fait " + tr.texte; let sujet = onGenre(target, 'il', 'elle'); if (tr.reussite) { - line += ", " + sujet + " résiste à la peur." + tr.modifiers; + line += ", " + sujet + " r\xE9siste \xE0 la peur." + tr.modifiers; if (options.immuniseSiResiste) setTokenAttr(target, options.immuniseSiResiste, true, evt); } else { @@ -29555,18 +29935,18 @@ var COFantasy = COFantasy || function() { let effet = 'apeureTemp'; let etat = 'apeure'; if (options.etourdi) { - line += "s'enfuit ou reste recroquevillé" + eForFemale(target) + " sur place"; + line += "s'enfuit ou reste recroquevill\xE9" + eForFemale(target) + " sur place"; effet = 'peurEtourdi'; } else if (options.ralenti) { line += "est ralenti" + eForFemale(target); effet = 'ralentiTemp'; etat = 'ralenti'; } else if (options.paralyse) { - line += "est paralysé" + eForFemale(target); + line += "est paralys\xE9" + eForFemale(target); effet = 'paralyseTemp'; etat = 'paralyse'; } else if (options.secoue && !attributeAsBool(target, 'secoue')) { - line += "est secoué" + eForFemale(target); + line += "est secou\xE9" + eForFemale(target); effet = 'secoue'; etat = false; } else { @@ -29596,12 +29976,12 @@ var COFantasy = COFantasy || function() { let pageId = getPageId(playerId); let difficulte = parseInt(cmd[1]); if (isNaN(difficulte)) { - error("Le premier argument de !cof-peur, la difficulté du test de résistance, n'est pas un nombre", cmd); + error("Le premier argument de !cof-peur, la difficult\xE9 du test de r\xE9sistance, n'est pas un nombre", cmd); return; } - let duree = parseDice(cmd[2], "durée de peur"); + let duree = parseDice(cmd[2], "dur\xE9e de peur"); if (!dePositif(duree)) { - error("Le second argument de !cof-peur, la durée, n'est pas un nombre positif", cmd); + error("Le second argument de !cof-peur, la dur\xE9e, n'est pas un nombre positif", cmd); return; } let options = {}; @@ -29621,12 +30001,12 @@ var COFantasy = COFantasy || function() { return; case 'portee': if (optCmd.length < 2) { - error("Il manque l'argument de portée", optArgs); + error("Il manque l'argument de port\xE9e", optArgs); return; } options.portee = parseInt(optCmd[1]); if (isNaN(options.portee) || options.portee < 0) { - error("La portée n'est pas un nombre positif", optCmd); + error("La port\xE9e n'est pas un nombre positif", optCmd); delete options.portee; } return; @@ -29659,7 +30039,7 @@ var COFantasy = COFantasy || function() { let cibles = []; getSelected(msg, function(selected) { if (selected === undefined || selected.length === 0) { - error("Pas de cible sélectionnée pour la peur", msg); + error("Pas de cible s\xE9lectionn\xE9e pour la peur", msg); return; } iterSelected(selected, function(perso) { @@ -29672,11 +30052,11 @@ var COFantasy = COFantasy || function() { perso.duree = rollDePlus(duree).val; cibles.push(perso); }); - }); + }, options); if (cibles.length > 0) { doPeur(cibles, difficulte, options); } else { - error("Aucune cible valable à portée de l'effet de Peur", msg); + error("Aucune cible valable \xE0 port\xE9e de l'effet de Peur", msg); } } @@ -29696,14 +30076,14 @@ var COFantasy = COFantasy || function() { if (options.titre) action += options.titre; else if (options.effroi) action += "est vraiment effrayant" + eForFemale(options.lanceur); - else action = "Capacité : Effet de peur"; + else action = "Capacit\xE9 : Effet de peur"; } else if (options.titre) action = options.titre; let messages = []; entrerEnCombat(options.lanceur, cibles, messages, evt); let display = startFramedDisplay(options.playerId, action, options.lanceur); let jet = " Jet de SAG "; if (options.resisteAvecForce) jet += "ou FOR "; - jet += "difficulté " + difficulte; + jet += "difficult\xE9 " + difficulte; addLineToFramedDisplay(display, jet, 80); let counter = cibles.length; let finalDisplay = function() { @@ -29730,7 +30110,7 @@ var COFantasy = COFantasy || function() { if (options === undefined || options.cmd === undefined) return; let cmd = options.cmd; if (cmd.length < 3) { - error("Il faut au moins 2 arguments à !cof-attaque-magique", cmd); + error("Il faut au moins 2 arguments \xE0 !cof-attaque-magique", cmd); return; } let attaquant = persoOfId(cmd[1], cmd[1]); @@ -29764,13 +30144,13 @@ var COFantasy = COFantasy || function() { } } - // callback est seulement appelé si on fait le test - // evt est facultatif ; si absent, en crée un nouveau générique et l'ajoute à l'historique + // callback est seulement appel\xE9 si on fait le test + // evt est facultatif ; si absent, en cr\xE9e un nouveau g\xE9n\xE9rique et l'ajoute \xE0 l'historique function attaqueMagiqueOpposee(playerId, attaquant, cible, options, callback, evt) { if (options.attaqueMentale) { if (predicateAsBool(cible, 'sansEsprit') || predicateAsBool(cible, 'vegetatif')) { sendPerso(attaquant, " est sans esprit, " + onGenre(cible, 'il', 'elle') + - " est immunisé" + onGenre(cible, '', 'e') + " aux attaques mentales."); + " est immunis\xE9" + onGenre(cible, '', 'e') + " aux attaques mentales."); return; } else if (predicateAsBool(cible, 'liberteDAction')) { sendPerso(cible, "reste libre de ses actions !"); @@ -29850,7 +30230,7 @@ var COFantasy = COFantasy || function() { let attackRoll2 = d20roll2 + att2Skill; if (options.chanceRollId && options.chanceRollId.roll2) attackRoll2 += options.chanceRollId.roll2; - let action = "Attaque magique opposée"; + let action = "Attaque magique oppos\xE9e"; let reussi; if (d20roll1 == 1) { if (d20roll2 == 1) reussi = (attackRoll1 >= attackRoll2); @@ -29903,10 +30283,10 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, line); if (reussi) { diminueMalediction(cible, evt); - addLineToFramedDisplay(display, "Attaque réussie !"); + addLineToFramedDisplay(display, "Attaque r\xE9ussie !"); } else { diminueMalediction(attaquant, evt); - addLineToFramedDisplay(display, "L'attaque échoue."); + addLineToFramedDisplay(display, "L'attaque \xE9choue."); } explications.forEach(explication => addLineToFramedDisplay(display, explication, 80)); if (callback) callback(display, reussi); @@ -29932,16 +30312,16 @@ var COFantasy = COFantasy || function() { function(display, reussi) { if (reussi) { if (attributeAsBool(cible, 'immunise24HA_injonction')) { - addLineToFramedDisplay(display, nomPerso(cible) + " a déjà résisté à une injonction aujourd'hui, c'est sans effet"); + addLineToFramedDisplay(display, nomPerso(cible) + " a d\xE9j\xE0 r\xE9sist\xE9 \xE0 une injonction aujourd'hui, c'est sans effet"); } else if (predicateAsBool(cible, 'liberteDAction')) { addLineToFramedDisplay(display, nomPerso(cible) + " reste libre de ses actions !"); } else { - addLineToFramedDisplay(display, nomPerso(cible) + " obéit à l'injonction"); + addLineToFramedDisplay(display, nomPerso(cible) + " ob\xE9it \xE0 l'injonction"); } sendFramedDisplay(display); } else { setTokenAttr(cible, 'immunise24HA_injonction', true, evt); - addLineToFramedDisplay(display, nomPerso(cible) + " n'obéit pas à l'injonction"); + addLineToFramedDisplay(display, nomPerso(cible) + " n'ob\xE9it pas \xE0 l'injonction"); sendFramedDisplay(display); } }, evt); @@ -29962,12 +30342,12 @@ var COFantasy = COFantasy || function() { function(display, reussi) { if (reussi) { if (estNonVivant(cible)) { - addLineToFramedDisplay(display, nomPerso(cible) + " n'est pas une créature vivante, il ne peut croire à sa mort"); + addLineToFramedDisplay(display, nomPerso(cible) + " n'est pas une cr\xE9ature vivante, il ne peut croire \xE0 sa mort"); sendFramedDisplay(display); return; } if (attributeAsBool(cible, 'limiteParJour_tueurFantasmagorique')) { - addLineToFramedDisplay(display, nomPerso(cible) + " a déjà été victime d'un tueur fantasmagorique aujourd'hui, c'est sans effet"); + addLineToFramedDisplay(display, nomPerso(cible) + " a d\xE9j\xE0 \xE9t\xE9 victime d'un tueur fantasmagorique aujourd'hui, c'est sans effet"); sendFramedDisplay(display); return; } @@ -29986,7 +30366,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, message, 80); }; const saveOpts = { - msgPour: " pour résister au tueur fantasmagorique", + msgPour: " pour r\xE9sister au tueur fantasmagorique", attaquant: attaquant, rolls: options.rolls, chanceRollId: options.chanceRollId, @@ -29996,10 +30376,10 @@ var COFantasy = COFantasy || function() { save(s, cible, saveId, expliquer, saveOpts, evt, function(reussiteSave, texte) { if (reussiteSave) { - addLineToFramedDisplay(display, nomPerso(cible) + " perd l'équilibre et tombe par terre"); + addLineToFramedDisplay(display, nomPerso(cible) + " perd l'\xE9quilibre et tombe par terre"); setState(cible, 'renverse', true, evt); - } else { //save raté - addLineToFramedDisplay(display, nomPerso(cible) + " succombe à ses pires terreurs"); + } else { //save rat\xE9 + addLineToFramedDisplay(display, nomPerso(cible) + " succombe \xE0 ses pires terreurs"); updateCurrentBar(cible, 1, 0, evt); setState(cible, 'mort', true, evt); } @@ -30027,7 +30407,7 @@ var COFantasy = COFantasy || function() { function(display, reussi) { if (reussi) { if (attributeAsBool(cible, 'limiteParJour_enkystementLointain')) { - addLineToFramedDisplay(display, nomPerso(cible) + " a déjà été victime d'un enkystement lointain aujourd'hui, c'est sans effet"); + addLineToFramedDisplay(display, nomPerso(cible) + " a d\xE9j\xE0 \xE9t\xE9 victime d'un enkystement lointain aujourd'hui, c'est sans effet"); sendFramedDisplay(display); return; } @@ -30038,13 +30418,13 @@ var COFantasy = COFantasy || function() { val, roll } = rollDePlus(20); - let message = nomPerso(cible) + " est téléporté" + eForFemale(cible) + " à une distance de "; + let message = nomPerso(cible) + " est t\xE9l\xE9port\xE9" + eForFemale(cible) + " \xE0 une distance de "; if (niveauCible < niveauAttaquant / 2) { - message += (val * 100) + " kilomètres."; + message += (val * 100) + " kilom\xE8tres."; } else if (niveauCible < niveauAttaquant) { - message += roll + " kilomètre" + (val > 1) ? 's' : ''; + message += roll + " kilom\xE8tre" + (val > 1) ? 's' : ''; } else { - message += (val * 10) + " mètres."; + message += (val * 10) + " m\xE8tres."; } addLineToFramedDisplay(display, message); sendFramedDisplay(display); @@ -30060,7 +30440,7 @@ var COFantasy = COFantasy || function() { if (options === undefined || options.cmd === undefined) return; const cmd = options.cmd; if (cmd.length < 3) { - error("Il faut au moins 2 arguments à !cof-injonction-mortelle", cmd); + error("Il faut au moins 2 arguments \xE0 !cof-injonction-mortelle", cmd); return; } let attaquant = persoOfId(cmd[1], cmd[1]); @@ -30097,7 +30477,7 @@ var COFantasy = COFantasy || function() { }); explications.forEach(msg => addLineToFramedDisplay(display, msg, 80)); if (attributeAsBool(cible, 'injonctionMortelle')) { - addLineToFramedDisplay(display, nomPerso(cible) + " a déjà été victime d'une injonction mortelle ce combat, c'est sans effet"); + addLineToFramedDisplay(display, nomPerso(cible) + " a d\xE9j\xE0 \xE9t\xE9 victime d'une injonction mortelle ce combat, c'est sans effet"); sendFramedDisplay(display); return; } @@ -30108,8 +30488,8 @@ var COFantasy = COFantasy || function() { } setTokenAttr(cible, 'injonctionMortelle', true, evt); let saveOpts = { - msgPour: " pour résister à l'injonction mortelle", - msgRate: ", raté.", + msgPour: " pour r\xE9sister \xE0 l'injonction mortelle", + msgRate: ", rat\xE9.", attaquant: attaquant, rolls: options.rolls, chanceRollId: options.chanceRollId, @@ -30142,7 +30522,7 @@ var COFantasy = COFantasy || function() { cible.attaquant = attaquant; dealDamage(cible, dmg, [], evt, false, options, explicationsDmg, function(dmgDisplay, dmgFinal) { addLineToFramedDisplay(display, - name + " reçoit " + dmgDisplay + " DM"); + name + " re\xE7oit " + dmgDisplay + " DM"); explicationsDmg.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); @@ -30168,7 +30548,7 @@ var COFantasy = COFantasy || function() { } const lanceur = persoOfId(args[1], args[1]); if (lanceur === undefined) { - error("Aucun personnage nommé " + args[1], args); + error("Aucun personnage nomm\xE9 " + args[1], args); return; } const casterCharId = lanceur.charId; @@ -30179,7 +30559,7 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionnée pour le sort de sommeil", playerId); + sendPlayer(msg, "Pas de cible s\xE9lectionn\xE9e pour le sort de sommeil", playerId); return; } let cibles = []; @@ -30188,7 +30568,7 @@ var COFantasy = COFantasy || function() { }); doSommeil(lanceur, cibles, options); }, { - lanceur: lanceur + lanceur }); } @@ -30219,14 +30599,14 @@ var COFantasy = COFantasy || function() { let rollD6 = evt.action.rolls[rollD6Id] || rolls.inlinerolls[d6RollNumber]; evt.action.rolls[rollD6Id] = rollD6; let nbTargetsMax = rollD6.results.total + cha; - let action = "Capacité : Sort de sommeil (max " + nbTargetsMax + " cibles)"; + let action = "Capacit\xE9 : Sort de sommeil (max " + nbTargetsMax + " cibles)"; let display = startFramedDisplay(options.playerId, action, lanceur); let attMag = rolls.inlinerolls[attMagRollNumber].results.total; let targetsWithSave = []; let targetsWithoutSave = []; cibles.forEach(function(perso) { - if (estNonVivant(perso) || predicateAsBool(perso, 'immunite_endormi')) { //le sort de sommeil n'affecte que les créatures vivantes - addLineToFramedDisplay(display, nomPerso(perso) + " n'est pas affecté par le sommeil"); + if (estNonVivant(perso) || predicateAsBool(perso, 'immunite_endormi')) { //le sort de sommeil n'affecte que les cr\xE9atures vivantes + addLineToFramedDisplay(display, nomPerso(perso) + " n'est pas affect\xE9 par le sommeil"); return; } if (predicateAsBool(perso, "liberteDAction")) { @@ -30235,7 +30615,7 @@ var COFantasy = COFantasy || function() { } let pv = perso.token.get('bar1_max'); if (pv > 2 * attMag) { - let line = nomPerso(perso) + " a trop de PV pour être affecté par le sort"; + let line = nomPerso(perso) + " a trop de PV pour \xEAtre affect\xE9 par le sort"; addLineToFramedDisplay(display, line); } else if (pv > attMag) { targetsWithSave.push(perso); @@ -30303,7 +30683,7 @@ var COFantasy = COFantasy || function() { let testId = 'resisteSommeil_' + perso.token.id; testCaracteristique(perso, 'SAG', seuil, testId, options, evt, function(tr) { - let line = "Jet de résistance de " + nomPerso(perso) + ": " + tr.texte; + let line = "Jet de r\xE9sistance de " + nomPerso(perso) + ": " + tr.texte; let sujet = onGenre(perso, 'il', 'elle'); if (tr.reussite) { line += ">=" + seuil + ", " + sujet + " ne s'endort pas." + tr.modifiers; @@ -30328,7 +30708,7 @@ var COFantasy = COFantasy || function() { if (options === undefined || options.cmd === undefined) return; let cmd = options.cmd; if (cmd.length < 3) { - error("Il faut au moins 2 arguments à !cof-attaque-magique-contre-pv", cmd); + error("Il faut au moins 2 arguments \xE0 !cof-attaque-magique-contre-pv", cmd); return; } let attaquant = persoOfId(cmd[1], cmd[1]); @@ -30393,41 +30773,41 @@ var COFantasy = COFantasy || function() { else if (d20roll == 20) reussi = true; else reussi = (attackRoll >= pvMax); if (reussi) { - addLineToFramedDisplay(display, "Attaque réussi !"); + addLineToFramedDisplay(display, "Attaque r\xE9ussi !"); } else { diminueMalediction(attaquant, evt); - addLineToFramedDisplay(display, "L'attaque échoue."); + addLineToFramedDisplay(display, "L'attaque \xE9choue."); } sendFramedDisplay(display); - }); //Fin du jet de dés pour l'attaque + }); //Fin du jet de d\xE9s pour l'attaque } function transeGuerison(msg) { if (stateCOF.combat) { - sendPlayer(msg, "Pas possible de méditer en combat"); + sendPlayer(msg, "Pas possible de m\xE9diter en combat"); return; } const options = parseOptions(msg); if (options === undefined) return; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionnée pour la transe de guérison", playerId); + sendPlayer(msg, "Pas de cible s\xE9lectionn\xE9e pour la transe de gu\xE9rison", playerId); return; } const evt = { - type: "Transe de guérison", + type: "Transe de gu\xE9rison", }; iterSelected(selected, function(perso) { let token = perso.token; - if (attributeAsBool(perso, 'transeDeGuérison')) { - sendPerso(perso, "a déjà médité depuis le dernier combat"); + if (attributeAsBool(perso, 'transeDeGu\xE9rison')) { + sendPerso(perso, "a d\xE9j\xE0 m\xE9dit\xE9 depuis le dernier combat"); return; } let bar1 = parseInt(token.get("bar1_value")); let pvmax = parseInt(token.get("bar1_max")); if (isNaN(bar1) || isNaN(pvmax)) return; if (bar1 >= pvmax) { - sendPerso(perso, "n'a pas besoin de méditer"); + sendPerso(perso, "n'a pas besoin de m\xE9diter"); return; } let sagMod = modCarac(perso, 'sagesse'); @@ -30447,11 +30827,11 @@ var COFantasy = COFantasy || function() { bar1 = pvmax; } updateCurrentBar(perso, 1, bar1, evt); - setTokenAttr(perso, 'transeDeGuérison', true, evt); - sendPerso(perso, "entre en méditation pendant 10 minutes et récupère " + soin + " points de vie."); + setTokenAttr(perso, 'transeDeGu\xE9rison', true, evt); + sendPerso(perso, "entre en m\xE9ditation pendant 10 minutes et r\xE9cup\xE8re " + soin + " points de vie."); }); addEvent(evt); - }); + }, options); } function raceIs(perso, race) { @@ -30463,7 +30843,7 @@ var COFantasy = COFantasy || function() { } function estFee(perso) { - if (predicateAsBool(perso, 'fée')) return true; + if (predicateAsBool(perso, 'f\xE9e')) return true; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.toLowerCase(); @@ -30473,7 +30853,7 @@ var COFantasy = COFantasy || function() { case 'licorne': case 'farfadet': case 'fee': - case 'fée': + case 'f\xE9e': case 'pixie': case 'lutin': return true; @@ -30483,14 +30863,14 @@ var COFantasy = COFantasy || function() { } function estDemon(perso) { - if (predicateAsBool(perso, 'démon')) return true; + if (predicateAsBool(perso, 'd\xE9mon')) return true; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.toLowerCase(); } if (perso.race === '') return false; switch (perso.race) { - case 'démon': + case 'd\xE9mon': case 'demon': case 'balor': case 'marilith': @@ -30542,14 +30922,14 @@ var COFantasy = COFantasy || function() { } function estGeant(perso) { - if (predicateAsBool(perso, 'géant')) return true; + if (predicateAsBool(perso, 'g\xE9ant')) return true; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.toLowerCase(); } if (perso.race === '') return false; switch (perso.race) { - case 'géant': + case 'g\xE9ant': case 'geant': case 'ogre': case 'troll': @@ -30615,7 +30995,7 @@ var COFantasy = COFantasy || function() { return false; } - //Vrai pour les insectes et araignées + //Vrai pour les insectes et araign\xE9es function estInsecte(perso) { if (predicateAsBool(perso, 'insecte')) return true; if (perso.profil === undefined) { @@ -30623,7 +31003,7 @@ var COFantasy = COFantasy || function() { perso.profil = perso.profil.toLowerCase(); } if (perso.profil == 'insecte') return true; - if (perso.profil == 'araignée') return true; + if (perso.profil == 'araign\xE9e') return true; if (perso.race === undefined) { perso.race = ficheAttribute(perso, 'race', ''); perso.race = perso.race.toLowerCase(); @@ -30632,7 +31012,7 @@ var COFantasy = COFantasy || function() { if (perso.race.includes('elf') && perso.race.includes('noir')) return true; switch (perso.race) { case 'ankheg': - case 'araignée': + case 'araign\xE9e': case 'araignee': case 'insecte': return true; @@ -30657,18 +31037,18 @@ var COFantasy = COFantasy || function() { case 'drow': case 'haut elfe': case 'halfelin': - case 'géant': + case 'g\xE9ant': case 'geant': case 'ange': case 'barghest': - case 'démon': + case 'd\xE9mon': case 'doppleganger': case 'dryade': case 'gnoll': case 'gobelin': case 'gobelours': case 'hobegobelin': - case 'homme-lézard': + case 'homme-l\xE9zard': case 'kobold': case 'nymphe': case 'ogre': @@ -30690,25 +31070,25 @@ var COFantasy = COFantasy || function() { if (perso.race === '') return false; switch (perso.race) { case 'ankheg': - case 'araignée': + case 'araign\xE9e': case 'araignee': case 'basilic': - case 'béhir': + case 'b\xE9hir': case 'behir': case 'bulette': case 'bison': case 'centaure': case 'cheval': case 'chien': - case 'chimère': + case 'chim\xE8re': case 'chimere': case 'cockatrice': case 'crocodile': case 'dragon': case 'drider': - case 'eléphant': + case 'el\xE9phant': case 'elephant': - case 'éléphant': + case '\xE9l\xE9phant': case 'mammouth': case 'griffon': case 'hipogriffe': @@ -30721,13 +31101,13 @@ var COFantasy = COFantasy || function() { case 'manticore': case 'ours': case 'panthere': - case 'panthère': + case 'panth\xE8re': case 'pegase': - case 'pégase': + case 'p\xE9gase': case 'pieuvre': case 'rat': case 'rhinoceros': - case 'rhinocéros': + case 'rhinoc\xE9ros': case 'sanglier': case 'taureau': case 'tigre': @@ -30759,7 +31139,7 @@ var COFantasy = COFantasy || function() { case 'animal': case 'aigle': case 'araignee': - case 'araignée': + case 'araign\xE9e': case 'basilic': case 'bulette': case 'bison': @@ -30769,8 +31149,8 @@ var COFantasy = COFantasy || function() { case 'chien': case 'crocodile': case 'dinosaure': - case 'éléphant': - case 'eléphant': + case '\xE9l\xE9phant': + case 'el\xE9phant': case 'elephant': case 'gorille': case 'griffon': @@ -30783,11 +31163,11 @@ var COFantasy = COFantasy || function() { case 'manticore': case 'ours': case 'ours-hibou': - case 'panthère': + case 'panth\xE8re': case 'pegase': - case 'pégase': + case 'p\xE9gase': case 'pieuvre': - case 'rhinocéros': + case 'rhinoc\xE9ros': case 'roc': case 'sanglier': case 'serpent': @@ -30807,7 +31187,7 @@ var COFantasy = COFantasy || function() { switch (perso.race) { case 'squelette': case 'zombie': - case 'élémentaire': + case '\xE9l\xE9mentaire': case 'momie': return true; default: @@ -30828,7 +31208,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd.length < 2) { - error("Il faut au moins un argument à !cof-soin", cmd); + error("Il faut au moins un argument \xE0 !cof-soin", cmd); return; } let soigneur = options.lanceur; @@ -30836,7 +31216,7 @@ var COFantasy = COFantasy || function() { let cible; let argSoin; if (cmd.length > 4) { - error("Trop d'arguments à !cof-soin", cmd); + error("Trop d'arguments \xE0 !cof-soin", cmd); } if (cmd.length > 2) { //cof-soin lanceur [cible] montant if (soigneur === undefined) { @@ -30850,7 +31230,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3) { // on a la cible en argument cible = persoOfId(cmd[2], cmd[2], pageId); if (cible === undefined) { - error("Le deuxième argument n'est pas un token valide: " + msg.content, cmd[2]); + error("Le deuxi\xE8me argument n'est pas un token valide: " + msg.content, cmd[2]); return; } argSoin = cmd[3]; @@ -30861,7 +31241,7 @@ var COFantasy = COFantasy || function() { argSoin = cmd[1]; } if (soigneur === undefined && (options.mana || (options.portee !== undefined) || options.limiteParJour || options.limiteParCombat || options.dose || options.limiteSoinsParJour)) { - error("Il faut préciser un soigneur pour ces options d'effet", options); + error("Il faut pr\xE9ciser un soigneur pour ces options d'effet", options); return; } let charId; @@ -30879,11 +31259,11 @@ var COFantasy = COFantasy || function() { if (options.tempeteDeManaIntense) nbDes += options.tempeteDeManaIntense; switch (argSoin) { case 'leger': - effet += ' légers'; + effet += ' l\xE9gers'; if (options.dose === undefined && options.limiteParJour === undefined) options.limiteAttribut = { nom: 'soinsLegers', - message: "ne peut plus lancer de sort de soins légers aujourd'hui", + message: "ne peut plus lancer de sort de soins l\xE9gers aujourd'hui", limite: rangSoin }; let bonusLeger = niveau + predicateAsInt(soigneur, 'voieDuGuerisseur', 0); @@ -30895,11 +31275,11 @@ var COFantasy = COFantasy || function() { if (options.portee === undefined) options.portee = 0; break; case 'modere': - effet += ' modérés'; + effet += ' mod\xE9r\xE9s'; if (options.dose === undefined && options.limiteParJour === undefined) options.limiteAttribut = { nom: 'soinsModeres', - message: "ne peut plus lancer de sort de soins modéréss aujourd'hui", + message: "ne peut plus lancer de sort de soins mod\xE9r\xE9ss aujourd'hui", limite: rangSoin }; if (options.portee === undefined) options.portee = 0; @@ -30953,7 +31333,7 @@ var COFantasy = COFantasy || function() { if (options.dose === undefined && options.limiteParJour === undefined) options.limiteAttribut = { nom: 'attributDeCombat_soinsDeGroupe', - message: " a déjà fait un soin de groupe durant ce combat", + message: " a d\xE9j\xE0 fait un soin de groupe durant ce combat", limite: 1 }; if (options.puissant) soins = "[[1d10"; @@ -30972,14 +31352,14 @@ var COFantasy = COFantasy || function() { case 'secondSouffle': { if (!stateCOF.combat) { - whisperChar(charId, " ne peut pas utiliser la capacité second souffle en dehors des combats"); + whisperChar(charId, " ne peut pas utiliser la capacit\xE9 second souffle en dehors des combats"); return; } effet = "second souffle"; if (options.dose === undefined && options.limiteParJour === undefined) options.limiteAttribut = { nom: 'secondSouffleUtilise', - message: " a déjà repris son souffle durant ce combat", + message: " a d\xE9j\xE0 repris son souffle durant ce combat", limite: 1 }; soins = "[[1d10+"; @@ -30989,8 +31369,8 @@ var COFantasy = COFantasy || function() { soins += "]]"; cible = soigneur; options.recuperation = true; - if (bonus == -1 || bonus > 0) { //Il y a un prédicat second souffle - //On limite les soins à ce qui a été perdu dans ce combat + if (bonus == -1 || bonus > 0) { //Il y a un pr\xE9dicat second souffle + //On limite les soins \xE0 ce qui a \xE9t\xE9 perdu dans ce combat const pvDebut = attributeAsInt(soigneur, 'PVsDebutCombat', 0); let pv = parseInt(soigneur.token.get('bar1_value')); if (isNaN(pv)) return; @@ -31039,7 +31419,7 @@ var COFantasy = COFantasy || function() { const playerId = getPlayerIdFromMsg(msg); if (options.tempeteDeMana && soigneur) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options const optMana = { mana: options.mana, rang: options.rang, @@ -31051,7 +31431,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(soigneur, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPerso(soigneur, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -31060,7 +31440,7 @@ var COFantasy = COFantasy || function() { soins = res[0].inlinerolls[0].results.total; let soinTxt = buildinline(res[0].inlinerolls[0], 'normal', true); if (soins <= 0) { - sendChar(charId, "ne réussit pas à soigner (total de soins " + soinTxt + ")", true); + sendChar(charId, "ne r\xE9ussit pas \xE0 soigner (total de soins " + soinTxt + ")", true); return; } const evt = { @@ -31093,7 +31473,7 @@ var COFantasy = COFantasy || function() { if (nbCibles > 1) { display = startFramedDisplay(playerId, effet, soigneur); } else if (nbCibles === 0) { - sendChar(charId, "personne à soigner", true); + sendChar(charId, "personne \xE0 soigner", true); return; } iterSelected(selected, callback); @@ -31139,7 +31519,7 @@ var COFantasy = COFantasy || function() { let utilisations = attributeAsInt(cible, ressourceLimiteCibleParJour, options.limiteCibleParJour); if (utilisations === 0) { - sendPerso(cible, "ne peut plus bénéficier de " + effet + " aujourd'hui"); + sendPerso(cible, "ne peut plus b\xE9n\xE9ficier de " + effet + " aujourd'hui"); finSoin(); return; } @@ -31175,11 +31555,11 @@ var COFantasy = COFantasy || function() { return; } if (display) { - addLineToFramedDisplay(display, "Résultat des dés : " + soinTxt); + addLineToFramedDisplay(display, "R\xE9sultat des d\xE9s : " + soinTxt); } if (msg.content.includes(' --sacrifierPV')) { //paie autant de PV que soins if (soigneur === undefined) { - error("Il faut préciser qui est le soigneur pour utiliser l'option --sacrifierPV", msg.content); + error("Il faut pr\xE9ciser qui est le soigneur pour utiliser l'option --sacrifierPV", msg.content); soinImpossible = true; display = undefined; finSoin(); @@ -31214,7 +31594,7 @@ var COFantasy = COFantasy || function() { let pv = parseInt(cible.token.get('bar1_value')); if (isNaN(pv) || pv > 0) { let sort = (souffleDeVie > 0) ? "souffle de vie" : "premiers soins"; - let m = nomPerso(cible) + " n'est pas à 0 PV, impossible d'utiliser " + sort + " pour " + onGenre(cible, 'lui', 'elle'); + let m = nomPerso(cible) + " n'est pas \xE0 0 PV, impossible d'utiliser " + sort + " pour " + onGenre(cible, 'lui', 'elle'); if (display) addLineToFramedDisplay(display, m); else sendChar(charId, m, true); finSoin(); @@ -31234,7 +31614,7 @@ var COFantasy = COFantasy || function() { } } if (tropTard) { - let m = nomPerso(cible) + " est à 0 PV depuis plus de 2 tours, impossible d'utiliser le souffle de vie pour " + onGenre(cible, 'lui', 'elle'); + let m = nomPerso(cible) + " est \xE0 0 PV depuis plus de 2 tours, impossible d'utiliser le souffle de vie pour " + onGenre(cible, 'lui', 'elle'); if (display) addLineToFramedDisplay(display, m); else sendChar(charId, m, true); finSoin(); @@ -31268,7 +31648,7 @@ var COFantasy = COFantasy || function() { } else { maxMsg += "soigner " + nomCible; } - sendChar(charId, maxMsg + ". " + Sujet + " est déjà au maximum de PV", true); + sendChar(charId, maxMsg + ". " + Sujet + " est d\xE9j\xE0 au maximum de PV", true); } }; let extraImg = afficheOptionImage(options); @@ -31288,9 +31668,9 @@ var COFantasy = COFantasy || function() { msgSoin = 'soigne ' + nomCible; } msgSoin += " de "; - if (options.recuperation) msgSoin = "récupère "; + if (options.recuperation) msgSoin = "r\xE9cup\xE8re "; if (limiteSoinsAtteinte || s != soins) - msgSoin += s + " PV. (Le résultat du jet était " + soinTxt + ")"; + msgSoin += s + " PV. (Le r\xE9sultat du jet \xE9tait " + soinTxt + ")"; else msgSoin += soinTxt + " PV."; msgSoin += extraImg; sendChar(charId, msgSoin, true); @@ -31299,7 +31679,7 @@ var COFantasy = COFantasy || function() { let callTrueFinal = printTrue; if (msg.content.includes(' --transfer')) { //paie avec ses PV if (soigneur === undefined) { - error("Il faut préciser qui est le soigneur pour utiliser l'option --transfer", msg.content); + error("Il faut pr\xE9ciser qui est le soigneur pour utiliser l'option --transfer", msg.content); soinImpossible = true; finSoin(); return; @@ -31342,15 +31722,15 @@ var COFantasy = COFantasy || function() { soigneToken(cible, soins, evt, callTrueFinal, callMax, options); finSoin(); }); //fin de iterCibles - }); //fin du sendChat du jet de dés + }); //fin du sendChat du jet de d\xE9s } catch (e) { if (soins) { log(msg.content); - log("L'expression des soins était " + soins + ", et il y a eu une erreur durant son évaluation"); + log("L'expression des soins \xE9tait " + soins + ", et il y a eu une erreur durant son \xE9valuation"); if (argSoin) { - error("L'expression des soins (" + argSoin + ") n'est pas bien formée", msg.content); + error("L'expression des soins (" + argSoin + ") n'est pas bien form\xE9e", msg.content); } else { - error("Erreur pendant l'évaluation de l'expression des soins. Plus d'informations dans le log", msg); + error("Erreur pendant l'\xE9valuation de l'expression des soins. Plus d'informations dans le log", msg); } } else { error("Erreur pendant les soins ", msg.content); @@ -31394,7 +31774,7 @@ var COFantasy = COFantasy || function() { } function ajouterConsommable(perso, nom, nb, action, evt) { - if (perso.token.get('bar1_link') === '') { //Perso non lié, on utilise un attribut + if (perso.token.get('bar1_link') === '') { //Perso non li\xE9, on utilise un attribut let attrName = 'dose_' + nom; let attr = tokenAttribute(perso, attrName); if (attr.length > 0) { @@ -31416,7 +31796,7 @@ var COFantasy = COFantasy || function() { maxVal: action }); } - } else { //On va mettre les consommables dans l'équipement + } else { //On va mettre les consommables dans l'\xE9quipement let attributes = findObjs({ _type: 'attribute', _characterid: perso.charId @@ -31466,7 +31846,7 @@ var COFantasy = COFantasy || function() { }); return true; }); - // si le consommable n'a pas été trouvé, on le crée avec une valeur de nb + // si le consommable n'a pas \xE9t\xE9 trouv\xE9, on le cr\xE9e avec une valeur de nb if (!found) { let pref = 'repeating_equipement_' + generateRowID() + '_'; let attre = createObj("attribute", { @@ -31506,11 +31886,11 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(lanceur) { let voieDeLaSurvie = predicateAsInt(lanceur, 'voieDeLaSurvie', 0); if (voieDeLaSurvie < 1) { - sendPerso(lanceur, " ne connaît pas la Voie de la Survie ?"); + sendPerso(lanceur, " ne conna\xEEt pas la Voie de la Survie ?"); } doNatureNourriciere(lanceur, options); }); - }); + }, options); } function doNatureNourriciere(perso, options) { @@ -31532,7 +31912,7 @@ var COFantasy = COFantasy || function() { } let output = "cherche des herbes. "; if (trouveBaies) output = "cherche des baies. "; - output += "Après " + evt.action.rolls.duree.roll + " heure"; + output += "Apr\xE8s " + evt.action.rolls.duree.roll + " heure"; if (evt.action.rolls.duree.val > 1) output += "s"; output += ", " + onGenre(perso, "il", "elle"); const testId = 'natureNourriciere'; @@ -31541,11 +31921,11 @@ var COFantasy = COFantasy || function() { let post = ""; if ((tr.reussite && !trouveBaies) || (trouveBaies && !tr.reussite && tr.valeur > 7)) { if (voieDeLaSurvie > 0) { - output += " revient avec " + voieDeLaSurvie + " plantes médicinales." + tr.modifiers; + output += " revient avec " + voieDeLaSurvie + " plantes m\xE9dicinales." + tr.modifiers; let actionHerbes = "!cof-soin @{selected|token_id} @{selected|token_id} 1d6"; - ajouterConsommable(perso, 'Plante médicinale', voieDeLaSurvie, actionHerbes, evt); + ajouterConsommable(perso, 'Plante m\xE9dicinale', voieDeLaSurvie, actionHerbes, evt); } else { - output += " revient avec de quoi soigner les blessés." + tr.modifiers; + output += " revient avec de quoi soigner les bless\xE9s." + tr.modifiers; } } else if (tr.reussite && trouveBaies) { let niveau = ficheAttributeAsInt(perso, 'niveau', 1); @@ -31568,10 +31948,10 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; let evtARefaire = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[1]); if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } @@ -31579,11 +31959,11 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(chevalier) { let token = chevalier.token; if (attributeAsInt(chevalier, 'douleurIgnoree', 0) > 0) { - sendPerso(chevalier, "a déjà ignoré la doubleur une fois pendant ce combat"); + sendPerso(chevalier, "a d\xE9j\xE0 ignor\xE9 la doubleur une fois pendant ce combat"); return; } if (evtARefaire === undefined || evtARefaire.type === undefined || !evtARefaire.type.startsWith('Attaque')) { - sendPerso(chevalier, "s'y prend trop tard pour ignorer la douleur : la dernière action n'était pas une attaque"); + sendPerso(chevalier, "s'y prend trop tard pour ignorer la douleur : la derni\xE8re action n'\xE9tait pas une attaque"); return; } let aIgnore; @@ -31591,18 +31971,18 @@ var COFantasy = COFantasy || function() { type: 'ignorer la douleur' }; let PVid = token.get('bar1_link'); - if (PVid === '') { //token non lié, effets seulement sur le token. + if (PVid === '') { //token non li\xE9, effets seulement sur le token. if (evtARefaire.affecte) { let affecte = evtARefaire.affectes[token.id]; if (affecte && affecte.prev) { let lastBar1 = affecte.prev.bar1_value; let bar1 = parseInt(token.get('bar1_value')); if (isNaN(lastBar1) || isNaN(bar1) || lastBar1 <= bar1) { - //On regarde la barre 2, peut-être qu'il s'agit de DM temporaires + //On regarde la barre 2, peut-\xEAtre qu'il s'agit de DM temporaires let lastBar2 = affecte.prev.bar2_value; let bar2 = parseInt(token.get('bar2_value')); if (isNaN(lastBar2) || isNaN(bar2) || bar2 <= lastBar2) { - sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la dernière attaque ne lui ait pas enlevé de PV"); + sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la derni\xE8re attaque ne lui ait pas enlev\xE9 de PV"); return; } updateCurrentBar(chevalier, 2, lastBar2, evt); @@ -31615,7 +31995,7 @@ var COFantasy = COFantasy || function() { } } } - } else { // token lié, il faut regarder l'attribut + } else { // token li\xE9, il faut regarder l'attribut let attrPV = evtARefaire.attributes.find(function(attr) { return (attr.attribute.id == PVid); }); @@ -31623,13 +32003,13 @@ var COFantasy = COFantasy || function() { let lastPV = attrPV.current; let newPV = attrPV.attribute.get('current'); if (isNaN(lastPV) || isNaN(newPV) || lastPV <= newPV) { - sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la dernière attaque ne lui ait pas enlevé de PV"); + sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la derni\xE8re attaque ne lui ait pas enlev\xE9 de PV"); return; } updateCurrentBar(chevalier, 1, lastPV, evt); setTokenAttr(chevalier, 'douleurIgnoree', lastPV - newPV, evt); aIgnore = true; - } else { //peut-être qu'il s'agit de DM temporaires + } else { //peut-\xEAtre qu'il s'agit de DM temporaires PVid = token.get('bar2_link'); attrPV = evtARefaire.attributes.find(function(attr) { return (attr.attribute.id == PVid); @@ -31638,7 +32018,7 @@ var COFantasy = COFantasy || function() { let lastDmTemp = attrPV.current; let newDmTemp = attrPV.attribute.get('current'); if (isNaN(lastDmTemp) || isNaN(newDmTemp) || newDmTemp <= lastDmTemp) { - sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la dernière attaque ne lui ait pas augmenté les DM temporaires"); + sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la derni\xE8re attaque ne lui ait pas augment\xE9 les DM temporaires"); return; } updateCurrentBar(chevalier, 2, lastDmTemp, evt); @@ -31648,13 +32028,13 @@ var COFantasy = COFantasy || function() { } } if (aIgnore) { - sendPerso(chevalier, " ignore la douleur de la dernière attaque"); + sendPerso(chevalier, " ignore la douleur de la derni\xE8re attaque"); addEvent(evt); } else { - sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la dernière attaque ne l'ait pas affecté"); + sendPerso(chevalier, "ne peut ignorer la douleur : il semble que la derni\xE8re attaque ne l'ait pas affect\xE9"); } }); - }); + }, options); } function fortifiant(msg) { @@ -31662,7 +32042,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("La fonction !cof-fortifiant attend en argument le rang dans la Voie des élixirs du créateur", cmd); + error("La fonction !cof-fortifiant attend en argument le rang dans la Voie des \xE9lixirs du cr\xE9ateur", cmd); return; } const rang = parseInt(cmd[1]); @@ -31683,19 +32063,19 @@ var COFantasy = COFantasy || function() { }); sendPerso(beneficiaire, " boit un fortifiant"); soigneToken(beneficiaire, soins.val, evt, function(soinsEffectifs) { - let msgSoins = "et est soigné de "; + let msgSoins = "et est soign\xE9 de "; if (soinsEffectifs == soins.val) msgSoins += soins.roll + " PV"; - else msgSoins += soinsEffectifs + " PV (le jet était " + soins.roll + ")"; + else msgSoins += soinsEffectifs + " PV (le jet \xE9tait " + soins.roll + ")"; sendPerso(beneficiaire, msgSoins); }); // Finalement on met l'effet fortifie setTokenAttr(beneficiaire, 'fortifie', rang + 1, evt); }); - }); + }, options); } //Appliquer une huile instable sur l'arme de la cible - // Par défaut, c'est l'arme en main de la cible + // Par d\xE9faut, c'est l'arme en main de la cible // TODO: le faire pour les projectiles // !cof-huile-instable @{target|token_id} function huileInstable(msg) { @@ -31744,7 +32124,7 @@ var COFantasy = COFantasy || function() { _id: options.lanceur.token.id }]; } else { - error("Pas de token sélectionée pour !cof-lancer-sort", cmd); + error("Pas de token s\xE9lection\xE9e pour !cof-lancer-sort", cmd); return; } } @@ -31756,7 +32136,7 @@ var COFantasy = COFantasy || function() { let lanceur = options.lanceur; if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, dm: false, @@ -31769,7 +32149,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(lanceur, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPerso(lanceur, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -31782,7 +32162,7 @@ var COFantasy = COFantasy || function() { if (!options.lanceur) { if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options const optMana = { mana: options.mana, dm: false, @@ -31795,7 +32175,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(cible, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPerso(cible, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -31845,11 +32225,11 @@ var COFantasy = COFantasy || function() { sendChat(nomPerso, cmd.join(' ')); } - // Renvoie la durée mise à jour ou undefined si l'action n'est pas possible + // Renvoie la dur\xE9e mise \xE0 jour ou undefined si l'action n'est pas possible function lancerMurDeForce(lanceur, playerId, duree, msg, typeMur, evt, options) { if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, dm: false, @@ -31862,7 +32242,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPerso(lanceur, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPerso(lanceur, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -31885,7 +32265,7 @@ var COFantasy = COFantasy || function() { } //!cof-mur-de-force [opt] [duree] - // opt peut être mur, noImage ou vent + // opt peut \xEAtre mur, noImage ou vent // On peut changer la taille du mur avec l'option --portee. function murDeForce(msg) { let options = parseOptions(msg); @@ -31915,13 +32295,13 @@ var COFantasy = COFantasy || function() { if (cmd.length > 2) { duree = parseInt(cmd[2]); if (isNaN(duree) || duree < 1) { - error("Le deuxième argument de !cof-mur-de-force doit être une durée", cmd); + error("Le deuxi\xE8me argument de !cof-mur-de-force doit \xEAtre une dur\xE9e", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Aucun personnage sélectionné pour lancer le mur de " + typeMur, playerId); + sendPlayer(msg, "Aucun personnage s\xE9lectionn\xE9 pour lancer le mur de " + typeMur, playerId); return; } const evt = { @@ -31974,7 +32354,7 @@ var COFantasy = COFantasy || function() { if (options.puissantDuree || options.tempeteDeManaDuree) duree += duree; setAttrDuree(cible, 'murDeForce', duree, evt); } else { - error("Impossible de créer l'image " + options.image, imageFields); + error("Impossible de cr\xE9er l'image " + options.image, imageFields); } } else { sendPlayerAndGM(msg, playerId, "placer l'image du mur sur la carte"); @@ -32021,7 +32401,7 @@ var COFantasy = COFantasy || function() { } else { capitaine = persoOfId(cmd[1], cmd[1]); if (capitaine === undefined) { - error("Le premier argument de !cof-capitaine doit être un token", cmd[1]); + error("Le premier argument de !cof-capitaine doit \xEAtre un token", cmd[1]); return; } setState(capitaine, 'chef', true, evt); @@ -32029,7 +32409,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 2 && !cmd[2].startsWith('--')) { bonus = parseInt(cmd[2]); if (isNaN(bonus) || bonus < 0) { - error("Le bonus de capitaine (second argument) doit être un nombre positif", cmd); + error("Le bonus de capitaine (second argument) doit \xEAtre un nombre positif", cmd); return; } if (bonus === 0) remove = true; @@ -32038,7 +32418,7 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected) { if (selected.length === 0) { - error("Pas de token sélectionné pour !cof-capitaine"); + error("Pas de token s\xE9lectionn\xE9 pour !cof-capitaine"); return; } iterSelected(selected, function(perso) { @@ -32063,12 +32443,12 @@ var COFantasy = COFantasy || function() { function distribuerBaies(msg) { if (msg.selected === undefined || msg.selected.length != 1) { - error("Pour utiliser !cof-distribuer-baies, il faut sélectionner un token", msg); + error("Pour utiliser !cof-distribuer-baies, il faut s\xE9lectionner un token", msg); return; } let druide = persoOfId(msg.selected[0]._id); if (druide === undefined) { - error("Erreur de sélection dans !cof-distribuer-baies", msg.selected); + error("Erreur de s\xE9lection dans !cof-distribuer-baies", msg.selected); return; } let niveau = ficheAttributeAsInt(druide, 'niveau', 1); @@ -32082,7 +32462,7 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(perso) { let nom = nomPerso(perso); ajouterConsommable(perso, 'Baie magique', 1, mangerBaie, evt); - let line = nom + " reçoit une baie"; + let line = nom + " re\xE7oit une baie"; if (perso.token.id == druide.token.id) line = nom + " en garde une pour " + onGenre(druide, "lui", "elle"); addLineToFramedDisplay(display, line); @@ -32100,17 +32480,17 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd.length < 2) { - error("Il faut un argument à !cof-consommer-baie", cmd); + error("Il faut un argument \xE0 !cof-consommer-baie", cmd); return; } let baie = parseInt(cmd[1]); if (isNaN(baie) || baie < 0) { - error("L'argument de !cof-consommer-baie doit être un nombre positif", cmd); + error("L'argument de !cof-consommer-baie doit \xEAtre un nombre positif", cmd); return; } getSelected(msg, function(selected, playerId) { if (selected === undefined) { - sendPlayer(msg, "Pas de token sélectionné pour !cof-consommer-baie", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof-consommer-baie", playerId); return; } const evt = { @@ -32118,21 +32498,21 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); iterSelected(selected, function(perso) { - if (limiteRessources(perso, options, 'baieMagique', "a déjà mangé une baie aujourd'hui. Pas d'effet.", evt)) return; + if (limiteRessources(perso, options, 'baieMagique', "a d\xE9j\xE0 mang\xE9 une baie aujourd'hui. Pas d'effet.", evt)) return; let soins = rollDePlus(6, { bonus: baie }); soigneToken(perso, soins.val, evt, function(soinsEffectifs) { let msgSoins = "mange une baie magique. " + - onGenre(perso, "Il est rassasié", "Elle est rassasiée") + - " et récupère "; + onGenre(perso, "Il est rassasi\xE9", "Elle est rassasi\xE9e") + + " et r\xE9cup\xE8re "; if (soinsEffectifs == soins.val) msgSoins += soins.roll + " points de vie"; - else msgSoins += soinsEffectifs + " PV (le jet était " + soins.roll + ")"; + else msgSoins += soinsEffectifs + " PV (le jet \xE9tait " + soins.roll + ")"; sendPerso(perso, msgSoins); }, function() { - sendPerso(perso, "mange une baie magique. " + onGenre(perso, "Il", "Elle") + " se sent rassasié" + onGenre(perso, '', 'e') + '.'); + sendPerso(perso, "mange une baie magique. " + onGenre(perso, "Il", "Elle") + " se sent rassasi\xE9" + onGenre(perso, '', 'e') + '.'); }); }); }); //fin de getSelected @@ -32152,9 +32532,9 @@ var COFantasy = COFantasy || function() { } } - /* Quand on protège un allié, on stocke l'idName dans un attribut 'protegerUnAllie', et pour ce token, on met un - * attribut 'protegePar_nom' où nom est le nom du token protecteur, et qui contient l'idName du protecteur - * Ces attributs disparaissent à la fin des combats */ + /* Quand on prot\xE8ge un alli\xE9, on stocke l'idName dans un attribut 'attributDeComat_protegerUnAllie', et pour ce token, on met un + * attribut 'protegePar_nom' o\xF9 nom est le nom du token protecteur, et qui contient l'idName du protecteur + * Ces attributs disparaissent \xE0 la fin des combats */ function protegerUnAllie(msg) { let args = msg.content.split(' '); if (args.length < 3) { @@ -32171,53 +32551,53 @@ var COFantasy = COFantasy || function() { let pageId = tokenProtecteur.get('pageid'); let target = persoOfId(args[2], args[2], pageId); if (target === undefined) { - error("Le deuxième argument n'est pas un token valide: " + msg.content, args[2]); + error("Le deuxi\xE8me argument n'est pas un token valide: " + msg.content, args[2]); return; } let tokenTarget = target.token; if (tokenTarget.id == tokenProtecteur.id) { - sendPerso(protecteur, "ne peut pas se protéger i" + onGenre(protecteur, 'lui', 'elle') + "-même"); + sendPerso(protecteur, "ne peut pas se prot\xE9ger i" + onGenre(protecteur, 'lui', 'elle') + "-m\xEAme"); return; } const nameTarget = nomPerso(target); const evt = { - type: "Protéger un allié" + type: "Prot\xE9ger un alli\xE9" }; - let attrsProtecteur = tokenAttribute(protecteur, 'protegerUnAllie'); + let attrsProtecteur = tokenAttribute(protecteur, 'attributDeCombat_protegerUnAllie'); let protegePar = 'protegePar_' + nameProtecteur; let other; - if (attrsProtecteur.length > 0) { //On protège déjà quelqu'un + if (attrsProtecteur.length > 0) { //On prot\xE8ge d\xE9j\xE0 quelqu'un let previousTarget = persoOfIdName(attrsProtecteur[0].get('current'), pageId); if (previousTarget) { if (previousTarget.token.id == tokenTarget.id) { - sendPerso(protecteur, "protège déjà " + nameTarget); + sendPerso(protecteur, "prot\xE8ge d\xE9j\xE0 " + nameTarget); return; } - if (predicateAsBool(protecteur, 'protegerUnAllieAvance')) { + if (predicateAsBool(protecteur, 'attributDeCombat_protegerUnAllieAvance')) { let previousTarget2 = persoOfIdName(attrsProtecteur[0].get('max'), pageId); if (previousTarget2) { if (previousTarget2.token.id == tokenTarget.id) { - sendPerso(protecteur, "protège déjà " + nameTarget); + sendPerso(protecteur, "prot\xE8ge d\xE9j\xE0 " + nameTarget); return; } removeTokenAttr(previousTarget2, protegePar, evt, { - msg: "n'est plus protégé par " + nameProtecteur + msg: "n'est plus prot\xE9g\xE9 par " + nameProtecteur }); } else { other = attrsProtecteur[0].get('current'); } } removeTokenAttr(previousTarget, protegePar, evt, { - msg: "n'est plus protégé par " + nameProtecteur + msg: "n'est plus prot\xE9g\xE9 par " + nameProtecteur }); } } let distTargetProtecteur = distanceCombat(target.token, protecteur.token, pageId); if (distTargetProtecteur > 0) { sendPerso(protecteur, "est trop loin de " + - nameTarget + " pour le protéger"); + nameTarget + " pour le prot\xE9ger"); return; } if (ficheAttributeAsInt(protecteur, 'defbouclieron', 0) === 0) { @@ -32230,30 +32610,30 @@ var COFantasy = COFantasy || function() { maxVal: '' }; if (other === undefined) { - setTokenAttr(protecteur, 'protegerUnAllie', idName(target), evt, opt); + setTokenAttr(protecteur, 'attributDeCombat_protegerUnAllie', idName(target), evt, opt); } else { opt.maxVal = idName(target); - setTokenAttr(protecteur, 'protegerUnAllie', other, evt, opt); + setTokenAttr(protecteur, 'attributDeCombat_protegerUnAllie', other, evt, opt); } setTokenAttr(target, protegePar, idName(protecteur), evt); - sendPerso(protecteur, "protège " + nameTarget); + sendPerso(protecteur, "prot\xE8ge " + nameTarget); addEvent(evt); } function actionDefensive(msg) { let combat = stateCOF.combat; if (!combat) { - sendPlayer(msg, "Il faut entrer en combat pour se défendre"); + sendPlayer(msg, "Il faut entrer en combat pour se d\xE9fendre"); return; } let cmd = msg.content.split(' '); - let def = 2; //pour une défense simple - let defMsg = "préfère se défendre pendant ce tour"; + let def = 2; //pour une d\xE9fense simple + let defMsg = "pr\xE9f\xE8re se d\xE9fendre pendant ce tour"; if (cmd.length > 1) { switch (cmd[1]) { case 'totale': def = 4; - defMsg = "se consacre entièrement à sa défense pendant ce tour"; + defMsg = "se consacre enti\xE8rement \xE0 sa d\xE9fense pendant ce tour"; break; case 'simple': def = 2; @@ -32263,7 +32643,7 @@ var COFantasy = COFantasy || function() { } } const evt = { - type: "action défensive" + type: "action d\xE9fensive" }; getSelected(msg, function(selected) { initiative(selected, evt); @@ -32278,20 +32658,20 @@ var COFantasy = COFantasy || function() { } function strangulation(msg) { - var args = msg.content.split(' '); + const args = msg.content.split(' '); if (args.length < 3) { error("Pas assez d'arguments pour !cof-strangulation: " + msg.content, args); return; } - var necromancien = persoOfId(args[1], args[1]); + const necromancien = persoOfId(args[1], args[1]); if (necromancien === undefined) { error("Le premier argument n'est pas un token", args[1]); return; } - var pageId = necromancien.token.get('pageid'); - var target = persoOfId(args[2], args[2], pageId); + let pageId = necromancien.token.get('pageid'); + const target = persoOfId(args[2], args[2], pageId); if (target === undefined) { - error("Le deuxième argument n'est pas un token valide: " + msg.content, args[2]); + error("Le deuxi\xE8me argument n'est pas un token valide: " + msg.content, args[2]); return; } let name2 = nomPerso(target); @@ -32299,15 +32679,15 @@ var COFantasy = COFantasy || function() { sendPerso(necromancien, "ne peut pas maintenir la strangulation. Il faut (re)lancer le sort"); return; } - var evt = { + const evt = { type: "Strangulation" }; - var dureeStrang = tokenAttribute(target, 'dureeStrangulation'); - var nouvelleDuree = 1; + let dureeStrang = tokenAttribute(target, 'dureeStrangulation'); + let nouvelleDuree = 1; if (dureeStrang.length > 0) { nouvelleDuree = parseInt(dureeStrang[0].get('current')); if (isNaN(nouvelleDuree)) { - log("Durée de strangulation n'est pas un nombre"); + log("Dur\xE9e de strangulation n'est pas un nombre"); log(dureeStrang); nouvelleDuree = 1; } else nouvelleDuree++; @@ -32323,7 +32703,7 @@ var COFantasy = COFantasy || function() { else if (modInt < 0) dmgExpr += modInt; dmgExpr += "]]"; sendChat('', dmgExpr, function(res) { - var dmg = { + const dmg = { type: 'magique', total: res[0].inlinerolls[0].results.total, display: buildinline(res[0].inlinerolls[0], 'normal', true), @@ -32340,27 +32720,27 @@ var COFantasy = COFantasy || function() { function ombreMortelle(msg) { - var options = parseOptions(msg); + const options = parseOptions(msg); if (options === undefined) return; - var cmd = options.cmd; + const cmd = options.cmd; if (cmd === undefined || cmd.length < 4) { error("Pas assez d'arguments pour " + cmd[0], cmd); return; } - var lanceur = persoOfId(cmd[1], cmd[1]); + const lanceur = persoOfId(cmd[1], cmd[1]); if (lanceur === undefined) { error("Le premier argument n'est pas un token valide", cmd[1]); return; } - var pageId = options.pageId || lanceur.token.get('pageid'); - var cible = persoOfId(cmd[2], cmd[2], pageId); + const pageId = options.pageId || lanceur.token.get('pageid'); + const cible = persoOfId(cmd[2], cmd[2], pageId); if (cible === undefined) { error("La cible n'est pas un token valide", cmd[2]); return; } let duree = parseInt(cmd[3]); if (isNaN(duree) || duree <= 0) { - error("La durée doit être un nombre positif", cmd); + error("La dur\xE9e doit \xEAtre un nombre positif", cmd); return; } let image = options.image || stateCOF.options.images.val.image_ombre.val; @@ -32378,13 +32758,13 @@ var COFantasy = COFantasy || function() { let msgRes = "invoquer une ombre mortelle"; if (limiteRessources(lanceur, options, "Ombre_mortelle", msgRes, evt)) return; copieToken(cible, image, stateCOF.options.images.val.image_ombre.val, "Ombre de " + nomPerso(cible), 'ombreMortelle', duree, pageId, evt); - let msgOmbre = "anime l'ombre de " + cible.tokName + ". Celle-ci commence à attaquer " + cible.tokName + " !"; + let msgOmbre = "anime l'ombre de " + cible.tokName + ". Celle-ci commence \xE0 attaquer " + cible.tokName + " !"; if (options.secret) whisperChar(lanceur.charId, msgOmbre); else sendPerso(lanceur, msgOmbre); addEvent(evt); } - //renvoie l'attribut de l'effet temporaire créé + //renvoie l'attribut de l'effet temporaire cr\xE9\xE9 function copieToken(cible, image1, image2, nom, effet, duree, pageId, evt) { let pv = parseInt(cible.token.get('bar1_value')); if (isNaN(pv)) { @@ -32431,7 +32811,7 @@ var COFantasy = COFantasy || function() { newToken = createObj('graphic', tokenFields); } if (newToken === undefined) { - error("L'image du token sélectionné n'a pas été uploadé, et l'image par défaut n'est pas correcte. Impossible de créer un token.", tokenFields); + error("L'image du token s\xE9lectionn\xE9 n'a pas \xE9t\xE9 upload\xE9, et l'image par d\xE9faut n'est pas correcte. Impossible de cr\xE9er un token.", tokenFields); return; } } @@ -32447,12 +32827,12 @@ var COFantasy = COFantasy || function() { return attr; } - //retourne true si le joueur est effectivement déplacé + //retourne true si le joueur est effectivement d\xE9plac\xE9 function movePlayerToPage(pid, oldPageId, newPageId) { if (getObj('player', pid) === undefined) return; - var c = Campaign(); - var playerPages = c.get('playerspecificpages'); - var playersMainPage = c.get('playerpageid'); + const c = Campaign(); + let playerPages = c.get('playerspecificpages'); + const playersMainPage = c.get('playerpageid'); if (!playerPages) playerPages = {}; if ((playerPages[pid] && playerPages[pid] == oldPageId)) { if (playersMainPage == newPageId) { @@ -32468,10 +32848,10 @@ var COFantasy = COFantasy || function() { } } else if ((!playerPages[pid] && playersMainPage == oldPageId)) { playerPages[pid] = newPageId; - var allPlayers = findObjs({ + let allPlayers = findObjs({ _type: 'player' }); - var allOnNewPage = allPlayers.every(function(p) { + let allOnNewPage = allPlayers.every(function(p) { if (playerIsGM(p.id)) return true; return playerPages[p.id] == newPageId; }); @@ -32485,8 +32865,8 @@ var COFantasy = COFantasy || function() { } function findEsc(escaliers, escName, i) { - var fullEscName = escName + labelsEscalier[i]; - var sortieEscalier = escaliers.find(function(esc) { + let fullEscName = escName + labelsEscalier[i]; + let sortieEscalier = escaliers.find(function(esc) { return esc.get('name') == fullEscName; }); if (sortieEscalier === undefined && i > 0) return findEsc(escName, i - 1); @@ -32500,17 +32880,17 @@ var COFantasy = COFantasy || function() { return ((pos2 + size2 / 2) >= pos1 - size1 / 2); } - var labelsEscalier = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]; + const labelsEscalier = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"]; function escalier(msg) { getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de sélection de token pour !cof-escalier", playerId); - log("!cof-escalier requiert de sélectionner des tokens"); + sendPlayer(msg, "Pas de s\xE9lection de token pour !cof-escalier", playerId); + log("!cof-escalier requiert de s\xE9lectionner des tokens"); return; } let pageId = getObj('graphic', selected[0]._id).get('pageid'); - var escaliers = findObjs({ + let escaliers = findObjs({ _type: 'graphic', _pageid: pageId, layer: 'gmlayer' @@ -32519,9 +32899,9 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "Pas de token dans le layer GM", playerId); return; } - var tmaps; //Les passages entre les maps. - var versLeHaut = true; - var loop = true; + let tmaps; //Les passages entre les maps. + let versLeHaut = true; + let loop = true; if (msg.content) { if (msg.content.includes(' bas')) { versLeHaut = false; @@ -32532,22 +32912,22 @@ var COFantasy = COFantasy || function() { } } iterSelected(selected, function(perso) { - var token = perso.token; - var posX = token.get('left'); - var sizeX = token.get('width'); - var posY = token.get('top'); - var sizeY = token.get('height'); - var sortieEscalier; + let token = perso.token; + let posX = token.get('left'); + let sizeX = token.get('width'); + let posY = token.get('top'); + let sizeY = token.get('height'); + let sortieEscalier; escaliers.forEach(function(esc) { if (sortieEscalier) return; if (intersection(posX, sizeX, esc.get('left'), esc.get('width')) && intersection(posY, sizeY, esc.get('top'), esc.get('height'))) { - var escName = esc.get('name'); - var l = escName.length; + let escName = esc.get('name'); + let l = escName.length; if (l > 1) { - var label = escName.substr(l - 1, 1); + let label = escName.substr(l - 1, 1); escName = escName.substr(0, l - 1); - var i = labelsEscalier.indexOf(label); + let i = labelsEscalier.indexOf(label); if (versLeHaut) { if (i == 11) { if (loop) escName += labelsEscalier[0]; @@ -32557,7 +32937,7 @@ var COFantasy = COFantasy || function() { if (loop) escName += labelsEscalier[11]; } else escName += labelsEscalier[i - 1]; } - var escs = escaliers; + let escs = escaliers; if (escName.startsWith('tmap_')) { if (!tmaps) { tmaps = findObjs({ @@ -32590,16 +32970,16 @@ var COFantasy = COFantasy || function() { let left = sortieEscalier.get('left'); let top = sortieEscalier.get('top'); let newPageId = sortieEscalier.get('pageid'); - //Déplacement du token + //D\xE9placement du token if (newPageId == pageId) { token.set('left', left); token.set('top', top); } else { //On change de carte, il faut donc copier le token - var tokenObj = JSON.parse(JSON.stringify(token)); + let tokenObj = JSON.parse(JSON.stringify(token)); tokenObj._pageid = newPageId; - //On met la taille du token à jour en fonction des échelles des cartes. - var ratio = computeScale(pageId) / computeScale(newPageId); + //On met la taille du token \xE0 jour en fonction des \xE9chelles des cartes. + let ratio = computeScale(pageId) / computeScale(newPageId); if (ratio < 0.9 || ratio > 1.1) { if (ratio < 0.25) ratio = 0.25; else if (ratio > 4) ratio = 4; @@ -32615,12 +32995,12 @@ var COFantasy = COFantasy || function() { return; } } - //On déplace ensuite le joueur. + //On d\xE9place ensuite le joueur. let character = getObj('character', perso.charId); if (character === undefined) return; let charControlledby = character.get('controlledby'); if (charControlledby === '') { - //Seul le MJ contrôle le personnage + //Seul le MJ contr\xF4le le personnage let players = findObjs({ _type: 'player', online: true @@ -32638,7 +33018,7 @@ var COFantasy = COFantasy || function() { sendPing(left, top, newPageId, pid, true, pid); }); } - //Enfin, on efface le token de départ si on a changé de page + //Enfin, on efface le token de d\xE9part si on a chang\xE9 de page if (newPageId != pageId) token.remove(); return; } @@ -32653,45 +33033,45 @@ var COFantasy = COFantasy || function() { } function defautDansLaCuirasse(msg) { - var args = msg.content.split(' '); + let args = msg.content.split(' '); if (args.length < 3) { error("Pas assez d'arguments pour !cof-defaut-dans-la-cuirasse", args); return; } - var tireur = persoOfId(args[1], args[1]); + let tireur = persoOfId(args[1], args[1]); if (tireur === undefined) { error("Le premier argument n'est pas un token valide", args[1]); return; } - var pageId = tireur.token.get('pageid'); - var cible = persoOfId(args[2], args[2], pageId); + let pageId = tireur.token.get('pageid'); + let cible = persoOfId(args[2], args[2], pageId); if (cible === undefined) { error("La cible n'est pas un token valide", args[2]); return; } - var evt = { - type: "Défaut dans la cuirasse" + const evt = { + type: "D\xE9faut dans la cuirasse" }; setTokenAttr(cible, 'defautDansLaCuirasse_' + nomPerso(tireur), 2, evt); - sendPerso(tireur, "passe le tour à analyser les points faibles de " + nomPerso(cible)); + sendPerso(tireur, "passe le tour \xE0 analyser les points faibles de " + nomPerso(cible)); addEvent(evt); } function postureDeCombat(msg) { - var args = msg.content.split(' '); + let args = msg.content.split(' '); if (args.length < 4) { error("Pas assez d'arguments pour !cof-posture-de-combat", args); return; } - var bonus = parseInt(args[1]); - var attrDebuf = args[2]; + let bonus = parseInt(args[1]); + let attrDebuf = args[2]; if (attrDebuf != 'DEF' && attrDebuf != 'ATT' && attrDebuf != 'DM') { - error("L'attribut à débuffer pour la posture de combat est incorrect", args); + error("L'attribut \xE0 d\xE9buffer pour la posture de combat est incorrect", args); return; } - var attrBuf = args[3]; + let attrBuf = args[3]; if (attrBuf != 'DEF' && attrBuf != 'ATT' && attrBuf != 'DM') { - error("L'attribut à augmenter pour la posture de combat est incorrect", args); + error("L'attribut \xE0 augmenter pour la posture de combat est incorrect", args); return; } getSelected(msg, function(selected, playerId) { @@ -32700,12 +33080,12 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "choisir un bonus positif (pas " + args[1] + ") pour sa posture de combat", playerId); return; } - var rang = predicateAsInt(guerrier, "voieDuSoldat", 0); + let rang = predicateAsInt(guerrier, "voieDuSoldat", 0); if (rang > 0 && rang < bonus) { - sendPerso(guerrier, "ne peut choisir qu'un bonus inférieur à " + rang + " pour sa posture de combat"); + sendPerso(guerrier, "ne peut choisir qu'un bonus inf\xE9rieur \xE0 " + rang + " pour sa posture de combat"); return; } - var evt = { + const evt = { type: "Posture de combat" }; if (attrBuf == attrDebuf) { @@ -32717,7 +33097,7 @@ var COFantasy = COFantasy || function() { msg = "prend une posture "; switch (attrBuf) { case 'DEF': - msg += "défensive"; + msg += "d\xE9fensive"; break; case 'ATT': msg += "offensive"; @@ -32730,10 +33110,10 @@ var COFantasy = COFantasy || function() { msg += " mais "; switch (attrDebuf) { case 'DEF': - msg += "risquée"; + msg += "risqu\xE9e"; break; case 'ATT': - msg += "moins précise"; + msg += "moins pr\xE9cise"; break; case 'DM': msg += "moins puissante"; @@ -32757,21 +33137,21 @@ var COFantasy = COFantasy || function() { } let bonus = parseInt(args[1]); if (bonus != 0 && bonus != 2 && bonus != 5) { - error("Le malus de DEF ne peut être que 0, 2 ou 5", args); + error("Le malus de DEF ne peut \xEAtre que 0, 2 ou 5", args); return; } getSelected(msg, function(selected) { iterSelected(selected, function(guerrier) { const evt = { - type: "Attaque à outrance" + type: "Attaque \xE0 outrance" }; if (bonus === 0) { - sendPerso(guerrier, "n'attaque plus à outrance"); + sendPerso(guerrier, "n'attaque plus \xE0 outrance"); removeTokenAttr(guerrier, 'attaqueAOutrance', evt); addEvent(evt); return; } - msg = "attaque à outrance "; + msg = "attaque \xE0 outrance "; switch (bonus) { case 2: msg += "(-2 DEF, +1D6 DM)"; @@ -32793,14 +33173,14 @@ var COFantasy = COFantasy || function() { var options = parseOptions(msg); var cmd = options.cmd; if (cmd < 2) { - error("Il manque un argument à !cof-tour-de-force", cmd); + error("Il manque un argument \xE0 !cof-tour-de-force", cmd); return; } var seuil = parseInt(cmd[1]); getSelected(msg, function(selected, playerId) { iterSelected(selected, function(barbare) { if (isNaN(seuil)) { - sendPlayer(msg, "le seuil de difficulté du tour de force doit être un nombre", playerId); + sendPlayer(msg, "le seuil de difficult\xE9 du tour de force doit \xEAtre un nombre", playerId); return; } doTourDeForce(barbare, seuil, options); @@ -32818,18 +33198,18 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - let action = "Capacité : Tour de force"; + let action = "Capacit\xE9 : Tour de force"; let display = startFramedDisplay(options.playerId, action, perso); let testId = 'tourDeForce'; options.bonus = 10; testCaracteristique(perso, 'FOR', seuil, testId, options, evt, function(tr) { - addLineToFramedDisplay(display, " Jet de force difficulté " + seuil); + addLineToFramedDisplay(display, " Jet de force difficult\xE9 " + seuil); let smsg = nomPerso(perso) + " fait " + tr.texte; if (tr.reussite) { - smsg += " => réussite"; + smsg += " => r\xE9ussite"; } else { - smsg += " => échec" + tr.rerolls; + smsg += " => \xE9chec" + tr.rerolls; } addLineToFramedDisplay(display, smsg); let d4 = options.rolls.tourDeForceDmg || rollDePlus(4); @@ -32843,7 +33223,7 @@ var COFantasy = COFantasy || function() { perso.ignoreTouteRD = true; dealDamage(perso, r, [], evt, false, {}, explications, function(dmgDisplay, dmg) { - let dmgMsg = "mais cela lui coûte " + dmgDisplay + " PV"; + let dmgMsg = "mais cela lui co\xFBte " + dmgDisplay + " PV"; addLineToFramedDisplay(display, dmgMsg); explications.forEach(function(expl) { addLineToFramedDisplay(display, expl, 80); @@ -32867,41 +33247,41 @@ var COFantasy = COFantasy || function() { } } - //!cof-encaisser-un-coup, avec la personne qui encaisse sélectionnée + //!cof-encaisser-un-coup, avec la personne qui encaisse s\xE9lectionn\xE9e function doEncaisserUnCoup(msg) { var optionsEncaisser = parseOptions(msg); if (optionsEncaisser === undefined) return; var cmd = optionsEncaisser.cmd; var evt = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Personne n'est sélectionné pour encaisser un coup", msg); + error("Personne n'est s\xE9lectionn\xE9 pour encaisser un coup", msg); return; } if (evt === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour encaisser un coup"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour encaisser un coup"); return; } if (evt.type != 'Attaque' || evt.succes === false) { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour encaisser le coup d'une action précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour encaisser le coup d'une action pr\xE9c\xE9dente"); return; } var action = evt.action; if (action.options.distance) { - sendChat('', "Impossible d'encaisser le dernier coup, ce n'était pas une attaque au contact"); + sendChat('', "Impossible d'encaisser le dernier coup, ce n'\xE9tait pas une attaque au contact"); return; } var toProceed; iterSelected(selected, function(chevalier) { if (!attributeAsBool(chevalier, 'encaisserUnCoup')) { - sendPerso(chevalier, "n'est pas placé pour encaisser un coup"); + sendPerso(chevalier, "n'est pas plac\xE9 pour encaisser un coup"); return; } if (!peutController(msg, chevalier)) { @@ -32912,7 +33292,7 @@ var COFantasy = COFantasy || function() { return (target.token.id === chevalier.token.id); }); if (cible === undefined) { - sendPerso(chevalier, "n'est pas la cible de la dernière attaque"); + sendPerso(chevalier, "n'est pas la cible de la derni\xE8re attaque"); return; } action.choices = action.choices || {}; @@ -32935,40 +33315,40 @@ var COFantasy = COFantasy || function() { removePreDmg(options, cible, "encaisserUnCoup"); } - //!cof-devier-les-coups, avec la personne qui encaisse sélectionnée + //!cof-devier-les-coups, avec la personne qui encaisse s\xE9lectionn\xE9e function doDevierLesCoups(msg) { let optionsDevier = parseOptions(msg); if (optionsDevier === undefined) return; let cmd = optionsDevier.cmd; let evt = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Personne n'est sélectionné pour dévier les coups", msg); + error("Personne n'est s\xE9lectionn\xE9 pour d\xE9vier les coups", msg); return; } if (evt === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour dévier les coups"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour d\xE9vier les coups"); return; } if (evt.type != 'Attaque' || evt.succes === false) { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour dévier les coups d'une action précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour d\xE9vier les coups d'une action pr\xE9c\xE9dente"); return; } var action = evt.action; if (action.options.distance) { - sendChat('', "Impossible d'encaisser le dernier coup, ce n'était pas une attaque au contact"); + sendChat('', "Impossible d'encaisser le dernier coup, ce n'\xE9tait pas une attaque au contact"); return; } let toProceed; iterSelected(selected, function(perso) { - let testDevierCoups = testLimiteUtilisationsCapa(perso, 'devierLesCoups', 'tour', "ne peut plus dévier les coups à ce tour-ci"); + let testDevierCoups = testLimiteUtilisationsCapa(perso, 'devierLesCoups', 'tour', "ne peut plus d\xE9vier les coups \xE0 ce tour-ci"); if (testDevierCoups === undefined) return; if (!peutController(msg, perso)) { sendPlayer(msg, "pas le droit d'utiliser ce bouton", playerId); @@ -32978,7 +33358,7 @@ var COFantasy = COFantasy || function() { return (target.token.id === perso.token.id); }); if (cible === undefined) { - sendPerso(perso, "n'est pas la cible de la dernière attaque"); + sendPerso(perso, "n'est pas la cible de la derni\xE8re attaque"); return; } action.choices = action.choices || {}; @@ -33007,33 +33387,33 @@ var COFantasy = COFantasy || function() { if (optionsParade === undefined) return; var cmd = optionsParade.cmd; var evt = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Personne n'est sélectionné pour parer le projectile", msg); + error("Personne n'est s\xE9lectionn\xE9 pour parer le projectile", msg); return; } if (evt === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour parer le projectile"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour parer le projectile"); return; } if (evt.type != 'Attaque' || evt.succes === false) { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour parer le projectile d'une action précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour parer le projectile d'une action pr\xE9c\xE9dente"); return; } var action = evt.action; if (!action.options.distance) { - sendChat('', "Impossible de parer le projectile, ce n'était pas une attaque à distance"); + sendChat('', "Impossible de parer le projectile, ce n'\xE9tait pas une attaque \xE0 distance"); return; } if (action.options.poudre) { - sendChat('', "Impossible de parer le projectile, il s'agit d'une arme à poudre"); + sendChat('', "Impossible de parer le projectile, il s'agit d'une arme \xE0 poudre"); return; } if (action.cibles.length > 1) { @@ -33054,7 +33434,7 @@ var COFantasy = COFantasy || function() { return (target.token.id === moine.token.id); }); if (cible === undefined) { - sendPerso(moine, "n'est pas la cible de la dernière attaque"); + sendPerso(moine, "n'est pas la cible de la derni\xE8re attaque"); return; } action.choices = action.choices || {}; @@ -33079,8 +33459,8 @@ var COFantasy = COFantasy || function() { // asynchrone : on fait les jets du personnage en opposition // options : - // predicat : on utilise un prédicat et non un attribut. Peut être 'tour' ou 'combat' - // protecteur: c'est un protecteur qui protège la cible (pas compatible avec predicate + // predicat : on utilise un pr\xE9dicat et non un attribut. Peut \xEAtre 'tour' ou 'combat' + // protecteur: c'est un protecteur qui prot\xE8ge la cible (pas compatible avec predicate function evitementGenerique(msg, verbe, attributeName, actionName, tente, msgDejaFait, carac, typeAttaque, msgReussite, opt) { let options = parseOptions(msg); if (options === undefined) return; @@ -33095,10 +33475,10 @@ var COFantasy = COFantasy || function() { } let evt; let chance; - if (cmd.length > 2) { //On relance pour un événement particulier + if (cmd.length > 2) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[2]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } chance = cmd.length > 3 && cmd[3] == 'chance'; @@ -33106,11 +33486,11 @@ var COFantasy = COFantasy || function() { evt = lastEvent(); } if (evt === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour esquiver"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour esquiver"); return; } if (evt.type != 'Attaque') { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour " + verbe + " l'attaque précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour " + verbe + " l'attaque pr\xE9c\xE9dente"); return; } const perso = persoOfId(cmd[1]); @@ -33125,12 +33505,12 @@ var COFantasy = COFantasy || function() { return (target.token.id === perso.token.id); }); if (cible === undefined) { - sendPerso(perso, "n'est pas la cible de la dernière attaque"); + sendPerso(perso, "n'est pas la cible de la derni\xE8re attaque"); return; } let attributAVerifier = attributeName; let persoAttribut = perso; - if (opt.protecteur) { // c'est un personnage tiers qui protège la cible + if (opt.protecteur) { // c'est un personnage tiers qui prot\xE8ge la cible let protecteurAttrs = tokenAttribute(perso, attributeName + 'Valeur'); if (protecteurAttrs.length < 1) { error("Erreur interne dans le bouton de protection, protecteur introuvable", cmd); @@ -33177,7 +33557,7 @@ var COFantasy = COFantasy || function() { } else { let curAttribut = parseInt(attribut.get('current')); if (isNaN(curAttribut)) { - error("Resource pour " + actionName + " mal formée", attribut); + error("Resource pour " + actionName + " mal form\xE9e", attribut); return; } if (curAttribut < 1) { @@ -33240,8 +33620,8 @@ var COFantasy = COFantasy || function() { } } else if (testPredicat) { utiliseCapacite(testPredicat.perso, testPredicat, evt); - } else if (attributeName !== undefined) { //ni attribut ni prédicat - error("On n'a ni attribut ni prédicat pour un évitement générique", evitementGen); + } else if (attributeName !== undefined) { //ni attribut ni pr\xE9dicat + error("On n'a ni attribut ni pr\xE9dicat pour un \xE9vitement g\xE9n\xE9rique", evitementGen); return; } let optDice; @@ -33320,20 +33700,20 @@ var COFantasy = COFantasy || function() { if (attEvBonus > 0) msg += "+" + attEvBonus; else if (attEvBonus < 0) msg += attEvBonus; msg = nomPerso(lanceur) + " tente " + tente + ". " + - onGenre(lanceur, "Il", "elle") + " fait " + msg; - var generalMsg = ''; + onGenre(lanceur, "Il", "Elle") + " fait " + msg; + let generalMsg = ''; if (totalEvitement < jetAdversaire) { - msg += " => Raté"; - var pc = pointsDeChance(lanceur); + msg += " => Rat\xE9"; + let pc = pointsDeChance(lanceur); if (attackRoll.results.total != 1 && pc > 0) { generalMsg += '
    ' + boutonSimple("!cof-bouton-chance " + evt.id + " " + testId, "Chance") + " (reste " + pc + " PC)"; } - if (stateCOF.combat && attributeAsBool(lanceur, 'runeForgesort_énergie') && - attributeAsInt(lanceur, 'limiteParCombat_runeForgesort_énergie', 1) > 0 && + if (stateCOF.combat && attributeAsBool(lanceur, 'runeForgesort_\xE9nergie') && + attributeAsInt(lanceur, 'limiteParCombat_runeForgesort_\xE9nergie', 1) > 0 && (carac == 'force' || carac == 'constitution' || carac == 'dexterite')) { - generalMsg += '
    ' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'énergie"); + generalMsg += '
    ' + boutonSimple("!cof-bouton-rune-energie " + evt.id + " " + testId, "Rune d'\xE9nergie"); } if (stateCOF.combat && capaciteDisponible(lanceur, 'petitVeinard', 'combat')) { generalMsg += '
    ' + boutonSimple("!cof-bouton-petit-veinard " + evt.id + " " + testId, "Petit veinard"); @@ -33343,23 +33723,23 @@ var COFantasy = COFantasy || function() { } else { //Sinon cacher le bouton mais laisser l'option reroll removePreDmg(options, cible, attributeName, 'reroll'); } - } else { //Évitement réussi + } else { //\xC9vitement r\xE9ussi if (opt && cible.critique && (opt.critiqueDevientNormal || (opt.critiqueAnnuleCritique && d20roll != 20))) { cible.critique = false; - msg += " => Réussi, l'attaque fait des dégâts normaux"; + msg += " => R\xE9ussi, l'attaque fait des d\xE9g\xE2ts normaux"; removePreDmg(options, cible, attributeName); } else { cible.touche = false; if (opt.annule) { delete options.preDmg; options.preDmgAnnule = true; - generalMsg += " => Réussi, " + msgReussite; + generalMsg += " => R\xE9ussi, " + msgReussite; } else { action.ciblesTouchees = action.ciblesTouchees.filter(function(c) { return c.token.id != cible.token.id; }); removePreDmg(options, cible); - msg += " => Réussi, " + msgReussite; + msg += " => R\xE9ussi, " + msgReussite; } } } @@ -33378,7 +33758,7 @@ var COFantasy = COFantasy || function() { }; evitementGenerique(msg, "absorber un coup au bouclier", 'absorberUnCoup', "d'absorption de coup au bouclier", "d'absorber un coup au bouclier", - " a déjà essayé d'absorber un coup au bouclier ce tour", 'force', 'contact', "le coup est absorbé !", { + " a d\xE9j\xE0 essay\xE9 d'absorber un coup au bouclier ce tour", 'force', 'contact', "le coup est absorb\xE9 !", { attrAsBool: true, condition, }); @@ -33395,7 +33775,7 @@ var COFantasy = COFantasy || function() { }; evitementGenerique(msg, "absorber un sort au bouclier", 'absorberUnSort', "d'absorption de sort au bouclier", "d'absorber un sort au bouclier", - " a déjà essayé d'absorber un sort au bouclier ce tour", 'sagesse', 'magique', "le sort est absorbé !", { + " a d\xE9j\xE0 essay\xE9 d'absorber un sort au bouclier ce tour", 'sagesse', 'magique', "le sort est absorb\xE9 !", { attrAsBool: true, condition: condition }); @@ -33404,10 +33784,10 @@ var COFantasy = COFantasy || function() { // asynchrone : on fait les jets du barbare en opposition //!cof-resister-a-la-magie id [evtid] [chance] function resisterALaMagie(msg) { - evitementGenerique(msg, 'résister à la magie', 'resistanceALaMagieBarbare', - 'résistance à la magie', "de résister à la magie", - " a déjà essayé de résister à la magie ce tour", - 'sagesse', 'magique', "il résiste à la magie !", { + evitementGenerique(msg, 'r\xE9sister \xE0 la magie', 'resistanceALaMagieBarbare', + 'r\xE9sistance \xE0 la magie', "de r\xE9sister \xE0 la magie", + " a d\xE9j\xE0 essay\xE9 de r\xE9sister \xE0 la magie ce tour", + 'sagesse', 'magique', "il r\xE9siste \xE0 la magie !", { predicat: 'tour' }); } @@ -33417,8 +33797,8 @@ var COFantasy = COFantasy || function() { function cercleDeProtection(msg) { evitementGenerique(msg, 'activer le cercle de protection', 'cercleDeProtection', 'activation du cercle de protection', "de bloquer le sort avec le Cercle de Protection", - " a déjà active le Cercle de Protection ce tour", - 'intelligence', 'magique', "le sort est annulé !", { + " a d\xE9j\xE0 active le Cercle de Protection ce tour", + 'intelligence', 'magique', "le sort est annul\xE9 !", { protecteur: true, annule: true }); @@ -33428,7 +33808,7 @@ var COFantasy = COFantasy || function() { //!cof-esquive-acrobatique id [evtid] [chance] function doEsquiveAcrobatique(msg) { evitementGenerique(msg, 'esquiver', 'esquiveAcrobatique', - 'esquive acrobatique', "une esquive acrobatique", " a déjà fait une esquive acrobatique ce tour", 'dexterite', 'distance', "l'attaque est esquivée !", { + 'esquive acrobatique', "une esquive acrobatique", " a d\xE9j\xE0 fait une esquive acrobatique ce tour", 'dexterite', 'distance', "l'attaque est esquiv\xE9e !", { critiqueDevientNormal: true, predicat: 'tour' }); @@ -33436,12 +33816,12 @@ var COFantasy = COFantasy || function() { function doEsquiveDeLaMagie(msg) { evitementGenerique(msg, 'esquiver', undefined, - "esquive de la magie", "d'esquiver la magie", " a déjà fait esquivé la magie", 'dexterite', 'esquive', "l'attaque est esquivée !", {}); + "esquive de la magie", "d'esquiver la magie", " a d\xE9j\xE0 fait esquiv\xE9 la magie", 'dexterite', 'esquive', "l'attaque est esquiv\xE9e !", {}); } function doEsquiveMagistrale(msg) { evitementGenerique(msg, 'esquiver', 'paradeMagistrale', - 'esquive acrobatique', "une esquive acrobatique", " a déjà fait une parade magistrale ce tour", 'dexterite', 'distance', "l'attaque est esquivée !", { + 'esquive acrobatique', "une esquive acrobatique", " a d\xE9j\xE0 fait une parade magistrale ce tour", 'dexterite', 'distance', "l'attaque est esquiv\xE9e !", { bonusAttaque: -5, critiqueDevientNormal: true, predicat: 'tour' @@ -33450,7 +33830,7 @@ var COFantasy = COFantasy || function() { function doParadeMagistrale(msg) { evitementGenerique(msg, 'parer', 'paradeMagistrale', - 'parade magistrale', "une parade magistrale", " a déjà fait une parade magistrale ce tour", 'dexterite', 'distance', "l'attaque est parée !", { + 'parade magistrale', "une parade magistrale", " a d\xE9j\xE0 fait une parade magistrale ce tour", 'dexterite', 'distance', "l'attaque est par\xE9e !", { arme: true, critiqueDevientNormal: true, predicat: 'tour' @@ -33460,7 +33840,7 @@ var COFantasy = COFantasy || function() { //!cof-parade-au-bouclier function doParadeAuBouclier(msg) { evitementGenerique(msg, 'parer', 'paradeAuBouclier', - 'parade au bouclier', "une parade au bouclier", " a déjà fait une parade au bouclier ce tour", 'force', 'contact', "l'attaque est parée !", { + 'parade au bouclier', "une parade au bouclier", " a d\xE9j\xE0 fait une parade au bouclier ce tour", 'force', 'contact', "l'attaque est par\xE9e !", { armeGauche: true, critiqueAnnuleCritique: true, predicat: 'tour' @@ -33468,7 +33848,7 @@ var COFantasy = COFantasy || function() { } //!cof-chair-a-canon id1 id2 [evt_id] - // id1 est l'id du pnj récurrent + // id1 est l'id du pnj r\xE9current // id2 est l'id du token qui se met devant l'attaque function doChairACanon(msg) { let options = parseOptions(msg); @@ -33479,13 +33859,13 @@ var COFantasy = COFantasy || function() { return; } let evtARefaire; - if (cmd.length > 3) { //On relance pour un événement particulier + if (cmd.length > 3) { //On relance pour un \xE9v\xE9nement particulier evtARefaire = findEvent(cmd[3]); } else { evtARefaire = lastEvent(); } if (evtARefaire === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } let pnjRec = persoOfId(cmd[1]); @@ -33497,7 +33877,7 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "pas le droit d'utiliser ce bouton"); return; } - let testChairACanon = testLimiteUtilisationsCapa(pnjRec, 'chairACanon', 'tour', "a déjà utilisé un sous-fifre ce tour", "ne sait pas utiliser ses sous-fifres pour se défendre"); + let testChairACanon = testLimiteUtilisationsCapa(pnjRec, 'chairACanon', 'tour', "a d\xE9j\xE0 utilis\xE9 un sous-fifre ce tour", "ne sait pas utiliser ses sous-fifres pour se d\xE9fendre"); if (testChairACanon === undefined) { return; } @@ -33507,11 +33887,11 @@ var COFantasy = COFantasy || function() { return; } if (evtARefaire === undefined) { - sendChat('', "Historique d'actions vide, pas d'action trouvée pour la chair à canon"); + sendChat('', "Historique d'actions vide, pas d'action trouv\xE9e pour la chair \xE0 canon"); return; } if (evtARefaire.type != 'Attaque') { - sendChat('', "la dernière action n'est pas une attaque"); + sendChat('', "la derni\xE8re action n'est pas une attaque"); return; } let attaque = evtARefaire.action; @@ -33536,7 +33916,7 @@ var COFantasy = COFantasy || function() { let optionsRedo = attaque.options; optionsRedo.rolls = attaque.rolls; let evt = { - type: "chair à canon" + type: "chair \xE0 canon" }; utiliseCapacite(pnjRec, testChairACanon, evt); undoEvent(evtARefaire); @@ -33545,7 +33925,7 @@ var COFantasy = COFantasy || function() { redoEvent(evtARefaire, attaque); } - // modifie res et le retourne (au cas où il ne serait pas donné) + // modifie res et le retourne (au cas o\xF9 il ne serait pas donn\xE9) function listRollResults(roll, res) { res = res || []; switch (roll.type) { @@ -33560,7 +33940,7 @@ var COFantasy = COFantasy || function() { roll.results.forEach(function(r) { if (r.v) res.push(r.v); else if (r.d) res.push(r.d); - else log("Type de résultat de dé inconnu " + r); + else log("Type de r\xE9sultat de d\xE9 inconnu " + r); }); return res; case 'M': @@ -33581,9 +33961,9 @@ var COFantasy = COFantasy || function() { return res; } - //category est un tableau de string, le premier élément étant la catégorie - //principale, le suivant la sous-catégorie, etc - //value peut être un nombre, un tableau de nombres, ou un inline roll + //category est un tableau de string, le premier \xE9l\xE9ment \xE9tant la cat\xE9gorie + //principale, le suivant la sous-cat\xE9gorie, etc + //value peut \xEAtre un nombre, un tableau de nombres, ou un inline roll function addStatistics(playerId, category, value) { if (stateCOF.statistiques === undefined) return; var stat = stateCOF.statistiques; @@ -33624,7 +34004,7 @@ var COFantasy = COFantasy || function() { nombre: 0, total: 0, }; - if (stats.nombre) { //on peut afficher des résultats + if (stats.nombre) { //on peut afficher des r\xE9sultats res.nombre = stats.nombre; res.total = stats.total; } @@ -33636,7 +34016,7 @@ var COFantasy = COFantasy || function() { res.nombre += catRes.nombre; res.total += catRes.total; } - var msg = "aucun jet cellecté"; + var msg = "aucun jet cellect\xE9"; if (res.nombre > 0) { var moyenne = res.total / res.nombre; msg = res.nombre + " jet" + ((res.nombre > 1) ? "s" : "") + ", moyenne " + moyenne; @@ -33658,7 +34038,7 @@ var COFantasy = COFantasy || function() { if (stats) addLineToFramedDisplay(display, "Statistiques en pause"); else { - addLineToFramedDisplay(display, "Aucune statistique collectée"); + addLineToFramedDisplay(display, "Aucune statistique collect\xE9e"); sendFramedDisplay(display); return; } @@ -33700,7 +34080,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let args = options.cmd; if (args === undefined || args.length < 2) { - error("Il faut au moins un argument à !cof-destruction-des-morts-vivants", args); + error("Il faut au moins un argument \xE0 !cof-destruction-des-morts-vivants", args); return; } args.shift(); @@ -33713,11 +34093,11 @@ var COFantasy = COFantasy || function() { dm = dm.replace(/\]/g, ']'); getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Il faut sélectionner le lanceur de la destruction des morts-vivants", playerId); + sendPlayer(msg, "Il faut s\xE9lectionner le lanceur de la destruction des morts-vivants", playerId); return; } if (selected.length > 1) { - sendPlayer(msg, "Ne sélectionner qu'un token à la fois pour lancer la destruction des mort-vivants.", playerId); + sendPlayer(msg, "Ne s\xE9lectionner qu'un token \xE0 la fois pour lancer la destruction des mort-vivants.", playerId); return; } let playerName = msg.who; @@ -33725,7 +34105,7 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(lanceur) { if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options var optMana = { mana: options.mana, dm: true, @@ -33737,7 +34117,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.rang && options.tempeteDeMana.cout > options.rang) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -33747,7 +34127,7 @@ var COFantasy = COFantasy || function() { let nbDes = parseInt(findNbDes[1]); dm = dm.replace(findNbDes[0], (nbDes + options.tempeteDeManaIntense) + 'd'); } else { - log("Pas réussi à trouver le nombre de dés dans " + dm); + log("Pas r\xE9ussi \xE0 trouver le nombre de d\xE9s dans " + dm); } } else if (options.puissant) { let findValDes = dm.match(/^([0-9]+d)([0-9]+)/); @@ -33755,7 +34135,7 @@ var COFantasy = COFantasy || function() { let valDes = parseInt(findValDes[2]) + 2; dm = dm.replace(findValDes[0], findValDes[1] + valDes); } else { - log("Pas réussi à trouver le nombre de faces des dés dans " + dm); + log("Pas r\xE9ussi \xE0 trouver le nombre de faces des d\xE9s dans " + dm); } } doDestructionDesMortsVivants(lanceur, playerName, dm, options); @@ -33827,7 +34207,7 @@ var COFantasy = COFantasy || function() { if (!estMortVivant(cible)) return; if (getState(cible, 'mort')) return; if (predicateAsBool(cible, 'immunite_destruction')) { - addLineToFramedDisplay(display, nomPerso(cible) + " ne semble pas affecté par la destruction des morts-vivants"); + addLineToFramedDisplay(display, nomPerso(cible) + " ne semble pas affect\xE9 par la destruction des morts-vivants"); return; } cibles.push(cible); @@ -33874,21 +34254,21 @@ var COFantasy = COFantasy || function() { dmg.display = buildinline(dmg.roll.inlinerolls[dmgRollNumber], dmg.type, optionsDM.magique); dealDamage(perso, dmg, [], evt, false, optionsDM, explications, function(dmgDisplay, dmgFinal) { addLineToFramedDisplay(display, - name + " reçoit " + dmgDisplay + " DM"); + name + " re\xE7oit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); finalDisplay(); }); - }); //fin du jet de dés + }); //fin du jet de d\xE9s } catch (rollError) { - error("Jet " + dm + " mal formé", dm); + error("Jet " + dm + " mal form\xE9", dm); } }); //fin forEach } else { addLineToFramedDisplay(display, msgJet + " < " + difficulte); - let msgRate = nomPerso(lanceur) + " ne réussit pas à invoquer son dieu." + testRes.rerolls + testRes.modifiers; + let msgRate = nomPerso(lanceur) + " ne r\xE9ussit pas \xE0 invoquer son dieu." + testRes.rerolls + testRes.modifiers; addLineToFramedDisplay(display, msgRate); sendFramedDisplay(display); } @@ -33909,7 +34289,7 @@ var COFantasy = COFantasy || function() { let label = cmd[1]; let typePoison = cmd[2]; if (typePoison != 'rapide' && typePoison != 'affaiblissant') { - error("Les seuls type de poison gérés sont rapide et affaiblissant, mais pas encore " + typePoison, cmd); + error("Les seuls type de poison g\xE9r\xE9s sont rapide et affaiblissant, mais pas encore " + typePoison, cmd); } let nomMunition; let estMunition = label.startsWith('munition_'); @@ -33917,7 +34297,7 @@ var COFantasy = COFantasy || function() { let forcePoison = cmd[3]; let savePoison = parseInt(cmd[4]); if (isNaN(savePoison)) { - error("Le dernier argument non optionnel doit être la difficulté du test de CON", cmd); + error("Le dernier argument non optionnel doit \xEAtre la difficult\xE9 du test de CON", cmd); return; } let testINT = 14; @@ -33926,7 +34306,7 @@ var COFantasy = COFantasy || function() { switch (cmd[0]) { case 'testINT': if (cmd.length < 2) { - error("Il faut un argument à --testINT", cmd); + error("Il faut un argument \xE0 --testINT", cmd); return; } testINT = parseInt(cmd[1]); @@ -33974,11 +34354,11 @@ var COFantasy = COFantasy || function() { return; } if (arme.sortilege) { - sendPerso(perso, "imossible d'enduire un sortilège de poison", true); + sendPerso(perso, "imossible d'enduire un sortil\xE8ge de poison", true); return; } if (arme.typeDegats == 'contondant') { - sendPerso(perso, arme.name + " fait des dégâts contondants. Est-il vraiment possible de l'empoisonner ?", true); + sendPerso(perso, arme.name + " fait des d\xE9g\xE2ts contondants. Est-il vraiment possible de l'empoisonner ?", true); } if (arme.armeDeJet) estMunition = true; } @@ -33993,22 +34373,22 @@ var COFantasy = COFantasy || function() { let munitions = listAllMunitions(perso); let m = munitions[nomMunition]; if (m) { - let typeMunition = fieldAsString(m, 'typemunition', 'Flèche'); + let typeMunition = fieldAsString(m, 'typemunition', 'Fl\xE8che'); armeEnduite = fieldAsString(m, 'nommunition', typeMunition); munitionsCourantes = fieldAsInt(m, 'qtemunition', 1); maxMunitions = fieldAsInt(m, 'qtemunition_max', 1); - } else { //ancienne variante, obsolète depuis mars 2023 + } else { //ancienne variante, obsol\xE8te depuis mars 2023 armeEnduite = nomMunition.replace(/_/g, ' '); let attrQte = tokenAttribute(perso, labelArme); if (attrQte.length === 0) { - sendPerso(perso, "n'a pas de munition nommée " + nomMunition); + sendPerso(perso, "n'a pas de munition nomm\xE9e " + nomMunition); return; } attrQte = attrQte[0]; munitionsCourantes = parseInt(attrQte.get('current')); maxMunitions = parseInt(attrQte.get('max')); if (isNaN(munitionsCourantes) || isNaN(maxMunitions)) { - error("Attribut de munitions mal formé", attrQte); + error("Attribut de munitions mal form\xE9", attrQte); return; } } @@ -34022,7 +34402,7 @@ var COFantasy = COFantasy || function() { let infos = attr[0].get('max'); let indexInfos = infos.indexOf(' '); if (indexInfos < 1) { - error("Attribut de poison rapide de munition mal formé (il faudrait la difficulté du save + le nombre de munitions empoisonnées)", infos); + error("Attribut de poison rapide de munition mal form\xE9 (il faudrait la difficult\xE9 du save + le nombre de munitions empoisonn\xE9es)", infos); return; } let oldSave = parseInt(infos.substring(0, indexInfos)); @@ -34031,23 +34411,23 @@ var COFantasy = COFantasy || function() { if (dejaEnduits > 0 && (attr[0].get('current') != typePoison + ' ' + forcePoison || oldSave != savePoison)) { - sendPlayer(msg, "Il y a déjà du poison de type " + attr[0].get('current') + "et de save " + oldSave + " sur les munitions " + armeEnduite + ". Le script ne sait pas gérer différents poisons sur les mêmes munitions.", playerId); + sendPlayer(msg, "Il y a d\xE9j\xE0 du poison de type " + attr[0].get('current') + "et de save " + oldSave + " sur les munitions " + armeEnduite + ". Le script ne sait pas g\xE9rer diff\xE9rents poisons sur les m\xEAmes munitions.", playerId); return; } } infosAdditionelles = savePoison + ' ' + (dejaEnduits + 1); if (dejaEnduits >= maxMunitions) { - sendPlayer(msg, "Toutes les munitions " + armeEnduite + " sont déjà enduites de poison", playerId); + sendPlayer(msg, "Toutes les munitions " + armeEnduite + " sont d\xE9j\xE0 enduites de poison", playerId); return; } } else { armeEnduite = getAttackName(labelArme, perso); if (armeEnduite === undefined) { - error(perso.tokNname + " n'a pas d'arme associée au label " + labelArme, cmd); + error(perso.tokNname + " n'a pas d'arme associ\xE9e au label " + labelArme, cmd); return; } if (attributeAsBool(perso, attribut)) { - sendPlayer(msg, armeEnduite + " est déjà enduit de poison.", playerId); + sendPlayer(msg, armeEnduite + " est d\xE9j\xE0 enduit de poison.", playerId); return; } } @@ -34087,13 +34467,13 @@ var COFantasy = COFantasy || function() { addEvent(evt); if (limiteRessources(perso, options, 'enduirePoison', 'enduire de poison', evt)) return; const display = startFramedDisplay(options.playerId, "Essaie d'enduire " + armeEnduite + " de poison", perso); - //Test d'INT pour savoir si l'action réussit. + //Test d'INT pour savoir si l'action r\xE9ussit. let testId = 'enduireDePoison'; testCaracteristique(perso, 'INT', testINT, testId, options, evt, function(tr) { let jet = "Jet d'INT : " + tr.texte; - if (tr.echecCritique) { //échec critique - jet += " Échec critique !" + tr.rerolls + tr.modifiers; + if (tr.echecCritique) { //\xE9chec critique + jet += " \xC9chec critique !" + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, jet); addLineToFramedDisplay(display, nomPerso(perso) + " s'empoisonne."); sendChat('', "[[" + forcePoison + "]]", function(res) { @@ -34122,7 +34502,7 @@ var COFantasy = COFantasy || function() { }); addLineToFramedDisplay(display, nomPerso(perso) + " subit " + dmgDisplay + " DM"); sendFramedDisplay(display); - }); //fin de dmg dus à l'échec critique + }); //fin de dmg dus \xE0 l'\xE9chec critique } }); //fin du jet de dmg } else if (tr.reussite) { @@ -34134,7 +34514,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, armeEnduite + " est maintenant enduit de poison"); sendFramedDisplay(display); } else { //echec normal au jet d'INT - jet += " < " + testINT + " : échec" + tr.rerolls + tr.modifiers; + jet += " < " + testINT + " : \xE9chec" + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, jet); sendFramedDisplay(display); } @@ -34142,72 +34522,72 @@ var COFantasy = COFantasy || function() { } const listeElixirs = [{ - nom: 'Élixir fortifiant', + nom: '\xC9lixir fortifiant', attrName: 'fortifiant', action: "!cof-fortifiant $rang", rang: 1 }, { - nom: 'Élixir de feu grégeois', - attrName: 'feu_grégeois', - action: "!cof-attack @{selected|token_id} @{target|token_id} Feu Grégeois --auto --dm $rangd6 --feu --psave DEX [[$base_save+@{selected|INT}]] --disque 3 --portee 10 --targetFx burst-fire", + nom: '\xC9lixir de feu gr\xE9geois', + attrName: 'feu_gr\xE9geois', + action: "!cof-attack @{selected|token_id} @{target|token_id} Feu Gr\xE9geois --auto --dm $rangd6 --feu --psave DEX [[$base_save+@{selected|INT}]] --disque 3 --portee 10 --targetFx burst-fire", rang: 2 }, { - nom: 'Élixir de guérison', - attrName: 'élixir_de_guérison', + nom: '\xC9lixir de gu\xE9rison', + attrName: '\xE9lixir_de_gu\xE9rison', action: "!cof-soin 3d6+$INT", rang: 3 }, { - nom: "Élixir d'agrandissement", + nom: "\xC9lixir d'agrandissement", attrName: "potion_d_agrandissement", action: "!cof-effet-temp agrandissement [[5+$INT]]", rang: 4 }, { - nom: "Élixir de forme gazeuse", + nom: "\xC9lixir de forme gazeuse", attrName: "potion_de_forme_gazeuse", action: "!cof-effet-temp formeGazeuse [[1d4+$INT]]", rang: 4 }, { - nom: "Élixir de protection contre les éléments", - attrName: "potion_de_protection_contre_les_éléments", + nom: "\xC9lixir de protection contre les \xE9l\xE9ments", + attrName: "potion_de_protection_contre_les_\xE9l\xE9ments", action: "!cof-effet-temp protectionContreLesElements [[5+$INT]] --valeur $rang", rang: 4 }, { - nom: "Élixir d'armure de mage", + nom: "\xC9lixir d'armure de mage", attrName: "potion_d_armure_de_mage", action: "!cof-effet-combat armureDuMage", rang: 4 }, { - nom: "Élixir de chute ralentie", + nom: "\xC9lixir de chute ralentie", attrName: "potion_de_chute_ralentie", - action: "est léger comme une plume.", + action: "est l\xE9ger comme une plume.", rang: 4 }, { - nom: "Élixir d'invisibilité", - attrName: "potion_d_invisibilité", + nom: "\xC9lixir d'invisibilit\xE9", + attrName: "potion_d_invisibilit\xE9", action: "!cof-set-state invisible true --message se rend invisible ([[1d6+$INT]] minutes)", rang: 5 }, { - nom: "Élixir de vol", + nom: "\xC9lixir de vol", attrName: "potion_de_vol", - action: "se met à voler", + action: "se met \xE0 voler", rang: 5 }, { - nom: "Élixir de respiration aquatique", + nom: "\xC9lixir de respiration aquatique", attrName: "potion_de_respiration_aquatique", action: "peut respirer sous l'eau", rang: 5 }, { - nom: "Élixir de flou", + nom: "\xC9lixir de flou", attrName: "potion_de_flou", action: "!cof-effet-temp flou [[1d4+$INT]]", rang: 5 }, { - nom: "Élixir de hâte", - attrName: "potion_de_hâte", + nom: "\xC9lixir de h\xE2te", + attrName: "potion_de_h\xE2te", action: "!cof-effet-temp hate [[1d6+$INT]]", rang: 5 }, - //Le élixirs pour les terres d'Arran + //Le \xE9lixirs pour les terres d'Arran { nom: 'Huile instable', attrName: 'huileInstable', @@ -34215,25 +34595,25 @@ var COFantasy = COFantasy || function() { rang: 3, arran: true }, { - nom: 'Élixir de guérison', - attrName: 'élixirGuérison', + nom: '\xC9lixir de gu\xE9rison', + attrName: '\xE9lixirGu\xE9rison', action: "!cof-soin 3d6+$INT", rang: 4, arran: true }, { - nom: "Élixir de peau d'écorce", + nom: "\xC9lixir de peau d'\xE9corce", attrName: 'peauEcorce', action: "!cof-effet-temp peauDEcorce [[5+$SAG]] --valeur 4", rang: 5, arran: true }, { - nom: "Élixir d'image décalée", + nom: "\xC9lixir d'image d\xE9cal\xE9e", attrName: 'imageDecalee', action: "!cof-effet-temp imageDecalee [[5+$SAG]]", rang: 5, arran: true }, { - nom: "Élixir de protection contre les éléments", + nom: "\xC9lixir de protection contre les \xE9l\xE9ments", attrName: 'protectionContreElements', action: "!cof-effet-temp protectionContreLesElements [[5+$SAG]] --valeur 5", rang: 5, @@ -34257,7 +34637,7 @@ var COFantasy = COFantasy || function() { getSelected(msg, function(selected, playerId) { iterSelected(selected, function(perso) { if (perso.token.get('bar1_link') === '') { - error("La liste de consommables n'est pas au point pour les tokens non liés", perso); + error("La liste de consommables n'est pas au point pour les tokens non li\xE9s", perso); return; } let display = startFramedDisplay(playerId, 'Liste de vos consommables :', perso, { @@ -34323,7 +34703,7 @@ var COFantasy = COFantasy || function() { var aConsommable; _.each(consommables, function(c, prefix) { if (c.effet === undefined || c.effet === '' || c.nom === undefined || c.nom === '') return; - //La quantité est de 1 par défaut sur la fiche + //La quantit\xE9 est de 1 par d\xE9faut sur la fiche if (c.quantite === undefined) { c.quantite = 1; c.attr = createObj('attribute', { @@ -34340,12 +34720,12 @@ var COFantasy = COFantasy || function() { ressource: c.attr }); // Pictos : https://wiki.roll20.net/CSS_Wizardry#Pictos - var overlay = ' title="Cliquez pour échanger"'; + var overlay = ' title="Cliquez pour \xE9changer"'; ligne += boutonSimple('!cof-echange-consommable ' + perso.token.id + ' @{target|token_id} ' + c.attr.id, 'r', overlay); addLineToFramedDisplay(display, ligne); }); //fin de la boucle sur les onsommables if (aConsommable) - addLineToFramedDisplay(display, 'Cliquez sur le consommable pour l\'utiliser ou sur r pour l\'échanger avec un autre personnage.'); + addLineToFramedDisplay(display, 'Cliquez sur le consommable pour l\'utiliser ou sur r pour l\'\xE9changer avec un autre personnage.'); else addLineToFramedDisplay(display, "Vous n'avez aucun consommable"); sendFramedDisplay(display); @@ -34364,15 +34744,15 @@ var COFantasy = COFantasy || function() { cmd.shift(); var perso = persoOfId(cmd[0]); if (perso === undefined) { - log("Propriétaire perdu"); - sendChat('COF', "Plus possible d'utiliser cette action. Réafficher les consommables."); + log("Propri\xE9taire perdu"); + sendChat('COF', "Plus possible d'utiliser cette action. R\xE9afficher les consommables."); return; } - // Vérifie les droits d'utiliser le consommable + // V\xE9rifie les droits d'utiliser le consommable if (msg.selected && msg.selected.length == 1) { var utilisateur = persoOfId(msg.selected[0]._id); if (utilisateur === undefined) { - sendChat('COF', "Le token sélectionné n'est pas valide"); + sendChat('COF', "Le token s\xE9lectionn\xE9 n'est pas valide"); return; } var d = distanceCombat(perso.token, utilisateur.token); @@ -34382,19 +34762,19 @@ var COFantasy = COFantasy || function() { } perso = utilisateur; } else { - //On regarde si le joueur contrôle le token + //On regarde si le joueur contr\xF4le le token if (!peutController(msg, perso)) { - sendPlayer(msg, "Pas les droits pour ça"); + sendPlayer(msg, "Pas les droits pour \xE7a"); return; } } - //on récupère l'attribut à utiliser + //on r\xE9cup\xE8re l'attribut \xE0 utiliser cmd.shift(); var attr = getObj('attribute', cmd[0]); if (attr === undefined) { - log("Attribut a changé/perdu"); + log("Attribut a chang\xE9/perdu"); log(msg.content); - sendChat('COF', "Plus possible d'utiliser cette action. Veuillez réafficher les consommables."); + sendChat('COF', "Plus possible d'utiliser cette action. Veuillez r\xE9afficher les consommables."); return; } //Nom du consommable (pour affichage) @@ -34443,40 +34823,40 @@ var COFantasy = COFantasy || function() { return; } if (cmd[1] == cmd[2]) { - sendChat('COF', "Échange avec soi-même, sans effet"); + sendChat('COF', "\xC9change avec soi-m\xEAme, sans effet"); return; } - //perso1 = token avec qui va échanger le consommable + //perso1 = token avec qui va \xE9changer le consommable var perso1 = persoOfId(cmd[1]); if (perso1 === undefined) { - log("Propriétaire perdu"); - sendChat('COF', "Plus possible d'utiliser cette action. Réafficher les consommables."); + log("Propri\xE9taire perdu"); + sendChat('COF', "Plus possible d'utiliser cette action. R\xE9afficher les consommables."); return; } - //perso2 = token avec lequel on va faire l'échange + //perso2 = token avec lequel on va faire l'\xE9change let perso2 = persoOfId(cmd[2]); if (perso2 === undefined) { log("Destinataire perdu"); - sendChat('COF', "Erreur concernant le destinataire. Veuillez réessayer."); + sendChat('COF', "Erreur concernant le destinataire. Veuillez r\xE9essayer."); return; } - //On regarde si le joueur contrôle le token + //On regarde si le joueur contr\xF4le le token if (!peutController(msg, perso1)) { - sendPlayer(msg, "Pas les droits pour ça"); + sendPlayer(msg, "Pas les droits pour \xE7a"); return; } - //on récupère l'attribut à échanger de perso1 + //on r\xE9cup\xE8re l'attribut \xE0 \xE9changer de perso1 var attr1 = getObj('attribute', cmd[3]); if (attr1 === undefined) { - log("Attribut a changé/perdu"); + log("Attribut a chang\xE9/perdu"); log(cmd); - sendChat('COF', "Plus possible d'utiliser cette action. Veuillez réafficher les consommables."); + sendChat('COF', "Plus possible d'utiliser cette action. Veuillez r\xE9afficher les consommables."); return; } var consName; var quantite1 = parseInt(attr1.get('current')); var evt = { - type: "Échange de consommable", + type: "\xC9change de consommable", attributes: [{ attribute: attr1, current: quantite1, @@ -34506,7 +34886,7 @@ var COFantasy = COFantasy || function() { whisperChar(perso1.charId, "Vous ne disposez plus de " + consName); return; } - // on baisse la valeur de 1 du consommable qu'on s'apprête à échanger + // on baisse la valeur de 1 du consommable qu'on s'appr\xEAte \xE0 \xE9changer quantite1--; attr1.set('current', quantite1); // ajout du consommable dans perso2 : @@ -34533,7 +34913,7 @@ var COFantasy = COFantasy || function() { attribute: attrEffet2, }); } else if (attrEffet2[0].get('current').trim() != effet) { - error("Échange dangereux : pas le même effet pour le consommable selon le personnage \n" + + error("\xC9change dangereux : pas le m\xEAme effet pour le consommable selon le personnage \n" + "Effet chez " + nomPerso(perso1) + " : " + effet + "\n" + "Effet chez " + nomPerso(perso2) + " : " + attrEffet2[0].get('current'), attr2.get('name')); return false; @@ -34562,7 +34942,7 @@ var COFantasy = COFantasy || function() { return true; } else if (!m1 && attrName == attrName2.trim()) { if (attr2.get('max').trim() != effet) { - error("Échange dangereux : pas le même effet pour le consommable selon le personnage \n" + + error("\xC9change dangereux : pas le m\xEAme effet pour le consommable selon le personnage \n" + "Effet chez " + nomPerso(perso1) + " : " + effet + "\n" + "Effet chez " + nomPerso(perso2) + " : " + attr2.get('max'), attr2); return false; @@ -34579,7 +34959,7 @@ var COFantasy = COFantasy || function() { } return false; }); - // si le consommable n'a pas été trouvé, on le crée avec une valeur de 1. + // si le consommable n'a pas \xE9t\xE9 trouv\xE9, on le cr\xE9e avec une valeur de 1. if (!found) { if (m1) { var pref = 'repeating_equipement_' + generateRowID() + '_'; @@ -34612,12 +34992,12 @@ var COFantasy = COFantasy || function() { } } quantite2++; - // on envoie un petit message précisant la résultante de l'action. - sendChat('COF', "Echange entre " + nomPerso(perso1) + " et " + nomPerso(perso2) + " terminée."); + // on envoie un petit message pr\xE9cisant la r\xE9sultante de l'action. + sendChat('COF', "Echange entre " + nomPerso(perso1) + " et " + nomPerso(perso2) + " termin\xE9e."); whisperChar(perso1.charId, " Il vous reste " + quantite1 + " " + consName + "."); - whisperChar(perso2.charId, " Vous possédez désormais " + quantite2 + " " + consName + "."); - // le MJ est notifié : - sendChat('COF', "/w GM " + nomPerso(perso1) + " vient de donner 1 " + consName + " à " + nomPerso(perso2) + "."); + whisperChar(perso2.charId, " Vous poss\xE9dez d\xE9sormais " + quantite2 + " " + consName + "."); + // le MJ est notifi\xE9 : + sendChat('COF', "/w GM " + nomPerso(perso1) + " vient de donner 1 " + consName + " \xE0 " + nomPerso(perso2) + "."); addEvent(evt); } @@ -34626,7 +35006,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -34640,7 +35020,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-provocation n'est pas un token valide"); + error("Le deuxi\xE8me argument de !cof-provocation n'est pas un token valide"); return; } if (cmd.length > 3 && cmd[3] == 'raillerie') { @@ -34689,16 +35069,16 @@ var COFantasy = COFantasy || function() { }); let reussite; switch (res) { - case 0: //en cas d'égalité, on considère que la provocation est réussie + case 0: //en cas d'\xE9galit\xE9, on consid\xE8re que la provocation est r\xE9ussie diminueMalediction(cible, evt); switch (crit) { case -1: - reussite = "Sur un malentendu, la " + action + " réussit..."; + reussite = "Sur un malentendu, la " + action + " r\xE9ussit..."; if (options.raillerie) setAttrDuree(cible, 'enerve', 1, evt); break; case 0: case 1: - reussite = "La " + action + " réussit tout juste."; + reussite = "La " + action + " r\xE9ussit tout juste."; if (options.raillerie) { setAttrDuree(cible, 'enerve', 1, evt); setTokenAttr(cible, 'resistanceRaillerie', @@ -34709,7 +35089,7 @@ var COFantasy = COFantasy || function() { case 1: switch (crit) { case -1: - reussite = nomCible + " marche complètement, il attaque " + nomVoleur; + reussite = nomCible + " marche compl\xE8tement, il attaque " + nomVoleur; if (options.raillerie) { setAttrDuree(cible, 'enerve', 1, evt); removeTokenAttr(cible, 'resistanceRaillerie', evt); @@ -34718,13 +35098,13 @@ var COFantasy = COFantasy || function() { case 0: if (options.raillerie) { setAttrDuree(cible, 'enerve', 1, evt); - reussite = nomVoleur + " a réussi à bien énerver " + nomCible; + reussite = nomVoleur + " a r\xE9ussi \xE0 bien \xE9nerver " + nomCible; setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) + 1, evt); - } else reussite = "La provocation réussit."; + } else reussite = "La provocation r\xE9ussit."; break; case 1: - reussite = "La provocation est une réussite critique !"; + reussite = "La provocation est une r\xE9ussite critique !"; setAttrDuree(cible, 'enerve', 1, evt); setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) - 1, evt); @@ -34733,7 +35113,7 @@ var COFantasy = COFantasy || function() { case 2: switch (crit) { case -1: - reussite = "Échec critique de la " + action + " !"; + reussite = "\xC9chec critique de la " + action + " !"; if (options.raillerie) { setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) + 5, evt); @@ -34744,19 +35124,19 @@ var COFantasy = COFantasy || function() { setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) + 1, evt); } - reussite = "La provocation échoue"; + reussite = "La provocation \xE9choue"; break; case 1: if (options.raillerie) { setTokenAttr(cible, 'resistanceRaillerie', attributeAsInt(cible, 'resistanceRaillerie', 0) + 10, evt); } - reussite = nomCible + " voit clair dans le jeu de " + nomVoleur + ". La provocation échoue."; + reussite = nomCible + " voit clair dans le jeu de " + nomVoleur + ". La provocation \xE9choue."; } } addLineToFramedDisplay(display, reussite); sendFramedDisplay(display); - }); //Fin du test opposé + }); //Fin du test oppos\xE9 } function enSelle(msg) { @@ -34800,14 +35180,14 @@ var COFantasy = COFantasy || function() { let nomMonture = cmd.join(' '); let monture = persoOfId(nomMonture, nomMonture, pageId); if (monture === undefined || !predicateAsBool(monture, 'monture')) { - sendPerso(cavalier, "ne peut pas monter là-dessus"); + sendPerso(cavalier, "ne peut pas monter l\xE0-dessus"); log(nomMonture); return; } const tokenM = monture.token; nomMonture = tokenM.get('name'); if (attributeAsBool(monture, 'estMontePar')) { - //Vérifie si le cavalier existe bien sur cette page. + //V\xE9rifie si le cavalier existe bien sur cette page. let cavalierBis; let estMontePar = tokenAttribute(monture, 'estMontePar'); estMontePar.forEach(function(emp) { @@ -34816,7 +35196,7 @@ var COFantasy = COFantasy || function() { if (cavalierBis === undefined) emp.remove(); }); if (cavalierBis) { - sendPerso(cavalier, "ne peut monter sur " + nomMonture + " car " + onGenre(monture, 'il', 'elle') + " a déjà un cavalier, " + nomPerso(cavalierBis)); + sendPerso(cavalier, "ne peut monter sur " + nomMonture + " car " + onGenre(monture, 'il', 'elle') + " a d\xE9j\xE0 un cavalier, " + nomPerso(cavalierBis)); return; } } @@ -34850,9 +35230,9 @@ var COFantasy = COFantasy || function() { } else voieDesElixirs = predicateAsInt(perso, 'voieDesElixirs', 0); if (voieDesElixirs < 1 && !noMsg) { if (arran) - sendPerso(perso, "ne connaît pas la Voie de l'Alchimie"); + sendPerso(perso, "ne conna\xEEt pas la Voie de l'Alchimie"); else - sendPerso(perso, "ne connaît pas la Voie des Élixirs"); + sendPerso(perso, "ne conna\xEEt pas la Voie des \xC9lixirs"); return; } return voieDesElixirs; @@ -34876,7 +35256,7 @@ var COFantasy = COFantasy || function() { if (forgesort === undefined) { let c = getObj('character', cmd[1]); if (c === undefined) { - error("Impossible de savoir qui crée l'élixir", cmd); + error("Impossible de savoir qui cr\xE9e l'\xE9lixir", cmd); return; } forgesort = { @@ -34890,7 +35270,7 @@ var COFantasy = COFantasy || function() { if (exilirInconnu(i, forgesort, voieDesElixirs)) return false; return i.attrName == cmd[2]; }); - if (elixir === undefined) { //Version perso des élixirs + if (elixir === undefined) { //Version perso des \xE9lixirs let altElixirs = findObjs({ _type: 'attribute', _characterid: forgesort.charId @@ -34911,16 +35291,16 @@ var COFantasy = COFantasy || function() { return true; }); if (elixir === undefined) { - error(nomPerso(forgesort) + " est incapable de créer " + cmd[2], cmd); + error(nomPerso(forgesort) + " est incapable de cr\xE9er " + cmd[2], cmd); return; } } const evt = { - type: "Création d'élixir" + type: "Cr\xE9ation d'\xE9lixir" }; addEvent(evt); let arran = persoArran(forgesort); - //Dépense de mana + //D\xE9pense de mana if (!arran && reglesOptionelles.mana.val.elixirs_sorts.val && ficheAttributeAsBool(forgesort, 'option_pm', true)) { if (reglesOptionelles.mana.val.mana_totale.val) { switch (elixir.rang) { @@ -34946,14 +35326,14 @@ var COFantasy = COFantasy || function() { } let elixirsACreer = tokenAttribute(forgesort, 'elixirsACreer'); if (elixirsACreer.length === 0) { - error(nomPerso(forgesort) + " ne peut créer d'élixirs " + cmd[2], cmd); + error(nomPerso(forgesort) + " ne peut cr\xE9er d'\xE9lixirs " + cmd[2], cmd); return; } elixirsACreer = elixirsACreer[0]; let extraFortifiants = toInt(elixirsACreer.get('max'), 0); let extra = extraFortifiants > 0 && elixir.rang == 1; if (!extra) options.decrAttribute = elixirsACreer.id; - if (limiteRessources(forgesort, options, 'elixirsACreer', 'élixirs à créer', evt)) return; + if (limiteRessources(forgesort, options, 'elixirsACreer', '\xE9lixirs \xE0 cr\xE9er', evt)) return; if (extra) { evt.attributes = evt.attributes || []; evt.attributes.push({ @@ -34964,7 +35344,7 @@ var COFantasy = COFantasy || function() { elixirsACreer.set('max', extraFortifiants - 1); } let attrName = 'elixir_' + elixir.attrName; - let message = "crée un " + elixir.nom; + let message = "cr\xE9e un " + elixir.nom; let attr = tokenAttribute(forgesort, attrName); if (attr.length === 0) { let rang = voieDesElixirs; @@ -35015,20 +35395,20 @@ var COFantasy = COFantasy || function() { let titre; if (elixirsACreer < 1) { if (fortifiantExtra < 1) - titre = "Impossible de créer un autre élixir aujourd'hui"; + titre = "Impossible de cr\xE9er un autre \xE9lixir aujourd'hui"; else { titre = "Encore " + fortifiantExtra + " fortifiant"; if (fortifiantExtra > 1) titre += 's'; - titre += "à créer"; + titre += "\xE0 cr\xE9er"; } } else { - titre = "Encore " + elixirsACreer + " élixir"; + titre = "Encore " + elixirsACreer + " \xE9lixir"; if (elixirsACreer > 1) titre += 's'; if (fortifiantExtra > 0) { titre += " et " + fortifiantExtra + " fortifiant"; if (fortifiantExtra > 1) titre += 's'; } - titre += " à créer"; + titre += " \xE0 cr\xE9er"; } let display = startFramedDisplay(playerId, titre, forgesort, { chuchote: true @@ -35036,7 +35416,7 @@ var COFantasy = COFantasy || function() { listeElixirs.forEach(function(elixir) { if (exilirInconnu(elixir, forgesort, voieDesElixirs)) return; if (elixir.rang < 4) { - //Il est possible de changer l'élixir par défaut + //Il est possible de changer l'\xE9lixir par d\xE9faut let altElixir = charAttribute(forgesort.charId, 'Elixir ' + elixir.rang); if (altElixir.length > 0) { elixir.nom = altElixir[0].get('current'); @@ -35128,17 +35508,17 @@ var COFantasy = COFantasy || function() { function proposerRenouveauElixirs(evt, attrs, options) { let attrsNamed = allAttributesNamed(attrs, 'elixir'); if (attrsNamed.length === 0) return attrs; - // Trouver les forgesorts avec des élixirs sur eux + // Trouver les forgesorts avec des \xE9lixirs sur eux let forgesorts = {}; attrsNamed.forEach(function(attr) { - // Check de l'existence d'un créateur + // Check de l'existence d'un cr\xE9ateur let charId = attr.get('characterid'); - let personnage = persoOfCharId(charId, options.pageId, "avec un élixir"); + let personnage = persoOfCharId(charId, options.pageId, "avec un \xE9lixir"); if (personnage === undefined) personnage = { charId }; let voieDesElixirs = rangVoieDesElixirs(personnage, true); - //TODO: réfléchir à une solution pour le renouveau des élixirs échangés + //TODO: r\xE9fl\xE9chir \xE0 une solution pour le renouveau des \xE9lixirs \xE9chang\xE9s if (voieDesElixirs > 0) { let elixirsDuForgesort = forgesorts[charId]; if (elixirsDuForgesort === undefined) { @@ -35148,24 +35528,24 @@ var COFantasy = COFantasy || function() { elixirsParRang: {} }; } - // Check de l'élixir à renouveler + // Check de l'\xE9lixir \xE0 renouveler let nomElixir = attr.get('name'); let typeElixir = listeElixirs.find(function(i) { if (i.rang > voieDesElixirs) return false; return "elixir_" + i.attrName == nomElixir; }); if (typeElixir === undefined) { - error("Impossible de trouver l'élixir à renouveler"); + error("Impossible de trouver l'\xE9lixir \xE0 renouveler"); return; } // Check des doses let doses = attr.get("current"); if (isNaN(doses)) { - error("Erreur interne : élixir mal formé"); + error("Erreur interne : \xE9lixir mal form\xE9"); return; } if (doses > 0) { - // Tout est ok, création de l'item + // Tout est ok, cr\xE9ation de l'item let elixirArenouveler = { typeElixir: typeElixir, doses: doses @@ -35199,7 +35579,7 @@ var COFantasy = COFantasy || function() { opt.maxVal = 2; } setTokenAttr(forgesort, 'elixirsACreer', elixirsDuForgesort.voieDesElixirs * 2, evt, opt); - let display = startFramedDisplay(allPlayers[0], "Renouveler les élixirs", forgesort, displayOpt); + let display = startFramedDisplay(allPlayers[0], "Renouveler les \xE9lixirs", forgesort, displayOpt); let actionToutRenouveler = ""; // Boucle par rang de rune for (const rang in elixirsDuForgesort.elixirsParRang) { @@ -35208,7 +35588,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, "Elixirs de rang " + rang, undefined, true); let actionTout = ''; let ligneBoutons = ''; - // Boucle par élixir de ce rang à renouveler + // Boucle par \xE9lixir de ce rang \xE0 renouveler for (const i in elixirsDeRang) { let elixir = elixirsDeRang[i]; // Boucle par dose @@ -35242,9 +35622,9 @@ var COFantasy = COFantasy || function() { var liste = []; if (rang < 2) return liste; liste.push({ - nom: "Rune d'énergie", + nom: "Rune d'\xE9nergie", action: "!cof-rune-energie", - attrName: "runeForgesort_énergie", + attrName: "runeForgesort_\xE9nergie", rang: 2 }); if (rang < 3) return liste; @@ -35274,19 +35654,19 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(forgesort) { let voieDesRunes = predicateAsInt(forgesort, 'voieDesRunes', 0); if (voieDesRunes < 1) { - sendPerso(forgesort, "ne connaît pas la Voie des Runes."); + sendPerso(forgesort, "ne conna\xEEt pas la Voie des Runes."); return; } else if (voieDesRunes < 2) { - sendPerso(forgesort, "ne peut écrire que des Runes de défense."); + sendPerso(forgesort, "ne peut \xE9crire que des Runes de d\xE9fense."); return; } - let titre = "Création de runes"; + let titre = "Cr\xE9ation de runes"; let display = startFramedDisplay(playerId, titre, forgesort, { chuchote: true }); listeRunes(voieDesRunes).forEach(function(rune) { var action = "!cof-creer-rune " + forgesort.token.id + " @{target|token_id} " + rune.rang; - if (rune.rang === 4) action += " ?{Numéro de l'arme de la cible?}"; + if (rune.rang === 4) action += " ?{Num\xE9ro de l'arme de la cible?}"; var options = bouton(action, rune.nom, forgesort); addLineToFramedDisplay(display, options); }); @@ -35310,40 +35690,40 @@ var COFantasy = COFantasy || function() { forgesort = persoOfId(msg.selected[0]._id); } if (forgesort === undefined) { - error("Impossible de savoir qui crée la rune", cmd); + error("Impossible de savoir qui cr\xE9e la rune", cmd); return; } } var target = persoOfId(cmd[2], cmd[2], options.pageId); if (target === undefined) { - error("Impossible de savoir à qui octroyer la rune", cmd); + error("Impossible de savoir \xE0 qui octroyer la rune", cmd); return; } var voieDesRunes = predicateAsInt(forgesort, 'voieDesRunes', 0); if (voieDesRunes < 1) { - sendPerso(forgesort, "ne connaît pas la Voie des Runes"); + sendPerso(forgesort, "ne conna\xEEt pas la Voie des Runes"); return; } else if (voieDesRunes < 2) { - sendPerso(forgesort, "ne peut écrire que des Runes de défense."); + sendPerso(forgesort, "ne peut \xE9crire que des Runes de d\xE9fense."); return; } var rune = listeRunes(voieDesRunes).find(function(i) { return i.rang == cmd[3]; }); if (rune === undefined) { - error(nomPerso(forgesort) + " est incapable de créer " + cmd[3], cmd); + error(nomPerso(forgesort) + " est incapable de cr\xE9er " + cmd[3], cmd); return; } var labelArme; if (rune.rang == 4) { if (cmd.length < 5) { - error("La rune de puissance nécessite de choisir un label d'arme."); + error("La rune de puissance n\xE9cessite de choisir un label d'arme."); return; } labelArme = parseInt(cmd[4]); } var evt = { - type: "Création de rune" + type: "Cr\xE9ation de rune" }; addEvent(evt); if (ficheAttributeAsBool(forgesort, 'option_pm', true)) { @@ -35364,11 +35744,11 @@ var COFantasy = COFantasy || function() { } } let attrName = rune.attrName; - let message = "reçoit "; + let message = "re\xE7oit "; let typeRune; switch (rune.rang) { case 2: - typeRune = "une rune d'énergie"; + typeRune = "une rune d'\xE9nergie"; break; case 3: typeRune = "une rune de protection"; @@ -35383,10 +35763,10 @@ var COFantasy = COFantasy || function() { } message += typeRune; if (attributeAsInt(target, attrName, 0) > 0) { - error("La cible possède déjà une rune " + typeRune, cmd); + error("La cible poss\xE8de d\xE9j\xE0 une rune " + typeRune, cmd); return; } - if (options.mana !== undefined && limiteRessources(forgesort, options, undefined, "créer " + typeRune, evt)) return; + if (options.mana !== undefined && limiteRessources(forgesort, options, undefined, "cr\xE9er " + typeRune, evt)) return; setTokenAttr(target, attrName, 1, evt, { msg: message, maxVal: forgesort.charId @@ -35402,19 +35782,19 @@ var COFantasy = COFantasy || function() { function proposerRenouveauRunes(evt, attrs, options) { let attrsNamed = allAttributesNamed(attrs, 'runeForgesort'); if (attrsNamed.length === 0) return attrs; - // Filtrer par Forgesort, dans l'éventualité qu'il y en ait plusieurs actifs + // Filtrer par Forgesort, dans l'\xE9ventualit\xE9 qu'il y en ait plusieurs actifs let forgesorts = {}; attrsNamed.forEach(function(attr) { - // Check de l'existence d'un créateur + // Check de l'existence d'un cr\xE9ateur let forgesortId = attr.get('max'); if (forgesortId === undefined) { - error("Impossible de retrouver le créateur de la rune : " + attr); + error("Impossible de retrouver le cr\xE9ateur de la rune : " + attr); return; } let runesDuForgesort = forgesorts[forgesortId]; if (runesDuForgesort === undefined) { - // Check de l'existence d'un token présent pour le créateur - let forgesort = persoOfCharId(forgesortId, options.pageId, "ayant créé une rune"); + // Check de l'existence d'un token pr\xE9sent pour le cr\xE9ateur + let forgesort = persoOfCharId(forgesortId, options.pageId, "ayant cr\xE9\xE9 une rune"); if (forgesort === undefined) { attr.remove(); return; @@ -35422,10 +35802,10 @@ var COFantasy = COFantasy || function() { // Check du perso voie des Runes let voieDesRunes = predicateAsInt(forgesort, 'voieDesRunes', 0); if (voieDesRunes < 1) { - sendPerso(forgesort, "ne connaît pas la Voie des Runes"); + sendPerso(forgesort, "ne conna\xEEt pas la Voie des Runes"); return; } else if (voieDesRunes < 2) { - sendPerso(forgesort, "ne peut écrire que des Runes de défense."); + sendPerso(forgesort, "ne peut \xE9crire que des Runes de d\xE9fense."); return; } runesDuForgesort = { @@ -35434,21 +35814,21 @@ var COFantasy = COFantasy || function() { runesParRang: {} }; } - // Check de la présence d'un token pour la cible + // Check de la pr\xE9sence d'un token pour la cible let targetCharId = attr.get('characterid'); let target = persoOfCharId(targetCharId, options.pageId, "ayant une rune"); if (target === undefined) return; - // Check de la rune à renouveler + // Check de la rune \xE0 renouveler let runeName = attr.get('name'); let typeRune = listeRunes(runesDuForgesort.voieDesRunes).find(function(i) { return i.attrName == runeName.split("(")[0]; }); if (typeRune === undefined) { - error("Impossible de trouver la rune à renouveler"); + error("Impossible de trouver la rune \xE0 renouveler"); return; } - // Tout est ok, création de l'item + // Tout est ok, cr\xE9ation de l'item let runeARenouveler = { target: target, typeRune: typeRune, @@ -35485,7 +35865,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, runesDeRang[0].typeRune.nom, undefined, true); let actionTout = ""; let ligneBoutons = ""; - // Boucle par rune de ce rang à renouveler + // Boucle par rune de ce rang \xE0 renouveler for (const i in runesDeRang) { let rune = runesDeRang[i]; let action = @@ -35518,7 +35898,7 @@ var COFantasy = COFantasy || function() { if (msg.content.includes(' --furie')) typeRage = 'furie'; getSelected(msg, function(selection, playerId) { if (selection.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour la rage", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour la rage", playerId); return; } const options = parseOptions(msg); @@ -35549,17 +35929,17 @@ var COFantasy = COFantasy || function() { typeRage = attrRage.get('current'); let difficulte = 13; if (typeRage == 'furie') difficulte = 16; - //Jet de sagesse difficulté 13 pou 16 pour sortir de cet état + //Jet de sagesse difficult\xE9 13 pou 16 pour sortir de cet \xE9tat let display = startFramedDisplay(options.playerId, "Essaie de calmer sa " + typeRage, perso); let testId = 'rageDuBerserk_' + perso.token.id; testCaracteristique(perso, 'SAG', difficulte, testId, options, evt, function(tr) { - addLineToFramedDisplay(display, "Résultat du jet de SAG : " + tr.texte); + addLineToFramedDisplay(display, "R\xE9sultat du jet de SAG : " + tr.texte); if (tr.reussite) { - addLineToFramedDisplay(display, "C'est réussi, " + nomPerso(perso) + " se calme." + tr.modifiers); + addLineToFramedDisplay(display, "C'est r\xE9ussi, " + nomPerso(perso) + " se calme." + tr.modifiers); removeTokenAttr(perso, 'rageDuBerserk', evt); } else { - let msgRate = "C'est raté, " + nomPerso(perso) + " reste enragé" + tr.rerolls + tr.modifiers; + let msgRate = "C'est rat\xE9, " + nomPerso(perso) + " reste enrag\xE9" + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, msgRate); } sendFramedDisplay(display); @@ -35586,17 +35966,17 @@ var COFantasy = COFantasy || function() { var options = parseOptions(msg); var cmd = msg.content.split(' '); if (cmd.length < 3) { - error("Il faut deux arguments à !cof-arme-secrete", cmd); + error("Il faut deux arguments \xE0 !cof-arme-secrete", cmd); return; } var barde = persoOfId(cmd[1]); var cible = persoOfId(cmd[2]); if (barde === undefined || cible === undefined) { - error("Token non valide pour l'arme secrète", cmd); + error("Token non valide pour l'arme secr\xE8te", cmd); return; } if (attributeAsInt(barde, 'armeSecreteBardeUtilisee')) { - sendPerso(barde, "a déjà utilisé son arme secrète durant ce combat"); + sendPerso(barde, "a d\xE9j\xE0 utilis\xE9 son arme secr\xE8te durant ce combat"); return; } doArmeSecrete(barde, cible, options); @@ -35624,14 +36004,14 @@ var COFantasy = COFantasy || function() { var testId = 'armeSecreteBarde'; testCaracteristique(perso, 'CHA', intCible, testId, options, evt, function(tr) { var display = startFramedDisplay(options.playerId, - "Arme secrète", perso, { + "Arme secr\xE8te", perso, { perso2: cible }); var line = "Jet de CHA : " + tr.texte; if (tr.reussite) { line += " ≥ " + intCible + tr.modifiers; addLineToFramedDisplay(display, line); - addLineToFramedDisplay(display, nomPerso(cible) + " est complètement déstabilisé"); + addLineToFramedDisplay(display, nomPerso(cible) + " est compl\xE8tement d\xE9stabilis\xE9"); setAttrDuree(cible, 'armeSecreteBarde', 1, evt); } else { line += " < " + intCible + tr.rerolls + tr.modifiers; @@ -35660,15 +36040,15 @@ var COFantasy = COFantasy || function() { } } - //Crée un nouveau personnage (de type PNJ par défaut) - //spec contient les charactéristiques, attributs et abilities - // - attributesFiche contient les attributs définis dans la fiche + //Cr\xE9e un nouveau personnage (de type PNJ par d\xE9faut) + //spec contient les charact\xE9ristiques, attributs et abilities + // - attributesFiche contient les attributs d\xE9finis dans la fiche // nom_attribut: valeur - // - pv (permet d'être indépendant de PJ ou PNJ) + // - pv (permet d'\xEAtre ind\xE9pendant de PJ ou PNJ) // - attaques, liste d'attaques, chacune avec (nom, atk, dmnbde, dmde, dm,...) // - attributes autres attributs (name, current, max) - // - abilities (name, action), toujours rajoutées à la liste d'actions - // - actions (titre, code), ajoutées aux listes d'actions + // - abilities (name, action), toujours rajout\xE9es \xE0 la liste d'actions + // - actions (titre, code), ajout\xE9es aux listes d'actions function createCharacter(nom, playerId, avatar, token, spec, evt, createur) { let res = createObj('character', { name: nom, @@ -35885,7 +36265,7 @@ var COFantasy = COFantasy || function() { } let tokenArbre = getObj('graphic', cmd[2]); if (tokenArbre === undefined) { - error("Le deuxième argument de !cof-animer-arbre n'est pas un token", cmd); + error("Le deuxi\xE8me argument de !cof-animer-arbre n'est pas un token", cmd); return; } if (tokenArbre.get('represents') !== '') { @@ -35900,10 +36280,10 @@ var COFantasy = COFantasy || function() { } } let rang = predicateAsInt(druide, 'voieDesVegetaux', 3); - if (cmd.length > 3) { //Le rang est spécifié en argument optionnel + if (cmd.length > 3) { //Le rang est sp\xE9cifi\xE9 en argument optionnel let cmd3 = parseInt(cmd[3]); if (isNaN(cmd3) || cmd3 < 1) { - error("Le rang n'est pas un nombre valie. On utilise " + rang + " à la place", cmd); + error("Le rang n'est pas un nombre valie. On utilise " + rang + " \xE0 la place", cmd); } else rang = cmd3; } const evt = { @@ -35915,7 +36295,7 @@ var COFantasy = COFantasy || function() { initPerso(druide, evt); } let niveau = ficheAttributeAsInt(druide, 'niveau', 1); - let nomArbre = nouveauNomDePerso('Arbre animé'); + let nomArbre = nouveauNomDePerso('Arbre anim\xE9'); let avatar = "https://s3.amazonaws.com/files.d20.io/images/42323556/6qxlm965aFhBXGoYFy5fqg/thumb.png?1510582137"; let specArbre = { pv: rang * 10, @@ -35958,11 +36338,11 @@ var COFantasy = COFantasy || function() { }; let charArbre = createCharacter(nomArbre, options.playerId, avatar, tokenArbre, specArbre, evt, druide); evt.characters = [charArbre]; - sendChar(charArbre.id, "commence à s'animer", true); + sendChar(charArbre.id, "commence \xE0 s'animer", true); initiative([{ _id: tokenArbre.id }], evt); - // Ajout de l'arbre animé aux alliés du Druide + // Ajout de l'arbre anim\xE9 aux alli\xE9s du Druide let alliesDruide = alliesParPerso[druide.charId] || new Set(); alliesDruide.add(charArbre.id); alliesParPerso[druide.charId] = alliesDruide; @@ -35978,20 +36358,20 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; var cmd = options.cmd; var evt = lastEvent(); - if (cmd !== undefined && cmd.length > 1) { //On relance pour un événement particulier + if (cmd !== undefined && cmd.length > 1) { //On relance pour un \xE9v\xE9nement particulier evt = findEvent(cmd[1]); if (evt === undefined) { - error("L'action est trop ancienne ou a été annulée", cmd); + error("L'action est trop ancienne ou a \xE9t\xE9 annul\xE9e", cmd); return; } } if (evt.type != 'Attaque') { - sendChat('', "la dernière action n'est pas une attaque réussie, trop tard pour absorber l'attaque précédente"); + sendChat('', "la derni\xE8re action n'est pas une attaque r\xE9ussie, trop tard pour absorber l'attaque pr\xE9c\xE9dente"); return; } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Personne n'est sélectionné pour utiliser une rune", msg); + error("Personne n'est s\xE9lectionn\xE9 pour utiliser une rune", msg); return; } var action = evt.action; @@ -36004,7 +36384,7 @@ var COFantasy = COFantasy || function() { return (target.token.id === perso.token.id); }); if (cible === undefined) { - sendPerso(perso, "n'est pas la cible de la dernière attaque"); + sendPerso(perso, "n'est pas la cible de la derni\xE8re attaque"); return; } if (!attributeAsBool(perso, 'runeForgesort_protection')) { @@ -36012,7 +36392,7 @@ var COFantasy = COFantasy || function() { return; } if (attributeAsInt(perso, 'limiteParCombat_runeForgesort_protection', 1) < 1) { - sendPerso(perso, "a déjà utilisé sa rune de protection durant ce combat"); + sendPerso(perso, "a d\xE9j\xE0 utilis\xE9 sa rune de protection durant ce combat"); return; } action.choices = action.choices || {}; @@ -36040,8 +36420,8 @@ var COFantasy = COFantasy || function() { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; - if (cmd === undefined || cmd.length < 3) { - error("cof-delivrance attend 2 arguments", msg.content); + if (cmd === undefined || cmd.length < 2) { + error("cof-delivrance attend un argument", msg.content); return; } let pretre = persoOfId(cmd[1], cmd[1], options.pageId); @@ -36049,127 +36429,143 @@ var COFantasy = COFantasy || function() { error("Le premier argument de !cof-delivrance n'est pas un token valide", msg.content); return; } - let cible = persoOfId(cmd[2], cmd[2], options.pageId); - if (cible === undefined) { - error("Le deuxième argument de !cof-delivrance n'est pas un token valide", msg.content); - return; - } - if (options.portee !== undefined) { - let dist = distanceCombat(pretre.token, cible.token, options.pageId); - if (dist > options.portee) { - sendPerso(pretre, "est trop loin de " + nomPerso(cible)); + let c; + if (cmd.length > 2) c = persoOfId(cmd[2], cmd[2], options.pageId); + let cibles = [c]; + if (c === undefined) { + cibles = []; + getSelected(msg, function(selected, playerId) { + iterSelected(selected, function(cible) { + cibles.push(cible); + }); + }); + if (cibles.length < 1) { + error("Le deuxi\xE8me argument de !cof-delivrance n'est pas un token valide", msg.content); return; } } + if (options.portee !== undefined) { + cibles = cibles.filter(function(cible) { + let dist = distanceCombat(pretre.token, cible.token, options.pageId); + if (dist > options.portee) { + sendPerso(pretre, "est trop loin de " + nomPerso(cible)); + return false; + } + return true; + }); + } + if (cibles.length < 1) return; const evt = { - type: "Délivrance", + type: "D\xE9livrance", deletedAttributes: [] }; addEvent(evt); - if (limiteRessources(pretre, options, 'délivrance', 'délivrance', evt)) return; - let display = startFramedDisplay(getPlayerIdFromMsg(msg), 'Délivrance', pretre, { - perso2: cible - }); - let printEffet = function(message) { - addLineToFramedDisplay(display, nomPerso(cible) + ' ' + message); - }; - let optFin = { - print: printEffet, - pageId: options.pageId - }; - _.each(messageEffetTemp, function(effet, nomEffet) { - if (effet.prejudiciable) { - //Attention, ne fonctionne pas avec les effets génériques - let attr = tokenAttribute(cible, nomEffet); - if (attr.length > 0) - finDEffet(attr[0], nomEffet, attr[0].get('name'), cible.charId, evt, optFin); - } - }); - _.each(messageEffetCombat, function(effet, nomEffet) { - if (effet.prejudiciable) { - let attr = tokenAttribute(cible, nomEffet); - if (attr.length > 0) { - printEffet(messageFin(cible, effet)); - evt.deletedAttributes.push(attr[0]); - attr[0].remove(); + if (limiteRessources(pretre, options, 'd\xE9livrance', 'd\xE9livrance', evt)) return; + cibles.forEach(function(cible) { + let display = startFramedDisplay(getPlayerIdFromMsg(msg), 'D\xE9livrance', pretre, { + perso2: cible + }); + let printEffet = function(message) { + addLineToFramedDisplay(display, nomPerso(cible) + ' ' + message); + }; + let optFin = { + print: printEffet, + pageId: options.pageId + }; + _.each(messageEffetTemp, function(effet, nomEffet) { + if (effet.prejudiciable) { + //Attention, ne fonctionne pas avec les effets g\xE9n\xE9riques + let attr = tokenAttribute(cible, nomEffet); + if (attr.length > 0) + finDEffet(attr[0], nomEffet, attr[0].get('name'), cible.charId, evt, optFin); } - } - }); - _.each(messageEffetIndetermine, function(effet, nomEffet) { - if (effet.prejudiciable) { - let attr = tokenAttribute(cible, nomEffet); - if (attr.length > 0) { - printEffet(messageFin(cible, effet)); - evt.deletedAttributes.push(attr[0]); - attr[0].remove(); + }); + _.each(messageEffetCombat, function(effet, nomEffet) { + if (effet.prejudiciable) { + let attr = tokenAttribute(cible, nomEffet); + if (attr.length > 0) { + printEffet(messageFin(cible, effet)); + evt.deletedAttributes.push(attr[0]); + attr[0].remove(); + } } + }); + _.each(messageEffetIndetermine, function(effet, nomEffet) { + if (effet.prejudiciable) { + let attr = tokenAttribute(cible, nomEffet); + if (attr.length > 0) { + printEffet(messageFin(cible, effet)); + evt.deletedAttributes.push(attr[0]); + attr[0].remove(); + } + } + }); + if (attributeAsBool(cible, 'malediction')) { + printEffet("n'est plus maudite"); + removeTokenAttr(cible, 'malediction', evt); + } + if (attributeAsBool(cible, 'pointsDeSang')) { + printEffet("n'a plus de point de sang."); + removeTokenAttr(cible, 'pointsDeSang', evt); + } + //On enl\xE8ve les \xE9tats pr\xE9judiciables + if (getState(cible, 'aveugle')) { + printEffet("retrouve la vue"); + setState(cible, 'aveugle', false, evt); + } + if (getState(cible, 'affaibli')) { + printEffet("retrouve des forces"); + setState(cible, 'affaibli', false, evt); + } + if (getState(cible, 'etourdi')) { + printEffet("retrouve ses esprits"); + setState(cible, 'etourdi', false, evt); + } + if (getState(cible, 'paralyse')) { + printEffet("peut \xE0 nouveau bouger"); + setState(cible, 'paralyse', false, evt); + } + if (getState(cible, 'ralenti')) { + printEffet("retrouve une vitesse normale"); + setState(cible, 'ralenti', false, evt); + } + if (getState(cible, 'endormi')) { + printEffet("se r\xE9veille"); + setState(cible, 'endormi', false, evt); + } + if (getState(cible, 'apeure')) { + printEffet("reprend courage"); + setState(cible, 'apeure', false, evt); + } + //R\xE9g\xE9n\xE9ration d'une carac affaiblie de 1d4, si il y en a. + if (attributeAsInt(cible, 'affaiblissementdesagesse', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'sagesse', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de sagesse"); + } else if (attributeAsInt(cible, 'affaiblissementdecharisme', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'charisme', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de charisme"); + } else if (attributeAsInt(cible, 'affaiblissementdeintelligence', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'intelligence', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points d'intelligence"); + } + if (attributeAsInt(cible, 'affaiblissementdeconstitution', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'constitution', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de constitution"); + } else if (attributeAsInt(cible, 'affaiblissementdeforce', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'force', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de force"); + } else if (attributeAsInt(cible, 'affaiblissementdedexterite', 0) > 0) { + let d4 = rollDePlus(4); + diminueAffaiblissement(cible, 'dexterite', d4.val, evt); + printEffet("r\xE9cup\xE8re " + d4.roll + " points de dext\xE9rit\xE9"); } + sendFramedDisplay(display); }); - if (attributeAsBool(cible, 'malediction')) { - printEffet("n'est plus maudite"); - removeTokenAttr(cible, 'malediction', evt); - } - if (attributeAsBool(cible, 'pointsDeSang')) { - printEffet("n'a plus de point de sang."); - removeTokenAttr(cible, 'pointsDeSang', evt); - } - //On enlève les états préjudiciables - if (getState(cible, 'aveugle')) { - printEffet("retrouve la vue"); - setState(cible, 'aveugle', false, evt); - } - if (getState(cible, 'affaibli')) { - printEffet("retrouve des forces"); - setState(cible, 'affaibli', false, evt); - } - if (getState(cible, 'etourdi')) { - printEffet("retrouve ses esprits"); - setState(cible, 'etourdi', false, evt); - } - if (getState(cible, 'paralyse')) { - printEffet("peut à nouveau bouger"); - setState(cible, 'paralyse', false, evt); - } - if (getState(cible, 'ralenti')) { - printEffet("retrouve une vitesse normale"); - setState(cible, 'ralenti', false, evt); - } - if (getState(cible, 'endormi')) { - printEffet("se réveille"); - setState(cible, 'endormi', false, evt); - } - if (getState(cible, 'apeure')) { - printEffet("reprend courage"); - setState(cible, 'apeure', false, evt); - } - //Régénération d'une carac affaiblie de 1d4, si il y en a. - if (attributeAsInt(cible, 'affaiblissementdesagesse', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'sagesse', d4.val, evt); - printEffet("récupère " + d4.roll + " points de sagesse"); - } else if (attributeAsInt(cible, 'affaiblissementdecharisme', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'charisme', d4.val, evt); - printEffet("récupère " + d4.roll + " points de charisme"); - } else if (attributeAsInt(cible, 'affaiblissementdeintelligence', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'intelligence', d4.val, evt); - printEffet("récupère " + d4.roll + " points d'intelligence"); - } - if (attributeAsInt(cible, 'affaiblissementdeconstitution', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'constitution', d4.val, evt); - printEffet("récupère " + d4.roll + " points de constitution"); - } else if (attributeAsInt(cible, 'affaiblissementdeforce', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'force', d4.val, evt); - printEffet("récupère " + d4.roll + " points de force"); - } else if (attributeAsInt(cible, 'affaiblissementdedexterite', 0) > 0) { - let d4 = rollDePlus(4); - diminueAffaiblissement(cible, 'dexterite', d4.val, evt); - printEffet("récupère " + d4.roll + " points de dextérité"); - } - sendFramedDisplay(display); } function guerisonPerso(perso, evt, lanceur) { @@ -36181,36 +36577,36 @@ var COFantasy = COFantasy || function() { msgSoin = 'soigne ' + nomPerso(perso); } } else { - msgSoin = 'récupère'; + msgSoin = 'r\xE9cup\xE8re'; } msgSoin += ' de toutes les blessures subies'; if (lanceur) sendPerso(lanceur, msgSoin); else sendPerso(perso, msgSoin); if (getState(perso, 'blesse')) { setState(perso, 'blesse', false, evt); - } else { //On peut bien faire récupérer un PR + } else { //On peut bien faire r\xE9cup\xE9rer un PR let d = rajouterPointDeRecuperation(perso, evt); - if (d) sendPerso(perso, "récupère un point de récupération"); + if (d) sendPerso(perso, "r\xE9cup\xE8re un point de r\xE9cup\xE9ration"); } let soins = perso.token.get('bar1_max') - perso.token.get('bar1_value'); if (isNaN(soins)) { updateCurrentBar(perso, 1, perso.token.get('bar1_max'), evt); return; } - //Les affaiblissements de caractéristiques + //Les affaiblissements de caract\xE9ristiques allCaracs.forEach(function(carac) { let malus = attributeAsInt(perso, 'affaiblissementde' + carac, 0); if (malus > 0) { diminueAffaiblissement(perso, carac, malus, evt, malus); - sendPerso(perso, "récupère " + malus + " points " + deCarac(carac)); + sendPerso(perso, "r\xE9cup\xE8re " + malus + " points " + deCarac(carac)); } }); - //La putréfaction des momies + //La putr\xE9faction des momies if (attributeAsBool(perso, 'putrefaction')) { finDEffetDeNom(perso, 'putrefaction', evt); } if (soins <= 0) { - //Rien d'autre à faire (le script ne gère pas encore le reste) + //Rien d'autre \xE0 faire (le script ne g\xE8re pas encore le reste) return; } soigneToken(perso, soins, evt); @@ -36221,8 +36617,8 @@ var COFantasy = COFantasy || function() { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; - if (cmd === undefined || cmd.length < 3) { - error("cof-guerison attend le lanceur et la cible en argument", msg.content); + if (cmd === undefined || cmd.length < 2) { + error("cof-guerison attend le lanceur en argument", msg.content); return; } let lanceur = persoOfId(cmd[1], cmd[1], options.pageId); @@ -36230,27 +36626,49 @@ var COFantasy = COFantasy || function() { error("Le premier argument de !cof-guerison n'est pas un token valide", msg.content); return; } - let cible = persoOfId(cmd[2], cmd[2], options.pageId); - if (cible === undefined) { - error("Le deuxième argument de !cof-guerison n'est pas un token valide", msg.content); - return; + let c; + if (cmd.length > 2) c = persoOfId(cmd[2], cmd[2], options.pageId); + let cibles = [c]; + if (c === undefined) { + cibles = []; + getSelected(msg, function(selected, playerId) { + iterSelected(selected, function(cible) { + cibles.push(cible); + }); + }); + if (cibles.length < 1) { + if (cmd.length < 3) { + error("cof-guerison attend le lanceur et la cible en argument", msg.content); + } else { + error("Le deuxi\xE8me argument de !cof-guerison n'est pas un token valide", msg.content); + } + return; + } } if (options.dose === undefined && options.decrAttribute === undefined) { - options.limiteParJour = 1; + options.limiteParJour = { + val: 1 + }; } if (options.portee !== undefined) { - const dist = distanceCombat(lanceur.token, cible.token, options.pageId); - if (dist > options.portee) { - sendPerso(lanceur, "est trop loin de " + nomPerso(cible)); - return; - } + cibles = cibles.filter(function(cible) { + const dist = distanceCombat(lanceur.token, cible.token, options.pageId); + if (dist > options.portee) { + sendPerso(lanceur, "est trop loin de " + nomPerso(cible)); + return false; + } + return true; + }); } + if (cibles.length < 1) return; const evt = { - type: "Guérison", + type: "Gu\xE9rison", }; addEvent(evt); - if (limiteRessources(lanceur, options, 'guérison', 'guérison', evt)) return; - guerisonPerso(cible, evt, lanceur); + if (limiteRessources(lanceur, options, 'gu\xE9rison', 'gu\xE9rison', evt)) return; + cibles.forEach(function(cible) { + guerisonPerso(cible, evt, lanceur); + }); if (options.messages) { options.messages.forEach(function(m) { sendChat('', m); @@ -36263,16 +36681,16 @@ var COFantasy = COFantasy || function() { arme = armesEnMain(perso); if (arme === undefined && labelArmeDefaut) arme = getWeaponStats(perso, labelArmeDefaut); - //L'arme doit être une arme de contact ? + //L'arme doit \xEAtre une arme de contact ? if (armeContact && arme && arme.portee) { - sendPerso(perso, armeContact + " " + arme.name + " est une arme à distance."); + sendPerso(perso, armeContact + " " + arme.name + " est une arme \xE0 distance."); return; } if (arme) { return arme; } arme = { - name: 'Attaque par défaut', + name: 'Attaque par d\xE9faut', attSkillDiv: 0, attSkill: "@{ATKCAC}", crit: 20, @@ -36288,12 +36706,12 @@ var COFantasy = COFantasy || function() { }; options.contact = true; entrerEnCombat(attaquant, [defenseur], explications, evt); - //Recherche des armes utilisées + //Recherche des armes utilis\xE9es let armeAttaquant = armeDeContact(attaquant, options.armeAttaquant, options.labelArmeAttaquant, options.armeAttaquantContact); let armeDefenseur = armeDeContact(defenseur, options.armeDefenseur, options.labelArmeDefenseur, options.armeDefenseurContact); - let action = options.action || "Attaque opposée"; + let action = options.action || "Attaque oppos\xE9e"; if (!armeAttaquant.parDefaut) { action += " (" + armeAttaquant.name + ")"; } @@ -36313,7 +36731,7 @@ var COFantasy = COFantasy || function() { } } else if (getState(attaquant, 'immobilise')) { dice = 12; - explications.push("Attaquant immobilisé => D12 au lieu de D20 en Attaque"); + explications.push("Attaquant immobilis\xE9 => D12 au lieu de D20 en Attaque"); } let toEvaluateAttack = attackExpression(attaquant, 1, dice, critAttaquant, true, armeAttaquant); @@ -36352,14 +36770,14 @@ var COFantasy = COFantasy || function() { if (estAffaibli(defenseur)) { if (predicateAsBool(defenseur, 'insensibleAffaibli')) { malusAttaque = -2; - explications.push("Défenseur affaibli, mais insensible => -2 en Attaque"); + explications.push("D\xE9fenseur affaibli, mais insensible => -2 en Attaque"); } else { dice = 12; - explications.push("Défenseur affaibli => D12 au lieu de D20 en Attaque"); + explications.push("D\xE9fenseur affaibli => D12 au lieu de D20 en Attaque"); } } else if (getState(defenseur, 'immobilise')) { dice = 12; - explications.push("Défenseur immobilisé => D12 au lieu de D20 en Attaque"); + explications.push("D\xE9fenseur immobilis\xE9 => D12 au lieu de D20 en Attaque"); } toEvaluateAttack = attackExpression(defenseur, 1, dice, critDefenseur, true, armeDefenseur); sendChat('', toEvaluateAttack, function(resAttack) { @@ -36417,11 +36835,11 @@ var COFantasy = COFantasy || function() { resultat.succes = true; diminueMalediction(defenseur, evt); } - callback(resultat, display, explications); //evt est mis à jour - }); //fin du sendchat pour jet du défenseur + callback(resultat, display, explications); //evt est mis \xE0 jour + }); //fin du sendchat pour jet du d\xE9fenseur }); //Fin du sendChat pour jet de l'attaquant } catch (rollError) { - error("Erreur pendant le jet " + toEvaluateAttack + " dans attaqueContactOpposé", options); + error("Erreur pendant le jet " + toEvaluateAttack + " dans attaqueContactOppos\xE9", options); } } @@ -36434,15 +36852,15 @@ var COFantasy = COFantasy || function() { const attaquant = persoOfId(cmd[1], cmd[1]); const defenseur = persoOfId(cmd[2], cmd[2]); if (attaquant === undefined) { - error("Le premier argument de !cof-test-attaque-opposee doit être un token valide", cmd[1]); + error("Le premier argument de !cof-test-attaque-opposee doit \xEAtre un token valide", cmd[1]); return; } if (defenseur === undefined) { - error("Le deuxième argument de !cof-test-attaque-opposee doit être un token valide", cmd[2]); + error("Le deuxi\xE8me argument de !cof-test-attaque-opposee doit \xEAtre un token valide", cmd[2]); return; } const evt = { - type: "Test d'attaque opposée" + type: "Test d'attaque oppos\xE9e" }; const options = { pasDeDmg: true @@ -36467,7 +36885,7 @@ var COFantasy = COFantasy || function() { function desarmer(msg) { let cmd = msg.content.split(' '); if (cmd.length < 3) { - error("Il manque des arguments à !cof-desarmer", msg.content); + error("Il manque des arguments \xE0 !cof-desarmer", msg.content); return; } const guerrier = persoOfId(cmd[1], cmd[1]); @@ -36477,21 +36895,21 @@ var COFantasy = COFantasy || function() { } const cible = persoOfId(cmd[2], cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-desarmer n'est pas un token valide", cmd); + error("Le deuxi\xE8me argument de !cof-desarmer n'est pas un token valide", cmd); return; } let pageId = guerrier.token.get('pageid'); if (distanceCombat(guerrier.token, cible.token, pageId)) { - sendPerso(guerrier, "est trop loin de " + nomPerso(cible) + " pour le désarmer."); + sendPerso(guerrier, "est trop loin de " + nomPerso(cible) + " pour le d\xE9sarmer."); return; } - var options = { - action: "Désarmement", - armeContact: "doit porter une arme de contact pour désarmer son adversaire.", + const options = { + action: "D\xE9sarmement", + armeContact: "doit porter une arme de contact pour d\xE9sarmer son adversaire.", pasDeDmg: true, pageId: pageId, }; - //On cherche l'arme de la cible. On en aura besoin pour désarmer + //On cherche l'arme de la cible. On en aura besoin pour d\xE9sarmer let armeCible = armesEnMain(cible); let attrArmeCible = cible.attrArmeEnMain; if (armeCible) { @@ -36499,7 +36917,7 @@ var COFantasy = COFantasy || function() { if (armeCible.deuxMains) { options.bonusAttaqueDefenseur = [{ val: 5, - explication: nomPerso(cible) + " porte une arme à 2 mains => +5 à son jet" + explication: nomPerso(cible) + " porte une arme \xE0 2 mains => +5 \xE0 son jet" }]; } } @@ -36512,7 +36930,7 @@ var COFantasy = COFantasy || function() { } }; const evt = { - type: 'Désarmer' + type: 'D\xE9sarmer' }; if (cmd.length > 3) options.labelArmeAttaquant = cmd[3]; const playerId = getPlayerIdFromMsg(msg); @@ -36520,23 +36938,23 @@ var COFantasy = COFantasy || function() { function(res, display, explications) { let resultat; if (res.echecCritique) { - resultat = "échec critique"; + resultat = "\xE9chec critique"; } else if (res.echecCritiqueDefenseur) { - resultat = "succès, " + nomPerso(cible) + " laisse tomber son arme, difficile de la récupérer..."; + resultat = "succ\xE8s, " + nomPerso(cible) + " laisse tomber son arme, difficile de la r\xE9cup\xE9rer..."; enleverArmeCible(); } else if (res.critique) { - resultat = "réussite critique : " + nomPerso(cible) + " est désarmé, et " + nomPerso(guerrier) + " empêche de reprendre l'arme"; + resultat = "r\xE9ussite critique : " + nomPerso(cible) + " est d\xE9sarm\xE9, et " + nomPerso(guerrier) + " emp\xEAche de reprendre l'arme"; enleverArmeCible(); } else if (res.critiqueDefenseur) { - resultat = "échec, " + nomPerso(cible) + " garde son arme bien en main"; + resultat = "\xE9chec, " + nomPerso(cible) + " garde son arme bien en main"; } else if (res.echec) { - resultat = "échec, " + nomPerso(guerrier) + " n'a pas réussi à désarmer son adversaire"; - } else { //succès + resultat = "\xE9chec, " + nomPerso(guerrier) + " n'a pas r\xE9ussi \xE0 d\xE9sarmer son adversaire"; + } else { //succ\xE8s enleverArmeCible(); if (res.rollAttaquant > res.rollDefenseur + 9) { - resultat = "succès, " + nomPerso(guerrier) + " désarme son adversaire et l'empêche de récupérer son arme"; + resultat = "succ\xE8s, " + nomPerso(guerrier) + " d\xE9sarme son adversaire et l'emp\xEAche de r\xE9cup\xE9rer son arme"; } else { - resultat = "succès, " + nomPerso(guerrier) + " désarme son adversaire."; + resultat = "succ\xE8s, " + nomPerso(guerrier) + " d\xE9sarme son adversaire."; } } addLineToFramedDisplay(display, resultat); @@ -36550,7 +36968,7 @@ var COFantasy = COFantasy || function() { function appliquerBloquer(attaquant, cible, critique, evt, envoyerMessage) { let msg; - if (envoyerMessage) msg = "est bloqué par son adversaire"; + if (envoyerMessage) msg = "est bloqu\xE9 par son adversaire"; setAttrDuree(cible, 'bloqueManoeuvre', 1, evt, msg); if (critique) appliquerTenirADistance(attaquant, cible, false, evt, envoyerMessage); @@ -36558,7 +36976,7 @@ var COFantasy = COFantasy || function() { function appliquerTenirADistance(attaquant, cible, critique, evt, envoyerMessage) { let msg; - if (envoyerMessage) msg = "est tenu à distance par son adversaire"; + if (envoyerMessage) msg = "est tenu \xE0 distance par son adversaire"; setAttrDuree( cible, 'tenuADistanceManoeuvre(' + attaquant.token.id + ')', 1, evt, msg); if (critique) appliquerBloquer(attaquant, cible, false, evt, envoyerMessage); @@ -36570,7 +36988,7 @@ var COFantasy = COFantasy || function() { let duree = 1; if (critique) duree = randomInteger(6); let msg; - if (envoyerMessage) msg = "est aveuglé par son adversaire"; + if (envoyerMessage) msg = "est aveugl\xE9 par son adversaire"; setAttrDuree( cible, 'aveugleManoeuvre', duree, evt, msg); return critique; //Pour les DMs en plus @@ -36594,19 +37012,19 @@ var COFantasy = COFantasy || function() { attrArmeCible.remove(); } if (envoyerMessage) { - let msgDesarme = "est désarmé" + onGenre(cible, '', 'e'); + let msgDesarme = "est d\xE9sarm\xE9" + onGenre(cible, '', 'e'); if (critique) msgDesarme += ", son adversaire lui a pris son arme."; else msgDesarme += "."; sendPerso(cible, msgDesarme); } }, - verbe: 'désarmer', + verbe: 'd\xE9sarmer', duelliste: true }, faireDiversion: { appliquer: function(attaquant, cible, critique, evt, envoyerMessage) { var msg; - if (envoyerMessage) msg = "a son attention attirée ailleurs"; + if (envoyerMessage) msg = "a son attention attir\xE9e ailleurs"; var malus = -5; if (critique) malus = -10; setAttrDuree(cible, 'diversionManoeuvre', 1, evt, msg); @@ -36642,7 +37060,7 @@ var COFantasy = COFantasy || function() { var distance = rollDePlus(6); if (critique && distance < 3) distance = 3; if (envoyerMessage) - sendPerso(cible, "est repoussé" + onGenre(cible, '', 'e') + " et doit reculer de " + distance.roll + "m."); + sendPerso(cible, "est repouss\xE9" + onGenre(cible, '', 'e') + " et doit reculer de " + distance.roll + "m."); if (critique) setState(cible, 'renverse', true, evt); }, penalitePlusPetit: true, @@ -36651,13 +37069,13 @@ var COFantasy = COFantasy || function() { }, tenirADistance: { appliquer: appliquerTenirADistance, - verbe: 'tenir à distance', + verbe: 'tenir \xE0 distance', duelliste: true } }; //!cof-appliquer-manoeuvre id1 id2 effet attrId - //attrId est utilisé pour limiter le nombre d'utilisations + //attrId est utilis\xE9 pour limiter le nombre d'utilisations function appliquerManoeuvre(msg) { var cmd = msg.content.split(' '); if (cmd.length < 5) { @@ -36670,7 +37088,7 @@ var COFantasy = COFantasy || function() { } var limiteAttr = getObj('attribute', cmd[4]); if (limiteAttr === undefined) { - sendPlayer(msg, "La manoeuvre a déjà été choisie"); + sendPlayer(msg, "La manoeuvre a d\xE9j\xE0 \xE9t\xE9 choisie"); return; } var attaquant = persoOfId(cmd[1], cmd[1]); @@ -36680,7 +37098,7 @@ var COFantasy = COFantasy || function() { } var cible = persoOfId(cmd[2], cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-appliquer-manoeuvre n'est pas un token valide", cmd); + error("Le deuxi\xE8me argument de !cof-appliquer-manoeuvre n'est pas un token valide", cmd); return; } var effet = listeManoeuvres[cmd[3]]; @@ -36715,7 +37133,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2], cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-manoeuvre n'est pas un token valide", cmd); + error("Le deuxi\xE8me argument de !cof-manoeuvre n'est pas un token valide", cmd); return; } const evt = { @@ -36738,7 +37156,7 @@ var COFantasy = COFantasy || function() { function(res, display, explications) { let dmSupp; if (res.succes) { - addLineToFramedDisplay(display, nomPerso(attaquant) + " réussit à " + effet.verbe + " " + nomPerso(cible)); + addLineToFramedDisplay(display, nomPerso(attaquant) + " r\xE9ussit \xE0 " + effet.verbe + " " + nomPerso(cible)); dmSupp = effet.appliquer(attaquant, cible, res.critique, evt); if (manoeuvreDuelliste && !dmSupp) { let pageId = cible.token.get('pageid'); @@ -36746,8 +37164,8 @@ var COFantasy = COFantasy || function() { dmSupp = res.rollAttaquant >= defense + 10; } } else { - addLineToFramedDisplay(display, nomPerso(attaquant) + " ne réussit pas à " + effet.verbe + " " + nomPerso(cible)); - //Envoyer à la cible la possibilité d'appliquer un effet de son choix + addLineToFramedDisplay(display, nomPerso(attaquant) + " ne r\xE9ussit pas \xE0 " + effet.verbe + " " + nomPerso(cible)); + //Envoyer \xE0 la cible la possibilit\xE9 d'appliquer un effet de son choix } explications.forEach(function(expl) { addLineToFramedDisplay(display, expl, 80); @@ -36755,7 +37173,7 @@ var COFantasy = COFantasy || function() { if (dmSupp) { let actionGratuite = "!cof-attack " + attaquant.token.id + " " + cible.token.id + " -1 --auto"; - addLineToFramedDisplay(display, nomPerso(attaquant) + " fait en plus des dégâts à " + nomPerso(cible) + boutonSimple(actionGratuite, "lancer une attaque pour déterminer le montant"), 80); + addLineToFramedDisplay(display, nomPerso(attaquant) + " fait en plus des d\xE9g\xE2ts \xE0 " + nomPerso(cible) + boutonSimple(actionGratuite, "lancer une attaque pour d\xE9terminer le montant"), 80); } sendFramedDisplay(display); addEvent(evt); @@ -36765,11 +37183,11 @@ var COFantasy = COFantasy || function() { if (!res.succes && !manoeuvreDuelliste) { let charCible = getObj('character', cible.charId); if (charCible === undefined) { - error("Cible sans personnage associé", cible); + error("Cible sans personnage associ\xE9", cible); return; } let titre = "Choisir un effet contre " + nomPerso(attaquant); - //On crée un display sans le header + //On cr\xE9e un display sans le header display = startFramedDisplay(undefined, titre, cible, { retarde: true }); @@ -36784,7 +37202,7 @@ var COFantasy = COFantasy || function() { let ligneManoeuvre = boutonSimple(appliquerManoeuvre, man); addLineToFramedDisplay(display, ligneManoeuvre, 90); } - // on envoie la liste aux joueurs qui gèrent le voleur + // on envoie la liste aux joueurs qui g\xE8rent le voleur let playerIds = getPlayerIds(cible); playerIds.forEach(function(playerid) { addFramedHeader(display, playerid, true); @@ -36806,7 +37224,7 @@ var COFantasy = COFantasy || function() { return; } if (cmd.length < 3) { - error("Il manque des arguments à !cof-expert-combat-bousculer", msg.content); + error("Il manque des arguments \xE0 !cof-expert-combat-bousculer", msg.content); return; } let expert = persoOfId(cmd[1], cmd[1]); @@ -36816,7 +37234,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2], cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-expert-combat-bousculer n'est pas un token valide", cmd); + error("Le deuxi\xE8me argument de !cof-expert-combat-bousculer n'est pas un token valide", cmd); return; } if (!predicateAsBool(expert, 'expertDuCombat')) { @@ -36842,14 +37260,14 @@ var COFantasy = COFantasy || function() { var display = startFramedDisplay(playerId, "Bousculer", expert, { perso2: cible }); - explications.push("Dé d'expertise : " + deExpertise.roll); + explications.push("D\xE9 d'expertise : " + deExpertise.roll); if (resultat === 1) { - addLineToFramedDisplay(display, nomPerso(cible) + " est repoussé de " + - Math.ceil(deExpertise.val / 2) + " mètre" + (deExpertise.val > 1 ? "s" : "") + "
    S'il est acculé : " + + addLineToFramedDisplay(display, nomPerso(cible) + " est repouss\xE9 de " + + Math.ceil(deExpertise.val / 2) + " m\xE8tre" + (deExpertise.val > 1 ? "s" : "") + "
    S'il est accul\xE9 : " + boutonSimple("!cof-dmg " + deExpertise.val + " --target " + cmd[2], "Appliquer " + deExpertise.val + " DM")); setState(cible, "renverse", "true", evt); } else { - addLineToFramedDisplay(display, nomPerso(cible) + " n'est pas renversé"); + addLineToFramedDisplay(display, nomPerso(cible) + " n'est pas renvers\xE9"); } explications.forEach(function(expl) { addLineToFramedDisplay(display, expl, 80); @@ -36960,7 +37378,7 @@ var COFantasy = COFantasy || function() { dm: 3, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }], abilities: [{ @@ -37011,7 +37429,7 @@ var COFantasy = COFantasy || function() { dm: 5, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }], abilities: [{ @@ -37062,7 +37480,7 @@ var COFantasy = COFantasy || function() { dm: 5, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }, { name: 'predicats_script', @@ -37076,7 +37494,7 @@ var COFantasy = COFantasy || function() { titre: 'Attaque en embuscade', code: '!cof-attack @{selected|token_id} @{target|token_id} 1 --sournoise 1 --if moins FOR --etat renverse --endif' }, { - titre: 'Dévorer', + titre: 'D\xE9vorer', code: '!cof-attack @{selected|token_id} @{target|token_id} 1' }] }, @@ -37118,7 +37536,7 @@ var COFantasy = COFantasy || function() { dm: 7, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }, { name: 'predicats_script', @@ -37132,7 +37550,7 @@ var COFantasy = COFantasy || function() { titre: 'Attaque en embuscade', code: '!cof-attack @{selected|token_id} @{target|token_id} 1 --sournoise 1 --if moins FOR --etat renverse --endif' }, { - titre: 'Dévorer', + titre: 'D\xE9vorer', code: '!cof-attack @{selected|token_id} @{target|token_id} 1' }] }, @@ -37183,7 +37601,7 @@ var COFantasy = COFantasy || function() { }, ] }, tigreDentsDeSabre: { - nom: 'Tigre à dents de sabre', + nom: 'Tigre \xE0 dents de sabre', avatar: "https://s3.amazonaws.com/files.d20.io/images/59486272/f5lUcN3Y9H0thmJPrqa6FQ/max.png?1533041702", token: "https://s3.amazonaws.com/files.d20.io/images/60186469/ShcrgpvgXKiQsLVOyg4SZQ/thumb.png?1533903741", attributesFiche: { @@ -37222,7 +37640,7 @@ var COFantasy = COFantasy || function() { dm: 12, }], attributes: [{ - name: 'discrétion', + name: 'discr\xE9tion', current: 5 }, { name: 'predicats_script', @@ -37236,12 +37654,12 @@ var COFantasy = COFantasy || function() { titre: 'Attaque en embuscade', code: '!cof-attack @{selected|token_id} @{target|token_id} 1 --sournoise 1 --if moins FOR --etat renverse --endif' }, { - titre: 'Dévorer', + titre: 'D\xE9vorer', ccode: '!cof-attack @{selected|token_id} @{target|token_id} 1' }] }, oursPrehistorique: { - nom: 'Ours préhistorique', + nom: 'Ours pr\xE9historique', avatar: "https://s3.amazonaws.com/files.d20.io/images/59486323/V6RVSlBbeRJi_aIaIuGGBw/max.png?1533041814", token: "https://s3.amazonaws.com/files.d20.io/images/60186633/lNHXvCOsvfPMZDQnqJKQVw/thumb.png?1533904189", attributesFiche: { @@ -37266,7 +37684,7 @@ var COFantasy = COFantasy || function() { pnj_init: 10, RDS: 2, race: 'ours', - taille: 'énorme' + taille: '\xE9norme' }, pv: 110, attaques: [{ @@ -37305,11 +37723,11 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - error("pas de lanceur pour la conjuration de prédateurs", msg); + error("pas de lanceur pour la conjuration de pr\xE9dateurs", msg); return; } let evt = { - type: 'conjuration de prédateurs' + type: 'conjuration de pr\xE9dateurs' }; let combat = initiative(selected, evt); let abort; @@ -37317,12 +37735,12 @@ var COFantasy = COFantasy || function() { if (abort) return; if (options.tempeteDeMana) { if (selected.length > 1) { - sendPlayerAndGM(msg, playerId, "Il faut sélectionner un seul token pour les options de tempête de mana"); + sendPlayerAndGM(msg, playerId, "Il faut s\xE9lectionner un seul token pour les options de temp\xEAte de mana"); abort = true; return; } if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, portee: false, @@ -37336,11 +37754,11 @@ var COFantasy = COFantasy || function() { return; } else { if (options.tempeteDeMana.cout > 1) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } - if (limiteRessources(invocateur, options, 'invocationPredateur', 'lancer une invocation de prédateur', evt)) return; + if (limiteRessources(invocateur, options, 'invocationPredateur', 'lancer une invocation de pr\xE9dateur', evt)) return; let pageId = invocateur.token.get('pageid'); let niveau = ficheAttributeAsInt(invocateur, 'niveau', 1); if (!renforce) { @@ -37392,13 +37810,13 @@ var COFantasy = COFantasy || function() { toFront(token); let charPredateur = createCharacter(nomPredateur, playerId, predateur.avatar, token, predateur, evt); - //Tous les prédateurs sont des quadrupèdes + //Tous les pr\xE9dateurs sont des quadrup\xE8des let persoPredateur = { token: token, charId: charPredateur.id }; setPredicate(persoPredateur, 'quadrupede', evt); - //Attribut de predateur conjuré pour la disparition automatique + //Attribut de predateur conjur\xE9 pour la disparition automatique let attr = createObj('attribute', { name: 'predateurConjure', _characterid: charPredateur.id, @@ -37420,7 +37838,7 @@ var COFantasy = COFantasy || function() { initiative([{ _id: token.id }], evt); - // Ajout du Prédateur aux alliés de l'invocateur + // Ajout du Pr\xE9dateur aux alli\xE9s de l'invocateur let alliesInvocateur = alliesParPerso[invocateur.charId] || new Set(); alliesInvocateur.add(charPredateur.id); alliesParPerso[invocateur.charId] = alliesInvocateur; @@ -37444,11 +37862,11 @@ var COFantasy = COFantasy || function() { return; } let evt = { - type: "invocation d'une sphère de feu", + type: "invocation d'une sph\xE8re de feu", }; let combat = initiative(selected, evt); iterSelected(selected, function(invocateur) { - if (limiteRessources(invocateur, options, 'sphereDeFeu', 'lancer un sort de sphère de feu', evt)) return; + if (limiteRessources(invocateur, options, 'sphereDeFeu', 'lancer un sort de sph\xE8re de feu', evt)) return; let character = getObj('character', invocateur.charId); if (character === undefined) { error("Impossible de trouver le personnage de " + nomPerso(invocateur), invocateur); @@ -37457,7 +37875,7 @@ var COFantasy = COFantasy || function() { let pageId = invocateur.token.get('pageid'); let niveau = ficheAttributeAsInt(invocateur, 'niveau', 1); let sphere = { - nom: 'Sphère de feu', + nom: 'Sph\xE8re de feu', avatar: "https://s3.amazonaws.com/files.d20.io/images/260057530/nL8O6US3f1BpeTJkodWNCg/max.png?16394116785", token: "https://s3.amazonaws.com/files.d20.io/images/260057530/nL8O6US3f1BpeTJkodWNCg/thumb.png?16394116785", attributesFiche: { @@ -37466,7 +37884,7 @@ var COFantasy = COFantasy || function() { }, pv: 1, attaques: [{ - nom: 'Brûlure', + nom: 'Br\xFBlure', atk: 0, dmnbde: 3, dmde: 6, @@ -37479,7 +37897,7 @@ var COFantasy = COFantasy || function() { name: 'predicats_script', current: 'nonVivant immunite_feu sansEsprit initiativeDeriveeDe::' + character.get('name') + '\n', }, { - name: 'predateurConjure', //Pas exactement ça, mais ça fait ce qu'il faut + name: 'predateurConjure', //Pas exactement \xE7a, mais \xE7a fait ce qu'il faut current: niveau, max: combat.init, lie: options.mana !== undefined @@ -37504,7 +37922,7 @@ var COFantasy = COFantasy || function() { has_limit_field_of_vision: true, }); if (token === undefined) { - error("Impossible de créer le token de la sphère de feu ", sphere); + error("Impossible de cr\xE9er le token de la sph\xE8re de feu ", sphere); return; } toFront(token); @@ -37515,7 +37933,7 @@ var COFantasy = COFantasy || function() { initiative([{ _id: token.id }], evt); - // Ajout du Prédateur aux alliés de l'invocateur + // Ajout du Pr\xE9dateur aux alli\xE9s de l'invocateur let alliesInvocateur = alliesParPerso[invocateur.charId] || new Set(); alliesInvocateur.add(charSphere.id); alliesParPerso[invocateur.charId] = alliesInvocateur; @@ -37524,18 +37942,18 @@ var COFantasy = COFantasy || function() { }); //end getSelected } - //!cof-conjuration-armee [dé de DM] --limiteParJour... + //!cof-conjuration-armee [d\xE9 de DM] --limiteParJour... function conjurationArmee(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Il faut sélectionner le lanceur de la conjuration d'arméé", playerId); + sendPlayer(msg, "Il faut s\xE9lectionner le lanceur de la conjuration d'arm\xE9\xE9", playerId); return; } let abort; @@ -37543,12 +37961,12 @@ var COFantasy = COFantasy || function() { if (abort) return; if (options.tempeteDeMana) { if (selected.length > 1) { - sendPlayerAndGM(msg, playerId, "Il faut sélectionner un seul token pour les options de tempête de mana"); + sendPlayerAndGM(msg, playerId, "Il faut s\xE9lectionner un seul token pour les options de temp\xEAte de mana"); abort = true; return; } if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, portee: false, @@ -37562,16 +37980,16 @@ var COFantasy = COFantasy || function() { return; } else { if (options.tempeteDeMana.cout > 1) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } let pageId = invocateur.token.get('pageid'); let niveau = ficheAttributeAsInt(invocateur, 'niveau', 1); const evt = { - type: "Conjuration d'armée" + type: "Conjuration d'arm\xE9e" }; - if (limiteRessources(invocateur, options, 'conjurationArmee', "conjurer une armée", evt)) { + if (limiteRessources(invocateur, options, 'conjurationArmee', "conjurer une arm\xE9e", evt)) { addEvent(evt); return; } @@ -37592,7 +38010,7 @@ var COFantasy = COFantasy || function() { dm.nbDe = 2; } } - let nomArmee = "Armée de " + nomPerso(invocateur); + let nomArmee = "Arm\xE9e de " + nomPerso(invocateur); let token = createObj('graphic', { name: nomArmee, subtype: 'token', @@ -37652,13 +38070,13 @@ var COFantasy = COFantasy || function() { } //!cof-tenebres token-lanceur token-cible - // possibilité de --brumes pour un effet de brumes + // possibilit\xE9 de --brumes pour un effet de brumes function tenebres(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("!cof-tenebres mal formé, il faut un token comme premier argument", msg.content); + error("!cof-tenebres mal form\xE9, il faut un token comme premier argument", msg.content); return; } let necromant = persoOfId(cmd[1], cmd[1], options.pageId); @@ -37675,7 +38093,7 @@ var COFantasy = COFantasy || function() { const playerId = getPlayerIdFromMsg(msg); if (options.tempeteDeMana) { if (options.tempeteDeMana.cout === 0) { - //On demande de préciser les options + //On demande de pr\xE9ciser les options let optMana = { mana: options.mana, portee: true, @@ -37687,7 +38105,7 @@ var COFantasy = COFantasy || function() { return; } else { if (options.tempeteDeMana.cout > 1) { - sendPlayerAndGM(msg, playerId, "Attention, le coût de la tempête de mana (" + options.tempeteDeMana.cout + ") est supérieur au rang du sort"); + sendPlayerAndGM(msg, playerId, "Attention, le co\xFBt de la temp\xEAte de mana (" + options.tempeteDeMana.cout + ") est sup\xE9rieur au rang du sort"); } } } @@ -37703,7 +38121,7 @@ var COFantasy = COFantasy || function() { if (distanceCombat(necromant.token, target.token, options.pageId, { strict2: true }) > portee) { - sendPlayer(msg, "Le point visé est trop loin (portée " + portee + ")", playerId); + sendPlayer(msg, "Le point vis\xE9 est trop loin (port\xE9e " + portee + ")", playerId); return; } let duree = 5; @@ -37719,7 +38137,7 @@ var COFantasy = COFantasy || function() { if (options.brumes) { if (limiteRessources(necromant, options, 'brumes', 'lancer un sort de brumes', evt)) return; } else { - if (limiteRessources(necromant, options, 'tenebres', 'lancer un sort de ténèbres', evt)) return; + if (limiteRessources(necromant, options, 'tenebres', 'lancer un sort de t\xE9n\xE8bres', evt)) return; } if (!stateCOF.combat) { initPerso(necromant, evt); @@ -37739,7 +38157,7 @@ var COFantasy = COFantasy || function() { tokSpec.height = rayonUnite * PIX_PER_UNIT; tokSpec.layer = 'map'; } else { - tokSpec.name = "Ténèbres de " + nomPerso(necromant); + tokSpec.name = "T\xE9n\xE8bres de " + nomPerso(necromant); tokSpec.imgsrc = 'https://s3.amazonaws.com/files.d20.io/images/192072874/eJXFx20fD931DuBDvzAnQQ/thumb.png?1610469273'; tokSpec.width = 70; tokSpec.height = 70; @@ -37759,9 +38177,9 @@ var COFantasy = COFantasy || function() { if (options.brumes) sendPerso(necromant, "lance un sort de brumes pour " + duree + " tours"); else - sendPerso(necromant, "lance un sort de ténèbres pour " + duree + " tours"); + sendPerso(necromant, "lance un sort de t\xE9n\xE8bres pour " + duree + " tours"); } - // Calcul des cibles à aveugler + // Calcul des cibles \xE0 aveugler let cibles = []; let allToksDisque = findObjs({ @@ -37811,8 +38229,8 @@ var COFantasy = COFantasy || function() { if (options.brumes) effetTenebres.effet = 'brumes'; setEffetTemporaire(necromant, effetTenebres, duree, evt, options); if (target.token.get('bar1_max') == 0) { // jshint ignore:line - //C'est juste un token utilisé pour définir le disque - target.token.remove(); //On l'enlève, normalement plus besoin + //C'est juste un token utilis\xE9 pour d\xE9finir le disque + target.token.remove(); //On l'enl\xE8ve, normalement plus besoin } if (options.messages) { options.messages.forEach(function(m) { @@ -37822,7 +38240,7 @@ var COFantasy = COFantasy || function() { } const demonInvoque = { - nom: 'Démon', + nom: 'D\xE9mon', avatar: "https://s3.amazonaws.com/files.d20.io/images/183633585/DWpHYp4SLPCDCMHdmTyKOw/thumb.png?1607339938", token: "https://s3.amazonaws.com/files.d20.io/images/183633585/DWpHYp4SLPCDCMHdmTyKOw/thumb.png?1607339938", attributesFiche: { @@ -37847,7 +38265,7 @@ var COFantasy = COFantasy || function() { DEFDIV: 3, pnj_def: 17, pnj_init: 16, - race: 'démon', + race: 'd\xE9mon', taille: 'moyen' }, attaques: [{ @@ -37859,7 +38277,7 @@ var COFantasy = COFantasy || function() { }], attributes: [{ name: 'predicats_script', - current: 'démon' + current: 'd\xE9mon' }], abilities: [] }; @@ -37869,7 +38287,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("!cof-invoquer-demon mal formé, il faut un token comme premier argument", msg.content); + error("!cof-invoquer-demon mal form\xE9, il faut un token comme premier argument", msg.content); return; } let necromant = persoOfId(cmd[1], cmd[1], options.pageId); @@ -37886,7 +38304,7 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - if (limiteRessources(necromant, options, 'invoquerDemon', 'lance une invocation de démon', evt)) return; + if (limiteRessources(necromant, options, 'invoquerDemon', 'lance une invocation de d\xE9mon', evt)) return; let d6 = rollDePlus(6); evt.action.rolls.invocationDemonDmg = d6; let r = { @@ -37901,7 +38319,7 @@ var COFantasy = COFantasy || function() { if (!stateCOF.combat) { initPerso(necromant, evt); } - let tokenDemon = "Démon de " + nomPerso(necromant); + let tokenDemon = "D\xE9mon de " + nomPerso(necromant); let token = createObj('graphic', { name: tokenDemon, showname: 'true', @@ -37929,7 +38347,7 @@ var COFantasy = COFantasy || function() { evt.characters = [charDemon]; evt.tokens = [token]; let duree = 5 + modCarac(necromant, 'intelligence'); - //Attribut de démon invoqué pour la disparition automatique + //Attribut de d\xE9mon invoqu\xE9 pour la disparition automatique createObj('attribute', { name: 'demonInvoque', _characterid: charDemon.id, @@ -37944,13 +38362,13 @@ var COFantasy = COFantasy || function() { initiative([{ _id: token.id }], evt); - // Ajout du Démon aux alliés du Nécromant + // Ajout du D\xE9mon aux alli\xE9s du N\xE9cromant var alliesNecromant = alliesParPerso[necromant.charId] || new Set(); alliesNecromant.add(charDemon.id); alliesParPerso[necromant.charId] = alliesNecromant; - var msg = "invoque un démon"; + var msg = "invoque un d\xE9mon"; if (stateCOF.options.affichage.val.duree_effets.val) msg += " pour " + duree + " tours"; - msg += " mais cela lui coûte " + dmgDisplay + " PV"; + msg += " mais cela lui co\xFBte " + dmgDisplay + " PV"; sendPerso(necromant, msg); }); }, options); @@ -37997,7 +38415,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined || cmd.length < 2) { - error("!cof-animer-mort mal formé, il faut un token comme premier argument", msg.content); + error("!cof-animer-mort mal form\xE9, il faut un token comme premier argument", msg.content); return; } const necromant = persoOfId(cmd[1], cmd[1], options.pageId); @@ -38008,7 +38426,7 @@ var COFantasy = COFantasy || function() { let zombiesControles = attributeAsInt(necromant, 'zombiesControles', 0); let rangVoie = predicateAsInt(necromant, 'voieOutreTombe', 1); if (zombiesControles >= rangVoie) { - sendPerso(necromant, "ne peut plus animer de Zombie car il en contrôle déjà assez."); + sendPerso(necromant, "ne peut plus animer de Zombie car il en contr\xF4le d\xE9j\xE0 assez."); return; } options.lanceur = necromant; @@ -38052,7 +38470,7 @@ var COFantasy = COFantasy || function() { let charZombie = createCharacter(nomToken, playerId, zombieAnime.avatar, token, zombie, evt); evt.characters.push(charZombie); evt.tokens.push(token); - // Dégradation du Zombie + // D\xE9gradation du Zombie createObj('attribute', { name: 'degradationZombie', _characterid: charZombie.id, @@ -38068,7 +38486,7 @@ var COFantasy = COFantasy || function() { initiative([{ _id: token.id }], evt); - // Ajout du Zombie aux alliés du Nécromant + // Ajout du Zombie aux alli\xE9s du N\xE9cromant let alliesNecromant = alliesParPerso[necromant.charId] || new Set(); alliesNecromant.add(charZombie.id); alliesParPerso[necromant.charId] = alliesNecromant; @@ -38086,7 +38504,7 @@ var COFantasy = COFantasy || function() { const MONTER = String.fromCharCode(0x2197); const DESCENDRE = String.fromCharCode(0x2198); - //Crée les macros utiles au jeu + //Cr\xE9e les macros utiles au jeu const gameMacros = [{ name: 'Actions', action: "!cof-liste-actions", @@ -38164,7 +38582,7 @@ var COFantasy = COFantasy || function() { istokenaction: true }, { name: 'Surprise', - action: "!cof-surprise ?{difficulté}", + action: "!cof-surprise ?{difficult\xE9}", visibleto: '', istokenaction: false, inBar: true @@ -38174,20 +38592,20 @@ var COFantasy = COFantasy || function() { visibleto: 'all', istokenaction: true, }, { - name: 'Éteindre', - action: "!cof-eteindre-lumiere ?{Quelle lumière?|Tout}", + name: '\xC9teindre', + action: "!cof-eteindre-lumiere ?{Quelle lumi\xE8re?|Tout}", visibleto: '', istokenaction: false, inBar: true }, { name: 'devient', - action: "!cof-set-state ?{État|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blesse|encombre} true", + action: "!cof-set-state ?{\xC9tat|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blesse|encombre} true", visibleto: '', istokenaction: false, inBar: true }, { - name: 'enlève', - action: "!cof-set-state ?{État|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blesse|encombre} false", + name: 'enl\xE8ve', + action: "!cof-set-state ?{\xC9tat|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blesse|encombre} false", visibleto: '', istokenaction: false, inBar: true @@ -38225,20 +38643,20 @@ var COFantasy = COFantasy || function() { if (prev === undefined) { m.playerid = playerId; createObj('macro', m); - sendPlayer(msg, "Macro " + m.name + " créée."); + sendPlayer(msg, "Macro " + m.name + " cr\xE9\xE9e."); if (m.inBar) inBar.push(m.name); } else if (force) { prev.set('action', m.action); prev.set('visibleto', m.visibleto); prev.set('istokenaction', m.istokenaction); - sendPlayer(msg, "Macro " + m.name + " réécrite."); + sendPlayer(msg, "Macro " + m.name + " r\xE9\xE9crite."); if (m.inBar) inBar.push(m.name); } else { - sendPlayer(msg, "Macro " + m.name + " déjà présente (utiliser --force pour réécrire)."); + sendPlayer(msg, "Macro " + m.name + " d\xE9j\xE0 pr\xE9sente (utiliser --force pour r\xE9\xE9crire)."); } }); if (inBar.length > 0) { - sendPlayer(msg, "Macros à mettre dans la barre d'action du MJ : " + inBar.join(', ')); + sendPlayer(msg, "Macros \xE0 mettre dans la barre d'action du MJ : " + inBar.join(', ')); } stateCOF.gameMacros = gameMacros; } @@ -38248,24 +38666,24 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd === undefined || cmd.length < 3) { - error("Il faut au moins 2 arguments à !cof-lumiere", cmd); + error("Il faut au moins 2 arguments \xE0 !cof-lumiere", cmd); return; } const cible = persoOfId(cmd[1]); if (cible === undefined) { - error("le premier argument de !cof-lumière doit être un token", cmd); + error("le premier argument de !cof-lumi\xE8re doit \xEAtre un token", cmd); return; } const radius = parseInt(cmd[2]); if (isNaN(radius) || radius <= 0) { - error("La distance de vue de la lumière doit être positive", cmd[2]); + error("La distance de vue de la lumi\xE8re doit \xEAtre positive", cmd[2]); return; } let dimRadius = ''; if (cmd.length > 3) { dimRadius = parseInt(cmd[3]); if (isNaN(dimRadius)) { - error("La distance de vue de la lumière assombrie doit être un nombre", cmd[3]); + error("La distance de vue de la lumi\xE8re assombrie doit \xEAtre un nombre", cmd[3]); dimRadius = ''; } } @@ -38278,7 +38696,7 @@ var COFantasy = COFantasy || function() { type: 'lumiere', }; addEvent(evt); - if (limiteRessources(options.lanceur, options, 'lumière', "lumière", evt)) return; + if (limiteRessources(options.lanceur, options, 'lumi\xE8re', "lumi\xE8re", evt)) return; ajouteUneLumiere(cible, nomToken, radius, dimRadius, evt); } @@ -38292,7 +38710,7 @@ var COFantasy = COFantasy || function() { } let lumId = al.get('max'); if (lumId == 'surToken') { - //Il faut enlever la lumière sur tous les tokens + //Il faut enlever la lumi\xE8re sur tous les tokens let allTokens = [perso.token]; if (perso.token.get('bar1_value') !== '') { allTokens = findObjs({ @@ -38320,7 +38738,7 @@ var COFantasy = COFantasy || function() { name: lumName }); if (tokensLumiere.length === 0) { - log("Pas de token pour la lumière " + lumName); + log("Pas de token pour la lumi\xE8re " + lumName); al.remove(); return; } @@ -38352,7 +38770,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionnée pour !cof-eteindre-lumiere", playerId); + sendPlayer(msg, "Pas de cible s\xE9lectionn\xE9e pour !cof-eteindre-lumiere", playerId); return; } const cmd = options.cmd; @@ -38361,7 +38779,7 @@ var COFantasy = COFantasy || function() { if (groupe && groupe.toLowerCase() == 'tout') groupe = ''; let pageId = options.pageId; const evt = { - type: "Eteindre la lumière" + type: "Eteindre la lumi\xE8re" }; iterSelected(selected, function(perso) { pageId = pageId || perso.token.get('pageid'); @@ -38380,7 +38798,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd.length < 2) { - error("Il faut préciser le token en argument de !cof-torche"); + error("Il faut pr\xE9ciser le token en argument de !cof-torche"); return; } let pageId = options.pageId; @@ -38392,15 +38810,15 @@ var COFantasy = COFantasy || function() { pageId = pageId || perso.token.get('pageid'); var diminueDuree = 0; if (cmd.length > 2) { - //Dans ce cas, c'est pour diminuer la durée de vie de la torche + //Dans ce cas, c'est pour diminuer la dur\xE9e de vie de la torche diminueDuree = parseInt(cmd[2]); if (isNaN(diminueDuree) || diminueDuree <= 0) { - sendPlayer(msg, "Le deuxième argument de !cof-torche doit être un nombre strictement positif " + msg.content); + sendPlayer(msg, "Le deuxi\xE8me argument de !cof-torche doit \xEAtre un nombre strictement positif " + msg.content); return; } } var evt; - //On commence par chercher si une torche est allumée + //On commence par chercher si une torche est allum\xE9e var torcheAllumee = false; var attrLumiere = tokenAttribute(perso, 'lumiere').filter(function(a) { return a.get('current').startsWith('torche'); @@ -38408,7 +38826,7 @@ var COFantasy = COFantasy || function() { if (!diminueDuree && attrLumiere.length > 0) { torcheAllumee = true; evt = { - type: "Éteindre les torches" + type: "\xC9teindre les torches" }; attrLumiere.forEach(function(al) { let lumName = al.get('current'); @@ -38436,8 +38854,8 @@ var COFantasy = COFantasy || function() { return; } if (tempsTorche === 0) { - if (nbTorches === 0) { //Donc forcément torcheAllumee - //On remet l'attribut dans un état convenable + if (nbTorches === 0) { //Donc forc\xE9ment torcheAllumee + //On remet l'attribut dans un \xE9tat convenable setTokenAttr(perso, 'torches', 0, evt, { maxVal: 60 }); @@ -38457,7 +38875,7 @@ var COFantasy = COFantasy || function() { nbTorches--; temps += tempsTorche; tempsTorche = 60; - var msgDiminue = "torche épuisée."; + var msgDiminue = "torche \xE9puis\xE9e."; if (nbTorches === 0) { msgDiminue += " Plus de torche !"; } else if (nbTorches == 1) { @@ -38470,23 +38888,23 @@ var COFantasy = COFantasy || function() { setTokenAttr(perso, 'torches', nbTorches, evt, { maxVal: tempsTorche }); - sendChar(perso.charId, '/w gm temps de torche diminué de ' + temps + ' minutes'); + sendChar(perso.charId, '/w gm temps de torche diminu\xE9 de ' + temps + ' minutes'); addEvent(evt); return; } if (torcheAllumee) { - var msgTorche = "/w gm torche éteinte. "; + var msgTorche = "/w gm torche \xE9teinte. "; if (nbTorches > 1) { msgTorche += "Reste " + (nbTorches - 1) + " torche"; if (nbTorches > 2) msgTorche += "s neuves"; else msgTorche += " neuve"; - msgTorche += ", et une torche pouvant encore éclairer " + tempsTorche + " minutes."; + msgTorche += ", et une torche pouvant encore \xE9clairer " + tempsTorche + " minutes."; } else { - msgTorche += "Elle peut encore éclairer " + tempsTorche + " minutes."; + msgTorche += "Elle peut encore \xE9clairer " + tempsTorche + " minutes."; } sendChar(perso.charId, msgTorche + - boutonSimple("!cof-torche " + perso.token.id + " ?{Durée?}", "Temps depuis allumage")); + boutonSimple("!cof-torche " + perso.token.id + " ?{Dur\xE9e?}", "Temps depuis allumage")); addEvent(evt); return; } @@ -38495,7 +38913,7 @@ var COFantasy = COFantasy || function() { }; ajouteUneLumiere(perso, 'torche', 13, 7, evt); var msgAllume = - "allume une torche, qui peut encore éclairer pendant " + tempsTorche + + "allume une torche, qui peut encore \xE9clairer pendant " + tempsTorche + " minute"; if (tempsTorche > 1) msgAllume += 's'; msgAllume += '.'; @@ -38508,9 +38926,9 @@ var COFantasy = COFantasy || function() { addEvent(evt); return; } - //On ne tient pas le compte précis des torches + //On ne tient pas le compte pr\xE9cis des torches if (torcheAllumee) { - whisperChar(perso.charId, "éteint sa torche"); + whisperChar(perso.charId, "\xE9teint sa torche"); } else { evt = { type: "Allumer une torche" @@ -38522,9 +38940,9 @@ var COFantasy = COFantasy || function() { } //!cof-options - //!cof-options opt1 [... optn] val, met l'option à val - //!cof-options [opt0 ... optk] reset remet toutes les options à leur valeur patr défaut - //Dans tous les cas, affiche les options du niveau demandé + //!cof-options opt1 [... optn] val, met l'option \xE0 val + //!cof-options [opt0 ... optk] reset remet toutes les options \xE0 leur valeur patr d\xE9faut + //Dans tous les cas, affiche les options du niveau demand\xE9 function setCofOptions(msg) { const playerId = getPlayerIdFromMsg(msg); if (!playerIsGM(playerId)) { @@ -38547,7 +38965,7 @@ var COFantasy = COFantasy || function() { cmd.shift(); cmd.forEach(function(c) { if (fini) { - sendPlayer(msg, "Option " + c + " ignorée", playerId); + sendPlayer(msg, "Option " + c + " ignor\xE9e", playerId); return; } if (c == 'reset') { @@ -38557,7 +38975,7 @@ var COFantasy = COFantasy || function() { } else if (cofOptions[c]) { if (cofOptions[c].type == 'options') { if (defOpt[c] === undefined) { - sendPlayer(msg, "Option " + c + " inconnue dans les options par défaut", playerId); + sendPlayer(msg, "Option " + c + " inconnue dans les options par d\xE9faut", playerId); fini = true; return; } @@ -38569,7 +38987,7 @@ var COFantasy = COFantasy || function() { newOption = cofOptions[c]; } } else { - if (newOption) { //on met newOption à c + if (newOption) { //on met newOption \xE0 c let val = c; switch (newOption.type) { case 'bool': @@ -38585,7 +39003,7 @@ var COFantasy = COFantasy || function() { val = false; break; default: - sendPlayer(msg, "L'option " + lastCmd + " ne peut être que true ou false", playerId); + sendPlayer(msg, "L'option " + lastCmd + " ne peut \xEAtre que true ou false", playerId); val = newOption.val; } fini = true; @@ -38593,7 +39011,7 @@ var COFantasy = COFantasy || function() { case 'int': val = parseInt(c); if (isNaN(val)) { - sendPlayer(msg, "L'option " + lastCmd + " est une valeur entière", playerId); + sendPlayer(msg, "L'option " + lastCmd + " est une valeur enti\xE8re", playerId); val = newOption.val; } fini = true; @@ -38634,7 +39052,7 @@ var COFantasy = COFantasy || function() { case 'bool': action += ' ?{Nouvelle valeur de ' + optVu + '|actif,true|inactif,false}'; if (displayedVal) - // Bizarrement, le caractère '*' modifie la suite du tableau + // Bizarrement, le caract\xE8re '*' modifie la suite du tableau displayedVal = '3'; else displayedVal = '*'; @@ -38664,7 +39082,7 @@ var COFantasy = COFantasy || function() { line += boutonSimple(action, displayedVal) + after; addLineToFramedDisplay(display, line); } - addLineToFramedDisplay(display, boutonSimple('!cof-options' + prefix + ' reset', 'Valeurs par défaut'), 70); + addLineToFramedDisplay(display, boutonSimple('!cof-options' + prefix + ' reset', 'Valeurs par d\xE9faut'), 70); sendFramedDisplay(display); } @@ -38680,20 +39098,20 @@ var COFantasy = COFantasy || function() { let pageId = options.pageId; let samourai = persoOfId(cmd[1], cmd[1], pageId); if (samourai === undefined) { - error("Le token sélectionné n'est pas valide", msg.content); + error("Le token s\xE9lectionn\xE9 n'est pas valide", msg.content); return; } if (attributeAsBool(samourai, 'defiSamourai')) { - sendPlayer(msg, nomPerso(samourai) + " a déjà lancé un défi durant ce combat."); + sendPlayer(msg, nomPerso(samourai) + " a d\xE9j\xE0 lanc\xE9 un d\xE9fi durant ce combat."); return; } let cible = persoOfId(cmd[2], cmd[2], pageId); if (cible === undefined) { - error("Le deuxième token sélectionné n'est pas valide", msg.content); + error("Le deuxi\xE8me token s\xE9lectionn\xE9 n'est pas valide", msg.content); return; } const evt = { - type: 'Défi samouraï' + type: 'D\xE9fi samoura\xEF' }; let explications = []; entrerEnCombat(samourai, [cible], explications, evt); @@ -38704,14 +39122,14 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3) { bonus = parseInt(cmd[3]); if (isNaN(bonus) || bonus < 1) { - error("Bonus de défi de samouraï incorrect", cmd[3]); + error("Bonus de d\xE9fi de samoura\xEF incorrect", cmd[3]); bonus = undefined; } } if (bonus === undefined) bonus = predicateAsInt(samourai, 'voieDeLHonneur', 2); setTokenAttr(samourai, 'defiSamourai', bonus, evt, { - msg: nomPerso(samourai) + " lance un défi à " + nomPerso(cible), + msg: nomPerso(samourai) + " lance un d\xE9fi \xE0 " + nomPerso(cible), maxVal: idName(cible) }); } @@ -38721,16 +39139,16 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; const cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 6) { - error("Il manque des arguments à !cof-enveloppement", cmd); + error("Il manque des arguments \xE0 !cof-enveloppement", cmd); return; } let cube = persoOfId(cmd[1]); if (cube === undefined) { - error("Token non défini", cmd[1]); + error("Token non d\xE9fini", cmd[1]); return; } if (!peutController(msg, cube)) { @@ -38739,12 +39157,12 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2]); if (cible === undefined) { - error("Token non défini", cmd[2]); + error("Token non d\xE9fini", cmd[2]); return; } let difficulte = parseInt(cmd[3]); if (isNaN(difficulte)) { - error("Difficulté n'est pas un nombre, on prend 15 par défaut", cmd[3]); + error("Difficult\xE9 n'est pas un nombre, on prend 15 par d\xE9faut", cmd[3]); difficulte = 15; } let exprDM; @@ -38756,18 +39174,18 @@ var COFantasy = COFantasy || function() { exprDM = cmd[4] + ' ' + cmd[5]; break; case 'etreinte': - type = 'étreinte'; + type = '\xE9treinte'; exprDM = cmd[4] + ' ' + cmd[5]; break; default: - error("Impossible de déterminer les dégâts quand enveloppé", cmd[4]); + error("Impossible de d\xE9terminer les d\xE9g\xE2ts quand envelopp\xE9", cmd[4]); return; } doEnveloppement(cube, cible, difficulte, type, exprDM, options); } //!cof-enveloppement cubeId targetId Difficulte Attaque - //Attaque peut être soit label l, soit ability a, soit etreinte expr + //Attaque peut \xEAtre soit label l, soit ability a, soit etreinte expr function doEnveloppement(attaquant, cible, difficulte, type, exprDM, options) { const evt = { type: type, @@ -38782,9 +39200,9 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - //Choix de la caractéristique pour résister : FOR ou DEX + //Choix de la caract\xE9ristique pour r\xE9sister : FOR ou DEX let caracRes = meilleureCarac('FOR', 'DEX', cible, 10 + modCarac(attaquant, 'force')); - let titre = (type == 'étreinte') ? 'Étreinte' : 'Enveloppement'; + let titre = (type == '\xE9treinte') ? '\xC9treinte' : 'Enveloppement'; let display = startFramedDisplay(options.playerId, titre, attaquant, { perso2: cible }); @@ -38793,14 +39211,14 @@ var COFantasy = COFantasy || function() { testOppose(rollId, attaquant, 'FOR', options, cible, caracRes, options, explications, evt, function(res, crit, rt1, rt2) { - let act = " a absorbé "; + let act = " a absorb\xE9 "; switch (res) { case 1: - if (type == 'étreinte') act = " s'est enroulé autour de "; + if (type == '\xE9treinte') act = " s'est enroul\xE9 autour de "; explications.push(nomPerso(attaquant) + act + nomPerso(cible)); let attaquantId = idName(attaquant); let maxval = difficulte; - if (type == 'étreinte') maxval = 'etreinte ' + difficulte; + if (type == '\xE9treinte') maxval = 'etreinte ' + difficulte; setTokenAttr(cible, 'enveloppePar', attaquantId, evt, { maxVal: maxval }); @@ -38810,23 +39228,23 @@ var COFantasy = COFantasy || function() { setTokenAttr(attaquant, 'enveloppe', cibleId, evt, { maxVal: exprDM }); - if (type == 'étreinte') setState(cible, 'immobilise', true, evt); + if (type == '\xE9treinte') setState(cible, 'immobilise', true, evt); break; case 2: if (caracRes == 'FOR') { - if (type == 'étreinte') act = 'étreindre'; + if (type == '\xE9treinte') act = '\xE9treindre'; else act = 'absorber'; - explications.push(nomPerso(cible) + " résiste et ne se laisse pas " + act); + explications.push(nomPerso(cible) + " r\xE9siste et ne se laisse pas " + act); } else { - if (type == 'étreinte') act = "l'étreinte"; + if (type == '\xE9treinte') act = "l'\xE9treinte"; else act = "l'absorption"; - explications.push(nomPerso(cible) + " évite " + act); + explications.push(nomPerso(cible) + " \xE9vite " + act); } break; default: //match null, la cible s'en sort - if (type == 'étreinte') act = "l'étreinte"; + if (type == '\xE9treinte') act = "l'\xE9treinte"; else act = "l'enveloppement"; - explications.push(nomPerso(cible) + " échappe de justesse à " + act); + explications.push(nomPerso(cible) + " \xE9chappe de justesse \xE0 " + act); } explications.forEach(function(e) { addLineToFramedDisplay(display, e); @@ -38843,8 +39261,8 @@ var COFantasy = COFantasy || function() { options.cmd && options.cmd.length > 1 && options.cmd[1] == 'libere'; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "!cof-echapper-enveloppement sans sélection de token", playerId); - log("!cof-echapper-enveloppement requiert de sélectionner des tokens"); + sendPlayer(msg, "!cof-echapper-enveloppement sans s\xE9lection de token", playerId); + log("!cof-echapper-enveloppement requiert de s\xE9lectionner des tokens"); return; } iterSelected(selected, function(perso) { @@ -38856,7 +39274,7 @@ var COFantasy = COFantasy || function() { attr = attr[0]; let cube = persoOfIdName(attr.get('current'), options.pageId); if (cube === undefined) { - error("Attribut enveloppePar mal formé, on le supprime", attr.get('current')); + error("Attribut enveloppePar mal form\xE9, on le supprime", attr.get('current')); attr.remove(); unlockToken(perso); return; @@ -38869,7 +39287,7 @@ var COFantasy = COFantasy || function() { } if (libere) { let evt = { - type: 'Libération', + type: 'Lib\xE9ration', deletedAttributes: [attr] }; addEvent(evt); @@ -38884,12 +39302,12 @@ var COFantasy = COFantasy || function() { a.remove(); } }); - sendChar(cube.charId, "libère " + nomPerso(perso)); + sendChar(cube.charId, "lib\xE8re " + nomPerso(perso)); return; } let difficulte = parseInt(maxAttr); if (isNaN(difficulte)) { - error("Difficulté mal formée", attr.get('max')); + error("Difficult\xE9 mal form\xE9e", attr.get('max')); difficulte = 15; } doEchapperEnveloppement(perso, etreinte, cube, difficulte, options); @@ -38912,16 +39330,16 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); let titre = "Tentative de sortir de " + nomPerso(cube); - if (etreinte) titre = "Tentative de se libérer de l'etreinte de " + cube.tokName; + if (etreinte) titre = "Tentative de se lib\xE9rer de l'etreinte de " + cube.tokName; const display = startFramedDisplay(options.playerId, titre, perso, { chuchote: options.secret }); const testId = 'enveloppement_' + perso.token.id; testCaracteristique(perso, 'FOR', difficulte, testId, options, evt, function(tr) { - addLineToFramedDisplay(display, "Résultat : " + tr.texte); + addLineToFramedDisplay(display, "R\xE9sultat : " + tr.texte); if (tr.reussite) { - addLineToFramedDisplay(display, "C'est réussi, " + nomPerso(perso) + " s'extirpe de " + cube.tokName + tr.modifiers); + addLineToFramedDisplay(display, "C'est r\xE9ussi, " + nomPerso(perso) + " s'extirpe de " + cube.tokName + tr.modifiers); toFront(perso.token); evt.deletedAttributes = evt.deletedAttributes || []; let attr = tokenAttribute(perso, 'enveloppePar')[0]; @@ -38938,7 +39356,7 @@ var COFantasy = COFantasy || function() { } }); } else { - let msgRate = "C'est raté." + tr.rerolls + tr.modifiers; + let msgRate = "C'est rat\xE9." + tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, msgRate); } sendFramedDisplay(display); @@ -38950,7 +39368,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { @@ -38974,7 +39392,7 @@ var COFantasy = COFantasy || function() { attr = tokenAttribute(perso, 'estDevorePar'); attrName = 'estDevorePar'; if (attr.length === 0) { - sendPlayer(msg, nomPerso(perso) + " n'est pas agrippé."); + sendPlayer(msg, nomPerso(perso) + " n'est pas agripp\xE9."); return; } } @@ -38983,13 +39401,17 @@ var COFantasy = COFantasy || function() { attr = attr[0]; let agrippant = persoOfIdName(attr.get('current'), options.pageId); if (agrippant === undefined) { - error("Attribut " + attrName + " mal formé, on le supprime", attr.get('current')); + error("Attribut " + attrName + " mal form\xE9, on le supprime", attr.get('current')); attr.remove(); unlockToken(perso); return; } if (cmd.length > 2 && cmd[2] == 'libere') { - finAgripper(perso, agrippant, attrName); + const evt = { + type: "Lib\xE8re une cible agripp\xE9e" + }; + finAgripper(perso, agrippant, attrName, evt); + sendPerso(agrippant, "rel\xE2che " + nomPerso(perso)); return; } doLibererAgrippe(perso, agrippant, attrName, options); @@ -39031,7 +39453,7 @@ var COFantasy = COFantasy || function() { const evt = { type: 'libererAgrippe', action: { - titre: "Se libérer", + titre: "Se lib\xE9rer", perso, agrippant, attrName, @@ -39039,7 +39461,7 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - let titre = "Tentative de se libérer de " + nomPerso(agrippant); + let titre = "Tentative de se lib\xE9rer de " + nomPerso(agrippant); let playerId = options.playerId; let display = startFramedDisplay(playerId, titre, perso, { chuchote: options.secret @@ -39056,14 +39478,14 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, e); }); if (tr == 2) { - let msgRate = "C'est raté, " + nomPerso(perso) + " est toujours "; + let msgRate = "C'est rat\xE9, " + nomPerso(perso) + " est toujours "; if (attrName == 'etreinteImmolePar' || attrName == 'etreinteScorpionPar') - msgRate += "prisonnier de l'étreinte de " + nomPerso(agrippant); + msgRate += "prisonnier de l'\xE9treinte de " + nomPerso(agrippant); else if (attrName == 'estDevorePar') msgRate += 'saisi' + eForFemale(perso) + '.'; - else msgRate += "agrippé" + eForFemale(perso) + "."; + else msgRate += "agripp\xE9" + eForFemale(perso) + "."; addLineToFramedDisplay(display, msgRate); - if (attrName == 'etreinteScorpionPar') { // Cas d'étreinte de scorpion avec dommages automatiques + if (attrName == 'etreinteScorpionPar') { // Cas d'\xE9treinte de scorpion avec dommages automatiques let d6 = evt.action.rolls.etreinteDmg || rollDePlus(6, { bonus: 3 }); @@ -39076,7 +39498,7 @@ var COFantasy = COFantasy || function() { let explications2 = []; perso.ignoreTouteRD = true; dealDamage(perso, r, [], evt, false, {}, explications2, function(dmgDisplay) { - let dmgMsg = "L'étreinte du scorpion inflige " + dmgDisplay + " dégâts."; + let dmgMsg = "L'\xE9treinte du scorpion inflige " + dmgDisplay + " d\xE9g\xE2ts."; setTokenAttr(perso, "etreinteScorpionRatee", true, evt); addLineToFramedDisplay(display, dmgMsg); explications2.forEach(function(expl) { @@ -39089,9 +39511,9 @@ var COFantasy = COFantasy || function() { } } else { if (tr === 0) - addLineToFramedDisplay(display, "Réussi de justesse, " + nomPerso(perso) + " se libère."); + addLineToFramedDisplay(display, "R\xE9ussi de justesse, " + nomPerso(perso) + " se lib\xE8re."); else //tr == 1 - addLineToFramedDisplay(display, "Réussi, " + nomPerso(perso) + " se libère."); + addLineToFramedDisplay(display, "R\xE9ussi, " + nomPerso(perso) + " se lib\xE8re."); toFront(perso.token); finAgripper(perso, agrippant, attrName, evt); sendFramedDisplay(display); @@ -39107,7 +39529,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { @@ -39118,13 +39540,13 @@ var COFantasy = COFantasy || function() { let attrName = 'estEcrasePar'; let attr = tokenAttribute(perso, attrName); if (attr.length === 0) { - sendPlayer(msg, nomPerso(perso) + " n'est pas écrasé."); + sendPlayer(msg, nomPerso(perso) + " n'est pas \xE9cras\xE9."); return; } attr = attr[0]; let agrippant = persoOfIdName(attr.get('current'), options.pageId); if (agrippant === undefined) { - error("Attribut " + attrName + " mal formé, on le supprime", attr.get('current')); + error("Attribut " + attrName + " mal form\xE9, on le supprime", attr.get('current')); attr.remove(); unlockToken(perso); return; @@ -39137,15 +39559,15 @@ var COFantasy = COFantasy || function() { estMauvais(agrippant)) { let bonusProtectionContreLeMal = getIntValeurOfEffet(perso, 'protectionContreLeMal', 2); bonus += bonusProtectionContreLeMal; - explications.push("Protection contre le mal => +" + bonusProtectionContreLeMal + " au jet pour se libérer"); + explications.push("Protection contre le mal => +" + bonusProtectionContreLeMal + " au jet pour se lib\xE9rer"); } if (predicateAsBool(perso, 'actionLibre')) { bonus += 5; - explications.push("Action libre => +5 pour résister aux entraves"); + explications.push("Action libre => +5 pour r\xE9sister aux entraves"); } let carac = meilleureCarac('FOR', 'DEX', perso, difficulte - bonus); if (bonus) options.bonus = bonus; - let titre = "Tentative de se libérer de " + nomPerso(agrippant); + let titre = "Tentative de se lib\xE9rer de " + nomPerso(agrippant); doLibererEcrase(perso, agrippant, titre, carac, difficulte, explications, options); } @@ -39184,7 +39606,7 @@ var COFantasy = COFantasy || function() { smsg += '">' + tr.texte + ''; } if (tr.reussite) { - smsg += " => réussi, " + nomPerso(perso) + " se libère."; + smsg += " => r\xE9ussi, " + nomPerso(perso) + " se lib\xE8re."; smsg += tr.modifiers; addLineToFramedDisplay(display, smsg); toFront(perso.token); @@ -39203,7 +39625,7 @@ var COFantasy = COFantasy || function() { } }); } else { - smsg += " => échec, " + nomPerso(perso) + " est toujours saisi dans les bras de " + nomPerso(agrippant); + smsg += " => \xE9chec, " + nomPerso(perso) + " est toujours saisi dans les bras de " + nomPerso(agrippant); smsg += tr.rerolls + tr.modifiers; addLineToFramedDisplay(display, smsg); } @@ -39228,7 +39650,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2], cmd[2], options.pageId); if (cible === undefined) { - error("Le deuxième argument de !cof-animer-cadavre n'est pas un token valide", msg.content); + error("Le deuxi\xE8me argument de !cof-animer-cadavre n'est pas un token valide", msg.content); return; } if (!getState(cible, 'mort')) { @@ -39236,13 +39658,13 @@ var COFantasy = COFantasy || function() { return; } if (attributeAsBool(cible, 'cadavreAnime')) { - sendPlayer(msg, nomPerso(cible) + " a déjà été animé" + eForFemale(cible) + "."); + sendPlayer(msg, nomPerso(cible) + " a d\xE9j\xE0 \xE9t\xE9 anim\xE9" + eForFemale(cible) + "."); return; } var niveauLanceur = ficheAttributeAsInt(lanceur, 'niveau', 1); var niveauCible = ficheAttributeAsInt(cible, 'niveau', 1); if (niveauCible > niveauLanceur) { - sendPlayer(msg, nomPerso(cible) + " est de NC " + niveauCible + ", supérieur à celui de " + nomPerso(lanceur) + " (" + niveauLanceur + ")"); + sendPlayer(msg, nomPerso(cible) + " est de NC " + niveauCible + ", sup\xE9rieur \xE0 celui de " + nomPerso(lanceur) + " (" + niveauLanceur + ")"); return; } var evt = { @@ -39250,27 +39672,27 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); if (limiteRessources(lanceur, options, 'animerUnCadavre', "animer un cadavre", evt)) return; - sendPerso(lanceur, 'réanime ' + nomPerso(cible)); + sendPerso(lanceur, 'r\xE9anime ' + nomPerso(cible)); setState(cible, 'mort', false, evt); var pvmax = parseInt(cible.token.get("bar1_max")); updateCurrentBar(cible, 1, pvmax, evt); setTokenAttr(cible, 'cadavreAnime', true, evt, { - msg: 'se relève' + msg: 'se rel\xE8ve' }); } var niveauxEbriete = [ "sobre", "pompette", - "bourré", + "bourr\xE9", "ivre-mort", - "en coma éthylique" + "en coma \xE9thylique" ]; function augmenteEbriete(personnage, evt, expliquer) { let n = attributeAsInt(personnage, 'niveauEbriete', 0) + 1; if (n >= niveauxEbriete.length) { - expliquer(nomPerso(personnage) + " est déjà en coma éthylique."); + expliquer(nomPerso(personnage) + " est d\xE9j\xE0 en coma \xE9thylique."); return; } expliquer(nomPerso(personnage) + " devient " + niveauxEbriete[n]); @@ -39292,7 +39714,7 @@ var COFantasy = COFantasy || function() { var cibles = []; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "pas de cible trouvée, action annulée", playerId); + sendPlayer(msg, "pas de cible trouv\xE9e, action annul\xE9e", playerId); return; } iterSelected(selected, function(perso) { @@ -39312,17 +39734,17 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - if (limiteRessources(options.lanceur, options, 'vapeursEthyliques', "lancer une fiole de vapeurs éthyliques", evt)) { + if (limiteRessources(options.lanceur, options, 'vapeursEthyliques', "lancer une fiole de vapeurs \xE9thyliques", evt)) { addEvent(evt); return; } - let display = startFramedDisplay(playerId, 'Vapeurs éthyliques'); + let display = startFramedDisplay(playerId, 'Vapeurs \xE9thyliques'); let expliquer = function(m) { addLineToFramedDisplay(display, m); }; const explications = []; if (options.save) { - explications.push(" Jet de " + options.save.carac + " " + options.save.seuil + " pour résister à l'alcool"); + explications.push(" Jet de " + options.save.carac + " " + options.save.seuil + " pour r\xE9sister \xE0 l'alcool"); } entrerEnCombat(options.lanceur, persos, explications, evt); explications.forEach(explication => expliquer(explications)); @@ -39361,11 +39783,11 @@ var COFantasy = COFantasy || function() { function desaouler(msg) { getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Aucune sélection pour !cof-desaouler", playerId); + sendPlayer(msg, "Aucune s\xE9lection pour !cof-desaouler", playerId); return; } var evt = { - type: 'desaoûler' + type: 'desao\xFBler' }; var expliquer = function(s) { sendChat('', s); @@ -39399,7 +39821,7 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - if (limiteRessources(options.lanceur, options, 'boireAlcool', "est affecté par l'alcool", evt)) { + if (limiteRessources(options.lanceur, options, 'boireAlcool', "est affect\xE9 par l'alcool", evt)) { return; } var display = startFramedDisplay(playerId, 'Alcool'); @@ -39407,7 +39829,7 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, m); }; if (options.save) { - expliquer("Jet de " + options.save.carac + " " + options.save.seuil + " pour résister à l'alcool"); + expliquer("Jet de " + options.save.carac + " " + options.save.seuil + " pour r\xE9sister \xE0 l'alcool"); } var count = persos.length; var finalize = function() { @@ -39443,7 +39865,7 @@ var COFantasy = COFantasy || function() { //On joue un son let son = msg.content.substring(sonIndex + 1); playSound(son); - } else { //On arrête tous les sons + } else { //On arr\xEAte tous les sons let AMdeclared; try { AMdeclared = Roll20AM; @@ -39480,7 +39902,7 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error('pas de token sélectionné pour !cof-bonus-couvert'); + error('pas de token s\xE9lectionn\xE9 pour !cof-bonus-couvert'); return; } var evt = { @@ -39491,12 +39913,12 @@ var COFantasy = COFantasy || function() { iterSelected(selected, function(perso) { if (nouveauBonus) { setTokenAttr(perso, 'bonusCouvert', nouveauBonus, evt, { - msg: "se met à couvert", + msg: "se met \xE0 couvert", secret: options.secret }); } else { removeTokenAttr(perso, 'bonusCouvert', evt, { - msg: "n'est plus à couvert", + msg: "n'est plus \xE0 couvert", secret: options.secret }); } @@ -39528,7 +39950,7 @@ var COFantasy = COFantasy || function() { return; }*/ if (selected.length === 0) { - error('pas de token sélectionné pour !cof-set-attribute'); + error('pas de token s\xE9lectionn\xE9 pour !cof-set-attribute'); return; } const evt = { @@ -39581,7 +40003,7 @@ var COFantasy = COFantasy || function() { let predicats = state.COFantasy.predicats; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error('pas de token sélectionné pour !cof-set-predicate'); + error('pas de token s\xE9lectionn\xE9 pour !cof-set-predicate'); return; } const evt = { @@ -39596,14 +40018,14 @@ var COFantasy = COFantasy || function() { case 'vrai': case 'oui': if (pred.includes(predicat)) { - sendPlayer(msg, 'Prédicat ' + predicat + ' déjà présent', playerId); + sendPlayer(msg, 'Pr\xE9dicat ' + predicat + ' d\xE9j\xE0 pr\xE9sent', playerId); return; } if (pred === '') pred = predicat; else pred = pred + ' ' + predicat; setFicheAttr(perso, 'predicats_script', pred, evt); if (predicats) predicats[perso.charId] = undefined; - sendPlayer(msg, 'Prédicat ' + predicat + ' ajouté', playerId); + sendPlayer(msg, 'Pr\xE9dicat ' + predicat + ' ajout\xE9', playerId); break; case 'false': case 'faux': @@ -39611,11 +40033,11 @@ var COFantasy = COFantasy || function() { let regPred = new RegExp('(^| |,|\n)' + predicat + '($| |,|\n)'); let newPred = pred.replace(regPred, ' '); if (newPred == pred) { - sendPlayer(msg, 'Prédicat ' + predicat + ' non trouvé', playerId); + sendPlayer(msg, 'Pr\xE9dicat ' + predicat + ' non trouv\xE9', playerId); } else { setFicheAttr(perso, 'predicats_script', newPred, evt); if (predicats) predicats[perso.charId] = undefined; - sendPlayer(msg, 'Prédicat ' + predicat + ' enlevé', playerId); + sendPlayer(msg, 'Pr\xE9dicat ' + predicat + ' enlev\xE9', playerId); } break; default: @@ -39643,11 +40065,11 @@ var COFantasy = COFantasy || function() { } var perso = persoOfId(cmd[1]); if (perso === undefined) { - error("Le token renseigné pour !cof-defense-armee-des-morts est inconnu", cmd); + error("Le token renseign\xE9 pour !cof-defense-armee-des-morts est inconnu", cmd); return; } if (!peutController(msg, perso)) { - sendPlayer(msg, "ne peut pas faire ça."); + sendPlayer(msg, "ne peut pas faire \xE7a."); return; } var evt = { @@ -39655,7 +40077,7 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); var opt = { - msg: "se défend contre les morts" + msg: "se d\xE9fend contre les morts" }; setTokenAttr(perso, "defenseArmeeDesMorts", true, evt, opt); } @@ -39675,8 +40097,8 @@ var COFantasy = COFantasy || function() { addLineToFramedDisplay(display, ligne); } - //!cof-options-d-attaque, affiche les options d'attaque du token sélectionné - // si on donne reset en argument, remet tout à zéro + //!cof-options-d-attaque, affiche les options d'attaque du token s\xE9lectionn\xE9 + // si on donne reset en argument, remet tout \xE0 z\xE9ro // si on donne en argument option valeur, change la valeur de l'option function optionsDAttaque(msg) { const options = parseOptions(msg); @@ -39806,7 +40228,7 @@ var COFantasy = COFantasy || function() { break; default: error("Argument de !cof-options-d-attaque non reconnu", cmd); - //Mais on peut quand même afficher les options + //Mais on peut quand m\xEAme afficher les options } turnAction(perso, playerId); return; @@ -39818,7 +40240,7 @@ var COFantasy = COFantasy || function() { }; if (aepc || arc || aac || adtc || (persoEstPNJ(perso) && adg > 1)) { action = "!cof-options-d-attaque reset --target " + perso.token.id; - opt_display.action_right = boutonSimple(action, 'réinit.'); + opt_display.action_right = boutonSimple(action, 'r\xE9init.'); } var display = startFramedDisplay(playerId, title, perso, opt_display); var ligne = ''; @@ -39827,7 +40249,7 @@ var COFantasy = COFantasy || function() { ligne = "Attaque de groupe : "; action = "!cof-options-d-attaque attaque_de_groupe ?{Combien d'adversaires par jet?}"; action += " --target " + perso.token.id; - overlay = 'title="+2 Att. par créature, si Att > DEF + 5, DM x2, si critique DM x3"'; + overlay = 'title="+2 Att. par cr\xE9ature, si Att > DEF + 5, DM x2, si critique DM x3"'; ligne += boutonSimple(action, adg, overlay); if (adg < 2) { ligne += "attaquant"; @@ -39847,7 +40269,7 @@ var COFantasy = COFantasy || function() { } action += " --target " + perso.token.id; ligne = boutonSimple(action, text) + "Attaque en puissance"; - action = "!cof-options-d-attaque attaque_en_puissance ?{nombre de dés de bonus (-5 att par dé)?}"; + action = "!cof-options-d-attaque attaque_en_puissance ?{nombre de d\xE9s de bonus (-5 att par d\xE9)?}"; action += " --target " + perso.token.id; ligne += "(+" + boutonSimple(action, aep) + "d"; if (predicateAsBool(perso, 'tropPetit') && !attributeAsBool(perso, 'grandeTaille')) { @@ -39856,8 +40278,8 @@ var COFantasy = COFantasy || function() { ligne += "6 DM)"; } addLineToFramedDisplay(display, ligne); - addLigneOptionAttaque(display, perso, arc, "Attaque risquée", 'attaque_risquee'); - addLigneOptionAttaque(display, perso, aac, "Attaque assurée", 'attaque_assuree'); + addLigneOptionAttaque(display, perso, arc, "Attaque risqu\xE9e", 'attaque_risquee'); + addLigneOptionAttaque(display, perso, aac, "Attaque assur\xE9e", 'attaque_assuree'); addLigneOptionAttaque(display, perso, adtc, "Attaque pour assommer", 'attaque_dm_temp'); sendFramedDisplay(display); }); @@ -39865,7 +40287,7 @@ var COFantasy = COFantasy || function() { if (evt.attributes) addEvent(evt); } - //si evt est défini, on ajoute les actions à evt + //si evt est d\xE9fini, on ajoute les actions \xE0 evt function nePlusSuivre(perso, pageId, evt, reutilise) { let attrSuit = tokenAttribute(perso, 'suit'); if (attrSuit.length > 0) { @@ -39938,7 +40360,7 @@ var COFantasy = COFantasy || function() { } let perso = persoOfId(cmd[1], cmd[1], options.pageId); if (perso === undefined) { - error("Token sélectionne incorrect pour !cof-suivre", cmd); + error("Token s\xE9lectionne incorrect pour !cof-suivre", cmd); return; } let pageId = perso.token.get('pageid'); @@ -39951,7 +40373,7 @@ var COFantasy = COFantasy || function() { type: 'Suivre', attributes: [] }; - //D'abord on arrête de suivre si on suivait quelqu'un + //D'abord on arr\xEAte de suivre si on suivait quelqu'un let attrSuit = nePlusSuivre(perso, pageId, evt, true); let cibleId = idName(cible); let attr = tokenAttribute(cible, 'estSuiviPar'); @@ -39974,7 +40396,7 @@ var COFantasy = COFantasy || function() { let yc = cible.token.get('top'); let distance = Math.floor(Math.sqrt((xc - xt) * (xc - xt) + (yc - yt) * (yc - yt))); if (attrSuit) { - //alors evt contient déjà attrSuit + //alors evt contient d\xE9j\xE0 attrSuit attrSuit.set('current', cibleId); attrSuit.set('max', distance); } else { @@ -39994,7 +40416,7 @@ var COFantasy = COFantasy || function() { return c !== ''; }); if (cmd.length < 2) { - error("Il faut préciser un token sur lequel se centrer", cmd); + error("Il faut pr\xE9ciser un token sur lequel se centrer", cmd); return; } let playerId = getPlayerIdFromMsg(msg); @@ -40002,7 +40424,7 @@ var COFantasy = COFantasy || function() { if (playerIsGM(playerId)) { let p = getObj('player', playerId); if (p === undefined) { - error("Impossible de trouver le joueur qui a lancé la commande", msg); + error("Impossible de trouver le joueur qui a lanc\xE9 la commande", msg); return; } pageId = p.get('_lastpage'); @@ -40049,7 +40471,7 @@ var COFantasy = COFantasy || function() { else possede = true; msg += pc + " PC"; } - if (possede) msg = 'possède ' + msg; + if (possede) msg = 'poss\xE8de ' + msg; else msg = "n'a pas d'argent"; if (dest) sendPlayer(dest, nomPerso(perso) + ' ' + msg); else whisperChar(perso.charId, msg); @@ -40071,19 +40493,19 @@ var COFantasy = COFantasy || function() { let val = ficheAttributeAsInt(perso, 'bourse_' + unite, 0); let line = '
    '; let action = - "!cof-bourse fixer ?{Nouveau montant de pièces " + piece + " ?} " + finAction; + "!cof-bourse fixer ?{Nouveau montant de pi\xE8ces " + piece + " ?} " + finAction; line += boutonSimple(action, val) + '' + nom + ''; line += ''; - action = "!cof-bourse depenser ?{Pièces " + piece + " à dépenser ?} " + finAction; - line += boutonSimple(action, 'Dépenser'); - action = "!cof-bourse gagner ?{Pièces " + piece + " ?} " + finAction; + action = "!cof-bourse depenser ?{Pi\xE8ces " + piece + " \xE0 d\xE9penser ?} " + finAction; + line += boutonSimple(action, 'D\xE9penser'); + action = "!cof-bourse gagner ?{Pi\xE8ces " + piece + " ?} " + finAction; line += boutonSimple(action, 'Gagner'); line += '
    '; addLineToFramedDisplay(display, line); } //!cof-bourse [action] - //Les actions peuvent être depenser val [unite], fixer val unite ou gagner val [unite] + //Les actions peuvent \xEAtre depenser val [unite], fixer val unite ou gagner val [unite] function gestionBourse(msg) { var cmd = msg.content.split(' ').filter(function(c) { return c.trim() !== ''; @@ -40100,11 +40522,11 @@ var COFantasy = COFantasy || function() { if (cmd.length > 1) { switch (cmd[1]) { case 'depenser': - case 'dépenser': + case 'd\xE9penser': case 'gagner': case 'fixer': if (cmd.length < 3) { - error("Il faut spécifier un montant à " + cmd[1], msg.content); + error("Il faut sp\xE9cifier un montant \xE0 " + cmd[1], msg.content); return; } montant = parseInt(cmd[2]); @@ -40117,7 +40539,7 @@ var COFantasy = COFantasy || function() { action = 'depenser'; } else if (cmd[1] == 'fixer') { if (montant < 0) { - error("On ne peut avoir qu'un nombre positif de pièces", cmd); + error("On ne peut avoir qu'un nombre positif de pi\xE8ces", cmd); return; } action = 'fixer'; @@ -40125,12 +40547,12 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3 && !cmd[3].startsWith('--')) { unite = cmd[3].toLowerCase().trim(); if (unite != 'pp' && unite != 'po' && unite != 'pa' && unite != 'pc') { - error("Pièces non reconnues : " + cmd[3], cmd); + error("Pi\xE8ces non reconnues : " + cmd[3], cmd); return; } depense[unite] = montant; } else if (action == 'fixer') { - error("Il faut préciser les unités pour !cof-bourse fixer", msg.content); + error("Il faut pr\xE9ciser les unit\xE9s pour !cof-bourse fixer", msg.content); return; } depense.total = depense.pc + 10 * (depense.pa + 10 * (depense.po + 10 * depense.pp)); @@ -40138,7 +40560,7 @@ var COFantasy = COFantasy || function() { } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de personnage sélectionné pour !cof-bourse", playerId); + sendPlayer(msg, "Pas de personnage s\xE9lectionn\xE9 pour !cof-bourse", playerId); return; } var evt = { @@ -40182,7 +40604,7 @@ var COFantasy = COFantasy || function() { } var montantPossede = pc + 10 * (pa + 10 * (po + 10 * pp)); if (montantPossede < depense.total) { - sendPerso(perso, "ne possède pas assez d'argent pour cette dépense"); + sendPerso(perso, "ne poss\xE8de pas assez d'argent pour cette d\xE9pense"); afficherRichesse(perso, msg); return; } @@ -40192,7 +40614,7 @@ var COFantasy = COFantasy || function() { po: po, pp: pp }; - // On privilégie les dépenses directes + // On privil\xE9gie les d\xE9penses directes var dpp = depense.pp; if (dpp <= bourse.pp) { bourse.pp -= dpp; @@ -40225,14 +40647,14 @@ var COFantasy = COFantasy || function() { dpc -= bourse.pc; bourse.pc = 0; } - // Puis on dépense d'abord la petite monnaie + // Puis on d\xE9pense d'abord la petite monnaie var v = dpc + 10 * (dpa + 10 * (dpo + 10 * dpp)); v = depenserSous(perso, 'pc', bourse, v); v = depenserSous(perso, 'pa', bourse, v); v = depenserSous(perso, 'po', bourse, v); v = depenserSous(perso, 'pp', bourse, v); if (v > 0) { - error("Erreur interne de calcul, il reste " + v + " PP à dépenser ??", bourse); + error("Erreur interne de calcul, il reste " + v + " PP \xE0 d\xE9penser ??", bourse); return; } if (bourse.pc != pc) @@ -40291,7 +40713,7 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); if (options.lanceur) { - sendPerso(options.lanceur, "prononce un mot avec la Voix d'une puissance supérieure. Tous ses ennemis sont immobilisés et ses alliés sont galvanisés."); + sendPerso(options.lanceur, "prononce un mot avec la Voix d'une puissance sup\xE9rieure. Tous ses ennemis sont immobilis\xE9s et ses alli\xE9s sont galvanis\xE9s."); let allies = alliesParPerso[options.lanceur.charId]; if (allies) { let tokens = findObjs({ @@ -40327,8 +40749,8 @@ var COFantasy = COFantasy || function() { }, options); } - // Ajoute evt à l'historique si présent - // msg n'est pas forcément présent + // Ajoute evt \xE0 l'historique si pr\xE9sent + // msg n'est pas forc\xE9ment pr\xE9sent function nextTurnChargeFantastique(msg, oldTurnOrder) { if (oldTurnOrder) Campaign().set('turnorder', oldTurnOrder); let cf = stateCOF.chargeFantastique; @@ -40367,7 +40789,7 @@ var COFantasy = COFantasy || function() { stateCOF.chargeFantastique.activeTokenId = perso.token.id; setTokenInitAura(perso); let display = startFramedDisplay(playerId, "Charge fantastique", perso, optionsDisplay); - addLineToFramedDisplay(display, "Phase de mouvement : déplacez votre token en ligne droite"); + addLineToFramedDisplay(display, "Phase de mouvement : d\xE9placez votre token en ligne droite"); addLineToFramedDisplay(display, "puis " + boutonSimple("!cof-next-charge-fantastique", "cliquez ici")); sendFramedDisplay(display); return; @@ -40401,12 +40823,12 @@ var COFantasy = COFantasy || function() { } const chevalier = persoOfId(cmd[1], cmd[1], options.pageId); if (chevalier === undefined) { - error("Le token sélectionné ne représente pas un personnage", cmd); + error("Le token s\xE9lectionn\xE9 ne repr\xE9sente pas un personnage", cmd); return; } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error('pas de token sélectionné pour !cof-charge-fantastique', msg.content); + error('pas de token s\xE9lectionn\xE9 pour !cof-charge-fantastique', msg.content); return; } const evt = { @@ -40414,7 +40836,7 @@ var COFantasy = COFantasy || function() { }; addEvent(evt); if (limiteRessources(chevalier, options, 'chargeFantastique', 'charge fantastique', evt)) return; - sendPerso(chevalier, "mène une charge fantastique !"); + sendPerso(chevalier, "m\xE8ne une charge fantastique !"); initiative(selected, evt); stateCOF.chargeFantastique = {}; let ordreActions = []; @@ -40432,14 +40854,14 @@ var COFantasy = COFantasy || function() { ordreActions.sort(function(p1, p2) { if (p1.init < p2.init) return 1; if (p1.init > p2.init) return -1; - // Priorité aux joueurs - // Premier critère : la barre de PV des joueurs est liée + // Priorit\xE9 aux joueurs + // Premier crit\xE8re : la barre de PV des joueurs est li\xE9e if (p1.perso.token.get('bar1_link') === '') { if (p2.perso.token.get('bar1_link') === '') return 0; return 1; } if (p2.perso.token.get('bar1_link') === '') return -1; - // Deuxième critère : les joueurs ont un DV + // Deuxi\xE8me crit\xE8re : les joueurs ont un DV let dvA = ficheAttributeAsInt(p1.perso, "DV", 0); let dvB = ficheAttributeAsInt(p2.perso, "DV", 0); if (dvA === 0) { @@ -40447,7 +40869,7 @@ var COFantasy = COFantasy || function() { return 1; } if (dvB === 0) return -1; - //Entre joueurs, priorité à la plus grosse sagesse + //Entre joueurs, priorit\xE9 \xE0 la plus grosse sagesse let sagA = ficheAttributeAsInt(p1.perso, 'sagesse', 10); let sagB = ficheAttributeAsInt(p2.perso, 'sagesse', 10); if (sagA < sagB) return 1; @@ -40501,9 +40923,9 @@ var COFantasy = COFantasy || function() { error("Impossible d'utiliser la prescience car l'historique est vide", cmd); return; } - //Au cas où, on vérifie que l'événement de début de tour est bien présent + //Au cas o\xF9, on v\xE9rifie que l'\xE9v\xE9nement de d\xE9but de tour est bien pr\xE9sent if (!findEvent(stateCOF.prescience.evt.id)) { - error("Impossible de trouver le début du tour dans l'historique.", stateCOF.prescience); + error("Impossible de trouver le d\xE9but du tour dans l'historique.", stateCOF.prescience); return; } while (evt && evt.id != stateCOF.prescience.evt.id) { @@ -40543,7 +40965,7 @@ var COFantasy = COFantasy || function() { updateNextInit(ensorceleur); } - //Synchronise les tokens de même nom entre les cartes + //Synchronise les tokens de m\xEAme nom entre les cartes function multiCartes(msg) { let options = parseOptions(msg); let enlever = options && options.cmd && options.cmd.length > 1 && @@ -40558,13 +40980,13 @@ var COFantasy = COFantasy || function() { addEvent(evt); return; } - sendPlayer(msg, "Aucun token selectionné pour !cof-multi-cartes", playerId); + sendPlayer(msg, "Aucun token selectionn\xE9 pour !cof-multi-cartes", playerId); return; } addEvent(evt); if (enlever) { iterSelected(selected, function(perso) { - sendPlayer(msg, nomPerso(perso) + " n'est plus synchronisé", playerId); + sendPlayer(msg, nomPerso(perso) + " n'est plus synchronis\xE9", playerId); removeTokenAttr(perso, 'tokensSynchronises', evt); }); return; @@ -40579,7 +41001,7 @@ var COFantasy = COFantasy || function() { let left = perso.token.get('left'); let top = perso.token.get('top'); let listTokens = [perso.token.id]; - //On cherche les tokens de même nom et on les met en même position + //On cherche les tokens de m\xEAme nom et on les met en m\xEAme position allTokens.forEach(function(tok) { if (tok.get('represents') != perso.charId) return; if (tok.get('name') != name) return; @@ -40602,7 +41024,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour !cof-ombre-mouvante", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof-ombre-mouvante", playerId); return; } iterSelected(selected, function(perso) { @@ -40621,16 +41043,16 @@ var COFantasy = COFantasy || function() { } }; addEvent(evt); - if (limiteRessources(voleur, options, 'ombreMouvante', 'disparaître dans les ombres', evt)) return; + if (limiteRessources(voleur, options, 'ombreMouvante', 'dispara\xEEtre dans les ombres', evt)) return; let optionsDisplay = { secret: options.secret }; let display = startFramedDisplay(playerId, 'Ombre mouvante', voleur, optionsDisplay); testCaracteristique(voleur, 'DEX', 10, 'ombreMouvante', options, evt, function(tr, explications) { - let msgRes = "Résultat : " + tr.texte; + let msgRes = "R\xE9sultat : " + tr.texte; if (tr.reussite) { - msgRes += ", " + nomPerso(voleur) + " disparaît dans les ombres"; + msgRes += ", " + nomPerso(voleur) + " dispara\xEEt dans les ombres"; addLineToFramedDisplay(display, msgRes + tr.modifiers); let ef = { effet: 'invisibleTemp', @@ -40641,7 +41063,7 @@ var COFantasy = COFantasy || function() { if (options.fx) spawnFx(voleur.token.get('left'), voleur.token.get('top'), options.fx, voleur.token.get('pageid')); } else { - msgRes += ", " + nomPerso(voleur) + " ne réussit pas à se fondre dans les ombres."; + msgRes += ", " + nomPerso(voleur) + " ne r\xE9ussit pas \xE0 se fondre dans les ombres."; addLineToFramedDisplay(display, msgRes + tr.rerolls + tr.modifiers); } explications.forEach(function(m) { @@ -40669,22 +41091,22 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné pour !cof-reveler-nom", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9 pour !cof-reveler-nom", playerId); return; } let nouveauNomToken; if (cmd.length > 1) nouveauNomToken = cmd.slice(1).join(' '); if (selected.length > 1 && nouveauNomToken) { - sendPlayer(msg, "Attention, on ne peut sélectionner qu'un seul token quand on précise le nouveau nom des tokens", playerId); + sendPlayer(msg, "Attention, on ne peut s\xE9lectionner qu'un seul token quand on pr\xE9cise le nouveau nom des tokens", playerId); return; } const evt = { - type: "Révélation de nom", + type: "R\xE9v\xE9lation de nom", characterNames: [], defaultTokens: [], attributes: [] @@ -40715,24 +41137,24 @@ var COFantasy = COFantasy || function() { }); ancienNom = ficheAttribute(perso, 'alias', ''); nouveauNom = character.get('name'); - sendChat('', ancienNom + " était en réalité " + nouveauNom + " !"); + sendChat('', ancienNom + " \xE9tait en r\xE9alit\xE9 " + nouveauNom + " !"); } else { nouveauNom = ficheAttribute(perso, 'alias', ''); ancienNom = character.get('name'); if (nouveauNom === '') { - sendPlayer(msg, ancienNom + " n'a pas d'alias, rien à révéler."); + sendPlayer(msg, ancienNom + " n'a pas d'alias, rien \xE0 r\xE9v\xE9ler."); return; } setFicheAttr(perso, 'alias', '', evt, { default: '' }); - sendChar(perso.charId, "était en réalité " + nouveauNom + " !"); + sendChar(perso.charId, "\xE9tait en r\xE9alit\xE9 " + nouveauNom + " !"); evt.characterNames.push({ character: character, name: ancienNom }); character.set('name', nouveauNom); - //On change aussi les prédicats qui stoquent le nom du personnage + //On change aussi les pr\xE9dicats qui stoquent le nom du personnage if (attrsWithCharNames === undefined) { attrsWithCharNames = allAttrs.filter(function(attr) { return attr.get('name') == 'predicats_script'; @@ -40825,7 +41247,7 @@ var COFantasy = COFantasy || function() { sendPlayer(msg, "Pas de renommage de " + tokName, playerId); } } else { - sendPlayer(msg, "Pas de token par défaut pour " + tokName + ", ce n'est pas encore géré dans !cof-reveler-nom", playerId); + sendPlayer(msg, "Pas de token par d\xE9faut pour " + tokName + ", ce n'est pas encore g\xE9r\xE9 dans !cof-reveler-nom", playerId); } } else { if (defaultTokenName && tokName == defaultTokenName) { @@ -40880,14 +41302,14 @@ var COFantasy = COFantasy || function() { } if (b) { if (stateCOF.tenebresMagiques) { - sendPlayer('GM', "Les personnages sont déjà dans des ténèbres magiques"); + sendPlayer('GM', "Les personnages sont d\xE9j\xE0 dans des t\xE9n\xE8bres magiques"); return; } - sendPlayer('GM', "Les personnages entrent dans des ténèbres magiques"); + sendPlayer('GM', "Les personnages entrent dans des t\xE9n\xE8bres magiques"); stateCOF.tenebresMagiques = {}; } else { stateCOF.tenebresMagiques = undefined; - sendPlayer('GM', "Les personnages sortent des ténèbres magiques"); + sendPlayer('GM', "Les personnages sortent des t\xE9n\xE8bres magiques"); } } @@ -40895,24 +41317,24 @@ var COFantasy = COFantasy || function() { let cmd = msg.content.split(' '); let tm = stateCOF.tenebresMagiques; if (tm === undefined) { - sendPlayer(msg, "Pas de ténèbres magiques, pas d'effet de fiole"); + sendPlayer(msg, "Pas de t\xE9n\xE8bres magiques, pas d'effet de fiole"); return; } cmd = cmd.filter(function(c) { return c.trim() !== ''; }); if (cmd.length < 2) { - error("Il faut un argument à !cof-fiole-de-lumiere", cmd); + error("Il faut un argument \xE0 !cof-fiole-de-lumiere", cmd); return; } var distance = parseInt(cmd[1]); getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - error("Aucun personnage sélectionné", cmd); + error("Aucun personnage s\xE9lectionn\xE9", cmd); return; } if (selected.length > 1) { - error("Il n'y a qu'une seule fiole de lumière", cmd); + error("Il n'y a qu'une seule fiole de lumi\xE8re", cmd); return; } var evt = { @@ -40933,7 +41355,7 @@ var COFantasy = COFantasy || function() { if (cmd.length > 3) { dimRadius = parseInt(cmd[3]); if (isNaN(dimRadius)) { - error("La distance de vue de la lumière assombrie doit être un nombre", cmd[3]); + error("La distance de vue de la lumi\xE8re assombrie doit \xEAtre un nombre", cmd[3]); dimRadius = ''; } } @@ -40950,25 +41372,25 @@ var COFantasy = COFantasy || function() { return c !== ''; }); if (cmd.length < 3) { - error("Il faut spécifier un attaquant et un défenseur pour !cof-agripper-de-demon", cmd); + error("Il faut sp\xE9cifier un attaquant et un d\xE9fenseur pour !cof-agripper-de-demon", cmd); return; } let attaquant = persoOfId(cmd[1], cmd[1]); let defenseur = persoOfId(cmd[2], cmd[2]); if (attaquant === undefined) { - error("Le premier argument de !cof-agripper-de-demon doit être un token valide", cmd[1]); + error("Le premier argument de !cof-agripper-de-demon doit \xEAtre un token valide", cmd[1]); return; } if (defenseur === undefined) { - error("Le deuxième argument de !cof-agripper-de-demon doit être un token valide", cmd[2]); + error("Le deuxi\xE8me argument de !cof-agripper-de-demon doit \xEAtre un token valide", cmd[2]); return; } if (attributeAsBool(defenseur, 'armureDEau')) { - sendChat("L'armure d'eau empêche " + nomPerso(defenseur) + " d'être aggripé"); + sendChat("L'armure d'eau emp\xEAche " + nomPerso(defenseur) + " d'\xEAtre aggrip\xE9"); return; } const evt = { - type: "Agripper (démon)" + type: "Agripper (d\xE9mon)" }; let options = { pasDeDmg: true @@ -40983,7 +41405,7 @@ var COFantasy = COFantasy || function() { setTokenAttr(defenseur, 'estAgrippePar', idName(attaquant), evt); setTokenAttr(defenseur, 'agrippeParUnDemon', true, evt); } else { - addLineToFramedDisplay(display, nomPerso(defenseur) + " échappe à la tentative de saisie."); + addLineToFramedDisplay(display, nomPerso(defenseur) + " \xE9chappe \xE0 la tentative de saisie."); } explications.forEach(function(expl) { addLineToFramedDisplay(display, expl, 80); @@ -41034,7 +41456,7 @@ var COFantasy = COFantasy || function() { evt.attributes.push({ attribute: attr }); - if ((carac == 'DEX' && comp != 'crochetage' && comp != 'désamorçage') || + if ((carac == 'DEX' && comp != 'crochetage' && comp != 'd\xE9samor\xE7age') || (carac == 'CON' && comp == 'survie') || comp == 'natation' || comp == 'escalade') { attrSpec.name = prefix + 'malus'; @@ -41080,7 +41502,7 @@ var COFantasy = COFantasy || function() { if (treatedChars.has(perso.charId)) return; treatedChars.add(perso.charId); if (!charAttributeAsBool(perso, 'ac')) { - sendPlayer(msg, nomPerso(perso) + " déjà converti (pas d'attribut ac)"); + sendPlayer(msg, nomPerso(perso) + " d\xE9j\xE0 converti (pas d'attribut ac)"); return; } let attributes = findObjs({ @@ -41165,7 +41587,7 @@ var COFantasy = COFantasy || function() { if (d.startsWith('channel resistance ')) { let resChannel = parseInt(d.substring(19)); if (isNaN(resChannel)) { - log("Capacité défensive " + d + " non connue"); + log("Capacit\xE9 d\xE9fensive " + d + " non connue"); } else { predicats += 'bonusSaveContre_positif:' + resChannel + ' '; return; @@ -41173,16 +41595,16 @@ var COFantasy = COFantasy || function() { } else if (d.startsWith('bravery ')) { let courage = parseInt(d.substring(8)); if (isNaN(courage)) { - log("Capacité défensive " + d + " non connue"); + log("Capacit\xE9 d\xE9fensive " + d + " non connue"); } else { predicats += 'courage:' + courage + ' '; return; } } else { - log("Capacité défensive " + d + " non connue"); + log("Capacit\xE9 d\xE9fensive " + d + " non connue"); } if (nonPrisEnCompte === '') - nonPrisEnCompte = 'Capacités défensives : ' + d; + nonPrisEnCompte = 'Capacit\xE9s d\xE9fensives : ' + d; else nonPrisEnCompte += ', ' + d; } }); @@ -41198,7 +41620,7 @@ var COFantasy = COFantasy || function() { if (w === '') return; switch (w) { case 'resurrection vulnerability': - notes += "Détruit par un sort de résurection \n"; + notes += "D\xE9truit par un sort de r\xE9surection \n"; return; case 'vulnerable to acid': case 'vulnerability to acid': @@ -41307,12 +41729,12 @@ var COFantasy = COFantasy || function() { case 'and': return; default: - log("Immunité à " + i + " non traitée"); + log("Immunit\xE9 \xE0 " + i + " non trait\xE9e"); immunitesNonTraitees += i + ' '; } }); if (immunitesNonTraitees !== '') { - log("Immunités non traitées : " + immunitesNonTraitees); + log("Immunit\xE9s non trait\xE9es : " + immunitesNonTraitees); attributsIgnores += 'immune : ' + immunitesNonTraitees + '.\n'; } deleteAttribute(attr, evt); @@ -41363,12 +41785,12 @@ var COFantasy = COFantasy || function() { else rd += ', sonique:' + resVal; return; default: - log("Résistance à " + res[0] + " non traitée"); + log("R\xE9sistance \xE0 " + res[0] + " non trait\xE9e"); resistancesNonTraitees += r + ', '; } }); if (resistancesNonTraitees !== '') { - log("Resistances non traitées : " + resistancesNonTraitees); + log("Resistances non trait\xE9es : " + resistancesNonTraitees); attributsIgnores += 'resist : ' + resistancesNonTraitees + '.\n'; } deleteAttribute(attr, evt); @@ -41418,10 +41840,10 @@ var COFantasy = COFantasy || function() { predicats += 'dragon '; break; case 'fey': - predicats += 'fée '; + predicats += 'f\xE9e '; break; case 'outsider': - predicats += 'extérieur '; + predicats += 'ext\xE9rieur '; break; case 'undead': predicats += 'nonVivant mortVivant '; @@ -41451,7 +41873,7 @@ var COFantasy = COFantasy || function() { taille = 'minuscule'; break; case 'tiny': - taille = 'très petit'; + taille = 'tr\xE8s petit'; break; case 'small': taille = 'petite'; @@ -41462,7 +41884,7 @@ var COFantasy = COFantasy || function() { taille = 'grand'; break; case 'huge': - taille = 'énorme'; + taille = '\xE9norme'; break; case 'gargantuan': case 'colossal': @@ -41551,15 +41973,15 @@ var COFantasy = COFantasy || function() { deleteAttribute(attr, evt); return; case 'disable_device': - ajouteCompetence(perso, 'désamorçage', 'DEX', attr.get('current'), evt); + ajouteCompetence(perso, 'd\xE9samor\xE7age', 'DEX', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'disguise': - ajouteCompetence(perso, 'déguisement', 'CHA', attr.get('current'), evt); + ajouteCompetence(perso, 'd\xE9guisement', 'CHA', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'escape_artist': - ajouteCompetence(perso, 'évasion', 'DEX', attr.get('current'), evt); + ajouteCompetence(perso, '\xE9vasion', 'DEX', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'fly': @@ -41587,11 +42009,11 @@ var COFantasy = COFantasy || function() { deleteAttribute(attr, evt); return; case 'knowledge_engineering': - ajouteCompetence(perso, 'connaissance (ingéniérie)', 'INT', attr.get('current'), evt); + ajouteCompetence(perso, 'connaissance (ing\xE9ni\xE9rie)', 'INT', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'knowledge_geography': - ajouteCompetence(perso, 'connaissance (géographie)', 'INT', attr.get('current'), evt); + ajouteCompetence(perso, 'connaissance (g\xE9ographie)', 'INT', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'knowledge_history': @@ -41635,7 +42057,7 @@ var COFantasy = COFantasy || function() { deleteAttribute(attr, evt); return; case 'ride': - ajouteCompetence(perso, 'Équitation', 'DEX', attr.get('current'), evt); + ajouteCompetence(perso, '\xC9quitation', 'DEX', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'sense_motive': @@ -41647,11 +42069,11 @@ var COFantasy = COFantasy || function() { deleteAttribute(attr, evt); return; case 'spellcraft': - ajouteCompetence(perso, 'sortilèges', 'INT', attr.get('current'), evt); + ajouteCompetence(perso, 'sortil\xE8ges', 'INT', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'stealth': - ajouteCompetence(perso, 'discrétion', 'DEX', attr.get('current'), evt); + ajouteCompetence(perso, 'discr\xE9tion', 'DEX', attr.get('current'), evt); deleteAttribute(attr, evt); return; case 'survival': @@ -41662,7 +42084,7 @@ var COFantasy = COFantasy || function() { ajouteCompetence(perso, 'natation', 'FOR', attr.get('current'), evt); deleteAttribute(attr, evt); return; - //Attributs de toutes facons modifiés: + //Attributs de toutes facons modifi\xE9s: case 'tab': case 'type_personnage': return; @@ -41690,7 +42112,7 @@ var COFantasy = COFantasy || function() { case 'skills_racial_modifiers': case 'fortitude': case 'reflex': - case 'will': //On n'y touche pas pour l'instant. À voir plus tard + case 'will': //On n'y touche pas pour l'instant. \xC0 voir plus tard let x = attr.get('current'); if (x === undefined || x === '') deleteAttribute(attr, evt); return; @@ -41749,7 +42171,7 @@ var COFantasy = COFantasy || function() { case 'spellabilities_flag': case 'sq': case 'xp': - case 'l1mancer_status': //Attributs ignorés + case 'l1mancer_status': //Attributs ignor\xE9s deleteAttribute(attr, evt); return; default: @@ -41887,7 +42309,7 @@ var COFantasy = COFantasy || function() { break; default: if (!e.startsWith('+')) { - log("Ennemi juré non reconnu : " + e); + log("Ennemi jur\xE9 non reconnu : " + e); } } } @@ -41925,7 +42347,7 @@ var COFantasy = COFantasy || function() { }); break; case 'dmgbase': - let dm = parseDice(attaque.dmgbase, 'dégâts'); + let dm = parseDice(attaque.dmgbase, 'd\xE9g\xE2ts'); if (dm) { if (dm.nbDe) createObj('attribute', { @@ -41996,7 +42418,7 @@ var COFantasy = COFantasy || function() { options += '--incrCritCoef ' + (cm - 2) + ' '; } break; - case 'atkname': //déjà traité plus haut + case 'atkname': //d\xE9j\xE0 trait\xE9 plus haut case 'options-flag': case 'dmgflag': case 'dmg2type': @@ -42039,7 +42461,7 @@ var COFantasy = COFantasy || function() { if (ab.description) notes += ab.description + '\n'; } if (maxAttackLabel > 0) setAttr('max_attack_label', maxAttackLabel); - //Puis on met les attributs nécessaires + //Puis on met les attributs n\xE9cessaires if (attributsIgnores !== '') setAttr('Attributs Pathfinder', attributsIgnores); if (predicats !== '') setAttr('predicats_script', predicats); @@ -42055,10 +42477,10 @@ var COFantasy = COFantasy || function() { let initiative = dexterite + init - mod_dex; if (isNaN(initiative)) initiative = 10 + 2 * init; setAttr('pnj_init', initiative); - // Nécessaire pour éviter que les sheetworkers re-calculent init et def + // N\xE9cessaire pour \xE9viter que les sheetworkers re-calculent init et def if (initiative != dexterite) setAttr('INIT_DIV', initiative - dexterite); if (def != 10 + mod_dex) setAttr('DEFDIV', def - 10 - mod_dex); - //Finalement, on change le token par défaut + //Finalement, on change le token par d\xE9faut let acAttr = perso.token.get('bar2_link'); affectToken(perso.token, 'bar2_link', acAttr, evt); perso.token.set('bar2_link', ''); @@ -42125,7 +42547,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { @@ -42133,15 +42555,15 @@ var COFantasy = COFantasy || function() { return; } let positif = true; - if (cmd[1] === 'false' || cmd[1] === 'negatif' || cmd[1] === 'négatif') + if (cmd[1] === 'false' || cmd[1] === 'negatif' || cmd[1] === 'n\xE9gatif') positif = false; if (options.soin === undefined && options.dm === undefined) { - sendPlayer(msg, "Rien à canaliser. Il faut préciser un montant de soins ou de dégâts"); + sendPlayer(msg, "Rien \xE0 canaliser. Il faut pr\xE9ciser un montant de soins ou de d\xE9g\xE2ts"); return; } getSelected(msg, function(selected, playerId) { if (selected.length != 1) { - sendPlayer(msg, "Il faut sélectionner un personnage", playerId); + sendPlayer(msg, "Il faut s\xE9lectionner un personnage", playerId); return; } let token = getObj('graphic', selected[0]._id); @@ -42151,7 +42573,7 @@ var COFantasy = COFantasy || function() { } let charId = token.get('represents'); if (charId === undefined || charId === '') { - error("Le token ne représente pas un personnage", token); + error("Le token ne repr\xE9sente pas un personnage", token); return; } let pretre = { @@ -42246,11 +42668,11 @@ var COFantasy = COFantasy || function() { let soins = res[0].inlinerolls[0].results.total; let soinTxt = buildinline(res[0].inlinerolls[0], 'normal', true); if (soins <= 0) { - sendPerso(pretre, "ne réussit pas à soigner (total de soins " + soinTxt + ")", true); + sendPerso(pretre, "ne r\xE9ussit pas \xE0 soigner (total de soins " + soinTxt + ")", true); sync(); return; } - //TODO: tenir compte des PV partagés + //TODO: tenir compte des PV partag\xE9s soigneToken(target, soins, evt, function(soinsEffectifs) { let line = "" + nomPerso(target) + " : + "; @@ -42268,7 +42690,7 @@ var COFantasy = COFantasy || function() { }, options); }); } catch (rollError) { - error("Jet " + options.soin + " mal formé", options); + error("Jet " + options.soin + " mal form\xE9", options); } }); } @@ -42302,7 +42724,7 @@ var COFantasy = COFantasy || function() { copyDmgOptionsToTarget(target, options); dealDamage(target, dmg, [], evt, false, options, explications, function(dmgDisplay, dmgFinal) { addLineToFramedDisplay(display, - nomPerso(target) + " reçoit " + dmgDisplay + " DM"); + nomPerso(target) + " re\xE7oit " + dmgDisplay + " DM"); explications.forEach(function(e) { addLineToFramedDisplay(display, e, 80, false); }); @@ -42310,7 +42732,7 @@ var COFantasy = COFantasy || function() { }); }); } catch (rollError) { - error("Jet " + options.dm + " mal formé", dm); + error("Jet " + options.dm + " mal form\xE9", dm); } }); } @@ -42321,7 +42743,7 @@ var COFantasy = COFantasy || function() { 1: { token: "https://s3.amazonaws.com/files.d20.io/images/250177368/mJsYWMFqDeEmJDJy8tJKWA/thumb.png?1634130296", avatar: "https://s3.amazonaws.com/files.d20.io/images/250177753/IMzDqEpNpuznVnAMYRil8A/max.jpg?1634130507", - taille: 'très petite', + taille: 'tr\xE8s petite', force: 4, pnj_for: -3, constitution: 4, @@ -42391,13 +42813,13 @@ var COFantasy = COFantasy || function() { }; //!cof-animation-des-objets lid niveau [tid] - // la cible optionelle correspond à un token existant non associé à un personnage + // la cible optionelle correspond \xE0 un token existant non associ\xE9 \xE0 un personnage function animationDesObjets(msg) { let options = parseOptions(msg); if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -42411,7 +42833,7 @@ var COFantasy = COFantasy || function() { } let niveauObjet = parseInt(cmd[2]); if (isNaN(niveauObjet) || niveauObjet < 1) { - error("Le niveau de l'objet animé doit être un nombre positif", cmd); + error("Le niveau de l'objet anim\xE9 doit \xEAtre un nombre positif", cmd); return; } if (niveauObjet > 10) niveauObjet = 10; @@ -42424,7 +42846,7 @@ var COFantasy = COFantasy || function() { let dejaAnime = attributeAsInt(lanceur, 'niveauDesObjetsAnimes', 0); let playerId = getPlayerIdFromMsg(msg); if (dejaAnime + niveauObjet > niveau) { - sendPlayer(msg, "Impossible d'animer plus d'objets pour le moment : somme des niveau animés = " + dejaAnime, playerId); + sendPlayer(msg, "Impossible d'animer plus d'objets pour le moment : somme des niveau anim\xE9s = " + dejaAnime, playerId); return; } let evt = { @@ -42434,7 +42856,7 @@ var COFantasy = COFantasy || function() { if (limiteRessources(lanceur, options, 'animationObjet', "animation d'un objet", evt)) return; let tokenSize = 70; switch (stats.taille) { - case 'très petite': + case 'tr\xE8s petite': tokenSize = 35; break; case 'petite': @@ -42453,7 +42875,7 @@ var COFantasy = COFantasy || function() { let pageId = lanceur.token.get('pageid'); tokenObjet = tokenObjet || createObj('graphic', { - name: 'Objet animé', + name: 'Objet anim\xE9', subtype: 'token', pageid: pageId, imgsrc: stats.token, @@ -42471,12 +42893,12 @@ var COFantasy = COFantasy || function() { limit_field_of_vision_total: 0, }); if (tokenObjet === undefined) { - error("Impossible de créer le token", stats); + error("Impossible de cr\xE9er le token", stats); return; } toFront(tokenObjet); let persoObjet = { - nom: 'Objet animé par ' + nomPerso(lanceur), + nom: 'Objet anim\xE9 par ' + nomPerso(lanceur), attributesFiche: { type_personnage: 'PNJ', niveau: niveauObjet, @@ -42543,7 +42965,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -42558,9 +42980,9 @@ var COFantasy = COFantasy || function() { break; case 'DEX': case 'dexterite': - case 'dexterité': - case 'dextérité': - case 'dextérite': + case 'dexterit\xE9': + case 'dext\xE9rit\xE9': + case 'dext\xE9rite': carac = 'dexterite'; break; case 'CON': @@ -42580,18 +43002,18 @@ var COFantasy = COFantasy || function() { carac = 'charisme'; break; default: - error("Caractéristique " + carac + " non reconnue", cmd); + error("Caract\xE9ristique " + carac + " non reconnue", cmd); return; } let valeur = parseInt(cmd[2]); if (isNaN(valeur) || valeur < 1) { - error("La valeur de soin d'affaiblissement doit être un nombre positif", cmd); + error("La valeur de soin d'affaiblissement doit \xEAtre un nombre positif", cmd); return; } let lanceur = options.lanceur; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour le soin d'affaiblissement", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour le soin d'affaiblissement", playerId); return; } if (lanceur === undefined) { @@ -42636,7 +43058,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -42651,9 +43073,9 @@ var COFantasy = COFantasy || function() { break; case 'DEX': case 'dexterite': - case 'dexterité': - case 'dextérité': - case 'dextérite': + case 'dexterit\xE9': + case 'dext\xE9rit\xE9': + case 'dext\xE9rite': carac = 'dexterite'; break; case 'CON': @@ -42678,18 +43100,18 @@ var COFantasy = COFantasy || function() { carac = 'random'; break; default: - error("Caractéristique " + carac + " non reconnue", cmd); + error("Caract\xE9ristique " + carac + " non reconnue", cmd); return; } let valeur = parseDice(cmd[2]); if (!valeur || !dePositif(valeur)) { - error("La valeur d'affaiblissement doit être un nombre positif", cmd); + error("La valeur d'affaiblissement doit \xEAtre un nombre positif", cmd); return; } let lanceur = options.lanceur; getSelected(msg, function(selected, playerId) { if (selected === undefined || selected.length === 0) { - sendPlayer(msg, "Pas de cible sélectionée pour l'affaiblissement", playerId); + sendPlayer(msg, "Pas de cible s\xE9lection\xE9e pour l'affaiblissement", playerId); return; } if (lanceur === undefined) { @@ -42714,8 +43136,8 @@ var COFantasy = COFantasy || function() { return; } } - if (options.type && immuniseAuType(perso, options.type, lanceur)) { - sendPerso(perso, "ne semble pas affecté par " + stringOfType(options.type)); + if (options.type && immuniseAuType(perso, options.type, lanceur, options)) { + sendPerso(perso, "ne semble pas affect\xE9 par " + stringOfType(options.type)); return; } cibles.push(perso); @@ -42756,15 +43178,15 @@ var COFantasy = COFantasy || function() { return carac; } - //carac est une caractéristique entière - //valeur est soit un nombre, soit le résultat de parseDice + //carac est une caract\xE9ristique enti\xE8re + //valeur est soit un nombre, soit le r\xE9sultat de parseDice function affaiblirCaracPerso(perso, carac, valeur, expliquer, evt) { let nomAttr = 'affaiblissementde' + carac; let valeurText = valeur; if (isNaN(valeur)) { let rid = valeur.id; if (rid === undefined) { - error("Résultat de parseDice sans id", valeur); + error("R\xE9sultat de parseDice sans id", valeur); return; } if (perso.affaiblirCaracRoll && perso.affaiblirCaracRoll[rid]) { @@ -42820,7 +43242,7 @@ var COFantasy = COFantasy || function() { updateCurrentBar(perso, 1, bar1, evt, pvmax); if (bar1 === 0) mort(perso, expliquer, evt); } - } else { //autre caractéristiques + } else { //autre caract\xE9ristiques if (malus >= cn) { setState(perso, 'renverse', true, evt); setState(perso, 'assomme', true, evt); @@ -42828,7 +43250,7 @@ var COFantasy = COFantasy || function() { } } - // valeur peut être un nombre ou le résultat de parseDice + // valeur peut \xEAtre un nombre ou le r\xE9sultat de parseDice function affaiblirCarac(playerId, cibles, carac, valeur, options) { const evt = { type: 'affaiblissement', @@ -42864,8 +43286,8 @@ var COFantasy = COFantasy || function() { }; if (options.save) { let saveOpts = { - msgPour: " pour résister à un affaiblissement de " + car, - msgRate: ", raté.", + msgPour: " pour r\xE9sister \xE0 un affaiblissement de " + car, + msgRate: ", rat\xE9.", attaquant: lanceur, rolls: options.rolls, chanceRollId: options.chanceRollId, @@ -42890,7 +43312,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { @@ -42905,19 +43327,19 @@ var COFantasy = COFantasy || function() { let playerId = getPlayerIdFromMsg(msg); let attr = tokenAttribute(perso, 'reactionViolente'); if (attr.length === 0) { - sendPlayer(msg, "Action inutile, " + perso.token.ge('name') + " n'est pas sous l'effet d'une réaction violente", playerId); + sendPlayer(msg, "Action inutile, " + perso.token.ge('name') + " n'est pas sous l'effet d'une r\xE9action violente", playerId); return; } attr = attr[0]; let duree = parseInt(attr.get('current')); if (isNaN(duree) || duree < 1) duree = 1; let evt = { - type: "Fin de réaction violente", + type: "Fin de r\xE9action violente", deletedAttributes: [attr] }; addEvent(evt); attr.remove(); - sendPerso(perso, "prend sur " + onGenre(perso, 'lui', 'elle') + " pour contenir sa réaction violente"); + sendPerso(perso, "prend sur " + onGenre(perso, 'lui', 'elle') + " pour contenir sa r\xE9action violente"); options.ignoreRD = true; let de = 6; if (predicateAsBool(perso, 'sangFroid')) de = 4; @@ -42935,16 +43357,16 @@ var COFantasy = COFantasy || function() { }); } - //!cof-explosion correspond à !cof-attack token token --explosion pour chaque token sélectionné + //!cof-explosion correspond \xE0 !cof-attack token token --explosion pour chaque token s\xE9lectionn\xE9 function attaqueExplosion(msg) { if (!msg.content) return; let index = msg.content.indexOf(' '); if (index < 1) { - error("Il manque le label de l'attaque à utiliser pour !cof-explosion", msg.content); + error("Il manque le label de l'attaque \xE0 utiliser pour !cof-explosion", msg.content); return; } let args_msg = msg.content.substring(index); - //On va ensuite enlever tout ce qui vient après --target + //On va ensuite enlever tout ce qui vient apr\xE8s --target index = args_msg.indexOf(' --target '); if (index > 0) args_msg = args_msg.substring(0, index); args_msg += ' --explosion'; @@ -42959,7 +43381,7 @@ var COFantasy = COFantasy || function() { }, { ignoreAllies: true, ignoreDisque: true - }); //On ignore les options d'alliés dans le getSelected + }); //On ignore les options d'alli\xE9s dans le getSelected } const listeEffetsAuD20 = { @@ -42985,7 +43407,7 @@ var COFantasy = COFantasy || function() { function setEffetChaqueD20(msg) { let playerId = getPlayerIdFromMsg(msg); if (!playerIsGM(playerId)) { - sendPlayer(msg, "Commande réservée au MJ", playerId); + sendPlayer(msg, "Commande r\xE9serv\xE9e au MJ", playerId); return; } let cmd = msg.content.split(' '); @@ -43079,7 +43501,7 @@ var COFantasy = COFantasy || function() { } let playerId = getPlayerIdFromMsg(msg); if (!playerIsGM(playerId)) { - sendPlayer(msg, "Commande réservée aux MJs", playerId); + sendPlayer(msg, "Commande r\xE9serv\xE9e aux MJs", playerId); return; } let pageId = getPageId(playerId); @@ -43089,7 +43511,7 @@ var COFantasy = COFantasy || function() { } let page = getObj('page', pageId); if (page === undefined) { - error("Impossible de trouver la page correspondant à l'id", pageId); + error("Impossible de trouver la page correspondant \xE0 l'id", pageId); return; } let agrandir = function(o, field) { @@ -43128,31 +43550,31 @@ var COFantasy = COFantasy || function() { texts.forEach(function(t) { move(t); }); - sendPlayer('GM', "Agrandissement terminé"); + sendPlayer('GM', "Agrandissement termin\xE9"); } function decoincer(msg) { getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Pas de token sélectionné", playerId); + sendPlayer(msg, "Pas de token s\xE9lectionn\xE9", playerId); return; } if (!playerIsGM(playerId)) { - sendPlayer(msg, "Action réservée au MJ", playerId); + sendPlayer(msg, "Action r\xE9serv\xE9e au MJ", playerId); return; } const evt = { - type: "Décoincer", + type: "D\xE9coincer", tokens: [] }; let pageId; iterSelected(selected, function(perso) { if (attributeAsBool(perso, 'decoince')) { - sendPlayer(msg, nomPerso(perso) + " peut déjà être déplacé", playerId); + sendPlayer(msg, nomPerso(perso) + " peut d\xE9j\xE0 \xEAtre d\xE9plac\xE9", playerId); return; } if (!perso.token.get('lockMovement')) { - sendPlayer(msg, nomPerso(perso) + "n'est pas bloqué", playerId); + sendPlayer(msg, nomPerso(perso) + "n'est pas bloqu\xE9", playerId); return; } let nom = 'decoince ' + perso.token.get('name'); @@ -43206,14 +43628,14 @@ var COFantasy = COFantasy || function() { }; let tokenBouge = createObj('graphic', tokenFields); if (!tokenBouge) { - error("Impossible de créer de token pour décoincer " + nomPerso(perso), tokenFields); + error("Impossible de cr\xE9er de token pour d\xE9coincer " + nomPerso(perso), tokenFields); return; } evt.tokens.push(tokenBouge); toFront(tokenBouge); setTokenAttr(perso, 'bougeGraceA', tokenBouge.id, evt); }); - if (pageId) sendPlayer(msg, "Penser à supprimer le token invisible quand vous aurez terminé le déplacement", playerId); + if (pageId) sendPlayer(msg, "Penser \xE0 supprimer le token invisible quand vous aurez termin\xE9 le d\xE9placement", playerId); }); } @@ -43282,7 +43704,7 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { @@ -43296,7 +43718,7 @@ var COFantasy = COFantasy || function() { } let cible = persoOfId(cmd[2]); if (cible === undefined) { - error("Le deuxième argument de !cof-sentir-la-corruption n'est pas un token valide", msg.content); + error("Le deuxi\xE8me argument de !cof-sentir-la-corruption n'est pas un token valide", msg.content); return; } let portee = 30; @@ -43350,7 +43772,7 @@ var COFantasy = COFantasy || function() { testCaracteristique(cible, 'INT', 15, 'sentirLaCorruptionCible', options, evt, function(tr, explications) { let msgRes = "Jet d'INT de " + nomPerso(cible) + " : " + tr.texte; - //On n'affiche pas les possibilités de rerolls, sinon il faudrait un bouton pour "continuer" afin de ne pas afficher le résultat. + //On n'affiche pas les possibilit\xE9s de rerolls, sinon il faudrait un bouton pour "continuer" afin de ne pas afficher le r\xE9sultat. addLineToFramedDisplay(display, msgRes + tr.modifiers); explications.forEach(function(m) { addLineToFramedDisplay(display, m, 80); @@ -43379,7 +43801,7 @@ var COFantasy = COFantasy || function() { } } else { addLineToFramedDisplay(display, msgRes + tr.rerolls + tr.modifiers); - addLineToFramedDisplay(display, nomPerso(chasseur) + " ne réussit pas à sentir la corruption."); + addLineToFramedDisplay(display, nomPerso(chasseur) + " ne r\xE9ussit pas \xE0 sentir la corruption."); endDisplay(); } }); @@ -43391,28 +43813,28 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } let nbBaies; if (cmd.length > 1) { nbBaies = parseInt(cmd[1]); if (isNaN(nbBaies) || nbBaies < 1) { - sendPlayer(msg, "Aucune baie créée. la commnde en demandait " + cmd[1]); + sendPlayer(msg, "Aucune baie cr\xE9\xE9e. la commnde en demandait " + cmd[1]); return; } } getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Utilisation de !cof-creer-baies sans sélection de token", playerId); + sendPlayer(msg, "Utilisation de !cof-creer-baies sans s\xE9lection de token", playerId); return; } const evt = { - type: "Création de baies" + type: "Cr\xE9ation de baies" }; addEvent(evt); iterSelected(selected, function(druide) { - if (limiteRessources(druide, options, 'creationDeBaies', "créer des baies", evt)) return; + if (limiteRessources(druide, options, 'creationDeBaies', "cr\xE9er des baies", evt)) return; let niveau = ficheAttributeAsInt(druide, 'niveau', 1); let mangerBaie = "!cof-consommer-baie " + niveau + " --limiteParJour 1 baieMagique"; let nb; @@ -43427,7 +43849,7 @@ var COFantasy = COFantasy || function() { }); } ajouterConsommable(druide, 'Baie magique', nb.val, mangerBaie, evt); - sendPerso(druide, "crée " + nb.roll + " baies magiques"); + sendPerso(druide, "cr\xE9e " + nb.roll + " baies magiques"); }); }); } @@ -43455,12 +43877,12 @@ var COFantasy = COFantasy || function() { if (attr.length > 0) { attr = attr[0]; if (attr.length > 1) { - error("Plus d'un attribut pour la quantité d'armes de jet", attr); + error("Plus d'un attribut pour la quantit\xE9 d'armes de jet", attr); attr[1].remove(); } max = parseInt(attr.get('max')); if (isNaN(max) || max < 1) { - error("Maximum de " + weaponStats.name + " mal formé, vérifier sur la fiche", attr); + error("Maximum de " + weaponStats.name + " mal form\xE9, v\xE9rifier sur la fiche", attr); max = 1; } evt.attributes.push({ @@ -43480,7 +43902,7 @@ var COFantasy = COFantasy || function() { }); } if (weaponStats.nbArmesDeJet >= max) { - error(nomPerso(lanceur) + " a déjà toutes ses armes de jet (" + max + ")", weaponStats); + error(nomPerso(lanceur) + " a d\xE9j\xE0 toutes ses armes de jet (" + max + ")", weaponStats); return; } attr.set('current', weaponStats.nbArmesDeJet + 1); @@ -43493,16 +43915,16 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 3) { - error("Il manque des arguments à !cof-retour-boomerang", cmd); + error("Il manque des arguments \xE0 !cof-retour-boomerang", cmd); return; } let lanceur = persoOfId(cmd[1]); if (!lanceur) { - error("L'id du token ayan lancé les armes est incorrecte", cmd); + error("L'id du token ayan lanc\xE9 les armes est incorrecte", cmd); return; } let evt = { @@ -43519,11 +43941,11 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { - error("Il manque un argument à !cof-open-door", cmd); + error("Il manque un argument \xE0 !cof-open-door", cmd); return; } let door = getObj('door', cmd[1]); @@ -43534,7 +43956,7 @@ var COFantasy = COFantasy || function() { door.set('isOpen', true); } - //Demande de bouger son token jusqu'à destination + //Demande de bouger son token jusqu'\xE0 destination function attaqueLigneBouger(msg) { const playerId = getPlayerIdFromMsg(msg); if (stateCOF.pause && !playerIsGM(playerId)) { @@ -43543,7 +43965,7 @@ var COFantasy = COFantasy || function() { } let args = msg.content.split(' '); if (args.length < 2) { - error("Il manque un argument à !cof-attack-line", args); + error("Il manque un argument \xE0 !cof-attack-line", args); return; } const attaquant = persoOfId(args[1]); @@ -43554,12 +43976,12 @@ var COFantasy = COFantasy || function() { let token = attaquant.token; let restArgs = args.slice(2).join(' '); let command = '!cof-attack-line-from ' + token.get('left') + ' ' + token.get('top') + ' ' + token.id + ' ' + restArgs; - sendPlayer(msg, "Déplacer votre token jusqu'au bout de la ligne (l'emplacement doit être libre), et " + boutonSimple(command, "cliquer ici"), playerId); + sendPlayer(msg, "D\xE9placer votre token jusqu'au bout de la ligne (l'emplacement doit \xEAtre libre), et " + boutonSimple(command, "cliquer ici"), playerId); return; } - //En partant de from, retourne la première position sur le segment [from, to] - // à distance dist de pt. S'il n'y en a pas, retourne la projection de pt sur le segment + //En partant de from, retourne la premi\xE8re position sur le segment [from, to] + // \xE0 distance dist de pt. S'il n'y en a pas, retourne la projection de pt sur le segment function positionLigne(from, to, token, dist) { let fx = from.x; let fy = from.y; @@ -43605,7 +44027,7 @@ var COFantasy = COFantasy || function() { let originLeft = parseInt(args[1]); let originTop = parseInt(args[2]); if (isNaN(originLeft) || isNaN(originTop)) { - error("Coordonnées non numériques dans !co-attack-line", args); + error("Coordonn\xE9es non num\xE9riques dans !co-attack-line", args); return; } const attaquant = persoOfId(args[3]); @@ -43615,7 +44037,7 @@ var COFantasy = COFantasy || function() { } let destLeft = attaquant.token.get('left'); let destTop = attaquant.token.get('top'); - //On remet l'attaquant à sa place + //On remet l'attaquant \xE0 sa place attaquant.token.set('left', originLeft); attaquant.token.set('top', originTop); let combat = stateCOF.combat; @@ -43642,12 +44064,12 @@ var COFantasy = COFantasy || function() { y: originTop }; let tropLoin = false; - //On cherche si argument --distanceMax, pas utilisé par cof-attack + //On cherche si argument --distanceMax, pas utilis\xE9 par cof-attack optArgs = optArgs.filter(function(cmd) { if (!cmd.startsWith('distanceMax')) return true; let a = cmd.split(' '); if (a.length < 2) { - error("Il manque un argument à --distanceMax", cmd); + error("Il manque un argument \xE0 --distanceMax", cmd); return false; } let distanceMax = parseInt(a[1]); @@ -43700,14 +44122,14 @@ var COFantasy = COFantasy || function() { return; } } - //On détermine les cibles sur le trajet + //On d\xE9termine les cibles sur le trajet let cibles = []; tokens.forEach(function(tok) { let cible = { token: tok, charId: tok.get('represents') }; - if (nePeutPlusPrendreDM(cible, {})) return; //pas de dégâts aux morts + if (nePeutPlusPrendreDM(cible, {})) return; //pas de d\xE9g\xE2ts aux morts let distToTrajectory = distancePixTokenSegment(tok, ptOrigin, ptDest); if (distToTrajectory > attRayon + tokenSize(tok, 0)) return; @@ -43734,7 +44156,7 @@ var COFantasy = COFantasy || function() { }); combat.attackId = combat.attackId || 0; combat.attackCallbacks = combat.attackCallBacks || {}; - //On trie les cibles selon leur distance à l'origine. + //On trie les cibles selon leur distance \xE0 l'origine. cibles.sort(function(c1, c2) { return c1.distanceOrigine - c2.distanceOrigine; }); @@ -43783,11 +44205,11 @@ var COFantasy = COFantasy || function() { if (options === undefined) return; let cmd = options.cmd; if (cmd === undefined) { - error("Problème de parse options", msg.content); + error("Probl\xE8me de parse options", msg.content); return; } if (cmd.length < 2) { - error("Il manque un argument à !cof-vision-nocturne", cmd); + error("Il manque un argument \xE0 !cof-vision-nocturne", cmd); return; } let distance = parseInt(cmd[1]); @@ -43798,7 +44220,7 @@ var COFantasy = COFantasy || function() { let pageId = options.pageId; getSelected(msg, function(selected, playerId) { if (selected.length === 0) { - sendPlayer(msg, "Utilisation de !cof-vision-nocturne sans sélection de token", playerId); + sendPlayer(msg, "Utilisation de !cof-vision-nocturne sans s\xE9lection de token", playerId); return; } const evt = { @@ -43818,27 +44240,27 @@ var COFantasy = COFantasy || function() { const listeDesRunesMortes = { Melianil: { - description: "+2 en attaque et +1d6 aux DM (à tous les sorts ou aux attaques au contact avec le bâton)", + description: "+2 en attaque et +1d6 aux DM (\xE0 tous les sorts ou aux attaques au contact avec le b\xE2ton)", }, Isulys: { - description: "une fois par tour, par une action d'attaque, peut produire un rayon d’énergie négative d’une portée de 40 mètres. Sur test d’attaque magique réussit, la victime subit [2d6 + Mod. %SAGINT] DM et doit utiliser un d12 à tous ses tests au lieu d’un d20 pendant un tour.", + description: "une fois par tour, par une action d'attaque, peut produire un rayon d\x2019\xE9nergie n\xE9gative d\x2019une port\xE9e de 40 m\xE8tres. Sur test d\x2019attaque magique r\xE9ussit, la victime subit [2d6 + Mod. %SAGINT] DM et doit utiliser un d12 \xE0 tous ses tests au lieu d\x2019un d20 pendant un tour.", }, Bryniza: { - description: "permet de voir parfaitement dans le noir à une portée de 30 m, et comme dans la pénombre jusqu'à 50 m. Au prix d'une action limitée, le porteur peut utiliser le sort Détection de la magie 3 fois par jour.", + description: "permet de voir parfaitement dans le noir \xE0 une port\xE9e de 30 m, et comme dans la p\xE9nombre jusqu'\xE0 50 m. Au prix d'une action limit\xE9e, le porteur peut utiliser le sort D\xE9tection de la magie 3 fois par jour.", activation: "Les yeux de %NOM deviennent d'un noir d'encre.", fin: "Les yeux de %NOM redeviennent normaux.", }, Lizura: { - description: "immunité au souffle de Swarathnak, à l'acide et au poison.", - activation: "La boue noire du bâton s'écoule le long du bras de %NOM et recouvre tout son corps à l'exception des yeux.", - fin: "La boue se retire dans le bâton, %NOM retrouve une apparence normale.", + description: "immunit\xE9 au souffle de Swarathnak, \xE0 l'acide et au poison.", + activation: "La boue noire du b\xE2ton s'\xE9coule le long du bras de %NOM et recouvre tout son corps \xE0 l'exception des yeux.", + fin: "La boue se retire dans le b\xE2ton, %NOM retrouve une apparence normale.", memeEffetQue: 'Mitrah', }, Mitrah: { - description: "RD 5 à tous les DM.", - activation: "La boue noire du bâton s'écoule le long du bras de %NOM et recouvre tout son corps à l'exception des yeux.", - fin: "La boue se retire dans le bâton, %NOM retrouve une apparence normale.", + description: "RD 5 \xE0 tous les DM.", + activation: "La boue noire du b\xE2ton s'\xE9coule le long du bras de %NOM et recouvre tout son corps \xE0 l'exception des yeux.", + fin: "La boue se retire dans le b\xE2ton, %NOM retrouve une apparence normale.", memeEffetQue: 'Lizura', }, }; @@ -43850,13 +44272,13 @@ var COFantasy = COFantasy || function() { function gererRunesMortes(msg) { let cmd = msg.content.split(' '); if (cmd.length < 2) { - error("il manque l'id du personnage qui gère ses runes mortes", cmd); + error("il manque l'id du personnage qui g\xE8re ses runes mortes", cmd); return; } let perso = persoOfId(cmd[1]); if (perso === undefined) return; if (!predicateAsBool(perso, 'batonDesRunesMortes')) { - sendPerso(perso, "ne porte pas le bâton des runes mortes"); + sendPerso(perso, "ne porte pas le b\xE2ton des runes mortes"); return; } let niveau = ficheAttributeAsInt(perso, 'niveau', 1); @@ -43880,7 +44302,7 @@ var COFantasy = COFantasy || function() { error("Rune " + cmd[3] + " non reconnue", cmd); break; } - //Vérification qu'on n'a pas déjà le max de runes + //V\xE9rification qu'on n'a pas d\xE9j\xE0 le max de runes let runesLibres = Math.ceil(niveau / 4); for (let rune in listeDesRunesMortes) { if (attributeAsBool(perso, 'rune' + rune)) runesLibres--; @@ -43894,11 +44316,11 @@ var COFantasy = COFantasy || function() { if (attr[0].get('current') == 'false') { let donne = attr[0].get('max'); if (donne) { - sendPerso(perso, "a donné " + cmd[3] + " à " + donne + ". Impossible de l'activer.", true); + sendPerso(perso, "a donn\xE9 " + cmd[3] + " \xE0 " + donne + ". Impossible de l'activer.", true); break; } } else { - sendPerso(perso, cmd[3] + " est déjà active", true); + sendPerso(perso, cmd[3] + " est d\xE9j\xE0 active", true); break; } } @@ -43938,7 +44360,7 @@ var COFantasy = COFantasy || function() { break; } if (!attributeAsBool(perso, 'rune' + cmd[3])) { - sendPerso(perso, cmd[3] + " n'est pas activée.", true); + sendPerso(perso, cmd[3] + " n'est pas activ\xE9e.", true); break; } let msg; @@ -43950,7 +44372,7 @@ var COFantasy = COFantasy || function() { msg }); if (cmd[3] == 'Bryniza') { - //On enlève la vision dans le noir + //On enl\xE8ve la vision dans le noir let token = perso.token; let pageId = token.get('pageid'); let visionNoir = predicateAsInt(perso, 'visionDansLeNoir', 0); @@ -43973,12 +44395,12 @@ var COFantasy = COFantasy || function() { case 'donner': { if (cmd.length < 4) { - error("Il faut préciser le token à qui donner la rune", cmd); + error("Il faut pr\xE9ciser le token \xE0 qui donner la rune", cmd); break; } let cible = persoOfId(cmd[4]); if (!cible) { - error("Impossible de trouver à qui donner la rune", cmd); + error("Impossible de trouver \xE0 qui donner la rune", cmd); break; } let attr = tokenAttribute(perso, 'rune' + cmd[3]); @@ -43986,11 +44408,11 @@ var COFantasy = COFantasy || function() { if (attr[0].get('current') == 'false') { let donne = attr[0].get('max'); if (donne) { - sendPerso(perso, "a déjà donné " + cmd[3] + " à " + donne + ".", true); + sendPerso(perso, "a d\xE9j\xE0 donn\xE9 " + cmd[3] + " \xE0 " + donne + ".", true); break; } } else { - sendPerso(perso, "Il faut d'abord désactiver " + cmd[3] + " avant de la donner", true); + sendPerso(perso, "Il faut d'abord d\xE9sactiver " + cmd[3] + " avant de la donner", true); break; } } @@ -43999,14 +44421,14 @@ var COFantasy = COFantasy || function() { error("Rune " + cmd[3] + " non reconnue", cmd); break; } - let msg = nomPerso(perso) + " donne une rune à " + nomPerso(cible); + let msg = nomPerso(perso) + " donne une rune \xE0 " + nomPerso(cible); let maxVal = nomPerso(cible); setTokenAttr(perso, 'rune' + cmd[3], 'false', evt, { msg, maxVal }); - sendPerso(perso, "peut maintenant communiquer par télépathie avec " + nomPerso(cible), true); - sendPerso(cible, "peut maintenant communiquer par télépathie avec " + nomPerso(perso), true); + sendPerso(perso, "peut maintenant communiquer par t\xE9l\xE9pathie avec " + nomPerso(cible), true); + sendPerso(cible, "peut maintenant communiquer par t\xE9l\xE9pathie avec " + nomPerso(perso), true); break; } case 'recuperer': @@ -44018,23 +44440,23 @@ var COFantasy = COFantasy || function() { } let attr = tokenAttribute(perso, 'rune' + cmd[3]); if (attr.length === 0) { - sendPerso(perso, "a déjà " + cmd[3], true); + sendPerso(perso, "a d\xE9j\xE0 " + cmd[3], true); break; } if (attr[0].get('current') != 'false') { - sendPerso(perso, "a déjà " + cmd[3], true); + sendPerso(perso, "a d\xE9j\xE0 " + cmd[3], true); break; } let donne = attr[0].get('max'); if (!donne) { - sendPerso(perso, "a déjà " + cmd[3], true); + sendPerso(perso, "a d\xE9j\xE0 " + cmd[3], true); break; } - let msg = nomPerso(perso) + " rappelle une rune sur le bâton"; + let msg = nomPerso(perso) + " rappelle une rune sur le b\xE2ton"; removeTokenAttr(perso, 'rune' + cmd[3], evt, { msg }); - sendPerso(perso, "ne peut plus communiquer par télépathie avec " + donne, true); + sendPerso(perso, "ne peut plus communiquer par t\xE9l\xE9pathie avec " + donne, true); break; } default: @@ -44071,13 +44493,13 @@ var COFantasy = COFantasy || function() { if (er.actif) { ligne = ' 3) { + rang = parseInt(cmd[3]); + if (isNaN(rang)) + rang = predicateAsInt(arquebusier, cmd[3], 0, 2); + if (rang < 1) { + error("Rang de d\xE9molition " + cmd[3] + " incorrect", cmd); + return; + } + } else rang = predicateAsInt(arquebusier, 'voieDesExplosifs', 2, 2); + portee = 6; + dm = rang + 'd6'; + let dmStruct = rollDePlus(6, { + nbDes: 2 * rang + }); + message += " et inflige " + dmStruct.roll + " DM \xE0 la structure (ignore la moiti\xE9 de la RD)"; + tempsDePose = 3; + break; + } + case 'piege': + case 'pi\xE8ge': + { + typeBombe = 'piege'; + if (cmd.length < 5) { + error("Il manque des arguments pour !cof-poser-bombe", cmd); + return; + } + dm = cmd[3]; + portee = 3; + switch (cmd[4]) { + case 'retard': + case 'retard\xE9': + tempsDePose = 1; + if (cmd.length > 5) { + duree = parseInt(cmd[5]); + if (isNaN(duree) || duree < 1) { + error("Dur\xE9e de retardement " + cmd[5] + " incorrecte"); + return; + } + } + break; + case 'intrusion': + case 'detection': + case 'd\xE9tection': + tempsDePose = 2; + intrusion = 1; + duree = 100; + if (cmd.length > 5) { + intrusion = parseInt(cmd[5]); + if (isNaN(intrusion) || intrusion < 1) { + error("Distance de d\xE9tection " + cmd[5] + " incorrecte"); + return; + } + } + //On converti la distance d'intrusion en pixels + let scale = computeScale(pageId); + intrusion = (intrusion / scale) * PIX_PER_UNIT; + break; + default: + error("Type de pi\xE8ge explosif " + cmd[4] + " non reconnu", cmd); + return; + } + break; + } + default: + error("Type de bombe " + cmd[2] + " non reconnu", cmd); + return; + } + let gmnotes = JSON.stringify({ + typeBombe, + portee, + message, + dm, + tempsDePose, + duree, + intrusion + }); + let name = "Bombe " + generateUUID(); + const evt = { + type: "Pose de bombe" + }; + addEvent(evt); + if (limiteRessources(arquebusier, options, 'poseBombe', "poser un explosif", evt)) return; + //create the token + let t = createObj('graphic', { + _pageid: pageId, + imgsrc: IMG_BOMB, + represents: '', + left: arquebusier.token.get('left'), + top: arquebusier.token.get('top'), + width: PIX_PER_UNIT, + height: PIX_PER_UNIT * 0.8, + layer: 'map', + isDrawing: true, + name, + gmnotes + }); + if (!t) { + error("Impossible de cr\xE9er le token de la bombe", IMG_BOMB); + return; + } + toFront(t); + evt.tokens = evt.tokens || []; + evt.tokens.push(t); + stateCOF.tokensTemps = stateCOF.tokensTemps || []; + stateCOF.tokensTemps.push({ + tid: t.id, + duree: duree + tempsDePose, + name, + init: getInit(), + intrusion + }); + //TODO: ajouter un effet temporaire "occup\xE9" + let msgPose = "pose un explosif. "; + if (tempsDePose < 2) msgPose += "Cela lui prend tout le tour"; + else { + msgPose += onGenre(arquebusier, 'Il', 'Elle') + " y passe le tour et encore le"; + if (tempsDePose < 3) msgPose += " suivant."; + else msgPose += "s " + (tempsDePose - 1) + " suivants."; + } + sendPerso(arquebusier, msgPose); } function apiCommand(msg) { @@ -44279,7 +44856,7 @@ var COFantasy = COFantasy || function() { case '!cof-attack-line': attaqueLigneBouger(msg); return; - case '!cof-attack-line-from': //seulement utilisé en interne + case '!cof-attack-line-from': //seulement utilis\xE9 en interne attaqueLigne(msg); return; case '!cof-attendre': @@ -44329,14 +44906,14 @@ var COFantasy = COFantasy || function() { case '!cof-explosion': attaqueExplosion(msg); return; - case '!cof-hors-combat': //ancienne syntaxe, plus documentée + case '!cof-hors-combat': //ancienne syntaxe, plus document\xE9e case '!cof-fin-combat': sortirDuCombat(); return; case '!cof-fin-reaction-violente': finReactionViolente(msg); return; - case '!cof-foudre-du-temps': //ancienne syntaxe, plus documentée + case '!cof-foudre-du-temps': //ancienne syntaxe, plus document\xE9e if (!msg.content) return; let i = msg.content.indexOf(' '); if (i < 0) return; @@ -44385,6 +44962,9 @@ var COFantasy = COFantasy || function() { case '!cof-pause': pauseGame(); return; + case '!cof-poser-bombe': + poserBombe(msg); + return; case '!cof-recharger': recharger(msg); return; @@ -44426,7 +45006,10 @@ var COFantasy = COFantasy || function() { case '!cof-sphere-de-feu': sphereDeFeu(msg); return; - case "!cof-save-state": + case '!cof-save-effet': + parseSaveEffet(msg); + return; + case '!cof-save-state': parseSaveState(msg); return; case '!cof-statut': @@ -44447,9 +45030,6 @@ var COFantasy = COFantasy || function() { case '!cof-zone-de-vie': lancerZoneDeVie(msg); return; - case "!cof-save-effet": - parseSaveEffet(msg); - return; case "!cof-degainer": parseDegainer(msg); return; @@ -44474,7 +45054,7 @@ var COFantasy = COFantasy || function() { case "!cof-fin-classe-effet": finClasseDEffet(msg); return; - case "!cof-attaque-magique": + case '!cof-attaque-magique': parseAttaqueMagique(msg); return; case "!cof-injonction": @@ -44631,7 +45211,7 @@ var COFantasy = COFantasy || function() { stateCOF.statistiques = stateCOF.statistiquesEnPause; delete stateCOF.statistiquesEnPause; } else { - stateCOF.statistiques = {}; //remet aussi les statistiques à 0 + stateCOF.statistiques = {}; //remet aussi les statistiques \xE0 0 } return; case "!cof-arreter-statistiques": @@ -44641,7 +45221,7 @@ var COFantasy = COFantasy || function() { if (stateCOF.statistiques) { stateCOF.statistiquesEnPause = stateCOF.statistiques; delete stateCOF.statistiques; - } // sinon, ne pas écraser les statistiques déjà en pause + } // sinon, ne pas \xE9craser les statistiques d\xE9j\xE0 en pause return; case '!cof-statistiques': displayStatistics(msg); @@ -44850,57 +45430,63 @@ var COFantasy = COFantasy || function() { } //Attributs possibles : - // activation : message à l'activation - // activationF : message à l'activation si la cible est féminine + // activation : message \xE0 l'activation + // activationF : message \xE0 l'activation si la cible est f\xE9minine // actif : message de statut - // actifF : message de statut si la cible est féminine - // fin : message à la fin de l'effet + // actifF : message de statut si la cible est f\xE9minine + // fin : message \xE0 la fin de l'effet // dm : permet d'infliger des dm // soins : soigne - // prejudiciable: est un effet préjudiciable, qui peut être enlevé par délivrance - // generic: admet un argument entre parenthèses - // seulementVivant: ne peut s'appliquer qu'aux créatures vivantes + // prejudiciable: est un effet pr\xE9judiciable, qui peut \xEAtre enlev\xE9 par d\xE9livrance + // generic: admet un argument entre parenth\xE8ses + // seulementVivant: ne peut s'appliquer qu'aux cr\xE9atures vivantes // visible : l'effet est visible - // msgSave: message à afficher quand on résiste à l'effet. Sera précédé de "pour " + // msgSave: message \xE0 afficher quand on r\xE9siste \xE0 l'effet. Sera pr\xE9c\xE9d\xE9 de "pour " // entrave: effet qui immobilise, paralyse ou ralentit - // statusMarker: marker par défaut pour l'effet + // statusMarker: marker par d\xE9faut pour l'effet const messageEffetTemp = { aCouvert: { - activation: "reste à couvert", - actif: "est à couvert", - fin: "n'est pas à couvert" + activation: "reste \xE0 couvert", + actif: "est \xE0 couvert", + fin: "n'est pas \xE0 couvert" }, affecteParAura: { activation: "entre dans une aura", - actif: "est entré dans une aura ce tour", - actifF: "est entrée dans une aura ce tour", + actif: "est entr\xE9 dans une aura ce tour", + actifF: "est entr\xE9e dans une aura ce tour", fin: "fin d'aura", generic: true, }, apeureTemp: { activation: "prend peur", - actif: "est dominé par sa peur", - actifF: "est dominée par sa peur", + actif: "est domin\xE9 par sa peur", + actifF: "est domin\xE9e par sa peur", fin: "retrouve du courage", msgSave: "retrouver du courage", prejudiciable: true, visible: true }, + attaqueADistanceRatee: { + activation: "rate une attaque \xE0 distance", + actif: "a rat\xE9 une attaque \xE0 distance", + fin: '', + visible: false + }, aveugleTemp: { activation: "n'y voit plus rien !", - actif: "est aveuglé", - actifF: "est aveuglée", + actif: "est aveugl\xE9", + actifF: "est aveugl\xE9e", fin: "retrouve la vue", msgSave: "retrouver la vue", prejudiciable: true, visible: true }, benediction: { - activation: "est touché par la bénédiction", - activationF: "est touchée par la bénédiction", - actif: "est béni", - actifF: "est bénie", - fin: "l'effet de la bénédiction s'estompe" + activation: "est touch\xE9 par la b\xE9n\xE9diction", + activationF: "est touch\xE9e par la b\xE9n\xE9diction", + actif: "est b\xE9ni", + actifF: "est b\xE9nie", + fin: "l'effet de la b\xE9n\xE9diction s'estompe" }, blessureSanglante: { activation: "saigne abondamment", @@ -44913,43 +45499,43 @@ var COFantasy = COFantasy || function() { }, carquoisMagique: { activation: "enchante son carquois", - actif: "a un carquois enchannté", + actif: "a un carquois enchannt\xE9", fin: "le carquois redevient normal", visible: true, }, chantDesHeros: { - activation: "écoute le chant du barde", - actif: "est inspiré par le Chant des Héros", - actifF: "est inspirée par le Chant des Héros", - fin: "n'est plus inspiré par le Chant des Héros", - finF: "n'est plus inspirée par le Chant des Héros" + activation: "\xE9coute le chant du barde", + actif: "est inspir\xE9 par le Chant des H\xE9ros", + actifF: "est inspir\xE9e par le Chant des H\xE9ros", + fin: "n'est plus inspir\xE9 par le Chant des H\xE9ros", + finF: "n'est plus inspir\xE9e par le Chant des H\xE9ros" }, drainDeForce: { - activation: "se sent drainé de sa force", - activationF: "se sent drainée de sa force", + activation: "se sent drain\xE9 de sa force", + activationF: "se sent drain\xE9e de sa force", actif: "est sous l'effet d'un drain de force", - msgSave: "ne plus être affaibli", + msgSave: "ne plus \xEAtre affaibli", fin: "n'est plus affaibli", finF: "n'est plus affaiblie", prejudiciable: true, seulementVivant: true, }, etourdiTemp: { - activation: "est étourdi : aucune action et -5 en DEF", - activationF: "est étourdie : aucune action et -5 en DEF", - actif: "est étourdi", - actifF: "est étourdie", - fin: "n'est plus étourdi", - finF: "n'est plus étourdie", + activation: "est \xE9tourdi : aucune action et -5 en DEF", + activationF: "est \xE9tourdie : aucune action et -5 en DEF", + actif: "est \xE9tourdi", + actifF: "est \xE9tourdie", + fin: "n'est plus \xE9tourdi", + finF: "n'est plus \xE9tourdie", msgSave: "se reprendre", prejudiciable: true, visible: true }, formeDAnge: { - activation: "prend la forme d'un ange ailé", + activation: "prend la forme d'un ange ail\xE9", actif: "est en forme d'ange et peut jeter des sorts en vol stationnaire", - fin: "retrouve sa forme normale. Espérons qu'il était au sol...", - finF: "retrouve sa forme normale. Espérons qu'elle était au sol...", + fin: "retrouve sa forme normale. Esp\xE9rons qu'il \xE9tait au sol...", + finF: "retrouve sa forme normale. Esp\xE9rons qu'elle \xE9tait au sol...", visible: true, }, frappeDesArcanes: { @@ -44958,50 +45544,50 @@ var COFantasy = COFantasy || function() { fin: "retrouve assez de puissance magique pour lancer des sorts", }, frenesieMinotaure: { - activation: "entre en frénésie", - actif: "est en frénésie", + activation: "entre en fr\xE9n\xE9sie", + actif: "est en fr\xE9n\xE9sie", fin: "retrouve son calme", msgSave: "retrouver son calme", }, inspiration: { - activation: "est inspiré", - activationF: "est inspirée", + activation: "est inspir\xE9", + activationF: "est inspir\xE9e", actif: "est sous l'effet d'une inspiration", - fin: "n'est plus inspiré", - finF: "n'est plus inspirée" + fin: "n'est plus inspir\xE9", + finF: "n'est plus inspir\xE9e" }, imageDecalee: { - activation: "décale légèrement son image", - actif: "a décalé son image", - fin: "apparaît à nouveau là où il se trouve", - finF: "apparaît à nouveau là où elle se trouve", + activation: "d\xE9cale l\xE9g\xE8rement son image", + actif: "a d\xE9cal\xE9 son image", + fin: "appara\xEEt \xE0 nouveau l\xE0 o\xF9 il se trouve", + finF: "appara\xEEt \xE0 nouveau l\xE0 o\xF9 elle se trouve", visible: false }, immobiliseTemp: { - activation: "est immobilisé : aucun déplacement possible", - activationF: "est immobilisée : aucun déplacement possible", - actif: "est immobilisé", - actifF: "est immobilisée", - fin: "n'est plus immobilisé", - finF: "n'est plus immobilisée", + activation: "est immobilis\xE9 : aucun d\xE9placement possible", + activationF: "est immobilis\xE9e : aucun d\xE9placement possible", + actif: "est immobilis\xE9", + actifF: "est immobilis\xE9e", + fin: "n'est plus immobilis\xE9", + finF: "n'est plus immobilis\xE9e", msgSave: "pouvoir bouger", prejudiciable: true, visible: true, entrave: true }, immuniteAmaladie: { - activation: "devient immunisé aux maladies", - activationF: "devient immunisée aux maladies", - actif: "est temporairement immunisé aux maladies", - actifF: "est temporairement immunisée aux maladies", + activation: "devient immunis\xE9 aux maladies", + activationF: "devient immunis\xE9e aux maladies", + actif: "est temporairement immunis\xE9 aux maladies", + actifF: "est temporairement immunis\xE9e aux maladies", fin: "redevient sensible aux maladies", visible: false }, immuniteApoison: { - activation: "devient immunisé au poison", - activationF: "devient immunisée au poison", - actif: "est temporairement immunisé au poison", - actifF: "est temporairement immunisée au poison", + activation: "devient immunis\xE9 au poison", + activationF: "devient immunis\xE9e au poison", + actif: "est temporairement immunis\xE9 au poison", + actifF: "est temporairement immunis\xE9e au poison", fin: "redevient sensible au poison", visible: false }, @@ -45014,36 +45600,36 @@ var COFantasy = COFantasy || function() { }, paradeCroisee: { activation: "se met en position pour parer des deux armes", - actif: "est en position de parade croisée", - fin: "ne bénéficie plus de sa parade croisée", + actif: "est en position de parade crois\xE9e", + fin: "ne b\xE9n\xE9ficie plus de sa parade crois\xE9e", visible: true, }, paralyseTemp: { - activation: "est paralysé : aucune action ni déplacement possible", - activationF: "est paralysée : aucune action ni déplacement possible", - actif: "est paralysé", - actifF: "est paralysée", - fin: "n'est plus paralysé", - finF: "n'est plus paralysée", - msgSave: "ne plus être paralysé", + activation: "est paralys\xE9 : aucune action ni d\xE9placement possible", + activationF: "est paralys\xE9e : aucune action ni d\xE9placement possible", + actif: "est paralys\xE9", + actifF: "est paralys\xE9e", + fin: "n'est plus paralys\xE9", + finF: "n'est plus paralys\xE9e", + msgSave: "ne plus \xEAtre paralys\xE9", prejudiciable: true, visible: true, entrave: true }, paralyseGoule: { - activation: "est paralysé : aucune action ni déplacement possible", - activationF: "est paralysée : aucune action ni déplacement possible", - actif: "est paralysé", - actifF: "est paralysée", - fin: "n'est plus paralysé", - finF: "n'est plus paralysée", - msgSave: "ne plus être paralysé", + activation: "est paralys\xE9 : aucune action ni d\xE9placement possible", + activationF: "est paralys\xE9e : aucune action ni d\xE9placement possible", + actif: "est paralys\xE9", + actifF: "est paralys\xE9e", + fin: "n'est plus paralys\xE9", + finF: "n'est plus paralys\xE9e", + msgSave: "ne plus \xEAtre paralys\xE9", prejudiciable: true, visible: true }, peauDEcorce: { - activation: "donne à sa peau la consistance de l'écorce", - actif: "a la peau dure comme l'écorce", + activation: "donne \xE0 sa peau la consistance de l'\xE9corce", + actif: "a la peau dure comme l'\xE9corce", fin: "retrouve une peau normale", visible: true }, @@ -45054,36 +45640,36 @@ var COFantasy = COFantasy || function() { visible: true }, penombreTemp: { - activation: "ne voit plus très loin", - actif: "est dans la pénombre", + activation: "ne voit plus tr\xE8s loin", + actif: "est dans la p\xE9nombre", fin: "retrouve une vue normale", msgSave: "retrouver la vue", prejudiciable: true, }, peurEtourdi: { - activation: "prend peur: il peut fuir ou rester recroquevillé", - activationF: "prend peur: elle peut fuir ou rester recroquevillé", - actif: "est paralysé par la peur", - actifF: "est paralysée par la peur", - fin: "retrouve du courage et peut à nouveau agir", + activation: "prend peur: il peut fuir ou rester recroquevill\xE9", + activationF: "prend peur: elle peut fuir ou rester recroquevill\xE9", + actif: "est paralys\xE9 par la peur", + actifF: "est paralys\xE9e par la peur", + fin: "retrouve du courage et peut \xE0 nouveau agir", msgSave: "retrouver du courage", prejudiciable: true, visible: true }, protectionContreLesProjectiles: { activation: "gagne une protection contre les projectiles", - actif: "est protégé contre les projectiles", - actifF: "est protégée contre les projectiles", - fin: "n'est plus protégé contre les projectiles", - finF: "n'est plus protégée contre les projectiles", + actif: "est prot\xE9g\xE9 contre les projectiles", + actifF: "est prot\xE9g\xE9e contre les projectiles", + fin: "n'est plus prot\xE9g\xE9 contre les projectiles", + finF: "n'est plus prot\xE9g\xE9e contre les projectiles", visible: false, }, ralentiTemp: { - activation: "est ralenti : une seule action, pas d'action limitée", - activationF: "est ralentie : une seule action, pas d'action limitée", + activation: "est ralenti : une seule action, pas d'action limit\xE9e", + activationF: "est ralentie : une seule action, pas d'action limit\xE9e", actif: "est ralenti", actifF: "est ralentie", - msgSave: "ne plus être ralenti", + msgSave: "ne plus \xEAtre ralenti", fin: "n'est plus ralenti", finF: "n'est plus ralentie", prejudiciable: true, @@ -45091,23 +45677,23 @@ var COFantasy = COFantasy || function() { entrave: true }, rayonAffaiblissant: { - activation: "est touché par un rayon affaiblissant", - activationF: "est touchée par un rayon affaiblissant", + activation: "est touch\xE9 par un rayon affaiblissant", + activationF: "est touch\xE9e par un rayon affaiblissant", actif: "est sous l'effet d'un rayon affaiblissant", - msgSave: "ne plus être affaibli", + msgSave: "ne plus \xEAtre affaibli", fin: "n'est plus affaibli", finF: "n'est plus affaiblie", prejudiciable: true }, rituelAssure: { - activation: "passe un tour complet à préparer un sort", - actif: "a préparé un rituel assuré", + activation: "passe un tour complet \xE0 pr\xE9parer un sort", + actif: "a pr\xE9par\xE9 un rituel assur\xE9", fin: "", visible: false }, secoue: { - activation: "hésite un peu, il est secoué", - activationF: "hésite un peu, elle est secouée", + activation: "h\xE9site un peu, il est secou\xE9", + activationF: "h\xE9site un peu, elle est secou\xE9e", actif: "a un peu peur", fin: "retrouve du courage", msgSave: "retrouver du courage", @@ -45116,29 +45702,29 @@ var COFantasy = COFantasy || function() { }, secretsDeLAuDela: { activation: "contacte des esprits", - actif: "des esprits lui murmurent des secrets oubliés", + actif: "des esprits lui murmurent des secrets oubli\xE9s", fin: "les esprits repartent" }, souffleDeMort: { - activation: "est terrifié par la mort de son allié", - activationF: "est terrifiée par la mort de son allié", + activation: "est terrifi\xE9 par la mort de son alli\xE9", + activationF: "est terrifi\xE9e par la mort de son alli\xE9", actif: "ne peut agir suite au souffle de mort", fin: "retrouve ses esprits", - msgSave: "pouvoir agir malgré la mort de son allié", + msgSave: "pouvoir agir malgr\xE9 la mort de son alli\xE9", prejudiciable: true, visible: true, }, tremblementMineur: { activation: "Tremblement mineur", - actif: "est déséquilibré par le tremblement", - actifF: "est déséquilibrée par le tremblement", + actif: "est d\xE9s\xE9quilibr\xE9 par le tremblement", + actifF: "est d\xE9s\xE9quilibr\xE9e par le tremblement", fin: '', visible: false }, zoneDeVie: { activation: "enchante une zone autour de lui", activationF: "enchante une zone autour d'elle", - actif: "a créé une zone de vie", + actif: "a cr\xE9\xE9 une zone de vie", fin: "la zone de vie se termine", visible: true, generic: true, //pour pouvoir avoir plusieurs zones de vie @@ -45152,10 +45738,10 @@ var COFantasy = COFantasy || function() { prejudiciable: true }, assommeTemp: { - activation: "est assommé", - activationF: "est assommée", - actif: "est assommé", - actifF: "est assommée", + activation: "est assomm\xE9", + activationF: "est assomm\xE9e", + actif: "est assomm\xE9", + actifF: "est assomm\xE9e", fin: "reprend conscience", msgSave: "reprendre conscience", prejudiciable: true, @@ -45163,90 +45749,90 @@ var COFantasy = COFantasy || function() { }, nauseeuxTemp: { activation: "souffre de violentes douleurs au ventre", - actif: "est nauséeux, seul le mouvement est possible", - actifF: "est nauséeuse, seul le mouvement est possible", + actif: "est naus\xE9eux, seul le mouvement est possible", + actifF: "est naus\xE9euse, seul le mouvement est possible", fin: "se sent mieux", - msgSave: "ne plus être nauséeux", + msgSave: "ne plus \xEAtre naus\xE9eux", prejudiciable: true, visible: true }, invisibleTemp: { - activation: "disparaît", + activation: "dispara\xEEt", actif: "est invisible", - fin: "réapparaît", + fin: "r\xE9appara\xEEt", msgSave: "ne pas devenir invisible", visible: true }, aveugleManoeuvre: { - activation: "est aveuglé par la manoeuvre", - activationF: "est aveuglée par la manoeuvre", - actif: "a du mal à voir où sont ses adversaires", + activation: "est aveugl\xE9 par la manoeuvre", + activationF: "est aveugl\xE9e par la manoeuvre", + actif: "a du mal \xE0 voir o\xF9 sont ses adversaires", fin: "retrouve une vision normale", - msgSave: "voir à nouveau", + msgSave: "voir \xE0 nouveau", prejudiciable: true, visible: true }, bloqueManoeuvre: { - activation: "est bloqué par la manoeuvre", - activationF: "est bloquée par la manoeuvre", - actif: "est bloqué et ne peut pas se déplacer", - actifF: "est bloquée et ne peut pas se déplacer", - fin: "peut à nouveau se déplacer", - msgSave: "pouvoir se déplacer", + activation: "est bloqu\xE9 par la manoeuvre", + activationF: "est bloqu\xE9e par la manoeuvre", + actif: "est bloqu\xE9 et ne peut pas se d\xE9placer", + actifF: "est bloqu\xE9e et ne peut pas se d\xE9placer", + fin: "peut \xE0 nouveau se d\xE9placer", + msgSave: "pouvoir se d\xE9placer", prejudiciable: true, entrave: true }, diversionManoeuvre: { - activation: "est déconcentré", - activationF: "est déconcentrée", - actif: "a été perturbé par une diversion", - actifF: "a été perturbée par une diversion", + activation: "est d\xE9concentr\xE9", + activationF: "est d\xE9concentr\xE9e", + actif: "a \xE9t\xE9 perturb\xE9 par une diversion", + actifF: "a \xE9t\xE9 perturb\xE9e par une diversion", fin: "se reconcentre sur le combat", msgSave: "se reconcentrer sur le combat", prejudiciable: true, visible: true }, menaceManoeuvre: { - activation: "est menacé", - activationF: "est menacée", - actif: "a été menacé, risque de plus de DM", - actifF: "a été menacée, risque de plus de DM", + activation: "est menac\xE9", + activationF: "est menac\xE9e", + actif: "a \xE9t\xE9 menac\xE9, risque de plus de DM", + actifF: "a \xE9t\xE9 menac\xE9e, risque de plus de DM", fin: "n'est plus sous la menace", - msgSave: "ne plus être sous la menace", + msgSave: "ne plus \xEAtre sous la menace", prejudiciable: true, generic: true }, tenuADistanceManoeuvre: { - activation: "est tenu à distance", - activationF: "est tenue à distance", - actif: "est tenu à distance de son adversaire, il ne peut pas l'attaquer", - actifF: "est tenue à distance de son adversaire, elle ne peut pas l'attaquer", - fin: "peut à nouveau attaquer son adversaire", - msgSave: "pouvoir à nouveau attaquer son adversaire", + activation: "est tenu \xE0 distance", + activationF: "est tenue \xE0 distance", + actif: "est tenu \xE0 distance de son adversaire, il ne peut pas l'attaquer", + actifF: "est tenue \xE0 distance de son adversaire, elle ne peut pas l'attaquer", + fin: "peut \xE0 nouveau attaquer son adversaire", + msgSave: "pouvoir \xE0 nouveau attaquer son adversaire", prejudiciable: true, generic: true, visible: true, entrave: true }, epeeDansante: { - activation: "fait apparaître une lame d'énergie lumineuse", - actif: "contrôle une lame d'énergie lumineuse", - fin: "La lame d'énergie lumineuse disparaît", + activation: "fait appara\xEEtre une lame d'\xE9nergie lumineuse", + actif: "contr\xF4le une lame d'\xE9nergie lumineuse", + fin: "La lame d'\xE9nergie lumineuse dispara\xEEt", dm: true, visible: true }, rapiereDansante: { - activation: "fait apparaître une rapière d'énergie lumineuse", - actif: "contrôle une rapière d'énergie lumineuse", - fin: "La rapière d'énergie lumineuse disparaît", + activation: "fait appara\xEEtre une rapi\xE8re d'\xE9nergie lumineuse", + actif: "contr\xF4le une rapi\xE8re d'\xE9nergie lumineuse", + fin: "La rapi\xE8re d'\xE9nergie lumineuse dispara\xEEt", dm: true, visible: true }, putrefaction: { - activation: "vient de contracter une sorte de lèpre fulgurante", - actif: "est en pleine putréfaction", - fin: "La putréfaction s'arrête.", - msgSave: "résister à la putréfaction", + activation: "vient de contracter une sorte de l\xE8pre fulgurante", + actif: "est en pleine putr\xE9faction", + fin: "La putr\xE9faction s'arr\xEAte.", + msgSave: "r\xE9sister \xE0 la putr\xE9faction", prejudiciable: true, dm: true, visible: true @@ -45254,38 +45840,38 @@ var COFantasy = COFantasy || function() { forgeron: { activation: "enflamme son arme", actif: "a une arme en feu", - fin: "L'arme n'est plus enflammée.", + fin: "L'arme n'est plus enflamm\xE9e.", dm: true, generic: true, visible: true }, armeEnflammee: { activation: "voit son arme prendre feu", - actif: "a une arme enflammée", - fin: "L'arme n'est plus enflammée.", + actif: "a une arme enflamm\xE9e", + fin: "L'arme n'est plus enflamm\xE9e.", dm: true, generic: true, visible: true }, armeGlacee: { activation: "voit son arme se couvrir de givre", - actif: "a une arme glacée", - fin: "L'arme n'est plus gelée.", + actif: "a une arme glac\xE9e", + fin: "L'arme n'est plus gel\xE9e.", dm: true, generic: true, visible: true }, armesEnflammees: { activation: "voit ses armes prendre feu", - actif: "a des armes enflammées", - fin: "Les armes ne sont plus enflammées.", + actif: "a des armes enflamm\xE9es", + fin: "Les armes ne sont plus enflamm\xE9es.", dm: true, visible: true }, dotGen: { activation: "subit un effet", - actif: "subit régulièrement des dégâts", - fin: "ne subit plus ces effets de dégâts", + actif: "subit r\xE9guli\xE8rement des d\xE9g\xE2ts", + fin: "ne subit plus ces effets de d\xE9g\xE2ts", dm: true, prejudiciable: true, generic: true @@ -45293,7 +45879,7 @@ var COFantasy = COFantasy || function() { rechargeGen: { activation: "doit maintenant attendre un peu avant de pouvoir le refaire", actif: "attend avant de pouvoir refaire une action", - fin: "a récupéré", + fin: "a r\xE9cup\xE9r\xE9", generic: true }, dmgArme: { @@ -45306,15 +45892,15 @@ var COFantasy = COFantasy || function() { flou: { activation: "devient flou", activationF: "devient floue", - actif: "apparaît flou", - actifF: "apparaît floue", + actif: "appara\xEEt flou", + actifF: "appara\xEEt floue", fin: "redevient net", visible: true }, agrandissement: { - activation: "se met à grandir", - actif: "est vraiment très grand", - actifF: "est vraiment très grande", + activation: "se met \xE0 grandir", + actif: "est vraiment tr\xE8s grand", + actifF: "est vraiment tr\xE8s grande", fin: "retrouve sa taille normale", visible: true }, @@ -45331,24 +45917,24 @@ var COFantasy = COFantasy || function() { visible: true }, intangibleInvisible: { - activation: "disparaît", + activation: "dispara\xEEt", actif: "est intangible et invisible", - fin: "réapparaît", + fin: "r\xE9appara\xEEt", visible: true }, sousTension: { - activation: "se charge d'énergie électrique", - actif: "est chargé d'énergie électrique", - actifF: "est chargée d'énergie électrique", - fin: "n'est plus chargé d'énergie électrique", - finF: "n'est plus chargée d'énergie électrique", + activation: "se charge d'\xE9nergie \xE9lectrique", + actif: "est charg\xE9 d'\xE9nergie \xE9lectrique", + actifF: "est charg\xE9e d'\xE9nergie \xE9lectrique", + fin: "n'est plus charg\xE9 d'\xE9nergie \xE9lectrique", + finF: "n'est plus charg\xE9e d'\xE9nergie \xE9lectrique", dm: true, visible: false }, strangulation: { - activation: "commence à étouffer", - actif: "est étranglé", - actifF: "est étranglée", + activation: "commence \xE0 \xE9touffer", + actif: "est \xE9trangl\xE9", + actifF: "est \xE9trangl\xE9e", fin: "respire enfin", msgSave: "pouvoir respirer", prejudiciable: true, @@ -45358,7 +45944,7 @@ var COFantasy = COFantasy || function() { }, ombreMortelle: { activation: "voit son ombre s'animer et l'attaquer !", - actif: "est une ombre animée", + actif: "est une ombre anim\xE9e", fin: "retrouve une ombre normale", dm: true, visible: true @@ -45367,7 +45953,7 @@ var COFantasy = COFantasy || function() { activation: "voit un double translucide sortir de lui", activationF: "voit un double translucide sortir d'elle", actif: "est un double translucide", - fin: "le double disparaît", + fin: "le double dispara\xEEt", dm: true, visible: true }, @@ -45375,20 +45961,20 @@ var COFantasy = COFantasy || function() { activation: "n'entend plus rien", actif: "est totalement sourd", actifF: "est totalement sourde", - fin: "peut à nouveau entendre" + fin: "peut \xE0 nouveau entendre" }, danseIrresistible: { - activation: "se met à danser", - actif: "danse malgré lui", - actifF: "danse malgré elle", - fin: "s'arrête de danser", - msgSave: "s'arrêter de danser", + activation: "se met \xE0 danser", + actif: "danse malgr\xE9 lui", + actifF: "danse malgr\xE9 elle", + fin: "s'arr\xEAte de danser", + msgSave: "s'arr\xEAter de danser", prejudiciable: true, visible: true }, confusion: { - activation: "ne sait plus très bien ce qu'il fait là", - activationF: "ne sait plus très bien ce qu'elle fait là", + activation: "ne sait plus tr\xE8s bien ce qu'il fait l\xE0", + activationF: "ne sait plus tr\xE8s bien ce qu'elle fait l\xE0", actif: "est en pleine confusion", fin: "retrouve ses esprits", msgSave: "retrouver ses esprits", @@ -45396,16 +45982,16 @@ var COFantasy = COFantasy || function() { visible: true }, murDeForce: { - activation: "fait apparaître un mur de force", - actif: "en entouré d'un mur de force", - actifF: "en entourée d'un mur de force", - fin: "voit son mur de force disparaître", + activation: "fait appara\xEEtre un mur de force", + actif: "en entour\xE9 d'un mur de force", + actifF: "en entour\xE9e d'un mur de force", + fin: "voit son mur de force dispara\xEEtre", visible: true }, asphyxie: { - activation: "commence à manquer d'air", - actif: "étouffe", - fin: "peut à nouveau respirer", + activation: "commence \xE0 manquer d'air", + actif: "\xE9touffe", + fin: "peut \xE0 nouveau respirer", msgSave: "pouvoir respirer normalement", prejudiciable: true, seulementVivant: true, @@ -45416,11 +46002,11 @@ var COFantasy = COFantasy || function() { forceDeGeant: { activation: "devient plus fort", activationE: "devient plus forte", - actif: "a une force de géant", + actif: "a une force de g\xE9ant", fin: "retrouve sa force normale" }, saignementsSang: { - activation: "commence à saigner du nez, des oreilles et des yeux", + activation: "commence \xE0 saigner du nez, des oreilles et des yeux", actif: "saigne de tous les orifices du visage", fin: "ne saigne plus", msgSave: "ne plus saigner", @@ -45430,70 +46016,70 @@ var COFantasy = COFantasy || function() { visible: true }, encaisserUnCoup: { - activation: "se place de façon à dévier un coup sur son armure", - actif: "est placé de façon à dévier un coup", - actifF: "est placée de façon à dévier un coup", + activation: "se place de fa\xE7on \xE0 d\xE9vier un coup sur son armure", + actif: "est plac\xE9 de fa\xE7on \xE0 d\xE9vier un coup", + actifF: "est plac\xE9e de fa\xE7on \xE0 d\xE9vier un coup", fin: "n'est plus en position pour encaisser un coup" }, seulContreTous: { - activation: "se place de façon à faire face à tous ses adversaires", + activation: "se place de fa\xE7on \xE0 faire face \xE0 tous ses adversaires", actif: "riposte", - fin: "ne fait plus face à tous ses adversaires" + fin: "ne fait plus face \xE0 tous ses adversaires" }, absorberUnCoup: { - activation: "se prépare à absorber un coup avec son bouclier", - actif: "est prêt à absorber un coup avec son bouclier", - actifF: "est prête à absorber un coup avec son bouclier", + activation: "se pr\xE9pare \xE0 absorber un coup avec son bouclier", + actif: "est pr\xEAt \xE0 absorber un coup avec son bouclier", + actifF: "est pr\xEAte \xE0 absorber un coup avec son bouclier", fin: "n'est plus en position de prendre le prochain coup sur son bouclier" }, absorberUnSort: { - activation: "se prépare à absorber un sort avec son bouclier", - actif: "est prêt à absorber un sort avec son bouclier", - actifF: "est prête à absorber un sort avec son bouclier", - fin: "n'est plus en position de se protéger d'un sort avec son bouclier" + activation: "se pr\xE9pare \xE0 absorber un sort avec son bouclier", + actif: "est pr\xEAt \xE0 absorber un sort avec son bouclier", + actifF: "est pr\xEAte \xE0 absorber un sort avec son bouclier", + fin: "n'est plus en position de se prot\xE9ger d'un sort avec son bouclier" }, nueeDInsectes: { - activation: "est attaqué par une nuée d'insectes", - activationF: "est attaquée par une nuée d'insectes", - actif: "est entouré d'une nuée d'insectes", - actifF: "est entourée d'une nuée d'insectes", - fin: "est enfin débarassé des insectes", - finF: "est enfin débarassée des insectes", - msgSave: "se débarasser des insectes", + activation: "est attaqu\xE9 par une nu\xE9e d'insectes", + activationF: "est attaqu\xE9e par une nu\xE9e d'insectes", + actif: "est entour\xE9 d'une nu\xE9e d'insectes", + actifF: "est entour\xE9e d'une nu\xE9e d'insectes", + fin: "est enfin d\xE9barass\xE9 des insectes", + finF: "est enfin d\xE9barass\xE9e des insectes", + msgSave: "se d\xE9barasser des insectes", prejudiciable: true, dm: true, visible: true }, nueeDeCriquets: { - activation: "est attaqué par une nuée de criquets", - activationF: "est attaquée par une nuée de criquets", - actif: "est entouré d'une nuée de criquets", - actifF: "est entourée d'une nuée de criquets", - fin: "est enfin débarassé des criquets", - finF: "est enfin débarassée des criquets", - msgSave: "se débarasser des criquets", + activation: "est attaqu\xE9 par une nu\xE9e de criquets", + activationF: "est attaqu\xE9e par une nu\xE9e de criquets", + actif: "est entour\xE9 d'une nu\xE9e de criquets", + actifF: "est entour\xE9e d'une nu\xE9e de criquets", + fin: "est enfin d\xE9barass\xE9 des criquets", + finF: "est enfin d\xE9barass\xE9e des criquets", + msgSave: "se d\xE9barasser des criquets", prejudiciable: true, dm: true, visible: true }, nueeDeScorpions: { - activation: "est attaqué par une nuée de scorpions", - activationF: "est attaquée par une nuée de scorpions", - actif: "est entouré d'une nuée de scorpions", - actifF: "est entourée d'une nuée de scorpions", - fin: "est enfin débarassé des scorpions", - finF: "est enfin débarassée des scorpions", - msgSave: "se débarasser des scorpions", + activation: "est attaqu\xE9 par une nu\xE9e de scorpions", + activationF: "est attaqu\xE9e par une nu\xE9e de scorpions", + actif: "est entour\xE9 d'une nu\xE9e de scorpions", + actifF: "est entour\xE9e d'une nu\xE9e de scorpions", + fin: "est enfin d\xE9barass\xE9 des scorpions", + finF: "est enfin d\xE9barass\xE9e des scorpions", + msgSave: "se d\xE9barasser des scorpions", prejudiciable: true, dm: true, visible: true }, toiles: { - activation: "voit des toiles d'araignées apparaître tout autour", - actif: "est bloqué par des toiles d'araignées", - actifF: "est bloquée par des toiles d'araignées", - fin: "se libère des toiles", - msgSave: "se libérer des toiles", + activation: "voit des toiles d'araign\xE9es appara\xEEtre tout autour", + actif: "est bloqu\xE9 par des toiles d'araign\xE9es", + actifF: "est bloqu\xE9e par des toiles d'araign\xE9es", + fin: "se lib\xE8re des toiles", + msgSave: "se lib\xE9rer des toiles", prejudiciable: true, statusMarker: 'cobweb', visible: true, @@ -45501,70 +46087,70 @@ var COFantasy = COFantasy || function() { }, prisonVegetale: { activation: "voit des plantes pousser et s'enrouler autour de ses jambes", - actif: "est bloqué par des plantes", - actifF: "est bloquée par des plantes", - fin: "se libère des plantes", - msgSave: "se libérer des plantes", + actif: "est bloqu\xE9 par des plantes", + actifF: "est bloqu\xE9e par des plantes", + fin: "se lib\xE8re des plantes", + msgSave: "se lib\xE9rer des plantes", prejudiciable: true, statusMarker: 'green', visible: true, entrave: true }, protectionContreLesElements: { - activation: "lance un sort de protection contre les éléments", - actif: "est protégé contre les éléments", - actifF: "est protégée contre les éléments", - fin: "n'est plus protégé contre les éléments", - finF: "n'est plus protégée contre les éléments" + activation: "lance un sort de protection contre les \xE9l\xE9ments", + actif: "est prot\xE9g\xE9 contre les \xE9l\xE9ments", + actifF: "est prot\xE9g\xE9e contre les \xE9l\xE9ments", + fin: "n'est plus prot\xE9g\xE9 contre les \xE9l\xE9ments", + finF: "n'est plus prot\xE9g\xE9e contre les \xE9l\xE9ments" }, masqueMortuaire: { activation: "prend l'apparence de la mort", - actif: "semble mort et animé", - actifF: "semble morte et animée", + actif: "semble mort et anim\xE9", + actifF: "semble morte et anim\xE9e", fin: "retrouve une apparence de vivant", visible: true }, masqueMortuaireAmeLiee: { - activation: "est lié à une apparence de la mort", - activationF: "est liée à une apparence de la mort", + activation: "est li\xE9 \xE0 une apparence de la mort", + activationF: "est li\xE9e \xE0 une apparence de la mort", actif: "semble en lien avec la mort", fin: "n'est plus en lien avec la mort" }, armeBrulante: { activation: "sent son arme lui chauffer la main", - actif: "se brûle la main sur son arme", + actif: "se br\xFBle la main sur son arme", fin: "sent son arme refroidir", dm: true }, armureBrulante: { activation: "sent son armure chauffer", - actif: "brûle dans son armure", + actif: "br\xFBle dans son armure", fin: "sent son armure refroidir", dm: true }, masqueDuPredateur: { - activation: "prend les traits d'un prédateur", - actif: "a les traits d'un prédateur", + activation: "prend les traits d'un pr\xE9dateur", + actif: "a les traits d'un pr\xE9dateur", fin: "redevient normal", finF: "redevient normale", visible: true }, masqueDuPredateurAmeLiee: { - activation: "est lié à une âme de prédateur", - activationF: "est liée à une âme de prédateur", - actif: "bénéficie d'un lien avec un prédateur", - fin: "le lien disparaît", + activation: "est li\xE9 \xE0 une \xE2me de pr\xE9dateur", + activationF: "est li\xE9e \xE0 une \xE2me de pr\xE9dateur", + actif: "b\xE9n\xE9ficie d'un lien avec un pr\xE9dateur", + fin: "le lien dispara\xEEt", visible: false }, aspectDeLaSuccube: { - activation: "acquiert une beauté fascinante", - actif: "est d'une beauté fascinante", - fin: "retrouve sa beauté habituelle", + activation: "acquiert une beaut\xE9 fascinante", + actif: "est d'une beaut\xE9 fascinante", + fin: "retrouve sa beaut\xE9 habituelle", visible: true }, aspectDuDemon: { - activation: "prend l’apparence d’un démon", - actif: "a l’apparence d’un démon", + activation: "prend l\x2019apparence d\x2019un d\xE9mon", + actif: "a l\x2019apparence d\x2019un d\xE9mon", fin: "retrouve son apparence habituelle", visible: true }, @@ -45574,124 +46160,125 @@ var COFantasy = COFantasy || function() { fin: "retrouve un sang normal" }, armeSecreteBarde: { - activation: "est déstabilisé", - activationF: "est déstabilisée", - actif: "est déstabilisé par une action de charme", - actifF: "est déstabilisée par une action de charme", + activation: "est d\xE9stabilis\xE9", + activationF: "est d\xE9stabilis\xE9e", + actif: "est d\xE9stabilis\xE9 par une action de charme", + actifF: "est d\xE9stabilis\xE9e par une action de charme", fin: "retrouve ses esprits", msgSave: "retrouver ses esprits", prejudiciable: true, visible: true }, regeneration: { - activation: "commence à se régénérer", - actif: "se régénère", - fin: "a fini de se régénérer", + activation: "commence \xE0 se r\xE9g\xE9n\xE9rer", + actif: "se r\xE9g\xE9n\xE8re", + fin: "a fini de se r\xE9g\xE9n\xE9rer", soins: true, visible: true }, arbreAnime: { - activation: "commence à bouger", - actif: "est un arbre animé", + activation: "commence \xE0 bouger", + actif: "est un arbre anim\xE9", fin: "redevient un arbre ordinaire", visible: true }, objetAnime: { - activation: "commence à bouger", - actif: "est un objet animé", + activation: "commence \xE0 bouger", + actif: "est un objet anim\xE9", fin: "redevient un objet ordinaire", visible: true }, magnetisme: { - activation: "contrôle le magnétisme", - actif: "contrôle le magnétisme", - fin: "relache son contrôle du magnétisme" + activation: "contr\xF4le le magn\xE9tisme", + actif: "contr\xF4le le magn\xE9tisme", + fin: "relache son contr\xF4le du magn\xE9tisme" }, hate: { - activation: "voit son métabolisme s'accélérer", + activation: "voit son m\xE9tabolisme s'acc\xE9l\xE9rer", actif: "peut faire une action de plus par tour", - fin: "retrouve un métabolisme normal (plus d'action supplémentaire)" + fin: "retrouve un m\xE9tabolisme normal (plus d'action suppl\xE9mentaire)" }, ailesCelestes: { - activation: "sent des ailes célestes lui pousser dans le dos", - actif: "possède des ailes célestes", - fin: "n'a plus d'aile céleste. Espérons qu'il était au sol...", - finF: "n'a plus d'aile céleste. Espérons qu'elle était au sol...", + activation: "sent des ailes c\xE9lestes lui pousser dans le dos", + actif: "poss\xE8de des ailes c\xE9lestes", + fin: "n'a plus d'aile c\xE9leste. Esp\xE9rons qu'il \xE9tait au sol...", + finF: "n'a plus d'aile c\xE9leste. Esp\xE9rons qu'elle \xE9tait au sol...", visible: true }, sanctuaire: { - activation: "lance un sort de sanctuaire", - actif: "est protégé par un sanctuaire", - actifF: "est protégée par un sanctuaire", - fin: "n'est plus protégé par le sanctuaire", - finF: "n'est plus protégée par le sanctuaire" + activation: "est prot\xE9g\xE9 par un sanctuaire", + activationF: "est prot\xE9g\xE9e par un sanctuaire", + actif: "est prot\xE9g\xE9 par un sanctuaire", + actifF: "est prot\xE9g\xE9e par un sanctuaire", + fin: "n'est plus prot\xE9g\xE9 par le sanctuaire", + finF: "n'est plus prot\xE9g\xE9e par le sanctuaire" }, rechargeSouffle: { activation: "doit maintenant attendre un peu avant de pouvoir le refaire", actif: "attend avant de pouvoir refaire un souffle", - fin: "a récupéré" + fin: "a r\xE9cup\xE9r\xE9" }, paralysieRoublard: { - activation: "est paralysé par la douleur", - activationF: "est paralysée par la douleur", - actif: "ne peut pas attaquer ni se déplacer", - fin: "peut à nouveau attaquer et se déplacer", - msgSave: "résister à la douleur", + activation: "est paralys\xE9 par la douleur", + activationF: "est paralys\xE9e par la douleur", + actif: "ne peut pas attaquer ni se d\xE9placer", + fin: "peut \xE0 nouveau attaquer et se d\xE9placer", + msgSave: "r\xE9sister \xE0 la douleur", prejudiciable: true, seulementVivant: true, visible: true, entrave: true }, mutationOffensive: { - activation: "échange une partie de son corps avec celle d'une créature monstrueuse", - actif: "possède un appendice monstrueux", + activation: "\xE9change une partie de son corps avec celle d'une cr\xE9ature monstrueuse", + actif: "poss\xE8de un appendice monstrueux", fin: "retrouve un corps normal", visible: true }, formeDArbre: { activation: "se transorme en arbre", - actif: "est transformé en arbre", - actifF: "est transformée en arbre", + actif: "est transform\xE9 en arbre", + actifF: "est transform\xE9e en arbre", fin: "retrouve sa forme normale", visible: true }, statueDeBois: { activation: "se transforme en statue de bois", - actif: "est transformé en statue de bois", - actifF: "est transformée en statue de bois", + actif: "est transform\xE9 en statue de bois", + actifF: "est transform\xE9e en statue de bois", fin: "retrouve sa forme normale", - msgSave: "ne plus être une statue de bois", + msgSave: "ne plus \xEAtre une statue de bois", prejudiciable: true, visible: true }, clignotement: { - activation: "disparaît, puis réapparaît", + activation: "dispara\xEEt, puis r\xE9appara\xEEt", actif: "clignote", - fin: "ne disparaît plus", + fin: "ne dispara\xEEt plus", visible: true }, agitAZeroPV: { - activation: "continue à agir malgré les blessures", - actif: "devrait être à terre", + activation: "continue \xE0 agir malgr\xE9 les blessures", + actif: "devrait \xEAtre \xE0 terre", fin: "subit l'effet de ses blessures", visible: true }, predateurConjure: { - activation: "apparaît depuis un autre plan", - actif: "est un prédateur conjuré", - fin: "disparaît", + activation: "appara\xEEt depuis un autre plan", + actif: "est un pr\xE9dateur conjur\xE9", + fin: "dispara\xEEt", dm: true }, champDeProtection: { - activation: "devient protégé par un champ télékinétique", - actif: "est protégé par un champ télékinétique", - actifF: "est protégée par un champ télékinétique", + activation: "devient prot\xE9g\xE9 par un champ t\xE9l\xE9kin\xE9tique", + actif: "est prot\xE9g\xE9 par un champ t\xE9l\xE9kin\xE9tique", + actifF: "est prot\xE9g\xE9e par un champ t\xE9l\xE9kin\xE9tique", fin: "n'est plus sous l'effet d'un champ de protection", }, attaqueArmeeConjuree: { - activation: "se bat contre une armée conjurée", - actif: "se bat contre une armée conjurée", - fin: "ne se bat plus contre l'armée conjurée" + activation: "se bat contre une arm\xE9e conjur\xE9e", + actif: "se bat contre une arm\xE9e conjur\xE9e", + fin: "ne se bat plus contre l'arm\xE9e conjur\xE9e" }, rechargeDuKiai: { activation: "pousse un kiai", @@ -45701,71 +46288,71 @@ var COFantasy = COFantasy || function() { memePasMalBonus: { activation: "enrage suite au coup critique", actif: "a subit un coup critique", - fin: "ne bénéficie plus des effets de même pas mal" + fin: "ne b\xE9n\xE9ficie plus des effets de m\xEAme pas mal" }, attaqueRisquee: { - activation: "fait une attaque risquée", - actif: "s'est mis en danger par une attaque risquée", - fin: "retrouve une position moins risquée", + activation: "fait une attaque risqu\xE9e", + actif: "s'est mis en danger par une attaque risqu\xE9e", + fin: "retrouve une position moins risqu\xE9e", }, peauDePierreMag: { activation: "transforme sa peau en pierre", - actif: "voit ses dégâts réduits par sa Peau de pierre", + actif: "voit ses d\xE9g\xE2ts r\xE9duits par sa Peau de pierre", fin: "retrouve sa peau normale", visible: true }, expose: { activation: "s'expose aux attaques de sa cible", - actif: "est exposé aux attaques de son adversaire", - actifF: "est exposée aux attaques de son adversaire", - fin: "n'est plus exposé", - finF: "n'est plus exposée", + actif: "est expos\xE9 aux attaques de son adversaire", + actifF: "est expos\xE9e aux attaques de son adversaire", + fin: "n'est plus expos\xE9", + finF: "n'est plus expos\xE9e", msgSave: "ne plus s'exposer", prejudiciable: true }, effetRetarde: { - activation: "il va bientôt se produire quelque chose", - actif: "s'attend à un effet", - fin: "effet retardé activé", + activation: "il va bient\xF4t se produire quelque chose", + actif: "s'attend \xE0 un effet", + fin: "effet retard\xE9 activ\xE9", generic: true, prejudiciable: true }, messageRetarde: { - activation: "il va bientôt se produire quelque chose", - actif: "s'attend à un effet", - fin: "effet activé", + activation: "il va bient\xF4t se produire quelque chose", + actif: "s'attend \xE0 un effet", + fin: "effet activ\xE9", generic: true }, detectionDeLInvisible: { - activation: "voit les choses invibles et cachées", - actif: "détecte l'invisible", + activation: "voit les choses invibles et cach\xE9es", + actif: "d\xE9tecte l'invisible", fin: "ne voit plus les choses invisibles", }, bonusAttaqueTemp: { activation: "affecte son attaque", - actif: "a son attaque affectée", + actif: "a son attaque affect\xE9e", fin: "retrouve son attaque normale", }, enerve: { - activation: "est énervé par ces railleries", - activationF: "est énervée par ces railleries", - actif: "est énervé", - actifF: "est énervée", + activation: "est \xE9nerv\xE9 par ces railleries", + activationF: "est \xE9nerv\xE9e par ces railleries", + actif: "est \xE9nerv\xE9", + actifF: "est \xE9nerv\xE9e", fin: "retrouve son calme", msgSave: "retrouver son calme", prejudiciable: true, visible: true }, cercleDeProtection: { - activation: "est protégé par le Cercle de protection", - activationF: "est protégée par le Cercle de protection", + activation: "est prot\xE9g\xE9 par le Cercle de protection", + activationF: "est prot\xE9g\xE9e par le Cercle de protection", actif: "est dans le Cercle de protection", fin: "sort du Cercle de protection", }, tenebres: { - activation: "lance un sort de Ténèbres", - actif: "maintient un sort de Ténèbres", - fin: "les ténèbres se dissipent", + activation: "lance un sort de T\xE9n\xE8bres", + actif: "maintient un sort de T\xE9n\xE8bres", + fin: "les t\xE9n\xE8bres se dissipent", visible: true }, brumes: { @@ -45775,12 +46362,12 @@ var COFantasy = COFantasy || function() { visible: true }, progresserACouvert: { - activation: "est à couvert de bouclier", - actif: "est à couvert de bouclier", - fin: "n'est plus à couvert de bouclier" + activation: "est \xE0 couvert de bouclier", + actif: "est \xE0 couvert de bouclier", + fin: "n'est plus \xE0 couvert de bouclier" }, cyclone: { - activation: "se transforme en tourbillon de matière élémentaire", + activation: "se transforme en tourbillon de mati\xE8re \xE9l\xE9mentaire", actif: "est en cyclone", fin: "retrouve sa forme habituelle", visible: true @@ -45791,57 +46378,57 @@ var COFantasy = COFantasy || function() { fin: "voit le temps reprendre son cours normal", }, armeeDesMorts: { - activation: "invoque d'innombrables squelettes émergeant du sol", + activation: "invoque d'innombrables squelettes \xE9mergeant du sol", actif: "invoque d'innombrables squelettes", fin: "laisse les morts en paix", visible: true }, demonInvoque: { - activation: "apparaît depuis un autre plan", - actif: "est un démon invoqué", - fin: "disparaît", + activation: "appara\xEEt depuis un autre plan", + actif: "est un d\xE9mon invoqu\xE9", + fin: "dispara\xEEt", dm: true }, degradationZombie: { - activation: "se relève d'entre les morts", - actif: "est un zombie animé", - fin: "tombe en poussière", + activation: "se rel\xE8ve d'entre les morts", + actif: "est un zombie anim\xE9", + fin: "tombe en poussi\xE8re", dm: true }, hemorragie: { - activation: "saigne à la moindre blessure", - actif: "saigne à la moindre blessure", - fin: "soigne son hémorragie", - msgSave: "guérir de son hémorragie", + activation: "saigne \xE0 la moindre blessure", + actif: "saigne \xE0 la moindre blessure", + fin: "soigne son h\xE9morragie", + msgSave: "gu\xE9rir de son h\xE9morragie", prejudiciable: true }, lienDeSang: { - activation: "est lié par le sang", - activationF: "est liée par le sang", + activation: "est li\xE9 par le sang", + activationF: "est li\xE9e par le sang", actif: "a un lien de sang", fin: "perd son lien de sang", - msgSave: "ne plus être lié par le sang", + msgSave: "ne plus \xEAtre li\xE9 par le sang", prejudiciable: true }, tenirADistance: { - activation: "utilise son allonge pour tenir ses ennemis à distance", - actif: "utilise son allonge pour tenir ses ennemis à distance", - fin: "ne tient plus ses ennemis à distance" + activation: "utilise son allonge pour tenir ses ennemis \xE0 distance", + actif: "utilise son allonge pour tenir ses ennemis \xE0 distance", + fin: "ne tient plus ses ennemis \xE0 distance" }, reactionViolente: { - activation: "est pris de folie et attaque la personne qui s'est moquée de lui", - activationF: "est prise de folie et attaque la personne qui s'est moquée d'elle", - actif: "a une réaction violente et doit attaquer", + activation: "est pris de folie et attaque la personne qui s'est moqu\xE9e de lui", + activationF: "est prise de folie et attaque la personne qui s'est moqu\xE9e d'elle", + actif: "a une r\xE9action violente et doit attaquer", fin: "reprend son calme", - msgSave: "résister à la provocation", + msgSave: "r\xE9sister \xE0 la provocation", prejudiciable: true, }, poisonAffaiblissantLatent: { - activation: "sent qu'un poison commence à se répandre dans ses veines", - actif: "est empoisonné, mais l'effet du poison ne se fait pas encore sentir", - actifF: "est empoisonnée, mais l'effet du poison ne se fait pas encore sentir", + 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ésister au poison", + msgSave: "r\xE9sister au poison", prejudiciable: true, seulementVivant: true, }, @@ -45882,23 +46469,23 @@ var COFantasy = COFantasy || function() { return (patternAttributEffetsTemp.test(name)); } - //On sait déjà que le nom a passé le test estEffetTemp + //On sait d\xE9j\xE0 que le nom a pass\xE9 le test estEffetTemp function effetTempOfAttribute(attr) { let ef = attr.get('name'); if (ef === undefined || messageEffetTemp[ef]) return ef; - //D'abord on enlève le nom du token + //D'abord on enl\xE8ve le nom du token let pu = ef.indexOf('_'); if (pu > 0) { ef = ef.substring(0, pu); if (messageEffetTemp[ef]) return ef; } - //Ensuite on enlève les parties entre parenthèse pour les effets génériques + //Ensuite on enl\xE8ve les parties entre parenth\xE8se pour les effets g\xE9n\xE9riques pu = ef.indexOf('('); if (pu > 0) { ef = ef.substring(0, pu); if (messageEffetTemp[ef]) return ef; } - error("Impossible de déterminer l'effet correspondant à " + ef, attr); + error("Impossible de d\xE9terminer l'effet correspondant \xE0 " + ef, attr); } function messageOfEffetTemp(effetC) { @@ -45910,61 +46497,61 @@ var COFantasy = COFantasy || function() { res = messageEffetTemp[ef]; return res; } - error("Effet temporaire non trouvé", effetC); + error("Effet temporaire non trouv\xE9", effetC); } const messageEffetCombat = { a0PVDepuis: { - activation: "est à 0 PV", - actif: "est à 0 PV", + activation: "est \xE0 0 PV", + actif: "est \xE0 0 PV", fin: "" }, armureMagique: { - activation: "est entouré d'un halo magique", - activationF: "est entourée d'un halo magique", - actif: "est protégé par une armure magique", - actifF: "est protégée par une armure magique", - fin: "n'est plus entouré d'un halo magique", - finF: "n'est plus entourée d'un halo magique" + activation: "est entour\xE9 d'un halo magique", + activationF: "est entour\xE9e d'un halo magique", + actif: "est prot\xE9g\xE9 par une armure magique", + actifF: "est prot\xE9g\xE9e par une armure magique", + fin: "n'est plus entour\xE9 d'un halo magique", + finF: "n'est plus entour\xE9e d'un halo magique" }, armureDuMage: { - activation: "fait apparaître un nuage magique argenté qui le protège", - activationF: "fait apparaître un nuage magique argenté qui la protège", - actif: "est entouré d'une armure du mage", - actifF: "est entourée d'une armure du mage", + activation: "fait appara\xEEtre un nuage magique argent\xE9 qui le prot\xE8ge", + activationF: "fait appara\xEEtre un nuage magique argent\xE9 qui la prot\xE8ge", + actif: "est entour\xE9 d'une armure du mage", + actifF: "est entour\xE9e d'une armure du mage", fin: "n'a plus son armure du mage" }, armureDEau: { - activation: "fait apparaître une couche d'eau de quelques centimètres qui le protège", - activationF: "fait apparaître une couche d'eau de quelques centimètres qui la protège", - actif: "est entouré d'une armure d'eau'", - actifF: "est entourée d'une armure d'eau'", + activation: "fait appara\xEEtre une couche d'eau de quelques centim\xE8tres qui le prot\xE8ge", + activationF: "fait appara\xEEtre une couche d'eau de quelques centim\xE8tres qui la prot\xE8ge", + actif: "est entour\xE9 d'une armure d'eau'", + actifF: "est entour\xE9e d'une armure d'eau'", fin: "n'a plus son armure d'eau'" }, armeDArgent: { - activation: "crée une arme d'argent et de lumière", - actif: "possède une arme d'argent et de lumière", - fin: "ne possède plus d'arme d'argent et de lumière", + activation: "cr\xE9e une arme d'argent et de lumi\xE8re", + actif: "poss\xE8de une arme d'argent et de lumi\xE8re", + fin: "ne poss\xE8de plus d'arme d'argent et de lumi\xE8re", dm: true }, attaqueAOutrance: { - activation: "attaque à outrance", - actif: "attaque à outrance", + activation: "attaque \xE0 outrance", + actif: "attaque \xE0 outrance", fin: "attaque normalement", }, - bonusInitEmbuscade: { //Effet interne pour la capacité Surveillance + 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: "" }, criDeGuerre: { activation: "pousse son cri de guerre", - actif: "a effrayé ses adversaires", + actif: "a effray\xE9 ses adversaires", fin: "" }, criDuPredateur: { activation: "pousse un hurlement effrayant", - actif: "a libéré son âme de prédateur", + actif: "a lib\xE9r\xE9 son \xE2me de pr\xE9dateur", fin: "" }, danseDesLames: { @@ -45973,22 +46560,22 @@ var COFantasy = COFantasy || function() { fin: "termine sa danse des lames" }, detournerLeRegard: { - activation: "détourne le regard", - actif: "détourne le regard", + activation: "d\xE9tourne le regard", + actif: "d\xE9tourne le regard", fin: "regarde normalement", }, enflamme: { activation: "prend feu !", actif: "est en feu", - fin: "les flammes s'éteignent", + fin: "les flammes s'\xE9teignent", dm: true, statusMarker: 'red', }, enrage: { - activation: "devient enragé", - activationF: "devient enragée", - actif: "est enragé", - actifF: "est enragée", + activation: "devient enrag\xE9", + activationF: "devient enrag\xE9e", + actif: "est enrag\xE9", + actifF: "est enrag\xE9e", fin: "retrouve son calme", msgSave: "retrouver son calme", }, @@ -45999,17 +46586,17 @@ var COFantasy = COFantasy || function() { fin: "retrouve son calme" }, protectionContreLeMal: { - activation: "reçoit une bénédiction de protection contre le mal", - actif: "est protégé contre le mal", - actifF: "est protégée contre le mal", - fin: "n'est plus protégé contre le mal", - finF: "n'est plus protégée contre le mal", + activation: "re\xE7oit une b\xE9n\xE9diction de protection contre le mal", + actif: "est prot\xE9g\xE9 contre le mal", + actifF: "est prot\xE9g\xE9e contre le mal", + fin: "n'est plus prot\xE9g\xE9 contre le mal", + finF: "n'est plus prot\xE9g\xE9e contre le mal", }, putrefactionOutreTombe: { activation: "sent ses chairs pourrir", - actif: "subit le contrecoup d'une putréfaction", - fin: "se remet de la putréfaction", - msgSave: "ne plus être putréfié", + actif: "subit le contrecoup d'une putr\xE9faction", + fin: "se remet de la putr\xE9faction", + msgSave: "ne plus \xEAtre putr\xE9fi\xE9", prejudiciable: true, dm: true }, @@ -46031,8 +46618,8 @@ var COFantasy = COFantasy || function() { fin: '' }, defiSamourai: { - activation: "lance un défi", - actif: "a lancé un défi", + activation: "lance un d\xE9fi", + actif: "a lanc\xE9 un d\xE9fi", fin: '' }, agrippe: { @@ -46041,12 +46628,12 @@ var COFantasy = COFantasy || function() { fin: "lache sa cible" }, estAgrippePar: { - activation: "est agrippé", - activationF: "est agrippée", - actif: "est agrippé", - actifF: "est agrippée", - fin: "se libère", - msgSave: "se libérer", + activation: "est agripp\xE9", + activationF: "est agripp\xE9e", + actif: "est agripp\xE9", + actifF: "est agripp\xE9e", + fin: "se lib\xE8re", + msgSave: "se lib\xE9rer", entrave: true }, devore: { @@ -46059,8 +46646,8 @@ var COFantasy = COFantasy || function() { activationF: "est saisie", actif: "est saisi", actifF: "est saisie", - fin: "se libère", - msgSave: "se libérer", + fin: "se lib\xE8re", + msgSave: "se lib\xE9rer", entrave: true }, ecrase: { @@ -46073,34 +46660,34 @@ var COFantasy = COFantasy || function() { activationF: "est saisie", actif: "est saisi", actifF: "est saisie", - fin: "se libère", - msgSave: "se libérer", + fin: "se lib\xE8re", + msgSave: "se lib\xE9rer", entrave: true }, aGobe: { activation: "avale sa cible", - actif: "a avalé une créature vivante", - fin: "digère sa cible" + actif: "a aval\xE9 une cr\xE9ature vivante", + fin: "dig\xE8re sa cible" }, estGobePar: { - activation: "est avalé", - activationF: "est avalée", - actif: "est dans le ventre d'une créature", + activation: "est aval\xE9", + activationF: "est aval\xE9e", + actif: "est dans le ventre d'une cr\xE9ature", fin: "fin de la digestion, sort du ventre", msgSave: "sortir du ventre", entrave: true }, inconfort: { - activation: "commence à être gêné par son armure", - activationF: "commence à être gênée par son armure", - actif: "est gêné par son armure", - actifF: "est gênée par son armure", - fin: "réajuste son armure", + activation: "commence \xE0 \xEAtre g\xEAn\xE9 par son armure", + activationF: "commence \xE0 \xEAtre g\xEAn\xE9e par son armure", + actif: "est g\xEAn\xE9 par son armure", + actifF: "est g\xEAn\xE9e par son armure", + fin: "r\xE9ajuste son armure", }, noyade: { - activation: "commence à se noyer", + activation: "commence \xE0 se noyer", actif: "se noie", - fin: "peut à nouveau respirer", + fin: "peut \xE0 nouveau respirer", msgSave: "surnager", prejudiciable: true, seulementVivant: true, @@ -46108,8 +46695,8 @@ var COFantasy = COFantasy || function() { visible: true }, blessureQuiSaigne: { - activation: "reçoit une blessure qui saigne", - actif: "saigne à cause d'une blessure", + activation: "re\xE7oit une blessure qui saigne", + actif: "saigne \xE0 cause d'une blessure", fin: "saigne beaucoup moins", msgSave: "ne plus saigner", prejudiciable: true, @@ -46117,10 +46704,10 @@ var COFantasy = COFantasy || function() { }, poisonAffaiblissant: { activation: "sent le poison ralentir ses mouvements", - actif: "est empoisonné", - actifF: "est empoisonnée", + actif: "est empoisonn\xE9", + actifF: "est empoisonn\xE9e", fin: "le poison n'agit plus", - msgSave: "résister au poison", + msgSave: "r\xE9sister au poison", prejudiciable: true, seulementVivant: true, }, @@ -46142,16 +46729,16 @@ var COFantasy = COFantasy || function() { function effetCombatOfAttribute(attr) { let ef = attr.get('name'); if (ef === undefined || messageEffetCombat[ef]) return ef; - //D'abord on enlève le nom du token + //D'abord on enl\xE8ve le nom du token let pu = ef.indexOf('_'); if (pu > 0) { ef = ef.substring(0, pu); if (messageEffetCombat[ef]) return ef; } - error("Impossible de déterminer l'effet correspondant à " + ef, attr); + error("Impossible de d\xE9terminer l'effet correspondant \xE0 " + ef, attr); } - // Si un effet est prejudiciable, enlevé par délivrance + // Si un effet est prejudiciable, enlev\xE9 par d\xE9livrance const messageEffetIndetermine = { armesNaturelles: { activation: "se fait pousser griffes et crocs", @@ -46172,29 +46759,29 @@ var COFantasy = COFantasy || function() { }, constructionTailleHumaine: { activation: "rentre dans une construction de taille humaine.", - actif: "est un peu à l'étroit, le bâtiment est trop petit", + actif: "est un peu \xE0 l'\xE9troit, le b\xE2timent est trop petit", fin: "sort de la construction de taille humains." }, dominationPsy: { - activation: "est maintenant sous le contrôle de quelqu'un", + activation: "est maintenant sous le contr\xF4le de quelqu'un", actif: "est sous l'effet d'une domination psy", - fin: "retrouve le contrôle de son corps", + fin: "retrouve le contr\xF4le de son corps", prejudiciable: true, }, fievreux: { - activation: "se sent fiévreux", - activationF: "se sent fiévreuse", - actif: "est fiévreux", - actifF: "est fiévreuse", + activation: "se sent fi\xE9vreux", + activationF: "se sent fi\xE9vreuse", + actif: "est fi\xE9vreux", + actifF: "est fi\xE9vreuse", fin: "se sent mieux", prejudiciable: true }, foretVivanteEnnemie: { - activation: "est gêné par la forêt", - activationF: "est gênée par la forêt", - actif: "est désorienté par la forêt", - actifF: "est désorientée par la forêt", - fin: "se retrouve dans une forêt normale", + activation: "est g\xEAn\xE9 par la for\xEAt", + activationF: "est g\xEAn\xE9e par la for\xEAt", + actif: "est d\xE9sorient\xE9 par la for\xEAt", + actifF: "est d\xE9sorient\xE9e par la for\xEAt", + fin: "se retrouve dans une for\xEAt normale", entrave: true }, grandeTaille: { @@ -46205,9 +46792,9 @@ var COFantasy = COFantasy || function() { fin: "retrouve sa taille normale" }, lameDeLigneePerdue: { - activation: "perd sa lame de lignée", - actif: "a perdu sa lame de lignée", - fin: "retrouve sa lame de lignée", + activation: "perd sa lame de lign\xE9e", + actif: "a perdu sa lame de lign\xE9e", + fin: "retrouve sa lame de lign\xE9e", }, marcheSylvestre: { activation: "se deplace maintenant en terrain difficile", @@ -46220,8 +46807,8 @@ var COFantasy = COFantasy || function() { fin: "retrouve une peau normale" }, mutationEcaillesRouges: { - activation: "recouvre sa peau d'écailles rouges", - actif: "a la peau recouverte d'écailles rouges", + activation: "recouvre sa peau d'\xE9cailles rouges", + actif: "a la peau recouverte d'\xE9cailles rouges", fin: "retrouve une peau normale" }, mutationFourrureViolette: { @@ -46230,15 +46817,15 @@ var COFantasy = COFantasy || function() { fin: "retrouve une peau normale" }, mutationMusclesHypertrophies: { - activation: "devient plus musclé", - activationF: "devient plus musclée", - actif: "a les muscles hypertrophiés", + activation: "devient plus muscl\xE9", + activationF: "devient plus muscl\xE9e", + actif: "a les muscles hypertrophi\xE9s", fin: "retrouve des muscles normaux", }, mutationOuies: { - activation: "se fait pousser des ouïes", - actif: "possède des ouïes", - fin: "n'a plus d'ouïes" + activation: "se fait pousser des ou\xEFes", + actif: "poss\xE8de des ou\xEFes", + fin: "n'a plus d'ou\xEFes" }, mutationSangNoir: { activation: "prend un teint plus sombre", @@ -46259,8 +46846,8 @@ var COFantasy = COFantasy || function() { }, presenceGlaciale: { activation: "transforme son corps en glace vivante", - actif: "est formé de glace", - actifF: "est formée de glace", + actif: "est form\xE9 de glace", + actifF: "est form\xE9e de glace", fin: "retrouve un corps normal", }, sensDuDevoir: { @@ -46270,12 +46857,12 @@ var COFantasy = COFantasy || function() { }, sixiemeSens: { activation: "fait un rituel de divination", - actif: "sait un peu à l'avance ce qu'il va se passer", + actif: "sait un peu \xE0 l'avance ce qu'il va se passer", fin: "l'effet du rituel de divination prend fin", }, espaceExigu: { activation: "entre dans un espace exigu.", - actif: "est à l'étroit.", + actif: "est \xE0 l'\xE9troit.", fin: "sort de l'espace exigu." }, sangDeLArbreCoeur: { @@ -46283,36 +46870,36 @@ var COFantasy = COFantasy || function() { actif: "a bu une potion de Sang de l'Arbre-Coeur", fin: "les effets de la potion de Sang de l'Arbre-Coeur diminuent un peu" }, - ondesCorruptrices: { //nombre, à mettre avec !cof-effet ondesCorruptrices 2 - activation: "se sent nauséeux", - activationF: "se sent nauséeuse", - actif: "se sent nauséeux", - actifF: "se sent nauséeuse", + ondesCorruptrices: { //nombre, \xE0 mettre avec !cof-effet ondesCorruptrices 2 + activation: "se sent naus\xE9eux", + activationF: "se sent naus\xE9euse", + actif: "se sent naus\xE9eux", + actifF: "se sent naus\xE9euse", fin: "se sent un peu mieux", prejudiciable: true }, petrifie: { activation: "se change en pierre", - actif: "est transformé en pierre", - actifF: "est transformée en pierre", - fin: "n'est plus pétrifié", - finF: "n'est plus pétrifiée", + actif: "est transform\xE9 en pierre", + actifF: "est transform\xE9e en pierre", + fin: "n'est plus p\xE9trifi\xE9", + finF: "n'est plus p\xE9trifi\xE9e", prejudiciable: true, - msgSave: "résister à la pétrification", + msgSave: "r\xE9sister \xE0 la p\xE9trification", }, poisonAffaiblissantLong: { activation: "sent le poison ralentir ses mouvements", - actif: "est empoisonné", - actifF: "est empoisonnée", + actif: "est empoisonn\xE9", + actifF: "est empoisonn\xE9e", fin: "le poison n'agit plus", - msgSave: "résister au poison", + msgSave: "r\xE9sister au poison", prejudiciable: true, seulementVivant: true, }, reactionAllergique: { - activation: "ressent de fortes démangeaisons", - actif: "est victime d'une réaction allergique", - fin: "les démangeaisons cessent", + activation: "ressent de fortes d\xE9mangeaisons", + actif: "est victime d'une r\xE9action allergique", + fin: "les d\xE9mangeaisons cessent", prejudiciable: true }, }; @@ -46326,13 +46913,13 @@ var COFantasy = COFantasy || function() { function effetIndetermineOfAttribute(attr) { let ef = attr.get('name'); if (ef === undefined || messageEffetIndetermine[ef]) return ef; - //D'abord on enlève le nom du token + //D'abord on enl\xE8ve le nom du token let pu = ef.indexOf('_'); if (pu > 0) { ef = ef.substring(0, pu); if (messageEffetIndetermine[ef]) return ef; } - error("Impossible de déterminer l'effet correspondant à " + ef, attr); + error("Impossible de d\xE9terminer l'effet correspondant \xE0 " + ef, attr); } function attributeExtending(charId, attrName, effetC, extension) { @@ -46344,10 +46931,10 @@ var COFantasy = COFantasy || function() { }); } - //Nom de l'effet, avec la partie générique, mais sans le nom de token + //Nom de l'effet, avec la partie g\xE9n\xE9rique, mais sans le nom de token function effetComplet(effet, attrName) { if (effet == attrName) return effet; - //On a un effet lié à un token ou bien un effet générique + //On a un effet li\xE9 \xE0 un token ou bien un effet g\xE9n\xE9rique if (attrName.charAt(effet.length) == '(') { let p = attrName.indexOf(')', effet.length); if (p > 0) return attrName.substring(0, p + 1); @@ -46388,7 +46975,7 @@ var COFantasy = COFantasy || function() { //alors dmg = '' et type = '' let valAttr = tokenAttribute(perso, effet + 'Valeur'); if (valAttr.length === 0) { - //Par défaut, 1d6 DM normaux + //Par d\xE9faut, 1d6 DM normaux dmgExpr = "1d6"; type = 'normal'; } else { @@ -46434,7 +47021,7 @@ var COFantasy = COFantasy || function() { count.v--; if (count.v === 0) callback(); }); - }); //fin sendChat du jet de dé + }); //fin sendChat du jet de d\xE9 } //asynchrone @@ -46465,7 +47052,7 @@ var COFantasy = COFantasy || function() { let expliquer = function(m) { addLineToFramedDisplay(display, m); }; - let msgPour = " pour ne pas prendre de dégâts de " + nameEffet; + let msgPour = " pour ne pas prendre de d\xE9g\xE2ts de " + nameEffet; let sujet = onGenre(perso, 'il', 'elle'); let msgReussite = ", " + sujet + " ne perd pas de PV ce tour"; let saveOpts = { @@ -46517,8 +47104,8 @@ var COFantasy = COFantasy || function() { let displaySoins = buildinline(soinRoll, 'normal', true); soigneToken(perso, soins, evt, function(s) { - if (s < soins) sendPerso(perso, "récupère tous ses PV."); - else sendPerso(perso, "récupère " + displaySoins + " PV."); + if (s < soins) sendPerso(perso, "r\xE9cup\xE8re tous ses PV."); + else sendPerso(perso, "r\xE9cup\xE8re " + displaySoins + " PV."); count--; if (count === 0) callback(); }, @@ -46526,7 +47113,7 @@ var COFantasy = COFantasy || function() { count--; if (count === 0) callback(); }); - }); //fin sendChat du jet de dé + }); //fin sendChat du jet de d\xE9 }); //fin iterTokensOfAttribute } @@ -46540,9 +47127,9 @@ var COFantasy = COFantasy || function() { return options; } - // gestion des effets qui se déclenchent à la fin de chaque tour - // N'ajoute pas evt à l'historique - // Asynchrone (à cause des saves par tour) + // 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) function changementDeTour(tour, attrs, evt, combat, pageId, options) { // Enlever les bonus d'un tour attrs = removeAllAttributes('limiteParTour', evt, attrs); @@ -46553,7 +47140,7 @@ var COFantasy = COFantasy || function() { attrs = removeAllAttributes('prescienceUtilisee', evt, attrs); attrs = removeAllAttributes('increvableHumainUtilise', evt, attrs); resetAttr(attrs, 'cercleDeProtectionActif', evt); - // Pour défaut dans la cuirasse, on diminue si la valeur est 2, et on supprime si c'est 1 + // Pour d\xE9faut dans la cuirasse, on diminue si la valeur est 2, et on supprime si c'est 1 let defautsDansLaCuirasse = allAttributesNamed(attrs, 'defautDansLaCuirasse'); defautsDansLaCuirasse.forEach(function(attr) { if (attr.get('current') < 2) { @@ -46585,7 +47172,7 @@ var COFantasy = COFantasy || function() { attr.set('current', 1); } }); - //Les tests ratés + //Les tests rat\xE9s let trTour = allAttributesNamed(attrs, 'testsRatesDuTour'); trTour.forEach(function(tr) { let curTr = tr.get('current'); @@ -46614,7 +47201,7 @@ var COFantasy = COFantasy || function() { attr.set('current', ve + 1); let veCharId = attr.get('characterid'); if (veCharId === undefined || veCharId === '') { - error("Attribut sans personnage associé", attr); + error("Attribut sans personnage associ\xE9", attr); return; } let veSeuil = parseInt(attr.get('max')); @@ -46629,9 +47216,9 @@ var COFantasy = COFantasy || function() { }; let testId = 'vapeursEthyliques_' + perso.token.id; testCaracteristique(perso, 'CON', veSeuil, testId, options, evt, function(testRes) { - let res = "tente un jet de CON " + veSeuil + " pour combattre les vapeurs éthyliques " + testRes.texte; + let res = "tente un jet de CON " + veSeuil + " pour combattre les vapeurs \xE9thyliques " + testRes.texte; if (testRes.reussite) { - res += " => réussi." + testRes.modifiers; + res += " => r\xE9ussi." + testRes.modifiers; let expliquer; if (attr.get('name') == 'vapeursEthyliques') { expliquer = function(s) { @@ -46645,14 +47232,14 @@ var COFantasy = COFantasy || function() { expliquer(res); diminueEbriete(perso, evt, expliquer); } else { - res += " => raté" + testRes.rerolls + testRes.modifiers; + res += " => rat\xE9" + testRes.rerolls + testRes.modifiers; sendPerso(perso, res); } }); }); }); // nouveau tour : enlever le statut surpris - // et faire les actions de début de tour + // et faire les actions de d\xE9but de tour let selected = []; updateNextInitSet.forEach(function(id) { selected.push({ @@ -46697,14 +47284,14 @@ var COFantasy = COFantasy || function() { }; dealDamage(perso, dmg, [], evt, false, {}, undefined, function(dmgDisplay, dmgFinal) { - sendPerso(perso, " est écrasé ! " + + sendPerso(perso, " est \xE9cras\xE9 ! " + onGenre(perso, 'Il', 'Elle') + " subit " + dmgDisplay + " DM"); }); } let enflammeAttr = tokenAttribute(perso, 'enflamme'); if (enflammeAttr.length > 0) { let enflamme = parseInt(enflammeAttr[0].get('current')); - // Pour ne pas faire les dégâts plusieurs fois (plusieurs tokens pour un même personnage), on utilise la valeur max de l'attribut + // Pour ne pas faire les d\xE9g\xE2ts plusieurs fois (plusieurs tokens pour un m\xEAme personnage), on utilise la valeur max de l'attribut let dernierTourEnflamme = parseInt(enflammeAttr[0].get('max')); if ((isNaN(dernierTourEnflamme) || dernierTourEnflamme < tour) && !isNaN(enflamme) && enflamme > 0) { @@ -46723,7 +47310,7 @@ var COFantasy = COFantasy || function() { display: roll }; if (getState(perso, 'mort')) { - sendChat('', "Le cadavre de " + nomPerso(perso) + " continue de brûler"); + sendChat('', "Le cadavre de " + nomPerso(perso) + " continue de br\xFBler"); } else { dealDamage(perso, dmgEnflamme, [], evt, false, {}, undefined, function(dmgDisplay, dmgFinal) { @@ -46732,7 +47319,7 @@ var COFantasy = COFantasy || function() { }); } if (d6Enflamme < 3) { - sendPerso(perso, ": les flammes s'éteignent"); + sendPerso(perso, ": les flammes s'\xE9teignent"); removeTokenAttr(perso, 'enflamme', evt); let ms = messageEffetCombat.enflamme.statusMarker; if (ms) { @@ -46749,14 +47336,14 @@ var COFantasy = COFantasy || function() { nbDes: 3 }); let dmg = { - type: 'normal', //correspond à de l'asphyxie + type: 'normal', //correspond \xE0 de l'asphyxie total: jet.val, display: jet.roll }; if (immuniseAsphyxie(perso)) dmg.type = 'acide'; dealDamage(perso, dmg, [], evt, false, {}, undefined, function(dmgDisplay, dmgFinal) { - sendPerso(perso, "est en train d'être digéré. " + onGenre(perso, 'Il', 'Elle') + " perd " + dmgDisplay + " PVs"); + sendPerso(perso, "est en train d'\xEAtre dig\xE9r\xE9. " + onGenre(perso, 'Il', 'Elle') + " perd " + dmgDisplay + " PVs"); }); } if (attributeAsBool(perso, 'blessureQuiSaigne') && @@ -46782,7 +47369,7 @@ var COFantasy = COFantasy || function() { let expliquer = function(m) { addLineToFramedDisplay(display, m); }; - let msgPour = " pour ne pas prendre de dégâts de noyade"; + let msgPour = " pour ne pas prendre de d\xE9g\xE2ts de noyade"; let sujet = onGenre(perso, 'il', 'elle'); let msgReussite = ", " + sujet + " ne perd pas de PV ce tour"; let saveOpts = { @@ -46838,7 +47425,7 @@ var COFantasy = COFantasy || function() { saufDMType = vitaliteSurnaturelle.substring(indexType + 1).split(','); soigneToken(perso, vitaliteSurnat, evt, function(s) { - whisperChar(perso.charId, 'récupère ' + s + ' PVs.'); + whisperChar(perso.charId, 'r\xE9cup\xE8re ' + s + ' PVs.'); }, function() {}, { saufDMType @@ -46850,7 +47437,7 @@ var COFantasy = COFantasy || function() { if (attributeAsBool(perso, 'sangDeLArbreCoeur') && !getState(perso, 'mort')) { soigneToken(perso, 5, evt, function(s) { - whisperChar(perso.charId, "régénère " + s + " PVs. (grâce à la potion de sang de l'Arbre Coeur)"); + whisperChar(perso.charId, "r\xE9g\xE9n\xE8re " + s + " PVs. (gr\xE2ce \xE0 la potion de sang de l'Arbre Coeur)"); }, function() {} ); @@ -46860,9 +47447,9 @@ var COFantasy = COFantasy || function() { increvableActif[0].remove(); let soins = randomInteger(6) + randomInteger(6) + randomInteger(6) + modCarac(perso, 'constitution'); soigneToken(perso, soins, evt, function(soinsEffectifs) { - let msgSoins = "est increvable et récupère "; + let msgSoins = "est increvable et r\xE9cup\xE8re "; if (soinsEffectifs == soins) msgSoins += soins + " points de vie"; - else msgSoins += soinsEffectifs + " PV (le jet était " + soins + ")"; + else msgSoins += soinsEffectifs + " PV (le jet \xE9tait " + soins + ")"; whisperChar(perso.charId, msgSoins); }); } @@ -46875,16 +47462,16 @@ var COFantasy = COFantasy || function() { }; perso.ignoreTouteRD = true; dealDamage(perso, r, [], evt, false, {}, [], function() { - // Vérification si le Zombie est toujours vivant + // V\xE9rification si le Zombie est toujours vivant let token = getObj('graphic', perso.token.id); - if (token) whisperChar(perso.charId, "se dégrade et perd 1 PV"); + if (token) whisperChar(perso.charId, "se d\xE9grade et perd 1 PV"); }); } }); setActiveToken(combat, undefined, evt); - initiative(selected, evt, true); // met Tour à la fin et retrie + initiative(selected, evt, true); // met Tour \xE0 la fin et retrie updateNextInitSet = new Set(); - // Saves à faire à la fin de chaque tour. Asynchrone, mais pas grave ? + // Saves \xE0 faire \xE0 la fin de chaque tour. Asynchrone, mais pas grave ? attrs.forEach(function(attr) { let attrName = attr.get('name'); let indexSave = attrName.indexOf('SaveParTour'); @@ -46896,12 +47483,12 @@ var COFantasy = COFantasy || function() { if (!cof_states[effetC] && !effetTemp && !estEffetCombat(effetC)) return; let carac = attr.get('current'); if (!isCarac(carac)) { - error("Save par tour " + attrName + " mal formé", carac); + error("Save par tour " + attrName + " mal form\xE9", carac); return; } let seuil = parseInt(attr.get('max')); if (isNaN(seuil)) { - error("Save par tour " + attrName + " mal formé", seuil); + error("Save par tour " + attrName + " mal form\xE9", seuil); return; } let charId = attr.get('characterid'); @@ -46930,7 +47517,7 @@ var COFantasy = COFantasy || function() { let se = stringOfEtat(effetC, perso); met = { etat: true, - msgSave: "ne plus être " + se, + msgSave: "ne plus \xEAtre " + se, fin: "n'est plus " + se, actif: "est toujours " + se }; @@ -46938,7 +47525,7 @@ var COFantasy = COFantasy || function() { let msgPour = " pour "; if (met.msgSave) msgPour += met.msgSave; else { - msgPour += "ne plus être sous l'effet de "; + msgPour += "ne plus \xEAtre sous l'effet de "; if (effetC.startsWith('dotGen(')) msgPour += effetC.substring(7, effetC.indexOf(')')); else msgPour += effetC; @@ -47024,7 +47611,7 @@ var COFantasy = COFantasy || function() { //Pour chaque token representant ce perso allPersos.forEach(function(perso) { if (perso.charId != charId) return; - //On cherche ensuite les tokens à portee + //On cherche ensuite les tokens \xE0 portee allPersos.forEach(function(target) { if (target.token.id == perso.token.id) return; let tokRepresents = target.charId; @@ -47053,19 +47640,19 @@ var COFantasy = COFantasy || function() { targetLine += " --target " + tokId; }); if (targetLine != "") - sendChat('player|' + gmId, "!cof-dmg 3d6" + targetLine + " --titre Dégâts des morts-vivants animés"); + sendChat('player|' + gmId, "!cof-dmg 3d6" + targetLine + " --titre D\xE9g\xE2ts des morts-vivants anim\xE9s"); targetLine = ""; Object.keys(degatsArmeeDefense).forEach(function(tokId) { targetLine += " --target " + tokId; }); if (targetLine != "") - sendChat('player|' + gmId, "!cof-dmg 1d6" + targetLine + " --titre Dégâts des morts-vivants animés sur les cibles qui les combattent"); + sendChat('player|' + gmId, "!cof-dmg 1d6" + targetLine + " --titre D\xE9g\xE2ts des morts-vivants anim\xE9s sur les cibles qui les combattent"); removeAllAttributes("defenseArmeeDesMorts", evt, attrs); if (stateCOF.prescience) { - //On affiche la prescience aux joueurs concernés + //On affiche la prescience aux joueurs concern\xE9s allPersos.forEach(function(perso) { if (capaciteDisponible(perso, 'prescience', 'combat')) { - whisperChar(perso.charId, "Possibilité d'utiliser la " + boutonSimple('!cof-prescience ' + perso.token.id + ' --mana 2', "Prescience")); + whisperChar(perso.charId, "Possibilit\xE9 d'utiliser la " + boutonSimple('!cof-prescience ' + perso.token.id + ' --mana 2', "Prescience")); } }); stateCOF.nextPrescience = { @@ -47086,7 +47673,7 @@ var COFantasy = COFantasy || function() { } //evt a un champ attributes et un champ deletedAttributes - //evt n'est pas ajouté à l'historique dans cette fonction + //evt n'est pas ajout\xE9 \xE0 l'historique dans cette fonction function nextTurnOfActive(active, attrs, evt, combat, pageId, options) { if (active === undefined) return; if (active.id == "-1" && active.custom == "Tour") { //Nouveau tour @@ -47099,8 +47686,8 @@ var COFantasy = COFantasy || function() { }; evt.combat.tour = tour - 1; evt.updateNextInitSet = updateNextInitSet; - active.pr = tour - 1; // préparation au calcul de l'undo - sendChat("GM", "Début du tour " + tour); + active.pr = tour - 1; // pr\xE9paration au calcul de l'undo + sendChat("GM", "D\xE9but du tour " + tour); combat.tour = tour; combat.init = 1000; changementDeTour(tour, attrs, evt, combat, pageId, options); @@ -47163,7 +47750,7 @@ var COFantasy = COFantasy || function() { nbDe: 1, de: 4 }, 'feu', - "brûle dans son armure", evt, { + "br\xFBle dans son armure", evt, { valeur: 'armureBrulanteValeur' }, callBack); return; @@ -47171,7 +47758,7 @@ var COFantasy = COFantasy || function() { degatsParTour(charId, pageId, effet, attrName, { cst: 1 }, 'normal', - "est piqué par les insectes", evt, { + "est piqu\xE9 par les insectes", evt, { valeur: 'nueeDInsectesValeur' }, callBack); return; @@ -47179,31 +47766,31 @@ var COFantasy = COFantasy || function() { degatsParTour(charId, pageId, effet, attrName, { cst: 2 }, 'normal', - "est piqué par les criquets", evt, {}, callBack); + "est piqu\xE9 par les criquets", evt, {}, callBack); return; case 'nueeDeScorpions': //prend 1D6 DM degatsParTour(charId, pageId, effet, attrName, { nbDe: 1, de: 6 }, 'normal', - "est piqué par les scorpions", evt, {}, callBack); + "est piqu\xE9 par les scorpions", evt, {}, callBack); return; case 'armeBrulante': //prend 1 DM degatsParTour(charId, pageId, effet, attrName, { cst: 1 }, 'feu', - "se brûle avec son arme", evt, { + "se br\xFBle avec son arme", evt, { valeur: 'armeBrulanteValeur' }, callBack); return; case 'regeneration': //soigne - soigneParTour(charId, pageId, effet, attrName, 3, "régénère", evt, { + soigneParTour(charId, pageId, effet, attrName, 3, "r\xE9g\xE9n\xE8re", evt, { valeur: 'regenerationValeur' }, callBack); return; case 'strangulation': let nameDureeStrang = 'dureeStrangulation'; - if (effet != attrName) { //concerne un token non lié + if (effet != attrName) { //concerne un token non li\xE9 nameDureeStrang += attrName.substring(attrName.indexOf('_')); } let dureeStrang = findObjs({ @@ -47223,18 +47810,18 @@ var COFantasy = COFantasy || function() { }); } else { let strangUpdate = dureeStrang[0].get('max'); - if (strangUpdate) { //a été mis à jour il y a au plus 1 tour + if (strangUpdate) { //a \xE9t\xE9 mis \xE0 jour il y a au plus 1 tour evt.attributes.push({ attribute: dureeStrang[0], current: dureeStrang[0].get('current'), max: strangUpdate }); dureeStrang[0].set('max', false); - } else { //Ça fait trop longtemps, on arrête tout + } else { //Ça fait trop longtemps, on arr\xEAte tout sendChar(charId, messageFin({ charId }, messageEffetTemp[effet]), true); - evt.attributes.pop(); //On enlève des attributs modifiés pour mettre dans les attribute supprimés. + evt.attributes.pop(); //On enl\xE8ve des attributs modifi\xE9s pour mettre dans les attribute supprim\xE9s. evt.deletedAttributes.push(attr); attr.remove(); evt.deletedAttributes.push(dureeStrang[0]); @@ -47322,14 +47909,14 @@ var COFantasy = COFantasy || function() { let displaySoins = buildinline(soinRoll, 'normal', true); soigneToken(cible, soins, evt, function(s) { - if (s < soins) sendPerso(cible, "récupère tous ses PV."); + if (s < soins) sendPerso(cible, "r\xE9cup\xE8re tous ses PV."); else if (s == soins) - sendPerso(cible, "récupère " + displaySoins + " PV."); + sendPerso(cible, "r\xE9cup\xE8re " + displaySoins + " PV."); else - sendPerso(cible, "récupère " + s + " PV. (Le jet était " + displaySoins + ")"); + sendPerso(cible, "r\xE9cup\xE8re " + s + " PV. (Le jet \xE9tait " + displaySoins + ")"); fin(); }, fin); - }); //fin sendChat du jet de dé + }); //fin sendChat du jet de d\xE9 }); }); return; @@ -47340,13 +47927,14 @@ var COFantasy = COFantasy || function() { } } - //Appelé si le turn order change, mais aussi en interne - //si evt est déjà défini, ne l'ajoute pas au turn order + //Appel\xE9 si le turn order change, mais aussi en interne + //si evt est d\xE9j\xE0 d\xE9fini, ne l'ajoute pas au turn order function nextTurn(cmp, options, evt) { if (!cmp.get('initiativepage')) return; let combat = stateCOF.combat; if (!combat) { error("Le script n'est pas en mode combat", cmp); + return; } let turnOrder = cmp.get('turnorder'); let pageId = combat.pageId; @@ -47400,7 +47988,7 @@ var COFantasy = COFantasy || function() { let attrs = findObjs({ _type: 'attribute' }); - // Si on a changé d'initiative, alors diminue les effets temporaires + // Si on a chang\xE9 d'initiative, alors diminue les effets temporaires if (combat.init > init) { if (stateCOF.tokensTemps && stateCOF.tokensTemps.length > 0) { stateCOF.tokensTemps = stateCOF.tokensTemps.filter(function(tt) { @@ -47414,15 +48002,8 @@ var COFantasy = COFantasy || function() { tt.duree--; return true; } else { - let token = getObj('graphic', tt.tid); - if (token) { - let ett = {...tt - }; - ett.deletedToken = getTokenFields(token); - evt.deletedTokensTemps = evt.deletedTokensTemps || []; - evt.deletedTokensTemps.push(ett); - token.remove(); - } + if (tt.intrusion) tt.pasDExplosion = true; + deleteTokenTemp(tt, evt); return false; } } else { @@ -47430,7 +48011,7 @@ var COFantasy = COFantasy || function() { } }); } - //attrsTemp ne contient que les attributs dont la durée doit baisser + //attrsTemp ne contient que les attributs dont la dur\xE9e doit baisser let attrsTemp = attrs.filter(function(obj) { if (!estEffetTemp(obj.get('name'))) return false; let obji = obj.get('max'); @@ -47439,7 +48020,7 @@ var COFantasy = COFantasy || function() { if (!evt.combat) evt.combat = {...stateCOF.combat }; combat.init = init; - // Boucle sur les effets temps peut être asynchrone à cause des DM + // Boucle sur les effets temps peut \xEAtre asynchrone \xE0 cause des DM let count = attrsTemp.length; if (count === 0) { nextTurnOfActive(active, attrs, evt, combat, pageId, options); @@ -47462,8 +48043,8 @@ var COFantasy = COFantasy || function() { let effetC = effetComplet(effet, attrName); let v = parseInt(attr.get('current')); if (isNaN(v)) v = 1; - if (v <= 1) { //L'effet arrive en fin de vie, doit être supprimé - //Sauf si on a accumulé plusieurs fois l'effet + if (v <= 1) { //L'effet arrive en fin de vie, doit \xEAtre supprim\xE9 + //Sauf si on a accumul\xE9 plusieurs fois l'effet let accumuleAttr = attributeExtending(charId, attrName, effetC, 'DureeAccumulee'); if (accumuleAttr.length > 0) { accumuleAttr = accumuleAttr[0]; @@ -47514,16 +48095,16 @@ var COFantasy = COFantasy || function() { if (v > 1) attr.set('current', v - 1); actionEffet(attr, effet, attrName, charId, pageId, evt, fin); }); //fin de la boucle sur tous les attributs d'effets temporaires - } else { //L'initiative n'a pas bougée + } else { //L'initiative n'a pas boug\xE9e nextTurnOfActive(active, attrs, evt, combat, pageId, options); } } - //Fonction appelée par !cof-tour-suivant + //Fonction appel\xE9e par !cof-tour-suivant function tourSuivant(msg) { let combat = stateCOF.combat; if (!combat) { - sendPlayer(msg, "Vous n'êtes pas en combat"); + sendPlayer(msg, "Vous n'\xEAtes pas en combat"); return; } let cmp = Campaign(); @@ -47561,10 +48142,10 @@ var COFantasy = COFantasy || function() { nextTurn(cmp); } - //nb à 11 pour ne pas retenter de lire les attributs + //nb \xE0 11 pour ne pas retenter de lire les attributs function scriptVersionToCharacter(character, nb) { let charId = character.id; - //On vérifie que les attributs sont peuplés + //On v\xE9rifie que les attributs sont peupl\xE9s let attrs = findObjs({ _type: 'attribute', _characterid: charId, @@ -47630,7 +48211,7 @@ var COFantasy = COFantasy || function() { removeTokenAttr(perso, 'bougeGraceA'); return; } - //On regarde si il existe une copie de ce token, par exemple à cause de l'invisibilité + //On regarde si il existe une copie de ce token, par exemple \xE0 cause de l'invisibilit\xE9 let otherTokens = findObjs({ _type: 'graphic', _pageid: pageId, @@ -47742,7 +48323,7 @@ var COFantasy = COFantasy || function() { activerEffetTemporaire(origine, cibles, 'drainDeForce', mEffet, 1, options, evtEffet, '', [], display); } - //retourne le nombre de cibles affectées + //retourne le nombre de cibles affect\xE9es function appliquerAura(origine, cibles, pageId, aura, evt, renew) { let effet; cibles = cibles.filter(function(perso) { @@ -47763,7 +48344,7 @@ var COFantasy = COFantasy || function() { save: { carac: 'CON', seuil: 12, - msgPour: ' pour ne pas être affaibli' + eForFemale(cibles[0]) + msgPour: ' pour ne pas \xEAtre affaibli' + eForFemale(cibles[0]) } }; let mEffet = messageEffetTemp.drainDeForce; @@ -47795,8 +48376,8 @@ var COFantasy = COFantasy || function() { return cibles.length; } - //Réagit au déplacement manuel d'un token. - // suivis est l'ensemble des tokens qui a déjà été bougé suite à ce déplacement + //R\xE9agit au d\xE9placement manuel d'un token. + // suivis est l'ensemble des tokens qui a d\xE9j\xE0 \xE9t\xE9 boug\xE9 suite \xE0 ce d\xE9placement function moveToken(token, prev, synchronisation, suivis) { let charId = token.get('represents'); if (charId === '') return; @@ -47809,6 +48390,57 @@ var COFantasy = COFantasy || function() { let y = token.get('top'); let deplacement = prev && (prev.left != x || prev.top != y); if (!deplacement) return; + //Effet des bombes \xE0 intrusion + if (stateCOF.tokensTemps) { + let collisions = []; + let pt_arrivee = { + x, + y + }; + let pt_depart = { + x: prev.left, + y: prev.top + }; + let rayon = tokenSizeAsCircle(token) / 2; + stateCOF.tokensTemps.forEach(function(tt) { + if (!tt.intrusion) return; + //tt.intrusion est exprim\xE9 en pixels + let bombe = getTokenTemp(tt); + if (!bombe) return; + let pb = pointOfToken(bombe); + let distance = distancePoints(pt_depart, pb); + if (distance < tt.intrusion) return; //On est parti de la zone de d\xE9part + let distToTrajectory = + distancePixTokenSegment(bombe, pt_depart, pt_arrivee); + if (distToTrajectory > tt.intrusion + rayon) return; + collisions.push({ + bombe, + tt, + distance + }); + }); + if (collisions.length > 0) { + collisions.sort(function(b1, b2) { + let d1 = b1.distance; + let d2 = b2.distance; + if (d1 < d2) return -1; + if (d2 < d1) return 1; + return 0; + }); + let bombe = collisions[0].bombe; + x = bombe.get('left'); + y = bombe.get('top'); + token.set('left', x); + token.set('top', y); + const evt = { + type: "Explosion de bombe" + }; + deleteTokenTemp(collisions[0].tt, evt); + stateCOF.tokensTemps = stateCOF.tokensTemps.filter(function(tt) { + return tt.id == collisions[0].tt.id; + }); + } + } //Effets des auras, asynchrone if (stateCOF.combat && stateCOF.combat.auras) { const evt = { @@ -47849,7 +48481,7 @@ var COFantasy = COFantasy || function() { if (tid == token.id) return; let tok = getObj('graphic', tid); if (tok === undefined) { - error("Impossible de trouver le token d'id " + tid + " synchronisé avec " + token.get('name'), attr); + error("Impossible de trouver le token d'id " + tid + " synchronis\xE9 avec " + token.get('name'), attr); return; } tok.set('left', x); @@ -47916,7 +48548,7 @@ var COFantasy = COFantasy || function() { type: "initiative" }; updateInit(monture.token, evt); - // Réadapter l'init_dynamique au token du perso + // R\xE9adapter l'init_dynamique au token du perso if (stateCOF.options.affichage.val.init_dynamique.val) { setTokenInitAura(perso); } @@ -47998,7 +48630,7 @@ var COFantasy = COFantasy || function() { autreInvisible.set('top', y); } } - //si non, perso est peut-être une monture + //si non, perso est peut-\xEAtre une monture let attrMontePar = tokenAttribute(perso, 'estMontePar'); attrMontePar.forEach(function(a) { let cavalier = persoOfIdName(a.get('current'), pageId); @@ -48024,7 +48656,7 @@ var COFantasy = COFantasy || function() { //Si le token suivait quelqu'un, ce n'est plus le cas if (prev.suit === undefined) nePlusSuivre(perso, pageId); //On bouge tous les tokens qui suivent le personnage - //sauf si on a déjà été bougé. + //sauf si on a d\xE9j\xE0 \xE9t\xE9 boug\xE9. if (!suivis.has(token.id)) { suivis.add(token.id); let attrSuivi = tokenAttribute(perso, 'estSuiviPar'); @@ -48058,7 +48690,7 @@ var COFantasy = COFantasy || function() { if (sh > width) return false; let sx = suivant.token.get('left'); let sy = suivant.token.get('top'); - //On essaie de garder la même position par rapport au token, en supposant qu'on était derrière lui + //On essaie de garder la m\xEAme position par rapport au token, en supposant qu'on \xE9tait derri\xE8re lui let attrSuit = tokenAttribute(suivant, 'suit'); let dp; if (attrSuit.length > 0) { @@ -48073,10 +48705,10 @@ var COFantasy = COFantasy || function() { if (nsy < 0) nsy = 0; if (nsx + sw / 2 > width) nsx = Math.floor(width - sw / 2); if (nsy + sh / 2 > height) nsy = Math.floor(height - sh / 2); - //vérifie si de la nouvelle position on peut voir le suivi + //v\xE9rifie si de la nouvelle position on peut voir le suivi if (obstaclePresent(nsx, nsy, pt, murs)) { - //On essaie de suivre le chemin du token, à la place - //D'abord se déplacer vers l'ancienne position de perso, au maximum de distance pixels + //On essaie de suivre le chemin du token, \xE0 la place + //D'abord se d\xE9placer vers l'ancienne position de perso, au maximum de distance pixels let distLoc = distance; if (distLoc - dp < 5) { nsx = prev.left; @@ -48133,7 +48765,7 @@ var COFantasy = COFantasy || function() { roundMarker.set('left', x); roundMarker.set('top', y); } else { - // Cas spéciaux du cavaliers : au tour du cavalier, l'init_dynamique suit la monture + // Cas sp\xE9ciaux du cavaliers : au tour du cavalier, l'init_dynamique suit la monture let estMontePar = tokenAttribute(perso, 'estMontePar'); if (estMontePar.length > 0) { let sp = splitIdName(estMontePar[0].get('current')); @@ -48145,7 +48777,7 @@ var COFantasy = COFantasy || function() { } } } - //On déplace les tokens de lumière, si il y en a + //On d\xE9place les tokens de lumi\xE8re, si il y en a let attrLumiere = tokenAttribute(perso, 'lumiere'); attrLumiere.forEach(function(al) { let lumId = al.get('max'); @@ -48165,13 +48797,13 @@ var COFantasy = COFantasy || function() { }); if (tokensLumiere.length === 0) { if (lumiereExiste) return; - log("Pas de token pour la lumière " + al.get('current')); + log("Pas de token pour la lumi\xE8re " + al.get('current')); al.remove(); return; } lumiere = tokensLumiere.shift(); if (tokensLumiere.length > 0) { - //On cherche le token le plus proche de la position précédente + //On cherche le token le plus proche de la position pr\xE9c\xE9dente let d = distanceTokenPrev(lumiere, prev); tokensLumiere.forEach(function(tl) { let d2 = distanceTokenPrev(tl, prev); @@ -48184,7 +48816,7 @@ var COFantasy = COFantasy || function() { } if (lumiere === undefined) { if (lumiereExiste) return; - log("Pas de token pour la lumière " + al.get('current')); + log("Pas de token pour la lumi\xE8re " + al.get('current')); al.remove(); return; } @@ -48207,7 +48839,7 @@ var COFantasy = COFantasy || function() { function synchronisationDesEtats(perso) { for (let etat in cof_states) { - // Récupère la valeur de l'état sur la fiche + // R\xE9cup\xE8re la valeur de l'\xE9tat sur la fiche let valEtat; if (etat == 'affaibli') { // Cas particulier affaibli sur la fiche perso valEtat = (ficheAttributeAsInt(perso, 'affaibli', 20) == 12); @@ -48219,10 +48851,10 @@ var COFantasy = COFantasy || function() { } } - //Opérations diverses au moment où on pose un token. - //Si le token représente un personnage et avec la barre de vie non liée, - // assure un nom unique en ajoutant un numéro - // On en profite aussi pour mettre certaines valeurs par défaut + //Op\xE9rations diverses au moment o\xF9 on pose un token. + //Si le token repr\xE9sente un personnage et avec la barre de vie non li\xE9e, + // assure un nom unique en ajoutant un num\xE9ro + // On en profite aussi pour mettre certaines valeurs par d\xE9faut // retourne un perso si c'est un token de personnage function renameToken(token, tokenName) { let charId = token.get('represents'); @@ -48285,11 +48917,11 @@ var COFantasy = COFantasy || function() { } return perso; } - //cas des mooks : numérotation + //cas des mooks : num\xE9rotation let copyOf = 0; let tokenBaseName = tokenName; if (tokenBaseName.includes('%%NUMBERED%%')) { - if (typeof TokenNameNumber !== 'undefined') return perso; //On laisse tokenNameNumber gérer ça + if (typeof TokenNameNumber !== 'undefined') return perso; //On laisse tokenNameNumber g\xE9rer \xE7a tokenBaseName = tokenBaseName.replace('%%NUMBERED%%', ''); } else { // On regarde si le nom se termine par un entier @@ -48341,7 +48973,7 @@ var COFantasy = COFantasy || function() { function addToken(token, nb) { let tokenName = token.get('name'); - //La plupart du temps, il faut attendre un peu que le nom soit affecté + //La plupart du temps, il faut attendre un peu que le nom soit affect\xE9 if (tokenName !== '') { let perso = renameToken(token, tokenName); if (perso === undefined) return; @@ -48355,16 +48987,16 @@ var COFantasy = COFantasy || function() { return; } nb = nb || 1; - if (nb > 10) return; //Tant pis, peut-être que le nom est vide + if (nb > 10) return; //Tant pis, peut-\xEAtre que le nom est vide _.delay(function() { addToken(token, nb + 1); }, 50); } - // Surveillance sur le changement d'état du token + // Surveillance sur le changement d'\xE9tat du token function changeMarker(token, prev) { const charId = token.get('represents'); - if (charId === undefined || charId === '') return; // Uniquement si token lié à un perso + if (charId === undefined || charId === '') return; // Uniquement si token li\xE9 \xE0 un perso const perso = { token, charId @@ -48430,7 +49062,7 @@ var COFantasy = COFantasy || function() { let lumId = al.get('max'); if (lumId == 'surToken') { if (!token.get('emits_bright_light') && !token.get('emits_low_light')) { - //On cherche un token qui représente le même personnage et émet de la lumière + //On cherche un token qui repr\xE9sente le m\xEAme personnage et \xE9met de la lumi\xE8re let allTokens = findObjs({ type: 'graphic', represents: perso.charId @@ -48449,7 +49081,7 @@ var COFantasy = COFantasy || function() { } return; } - //Lumière sur un token qui suit le perso. + //Lumi\xE8re sur un token qui suit le perso. let lumiere = getObj('graphic', lumId); if (lumiere && lumiere.get('pageid') != pageId) { let copyLum = createObj('graphic', { @@ -48475,7 +49107,7 @@ var COFantasy = COFantasy || function() { } } - //Actions à faire pour maintenir la cohérence des tokens qui représentent le même personnage. + //Actions \xE0 faire pour maintenir la coh\xE9rence des tokens qui repr\xE9sentent le m\xEAme personnage. function changePlayerPage(campaign) { let currentMap = getObj('page', campaign.get('playerpageid')); let tokens = findObjs({ @@ -48485,7 +49117,7 @@ var COFantasy = COFantasy || function() { }); tokens.forEach(function(token) { let charId = token.get('represents'); - if (charId === undefined || charId === '') return; // Si token lié à un perso + if (charId === undefined || charId === '') return; // Si token li\xE9 \xE0 un perso if (token.get('bar1_link') === '') return; // Si unique let perso = { token, @@ -48527,8 +49159,8 @@ var COFantasy = COFantasy || function() { function changeTokenLock(token, prev) { const charId = token.get('represents'); - if (charId === undefined || charId === '') return; // Uniquement si token lié à un perso - if (token.get('lockMovement')) return; //Rien de spécial à faire + if (charId === undefined || charId === '') return; // Uniquement si token li\xE9 \xE0 un perso + if (token.get('lockMovement')) return; //Rien de sp\xE9cial \xE0 faire const perso = { token, charId @@ -48557,8 +49189,8 @@ var COFantasy = COFantasy || function() { state.COFantasy.eventId = 0; } if (version < 1.0) { - log("Mise à jour des attributs et macros vers la version 1.0"); - //Mise à jour des effets temporaires avec _ + log("Mise \xE0 jour des attributs et macros vers la version 1.0"); + //Mise \xE0 jour des effets temporaires avec _ let strReg = "(rayon_affaiblissant|peau_d_ecorce|chant_des_heros|image_decalee|a_couvert|sous_tension|forgeron_|armeEnflammee)"; let regName = new RegExp("^" + strReg); let regText = new RegExp(strReg); @@ -48611,10 +49243,10 @@ var COFantasy = COFantasy || function() { m.set('action', action); } }); - log("Mise à jour effectuée."); + log("Mise \xE0 jour effectu\xE9e."); } if (version < 2.0) { - log("Mise à jour des attributs et macros vers la version 2.0"); + log("Mise \xE0 jour des attributs et macros vers la version 2.0"); let strReg = "(--argent)"; let regName = new RegExp("^" + strReg); let regText = new RegExp(strReg); @@ -48646,7 +49278,7 @@ var COFantasy = COFantasy || function() { m.set('action', action); } }); - log("Mise à jour effectuée."); + log("Mise \xE0 jour effectu\xE9e."); } if (version < 2.02) { let attrs = findObjs({ @@ -48656,7 +49288,7 @@ var COFantasy = COFantasy || function() { let attrName = attr.get('name'); if (attrName == 'mort-vivant') attr.set('name', 'mortVivant'); }); - log("Mise à jour effectuée."); + log("Mise \xE0 jour effectu\xE9e."); } if (version < 2.03) { let attrs = findObjs({ @@ -48664,13 +49296,13 @@ var COFantasy = COFantasy || function() { }); attrs.forEach(function(attr) { let attrName = attr.get('name'); - if (attrName == 'runeDEnergie') attr.set('name', 'runeForgesort_énergie'); + if (attrName == 'runeDEnergie') attr.set('name', 'runeForgesort_\xE9nergie'); if (attrName == 'runeDeProtection') attr.set('name', 'runeForgesort_protection'); if (attrName.includes('runeDePuissance')) { attr.set('name', 'runeForgesort_puissance(' + attrName.substring(attrName.indexOf("(") + 1, attrName.indexOf(")")) + ')'); } }); - log("Mise à jour des runes effectuée."); + log("Mise \xE0 jour des runes effectu\xE9e."); } if (version < 2.04) { let attrs = findObjs({ @@ -48718,7 +49350,7 @@ var COFantasy = COFantasy || function() { attrRDS.set('current', rdPerso); a.remove(); }); - log("Mise à jour de la RD effectuée"); + log("Mise \xE0 jour de la RD effectu\xE9e"); } if (version < 2.05) { let attrs = findObjs({ @@ -48733,7 +49365,7 @@ var COFantasy = COFantasy || function() { let message = action.substring(19); a.set("max", "!cof-lancer-sort --message " + message + " --mana " + mana); }); - log("Mise à jour des consommables !cof-lancer-sort effectuée"); + log("Mise \xE0 jour des consommables !cof-lancer-sort effectu\xE9e"); let macros = findObjs({ _type: 'macro' }).concat(findObjs({ @@ -48746,7 +49378,7 @@ var COFantasy = COFantasy || function() { let message = macro.substring(19); m.set("action", "!cof-lancer-sort --message " + message + " --mana " + mana); }); - log("Mise à jour des ability & macros !cof-lancer-sort effectuée"); + log("Mise \xE0 jour des ability & macros !cof-lancer-sort effectu\xE9e"); } if (version < 2.10) { let tokens = findObjs({ @@ -48775,7 +49407,7 @@ var COFantasy = COFantasy || function() { let removeAttrs = function() { charsToTreat--; if (charsToTreat > 0) return; - log("Supression des attributs obsolètes"); + log("Supression des attributs obsol\xE8tes"); let attrs = findObjs({ _type: 'attribute', }); @@ -48840,13 +49472,13 @@ var COFantasy = COFantasy || function() { setDefaultTokenForCharacter(character, newToken); newToken.remove(); } else { - log('Impossible de créer un token pour ' + token.name); + log('Impossible de cr\xE9er un token pour ' + token.name); log(token); } removeAttrs(); }); }); - log("Mise à jour des attributs et tokens effectuée"); + log("Mise \xE0 jour des attributs et tokens effectu\xE9e"); } if (version < 2.11) { let attrs = findObjs({ @@ -48862,7 +49494,7 @@ var COFantasy = COFantasy || function() { }; a.set(na); }); - log("Mise à jour des attributs de capitaine effectuée"); + log("Mise \xE0 jour des attributs de capitaine effectu\xE9e"); } if (version < 2.12) { let attrs = findObjs({ @@ -48931,10 +49563,10 @@ var COFantasy = COFantasy || function() { } a.remove(); }); - log("Déplacement des attributs de consommables vers la fiche"); + log("D\xE9placement des attributs de consommables vers la fiche"); } if (version < 2.13) { - //On enlève les attributs obsolètes de la verison 4.00 de la fiche + //On enl\xE8ve les attributs obsol\xE8tes de la verison 4.00 de la fiche let attrs = findObjs({ _type: 'attribute', }); @@ -48974,7 +49606,7 @@ var COFantasy = COFantasy || function() { }); } if (version < 2.14) { - //Migration des éléments de règles optionnels + //Migration des \xE9l\xE9ments de r\xE8gles optionnels //Divers if (state.COFantasy.options.regles.val.poudre_explosif) { state.COFantasy.options.regles.val.divers.val.poudre_explosif.val = state.COFantasy.options.regles.val.poudre_explosif.val; @@ -49007,13 +49639,13 @@ var COFantasy = COFantasy || function() { delete state.COFantasy.options.regles.val.usure_DEF; } if (state.COFantasy.options.regles.val.generer_options_attaques) { - log("Options d'attaques supprimées ; veuiller utiliser le bouton 'Options' de la liste d'Actions à la place"); - sendChat('COFantasy', "Options d'attaques supprimées ; veuiller utiliser le bouton 'Options' de la liste d'Actions à la place"); + log("Options d'attaques supprim\xE9es ; veuiller utiliser le bouton 'Options' de la liste d'Actions \xE0 la place"); + sendChat('COFantasy', "Options d'attaques supprim\xE9es ; veuiller utiliser le bouton 'Options' de la liste d'Actions \xE0 la place"); delete state.COFantasy.options.regles.val.generer_options_attaques; } if (state.COFantasy.options.regles.val.generer_attaque_groupe) { - log("Attaques de groupe supprimées ; veuiller utiliser le bouton 'Options' de la liste d'Actions à la place"); - sendChat('COFantasy', "Options d'attaques supprimées ; veuiller utiliser le bouton 'Options' de la liste d'Actions à la place"); + log("Attaques de groupe supprim\xE9es ; veuiller utiliser le bouton 'Options' de la liste d'Actions \xE0 la place"); + sendChat('COFantasy', "Options d'attaques supprim\xE9es ; veuiller utiliser le bouton 'Options' de la liste d'Actions \xE0 la place"); delete state.COFantasy.options.regles.val.generer_attaque_groupe; } if (state.COFantasy.options.regles.val.bonus_attaque_groupe) { @@ -49042,7 +49674,7 @@ var COFantasy = COFantasy || function() { state.COFantasy.options.regles.val.mana.val.elixirs_sorts.val = state.COFantasy.options.regles.val.elixirs_sorts.val; delete state.COFantasy.options.regles.val.elixirs_sorts; } - log("Règles optionelles mises à jour"); + log("R\xE8gles optionelles mises \xE0 jour"); } if (version < 2.15) { let attrs = findObjs({ @@ -49084,7 +49716,7 @@ var COFantasy = COFantasy || function() { }); a.remove(); }); - log("Déplacement des attributs de consommables de PNJs vers la fiche"); + log("D\xE9placement des attributs de consommables de PNJs vers la fiche"); } if (version < 2.16) { let attrs = findObjs({ @@ -49095,7 +49727,7 @@ var COFantasy = COFantasy || function() { }); let handhoutComp = handouts.find(function(h) { let handName = h.get('name'); - return (handName == 'Compétences' || handName == 'Competences'); + return (handName == 'Comp\xE9tences' || handName == 'Competences'); }); if (handhoutComp) { let listeCompetences = { @@ -49108,7 +49740,7 @@ var COFantasy = COFantasy || function() { nombre: 0 }; handhoutComp.get('notes', function(note) { // asynchronous - let carac; //La carac dont on spécifie les compétences actuellement + let carac; //La carac dont on sp\xE9cifie les comp\xE9tences actuellement note = note.trim(); if (note.startsWith('

    ')) note = note.substring(3); note = note.trim().replace(/]*>|<\/span>/g, ''); @@ -49126,7 +49758,7 @@ var COFantasy = COFantasy || function() { } if (ligne.length === 0) return; if (carac === undefined) { - log("Compétences sans caractéristique associée"); + log("Comp\xE9tences sans caract\xE9ristique associ\xE9e"); return; } let comps = ligne.split(/, |\/| /); @@ -49204,9 +49836,9 @@ var COFantasy = COFantasy || function() { a.set('name', 'charisme'); return; } - //Les compétences + //Les comp\xE9tences let charId = a.get('characterid'); - //On ne bouge les compétences que pour les persos de type PJ + //On ne bouge les comp\xE9tences que pour les persos de type PJ let typePerso = findObjs({ _type: 'attribute', _characterid: charId, @@ -49232,7 +49864,7 @@ var COFantasy = COFantasy || function() { attrSpec.current = compToCarac[attrName]; createObj('attribute', attrSpec); let attrMalus; - if ((attrSpec.current == 'DEX' && attrName != 'crochetage' && attrName != 'désamorçage') || + if ((attrSpec.current == 'DEX' && attrName != 'crochetage' && attrName != 'd\xE9samor\xE7age') || (attrSpec.current == 'CON' && attrName == 'survie') || attrName == 'natation' || attrName == 'escalade') { attrSpec.name = prefix + 'malus'; @@ -49296,7 +49928,7 @@ var COFantasy = COFantasy || function() { } }); } - log("Mise à jour des attributs de compétence effectué"); + log("Mise \xE0 jour des attributs de comp\xE9tence effectu\xE9"); } if (version < 2.17) { let macros = findObjs({ @@ -49311,7 +49943,7 @@ var COFantasy = COFantasy || function() { if (macro !== newMacro) m.set("action", newMacro); }); - log("Mise à jour des ability Ténèbres effectuée"); + log("Mise \xE0 jour des ability T\xE9n\xE8bres effectu\xE9e"); } let updateReset = function(a, nom, typ) { let c = parseInt(a.get('current')); @@ -49353,7 +49985,7 @@ var COFantasy = COFantasy || function() { } }); } - log("Mise à jour des attributs effectuée"); + log("Mise \xE0 jour des attributs effectu\xE9e"); } if (version < 3.00) { let macros = findObjs({ @@ -49601,7 +50233,7 @@ var COFantasy = COFantasy || function() { characterid: cid, }); if (abilitiesInList.has(actionCmd) || abilitie.get('istokenaction')) { - //On garde le texte partagé de l'ability. + //On garde le texte partag\xE9 de l'ability. createObj('attribute', { name: pref + 'actiontitre', current: action, @@ -49648,7 +50280,7 @@ var COFantasy = COFantasy || function() { characterid: cid, }); // Macro - //D'abord le cas de #Attaque, car le nom affiché est celui de l'arme + //D'abord le cas de #Attaque, car le nom affich\xE9 est celui de l'arme if (actionCmd == '#Attaque' && actionCommands.length > 1) { createObj('attribute', { name: pref + 'actiontitre', @@ -49711,7 +50343,7 @@ var COFantasy = COFantasy || function() { state.COFantasy.options.affichage && state.COFantasy.options.affichage.val && state.COFantasy.options.affichage.val.actions_par_defaut.val) { - //Par défaut, on montrait la liste de toutes les abilities + //Par d\xE9faut, on montrait la liste de toutes les abilities abilities.forEach(function(a) { n++; let pref = 'repeating_actions_' + generateRowID() + '_'; @@ -49762,17 +50394,17 @@ var COFantasy = COFantasy || function() { } if (n > 0) attrRang.set('current', n); }); - log("Mise à jour des listes d'action effectuée"); - //Ensuite les prédicats booléens + log("Mise \xE0 jour des listes d'action effectu\xE9e"); + //Ensuite les pr\xE9dicats bool\xE9ens let predicates = '^(' + 'actionLibre|agripper|ambidextreDuelliste|animal|argumentDeTaille' + '|armureProtection|aucuneActionCombat|baroudHonneur' + '|botteMortelle|bouclierPsi|briseurDOs|bucheron|champion' + '|chasseurEmerite|chatimentDuMale|chimiste|ciblesMultiples' + '|combatEnPhalange|combatKinetique|commandant|controleDuMetabolisme' + - '|creatureArtificielle|crocEnJambe|defenseIntuitive|démon|devorer' + + '|creatureArtificielle|crocEnJambe|defenseIntuitive|d\xE9mon|devorer' + '|durACuire|ecuyer|elfeNoir|enchainement|energieDeLaMort' + - '|estUneIllusion|exsangue|fée|fievreChene|frappeChirurgicale|gober' + + '|estUneIllusion|exsangue|f\xE9e|fievreChene|frappeChirurgicale|gober' + '|graceFeline|graceFelineVoleur|grosMonstreGrosseArme|grosseTete' + '|hachesEtMarteaux|hausserLeTon|horsDePortee|humanoide' + '|ignorerLaDouleur|immuniteAuxArmes|immuniteAuxSournoises' + @@ -49823,7 +50455,7 @@ var COFantasy = COFantasy || function() { { let charId = attribute.get('characterid'); parChar[charId] = parChar[charId] || new Set(); - parChar[charId].add('géant'); + parChar[charId].add('g\xE9ant'); attribute.remove(); } break; @@ -49854,7 +50486,7 @@ var COFantasy = COFantasy || function() { attr.set('current', predText + attr.get('current')); } } - log("Transformation des attributs booléens en prédicats"); + log("Transformation des attributs bool\xE9ens en pr\xE9dicats"); } let getPredicateAttr = function(charId) { let attr = findObjs({ @@ -49922,7 +50554,7 @@ var COFantasy = COFantasy || function() { } attr.set('current', predText); } - log("Transformation des attributs numériques en prédicats"); + log("Transformation des attributs num\xE9riques en pr\xE9dicats"); } if (version < 3.02) { const regPJ = new RegExp("^(repeating_armes_[^_]*_)(.*)$"); @@ -49991,7 +50623,7 @@ var COFantasy = COFantasy || function() { taux = parseInt(cmd[2]); if (isNaN(taux) || taux < 0 || taux > 100) taux = 0; } else { - taux = 100; //La valeur par défaut en option. + taux = 100; //La valeur par d\xE9faut en option. } return false; }); @@ -50038,7 +50670,7 @@ var COFantasy = COFantasy || function() { } }); }); - log("Mise à jour des armes de jet effectuée"); + log("Mise \xE0 jour des armes de jet effectu\xE9e"); } if (version < 3.03) { findObjs({ @@ -50057,7 +50689,7 @@ var COFantasy = COFantasy || function() { if (arme.trim() !== '') predText += ':' + arme; attr.set('current', predText); }); - log("Mise à jour de prédicats effectuée"); + log("Mise \xE0 jour de pr\xE9dicats effectu\xE9e"); } if (version < 3.04) { let attrs = findObjs({ @@ -50138,7 +50770,7 @@ var COFantasy = COFantasy || function() { } attr.set('current', predText); } - log("Transformation d'attributs de combat en prédicats"); + log("Transformation d'attributs de combat en pr\xE9dicats"); } if (version < 3.05) { let attrs = findObjs({ @@ -50151,7 +50783,7 @@ var COFantasy = COFantasy || function() { log("Suppression des attributs pnj d'armure et de bouclier"); } if (version < 3.07) { - //Collecte des persos ayant un prédicat charge_ ou eclaire_ + //Collecte des persos ayant un pr\xE9dicat charge_ ou eclaire_ let charIds = {}; let attrs = findObjs({ _type: 'attribute', @@ -50244,7 +50876,7 @@ var COFantasy = COFantasy || function() { } } } - log("Copie des prédicats de charge et éclairage vers les attaques des armes"); + log("Copie des pr\xE9dicats de charge et \xE9clairage vers les attaques des armes"); } if (version < 3.08) { let attrs = findObjs({ @@ -50285,10 +50917,10 @@ var COFantasy = COFantasy || function() { a.set('current', preds); } }); - log("Changement du prédicat laissez-le-moi"); + log("Changement du pr\xE9dicat laissez-le-moi"); } if (version < 3.11) { - //aura sera passé en actions plus tard + //aura sera pass\xE9 en actions plus tard let predicates = '^(' + 'attributsDeStatut|chairACanonDe|defDeriveeDe|dmSiToucheContact' + '|ecuyerDe|ennemiJure|entrerEnCombatAvec|familier|guetteur' + @@ -50327,7 +50959,7 @@ var COFantasy = COFantasy || function() { for (let charId in parChar) { parChar[charId].attr.set('current', parChar[charId].predText); } - log("Transformation des attributs complexes en prédicats"); + log("Transformation des attributs complexes en pr\xE9dicats"); } if (version < 3.12) { if (state.COFantasy.foudresDuTemps) { @@ -50351,7 +50983,15 @@ var COFantasy = COFantasy || function() { charAttr: true }); }); - log("Mise à jour effectuée"); + log("Mise \xE0 jour effectu\xE9e"); + } + } + + function changePredicats(attr, prev) { + let curPred = attr.get('current'); + let prevPred = prev.current; + if (curPred.includes('attaqueEnMeute') != prevPred.includes('attaqueEnMeute')) { + recomputeAllies(); } } @@ -50371,7 +51011,8 @@ var COFantasy = COFantasy || function() { predicateOfRaw, listAllAttacks, getWeaponStats, - updateVersion + updateVersion, + changePredicats, }; }(); @@ -50397,7 +51038,7 @@ on('ready', function() { handout.forEach(function(hand) { COFantasy.changeHandout(hand); }); - //Vérification de la version sur les fiches + //V\xE9rification de la version sur les fiches characters.forEach(function(c) { COFantasy.scriptVersionToCharacter(c, 11); }); @@ -50416,8 +51057,8 @@ on("chat:message", function(msg) { try { COFantasy.apiCommand(msg); } catch (e) { - sendChat('COF', "Erreur durant l'exécution de " + msg.content); - log("Erreur durant l'exécution de " + msg.content); + sendChat('COF', "Erreur durant l'ex\xE9cution de " + msg.content); + log("Erreur durant l'ex\xE9cution de " + msg.content); log(msg); let errMsg = e.name; if (e.lineNumber) errMsg += " at " + e.lineNumber; @@ -50450,6 +51091,8 @@ on("change:attribute", function(attr, prev) { let predicats = state.COFantasy.predicats; if (!predicats) return; let n = attr.get("name"); - if (n == "predicats_script" || n.includes('armepredicats')) + if (n == "predicats_script" || n.includes('armepredicats')) { predicats[attr.get('characterid')] = undefined; + COFantasy.changePredicats(attr, prev); + } }); diff --git a/COFantasy/ChangeLog.md b/COFantasy/ChangeLog.md index 6b0a05e7a..5289b8914 100644 --- a/COFantasy/ChangeLog.md +++ b/COFantasy/ChangeLog.md @@ -1,6 +1,11 @@ # COFantasy: Historique des changements (depuis la version 1.0) ## 3.13 ### Capacités +* Support pour la démolition et les pièges explosifs. +* Amélioration du support des tirs de semonce. +* Attaque en meute pour un joueur gobelin. +* Attaque bondissante du druide +* Charge du barbare (avec le déplacement) * Vitalité épique. * Pluie de flèches de la Voie d'Arwendée. * Rangs 1 à 4 de la Voie du guérisseur. @@ -8,6 +13,8 @@ * Expertise (rang 1 de la Voie de prestige spécialisée) ### Autres améliorations +* Possibilité d'utiliser des prédicats comme valeurs limites des limitations par jour ou par combat. +* Possibilité de faire un déplacement automatique avant une attaque * Possibilité que la peur paralyse. * Ajout d'une commande !cof-clean-global-state. * Ajout d'une action pour relacher une cible agrippée. @@ -20,6 +27,8 @@ * Ajout d'un prédicat pour l'immnunité aux dégâts magiques. ### Corrections de bugs +* Correction d'un bug avec le lien épique. +* Activation correcte de l'attaque en traître. * Activation de Ignorer la douleur sur les attaques automatiques. * Dépense de mana quand on dépasse les limites journalières diff --git a/COFantasy/doc.html b/COFantasy/doc.html index c71932c9e..e9f19a181 100644 --- a/COFantasy/doc.html +++ b/COFantasy/doc.html @@ -4,7 +4,7 @@ - Scripts pour Chroniques Oubli\xE9es Fantasy sous Roll20 + Scripts pour Chroniques Oubliées Fantasy sous Roll20 @@ -57,26 +57,26 @@

    Sommaire

  • Actions principales
  • -
  • Capacit\xE9s par Classe
  • +
  • Capacités par Classe
  • -
  • Autres capacit\xE9s
  • +
  • Autres capacités
  • Terres d'Arran
  • -
  • Markers personnalis\xE9s
  • +
  • Markers personnalisés
  • Console API
  • Conversion depuis Pathfinder
  • @@ -136,129 +136,129 @@

    1. Comment utiliser Le scr

    1.1 Tokens et personnages

    -

    Ces scripts ont \xE9t\xE9 \xE9crits pour fonctionner avec les fiches de personnages d\xE9velopp\xE9es par Natha.

    +

    Ces scripts ont été écrits pour fonctionner avec les fiches de personnages développées par Natha.

    -
    A choisir pendant la cr\xE9ation de la partie sur Roll20.
    +
    A choisir pendant la création de la partie sur Roll20.
    -

    Chaque token avec lequel vous souhaitez interagir doit repr\xE9senter un personnage.

    -

    La barre 1 repr\xE9sente toujours les points de vie du token.
    - La barre 2 est soit la mana, pour les personnages qui ont des points de mana, soit les d\xE9g\xE2ts temporaires pour les personnages qui n\x2019ont pas de points de mana
    - La barre 3 est utilis\xE9e pour donner un modificateur temporaire \xE0 l\x2019attaque du token. +

    Chaque token avec lequel vous souhaitez interagir doit représenter un personnage.

    +

    La barre 1 représente toujours les points de vie du token.
    + La barre 2 est soit la mana, pour les personnages qui ont des points de mana, soit les dégâts temporaires pour les personnages qui n’ont pas de points de mana
    + La barre 3 est utilisée pour donner un modificateur temporaire à l’attaque du token.

    -

    Les statuts des tokens sont en partie utilis\xE9s pour repr\xE9senter des \xE9tats. Voir plus loin pour la liste des statuts utilis\xE9s par les scripts.
    - Pour tenir compte d'autre \xE9tats non visibles sur les tokens, les scripts utilisent des attributs suppl\xE9mentaires (hors fiche). Parfois, le MJ devra cr\xE9er et remplir lui-m\xEAme certains attributs, d'autres fois cela sera g\xE9r\xE9 par les scripts. +

    Les statuts des tokens sont en partie utilisés pour représenter des états. Voir plus loin pour la liste des statuts utilisés par les scripts.
    + Pour tenir compte d'autre états non visibles sur les tokens, les scripts utilisent des attributs supplémentaires (hors fiche). Parfois, le MJ devra créer et remplir lui-même certains attributs, d'autres fois cela sera géré par les scripts.

    -

    Il est important de noter la diff\xE9rence entre les tokens li\xE9s \xE0 un personnage (la barre 1 est li\xE9e aux points de vie du personnage, tout changement sur la fiche se r\xE9percute sur le token), et les tokens non li\xE9s (dans ce cas, la fiche de personnage est g\xE9n\xE9rique, et chaque token est une instance diff\xE9rente, avec des PV ind\xE9pendants).

    -

    Pour g\xE9rer les \xE9tats sp\xE9cifiques \xE0 un token non li\xE9, les scripts utilisent des conventions de nom d'attribut utilisant le nom du token. Pour que cela fonctionne correctement, il est important que deux tokens ind\xE9pendants ne portent pas le m\xEAme nom, m\xEAme si ils repr\xE9sentent le m\xEAme personnage. Pour cette raison, le script va automatiquement renommer les tokens ind\xE9pendants, en leur associant un num\xE9ro. Il est toujours possible de remodifier le nom apr\xE8s la cr\xE9ation du token, mais dans ce cas, c'est vous qui g\xE9rez...

    -

    Certains messages tiennent compte du genre (masculin ou f\xE9minin) des personnages. Ils utilisent le champ Sexe de la fiche de personnage. Un personnage est reconnu comme f\xE9minin si ce champ commence par la lettre F. +

    Il est important de noter la différence entre les tokens liés à un personnage (la barre 1 est liée aux points de vie du personnage, tout changement sur la fiche se répercute sur le token), et les tokens non liés (dans ce cas, la fiche de personnage est générique, et chaque token est une instance différente, avec des PV indépendants).

    +

    Pour gérer les états spécifiques à un token non lié, les scripts utilisent des conventions de nom d'attribut utilisant le nom du token. Pour que cela fonctionne correctement, il est important que deux tokens indépendants ne portent pas le même nom, même si ils représentent le même personnage. Pour cette raison, le script va automatiquement renommer les tokens indépendants, en leur associant un numéro. Il est toujours possible de remodifier le nom après la création du token, mais dans ce cas, c'est vous qui gérez...

    +

    Certains messages tiennent compte du genre (masculin ou féminin) des personnages. Ils utilisent le champ Sexe de la fiche de personnage. Un personnage est reconnu comme féminin si ce champ commence par la lettre F.

    1.2 Macros et Abilities

    -

    Comme tous les scripts, ces scripts sont utilisables tels quels dans le chat, mais ils sont pens\xE9s pour \xEAtre utilis\xE9s par des macros qui permettent un autre niveau d'automatisation parfois difficile d'acc\xE8s au sein des scripts. le script g\xE9n\xE8re d'ailleurs la plupart des macros utiles \xE0 la premi\xE8re utilisation, et il met automatiquement les macros \xE0 jour \xE0 chaque changement de version. Il est possible de demander des les re-cr\xE9er en tapant la commande !cof-set-macros dans le chat.

    +

    Comme tous les scripts, ces scripts sont utilisables tels quels dans le chat, mais ils sont pensés pour être utilisés par des macros qui permettent un autre niveau d'automatisation parfois difficile d'accès au sein des scripts. le script génère d'ailleurs la plupart des macros utiles à la première utilisation, et il met automatiquement les macros à jour à chaque changement de version. Il est possible de demander des les re-créer en tapant la commande !cof-set-macros dans le chat.

    - Le script ne peut pas mettre les macros dans la barre de raccourci. Je recommande que chaque joueur se cr\xE9e sa macro Centrer, contenant le code !cof-centrer-sur-token nom_de_leur_token_principal, qui leur permettra en un click de centrer la vue de la carte sur leur token. Pour le MJ, le script sugg\xE8re de mettre un certain nombre des macros qu'il cr\xE9e, au moment de la premi\xE8re utilisation.

    -

    Une partie des capacit\xE9s et attaques des personnages devraient \xEAtre utilis\xE9es au sein d'abilities de personnages, accessibles comme "Token action". Si ces abilities utilisent des macros, ne pas oublier de rendre ces macros accessibles aux joueurs.

    + Le script ne peut pas mettre les macros dans la barre de raccourci. Je recommande que chaque joueur se crée sa macro Centrer, contenant le code !cof-centrer-sur-token nom_de_leur_token_principal, qui leur permettra en un click de centrer la vue de la carte sur leur token. Pour le MJ, le script suggère de mettre un certain nombre des macros qu'il crée, au moment de la première utilisation.

    +

    Une partie des capacités et attaques des personnages devraient être utilisées au sein d'abilities de personnages, accessibles comme "Token action". Si ces abilities utilisent des macros, ne pas oublier de rendre ces macros accessibles aux joueurs.

    -

    1.3 Pr\xE9dicats

    +

    1.3 Prédicats

    -

    Une fa\xE7on courante d'informer le script qu'un personnage dispose d'une capacit\xE9 particuli\xE8re (que ce soit d\xFB \xE0 son entra\xEEnement ou \xE0 un objet port\xE9) consiste \xE0 utiliser des pr\xE9dicats. Il s'agit de mots cl\xE9s \xE0 rentrer dans la zone de texte Pr\xE9dicats, visible depuis l'onglet Script de la fiche. Ces mots cl\xE9s peuvent \xEAtre s\xE9par\xE9s de blancs ou de retours \xE0 la ligne.

    -

    On peut associer une valeur \xE0 un pr\xE9dicat (le plus souvent un nombre, mais en fait n'importe quel mot qui ne contienne ni virgule, ni blanc, ni :). Pour cela, faire suivre le pr\xE9dicat de : puis de la valeur.

    -

    Dans chaque ligne de la zone de pr\xE9dicats, tout ce qui vient apr\xE8s // est consid\xE9r\xE9 comme du commentaire et ignor\xE9 (exception: les valeurs complexes, si le // vient apr\xE8s ::, voir plus bas).

    +

    Une façon courante d'informer le script qu'un personnage dispose d'une capacité particulière (que ce soit dû à son entraînement ou à un objet porté) consiste à utiliser des prédicats. Il s'agit de mots clés à rentrer dans la zone de texte Prédicats, visible depuis l'onglet Script de la fiche. Ces mots clés peuvent être séparés de blancs ou de retours à la ligne.

    +

    On peut associer une valeur à un prédicat (le plus souvent un nombre, mais en fait n'importe quel mot qui ne contienne ni virgule, ni blanc, ni :). Pour cela, faire suivre le prédicat de : puis de la valeur.

    +

    Dans chaque ligne de la zone de prédicats, tout ce qui vient après // est considéré comme du commentaire et ignoré (exception: les valeurs complexes, si le // vient après ::, voir plus bas).

    -
    Exemple de pr\xE9dicats.
    -

    Certains pr\xE9dicats ont des valeurs complexes, qui peuvent contenir des blancs, des virgules, des guillements, ou m\xEAme des : ou //. Afin de pouvoir utliser ces valeurs, vous pouvez faire suivre le nom du pr\xE9dicat de ::. Tout ce qui viendra apr\xE8s jusqu'\xE0 la fin de la ligne sera consid\xE9r\xE9 comme \xE9tant la valeur associ\xE9e \xE0 ce pr\xE9dicat. Un exemple typique d'utilisation : quand la valeur est un nom de personnage.

    -

    Il est aussi possible d'associer des pr\xE9dicats \xE0 des attaques. Ces pr\xE9dicats sont pris en compte quand ses attaques sont des armes, et ce que ces armes sont tenues en main. Cela permet de coder une grande vari\xE9t\xE9 d'effets magiques des armes. Attention, cela ne fonctionne pas pour les mooks avec les pr\xE9dicats animeAPartirDExistant, intercepter, lienEpique, attaqueEnTraitre, sansPeur, immuniteSaignement, et controleSanguin.

    +
    Exemple de prédicats.
    +

    Certains prédicats ont des valeurs complexes, qui peuvent contenir des blancs, des virgules, des guillements, ou même des : ou //. Afin de pouvoir utliser ces valeurs, vous pouvez faire suivre le nom du prédicat de ::. Tout ce qui viendra après jusqu'à la fin de la ligne sera considéré comme étant la valeur associée à ce prédicat. Un exemple typique d'utilisation : quand la valeur est un nom de personnage.

    +

    Il est aussi possible d'associer des prédicats à des attaques. Ces prédicats sont pris en compte quand ses attaques sont des armes, et ce que ces armes sont tenues en main. Cela permet de coder une grande variété d'effets magiques des armes. Attention, cela ne fonctionne pas pour les mooks avec les prédicats animeAPartirDExistant, intercepter, lienEpique, attaqueEnTraitre, sansPeur, immuniteSaignement, et controleSanguin.

    -
    Une \xE9p\xE9e +1 aff\xFBt\xE9e avec le pr\xE9dicat enchainement (actif pour toute attaque, tant que cette \xE9p\xE9e est en main).
    +
    Une épée +1 affûtée avec le prédicat enchainement (actif pour toute attaque, tant que cette épée est en main).
    -

    1.4 M\xE9thodes de s\xE9lection de groupes

    +

    1.4 Méthodes de sélection de groupes

    -

    Comme les joueurs ne peuvent pas s\xE9lectionner un nombre arbitraire d'ennemis, 7 m\xE9thodes sont disponibles :

    +

    Comme les joueurs ne peuvent pas sélectionner un nombre arbitraire d'ennemis, 7 méthodes sont disponibles :

      -
    • Le MJ lance la macro en s\xE9lectionnant les cibles
    • -
    • option --allies : cela fait chercher tous les handout dont le nom est Equipe suivi d'un nom, et tels que le handout contienne une liste de noms (un par ligne), parmis lesquels, celui du personnage qui agit. Le personnage qui agit est celui qui est s\xE9lectionn\xE9. Les cibles sont tous les alli\xE9s du personnage s\xE9lectionn\xE9, mais pas le personnage lui-m\xEAme. Attention, les noms de personnages ne doivent pas contenir de balise XML (texte encadr\xE9 par des < et >). Optionellement, on peut pr\xE9ciser une distance maximale entre le personnage s\xE9lectionn\xE9 et ses allies.
    • -
    • option --alliesEnVue : comme --allies, mais ne garde que les alli\xE9s en vue (en fonction des murs sur le layer lumi\xE8re).
    • -
    • option --equipe nom : agit sur tous les personnages mentionn\xE9s dans le handout s'appelant Equipe nom.
    • -
    • option --self : pour rajouter le personnage s\xE9lectionn\xE9. Utile si on veut le personnage et ses alli\xE9s, par exemple.
    • -
    • option --target : pour ajouter une seule cible, avec une id de token. Le personnage qui agit est celui qui est s\xE9lectionn\xE9.
    • -
    • option --disque : le premier argument, optionnel, est l'id ou le nom d'un token qui repr\xE9sente un personnage, le deuxi\xE8me argument un rayon. Cela s\xE9lectionne tous les tokens \xE0 une distance de moins que le rayon du premier argument (ou du personnage \xE0 l'origine de l'effet, si le premier argument est absent). Si un troisi\xE8me argument est donn\xE9, il est interpr\xE9t\xE9 comme la port\xE9e maximum entre le centre du disque et le token du personnage \xE0 l'origine de l'effet. Si le premier argument repr\xE9sente un personnage avec un max de PV \xE0 0, il est compris comme un personnage fictif cr\xE9\xE9 juste pour d\xE9finir le disque, et il sera supprim\xE9 apr\xE8s la s\xE9lection. \xC0 noter que le script cr\xE9e par d\xE9faut un tel personnage, utilisable par tous, et appel\xE9 Cible.
    • +
    • Le MJ lance la macro en sélectionnant les cibles
    • +
    • option --allies : cela fait chercher tous les handout dont le nom est Equipe suivi d'un nom, et tels que le handout contienne une liste de noms (un par ligne), parmis lesquels, celui du personnage qui agit. Le personnage qui agit est celui qui est sélectionné. Les cibles sont tous les alliés du personnage sélectionné, mais pas le personnage lui-même. Attention, les noms de personnages ne doivent pas contenir de balise XML (texte encadré par des < et >). Optionellement, on peut préciser une distance maximale entre le personnage sélectionné et ses allies.
    • +
    • option --alliesEnVue : comme --allies, mais ne garde que les alliés en vue (en fonction des murs sur le layer lumière).
    • +
    • option --equipe nom : agit sur tous les personnages mentionnés dans le handout s'appelant Equipe nom.
    • +
    • option --self : pour rajouter le personnage sélectionné. Utile si on veut le personnage et ses alliés, par exemple.
    • +
    • option --target : pour ajouter une seule cible, avec une id de token. Le personnage qui agit est celui qui est sélectionné.
    • +
    • option --disque : le premier argument, optionnel, est l'id ou le nom d'un token qui représente un personnage, le deuxième argument un rayon. Cela sélectionne tous les tokens à une distance de moins que le rayon du premier argument (ou du personnage à l'origine de l'effet, si le premier argument est absent). Si un troisième argument est donné, il est interprété comme la portée maximum entre le centre du disque et le token du personnage à l'origine de l'effet. Si le premier argument représente un personnage avec un max de PV à 0, il est compris comme un personnage fictif créé juste pour définir le disque, et il sera supprimé après la sélection. À noter que le script crée par défaut un tel personnage, utilisable par tous, et appelé Cible.
    • option --disquePasseMur : comme --disque, mais l'effet traverse les murs.
    • -
    • option --enVue : s\xE9lectionne tous les tokens en vue du personnage qui lance l'effet. Accepte aussi un argument d'id de token, dans ce cas on garde les token en vue de celui avec cette id.
    • -
    • option --saufAllies permet d'exclure les alli\xE9s de la s\xE9lection (voir plus haut pour la d\xE9finition des alli\xE9s).
    • +
    • option --enVue : sélectionne tous les tokens en vue du personnage qui lance l'effet. Accepte aussi un argument d'id de token, dans ce cas on garde les token en vue de celui avec cette id.
    • +
    • option --saufAllies permet d'exclure les alliés de la sélection (voir plus haut pour la définition des alliés).

    -
    Exemple d'handout avec diff\xE9rentes \xE9quipes.
    +
    Exemple d'handout avec différentes équipes.

    1.5 Options de mana

    -

    COF sous ses diff\xE9rentes formes est une bo\xEEte \xE0 outils et nombreuses sont les variantes de syst\xE8me de magie qui peuvent \xEAtre utilis\xE9es. Le script propose un support pour les plus populaires d'entre elles. Voici quelques consignes pour les impl\xE9menter.

    -

    Sp\xE9cifier un co\xFBt en mana

    +

    COF sous ses différentes formes est une boîte à outils et nombreuses sont les variantes de système de magie qui peuvent être utilisées. Le script propose un support pour les plus populaires d'entre elles. Voici quelques consignes pour les implémenter.

    +

    Spécifier un coût en mana

      -
    • Les points de mana sont d\xE9pens\xE9s en ajoutant l'option --mana X \xE0 une action ou dans les options d'une attaque. Toutes les capacit\xE9s impl\xE9ment\xE9es dans la documentation donnent par d\xE9faut le co\xFBt en mana selon les r\xE8gles de base.
    • -
    • M\xEAme un sort qui ne co\xFBte pas de mana devrait utiliser --mana 0. Cela permet au script de dissiper automatiquement un effet g\xE9n\xE9r\xE9 par un lanceur de sort mis hors de combat.
    • -
    • Une option d'affichage disponible via !cof-options permet de demander au script d'afficher explicitement dans le chat toute d\xE9pense de PM effectu\xE9e par un personnage.
    • +
    • Les points de mana sont dépensés en ajoutant l'option --mana X à une action ou dans les options d'une attaque. Toutes les capacités implémentées dans la documentation donnent par défaut le coût en mana selon les règles de base.
    • +
    • Même un sort qui ne coûte pas de mana devrait utiliser --mana 0. Cela permet au script de dissiper automatiquement un effet généré par un lanceur de sort mis hors de combat.
    • +
    • Une option d'affichage disponible via !cof-options permet de demander au script d'afficher explicitement dans le chat toute dépense de PM effectuée par un personnage.
    -

    Syst\xE8me de base (COF p. 79)

    -

    Le support des effets suppl\xE9mentaires \xE0 disposition du lanceur de sort sont g\xE9r\xE9es via l'utilisation d'options sur les commandes utilis\xE9es.

    +

    Système de base (COF p. 79)

    +

    Le support des effets supplémentaires à disposition du lanceur de sort sont gérées via l'utilisation d'options sur les commandes utilisées.

    • Magie rapide : pas de support particulier
    • -
    • Magie puissante (d\xE9s) : utiliser l'option --puissant dans vos abilities ou attaques
    • -
    • Magie puissante (port\xE9e) : utiliser l'option --puissant portee dans vos abilities ou attaques
    • -
    • Magie puissante (dur\xE9e) : utiliser l'option --puissant duree dans vos abilities ou attaques
    • +
    • Magie puissante (dés) : utiliser l'option --puissant dans vos abilities ou attaques
    • +
    • Magie puissante (portée) : utiliser l'option --puissant portee dans vos abilities ou attaques
    • +
    • Magie puissante (durée) : utiliser l'option --puissant duree dans vos abilities ou attaques
    -

    On peut facilement combiner ces options avec un input de choix roll20 qui permettra au joueur de choisir le type d'incantation lorsqu'il lance le sort, tout en sp\xE9cifiant la d\xE9pense de Mana.

    -

    --mana X ?{Incantation ?|Rapide,&#32;|Puissante (L),--puissant|Port\xE9e \xE9tendue (L),--puissant portee|Dur\xE9e \xE9tendue (L),--puissant duree}

    +

    On peut facilement combiner ces options avec un input de choix roll20 qui permettra au joueur de choisir le type d'incantation lorsqu'il lance le sort, tout en spécifiant la dépense de Mana.

    +

    --mana X ?{Incantation ?|Rapide,&#32;|Puissante (L),--puissant|Portée étendue (L),--puissant portee|Durée étendue (L),--puissant duree}

    Mana Totale (COF p. 180)

    -

    La premi\xE8re chose \xE0 faire est d'activer l'option Mana totale via !cof-options. Pour le reste, vous pouvez r\xE9utiliser le principe du syst\xE8me de base ci-dessus.

    -
    Co\xFBt al\xE9atoire
    -

    Vous pouvez utiliser des lancers de d\xE9s dans vos options --mana. Par exemple pour un sort de rang 1, on peut renseigner --mana [[1d3]]. L'option d'affichage de la d\xE9pense de mana prend ici tout son sens, activable via !cof-options.

    +

    La première chose à faire est d'activer l'option Mana totale via !cof-options. Pour le reste, vous pouvez réutiliser le principe du système de base ci-dessus.

    +
    Coût aléatoire
    +

    Vous pouvez utiliser des lancers de dés dans vos options --mana. Par exemple pour un sort de rang 1, on peut renseigner --mana [[1d3]]. L'option d'affichage de la dépense de mana prend ici tout son sens, activable via !cof-options.

    Contrecoup
    -

    Vous pouvez activer la r\xE8gle sp\xE9cifique de Contrecoup via !cof-options.

    -

    Temp\xEAte de Mana (COF Compagnon p. 105)

    -

    Le script impl\xE9mente un support complet des r\xE8gles de Temp\xEAte de Mana. Pour ce faire, il faut ajouter les options --tempeteDeMana --rang X sur les sorts combinables avec Temp\xEAte de Mana. L'option rang permet d'indiquer le rang du sort afin que le script puisse calculer le maximum de PM qu'on peut d\xE9penser lors du lancement du sort. Pour mettre \xE7a de mani\xE8re g\xE9n\xE9rique sur une action ou une attaque et permettre au joueur de choisir de faire appel \xE0 Temp\xEAte de Mana ou pas, on peut utiliser :

    -

    --mana X --rang Y ?{Temp\xEAte de Mana ?|Non,&#32;|Oui,--tempeteDeMana}

    -

    Temp\xEAte de Mana est compatible avec Mana Totale et Br\xFBlure de Magie.

    +

    Vous pouvez activer la règle spécifique de Contrecoup via !cof-options.

    +

    Tempête de Mana (COF Compagnon p. 105)

    +

    Le script implémente un support complet des règles de Tempête de Mana. Pour ce faire, il faut ajouter les options --tempeteDeMana --rang X sur les sorts combinables avec Tempête de Mana. L'option rang permet d'indiquer le rang du sort afin que le script puisse calculer le maximum de PM qu'on peut dépenser lors du lancement du sort. Pour mettre ça de manière générique sur une action ou une attaque et permettre au joueur de choisir de faire appel à Tempête de Mana ou pas, on peut utiliser :

    +

    --mana X --rang Y ?{Tempête de Mana ?|Non,&#32;|Oui,--tempeteDeMana}

    +

    Tempête de Mana est compatible avec Mana Totale et Brûlure de Magie.

    Option altruiste
    -

    Si vous d\xE9sirez jouer avec l'option de Magie altruiste, il suffit de changer l'option en --tempeteDeMana altruiste sur les sorts o\xF9 c'est utile.

    +

    Si vous désirez jouer avec l'option de Magie altruiste, il suffit de changer l'option en --tempeteDeMana altruiste sur les sorts où c'est utile.

    Terres d'Arran (COTA p. 112)

    -

    Premi\xE8re chose \xE0 faire, activer l'option Br\xFBlure de Magie via !cof-options. Note : si vous utilisez l'option de Br\xFBlure de Magie avec l'option Mana Totale, vous pouvez utiliser un pr\xE9dicat coefPVMana qui va diviser le nombre de PVs d\xE9pens\xE9 par point de mana.

    -

    Vous pouvez ensuite r\xE9utiliser le m\xEAme principe que le syst\xE8me de base en combinant d\xE9pense de Mana et effets suppl\xE9mentaires. Voici un exemple pour une Boule de Feu (Voie de l'\xE9l\xE9mentaliste, rang 4) :

    -

    --mana 2 ?{Incantation ?|Normale,--mana 2|\xC9conome (L),&#32;|Puissante (L),--mana 2 --puissant|Port\xE9e \xE9tendue (L),--mana 2 --puissant portee} (notez que les co\xFBt total pour une incantation normale sera de 4 points de mana)

    +

    Première chose à faire, activer l'option Brûlure de Magie via !cof-options. Note : si vous utilisez l'option de Brûlure de Magie avec l'option Mana Totale, vous pouvez utiliser un prédicat coefPVMana qui va diviser le nombre de PVs dépensé par point de mana.

    +

    Vous pouvez ensuite réutiliser le même principe que le système de base en combinant dépense de Mana et effets supplémentaires. Voici un exemple pour une Boule de Feu (Voie de l'élémentaliste, rang 4) :

    +

    --mana 2 ?{Incantation ?|Normale,--mana 2|Économe (L),&#32;|Puissante (L),--mana 2 --puissant|Portée étendue (L),--mana 2 --puissant portee} (notez que les coût total pour une incantation normale sera de 4 points de mana)

    -

    1.6 R\xE8gles optionnelles utilis\xE9es

    +

    1.6 Règles optionnelles utilisées

    -

    Le script supporte l'utilisation de la r\xE8gle des points de chance et des points de r\xE9cup\xE9ration.

    -

    J'ai aussi choisi, comme propos\xE9 par Kegron, de diminuer la DEF de tous les protagonistes apr\xE8s un certain nombre de tours de combat (-2 tous les 5 tours, peut \xEAtre d\xE9sactiv\xE9 pendant un combat par la commande !cof-usure-off, ou bien dans les options de jeu).

    -

    Le script utilise aussi par d\xE9faut une r\xE8gle de blessure grave : chaque fois qu'un personnage tombe \xE0 0 PV, il encaisse une perte d'un point de r\xE9cup\xE9ration. S'il \xE9tait \xE0 0 points de r\xE9cup\xE9ration, il devient gravement bless\xE9, ce qui le rend affaibli. Si le personnage \xE9tait d\xE9j\xE0 gravement bless\xE9, il meurt. Pour r\xE9cup\xE9rer d'une blessure grave, le personnage doit se reposer une nuit, et r\xE9ussir un test de CON difficult\xE9 8 (avec le d12). Il est impossible de r\xE9g\xE9n\xE9rer les points de r\xE9cup\xE9ration quand on est gravement bless\xE9.

    -

    Le script utilise \xE9galement une r\xE8gle de dommages importants : chaque fois qu'un PJ re\xE7oit plus de dommages en une fois que la somme de sa valeur de constitution et de son niveau, il perd 1PR et la r\xE8gle de blessure grave s'applique. S'il \xE9tait d\xE9j\xE0 bless\xE9 mais qu'il lui reste des PV, il tombe inconscient. Les deux r\xE8gles sont d\xE9sactivables s\xE9par\xE9ment via !cof-options, dans la section dommages.

    -

    Le script propose \xE9galement quelques autres options qui sont activables et/ou modifiables via la commande !cof-options. Quelques exemples :

    +

    Le script supporte l'utilisation de la règle des points de chance et des points de récupération.

    +

    J'ai aussi choisi, comme proposé par Kegron, de diminuer la DEF de tous les protagonistes après un certain nombre de tours de combat (-2 tous les 5 tours, peut être désactivé pendant un combat par la commande !cof-usure-off, ou bien dans les options de jeu).

    +

    Le script utilise aussi par défaut une règle de blessure grave : chaque fois qu'un personnage tombe à 0 PV, il encaisse une perte d'un point de récupération. S'il était à 0 points de récupération, il devient gravement blessé, ce qui le rend affaibli. Si le personnage était déjà gravement blessé, il meurt. Pour récupérer d'une blessure grave, le personnage doit se reposer une nuit, et réussir un test de CON difficulté 8 (avec le d12). Il est impossible de régénérer les points de récupération quand on est gravement blessé.

    +

    Le script utilise également une règle de dommages importants : chaque fois qu'un PJ reçoit plus de dommages en une fois que la somme de sa valeur de constitution et de son niveau, il perd 1PR et la règle de blessure grave s'applique. S'il était déjà blessé mais qu'il lui reste des PV, il tombe inconscient. Les deux règles sont désactivables séparément via !cof-options, dans la section dommages.

    +

    Le script propose également quelques autres options qui sont activables et/ou modifiables via la commande !cof-options. Quelques exemples :

    • Initiative variable (individuelle / de groupe)
    • -
    • Versions alternatives de capacit\xE9s (interchangeable, forme d'arbre, rune de protection)
    • -
    • Critiques \xE9tendus
    • +
    • Versions alternatives de capacités (interchangeable, forme d'arbre, rune de protection)
    • +
    • Critiques étendus
    • Dommages minimums
    • Attaques de groupe

    2. Actions principales

    -

    Pour la plupart des actions ci-dessous, il est g\xE9n\xE9ralement utile de cr\xE9er des macros facilitant leur utilisation. Pour mettre en place un jeu de macros par d\xE9faut, vous pouvez taper !cof-set-macros dans le chat. Si vous souhaitez red\xE9finir des macros existantes, vous pouvez taper !cof-set-macros --force.

    +

    Pour la plupart des actions ci-dessous, il est généralement utile de créer des macros facilitant leur utilisation. Pour mettre en place un jeu de macros par défaut, vous pouvez taper !cof-set-macros dans le chat. Si vous souhaitez redéfinir des macros existantes, vous pouvez taper !cof-set-macros --force.

    2.1 Le combat

    Initiative : !cof-init

    -

    Les tokens s\xE9lectionn\xE9s sont ajout\xE9 au tracker de tour. Si celui-ci n'existe pas, un nouveau est cr\xE9\xE9, avec compteur de tour \xE0 1, et on rentre en combat. Les tokens ayant un pr\xE9dicat aucuneActionCombat ne sont jamais ajout\xE9s au turn tracker.

    -

    Une option du script (ajustable en utilisant !cof-options) permet d'utiliser la r\xE8gle de l'initiative variable (ajout d'un d6 explosif \xE0 l'initiative). Il est alors possible de faire lancer les d\xE9s d'initiative par les joueurs.

    -

    Les r\xE8gles de tri suivent ce qui est donn\xE9 p 70 : priorit\xE9 aux PJs. Pour l'instant, on distingue un PJ d'un PNJ au d\xE9 de vie : si le personnage d'a pas de d\xE9 de vie, c'est un PNJ. Ensuite, entre PJs, priorit\xE9 \xE0 la plus haute sagesse. Pour les PNJ, c'est al\xE9atoire.

    -

    \xC0 chaque instant, le token dont c'est le tour d'agir est signal\xE9 par une aura qui bouge lentement. L'image de cette aura peut \xEAtre modifi\xE9e dans les options (!cof-options images), et il est possible de sp\xE9cifier une aura pour chaque token, en ajoutant une ligne dans le champ GM Notes du token (en bas de la partie basique de l'\xE9dition du token). Cette ligne doit commencer par init_aura:, et contenir une url valide pour un token. N'oubliez pas de sauvegarder le token comme token par d\xE9faut our un personnage si vous voulez que ce personnage ait toujours cette aura.

    +

    Les tokens sélectionnés sont ajouté au tracker de tour. Si celui-ci n'existe pas, un nouveau est créé, avec compteur de tour à 1, et on rentre en combat. Les tokens ayant un prédicat aucuneActionCombat ne sont jamais ajoutés au turn tracker.

    +

    Une option du script (ajustable en utilisant !cof-options) permet d'utiliser la règle de l'initiative variable (ajout d'un d6 explosif à l'initiative). Il est alors possible de faire lancer les dés d'initiative par les joueurs.

    +

    Les règles de tri suivent ce qui est donné p 70 : priorité aux PJs. Pour l'instant, on distingue un PJ d'un PNJ au dé de vie : si le personnage d'a pas de dé de vie, c'est un PNJ. Ensuite, entre PJs, priorité à la plus haute sagesse. Pour les PNJ, c'est aléatoire.

    +

    À chaque instant, le token dont c'est le tour d'agir est signalé par une aura qui bouge lentement. L'image de cette aura peut être modifiée dans les options (!cof-options images), et il est possible de spécifier une aura pour chaque token, en ajoutant une ligne dans le champ GM Notes du token (en bas de la partie basique de l'édition du token). Cette ligne doit commencer par init_aura:, et contenir une url valide pour un token. N'oubliez pas de sauvegarder le token comme token par défaut our un personnage si vous voulez que ce personnage ait toujours cette aura.

    Il est possible de laisser les joueurs passer leur tour, en utilisant la commande !cof-tour-suivant. Une utilisation possible est de le mettre en macro dans les actions du tour (voir Actions du tour ci-dessous).

    Astuces :
      -
    • !cof-attendre ?{Nouvelle initiative} : Permet d'attendre avant d'agir en r\xE9duisant temporairement son initiative.

    • -
    • Il est possible de se passer de l'aura qui bouge, et d'utiliser \xE0 la place une ic\xF4ne de drapeau ou avec la syntaxe - !cof-init --aura une aura autour du Token de couleur verte (ou rouge si le personnage n'est pas contr\xF4l\xE9 par un joueur ou dans une \xE9quipe contenant un personnage contr\xF4l\xE9 par un joueur). Pour cela, d\xE9sactiver l'initiative dynamique dans les options d'affichage (!cof-options affichage). +
    • !cof-attendre ?{Nouvelle initiative} : Permet d'attendre avant d'agir en réduisant temporairement son initiative.

    • +
    • Il est possible de se passer de l'aura qui bouge, et d'utiliser à la place une icône de drapeau ou avec la syntaxe + !cof-init --aura une aura autour du Token de couleur verte (ou rouge si le personnage n'est pas contrôlé par un joueur ou dans une équipe contenant un personnage contrôlé par un joueur). Pour cela, désactiver l'initiative dynamique dans les options d'affichage (!cof-options affichage).
    @@ -266,349 +266,353 @@
    Astuces :

    Liste d'actions pour le personnage dont c'est le tour

    -

    Le script affiche, pour le personnage dont c'est le tour, une liste d'actions. Cette liste est chuchot\xE9e au joueur qui contr\xF4le le personnage, ou si aucun joueur le contr\xF4lant n'est connect\xE9, au MJ. Elle se compose par d\xE9faut des attaques du personnage et des actions d'attendre, se d\xE9fendre et faire une manoeuvre. - Pour voir ce message en dehors du changement d'initiative, ou pour le MJ, on peut utiliser !cof-liste-actions en s\xE9lectionnant le token (un bon candidat pour une macro de type token action, d'ailleurs g\xE9n\xE9r\xE9 par la commande !cof-set-macros). - Pour contr\xF4ler ce qui est affich\xE9 dans cette liste, vous pouvez principalement utiliser la liste des attaques du personnage et surtout la partie script de la fiche.

    -
    Les attaques affich\xE9es
    -

    Il est possible de ne pas afficher une attaque en d\xE9cochant la case sous le d\xE9 dans les options d'attaque. Les attaques sont affich\xE9es dans l'ordre des labels d'attaques. les attaques avec des conditions impossibles (du genre limite par jour \xE9puis\xE9e, etc.) ne sont pas affich\xE9es.

    -

    \xC0 cela se rajoute \xE9ventuellement l'attaque avec l'arme en main. \xC0 c\xF4t\xE9 de cette attaque, le script propose un bouton pour rengainer l'arme ou en d\xE9gainer une autre (parmis les armes de la fiche coch\xE9es). On peut modifier cette liste des armes \xE0 d\xE9gainer en utilisant des pr\xE9dicats actionDegainern, de valeur le label de l'arme \xE0 afficher en position n dans la liste (seulement pour les premi\xE8res armes, il n'est pas possible de ne sp\xE9cifier que la 2nde arme ou la 1\xE8re et le 3\xE8me). On peut ainsi faire afficher 2 armes \xE0 d\xE9gainer en m\xEAme temps en s\xE9parant les labels d'un - (par exemple pour faire d\xE9gainer l'arme 1 en main droite et l'arme 4 en main gauche, en premi\xE8re position dans la liste, on \xE9crira actionDegainer1:1-4). \xC0 noter que si aucune arme n'est en main, et qu'aucune attaque naturelle n'est coch\xE9e, le script va tout de m\xEAme afficher une des attaques naturelles non coch\xE9es \xE0 la place de l'arme en main. Cela permet d'avoir une attaque que l'on n'affiche que quand on n'a pas d'arme en main.

    -

    Notez qu'il est possible d'avoir une arme par d\xE9faut en main, en ajoutant un pr\xE9dicat armeParDefaut, de valeur le label de l'attaque correspondante. C'est parfois bien pratique pour ne pas avoir \xE0 d\xE9gainer les armes de chacun des orques en embuscade, par exemple.

    -
    Choisir les actions \xE0 afficher
    -

    Pour changer les attaques affich\xE9es par d\xE9faut, rajouter des actions \xE0 la liste d'actions du tour, ou utiliser de nouvelles listes, il faut aller dans l'onglet Script de la fiche de personnage.

    +

    Le script affiche, pour le personnage dont c'est le tour, une liste d'actions. Cette liste est chuchotée au joueur qui contrôle le personnage, ou si aucun joueur le contrôlant n'est connecté, au MJ. Elle se compose par défaut des attaques du personnage et des actions d'attendre, se défendre et faire une manoeuvre. + Pour voir ce message en dehors du changement d'initiative, ou pour le MJ, on peut utiliser !cof-liste-actions en sélectionnant le token (un bon candidat pour une macro de type token action, d'ailleurs généré par la commande !cof-set-macros). + Pour contrôler ce qui est affiché dans cette liste, vous pouvez principalement utiliser la liste des attaques du personnage et surtout la partie script de la fiche.

    +
    Les attaques affichées
    +

    Il est possible de ne pas afficher une attaque en décochant la case sous le dé dans les options d'attaque. Les attaques sont affichées dans l'ordre des labels d'attaques. les attaques avec des conditions impossibles (du genre limite par jour épuisée, etc.) ne sont pas affichées.

    +

    À cela se rajoute éventuellement l'attaque avec l'arme en main. À côté de cette attaque, le script propose un bouton pour rengainer l'arme ou en dégainer une autre (parmis les armes de la fiche cochées). On peut modifier cette liste des armes à dégainer en utilisant des prédicats actionDegainern, de valeur le label de l'arme à afficher en position n dans la liste (seulement pour les premières armes, il n'est pas possible de ne spécifier que la 2nde arme ou la 1ère et le 3ème). On peut ainsi faire afficher 2 armes à dégainer en même temps en séparant les labels d'un - (par exemple pour faire dégainer l'arme 1 en main droite et l'arme 4 en main gauche, en première position dans la liste, on écrira actionDegainer1:1-4). À noter que si aucune arme n'est en main, et qu'aucune attaque naturelle n'est cochée, le script va tout de même afficher une des attaques naturelles non cochées à la place de l'arme en main. Cela permet d'avoir une attaque que l'on n'affiche que quand on n'a pas d'arme en main.

    +

    Notez qu'il est possible d'avoir une arme par défaut en main, en ajoutant un prédicat armeParDefaut, de valeur le label de l'attaque correspondante. C'est parfois bien pratique pour ne pas avoir à dégainer les armes de chacun des orques en embuscade, par exemple.

    +
    Choisir les actions à afficher
    +

    Pour changer les attaques affichées par défaut, rajouter des actions à la liste d'actions du tour, ou utiliser de nouvelles listes, il faut aller dans l'onglet Script de la fiche de personnage.

    Exemple d'une liste d'actions pour un magicien
    -

    Pour rajouter des actions \xE0 montrer, il faut ajouter des lignes en-dessous de Montrer l'arme en main et d\xE9gainer. La case coch\xE9e devant chaque action peut \xEAtre d\xE9coch\xE9e pour ne pas afficher l'action. Les actions seront affich\xE9e dans l'ordre des num\xE9ros d'action. Attention, si deux actions ont le m\xEAme num\xE9ro, une des deux ne sera pas affich\xE9e. Le titre de l'action peut soit \xEAtre directement une commande (commen\xE7ant par %, # ou !), et dans ce cas l'action affich\xE9e sera d\xE9termin\xE9e par le script, soit du texte qui sera affich\xE9 tel quel. Dans ce cas, il sera souvent n\xE9cessaire de pr\xE9ciser le code de l'action : cliquer sur la roue au bout \xE0 droite de la ligne de l'action pour faire appara\xEEtre les lignes de condition et de code. La ligne de conditions n'est pas encore utilis\xE9e par le script.

    -

    Il existe un certain nombre de commandes sp\xE9ciales, qui peuvent \xEAtre rentr\xE9e dans le titre ou le code : +

    Pour rajouter des actions à montrer, il faut ajouter des lignes en-dessous de Montrer l'arme en main et dégainer. La case cochée devant chaque action peut être décochée pour ne pas afficher l'action. Les actions seront affichée dans l'ordre des numéros d'action. Attention, si deux actions ont le même numéro, une des deux ne sera pas affichée. Le titre de l'action peut soit être directement une commande (commençant par %, # ou !), et dans ce cas l'action affichée sera déterminée par le script, soit du texte qui sera affiché tel quel. Dans ce cas, il sera souvent nécessaire de préciser le code de l'action : cliquer sur la roue au bout à droite de la ligne de l'action pour faire apparaître les lignes de condition et de code. La ligne de conditions n'est pas encore utilisée par le script.

    +

    Il existe un certain nombre de commandes spéciales, qui peuvent être rentrée dans le titre ou le code :

      -
    • !attaques fera afficher toutes les attaques coch\xE9es de la fiche
    • -
    • !arme-en-main affichera l'attaque correspondant \xE0 l'arme en main, ou si aucune arme n'est en main, une attaque naturelle non coch\xE9e, et si il n'y en a pas non plus, une attaque \xE0 mains nues. Vous pouvez faire suivre cette commandes d'options d'attaque, comme --m2d20.
    • -
    • !options passera en option \xE0 toutes les actions suivantes tout ce que vous \xE9crirez dans la m\xEAme ligne (par exemple !options --traquenard passe l'option --traquenard \xE0 toutes les actions suivantes).
    • +
    • !attaques fera afficher toutes les attaques cochées de la fiche
    • +
    • !arme-en-main affichera l'attaque correspondant à l'arme en main, ou si aucune arme n'est en main, une attaque naturelle non cochée, et si il n'y en a pas non plus, une attaque à mains nues. Vous pouvez faire suivre cette commandes d'options d'attaque, comme --m2d20.
    • +
    • !options passera en option à toutes les actions suivantes tout ce que vous écrirez dans la même ligne (par exemple !options --traquenard passe l'option --traquenard à toutes les actions suivantes).

    Autres listes d'action
    -

    Il est possible d'ouvrir d'autre listes d'actions, \xE0 partir des commandes ou m\xEAme d'une liste d'actions. La fiche propose 4 emplacements pour ces listes d'action, mais si cela ne suffit pas, vous pouvez utiliser des abilities dont le nom commence et termine par #. Pour faire r\xE9f\xE9rence \xE0 une liste dans une action, inscrivez simplement le nom de la liste dans le titre de l'action et s\xE9lectionnez Liste d'actions dans le menu d\xE9roulant \xE0 c\xF4t\xE9. Les listes d'action sur la fiche fonctionnent de la m\xEAme fa\xE7on que la liste des actions du tour, sauf qu'il n'y a pas d'affichage par d\xE9faut des attaques ou de l'arme en main (pour cela, une simple ligne avec en titre #Attaque -1 permet d'y rem\xE9dier), et que la liste peut avoir une liste d'options globales (cliquer sur la roue \xE0 droite du nom de la liste).

    -

    Pour les listes d'actions suppl\xE9mentaires, dans les abilities, il faut respecter la syntaxe suivante : +

    Il est possible d'ouvrir d'autre listes d'actions, à partir des commandes ou même d'une liste d'actions. La fiche propose 4 emplacements pour ces listes d'action, mais si cela ne suffit pas, vous pouvez utiliser des abilities dont le nom commence et termine par #. Pour faire référence à une liste dans une action, inscrivez simplement le nom de la liste dans le titre de l'action et sélectionnez Liste d'actions dans le menu déroulant à côté. Les listes d'action sur la fiche fonctionnent de la même façon que la liste des actions du tour, sauf qu'il n'y a pas d'affichage par défaut des attaques ou de l'arme en main (pour cela, une simple ligne avec en titre #Attaque -1 permet d'y remédier), et que la liste peut avoir une liste d'options globales (cliquer sur la roue à droite du nom de la liste).

    +

    Pour les listes d'actions supplémentaires, dans les abilities, il faut respecter la syntaxe suivante :

    • une action par ligne
    • chaque ligne est donc soit un commentaire, soit une macro (qui commence par #), soit une ability (qui commence par %), soit une commande qui commence par !
    • -
    • l'action affich\xE9e sera le nom de la macro ou de l'ability (sauf pour les attaques, pour lesquelles le nom de l'arme sera affich\xE9e)
    • +
    • l'action affichée sera le nom de la macro ou de l'ability (sauf pour les attaques, pour lesquelles le nom de l'arme sera affichée)
    • les commandes disponibles sont !options et !attaques.
    • -
    • pour les listes d'actions, il suffit de mettre %# suivi du nom de la liste et termin\xE9 par #.
    • +
    • pour les listes d'actions, il suffit de mettre %# suivi du nom de la liste et terminé par #.
    -

    Il est aussi possible de faire afficher une liste quelconque avec une commande, avec !cof-liste-actions nom (o\xF9 le nom est celui de la liste, ou bien de l'ability sans les #). Par exemple, si on ne souhaite pas afficher la liste compl\xE8te des sorts d'un personnage \xE0 son tour, on peut faire une liste Sorts, puis faire une macro qui lance !cof-liste-actions Sorts pour que le joueur puisse afficher la liste quand il le souhaite.

    +

    Il est aussi possible de faire afficher une liste quelconque avec une commande, avec !cof-liste-actions nom (où le nom est celui de la liste, ou bien de l'ability sans les #). Par exemple, si on ne souhaite pas afficher la liste complète des sorts d'un personnage à son tour, on peut faire une liste Sorts, puis faire une macro qui lance !cof-liste-actions Sorts pour que le joueur puisse afficher la liste quand il le souhaite.

    Attaquer une (ou plusieurs) cible : !cof-attack @{selected|token_id} @{target|token_id} n

    -

    o\xF9 n est un argument optionnel qui peut soit correspondre au label de l'attaque sur la fiche du personnage (ce label est automatiquement g\xE9n\xE9r\xE9 par la fiche et affich\xE9 juste devant le nom), soit \xEAtre le nom de l'attaque. Si cet argument est -1, le script cherchera si le personnage a une arme en main et utilisera cette arme. Si c'est -2, il va chercher l'arme en main gauche. Si cet argument est absent ou qu'il ne correspond pas \xE0 un label de la fiche du personnage, l'attaque aura les valeurs par d\xE9faut d'une attaque au contact infligeant 1d4 DM. Pour plus de facilit\xE9, vous pouvez utiliser la macro Attaque qui fait !cof-attack @{selected|token_id} @{target|token_id}

    +

    n est un argument optionnel qui peut soit correspondre au label de l'attaque sur la fiche du personnage (ce label est automatiquement généré par la fiche et affiché juste devant le nom), soit être le nom de l'attaque. Si cet argument est -1, le script cherchera si le personnage a une arme en main et utilisera cette arme. Si c'est -2, il va chercher l'arme en main gauche. Si cet argument est absent ou qu'il ne correspond pas à un label de la fiche du personnage, l'attaque aura les valeurs par défaut d'une attaque au contact infligeant 1d4 DM. Pour plus de facilité, vous pouvez utiliser la macro Attaque qui fait !cof-attack @{selected|token_id} @{target|token_id}

    -

    L'attaque tient alors compte de toutes les informations de l'attaque, y compris chances de critique, port\xE9e, type d'attaque, type de d\xE9g\xE2s et autres options sp\xE9cifi\xE9es sur la fiche. Par d\xE9faut, l'attaque montre le label, le nom de l'attaque, le calcul du bonus d'attaque, le calcul des d\xE9g\xE2ts, la port\xE9e et un champ SP\xC9CIAL (ou encore appel\xE9 divers). En cliquant sur la roue au bout \xE0 droite de cette ligne, on affiche une deuxi\xE8me ligne, avec un case \xE0 d\xE9cocher pour ne pas faire appara\xEEtre l'attaque \xE0 chaque tour, un choix de type d'attaque, des modificateurs, un choix de type de deg\xE2ts et un champ d'options. Les modificateurs sont constitu\xE9s d'options sans argument, s\xE9par\xE9e par une espace. Les options sont reprises telles quels comme un argument \xE0 l'attaque (voir plus bas pour le liste de ces options). Attention, pour l'instant ne traite correctment les jets (parties entre crochets) et les demandes au joueur (de type ?{question?}) que si on passe par une liste d'actions (donc pas directement en faisant #Attaque 1 dans le chat). Une troisi\xE8me ligne peut aussi s'afficher, pour g\xE9rer le nombre d'armes de jet, ou pour les armes port\xE9es, pour indiquer des pr\xE9dicats actifs seulement quand on porte l'arme. Il est possible de sp\xE9cifier une arme batarde (pouvant se porter \xE0 une ou deux mains) en renseignant un pr\xE9dicat batarde de valeur le d\xE9 de DM \xE0 utiliser quand on porte l'arme \xE0 deux mains.

    +

    L'attaque tient alors compte de toutes les informations de l'attaque, y compris chances de critique, portée, type d'attaque, type de dégâs et autres options spécifiées sur la fiche. Par défaut, l'attaque montre le label, le nom de l'attaque, le calcul du bonus d'attaque, le calcul des dégâts, la portée et un champ SPÉCIAL (ou encore appelé divers). En cliquant sur la roue au bout à droite de cette ligne, on affiche une deuxième ligne, avec un case à décocher pour ne pas faire apparaître l'attaque à chaque tour, un choix de type d'attaque, des modificateurs, un choix de type de degâts et un champ d'options. Les modificateurs sont constitués d'options sans argument, séparée par une espace. Les options sont reprises telles quels comme un argument à l'attaque (voir plus bas pour le liste de ces options). Attention, pour l'instant ne traite correctment les jets (parties entre crochets) et les demandes au joueur (de type ?{question?}) que si on passe par une liste d'actions (donc pas directement en faisant #Attaque 1 dans le chat). Une troisième ligne peut aussi s'afficher, pour gérer le nombre d'armes de jet, ou pour les armes portées, pour indiquer des prédicats actifs seulement quand on porte l'arme. Il est possible de spécifier une arme batarde (pouvant se porter à une ou deux mains) en renseignant un prédicat batarde de valeur le dé de DM à utiliser quand on porte l'arme à deux mains.

    Exemple d'attaques.
    -

    En l'absence de label, on peut sp\xE9cifier ces informations sous forme d'options d'attaque

    +

    En l'absence de label, on peut spécifier ces informations sous forme d'options d'attaque

    -

    Malus ou bonus temporaire \xE0 une attaque : utiliser la barre 3.

    -

    Toutes les attaques ayant une port\xE9e non nulles sont consid\xE9r\xE9es par le script comme des attaques \xE0 distance.

    -

    Le test d'attaque \xE0 distance tient compte de la port\xE9e (malus de -1 \xE0 -5 si distance entre port\xE9e et deux fois cette valeur), ainsi que des tokens sur le trajet de l'attaque. Une attaque de trop loin ne porte jamais.

    +

    Malus ou bonus temporaire à une attaque : utiliser la barre 3.

    +

    Toutes les attaques ayant une portée non nulles sont considérées par le script comme des attaques à distance.

    +

    Le test d'attaque à distance tient compte de la portée (malus de -1 à -5 si distance entre portée et deux fois cette valeur), ainsi que des tokens sur le trajet de l'attaque. Une attaque de trop loin ne porte jamais.

    Utiliser une attaque fait rentrer l'attaquant en combat (et le rajoute au turn tracker).

    -

    Il existe une version sp\xE9cialis\xE9e permettant de faire des d\xE9g\xE2ts dans un disque centr\xE9 sur un token, !cof-explosion, dont le premier argument doit \xEAtre le label d'une attaque.

    +

    Il existe une version spécialisée permettant de faire des dégâts dans un disque centré sur un token, !cof-explosion, dont le premier argument doit être le label d'une attaque.

    Options pour l'attaque :

    - Toutes les options sans arguments peuvent \xEAtre directement utilis\xE9es comme modificateurs dans le liste des modifcateurs d'une attaque. + Toutes les options sans arguments peuvent être directement utilisées comme modificateurs dans le liste des modifcateurs d'une attaque.
      -
    • --nom txt : nom de l'attaque \xE0 afficher. Remplace le nom dans la ligne d'attaque si on a donn\xE9 un label en argument. Le nom ne doit pas comporte de blanc usivi de 2 tirets ( --).
    • -
    • --toucher n : bonus de base de l'attaque. Remplace les valeurs dans la ligne d'attaque si on a donn\xE9 un label en argument. Pour r\xE9f\xE9rence, sur les fiches de PJ, l'attaque au contact est [[@{selected|ATKCAC}]], l'attaque \xE0 distance [[@{selected|ATKTIR}]], et l'attaque magique [[@{selected|ATKMAG}]].
    • -
    • --crit n : valeur \xE0 partir de laquelle le jet de d\xE9 est un critique. Remplace les valeurs dans la ligne d'attaque si on a donn\xE9 un label en argument.
    • -
    • --dm expr : D\xE9g\xE2ts de base de l'attaque. Remplace les valeurs dans la ligne d'attaque si on a donn\xE9 un label en argument. expr peut \xEAtre un entier ou bien une expression du type adb+c. La partie constante de cette expression est optionnelle et peut \xEAtre n\xE9gative.
    • -
    • --portee n : la port\xE9e de l'attaque exprim\xE9e en m\xE8tres. Remplace les valeurs dans la ligne d'attaque si on a donn\xE9 un label en argument.
    • -
    • --special txt : remplace le champ sp\xE9cial de l'attaque sur la fiche.
    • -
    • --tempDmg : l'attaque fait des d\xE9g\xE2ts temporaires (tient compte de la force de l'adversaire, utilise la barre 2 pour les dmg temp, sauf si le token a des PM, auquel cas on utilisera un attribut temporaire).
    • +
    • --nom txt : nom de l'attaque à afficher. Remplace le nom dans la ligne d'attaque si on a donné un label en argument. Le nom ne doit pas comporte de blanc usivi de 2 tirets ( --).
    • +
    • --toucher n : bonus de base de l'attaque. Remplace les valeurs dans la ligne d'attaque si on a donné un label en argument. Pour référence, sur les fiches de PJ, l'attaque au contact est [[@{selected|ATKCAC}]], l'attaque à distance [[@{selected|ATKTIR}]], et l'attaque magique [[@{selected|ATKMAG}]].
    • +
    • --crit n : valeur à partir de laquelle le jet de dé est un critique. Remplace les valeurs dans la ligne d'attaque si on a donné un label en argument.
    • +
    • --dm expr : Dégâts de base de l'attaque. Remplace les valeurs dans la ligne d'attaque si on a donné un label en argument. expr peut être un entier ou bien une expression du type adb+c. La partie constante de cette expression est optionnelle et peut être négative.
    • +
    • --portee n : la portée de l'attaque exprimée en mètres. Remplace les valeurs dans la ligne d'attaque si on a donné un label en argument.
    • +
    • --special txt : remplace le champ spécial de l'attaque sur la fiche.
    • +
    • --tempDmg : l'attaque fait des dégâts temporaires (tient compte de la force de l'adversaire, utilise la barre 2 pour les dmg temp, sauf si le token a des PM, auquel cas on utilisera un attribut temporaire).
    • --pasDeDmg : l'attaque ne fait pas de DM.
    • -
    • --poudre : l'arme est une arme \xE0 poudre, utilisation d'un d\xE9 de poudre. Une arme est aussi consid\xE9r\xE9e comme une arme \xE0 poudre si elle contient poudre dans le nom de l'arme ou dans le champ modifcateur ou de pr\xE9dicats.
    • -
    • --epieu : l'arme est un \xE9pieu. \xC0 noter que l'arme est aussi consid\xE9r\xE9e comme un \xE9pieu si elle contient \xE9pieu dans son nom ou epieu dans son champs modificateurs ou pr\xE9dicats. Cette option augmente de 1 le nombre de d\xE9s contre un adversaire sans armure.
    • -
    • --hache : l'arme est une hache. \xC0 noter que l'arme est aussi consid\xE9r\xE9e comme une hache si elle contient hache dans son nom ou dans son champs modificateurs ou pr\xE9dicats. Cette option permet de passer la RD/hache (pour les sylvaniens, par exemple).
    • -
    • --marteau : l'arme est un marteau. \xC0 noter que l'arme est aussi consid\xE9r\xE9e comme un marteau si elle contient marteau dans son nom ou dans son champs modificateurs ou pr\xE9dicats.
    • -
    • --auto : l'attaque r\xE9ussit automatiquement
    • +
    • --poudre : l'arme est une arme à poudre, utilisation d'un dé de poudre. Une arme est aussi considérée comme une arme à poudre si elle contient poudre dans le nom de l'arme ou dans le champ modifcateur ou de prédicats.
    • +
    • --epieu : l'arme est un épieu. À noter que l'arme est aussi considérée comme un épieu si elle contient épieu dans son nom ou epieu dans son champs modificateurs ou prédicats. Cette option augmente de 1 le nombre de dés contre un adversaire sans armure.
    • +
    • --hache : l'arme est une hache. À noter que l'arme est aussi considérée comme une hache si elle contient hache dans son nom ou dans son champs modificateurs ou prédicats. Cette option permet de passer la RD/hache (pour les sylvaniens, par exemple).
    • +
    • --marteau : l'arme est un marteau. À noter que l'arme est aussi considérée comme un marteau si elle contient marteau dans son nom ou dans son champs modificateurs ou prédicats.
    • +
    • --auto : l'attaque réussit automatiquement
    • --bonusAttaque n : ajoute n au jet d'attaque
    • -
    • --bonusCritique n : augmente n \xE0 la plage de coups critiques
    • -
    • --modifiePortee n : ajoute n \xE0 la port\xE9e de l'attaque.
    • -
    • --divisePortee n : divise la port\xE9e de base par n. C'est appliqu\xE9 avant toute modification de port\xE9e.
    • -
    • --bonusContreBouclier n : ajoute n au jet d'attaque si le d\xE9fenseur porte un bouclier. Utile par exemple pour le fl\xE9au d'arme.
    • -
    • --bonusContreArmure n : ajoute n au jet d'attaque si le d\xE9fenseur porte une armure.
    • -
    • --psave carac seuil : jet de carac, si le jet est sup\xE9rieur \xE0 seuil, les d\xE9g\xE2ts sont divis\xE9s par 2. carac est l'abbr\xE9viation de caract\xE9ristiques de 3 lettres standard (FOR, DEX, ...). Il est possible de prendre la meilleure de 2 caract\xE9ristiques pour le save : pour cela indiquer les 2 caract\xE9ristiques coll\xE9es (donc 6 caract\xE8res, par exemple FORDEX, pour le meilleur de FOR et de DEX). Le script choisira automatiquement la caract\xE9ristique qui donne les meilleures chances de r\xE9ussite (en tenant compte de la difficult\xE9 et des caract\xE9ristiques sup\xE9rieures).
    • Enfin on peut encore ajouter un ou des arguments optionnels. Si vous avez besoin de plus d'un argument optionnel, s\xE9parez-les par +: +
    • --bonusCritique n : augmente n à la plage de coups critiques
    • +
    • --modifiePortee n : ajoute n à la portée de l'attaque.
    • +
    • --divisePortee n : divise la portée de base par n. C'est appliqué avant toute modification de portée.
    • +
    • --bonusContreBouclier n : ajoute n au jet d'attaque si le défenseur porte un bouclier. Utile par exemple pour le fléau d'arme.
    • +
    • --bonusContreArmure n : ajoute n au jet d'attaque si le défenseur porte une armure.
    • +
    • --psave carac seuil : jet de carac, si le jet est supérieur à seuil, les dégâts sont divisés par 2. carac est l'abbréviation de caractéristiques de 3 lettres standard (FOR, DEX, ...). Il est possible de prendre la meilleure de 2 caractéristiques pour le save : pour cela indiquer les 2 caractéristiques collées (donc 6 caractères, par exemple FORDEX, pour le meilleur de FOR et de DEX). Le script choisira automatiquement la caractéristique qui donne les meilleures chances de réussite (en tenant compte de la difficulté et des caractéristiques supérieures).
    • Enfin on peut encore ajouter un ou des arguments optionnels. Si vous avez besoin de plus d'un argument optionnel, séparez-les par +:
        -
      • Si on souhaite que le jet ne permette de r\xE9duire qu'une partie des dommages (la derni\xE8re ajout\xE9e avec --plus), on peut ajouter local. La syntaxe compl\xE8te est alors --psave carac seuil local.
      • -
      • Si on souhaite que la difficult\xE9 soit augment\xE9e en cas de temp\xEAte de mana, on peut utiliser le mot cl\xE9 tempete suivi si besoin de l'incr\xE9ment en fonction de la mana (par defaut 1 mana augmente de 1 la difficult\xE9).
      • -
      • Si on souhaite indiquer une difficult\xE9 alternative pour les cibles au contact, ajouter contact n, o\xF9 n est la difficult\xE9 en question.
      • +
      • Si on souhaite que le jet ne permette de réduire qu'une partie des dommages (la dernière ajoutée avec --plus), on peut ajouter local. La syntaxe complète est alors --psave carac seuil local.
      • +
      • Si on souhaite que la difficulté soit augmentée en cas de tempête de mana, on peut utiliser le mot clé tempete suivi si besoin de l'incrément en fonction de la mana (par defaut 1 mana augmente de 1 la difficulté).
      • +
      • Si on souhaite indiquer une difficulté alternative pour les cibles au contact, ajouter contact n, où n est la difficulté en question.
      • +
      • Si on souhaite augmenter la difficulté du save en fonction de la marge de réussite du jet d'attaque, ajouter augmenteAvecMargeDeToucher.
      -
    • --demiAuto : si l'attaque rate, on consid\xE8re juste que les saves partiels sont automatiquemet r\xE9ussi. Ça signifie en g\xE9n\xE9ral que la cible prend au moins la moiti\xE9 des d\xE9g\xE2ts.
    • -
    • --dmSiRate dmg : si l'attaque rate, la cible est quand m\xEAme touch\xE9e et se voit infliger dmg d\xE9g\xE2ts.
    • -
    • --toucheDoubleDmg : si l'attaque rate, elle inflige les d\xE9g\xE2ts normaux, et si elle touche, elle double les d\xE9g\xE2ts de base. Pas cumulable avec dmSiRate ou demiAuto.
    • -
    • --save carac seuil : m\xEAme effet que --psave, mais pour annuler le dernier --effet ou etat (aucun effet sur les DM). Si on rajoute un argument demiDuree au save, alors la r\xE9ussite du save ne fait que diviser par 2 sa dur\xE9e.
    • -
    • --saveDM carac seuil : m\xEAme effet que --psave, mais pour annuler l'ensemble des d\xE9g\xE2ts.
    • -
    • --saveParTour carac seuil : m\xEAme effet que --save, mais donne droit \xE0 un jet \xE0 la fin de chaque tour au lieu d'un jet au moment de l'attaque.
    • -
    • --saveActifParTour carac seuil : m\xEAme effet que --save, mais affiche un bouton pour faire le save dans la liste d'actions \xE0 chaque tour. Utile si les joueurs pr\xE9f\xE8rent jeter "eux-m\xEAmes" le d\xE9, ou si le save est sens\xE9 arriver au tour du joueur.
    • -
    • --saveParJour carac seuil : m\xEAme effet que --save, mais donne droit \xE0 un jet \xE0 la fin de chaque jour au lieu d'un jet au moment de l'attaque.
    • -
    • --fx effet : ajoute un effet qui part de l'attaquant \xE0 la cible. Si l'attaque rate, l'effet rate aussi, d'autant plus que le jet d'attaque est loin de la d\xE9fense. Il est possible d'utiliser un effet que vous avez d\xE9fini vous-m\xEAme en utilisant l'option --fx custom nom, o\xF9 nom est le nom de votre effet.
    • -
    • --targetFx effet : ajoute un effet au niveau de la cible (l'effet ne doit pas \xEAtre directionnel). Comme avec --fx, on peut utiliser un effet qu'on a cr\xE9\xE9.
    • +
    • --demiAuto : si l'attaque rate, on considère juste que les saves partiels sont automatiquemet réussi. Ça signifie en général que la cible prend au moins la moitié des dégâts.
    • +
    • --dmSiRate dmg : si l'attaque rate, la cible est quand même touchée et se voit infliger dmg dégâts.
    • +
    • --toucheDoubleDmg : si l'attaque rate, elle inflige les dégâts normaux, et si elle touche, elle double les dégâts de base. Pas cumulable avec dmSiRate ou demiAuto.
    • +
    • --save carac seuil : même effet que --psave, mais pour annuler le dernier --effet ou etat (aucun effet sur les DM). Si on rajoute un argument demiDuree au save, alors la réussite du save ne fait que diviser par 2 sa durée.
    • +
    • --saveDM carac seuil : même effet que --psave, mais pour annuler l'ensemble des dégâts.
    • +
    • --saveParTour carac seuil : même effet que --save, mais donne droit à un jet à la fin de chaque tour au lieu d'un jet au moment de l'attaque.
    • +
    • --saveActifParTour carac seuil : même effet que --save, mais affiche un bouton pour faire le save dans la liste d'actions à chaque tour. Utile si les joueurs préfèrent jeter "eux-mêmes" le dé, ou si le save est sensé arriver au tour du joueur.
    • +
    • --saveParJour carac seuil : même effet que --save, mais donne droit à un jet à la fin de chaque jour au lieu d'un jet au moment de l'attaque.
    • +
    • --fx effet : ajoute un effet qui part de l'attaquant à la cible. Si l'attaque rate, l'effet rate aussi, d'autant plus que le jet d'attaque est loin de la défense. Il est possible d'utiliser un effet que vous avez défini vous-même en utilisant l'option --fx custom nom, où nom est le nom de votre effet.
    • +
    • --targetFx effet : ajoute un effet au niveau de la cible (l'effet ne doit pas être directionnel). Comme avec --fx, on peut utiliser un effet qu'on a créé.
    • - --si condition : l'attaque n'est possible que si condition est valid\xE9e. Une condition peut \xEAtre + --si condition : l'attaque n'est possible que si condition est validée. Une condition peut être
      • moins attribut : vrai si l'attribut attribut de la cible est moins haute que celle de l'attaquant
      • -
      • etat e : vrai si l'\xE9tat e est actif sur l'attaquant. Cet \xE9tat peut \xEAtre un des \xE9tats d\xE9finis plus bas, ou un attribut quelconque.
      • -
      • attribut attr val: vrai si l'attaquant poss\xE8de un attribut attr, de valeur val, aux majuscules pr\xE8s. On peut optionnellement pr\xE9ciser qu'il s'agit d'un attribut par token en rajoutant le mot cl\xE9 local, ou encore qu'il sagit d'un attribut de la fiche, avec \xE9ventuellement sa valeur par d\xE9faut, en ajoutant le mot cl\xE9 fiche defaut.
      • -
      • etatCible e : vrai si l'\xE9tat e est actif sur toutes la cible. Cet \xE9tat peut \xEAtre un des \xE9tats d\xE9finis plus bas, ou un attribut quelconque.
      • -
      • attributCible attr val: vrai si la cible poss\xE8de un attribut attr, de valeur val, aux majuscules pr\xE8s. On peut optionnellement pr\xE9ciser qu'il s'agit d'un attribut par token en rajoutant le mot cl\xE9 local, ou encore qu'il sagit d'un attribut de la fiche, avec \xE9ventuellement sa valeur par d\xE9faut, en ajoutant le mot cl\xE9 fiche defaut.
      • -
      • predicatCible predicat: vrai si la cible poss\xE8de un pr\xE9dicat predicat. On peut aussi sp\xE9cifier une valeur auquel le pr\xE9dicat doit \xEAtre \xE9gal.
      • -
      • typeCible type: vrai si la cible est du type sp\xE9cifi\xE9. Les types reconnus sont animal, d\xE9mon, dragon, f\xE9e, insecte, mauvais, mort-vivant, g\xE9ant, gobelin, et si le type n'est pas reconnu, va chercher si la race ou un pr\xE9dicat correspondant.
      • -
      • deAttaque n : vrai si le jet de d\xE9 d'attaque est sup\xE9rieur ou \xE9gal \xE0 n.
      • +
      • etat e : vrai si l'état e est actif sur l'attaquant. Cet état peut être un des états définis plus bas, ou un attribut quelconque.
      • +
      • attribut attr val: vrai si l'attaquant possède un attribut attr, de valeur val, aux majuscules près. On peut optionnellement préciser qu'il s'agit d'un attribut par token en rajoutant le mot clé local, ou encore qu'il sagit d'un attribut de la fiche, avec éventuellement sa valeur par défaut, en ajoutant le mot clé fiche defaut.
      • +
      • etatCible e : vrai si l'état e est actif sur toutes la cible. Cet état peut être un des états définis plus bas, ou un attribut quelconque.
      • +
      • attributCible attr val: vrai si la cible possède un attribut attr, de valeur val, aux majuscules près. On peut optionnellement préciser qu'il s'agit d'un attribut par token en rajoutant le mot clé local, ou encore qu'il sagit d'un attribut de la fiche, avec éventuellement sa valeur par défaut, en ajoutant le mot clé fiche defaut.
      • +
      • predicatCible predicat: vrai si la cible possède un prédicat predicat. On peut aussi spécifier une valeur auquel le prédicat doit être égal.
      • +
      • typeCible type: vrai si la cible est du type spécifié. Les types reconnus sont animal, démon, dragon, fée, insecte, mauvais, mort-vivant, géant, gobelin, et si le type n'est pas reconnu, va chercher si la race ou un prédicat correspondant.
      • +
      • deAttaque n : vrai si le jet de dé d'attaque est supérieur ou égal à n.
      • touche : vrai si l'attaque touche.
      • critique : vrai si l'attaque est un critique.
      • -
      • echecCritique : vrai si l'attaque est un \xE9chec critique.
      • +
      • echecCritique : vrai si l'attaque est un échec critique.
      • +
      • premiereAttaque : vrai si c'est la première attaque du combat.
    • -
    • --if condition options --endif: permet de ne prendre en compte des options que si certaines conditions sont r\xE9alis\xE9es. Il est possible d'utiliser un --else pour activer des options quand les conditions ne sont pas r\xE9alis\xE9es. Attention, les options qui modifient une option pr\xE9c\xE9dente (comme --valeur) doivent appara\xEEtre au m\xEAme niveau que l'option qu'elles modifient. Comme les conditions peuvent d\xE9pendre du d\xE9 d'attaque, un certain nombre d'options ne sont pas affect\xE9es par cette conditionnelle : tempeteDeMana, les options d'aoe (ligne, cone, disque, target), avecd12, avantage, auto, demiAuto, test, pointsVitaux, tempsRecharge, sortilege, bonusCritique, disparition, affute, munition, tirDouble, semonce, tirDeBarrage, poudre, traquenard, feinte, asDeLaGachette, magique, tranchant, percant, contondant, pasDeDmg. Ne pas h\xE9siter \xE0 me demander si vous aviez besoin que l'une de ces options puissent \xEAtre conditionnelle.
    • -
    • --ifSaveFails carac seuil options --endif : comme --if, mais fait r\xE9aliser une jet de sauvegarde \xE0 la cible (comme avec --save), et si le test est rat\xE9, applique les options qui suivent. Un --else permet de choisir des options \xE0 appliquer quand le test est r\xE9ussi. \xC0 utiliser seulement si on ne peut pas se contenter d'un --save, car \xE7a marche moins bien.
    • -
    • --decrAttribute nom : l'attaque n'est possible que si l'attribut existe et si sa valeur est strictement positive. L'attaque diminue cette valeur de 1. Si cette option est utilis\xE9e \xE0 l'int\xE9rieur d'un --if, alors l'option se contente de diminuer l'attribut (on peut savoir si la valeur est positive gr\xE2ce \xE0 --if etat nom).
    • -
    • --decrLimitePredicatParTour nom : l'attaque n'est possible que si un pr\xE9dicat nom existe et si elle n'a pas \xE9t\xE9 utilis\xE9e plus de fois dans le tour que la valeur de ce pr\xE9dicat. L'attaque augmente ce nombre de 1.
    • -
    • --tempsRecharge effet duree : l'attaque n'est possible que si l'effet est inactif sur l'attaquant, et de plus active l'effet sur l'attaquant pour la dur\xE9e indiqu\xE9e si l'attaque est possible. Il existe un effet temporaire g\xE9n\xE9rique, rechargeGen(desc) que vous pouvez utiliser si aucun effet existant ne correspond pour votre attaque.
    • -
    • --etat e: si l'attaque touche, la cible passe dans l'\xE9tat e. Il est aussi possible de sp\xE9cifier une caract\xE9ristique et un seuil (comme pour !cof-set-state) pour faire afficher \xE0 chaque tour une action permettant de se lib\xE9rer de l'\xE9tat.
    • -
    • --effet e duree : ajoute \xE0 la cible l'effet temporaire e pour la duree sp\xE9cifi\xE9e. Pour que cela soit automatiquement mis \xE0 jour, il faut utiliser le turn tracker. Noter que l'argument de dur\xE9e peut \xEAtre omis pour certains effets, comme ceux qui par d\xE9finition durent tout le combat.
    • -
    • --valeur v : sp\xE9cifie une valeur au dernier effet mentionn\xE9.
    • -
    • --optionEffet opt arg1 arg2 ... : sp\xE9cifie une option au dernier effet mentionn\xE9. L'option opt doit \xEAtre donn\xE9e sans le -- et sera pass\xE9e telle quelle \xE0 l'effet, par exemple pour les d\xE9g\xE2ts p\xE9riodiques, si on ne veut pas que la RD s'applique, on pourra ajouter --optionEffet ignoreRD.
    • -
    • --peur seuil duree : fait un effet de peur si l'attaque touche. Le seuil sert pour le test de sagesse de r\xE9sistance \xE0 la peur (tient compte de la capacit\xE9 sans peur du chevalier).
    • -
    • --affaiblirCarac carac n : l'attaque diminue la caract\xE9ristique carac de n. Si carac est random, le script tire une caract\xE9ristique au hasard.
    • -
    • --plus dmg : ajoute dmg d\xE9g\xE2ts. Attention, si dmg est un simple nombre, ces d\xE9g\xE2ts sont multipli\xE9s par les critiques (sauf si de type diff\xE9rent de l'attaque principale). Ainsi, --plus [[1d6]] donnera des d\xE9g\xE2ts multipli\xE9s par les critiques (car la fonction ne voit que le r\xE9sultat du jet), alors que --plus 1d6 ne le sera pas.
    • -
    • --plusCrit dmg : ajoute dmg d\xE9g\xE2ts en cas de r\xE9ussite critique
    • -
    • --test pour voir le r\xE9sultat du jet d'attaque. On n'applique pas les r\xE9sultats d'un touch\xE9.
    • -
    • --sournoise n : ajoute nd6 de d\xE9g\xE2ts d'attaque sournoise ou par surprise. Si l'option n'a pas d'argument, le nombre de d\xE9s rajout\xE9s sera celui associ\xE9 \xE0 un pr\xE9dicat attaqueSournoise, et si l'attaquant n'a pas de pr\xE9dicat attaqueSournoise, l'attaque ajoute juste 1d6. Le script limite le nombre d'attaque sournoise par personnage \xE0 1 par tour. On peut augmenter ce nombre en utilisant un pr\xE9dicat sournoisesParTour, de valeur la limite au nombre de sournoises pour ce personnage.
    • -
    • --magique : les d\xE9g\xE2ts sont magiques. On peut passer en argument le niveau de magie. Il est utilis\xE9 contre les cr\xE9atures immunis\xE9es aux armes. Le niveau par d\xE9faut est 1.
    • -
    • --+k : l'attaque utilise une arme magique +k. Pratique \xE0 mettre dans les modificateurs de l'attaque (dans ce cas, on n'a pas les --), cela rajoute les bonus au toucher et aux d\xE9g\xE2ts, et indique que les d\xE9g\xE2ts sont magiques. Si un niveau de magie est sp\xE9cifi\xE9, rajoute k \xE0 ce niveau.
    • -
    • --feu, --acide, --electrique, --froid, --sonique, --poison, --maladie, --argent, --drain, --energie : les d\xE9g\xE2ts sont de type feu, acide, \xE9lectrique, froid, sonique, poison, maladie, argent, drain ou \xE9nergie. Le type sp\xE9cifie uniquement le dernier --plus pr\xE9c\xE9dent cette option, ou si il n'y en a pas, celui des d\xE9g\xE2ts principaux. Seul le dernier type sp\xE9cifi\xE9 est pris en compte (pas de type multiple pour l'instant). Le type affecte diff\xE9rents attributs, et aussi la couleur d'affichage des d\xE9g\xE2ts.
    • -
    • --beni : les d\xE9g\xE2ts sont d'une source sainte ou b\xE9nie. Sert principalement \xE0 signaler pour les r\xE9sistances aux d\xE9g\xE2ts qui peuvent d\xE9pendre de cela (genre RD 5/beni).
    • -
    • --spectral : L'attaque peut toucher les cr\xE9atures intangibles.
    • -
    • --tranchant, --percant, --contondant : pr\xE9cise le type d'arme (si pertinent), pour pouvoir utiliser les RD sp\xE9cifiques \xE0 un type d'arme.
    • -
    • --ignoreRD : l'attaque ignore les RD et division de DMs. Il est possible de donner en argument une valeur de RD ignor\xE9e, de sorte que l'attaque ignore les RD jusqu'\xE0 cette valeur. Par exemple on pourra \xE9crire --ignoreRD 5.
    • -
    • --ignoreMoitieRD : l'attaque ignore la moiti\xE9 de la RD.
    • -
    • --sortilege pour indiquer qu'il s'agit d'un sortil\xE8ge, de fa\xE7ons \xE0 pouvoir appliquer tous les effets sp\xE9cifiques aux sorts. Cette options devrait \xEAtre pass\xE9es pour toutes les capacit\xE9s suivies d'une \xE9toile dans le livre des r\xE8gles. En particulier, tout sortilege ignore les malus d'obstacles.
    • -
    • --reroll1 : relance les 1 aux d\xE9s de d\xE9gats. \xC0 noter que cela ne concerne que les d\xE9s de base de l'attaque, pas les DM suppl\xE9mentaire.
    • -
    • --explodeMax : relance les valeurs maximum aux d\xE9s de DM de base, et rajoute le nouveau r\xE9sultat (qui lui-m\xEAme explose).
    • -
    • --mana n : l'attaque co\xFBte n points de mana. Si l'attaque provoque un effet temporaire, le script essaiera de le supprimer \xE0 la mort du lanceur (m\xEAme avec un co\xFBt nul).
    • -
    • --magieRapide : augmente le co\xFBt en mana (1 avec la mana normale, 3 avec la mana totale) et affiche un petit message indiquant que le lancement est rapide. Il est possible de pr\xE9ciser un co\xFBt en mana diff\xE9rent.
    • -
    • --rang n : indique le rang de la capacit\xE9 utilis\xE9e, si besoin. Utilis\xE9 par l'option --tempeteDeMana.
    • -
    • --tempeteDeMana liste : indique des effets de temp\xEAte de mana. La liste peut contenir un nombre (pour l'effet intense), duree, rapide, portee et altruiste id. Si le rang du sort est sp\xE9cifi\xE9 (par l'option --rang, un message est affich\xE9e si le co\xFBt en mana est sup\xE9rieur au rang. Si la liste d'options est vide ou ne contient que altruiste, le script affiche un menu dans le chat pour sp\xE9cifier les options de temp\xEAte de mana. Il est possible d'utiliser les r\xE8gles de mana totale pour les co\xFBts de temp\xEAte de mana (\xE0 activer avec !cof-options).
    • -
    • --magieEnArmure : applique un malus \xE0 l'attaque \xE9gale au rang du sort + le malus d'armure de l'attaquant. On peut ajouter un argument optionnel : soit un nombre qui va remplacer le rang dans cette formule, soit mana qui va augmenter le co\xFBt en mana de l'attaque en fonction de l'armure port\xE9e.
    • -
    • --frappeDesArcanes n : ajoute +5 \xE0 l'attaque et +nd6 aux DM, mais emp\xEAche de lancer des sorts pendant 1d6 tours si l'attaque touche. Si le nombre n n'est pas pr\xE9sent, le bonus est de 2d6.
    • -
    • --limiteParJour l : limite le nombre d'utilisations de cette attaque \xE0 l fois par jour. On peut pr\xE9ciser un nom apr\xE8s l, qui va correspondre \xE0 une ressource pouvant \xEAtre partag\xE9e avec d'autres attaques ou d'autres effets (voir !cof-effet-temp). Par d\xE9faut, le nom de cette ressource est le label de l'attaque.
    • -
    • --limiteParCombat : m\xEAme effet que la limite par jour. Si aucun argument n'est donn\xE9, la limite est de une fois par combat.
    • -
    • --limiteParTour : m\xEAme effet que la limite par jour. Si aucun argument n'est donn\xE9, la limite est de une fois par tour.
    • -
    • --munition label : l'attaque utilise les munitions de label label (not\xE9es dans l'onglet \xE9quipement de la fiche). \xC0 chaque attaque port\xE9e, une munition est utilis\xE9e, et le script teste si elle sera r\xE9cup\xE9rable (en fonction du taux de pertes not\xE9e sur la fiche). En fin de combat, on consid\xE8re que le personnage r\xE9cup\xE8re toutes les munitions r\xE9cup\xE9rables. Si une arme est reconnue comme \xE9tant un arc,une arbal\xE8te ou une arme \xE0 poudre, et que les options de l'attaque ne contiennent pas l'option --munition, alors le script propose automatiquement de choisir parmis les munitions normales (suppos\xE9es illimit\xE9es) et celles encores pr\xE9sentes du bon type. \xC0 noter que cette option devrait \xEAtre inutile pour les armes de jet qui ont d\xE9j\xE0 leur propre case associ\xE9e \xE0 l'attaque.
    • -
    • --aussiArmeDeJet L : permet d'indiquer que l'arme peut aussi \xEAtre employ\xE9e comme arme de jet. L doit \xEAtre le label de l'attaque avec cette arme en tant qu'arme de jet. Cela permet de tenir compte des cas o\xF9 l'arme a \xE9t\xE9 lanc\xE9e et ne peut donc plus \xEAtre utilis\xE9e au corps \xE0 corps. Si l'arme est utilis\xE9e \xE0 distance, le script va automatiquement utiliser l'attaque L.
    • -
    • --arcComposite n : augmente les DM du modificateur de force, (qui peut \xEAtre n\xE9gatif), mais sans d\xE9passer n. Si le modificateur est strictement inf\xE9rieur \xE0 n, l'attaque se fait avec un malus de -2.
    • -
    • --seulementDistance : l'attaque ne peut \xEAtre r\xE9alis\xE9e que contre un adversaire \xE0 distance.
    • -
    • --vampirise : soigne de tous les DM inflig\xE9s, quel que soit leur type. Il est possible de soigner un pourcentage des d\xE9g\xE2ts : pour cela, pr\xE9ciser le pourcentage entier apr\xE8s l'option. Par exemple, pour une attaque qui soigne de la moiti\xE9 des d\xE9g\xE2ts inflig\xE9s, on pourra mettre --vampirise 50. \xC0 noter que les soins se cumulent avec les d\xE9g\xE2ts de type drain.
    • +
    • --if condition options --endif: permet de ne prendre en compte des options que si certaines conditions sont réalisées. Il est possible d'utiliser un --else pour activer des options quand les conditions ne sont pas réalisées. Attention, les options qui modifient une option précédente (comme --valeur) doivent apparaître au même niveau que l'option qu'elles modifient. Comme les conditions peuvent dépendre du dé d'attaque, un certain nombre d'options ne sont pas affectées par cette conditionnelle : tempeteDeMana, les options d'aoe (ligne, cone, disque, target), avecd12, avantage, auto, demiAuto, test, pointsVitaux, tempsRecharge, sortilege, bonusCritique, disparition, affute, munition, tirDouble, semonce, tirDeBarrage, poudre, traquenard, feinte, asDeLaGachette, magique, tranchant, percant, contondant, pasDeDmg. Ne pas hésiter à me demander si vous aviez besoin que l'une de ces options puissent être conditionnelle.
    • +
    • --ifSaveFails carac seuil options --endif : comme --if, mais fait réaliser une jet de sauvegarde à la cible (comme avec --save), et si le test est raté, applique les options qui suivent. Un --else permet de choisir des options à appliquer quand le test est réussi. À utiliser seulement si on ne peut pas se contenter d'un --save, car ça marche moins bien.
    • +
    • --decrAttribute nom : l'attaque n'est possible que si l'attribut existe et si sa valeur est strictement positive. L'attaque diminue cette valeur de 1. Si cette option est utilisée à l'intérieur d'un --if, alors l'option se contente de diminuer l'attribut (on peut savoir si la valeur est positive grâce à --if etat nom).
    • +
    • --decrLimitePredicatParTour nom : l'attaque n'est possible que si un prédicat nom existe et si elle n'a pas été utilisée plus de fois dans le tour que la valeur de ce prédicat. L'attaque augmente ce nombre de 1.
    • +
    • --tempsRecharge effet duree : l'attaque n'est possible que si l'effet est inactif sur l'attaquant, et de plus active l'effet sur l'attaquant pour la durée indiquée si l'attaque est possible. Il existe un effet temporaire générique, rechargeGen(desc) que vous pouvez utiliser si aucun effet existant ne correspond pour votre attaque.
    • +
    • --etat e: si l'attaque touche, la cible passe dans l'état e. Il est aussi possible de spécifier une caractéristique et un seuil (comme pour !cof-set-state) pour faire afficher à chaque tour une action permettant de se libérer de l'état.
    • +
    • --effet e duree : ajoute à la cible l'effet temporaire e pour la duree spécifiée. Pour que cela soit automatiquement mis à jour, il faut utiliser le turn tracker. Noter que l'argument de durée peut être omis pour certains effets, comme ceux qui par définition durent tout le combat.
    • +
    • --valeur v : spécifie une valeur au dernier effet mentionné.
    • +
    • --optionEffet opt arg1 arg2 ... : spécifie une option au dernier effet mentionné. L'option opt doit être donnée sans le -- et sera passée telle quelle à l'effet, par exemple pour les dégâts périodiques, si on ne veut pas que la RD s'applique, on pourra ajouter --optionEffet ignoreRD.
    • +
    • --peur seuil duree : fait un effet de peur si l'attaque touche. Le seuil sert pour le test de sagesse de résistance à la peur (tient compte de la capacité sans peur du chevalier).
    • +
    • --affaiblirCarac carac n : l'attaque diminue la caractéristique carac de n. Si carac est random, le script tire une caractéristique au hasard.
    • +
    • --plus dmg : ajoute dmg dégâts. Attention, si dmg est un simple nombre, ces dégâts sont multipliés par les critiques (sauf si de type différent de l'attaque principale). Ainsi, --plus [[1d6]] donnera des dégâts multipliés par les critiques (car la fonction ne voit que le résultat du jet), alors que --plus 1d6 ne le sera pas.
    • +
    • --plusCrit dmg : ajoute dmg dégâts en cas de réussite critique
    • +
    • --test pour voir le résultat du jet d'attaque. On n'applique pas les résultats d'un touché.
    • +
    • --sournoise n : ajoute nd6 de dégâts d'attaque sournoise ou par surprise. Si l'option n'a pas d'argument, le nombre de dés rajoutés sera celui associé à un prédicat attaqueSournoise, et si l'attaquant n'a pas de prédicat attaqueSournoise, l'attaque ajoute juste 1d6. Le script limite le nombre d'attaque sournoise par personnage à 1 par tour. On peut augmenter ce nombre en utilisant un prédicat sournoisesParTour, de valeur la limite au nombre de sournoises pour ce personnage.
    • +
    • --magique : les dégâts sont magiques. On peut passer en argument le niveau de magie. Il est utilisé contre les créatures immunisées aux armes. Le niveau par défaut est 1.
    • +
    • --+k : l'attaque utilise une arme magique +k. Pratique à mettre dans les modificateurs de l'attaque (dans ce cas, on n'a pas les --), cela rajoute les bonus au toucher et aux dégâts, et indique que les dégâts sont magiques. Si un niveau de magie est spécifié, rajoute k à ce niveau.
    • +
    • --feu, --acide, --electrique, --froid, --sonique, --poison, --maladie, --argent, --drain, --energie : les dégâts sont de type feu, acide, électrique, froid, sonique, poison, maladie, argent, drain ou énergie. Le type spécifie uniquement le dernier --plus précédent cette option, ou si il n'y en a pas, celui des dégâts principaux. Seul le dernier type spécifié est pris en compte (pas de type multiple pour l'instant). Le type affecte différents attributs, et aussi la couleur d'affichage des dégâts.
    • +
    • --beni : les dégâts sont d'une source sainte ou bénie. Sert principalement à signaler pour les résistances aux dégâts qui peuvent dépendre de cela (genre RD 5/beni).
    • +
    • --spectral : L'attaque peut toucher les créatures intangibles.
    • +
    • --tranchant, --percant, --contondant : précise le type d'arme (si pertinent), pour pouvoir utiliser les RD spécifiques à un type d'arme.
    • +
    • --ignoreRD : l'attaque ignore les RD et division de DMs. Il est possible de donner en argument une valeur de RD ignorée, de sorte que l'attaque ignore les RD jusqu'à cette valeur. Par exemple on pourra écrire --ignoreRD 5.
    • +
    • --ignoreMoitieRD : l'attaque ignore la moitié de la RD.
    • +
    • --sortilege pour indiquer qu'il s'agit d'un sortilège, de façons à pouvoir appliquer tous les effets spécifiques aux sorts. Cette options devrait être passées pour toutes les capacités suivies d'une étoile dans le livre des règles. En particulier, tout sortilege ignore les malus d'obstacles.
    • +
    • --reroll1 : relance les 1 aux dés de dégats. À noter que cela ne concerne que les dés de base de l'attaque, pas les DM supplémentaire.
    • +
    • --explodeMax : relance les valeurs maximum aux dés de DM de base, et rajoute le nouveau résultat (qui lui-même explose).
    • +
    • --mana n : l'attaque coûte n points de mana. Si l'attaque provoque un effet temporaire, le script essaiera de le supprimer à la mort du lanceur (même avec un coût nul).
    • +
    • --magieRapide : augmente le coût en mana (1 avec la mana normale, 3 avec la mana totale) et affiche un petit message indiquant que le lancement est rapide. Il est possible de préciser un coût en mana différent.
    • +
    • --rang n : indique le rang de la capacité utilisée, si besoin. Utilisé par l'option --tempeteDeMana.
    • +
    • --tempeteDeMana liste : indique des effets de tempête de mana. La liste peut contenir un nombre (pour l'effet intense), duree, rapide, portee et altruiste id. Si le rang du sort est spécifié (par l'option --rang, un message est affichée si le coût en mana est supérieur au rang. Si la liste d'options est vide ou ne contient que altruiste, le script affiche un menu dans le chat pour spécifier les options de tempête de mana. Il est possible d'utiliser les règles de mana totale pour les coûts de tempête de mana (à activer avec !cof-options).
    • +
    • --magieEnArmure : applique un malus à l'attaque égale au rang du sort + le malus d'armure de l'attaquant. On peut ajouter un argument optionnel : soit un nombre qui va remplacer le rang dans cette formule, soit mana qui va augmenter le coût en mana de l'attaque en fonction de l'armure portée.
    • +
    • --frappeDesArcanes n : ajoute +5 à l'attaque et +nd6 aux DM, mais empêche de lancer des sorts pendant 1d6 tours si l'attaque touche. Si le nombre n n'est pas présent, le bonus est de 2d6.
    • +
    • --limiteParJour l : limite le nombre d'utilisations de cette attaque à l fois par jour. On peut préciser un nom après l, qui va correspondre à une ressource pouvant être partagée avec d'autres attaques ou d'autres effets (voir !cof-effet-temp). Par défaut, le nom de cette ressource est le label de l'attaque. On peut remplacer le nombre n par le nom d'un prédicat dont la valeur sera utilisée.
    • +
    • --limiteParCombat : même effet que la limite par jour. Si aucun argument n'est donné, la limite est de une fois par combat.
    • +
    • --limiteParTour : même effet que la limite par jour. Si aucun argument n'est donné, la limite est de une fois par tour.
    • +
    • --munition label : l'attaque utilise les munitions de label label (notées dans l'onglet équipement de la fiche). À chaque attaque portée, une munition est utilisée, et le script teste si elle sera récupérable (en fonction du taux de pertes notée sur la fiche). En fin de combat, on considère que le personnage récupère toutes les munitions récupérables. Si une arme est reconnue comme étant un arc,une arbalète ou une arme à poudre, et que les options de l'attaque ne contiennent pas l'option --munition, alors le script propose automatiquement de choisir parmis les munitions normales (supposées illimitées) et celles encores présentes du bon type. À noter que cette option devrait être inutile pour les armes de jet qui ont déjà leur propre case associée à l'attaque.
    • +
    • --aussiArmeDeJet L : permet d'indiquer que l'arme peut aussi être employée comme arme de jet. L doit être le label de l'attaque avec cette arme en tant qu'arme de jet. Cela permet de tenir compte des cas où l'arme a été lancée et ne peut donc plus être utilisée au corps à corps. Si l'arme est utilisée à distance, le script va automatiquement utiliser l'attaque L.
    • +
    • --arcComposite n : augmente les DM du modificateur de force, (qui peut être négatif), mais sans dépasser n. Si le modificateur est strictement inférieur à n, l'attaque se fait avec un malus de -2.
    • +
    • --seulementDistance : l'attaque ne peut être réalisée que contre un adversaire à distance.
    • +
    • --vampirise : soigne de tous les DM infligés, quel que soit leur type. Il est possible de soigner un pourcentage des dégâts : pour cela, préciser le pourcentage entier après l'option. Par exemple, pour une attaque qui soigne de la moitié des dégâts infligés, on pourra mettre --vampirise 50. À noter que les soins se cumulent avec les dégâts de type drain.
    • --seulementVivant : n'affecte que les cibles vivantes
    • --forceMinimum n : l'attaque n'est possible que si l'attaquant a au moins n en force.
    • -
    • --necromancie : l'attaque est de la n\xE9cromancie
    • -
    • --ferFroid : multiplie par 2 les d\xE9g\xE2ts contre les f\xE9es et les d\xE9mons (le script reconna\xEEt certaines races et les pr\xE9dicats d\xE9mon et f\xE9e).
    • -
    • --adamantium : l'arme utilis\xE9e est en adamantium. Reconnu pour la RD.
    • -
    • --tueurDe categorie : bonus de +2 en attaque et +2d6 DM contre les esp\xE8ces appartenant \xE0 la cat\xE9gorie (voir la condition typeCible.
    • -
    • --tueurDeGrands : bonus de +1d6 DM contre les cr\xE9atures de taille grande et +2d6 DM contre les cr\xE9atures de taille \xE9norme ou plus.
    • -
    • --ignoreObstacles : ignore les tokens sur le trajet. Ça semble n\xE9cessaire pour les attaques magiques d'apr\xE8s Kegron.
    • -
    • --retourneEnMain : L'arme de jet revient en main apr\xE8s l'attaque.
    • -
    • --puissant : augmente la valeur max des d\xE9s de d\xE9g\xE2ts de 2. Si --puissant est suivi d'un argument effet, on teste la pr\xE9sence d'un attribut effetPuissant pour d\xE9cider si l'attaque est puissante ou non. Il est aussi possible de donner oui ou non en argument (ce n'est alors pas consid\xE9r\xE9 comme un effet). --puissant portee permet de doubler la port\xE9e de l'attaque (utile pour l'option de Magie Puissante)
    • -
    • --attaqueAssuree : impl\xE9mente une attaque assur\xE9e (+5 \xE0 l'attaque, d\xE9g\xE2ts divis\xE9s par 2, critique impossible).
    • -
    • --attaqueRisquee : impl\xE9mente une attaque risqu\xE9e (+2 \xE0 l'attaque au contact, -4 en DEF pendant un tour).
    • -
    • --attaqueDeGroupe n : n est le nombre de cr\xE9atures qui attaquent ; impl\xE9mente une attaque de groupe (+2 \xE0 l'attaque par attaquant au-del\xE0 du premier, x2 DMG si l'attaque d\xE9passe la DEF de 5 ou plus, x3 DMG si critique).
    • -
    • --attaqueAcrobatique : l'attaquant effectue un test d'acrobatie difficult\xE9 15, et s'il r\xE9ussit, l'attaque b\xE9n\xE9ficie des effets d'une sournoise. On peut en option pr\xE9ciser le nombre de d\xE9s de cette attaque sournoise.
    • -
    • --strigeSuce : option sp\xE9cifique aux striges. Donne le malus de -3 en DEF et compte la quantite suc\xE9e. Quand cette quantit\xE9 arrive \xE0 6, enl\xE8ve le malus de DEF et rend la cible affaiblie.
    • -
    • --mainsDEnergie : +2 \xE0 +5 \xE0 l'attaque, selon l'armure de la cible
    • -
    • --semonce : +5 au touch\xE9 et +1d6 aux DM (ne change pas les charges de l'arme).
    • -
    • --avantage : lance un d\xE9 de plus en attaque et garde le meilleur. plusieurs arguments avantage se cumulent et sont annul\xE9s par les d\xE9savantages (syntaxe alertnative: (--m2d20)
    • -
    • --desavantage : lance un d\xE9 de plus en attaque et garde le moins bon. plusieurs arguments d\xE9savantage se cumulent et sont annul\xE9s par les avantages.
    • -
    • --avecd12 : lance un d12 au lieu du d20 pour le jet d'attaque. L'attaque est impossible si l'attaquant est d\xE9j\xE0 affaibli.
    • -
    • --avecd12crit : comme --avecd12, mais le jet peut faire un critique. La plage de critique est divis\xE9e par 2, arrondie \xE0 l'inf\xE9rieur. Ainsi si le d20 sevait critiquer sur un 20 seulement, le d12 ne fait pas de critique. Il fait un critique sur un 12 si le d20 devait faire un critique sur un 19 ou un 18, et ainsi de suite.
    • -
    • --incrDmgCoef n : augmente le coefficient des d\xE9g\xE2ts de base de 1. Les d\xE9g\xE2ts de base comprennent les d\xE9s de dommage de l'arme (ou du sort), plus tous les bonus constants. Le coefficient par d\xE9faut est de 1, et une r\xE9ussite critique augmente ce coefficient de 1.
    • -
    • --incrCritCoef n : augmente le coefficient des d\xE9g\xE2ts critiques de n (1 si on ne donne pas d'argument).
    • -
    • --diviseDmg n : divise les d\xE9g\xE2ts de base par n.
    • -
    • --maxDmg : l'attaque inflige le maximum de DM permis par les d\xE9s de base.
    • -
    • --runeDePuissance : l'arme est enchant\xE9e avec une rune de puissance permanente.
    • -
    • --difficultePVmax : la difficult\xE9 du jet d'attaque est le maximum de PVs au lieu de la d\xE9fense.
    • -
    • --difficultePV : la difficult\xE9 du jet d'attaque est la valeur courante des PVs au lieu de la d\xE9fense.
    • -
    • --difficulteCarac carac : la difficult\xE9 du jet d'attaque est une des caract\xE9ristiques de la cible (sous forme de code \xE0 3 lettres, FOR, DEX, etc). Il est possible de prendre le meilleur de 2 caract\xE9ristiques en \xE9crivant les 2 noms coll\xE9s. Par exemple, pour viser le meilleur de l'intelligence et du charisme, on \xE9crira --difficuletCarac INTCHA.
    • +
    • --necromancie : l'attaque est de la nécromancie
    • +
    • --ferFroid : multiplie par 2 les dégâts contre les fées et les démons (le script reconnaît certaines races et les prédicats démon et fée).
    • +
    • --adamantium : l'arme utilisée est en adamantium. Reconnu pour la RD.
    • +
    • --tueurDe categorie : bonus de +2 en attaque et +2d6 DM contre les espèces appartenant à la catégorie (voir la condition typeCible.
    • +
    • --tueurDeGrands : bonus de +1d6 DM contre les créatures de taille grande et +2d6 DM contre les créatures de taille énorme ou plus.
    • +
    • --ignoreObstacles : ignore les tokens sur le trajet. Ça semble nécessaire pour les attaques magiques d'après Kegron.
    • +
    • --retourneEnMain : L'arme de jet revient en main après l'attaque.
    • +
    • --puissant : augmente la valeur max des dés de dégâts de 2. Si --puissant est suivi d'un argument effet, on teste la présence d'un attribut effetPuissant pour décider si l'attaque est puissante ou non. Il est aussi possible de donner oui ou non en argument (ce n'est alors pas considéré comme un effet). --puissant portee permet de doubler la portée de l'attaque (utile pour l'option de Magie Puissante)
    • +
    • --attaqueAssuree : implémente une attaque assurée (+5 à l'attaque, dégâts divisés par 2, critique impossible).
    • +
    • --attaqueRisquee : implémente une attaque risquée (+2 à l'attaque au contact, -4 en DEF pendant un tour).
    • +
    • --attaqueDeGroupe n : n est le nombre de créatures qui attaquent ; implémente une attaque de groupe (+2 à l'attaque par attaquant au-delà du premier, x2 DMG si l'attaque dépasse la DEF de 5 ou plus, x3 DMG si critique).
    • +
    • --attaqueAcrobatique : l'attaquant effectue un test d'acrobatie difficulté 15, et s'il réussit, l'attaque bénéficie des effets d'une sournoise. On peut en option préciser le nombre de dés de cette attaque sournoise.
    • +
    • --strigeSuce : option spécifique aux striges. Donne le malus de -3 en DEF et compte la quantite sucée. Quand cette quantité arrive à 6, enlève le malus de DEF et rend la cible affaiblie.
    • +
    • --mainsDEnergie : +2 à +5 à l'attaque, selon l'armure de la cible
    • +
    • --semonce : +5 au touché et +1d6 aux DM (ne change pas les charges de l'arme).
    • +
    • --avantage : lance un dé de plus en attaque et garde le meilleur. plusieurs arguments avantage se cumulent et sont annulés par les désavantages (syntaxe alertnative: (--m2d20)
    • +
    • --desavantage : lance un dé de plus en attaque et garde le moins bon. plusieurs arguments désavantage se cumulent et sont annulés par les avantages.
    • +
    • --avecd12 : lance un d12 au lieu du d20 pour le jet d'attaque. L'attaque est impossible si l'attaquant est déjà affaibli.
    • +
    • --avecd12crit : comme --avecd12, mais le jet peut faire un critique. La plage de critique est divisée par 2, arrondie à l'inférieur. Ainsi si le d20 sevait critiquer sur un 20 seulement, le d12 ne fait pas de critique. Il fait un critique sur un 12 si le d20 devait faire un critique sur un 19 ou un 18, et ainsi de suite.
    • +
    • --incrDmgCoef n : augmente le coefficient des dégâts de base de 1. Les dégâts de base comprennent les dés de dommage de l'arme (ou du sort), plus tous les bonus constants. Le coefficient par défaut est de 1, et une réussite critique augmente ce coefficient de 1.
    • +
    • --incrCritCoef n : augmente le coefficient des dégâts critiques de n (1 si on ne donne pas d'argument).
    • +
    • --diviseDmg n : divise les dégâts de base par n.
    • +
    • --maxDmg : l'attaque inflige le maximum de DM permis par les dés de base.
    • +
    • --runeDePuissance : l'arme est enchantée avec une rune de puissance permanente.
    • +
    • --difficultePVmax : la difficulté du jet d'attaque est le maximum de PVs au lieu de la défense.
    • +
    • --difficultePV : la difficulté du jet d'attaque est la valeur courante des PVs au lieu de la défense.
    • +
    • --difficulteCarac carac : la difficulté du jet d'attaque est une des caractéristiques de la cible (sous forme de code à 3 lettres, FOR, DEX, etc). Il est possible de prendre le meilleur de 2 caractéristiques en écrivant les 2 noms collés. Par exemple, pour viser le meilleur de l'intelligence et du charisme, on écrira --difficuletCarac INTCHA.
    • --affute : augmente de 1 les chances de crit et +1d6 aux DM des crit.
    • --tirDeBarrage : ignore la charge, multiplie les DM par 2 et message pour undo si la cible bouge.
    • --tirAveugle : ignore le malus de tir sur une cible invisible.
    • -
    • --vicieux : ajoute 2d6 DM mais inflige 1d6 DM \xE0 l'attaquant.
    • -
    • --enflamme : enflamme la cible, lui infligeant 1d6 DM par tour. Les flammes s'\xE9teindent sur un 1 ou 2. Si l'option --puissant est donn\xE9e en conjonction, les DM augmentent de 1.
    • +
    • --vicieux : ajoute 2d6 DM mais inflige 1d6 DM à l'attaquant.
    • +
    • --enflamme : enflamme la cible, lui infligeant 1d6 DM par tour. Les flammes s'éteindent sur un 1 ou 2. Si l'option --puissant est donnée en conjonction, les DM augmentent de 1.
    • --malediction : maudit la cible pour 3 jets.
    • -
    • --asDeLaGachette : ajoute 1d6 DM si le jet d'attaque d\xE9passe une DEF de 25.
    • -
    • --armeDArgent : bonus de +2 en attaque et 1d6 aux DM si la cible est un mort-vivant ou un d\xE9mon (utilise le champ Race de la fiche ou si pr\xE9sent un pr\xE9dicat mortVivant).
    • -
    • --pietine : si l'attaquant est de taille au moins \xE9gale \xE0 celle de la cible (ou si la taille de l'un des deux n'est pas connue), fait un test oppos\xE9 de FOR. En cas d'\xE9chec de la cible, elle est renvers\xE9e et les DM sont doubl\xE9s.
    • -
    • --percute : comme --pietine, mais la cible est en plus projet\xE9e \xE0 1d6+1 m\xE8tres et \xE9tourdie si elle rate un test de CON difficult\xE9 15, renouvelable chaque tour.
    • -
    • --feinte : L'attaque ne fait pas de d\xE9g\xE2t, mais un bonus de +5 en attaque est donn\xE9 sur les attaques du tour suivant sur cette cible (par celui qui a fait la feinte), et +2d6 DM si l'attaque fictive \xE9tait un succ\xE8s. Si l'attaquant poss\xE8de un pr\xE9dicat bonusFeinte, c'est la valeur de ce pr\xE9dicat qui est donn\xE9 en bonus aux attaques, \xE0 la place de +5.
    • -
    • --enveloppe difficulte type expr : si l'attaque touche, elle a une chance d'envelopper la cible. Dans ce cas, un bouton appara\xEEt qui lance un test en opposition. Si celui-ci est remport\xE9 par l'attaquant, difficulte est la difficult\xE9 du test pour se sortir de l'enveloppement, type est soit label, et dans ce cas, expr doit \xEAtre le label d'une attaque de l'attaquant, soit ability, et dans ce cas, expr est le nom d'une ability de l'attaquant. Cette attaque ou ability est appel\xE9e pour les d\xE9g\xE2ts p\xE9riodiques. Si les deux derniers arguments sont ommis, le script prend label et le label de l'attaque courante, et si le premier argument est ommis, la difficult\xE9 est de 15.
    • -
    • --etreinte difficulte : si l'attaque touche, il y a une chance que l'attaquant puisse s'enrouler autour de la cible. Dans ce cas, un bouton appara\xEEt qui lance un test en opposition. Si celui-ci est remport\xE9 par l'attaquant, difficulte est la difficult\xE9 du test pour se sortir de l'enveloppement. Cela fera appara\xEEtre un bouton pour les d\xE9g\xE2ts de l'\xE9treinte, par d\xE9faut 1d6, mais on peut sp\xE9cifier une autre expression pour les d\xE9g\xE2ts (optionelle, juste apr\xE8s la difficult\xE9).
    • -
    • --ouvertureMortelle : touche automatiquement, fait des d\xE9g\xE2t comme en cas de critique et multiplie par 2 les d\xE9g\xE2ts d'attaque sournoise (si il y en a).
    • -
    • --rate, --touche, --critique, --echecCritique, --pasDEchecCritique : options pour tricher : le r\xE9sultat des d\xE9s donne toujours le r\xE9sultat voulu.
    • -
    • --ligne : l'attaque porte sur toutes les cibles \xE0 port\xE9e, entre l'attaquant et le token cibl\xE9. Si le token cibl\xE9 est plus proche que la port\xE9e de l'attaque, les tokens derri\xE8re le token cibl\xE9 sont aussi vis\xE9s. Pour permettre de viser un point quelconque, on peut utiliser un personnage d\xE9di\xE9 avec un maximum de 0 pv. \xC0 chaque fois qu'un token repr\xE9sentant ce personnage est utilis\xE9 comme cible de --ligne, le token est enlev\xE9 de la carte.
    • -
    • --disque r : l'attaque porte sur toutes les cibles dans le disque de centre le token cibl\xE9 et de rayon r. Comme pour --ligne, on peut utiliser un token cible qui sera supprim\xE9 apr\xE8s l'attaque. \xC0 noter que l'attaquant lui-m\xEAme peut prendre des d\xE9g\xE2ts, sauf si l'attaque a une port\xE9e nulle et que l'attaquant se cible lui-m\xEAme (attaque centr\xE9e sur le lanceur). On peut donner en argument optionel le mot souffleDeMort pour ne valider l'attaque que si le centre du disque est un personnage mort depuis moins d'un tour et ne garder que les alli\xE9s de ce personnage de niveau inf\xE9rieur ou \xE9gal.
    • -
    • --cone angle : cible toutes les cr\xE9atures dans un c\xF4ne de sommet l'attaquant, d'angle angle degr\xE9s (90 degr\xE9s par d\xE9faut), et s\xE9par\xE9 en deux par le segment joignant l'attaquant et le token vis\xE9.
    • -
    • --explosion : si l'attaque n'est pas d\xE9j\xE0 un disque, consid\xE8re qu'elle forme un disque de rayon \xE9gal \xE0 la port\xE9e. L'attaquant est automatiquement exclus de la zone.
    • -
    • --dmCible dmg : utilis\xE9 conjointement aux options de zone ci-dessus, cette option permet de remplacer les dommages de base de l'attaque sp\xE9cifiquement sur la cible s\xE9lectionn\xE9e lors de l'attaque
    • -
    • --saufAllies : ne cible pas les allies dans la zone ou les cibles sp\xE9cifi\xE9es.
    • -
    • --target id : ajoute une cible \xE0 l'attaque (s'ajoute \xE0 la cible principale et aux options d'aoe).
    • -
    • --ciblesDansDisque n : impose que les diff\xE9rentes cibles soient dans un disque de rayon n.
    • -
    • --ricochets n : l'arme de jet peut faire n ricochets. Une cible ne peut \xEAtre touch\xE9e qu'une fois par attaque.
    • -
    • --message texte : ajoute une ligne avec le message dans la fen\xEAtre de l'attaque. Attention, texte ne doit pas contenir la s\xE9quence --.
    • -
    • --secret : affiche les jets et r\xE9sultats de l'attaque seulement aux joueurs qui contr\xF4lent l'attaquant ou ses cibles, ainsi qu'au MJ.
    • -
    • --allonge n : ajoute n m\xE8tres \xE0 la port\xE9e d'une attaque au contact. L'allonge peut \xEAtre un nombre \xE0 virgule et m\xEAme n\xE9gative.
    • -
    • --canaliseParFamilier : le point de d\xE9part de l'attaque est le familier s'il est actif sur la carte.
    • -
    • --peutAgripper : l'attaque peut agripper comme si l'attaquant avait le pr\xE9dicat agripper.
    • -
    • --soundAttack son : joue le son son, \xE0 moins qu'une version plus longue de l'option (voir ci-dessous) n'existe et qu'elle soit active.
    • -
    • --soundAttackEchec son : joue le son son lorque l'arme fait un echec, sauf si c'est un \xE9chec particulier et une version plus longue existe.
    • +
    • --asDeLaGachette : ajoute 1d6 DM si le jet d'attaque dépasse une DEF de 25.
    • +
    • --armeDArgent : bonus de +2 en attaque et 1d6 aux DM si la cible est un mort-vivant ou un démon (utilise le champ Race de la fiche ou si présent un prédicat mortVivant).
    • +
    • --pietine : si l'attaquant est de taille au moins égale à celle de la cible (ou si la taille de l'un des deux n'est pas connue), fait un test opposé de FOR. En cas d'échec de la cible, elle est renversée et les DM sont doublés.
    • +
    • --percute : comme --pietine, mais la cible est en plus projetée à 1d6+1 mètres et étourdie si elle rate un test de CON difficulté 15, renouvelable chaque tour.
    • +
    • --feinte : L'attaque ne fait pas de dégât, mais un bonus de +5 en attaque est donné sur les attaques du tour suivant sur cette cible (par celui qui a fait la feinte), et +2d6 DM si l'attaque fictive était un succès. Si l'attaquant possède un prédicat bonusFeinte, c'est la valeur de ce prédicat qui est donné en bonus aux attaques, à la place de +5.
    • +
    • --enveloppe difficulte type expr : si l'attaque touche, elle a une chance d'envelopper la cible. Dans ce cas, un bouton apparaît qui lance un test en opposition. Si celui-ci est remporté par l'attaquant, difficulte est la difficulté du test pour se sortir de l'enveloppement, type est soit label, et dans ce cas, expr doit être le label d'une attaque de l'attaquant, soit ability, et dans ce cas, expr est le nom d'une ability de l'attaquant. Cette attaque ou ability est appelée pour les dégâts périodiques. Si les deux derniers arguments sont ommis, le script prend label et le label de l'attaque courante, et si le premier argument est ommis, la difficulté est de 15.
    • +
    • --etreinte difficulte : si l'attaque touche, il y a une chance que l'attaquant puisse s'enrouler autour de la cible. Dans ce cas, un bouton apparaît qui lance un test en opposition. Si celui-ci est remporté par l'attaquant, difficulte est la difficulté du test pour se sortir de l'enveloppement. Cela fera apparaître un bouton pour les dégâts de l'étreinte, par défaut 1d6, mais on peut spécifier une autre expression pour les dégâts (optionelle, juste après la difficulté).
    • +
    • --ouvertureMortelle : touche automatiquement, fait des dégât comme en cas de critique et multiplie par 2 les dégâts d'attaque sournoise (si il y en a).
    • +
    • --rate, --touche, --critique, --echecCritique, --pasDEchecCritique : options pour tricher : le résultat des dés donne toujours le résultat voulu.
    • +
    • --ligne : l'attaque porte sur toutes les cibles à portée, entre l'attaquant et le token ciblé. Si le token ciblé est plus proche que la portée de l'attaque, les tokens derrière le token ciblé sont aussi visés. Pour permettre de viser un point quelconque, on peut utiliser un personnage dédié avec un maximum de 0 pv. À chaque fois qu'un token représentant ce personnage est utilisé comme cible de --ligne, le token est enlevé de la carte.
    • +
    • --disque r : l'attaque porte sur toutes les cibles dans le disque de centre le token ciblé et de rayon r. Comme pour --ligne, on peut utiliser un token cible qui sera supprimé après l'attaque. À noter que l'attaquant lui-même peut prendre des dégâts, sauf si l'attaque a une portée nulle et que l'attaquant se cible lui-même (attaque centrée sur le lanceur). On peut donner en argument optionel le mot souffleDeMort pour ne valider l'attaque que si le centre du disque est un personnage mort depuis moins d'un tour et ne garder que les alliés de ce personnage de niveau inférieur ou égal.
    • +
    • --cone angle : cible toutes les créatures dans un cône de sommet l'attaquant, d'angle angle degrés (90 degrés par défaut), et séparé en deux par le segment joignant l'attaquant et le token visé.
    • +
    • --explosion : si l'attaque n'est pas déjà un disque, considère qu'elle forme un disque de rayon égal à la portée. L'attaquant est automatiquement exclus de la zone.
    • +
    • --dmCible dmg : utilisé conjointement aux options de zone ci-dessus, cette option permet de remplacer les dommages de base de l'attaque spécifiquement sur la cible sélectionnée lors de l'attaque
    • +
    • --saufAllies : ne cible pas les allies dans la zone ou les cibles spécifiées.
    • +
    • --target id : ajoute une cible à l'attaque (s'ajoute à la cible principale et aux options d'aoe).
    • +
    • --ciblesDansDisque n : impose que les différentes cibles soient dans un disque de rayon n.
    • +
    • --ricochets n : l'arme de jet peut faire n ricochets. Une cible ne peut être touchée qu'une fois par attaque.
    • +
    • --message texte : ajoute une ligne avec le message dans la fenêtre de l'attaque. Attention, texte ne doit pas contenir la séquence --.
    • +
    • --secret : affiche les jets et résultats de l'attaque seulement aux joueurs qui contrôlent l'attaquant ou ses cibles, ainsi qu'au MJ.
    • +
    • --allonge n : ajoute n mètres à la portée d'une attaque au contact. L'allonge peut être un nombre à virgule et même négative.
    • +
    • --canaliseParFamilier : le point de départ de l'attaque est le familier s'il est actif sur la carte.
    • +
    • --peutAgripper : l'attaque peut agripper comme si l'attaquant avait le prédicat agripper.
    • +
    • --soundAttack son : joue le son son, à moins qu'une version plus longue de l'option (voir ci-dessous) n'existe et qu'elle soit active.
    • +
    • --soundAttackEchec son : joue le son son lorque l'arme fait un echec, sauf si c'est un échec particulier et une version plus longue existe.
    • --soundAttackEchecCritique son : joue le son n lorque l'arme fait un echec critique
    • --soundAttackEchecClignotement son : joue le son son lorque l'arme fait un echec par clignotement
    • -
    • --soundAttackSucces son : joue le son son lorque l'arme fait un succ\xE8s
    • -
    • --soundAttackSuccesCritique son : joue le son n lorque l'arme fait un succ\xE8s critique
    • -
    • --soundAttackSuccesChampion son : joue le son son lorque l'arme fait un succ\xE8s champion
    • -
    • --imgAttack img : Affiche dans le chat l'image (.jpg/.png/.gif) img, \xE0 moins qu'une version plus longue de l'option (voir ci-dessous) n'existe et qu'elle soit active.
    • +
    • --soundAttackSucces son : joue le son son lorque l'arme fait un succès
    • +
    • --soundAttackSuccesCritique son : joue le son n lorque l'arme fait un succès critique
    • +
    • --soundAttackSuccesChampion son : joue le son son lorque l'arme fait un succès champion
    • +
    • --imgAttack img : Affiche dans le chat l'image (.jpg/.png/.gif) img, à moins qu'une version plus longue de l'option (voir ci-dessous) n'existe et qu'elle soit active.
    • --imgAttackEchecCritique img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec critique
    • --imgAttackEchec img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec
    • --imgAttackEchecClignotement img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec par clignotement
    • -
    • --imgAttackSuccesCritique img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s critique
    • -
    • --imgAttackSucces img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s
    • -
    • --imgAttackSuccesChampion img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s champion
    • +
    • --imgAttackSuccesCritique img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès critique
    • +
    • --imgAttackSucces img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès
    • +
    • --imgAttackSuccesChampion img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès champion
    • +
    • --terrainDifficile duree : si l'attaque affecte une zone en forme de disque, cette zone sera considérée comme du terrain difficile pendant duree tours. En deuxième argument, on peut mettre le nom de la zone, et en troisième argument une image à afficher sur la carte.
    • +
    • --deplaceDe dmax : l'attaquant se déplacer de dmax mètres maximum pour arriver à portée de sa cible. Le déplacement (et l'attaque) n'a lieu que si il existe une position libre, sans aucun token sur le trajet. On peut spécifier une distance minimum avec --deplaceDe min max. On peut aussi ajouter le mot-clé saut pour ignorer les tokens sur le trajet.
    -

    R\xE9duction des d\xE9g\xE2ts

    +

    Réduction des dégâts

    Fonctionnement de base
      -
    • Le script utilise les cases RD et Casque pr\xE9sentes sur les fiches.
    • -
    • Il est possible d'indiquer plusieurs RD diff\xE9rentes, il suffit de les s\xE9parer par une virgule.
    • +
    • Le script utilise les cases RD et Casque présentes sur les fiches.
    • +
    • Il est possible d'indiquer plusieurs RD différentes, il suffit de les séparer par une virgule.
    • Toutes les RD se cumulent.
    • -
    • Le script se base sur les types de d\xE9g\xE2ts pour choisir d'appliquer ou non les d\xE9g\xE2ts.
    • -
    • Pour les armes magiques, il est possible de sp\xE9cifier \xE0 la fois le type de l'arme (par exemple --tranchant) et --magique.
    • +
    • Le script se base sur les types de dégâts pour choisir d'appliquer ou non les dégâts.
    • +
    • Pour les armes magiques, il est possible de spécifier à la fois le type de l'arme (par exemple --tranchant) et --magique.
    RD simple
    -

    Dans le cas d'une RD simple (r\xE9sistance \xE0 tous les d\xE9g\xE2ts), il suffit d'indiquer un nombre. Exemple : 3

    -
    RD \xE0 un type de d\xE9g\xE2ts particuliers
    -

    Pour une RD qui ne s'applique qu'\xE0 un type de d\xE9g\xE2ts particuliers, indiquer le type et la valeur s\xE9par\xE9s par :. Exemple : feu:5. On peut aussi sp\xE9cifier une RD conte tous les types \xE9l\xE9mentaires avec le mot cl\xE9 elementaire. On peut aussi avoir une RD qui ne s'applique qu'aux attaques \xE0 distance avec le mot cl\xE9 distance.

    -
    RD sauf un ou plusieurs types de d\xE9g\xE2ts particuliers
    -

    Pour une RD qui s'applique tout le temps sauf un ou plusieurs types de d\xE9g\xE2ts particuliers, indiquer la valeur puis / puis les diff\xE9rents types s\xE9par\xE9s par _. Exemple /. Exemple : 5/argent_magique
    - Pour une RD qui s'appliquerait \xE0 tous les types d'armes sauf une, utiliser \xE0 la place une r\xE9sistance aux 2 autres types d'armes. Exemple, pour 5/tranchant, utiliser percant:5,contondant:5.

    +

    Dans le cas d'une RD simple (résistance à tous les dégâts), il suffit d'indiquer un nombre. Exemple : 3

    +
    RD à un type de dégâts particuliers
    +

    Pour une RD qui ne s'applique qu'à un type de dégâts particuliers, indiquer le type et la valeur séparés par :. Exemple : feu:5. On peut aussi spécifier une RD conte tous les types élémentaires avec le mot clé elementaire. On peut aussi avoir une RD qui ne s'applique qu'aux attaques à distance avec le mot clé distance.

    +
    RD sauf un ou plusieurs types de dégâts particuliers
    +

    Pour une RD qui s'applique tout le temps sauf un ou plusieurs types de dégâts particuliers, indiquer la valeur puis / puis les différents types séparés par _. Exemple /. Exemple : 5/argent_magique
    + Pour une RD qui s'appliquerait à tous les types d'armes sauf une, utiliser à la place une résistance aux 2 autres types d'armes. Exemple, pour 5/tranchant, utiliser percant:5,contondant:5.

    RD critique
    -

    Utiliser un pr\xE9dicat RD_critique avec comme valeur la r\xE9sistance aux critiques. Se combine avec une \xE9ventuelle RD critique fournie par le port d'un casque.

    -
    R\xE9sistances
    -

    Pour les effets qui divisent la d\xE9g\xE2ts subits d'un type donn\xE9, utilisez un pr\xE9dicat resistanceA_type. Une resistance \xE0 tous les d\xE9g\xE2ts non-magiques est possible avec resistanceA_nonMagique.Il est aussi possible d'octroyer une r\xE9sistance temporaire, par exemple une potion de r\xE9sistance au feu pourra \xEAtre simul\xE9e par la commande !cof-set-attribute resistanceA_feu true. Cela ne sera pas visible dans les pr\xE9dicats, local \xE0 un mook, et il faut ensuite effacer l'attribut \xE0 la fin de l'effet.

    -

    Pour les effets qui divisent par 2 les d\xE9g\xE2ts ou la dur\xE9e, utiliser un pr\xE9dicat diviseEffet_type.

    -

    Pour les effets qui donnent un bonus aux tests pour r\xE9sister aux effets ou d\xE9g\xE2ts d'un certain type, utiliser un pr\xE9dicat bonusSaveContre_type de valeur le bonus accord\xE9. Par exemple, un objet qui donnerait +5 \xE0 tous les tests pour r\xE9sister au poison pourrait \xEAtre encod\xE9 par un pr\xE9dicat bonusSaveContre_poison de valeur 5.

    +

    Utiliser un prédicat RD_critique avec comme valeur la résistance aux critiques. Se combine avec une éventuelle RD critique fournie par le port d'un casque.

    +
    Résistances
    +

    Pour les effets qui divisent la dégâts subits d'un type donné, utilisez un prédicat resistanceA_type. Une resistance à tous les dégâts non-magiques est possible avec resistanceA_nonMagique.Il est aussi possible d'octroyer une résistance temporaire, par exemple une potion de résistance au feu pourra être simulée par la commande !cof-set-attribute resistanceA_feu true. Cela ne sera pas visible dans les prédicats, local à un mook, et il faut ensuite effacer l'attribut à la fin de l'effet.

    +

    Pour les effets qui divisent par 2 les dégâts ou la durée, utiliser un prédicat diviseEffet_type.

    +

    Pour les effets qui donnent un bonus aux tests pour résister aux effets ou dégâts d'un certain type, utiliser un prédicat bonusSaveContre_type de valeur le bonus accordé. Par exemple, un objet qui donnerait +5 à tous les tests pour résister au poison pourrait être encodé par un prédicat bonusSaveContre_poison de valeur 5.

    Armures/Boucliers de Protection (COF p. 203)
    -

    ajoutez un pr\xE9dicat armureProtection ou bouclierProtection. Le script d\xE9tecte si l'\xE9quipement est port\xE9 ou pas via la fiche, et fonctionne sp\xE9cifiquement contre les attaques qui utilisent --sournoise. Il est aussi possible de sp\xE9cifier le port d'un anneau de protection ayant le m\xEAme effet (pr\xE9dicat anneauProtection.

    +

    ajoutez un prédicat armureProtection ou bouclierProtection. Le script détecte si l'équipement est porté ou pas via la fiche, et fonctionne spécifiquement contre les attaques qui utilisent --sournoise. Il est aussi possible de spécifier le port d'un anneau de protection ayant le même effet (prédicat anneauProtection.

    Manoeuvres

    -

    !cof-action-defensive avec comme argument soit simple, soit totale donne le bonus en d\xE9fense de l'action d\xE9fensive (p 71). Cette action est disponible par d\xE9faut dans la liste des actions du tour. Alternativement, si vous n'utilisez pas cette m\xE9thode, vous pouvez cr\xE9er une macro accessible \xE0 tous les tokens, !cof-action-defensive ?{Action d\xE9fensive|simple|totale}.

    -

    Les manoeuvres risqu\xE9es peuvent \xEAtre lanc\xE9es avec la commande !cof-manoeuvre @{selected|token_id} @{target|token_id} effet. Liste des manoeuvres : aveugler, bloquer, desarmer, faireDiversion, menacer, renverser, repousser, tenirADistance.

    -

    Il est aussi possible de faire un test d'attaque oppos\xE9e avec la commande !cof-test-attaque-opposee @{selected|token_id} @{target|token_id}.

    +

    !cof-action-defensive avec comme argument soit simple, soit totale donne le bonus en défense de l'action défensive (p 71). Cette action est disponible par défaut dans la liste des actions du tour. Alternativement, si vous n'utilisez pas cette méthode, vous pouvez créer une macro accessible à tous les tokens, !cof-action-defensive ?{Action défensive|simple|totale}.

    +

    Les manoeuvres risquées peuvent être lancées avec la commande !cof-manoeuvre @{selected|token_id} @{target|token_id} effet. Liste des manoeuvres : aveugler, bloquer, desarmer, faireDiversion, menacer, renverser, repousser, tenirADistance.

    +

    Il est aussi possible de faire un test d'attaque opposée avec la commande !cof-test-attaque-opposee @{selected|token_id} @{target|token_id}.

    Recharger des armes : !cof-recharger N

    -

    Il faut un pr\xE9dicat charge dans le champ de pr\xE9dicat des armes qui ont besoin d'\xEAtre charg\xE9es pour fonctionner. On peut associer un nombre au pr\xE9dicat, pour indiquer un maximum de charges sup\xE9rieur \xE0 1. Noter que si on a 2 armes \xE0 une charge, il faut utiliser un maximum de 2.
    - Recharge l'arme N (augmente les charges d'un). Les armes sont toutes recharg\xE9es \xE0 la fin d'un combat.
    - La commande admet un argment optionel --grenaille pour charger (une arme \xE0 poudre) avec de la grenaille. +

    Il faut un prédicat charge dans le champ de prédicat des armes qui ont besoin d'être chargées pour fonctionner. On peut associer un nombre au prédicat, pour indiquer un maximum de charges supérieur à 1. Noter que si on a 2 armes à une charge, il faut utiliser un maximum de 2.
    + Recharge l'arme N (augmente les charges d'un). Les armes sont toutes rechargées à la fin d'un combat.
    + La commande admet un argment optionel --grenaille pour charger (une arme à poudre) avec de la grenaille.

    -

    D\xE9gainer une arme : !cof-degainer N

    +

    Dégainer une arme : !cof-degainer N

    -

    Pour certaines capacit\xE9s, (commme Plus vite que son ombre ou D\xE9sarmer), il peut \xEAtre utile de savoir quelle arme est en main. Pour cela, le script peut utiliser deux m\xE9thodes : +

    Pour certaines capacités, (commme Plus vite que son ombre ou Désarmer), il peut être utile de savoir quelle arme est en main. Pour cela, le script peut utiliser deux méthodes :

      -
    • !cof-degainer L o\xF9 L est le label d'une des attaques sur la fiche de personnage : cela fait rengainer l'arme en main et d\xE9gainer l'arme correspondant \xE0 cette attaque. Si le label ne correspond \xE0 aucune attaque (ou qu'on ne donne pas de label), l'action fait rengainer l'arme en main. On peut donner en argument 2 labels d'armes, pour faire d\xE9gainer \xE0 la fois une arme dans la main droite (le premier label) et une arme dans la main gauche. !cof-degainer l gauche permet de d\xE9gainer uniquement une arme dans la main gauche. \xC0 noter que si une arme est not\xE9e comme arme gauche dans l'attaque, alors elle est toujours port\xE9e en main gauche. L'ordre de rengainer fait rengainer les deux armes si le personnage porte une arme en main gauche.
    • -
    • Si on attaque avec !cof-attack tok1 tok2 L, et que l'attaque est de type Arme 1 main, Arme 2 mains ou Arme gauche, alors on consid\xE8re qu'on doit d\xE9gainer cette arme pour pouvoir l'utiliser. Le script envoie le message et consid\xE8re ensuite l'arme comme \xE9tant en main, au MJ de v\xE9rifier que le joueur dispose bien d'une action de mouvement pour le faire.
    • -
    • En fin de combat, si le personnage a la capacit\xE9 frappe du vide, le script va automatiquement lui faire rengainer son arme.
    • -
    • Enfin, en fin de combat, si le personnage poss\xE8de un pr\xE9dicat armeParDefaut, le script va lui faire d\xE9gainer l'arme dont le label est la valeur du pr\xE9dicat. Donc si le pr\xE9dicat n'a pas de label associ\xE9, le personnage va rengainer son arme.
    • +
    • !cof-degainer LL est le label d'une des attaques sur la fiche de personnage : cela fait rengainer l'arme en main et dégainer l'arme correspondant à cette attaque. Si le label ne correspond à aucune attaque (ou qu'on ne donne pas de label), l'action fait rengainer l'arme en main. On peut donner en argument 2 labels d'armes, pour faire dégainer à la fois une arme dans la main droite (le premier label) et une arme dans la main gauche. !cof-degainer l gauche permet de dégainer uniquement une arme dans la main gauche. À noter que si une arme est notée comme arme gauche dans l'attaque, alors elle est toujours portée en main gauche. L'ordre de rengainer fait rengainer les deux armes si le personnage porte une arme en main gauche.
    • +
    • Si on attaque avec !cof-attack tok1 tok2 L, et que l'attaque est de type Arme 1 main, Arme 2 mains ou Arme gauche, alors on considère qu'on doit dégainer cette arme pour pouvoir l'utiliser. Le script envoie le message et considère ensuite l'arme comme étant en main, au MJ de vérifier que le joueur dispose bien d'une action de mouvement pour le faire.
    • +
    • En fin de combat, si le personnage a la capacité frappe du vide, le script va automatiquement lui faire rengainer son arme.
    • +
    • Enfin, en fin de combat, si le personnage possède un prédicat armeParDefaut, le script va lui faire dégainer l'arme dont le label est la valeur du prédicat. Donc si le prédicat n'a pas de label associé, le personnage va rengainer son arme.
    -

    Dans tous les cas, si le personnage d\xE9gaine une arme \xE0 2 mains, le script fait enlever le bouclier, et il le fait remettre si on passe d'une arme \xE0 2 mains \xE0 une arme \xE0 1 main.

    -

    Il existe un pr\xE9dicat DEF qui permet d'ajouter sa valeur \xE0 la d\xE9fense d'un personnage. C'est particuli\xE8rement utile pour coder une arme de parade. Par exemple avecDEF:2 dans les pr\xE9dicats de l'arme, elle augmentera la d\xE9fense de 2 quand elle sera port\xE9e.

    +

    Dans tous les cas, si le personnage dégaine une arme à 2 mains, le script fait enlever le bouclier, et il le fait remettre si on passe d'une arme à 2 mains à une arme à 1 main.

    +

    Il existe un prédicat DEF qui permet d'ajouter sa valeur à la défense d'un personnage. C'est particulièrement utile pour coder une arme de parade. Par exemple avecDEF:2 dans les prédicats de l'arme, elle augmentera la défense de 2 quand elle sera portée.

    Couvert :!cof-bonus-couvert b

    - Pour donner un bonus en DEF contre toutes les attaques \xE0 distance, on peut utiliser !cof-bonus-couvert ?{Bonus du couvert?} en s\xE9lectionnant les tokens b\xE9n\xE9ficiant du couvert. La commande accepte un argument --secret permettant de ne pas faire conna\xEEtre l'action du personnage \xE0 tous les joueurs. Pour ne plus \xEAtre \xE0 couvert, il suffit de lancer la commande sans argument. + Pour donner un bonus en DEF contre toutes les attaques à distance, on peut utiliser !cof-bonus-couvert ?{Bonus du couvert?} en sélectionnant les tokens bénéficiant du couvert. La commande accepte un argument --secret permettant de ne pas faire connaître l'action du personnage à tous les joueurs. Pour ne plus être à couvert, il suffit de lancer la commande sans argument.
    -

    \xC9checs critiques :

    -

    En cas d'\xE9chec critique \xE0 une attaque, le script va sugg\xE9rer des effets d'\xE9chec critique inspir\xE9s de cette table sugg\xE9r\xE9e par l'auteur du jeu. Le script proposera m\xEAme dans la plupart des cas un bouton qui automatisera les lancers de d\xE9s et l'application de l'effet, si relevant.

    -

    Il est aussi possible d'utiliser une table personnelle, non-automatis\xE9e (voir les options d'affichage, !cof-options affichage). La table utilis\xE9e (Echec-Critique-Contact) peut \xEAtre modifi\xE9e par le MJ.

    -

    D\xE9g\xE2ts directs (sans attaquant, ou aire d'effet trop complexe pour !cof-attack) : !cof-dmg dm

    +

    Échecs critiques :

    +

    En cas d'échec critique à une attaque, le script va suggérer des effets d'échec critique inspirés de cette table suggérée par l'auteur du jeu. Le script proposera même dans la plupart des cas un bouton qui automatisera les lancers de dés et l'application de l'effet, si relevant.

    +

    Il est aussi possible d'utiliser une table personnelle, non-automatisée (voir les options d'affichage, !cof-options affichage). La table utilisée (Echec-Critique-Contact) peut être modifiée par le MJ.

    +

    Dégâts directs (sans attaquant, ou aire d'effet trop complexe pour !cof-attack) : !cof-dmg dm

    -

    Applique des d\xE9g\xE2ts \xE0 tous les tokens s\xE9lectionn\xE9s. L'argument dm peut \xEAtre un inline roll. Utile par exemple pour les chutes, ou bien les d\xE9g\xE2ts d'environnement, voire de pi\xE8ges.
    - Arguments optionels: une partie des options de !cof-attack, dont le type, et par exemple --psave carac seuil (jet de carac, si sup\xE9rieur au seuil, les d\xE9g\xE2ts sont divis\xE9s par 2). On peut aussi donner un titre aux d\xE9g\xE2ts en utilisant l'option --titre +

    Applique des dégâts à tous les tokens sélectionnés. L'argument dm peut être un inline roll. Utile par exemple pour les chutes, ou bien les dégâts d'environnement, voire de pièges.
    + Arguments optionels: une partie des options de !cof-attack, dont le type, et par exemple --psave carac seuil (jet de carac, si supérieur au seuil, les dégâts sont divisés par 2). On peut aussi donner un titre aux dégâts en utilisant l'option --titre

    -

    Il est possible d'infliger des d\xE9g\xE2ts sur la dur\xE9e en utilisant la commande !cof-effet-temp dotGen(nom) duree --valeur expr type. Les arguments de --valeur donnent l'expression \xE0 \xE9valuer, de type lanc\xE9 de d\xE9, et le type de d\xE9g\xE2ts. Par d\xE9faut, si rien n'est pr\xE9cis\xE9, c'est 1d6 et normal. On peut utiliser les options habituelles de !cof-effet-temp. Ainsi, si on souhaite infliger des d\xE9g\xE2ts de poison de 1d4+1 par tour, pendant 10 tours, avec un jet de CON difficult\xE9 12 pour arr\xEAter l'effet, on pourra \xE9crire !cof-effet-temp dotGen(monPoison) 10 --saveParTour CON 12 --valeur 1d4+1 poison. +

    Il est possible d'infliger des dégâts sur la durée en utilisant la commande !cof-effet-temp dotGen(nom) duree --valeur expr type. Les arguments de --valeur donnent l'expression à évaluer, de type lancé de dé, et le type de dégâts. Par défaut, si rien n'est précisé, c'est 1d6 et normal. On peut utiliser les options habituelles de !cof-effet-temp. Ainsi, si on souhaite infliger des dégâts de poison de 1d4+1 par tour, pendant 10 tours, avec un jet de CON difficulté 12 pour arrêter l'effet, on pourra écrire !cof-effet-temp dotGen(monPoison) 10 --saveParTour CON 12 --valeur 1d4+1 poison.

    Sortir du combat : !cof-fin-combat

    -

    Ferme aussi le tracker de tour. Encore \xE0 mettre en macro dans la barre du MJ (macro automatiquement g\xE9n\xE9r\xE9e par !cof-set-macros). Permet de tenir compte de pleins de capacit\xE9s qui durent un combat, ou utilisables une seule fois par combat,...

    +

    Ferme aussi le tracker de tour. Encore à mettre en macro dans la barre du MJ (macro automatiquement générée par !cof-set-macros). Permet de tenir compte de pleins de capacités qui durent un combat, ou utilisables une seule fois par combat,...

    -

    Utilisation sp\xE9ciale des images et son des armes

    +

    Utilisation spéciale des images et son des armes

    -

    Les images des armes et les sons peuvent \xEAtre red\xE9finis dans le champ d\xE9tail de l'arme.

    +

    Les images des armes et les sons peuvent être redéfinis dans le champ détail de l'arme.

    Pour ce faire vous devez ajouter les urls des images au format suivant dans la description de l'arme :

    -

    [Type de r\xE9ussite] url de l'image [Type de r\xE9ussite]

    +

    [Type de réussite] url de l'image [Type de réussite]

    Par exemple : [img-attack-echec-critique]https://media0.giphy.com/media/3og0INyCmHlNylks9O/giphy.gif[img-attack-echec-critique]

    -

    Les types de r\xE9ussite que vous pouvez mettre en image sont :

    +

    Les types de réussite que vous pouvez mettre en image sont :

    • [img-attack-echec-critique] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec critique
    • [img-attack-echec] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec
    • [img-attack-echec-clignotement] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un echec par clignotement
    • -
    • [img-attack-succes-critique] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s critique
    • -
    • [img-attack-succes] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s
    • -
    • [img-attack-succes-champion] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succ\xE8s champion
    • +
    • [img-attack-succes-critique] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès critique
    • +
    • [img-attack-succes] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès
    • +
    • [img-attack-succes-champion] img : Affiche dans le chat l'image (.jpg/.png/.gif) img lorque l'arme fait un succès champion
    -

    De la m\xEAme mani\xE8re vous pouvez ajouter des sons :

    -

    [Type de r\xE9ussite] Nom du son dans votre jukebox [Type de r\xE9ussite]

    +

    De la même manière vous pouvez ajouter des sons :

    +

    [Type de réussite] Nom du son dans votre jukebox [Type de réussite]

    • [sound-attack-echec-critique] son : joue le son n lorque l'arme fait un echec critique
    • [sound-attack-echec] son : joue le son son lorque l'arme fait un echec
    • [sound-attack-echec-clignotement] son : joue le son son lorque l'arme fait un echec par clignotement
    • -
    • [sound-attack-succes-critique] son : joue le son n lorque l'arme fait un succ\xE8s critique
    • -
    • [sound-attack-succes] son : joue le son son lorque l'arme fait un succ\xE8s
    • -
    • [sound-attack-succes-champion] son : joue le son son lorque l'arme fait un succ\xE8s champion
    • +
    • [sound-attack-succes-critique] son : joue le son n lorque l'arme fait un succès critique
    • +
    • [sound-attack-succes] son : joue le son son lorque l'arme fait un succès
    • +
    • [sound-attack-succes-champion] son : joue le son son lorque l'arme fait un succès champion

    Par exemple : [sound-attack-echec-critique]bang[sound-attack-echec-critique]

    -

    Dans cette exemple le son nom\xE9 "bang" dans votre jutbox serra jou\xE9 a chaque echec critique de cette arme

    +

    Dans cette exemple le son nomé "bang" dans votre jutbox serra joué a chaque echec critique de cette arme

    2.2 Soins :

    !cof-soin @{selected|token_id} @{target|token_id} x

    -

    x peut \xEAtre un nombre, un jet de d\xE9 ou leger, modere, groupe ou secondSouffle.

    -

    Les deux premiers arguments sont optionnels. Si !cof-soin n'a qu'un seul argument, c'est interpr\xE9t\xE9 comme le montant des soins, et les tokens soign\xE9s sont ceux s\xE9lectionn\xE9s. Si !cof-soin n'a que 2 arguments, le premier argument est le token du soigneur, et les cibles doivent \xEAtre d\xE9sign\xE9es avec une option de s\xE9lection de groupe.

    +

    x peut être un nombre, un jet de dé ou leger, modere, groupe ou secondSouffle.

    +

    Les deux premiers arguments sont optionnels. Si !cof-soin n'a qu'un seul argument, c'est interprété comme le montant des soins, et les tokens soignés sont ceux sélectionnés. Si !cof-soin n'a que 2 arguments, le premier argument est le token du soigneur, et les cibles doivent être désignées avec une option de sélection de groupe.

    Options (en plus de options normales de commandes):
      -
    • --portee n : permet de sp\xE9cifier une distance maximum entre le soigneur et le soign\xE9 (au-del\xE0, le soin \xE9choue)
    • -
    • --transfer : le soin est pay\xE9 avec les PV du soigneur
    • +
    • --portee n : permet de spécifier une distance maximum entre le soigneur et le soigné (au-delà, le soin échoue)
    • +
    • --transfer : le soin est payé avec les PV du soigneur
    • --mana n : demande au lanceur de payer n points de mana
    • -
    • --depasseLimite n : permet de lancer les sorts de soins l\xE9ger, mod\xE9r\xE9 ou de groupe quand la limite journali\xE8re est d\xE9pass\xE9e, mais en augmentant le co\xFBt en mana de n \xE0 chaque nouveau d\xE9passement.
    • -
    • --limiteSoinsParJour n : limite le nombre total de PVs soign\xE9s par jour. Cette limite peut \xEAtre associ\xE9e \xE0 une ressource (sp\xE9cifier en deuxi\xE8me argument de l'option, peut contenir des espaces), de sorte que seuls les soins qui mentionnent cette ressource sont concern\xE9s par cette limitation. Cette option n'a de sens que si un soigneur est pr\xE9cis\xE9.
    • -
    • --sacrifierPV : le soigneur doit sacrifier autant de PV que le montant des soins (que ces soins soient utilis\xE9s ou non).
    • +
    • --depasseLimite n : permet de lancer les sorts de soins léger, modéré ou de groupe quand la limite journalière est dépassée, mais en augmentant le coût en mana de n à chaque nouveau dépassement.
    • +
    • --limiteSoinsParJour n : limite le nombre total de PVs soignés par jour. Cette limite peut être associée à une ressource (spécifier en deuxième argument de l'option, peut contenir des espaces), de sorte que seuls les soins qui mentionnent cette ressource sont concernés par cette limitation. Cette option n'a de sens que si un soigneur est précisé.
    • +
    • --sacrifierPV : le soigneur doit sacrifier autant de PV que le montant des soins (que ces soins soient utilisés ou non).
    @@ -616,33 +620,33 @@

    2.3 Repos et changement de jour

    Changement de jour

    -

    !cof-nouveau-jour : remise \xE0 z\xE9ro de toutes les limites journali\xE8res.

    +

    !cof-nouveau-jour : remise à zéro de toutes les limites journalières.

    Repos de plus de 8 h

    -

    Fait r\xE9cup\xE9rer 1 PR ou les points de vie correspondant \xE0 1 PR, plus les points de mana.

    +

    Fait récupérer 1 PR ou les points de vie correspondant à 1 PR, plus les points de mana.

      -
    • !cof-nouveau-jour --repos : Pour une nuit qui se passe bien : fait l'effet d'un nouveau jour sur le monde, et, si aucun token n'est s\xE9lectionn\xE9, applique un repos de 8 h \xE0 tous les tokens de la page, sinon applique ce repos uniquement aux tokens s\xE9lectionn\xE9s.
    • -
    • !cof-recuperation --reposLong : applique le repos aux tokens selectionn\xE9s, sans remettre \xE0 z\xE9ro les limites journali\xE8res. +
    • !cof-nouveau-jour --repos : Pour une nuit qui se passe bien : fait l'effet d'un nouveau jour sur le monde, et, si aucun token n'est sélectionné, applique un repos de 8 h à tous les tokens de la page, sinon applique ce repos uniquement aux tokens sélectionnés.
    • +
    • !cof-recuperation --reposLong : applique le repos aux tokens selectionnés, sans remettre à zéro les limites journalières.

    Repos de 10 minutes

    -

    !cof-recuperation : d\xE9pense 1 PR pour se soigner. \xC0 mettre en macro associ\xE9e aux tokens, car tous les joueurs en ont besoin (g\xE9n\xE9r\xE9 par !cof-set-macros.

    +

    !cof-recuperation : dépense 1 PR pour se soigner. À mettre en macro associée aux tokens, car tous les joueurs en ont besoin (généré par !cof-set-macros.

    -

    2.4 Statut et \xE9tats

    +

    2.4 Statut et états

    -

    !cof-statut affiche l'\xE9tat courant de tous les tokens s\xE9lectionn\xE9s. Utile pour conna\xEEtre facilement les \xE9tats qui ne sont pas directement visibles sur un token (points de r\xE9cup\xE9ration, armes charg\xE9es, ...). Il est possible de rajouter l'affichage d'autres attributs que ceux s\xE9lectionn\xE9s par d\xE9faut par le script. Pour cela, utiliser un pr\xE9dicat attributsDeStatut, de valeur la liste des noms d'attributs \xE0 afficher, s\xE9par\xE9s par des virgules. Attention, si vous avez besoin de s\xE9parer vos attributs par des virgules, pensez \xE0 utiliser la syntaxe avec ::. Si vous le souhaitez, vous pouvez utiliser plusieurs pr\xE9dicats nomm\xE9s attributsDeStatut.

    -

    \xC9tats g\xE9r\xE9s en utilisant le statut des tokens

    +

    !cof-statut affiche l'état courant de tous les tokens sélectionnés. Utile pour connaître facilement les états qui ne sont pas directement visibles sur un token (points de récupération, armes chargées, ...). Il est possible de rajouter l'affichage d'autres attributs que ceux sélectionnés par défaut par le script. Pour cela, utiliser un prédicat attributsDeStatut, de valeur la liste des noms d'attributs à afficher, séparés par des virgules. Attention, si vous avez besoin de séparer vos attributs par des virgules, pensez à utiliser la syntaxe avec ::. Si vous le souhaitez, vous pouvez utiliser plusieurs prédicats nommés attributsDeStatut.

    +

    États gérés en utilisant le statut des tokens

    -

    !cof-set-state etat [true|false] permet de changer l'\xE9tat des tokens s\xE9lectionn\xE9s. Si cet \xE9tat concerne un personnage avec tokens li\xE9s (en liant la barre 1 aux points de vie), alors l'\xE9tat persiste si on change de carte (utilisation d'un attribut hors fiche).

    -

    Liste des \xE9tats et markers correspondants :

    +

    !cof-set-state etat [true|false] permet de changer l'état des tokens sélectionnés. Si cet état concerne un personnage avec tokens liés (en liant la barre 1 aux points de vie), alors l'état persiste si on change de carte (utilisation d'un attribut hors fiche).

    +

    Liste des états et markers correspondants :

    - + @@ -653,40 +657,40 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - + - - - - - @@ -700,14 +704,14 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - - @@ -716,19 +720,19 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - + - + - @@ -742,7 +746,7 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - @@ -756,7 +760,7 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    - @@ -764,393 +768,393 @@

    \xC9tats g\xE9r\xE9s en utilisant le statu

    LdB : Livre de Base, Comp : Compagnon
    \xC9tatÉtat Source Remarque Marker Std.
    Affaibli LdB p70Appara\xEEt sur la fiche persoApparaît sur la fiche perso half-heart cof-affaibli
    Apeur\xE9 + Apeuré Victime d'un sort de Peur screaming cof-apeure
    Assomm\xE9 + Assommé LdB p72 pummeled cof-assomme
    Aveugl\xE9 + Aveuglé LdB p70 Change aussi la vision du token bleeding-eye cof-aveugle
    Bless\xE9 + Blessé LdB p177 arrowed cof-blesse
    Encombr\xE9 + Encombré Comp p103 frozen-orbcof-endormi
    \xC9tourdi + Étourdi LdB p70 half-haze cof-etourdi
    Immobilis\xE9 + Immobilisé LdB p70 cobweb
    Invisible Sort d'invisibilit\xE9Sort d'invisibilité ninja-mask cof-invisible
    Mort LdB p73M\xEAme \xE9tat pour un PJ juste inconscient \xE0 0 PVMême état pour un PJ juste inconscient à 0 PV dead dead
    Paralys\xE9 + Paralysé LdB p70 fishing-netcof-ralenti
    Renvers\xE9 + Renversé LdB p70 back-paincof-surpris
    P\xE9nombre + Pénombre LdB p71 archery-target
    -

    Pour faciliter la gestion des \xE9tats, on peut deux macros dans la barre du GM, !cof-set-state ?{\xC9tat|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|bless\xE9|encombre} true, et la m\xEAme avec false. (N'oubliez pas que la commande !cof-set-macros permet de g\xE9n\xE9rer automatiquement les macros utiles au script). Une fois qu'on conna\xEEt bien les ic\xF4nes, on peut directement les changer sur les tokens pour le m\xEAme effet (et m\xEAme faire un undo de ces changements si besoin).

    -

    \xC0 noter qu'un personnage ayant un pr\xE9dicat nomm\xE9 immunite_etat ne pourra pas \xEAtre mis dans l'\xE9tat etat.

    -

    Enfin, il est possible de faire r\xE9aliser un jet pour se lib\xE9rer d'un \xE9tat, en utilisant la commande !cof-save-state etat carac seuil. Il est possible de remplacer seuil par une id de token pour faire faire un test en opposition avec ce token. On peut aussi passer la caract\xE9ristique et le seuil en argument \xE0 !cof-set-state pour proposer le jet \xE0 chaque fois qu'on affiche les actions du tour ou qu'on affiche le statut du personnage.

    +

    Pour faciliter la gestion des états, on peut deux macros dans la barre du GM, !cof-set-state ?{État|mort|surpris|assomme|renverse|aveugle|affaibli|etourdi|paralyse|ralenti|immobilise|endormi|apeure|invisible|blessé|encombre} true, et la même avec false. (N'oubliez pas que la commande !cof-set-macros permet de générer automatiquement les macros utiles au script). Une fois qu'on connaît bien les icônes, on peut directement les changer sur les tokens pour le même effet (et même faire un undo de ces changements si besoin).

    +

    À noter qu'un personnage ayant un prédicat nommé immunite_etat ne pourra pas être mis dans l'état etat.

    +

    Enfin, il est possible de faire réaliser un jet pour se libérer d'un état, en utilisant la commande !cof-save-state etat carac seuil. Il est possible de remplacer seuil par une id de token pour faire faire un test en opposition avec ce token. On peut aussi passer la caractéristique et le seuil en argument à !cof-set-state pour proposer le jet à chaque fois qu'on affiche les actions du tour ou qu'on affiche le statut du personnage.

    -

    Affaiblissements de caract\xE9ristiques

    +

    Affaiblissements de caractéristiques

    - !cof-affaiblir-carac carac valeur permet d'affaiblir temporairement une caract\xE9ristique (force, dext\xE9rit\xE9, constitution, intelligence, sagesse, charisme ou random) d'une valeur positive. Il existe aussi une option pour les attaques, --affaiblirCarac, qui permet de n'affaiblir une caract\xE9ristique que si une attaque est r\xE9ussie. + !cof-affaiblir-carac carac valeur permet d'affaiblir temporairement une caractéristique (force, dextérité, constitution, intelligence, sagesse, charisme ou random) d'une valeur positive. Il existe aussi une option pour les attaques, --affaiblirCarac, qui permet de n'affaiblir une caractéristique que si une attaque est réussie.

    -

    Une caract\xE9ristique affaiblie remonte de 1 apr\xE8s chaque nuit de repos. Le sort de r\xE9g\xE9n\xE9ration permet de r\xE9cup\xE9rer 1d4 points d'une seule caract\xE9ristique physique (d'abord constitution, puis force puis dext\xE9rit\xE9). Le sort d\xE9livrance permet de r\xE9cup\xE9rer 1d4 point d'une seule caract\xE9ristique, et comme indiqu\xE9 dans les r\xE8gles, le sort de gu\xE9rison annule tous les affaiblissements de caract\xE9ritiques. Enfin le script propose une commande d\xE9di\xE9e, !cof-soigner-affaiblissement carac valeur pour soigner les affaiblissements. +

    Une caractéristique affaiblie remonte de 1 après chaque nuit de repos. Le sort de régénération permet de récupérer 1d4 points d'une seule caractéristique physique (d'abord constitution, puis force puis dextérité). Le sort délivrance permet de récupérer 1d4 point d'une seule caractéristique, et comme indiqué dans les règles, le sort de guérison annule tous les affaiblissements de caractéritiques. Enfin le script propose une commande dédiée, !cof-soigner-affaiblissement carac valeur pour soigner les affaiblissements.

    -

    \xC0 noter que la diminution de constitution fait baisser les points de vie maximum, et qu'une constitution de 0 conduit \xE0 la mort.

    +

    À noter que la diminution de constitution fait baisser les points de vie maximum, et qu'une constitution de 0 conduit à la mort.

    -

    Conditions hostiles et extr\xEAmes

    +

    Conditions hostiles et extrêmes

    -

    Pour des conditions hostiles, faire !cof-effet conditionsHostiles oui en s\xE9lectionnant les personnages concern\xE9s. Pour des conditions extr\xEAmes, !cof-effet conditionsHostiles 5. \xC0 noter que le script permet de passer en argument n'importe quel nombre, qui sera appliqu\xE9 en malus \xE0 la DEX, FOR, DEF et attaque.

    +

    Pour des conditions hostiles, faire !cof-effet conditionsHostiles oui en sélectionnant les personnages concernés. Pour des conditions extrêmes, !cof-effet conditionsHostiles 5. À noter que le script permet de passer en argument n'importe quel nombre, qui sera appliqué en malus à la DEX, FOR, DEF et attaque.

    Autres bufs et debufs

    !cof-buf-def n : buf ou debuf de la DEF.

    -

    !cof-remove-buf-def : enl\xE8ve tout buf ou debuf de la def.

    -

    !cof-effet-temp effet duree : ajoute l'effet effet \xE0 la cible pour la dur\xE9e, !cof-effet-combat effet ajoute l'effet pour le combat, et !cof-effet effet ajoute ou enl\xE8ve un effet \xE0 dur\xE9e ind\xE9termin\xE9e. \xC0 noter que si la dur\xE9e est 0 ou fin, alors la commande met fin \xE0 l'effet (utile pour des effets temporaires qui ont une action en fin d'effet, comme agrandissement ou formeDArbre). Un personnage ayant un pr\xE9dicat nomm\xE9 immunite_effetTemp est immunis\xE9 \xE0 l'effet temporaire de nom effetTemp.

    +

    !cof-remove-buf-def : enlève tout buf ou debuf de la def.

    +

    !cof-effet-temp effet duree : ajoute l'effet effet à la cible pour la durée, !cof-effet-combat effet ajoute l'effet pour le combat, et !cof-effet effet ajoute ou enlève un effet à durée indéterminée. À noter que si la durée est 0 ou fin, alors la commande met fin à l'effet (utile pour des effets temporaires qui ont une action en fin d'effet, comme agrandissement ou formeDArbre). Un personnage ayant un prédicat nommé immunite_effetTemp est immunisé à l'effet temporaire de nom effetTemp.

    • --lanceur id : indique quel est le lanceur. Utile pour un certain nombre d'autres options.
    • -
    • --mana id cout : impose au token id de d\xE9penser cout mana. Si --lanceur est donn\xE9, id est inutile. La pr\xE9sence de cette option, m\xEAme avec un co\xFBt de 0, indique au script que l'effet devrait \xEAtre supprim\xE9 \xE0 la mort du lanceur.
    • -
    • --limiteParJour l : limite le nombre d'utilisations de cette effet \xE0 l fois par jour. On peut pr\xE9ciser un nom apr\xE8s l, qui va correspondre \xE0 une ressource pouvant \xEAtre partag\xE9e avec d'autres attaques ou d'autres effets (voir !cof-attack). Par d\xE9faut, le nom de cette ressource est effet. Attention, il faut un lanceur auquel appliquer la limite par jour !
    • -
    • --limiteParCombat : m\xEAme effet que la limite par jour. Si aucun argument n'est donn\xE9, la limite est de une fois par combat. Attention, il faut un lanceur auquel appliquer la limite par combat !
    • -
    • --tempsRecharge effet duree : l'action n'est possible que si l'effet est inactif sur le personnage qui g\xE9n\xE8re l'effet, et de plus active l'effet sur celui-ci pour la dur\xE9e indiqu\xE9e. Il existe un effet temporaire g\xE9n\xE9rique, rechargeGen(desc) que vous pouvez utiliser si aucun effet existant ne correspond.
    • -
    • --dose nom: d\xE9finie une ressource nomm\xE9e dose_nom, dont la valeur doit \xEAtre positive. Utile par exemple pour les parchemins, les potions ou les baguettes.
    • -
    • --portee id d : impose aux cibles de l'effet d'\xEAtre \xE0 moins de d m\xE8tres du token id. Si --lanceur est pr\xE9cis\xE9, inutile de donner id.
    • +
    • --mana id cout : impose au token id de dépenser cout mana. Si --lanceur est donné, id est inutile. La présence de cette option, même avec un coût de 0, indique au script que l'effet devrait être supprimé à la mort du lanceur.
    • +
    • --limiteParJour l : limite le nombre d'utilisations de cette effet à l fois par jour. On peut préciser un nom après l, qui va correspondre à une ressource pouvant être partagée avec d'autres attaques ou d'autres effets (voir !cof-attack). Par défaut, le nom de cette ressource est effet. Attention, il faut un lanceur auquel appliquer la limite par jour !
    • +
    • --limiteParCombat : même effet que la limite par jour. Si aucun argument n'est donné, la limite est de une fois par combat. Attention, il faut un lanceur auquel appliquer la limite par combat !
    • +
    • --tempsRecharge effet duree : l'action n'est possible que si l'effet est inactif sur le personnage qui génère l'effet, et de plus active l'effet sur celui-ci pour la durée indiquée. Il existe un effet temporaire générique, rechargeGen(desc) que vous pouvez utiliser si aucun effet existant ne correspond.
    • +
    • --dose nom: définie une ressource nommée dose_nom, dont la valeur doit être positive. Utile par exemple pour les parchemins, les potions ou les baguettes.
    • +
    • --portee id d : impose aux cibles de l'effet d'être à moins de d mètres du token id. Si --lanceur est précisé, inutile de donner id.
    • --puissant : lance la version puissante de l'effet
    • --puissant oui : idem
    • --puissant non : lance la version non puissante (efface le dernier effet puissant)
    • -
    • --puissant duree : multiplie la dur\xE9e par 2
    • -
    • --puissant portee : multiplie la port\xE9e par 2
    • -
    • --saveParTour carac seuil : la cible peut se sortir de l'effet chaque tour gr\xE2ce \xE0 un test de carac de difficulte seuil.
    • -
    • --saveActifParTour carac seuil : la cible peut se sortir de l'effet \xE0 tour gr\xE2ce \xE0 un test de carac de difficulte seuil (utilisation dans bouton dans la liste d'actions).
    • -
    • --save carac seuil : la cible peut faire un jet pour \xE9chapper \xE0 l'effet. Si on ajoute l'argument demiDuree, alors r\xE9ussir la sauvegarde ne fait que diviser la dur\xE9e.
    • +
    • --puissant duree : multiplie la durée par 2
    • +
    • --puissant portee : multiplie la portée par 2
    • +
    • --saveParTour carac seuil : la cible peut se sortir de l'effet chaque tour grâce à un test de carac de difficulte seuil.
    • +
    • --saveActifParTour carac seuil : la cible peut se sortir de l'effet à tour grâce à un test de carac de difficulte seuil (utilisation dans bouton dans la liste d'actions).
    • +
    • --save carac seuil : la cible peut faire un jet pour échapper à l'effet. Si on ajoute l'argument demiDuree, alors réussir la sauvegarde ne fait que diviser la durée.
    • --seulementVivant : l'effet ne peut s'appliquer qu'aux personnages vivants.
    • -
    • --tempeteDeMana liste : indique des effets de temp\xEAte de mana. La liste peut contenir un nombre (pour l'effet intense), duree, rapide et portee. Si le rang du sort est sp\xE9cifi\xE9 (par l'option --rang, un message est affich\xE9e si le co\xFBt en mana est sup\xE9rieur au rang. Si la liste d'options est vide, le script affiche un menu dans le chat pour sp\xE9cifier les options de temp\xEAte de mana.
    • -
    • --magieEnArmure : indique d'appliquer les r\xE8gles pour la magie en armure pour un profil hybride. Il faut pour cela un lanceur d\xE9fini. Par defaut, va faire test l'intelligence par un jet de difficult\xE9 10 + rang + malus d'armure. Le rang est obtenu par l'option --rang. J'utilise le malus d'armure car il n'y a pas moyen de distinguer la DEF intrins\xE8que de l'armure de ses bonus de DEF d\xFBs \xE0 un bonus magique. Enfin, on peut utiliser la r\xE8gle de d\xE9pense suppl\xE9mentaire de mana \xE0 la place du jet d'INT en utilisant l'option --magieEnarmure mana. Encore une fois, je prends le malus d'armure, divis\xE9 par 3 et arrondi au sup\xE9rieur pour les r\xE8gles de mana de base.
    • -
    • --accumuleDuree n : l'effet peut \xEAtre accumul\xE9 : chaque fois qu'on applique \xE0 nouveau l'effet avec une dur\xE9e donn\xE9e, on ajoute cette dur\xE9e \xE0 la dur\xE9e courante de l'effet sur la cible. On ne peut cumuler ainsi que n instances de l'effet.
    • -
    • --valeur n : pour certains effet, permet de sp\xE9cifier une valeur qui remplace la valeur par d\xE9faut de l'effet.
    • -
    • --optionEffet opt arg1 arg2 ... : sp\xE9cifie une option \xE0 l'effet. L'option opt doit \xEAtre donn\xE9e sans le -- et sera pass\xE9e telle quelle \xE0 l'effet, par exemple pour les d\xE9g\xE2ts p\xE9riodiques. Si on a besoin de plusieurs options, il faut utiliser plusieurs fois --optionEffet.
    • -
    • --secret : le r\xE9sultat de l'effet est chuchot\xE9 au joueur qui lance la commande.
    • -
    • --fx effet : affiche l'effet sp\xE9cial entre le lanceur et ses cibles. Il est possible d'utiliser un effet que vous avez d\xE9fini vous-m\xEAme en utilisant l'option --fx custom nom, o\xF9 nom est le nom de votre effet.
    • -
    • --targetFx effet : affiche l'effet sp\xE9cial sur toutes les cibles (l'effet ne doit pas \xEAtre directionnel).
    • +
    • --tempeteDeMana liste : indique des effets de tempête de mana. La liste peut contenir un nombre (pour l'effet intense), duree, rapide et portee. Si le rang du sort est spécifié (par l'option --rang, un message est affichée si le coût en mana est supérieur au rang. Si la liste d'options est vide, le script affiche un menu dans le chat pour spécifier les options de tempête de mana.
    • +
    • --magieEnArmure : indique d'appliquer les règles pour la magie en armure pour un profil hybride. Il faut pour cela un lanceur défini. Par defaut, va faire test l'intelligence par un jet de difficulté 10 + rang + malus d'armure. Le rang est obtenu par l'option --rang. J'utilise le malus d'armure car il n'y a pas moyen de distinguer la DEF intrinsèque de l'armure de ses bonus de DEF dûs à un bonus magique. Enfin, on peut utiliser la règle de dépense supplémentaire de mana à la place du jet d'INT en utilisant l'option --magieEnarmure mana. Encore une fois, je prends le malus d'armure, divisé par 3 et arrondi au supérieur pour les règles de mana de base.
    • +
    • --accumuleDuree n : l'effet peut être accumulé : chaque fois qu'on applique à nouveau l'effet avec une durée donnée, on ajoute cette durée à la durée courante de l'effet sur la cible. On ne peut cumuler ainsi que n instances de l'effet.
    • +
    • --valeur n : pour certains effet, permet de spécifier une valeur qui remplace la valeur par défaut de l'effet.
    • +
    • --optionEffet opt arg1 arg2 ... : spécifie une option à l'effet. L'option opt doit être donnée sans le -- et sera passée telle quelle à l'effet, par exemple pour les dégâts périodiques. Si on a besoin de plusieurs options, il faut utiliser plusieurs fois --optionEffet.
    • +
    • --secret : le résultat de l'effet est chuchoté au joueur qui lance la commande.
    • +
    • --fx effet : affiche l'effet spécial entre le lanceur et ses cibles. Il est possible d'utiliser un effet que vous avez défini vous-même en utilisant l'option --fx custom nom, où nom est le nom de votre effet.
    • +
    • --targetFx effet : affiche l'effet spécial sur toutes les cibles (l'effet ne doit pas être directionnel).
    • --son son : joue le son (normalement compatible avec Roll20AM)
    • --image img : affiche l'image dans le texte d'activation de l'effet.
    • -
    • --tokenSide n : utilisable seulement pour les tokens \xE0 plusieurs faces. Dans ce cas, va changer la face du token en n (\xE0 noter que les faces sont num\xE9rot\xE9es \xE0 partir de 0). Quand l'effet se termine, le token retrouve la face qu'il avait au moment o\xF9 on avait appliqu\xE9 l'effet.
    • -
    • --type : il est possible d'associer un type \xE0 l'effet. L'utilisation la plus courante est le type poison ou maladie, qui vont permettre de tenir compte des bonus ou immunit\xE9s contre les effets de ce type.
    • -
    • --montreActions : affiche les actions du tours de la cible apr\xE8s avoir appliqu\xE9 l'effet. Utile si les actions du tours d\xE9pendent de cet effet, pour afficher une liste \xE0 jour.
    • -
    • --degainer L : le lanceur d\xE9gaine l'arme de label L.
    • +
    • --tokenSide n : utilisable seulement pour les tokens à plusieurs faces. Dans ce cas, va changer la face du token en n (à noter que les faces sont numérotées à partir de 0). Quand l'effet se termine, le token retrouve la face qu'il avait au moment où on avait appliqué l'effet.
    • +
    • --type : il est possible d'associer un type à l'effet. L'utilisation la plus courante est le type poison ou maladie, qui vont permettre de tenir compte des bonus ou immunités contre les effets de ce type.
    • +
    • --montreActions : affiche les actions du tours de la cible après avoir appliqué l'effet. Utile si les actions du tours dépendent de cet effet, pour afficher une liste à jour.
    • +
    • --degainer L : le lanceur dégaine l'arme de label L.
    -

    !cof-boire-alcool et !cof-desaouler permettent de faire varier le niveau d'\xE9bri\xE9t\xE9. Par exemple, pour tester si le niveau d'\xE9bri\xE9t\xE9 augmente apr\xE8s avoir bu un certain nombre de verres, on peut utiliser la macro !cof-boire-alcool --save CON [[10+?{Nombre de verres}]]. +

    !cof-boire-alcool et !cof-desaouler permettent de faire varier le niveau d'ébriété. Par exemple, pour tester si le niveau d'ébriété augmente après avoir bu un certain nombre de verres, on peut utiliser la macro !cof-boire-alcool --save CON [[10+?{Nombre de verres}]].

    -

    Effets retard\xE9s

    +

    Effets retardés

    -

    On peut utiliser l'effet temporaire g\xE9n\xE9rique messageRetarde(nom) pour programmer un message qui sera affich\xE9 apr\xE8s un certain nombre de tours. Au bout de ce nombre de tours, le nom est affich\xE9, ainsi que le texte de valeur (avec --valeur si besoin). La syntaxe est !cof-effet-temp messageRetarde(nom) duree --valeur message. Si vous avez besoin d'un message qui contienne des espaces, remplacez les espaces par des _.

    -

    On peut aussi d\xE9clencher un effet apr\xE8s un certain nombre de tour avec l'effet temporaire g\xE9n\xE9rique effetRetarde(effet). Apr\xE8s la dur\xE9e de l'effet retard\xE9, si effet est un \xE9tat, la cible est mise dans cet \xE9tat, si c'est un effet temporaire, on lui applique cet effet pour une dur\xE9e de 1 tour, ou si un argument --valeur a \xE9t\xE9 donn\xE9, il sera utilis\xE9 comme dur\xE9e. Enfin si ce n'est ni l'un ni l'autre, un attribut avec le nom effet sera cr\xE9\xE9, de valeur courante true, ou bien si un argument --valeur a \xE9t\xE9 donn\xE9, cette valeur sera utilis\xE9e comme valeur courante de l'attribut effet.

    +

    On peut utiliser l'effet temporaire générique messageRetarde(nom) pour programmer un message qui sera affiché après un certain nombre de tours. Au bout de ce nombre de tours, le nom est affiché, ainsi que le texte de valeur (avec --valeur si besoin). La syntaxe est !cof-effet-temp messageRetarde(nom) duree --valeur message. Si vous avez besoin d'un message qui contienne des espaces, remplacez les espaces par des _.

    +

    On peut aussi déclencher un effet après un certain nombre de tour avec l'effet temporaire générique effetRetarde(effet). Après la durée de l'effet retardé, si effet est un état, la cible est mise dans cet état, si c'est un effet temporaire, on lui applique cet effet pour une durée de 1 tour, ou si un argument --valeur a été donné, il sera utilisé comme durée. Enfin si ce n'est ni l'un ni l'autre, un attribut avec le nom effet sera créé, de valeur courante true, ou bien si un argument --valeur a été donné, cette valeur sera utilisée comme valeur courante de l'attribut effet.

    -

    Pr\xE9dicats : !cof-set-predicate

    +

    Prédicats : !cof-set-predicate

    -

    Il est possible d'ajouter ou de retirer un pr\xE9dicat avec la fonction !cof-set-predicate nom, optionellement suivi de true ou false.

    +

    Il est possible d'ajouter ou de retirer un prédicat avec la fonction !cof-set-predicate nom, optionellement suivi de true ou false.

    Autres attributs : !cof-set-attribute

    - Il est possible de changer ou cr\xE9er n'importe quel attribut avec la fonction !cof-set-attribute nom val. Optionellement, on peut sp\xE9cifier en troisi\xE8me argument une valeur maximale de l'attribut (comme dans !cof-set-attribute nom val max). Attention, \xE7a peut interragir de fa\xE7on impr\xE9vue avec le script ou la fiche, si on \xE9crit dans un attribut utilis\xE9 par la fiche. + Il est possible de changer ou créer n'importe quel attribut avec la fonction !cof-set-attribute nom val. Optionellement, on peut spécifier en troisième argument une valeur maximale de l'attribut (comme dans !cof-set-attribute nom val max). Attention, ça peut interragir de façon imprévue avec le script ou la fiche, si on écrit dans un attribut utilisé par la fiche.

    2.5 Sorts

    -

    !cof-attaque-magique @{selected|token_id} @{target|token_id} : fait un jet d'attaque magique oppos\xE9 entre le lanceur et sa cible, et dit juste si le sort est rat\xE9 ou r\xE9ussi. Options disponibles : --portee et --mana.

    -

    !cof-lancer-sort texte : le token s\xE9lectionn\xE9 lance un sort sans support particulier du script (seul un whisper est envoy\xE9 au joueur et au MJ). Options disponibles : --manapour indiquer un co\xFBt en mana et --son pour jouer un son. Pour un sort sur plusieurs cibles, utiliser l'option --lanceur @{selected|token_id}.

    -

    !cof-peur difficult\xE9 dur\xE9e : effet de peur (n\xE9cromant, dragon, etc). Tant que la peur est active, statut screaming. difficult\xE9 est la difficult\xE9 du jet de SAG.

    +

    !cof-attaque-magique @{selected|token_id} @{target|token_id} : fait un jet d'attaque magique opposé entre le lanceur et sa cible, et dit juste si le sort est raté ou réussi. Options disponibles : --portee et --mana.

    +

    !cof-lancer-sort texte : le token sélectionné lance un sort sans support particulier du script (seul un whisper est envoyé au joueur et au MJ). Options disponibles : --manapour indiquer un coût en mana et --son pour jouer un son. Pour un sort sur plusieurs cibles, utiliser l'option --lanceur @{selected|token_id}.

    +

    !cof-peur difficulté durée : effet de peur (nécromant, dragon, etc). Tant que la peur est active, statut screaming. difficulté est la difficulté du jet de SAG.

    Options :
      -
    • --resisteAvecForce : on prend le max de FOR et SAG pour r\xE9sister
    • -
    • --etourdi : la peur fait fuir ou rend \xE9tourdi
    • +
    • --resisteAvecForce : on prend le max de FOR et SAG pour résister
    • +
    • --etourdi : la peur fait fuir ou rend étourdi
    • --ralenti : la peur ralenti
    • --paralyse : la peur paralyse
    • -
    • --secoue : la peur ne donne qu'un malus de -2 aux tests. Mais un autre effet de peur de m\xEAme type fait fuir.
    • +
    • --secoue : la peur ne donne qu'un malus de -2 aux tests. Mais un autre effet de peur de même type fait fuir.
    • --effroi : la peur est passive (pas un sort)
    • -
    • --portee n : limite la port\xE9e du sort \xE0 n metres.
    • -
    • --lanceur id : le lanceur de l'effet de peur (si il y en a un). N\xE9cessaire pour la port\xE9e, par exemple.
    • -
    • --titre message : sp\xE9cifie un titre pour la fen\xEAtre affichant les jets de r\xE9sistance \xE0 la peur.
    • -
    • --immuniseSiResiste nom : la personne qui r\xE9siste \xE0 cet effet de peur est ensuite immunis\xE9 pour la journ\xE9e aux effets de peur ayant la m\xEAme option (avec le m\xEAme nom).
    • +
    • --portee n : limite la portée du sort à n metres.
    • +
    • --lanceur id : le lanceur de l'effet de peur (si il y en a un). Nécessaire pour la portée, par exemple.
    • +
    • --titre message : spécifie un titre pour la fenêtre affichant les jets de résistance à la peur.
    • +
    • --immuniseSiResiste nom : la personne qui résiste à cet effet de peur est ensuite immunisé pour la journée aux effets de peur ayant la même option (avec le même nom).
    - Noter qu'un pr\xE9dicat courage permet d'obtenir un bonus (\xE9gal \xE0 la valeur du pr\xE9dicat) au jet pour r\xE9sister \xE0 la peur. + Noter qu'un prédicat courage permet d'obtenir un bonus (égal à la valeur du prédicat) au jet pour résister à la peur.

    2.6 Consommables !cof-consommables

    -

    Cette fonction affiche une liste de consommables, avec la possibilit\xE9 de cliquer sur un \xE9l\xE9ment de la liste pour le consommer (et activer son effet) ou l'\xE9changer avec un autre personnage (via le symbole d'\xE9change).

    -

    Pour cela, la fonction utilise la liste des consommables sur la fiche (onglet "\xC9quipement"). Elle ne va afficher que les consommables qui ont un effet (d\xE9crit dans la ligne Effet sous le nom du consommable).

    +

    Cette fonction affiche une liste de consommables, avec la possibilité de cliquer sur un élément de la liste pour le consommer (et activer son effet) ou l'échanger avec un autre personnage (via le symbole d'échange).

    +

    Pour cela, la fonction utilise la liste des consommables sur la fiche (onglet "Équipement"). Elle ne va afficher que les consommables qui ont un effet (décrit dans la ligne Effet sous le nom du consommable).

    Exemple d'une liste de consommable.
    - +

    Pour l'instant, seules les commandes !cof-effet-temp, !cof-effet-combat, !cof-effet, !cof-enduire-poison, !cof-attack, !cof-lancer-sort et !cof-soin diminuent correctement le nombre de consommables.

    Attention :

      -
    • Pour la commande !cof-attack, il est vivemement recommand\xE9 de ne pas utiliser de label, mais uniquement un nom et des options si vous voulez faciliter l'\xE9change du consommable.
    • -
    • De mani\xE8re g\xE9n\xE9rale, faites attention avec les r\xE9f\xE9rences utilis\xE9 dans le consommable du personnage qui utilise le consommable.
      +
    • Pour la commande !cof-attack, il est vivemement recommandé de ne pas utiliser de label, mais uniquement un nom et des options si vous voulez faciliter l'échange du consommable.
    • +
    • De manière générale, faites attention avec les références utilisé dans le consommable du personnage qui utilise le consommable.
    -

    L'\xE9change via le symbole vous permettra de s\xE9lectionner un token destinataire qui recevra le consommable dans sa liste. Si le consommable existe d\xE9j\xE0 pour le destinataire, sa quantit\xE9 sera augment\xE9 de 1, sinon le consommable sera cr\xE9\xE9.

    +

    L'échange via le symbole vous permettra de sélectionner un token destinataire qui recevra le consommable dans sa liste. Si le consommable existe déjà pour le destinataire, sa quantité sera augmenté de 1, sinon le consommable sera créé.

    -

    Cette fonction peut-\xEAtre tr\xE8s utile pour que les PJ \xE9changent entre eux un consommable, mais aussi pour faciliter la vente d'objet entre PNJ et PJ.

    -

    Pour cette derni\xE8re, il vous suffira de pr\xE9parer un personnage avec un token qui contient, dans son \xE9quipement, les consommables \xE0 \xE9changer/vendre.

    +

    Cette fonction peut-être très utile pour que les PJ échangent entre eux un consommable, mais aussi pour faciliter la vente d'objet entre PNJ et PJ.

    +

    Pour cette dernière, il vous suffira de préparer un personnage avec un token qui contient, dans son équipement, les consommables à échanger/vendre.

    -

    2.7 D\xE9placements

    +

    2.7 Déplacements

    Retrouver un personnage

    -

    Pour centrer la vue d'un joueur sur un token particulier, on peut utiliser !cof-centrer-sur-token suivi du nom du token. G\xE9n\xE9ralement, c'est une bonne id\xE9e pour un joueur d'avoir une macro avec le nom de son token pour le retrouver facilement quand il arrive sur une nouvelle carte.

    +

    Pour centrer la vue d'un joueur sur un token particulier, on peut utiliser !cof-centrer-sur-token suivi du nom du token. Généralement, c'est une bonne idée pour un joueur d'avoir une macro avec le nom de son token pour le retrouver facilement quand il arrive sur une nouvelle carte.

    -

    Personnages immobilis\xE9s

    +

    Personnages immobilisés

    -

    Le script bloque automatiquement personnages immobilis\xE9s (paralys\xE9, \xE9tourdi, etc...). Pour permettre de d\xE9placer ces personnages vous pouvez simplement enlever le blockage (click droit sur le token, propri\xE9t\xE9s avanc\xE9es). Si vous souhaitez \xEAtre le seul \xE0 pouvoir le bouger, s\xE9lectionner le (ou les) token et cliquer sur la macro Bouger. Cela cr\xE9e un token non bloqu\xE9 associ\xE9 au personnage. Bien penser \xE0 supprimer ce token apr\xE8s utilisation.

    +

    Le script bloque automatiquement personnages immobilisés (paralysé, étourdi, etc...). Pour permettre de déplacer ces personnages vous pouvez simplement enlever le blockage (click droit sur le token, propriétés avancées). Si vous souhaitez être le seul à pouvoir le bouger, sélectionner le (ou les) token et cliquer sur la macro Bouger. Cela crée un token non bloqué associé au personnage. Bien penser à supprimer ce token après utilisation.

    Il est possible de mettre le jeu en pause (les joueurs ne peuvent plus bouger leurs tokens) en utilisant la macro ⏸. La macro change alors de nom et devient ⏵, que vous pouvez utiliser pour enlever la pause.

    Escaliers

    -

    Pour g\xE9rer les escaliers sur les cartes, vous pouvez utiliser la m\xE9thode suivante, inspir\xE9e du script Teleport : placez dans le layer "GM Info Overlay", au niveau des escaliers, des tokens qui prennent exactement la place des escaliers. Nommez ces escaliers avec un nom, suivi d'une lettre majuscule. Par exemple EscalierA.

    -

    Chaque escalier de la m\xEAme colonne doit avoir le m\xEAme nom, et diff\xE9rer seulement par la lettre finale. Ensuite, si un ensemble de tokens est sur un escalier, utilisez !cof-escalier pour t\xE9l\xE9porter les tokens \xE0 l'emplacement de l'escalier suivant dans l'ordre des lettres. Si vous utilisez l'argument haut, alors les tokens n'iront pas plus loin que le dernier \xE9tage, et avec l'argument bas, il iront dans l'ordre inverse.

    -

    Dans l'exemple pr\xE9c\xE9dent, il serait t\xE9l\xE9port\xE9 \xE0 l'emplacement du token nomm\xE9 EscalierB. Cela ne fonctionne que si les bouts de l'escalier sont sur la m\xEAme carte. \xC0 vous de choisir sir vous pr\xE9f\xE9rez r\xE9v\xE9ler cette fonctionalit\xE9 \xE0 vos joueurs, ou si vous le faites vous-m\xEAme.

    -

    La limite au nombre d'escaliers est de 12 \xE9tages, donc pas de lettre apr\xE8s L.

    -

    Il est possible d'avoir des escaliers qui m\xE8nent \xE0 d'autres cartes (ce qui fait alors changer la carte vue par le joueur). Il suffit que le nom de l'escalier commence par tmap_. Attention, \xE0 cause de limitations de Roll20, cela ne peut fonctionner que si l'image du token est dans une lirary personnelle d'un joueur : si elle vient du marketplace, il fait d'abord la copier dans sa library, puis utiliser l'image qui est dans la library pour le token.

    +

    Pour gérer les escaliers sur les cartes, vous pouvez utiliser la méthode suivante, inspirée du script Teleport : placez dans le layer "GM Info Overlay", au niveau des escaliers, des tokens qui prennent exactement la place des escaliers. Nommez ces escaliers avec un nom, suivi d'une lettre majuscule. Par exemple EscalierA.

    +

    Chaque escalier de la même colonne doit avoir le même nom, et différer seulement par la lettre finale. Ensuite, si un ensemble de tokens est sur un escalier, utilisez !cof-escalier pour téléporter les tokens à l'emplacement de l'escalier suivant dans l'ordre des lettres. Si vous utilisez l'argument haut, alors les tokens n'iront pas plus loin que le dernier étage, et avec l'argument bas, il iront dans l'ordre inverse.

    +

    Dans l'exemple précédent, il serait téléporté à l'emplacement du token nommé EscalierB. Cela ne fonctionne que si les bouts de l'escalier sont sur la même carte. À vous de choisir sir vous préférez révéler cette fonctionalité à vos joueurs, ou si vous le faites vous-même.

    +

    La limite au nombre d'escaliers est de 12 étages, donc pas de lettre après L.

    +

    Il est possible d'avoir des escaliers qui mènent à d'autres cartes (ce qui fait alors changer la carte vue par le joueur). Il suffit que le nom de l'escalier commence par tmap_. Attention, à cause de limitations de Roll20, cela ne peut fonctionner que si l'image du token est dans une lirary personnelle d'un joueur : si elle vient du marketplace, il fait d'abord la copier dans sa library, puis utiliser l'image qui est dans la library pour le token.

    Montures

    -

    Pour qu'un personnage puisse monter sur une monture, il faut que cette monture soit associ\xE9e \xE0 une fiche de personnage et qu'il poss\xE8de un pr\xE9dicat monture. La commande pour monter sur la monture est !cof-en-selle @{selected|token_id} @{target|token_id}, \xE0 lancer en s\xE9lectionnant le cavalier.

    -

    On peut ensuite bouger la monture, cela d\xE9place le cavalier. Le mieux est de lancer la commander alors que le token du cavalier est sur le token de la monture. Si on d\xE9place le cavalier, cela fait aussi bouger sa monture.

    +

    Pour qu'un personnage puisse monter sur une monture, il faut que cette monture soit associée à une fiche de personnage et qu'il possède un prédicat monture. La commande pour monter sur la monture est !cof-en-selle @{selected|token_id} @{target|token_id}, à lancer en sélectionnant le cavalier.

    +

    On peut ensuite bouger la monture, cela déplace le cavalier. Le mieux est de lancer la commander alors que le token du cavalier est sur le token de la monture. Si on déplace le cavalier, cela fait aussi bouger sa monture.

    Suivre un autre personnages

    - Le principe est le suivant : on s\xE9lectionne un token, dans les abilities qui s'affichent en haut de la map, on clique sur Suivre, puis on s\xE9lectionne le token \xE0 suivre. \xC0 partir de ce moment, le script d\xE9place le premier token \xE0 chaque fois qu'on d\xE9place le second (en tenant compte des \xE9tats qui emp\xEAchent le mouvement et des obstacles sur le layer de lumi\xE8re, si ils doivent emp\xEAcher le mouvement). On peut aussi suivre un token qui en suit un autre. Et pour arr\xEAter de suivre un token, il suffit de d\xE9placer manuellement le premier token. + Le principe est le suivant : on sélectionne un token, dans les abilities qui s'affichent en haut de la map, on clique sur Suivre, puis on sélectionne le token à suivre. À partir de ce moment, le script déplace le premier token à chaque fois qu'on déplace le second (en tenant compte des états qui empêchent le mouvement et des obstacles sur le layer de lumière, si ils doivent empêcher le mouvement). On peut aussi suivre un token qui en suit un autre. Et pour arrêter de suivre un token, il suffit de déplacer manuellement le premier token. - Ça permet donc d'avoir un familier qui suit un personnage, ou bien de faire automatiquement bouger un groupe de perosnnage dont l'ordre de marche est d\xE9termin\xE9. + Ça permet donc d'avoir un familier qui suit un personnage, ou bien de faire automatiquement bouger un groupe de perosnnage dont l'ordre de marche est déterminé.
    -

    D\xE9placer un personnage sur plusieurs cartes

    +

    Déplacer un personnage sur plusieurs cartes

    -

    Il est possible de synchroniser des tokens de m\xEAme nom (repr\xE9sentant le m\xEAme personnage) sur plusieurs cartes. Ainsi, d\xE9placer le token sur une carte d\xE9place aussi les token sur les autres cartes. Cela peut servir par exemple si tous les joueurs ne doivent pas voir la m\xEAme chose sur une carte : chaque joueur est alors sur la carte qui lui montre ce qu'il doit voir, et tous les tokens des joueurs sont synchronis\xE9s entre les cartes.

    -

    La commande pour activer la synchonisation d'un (ou plusieurs) tokens s\xE9l\xE9ctionn\xE9s est !cof-multi-cartes. Pour mettre fin \xE0 la synchronisation, on peut s\xE9lectionner ces tokens et faire !cof-multi-cartes false. Enfin, cette m\xEAme commande sans selectionner aucun token met fin \xE0 toutes les synchronisations.

    +

    Il est possible de synchroniser des tokens de même nom (représentant le même personnage) sur plusieurs cartes. Ainsi, déplacer le token sur une carte déplace aussi les token sur les autres cartes. Cela peut servir par exemple si tous les joueurs ne doivent pas voir la même chose sur une carte : chaque joueur est alors sur la carte qui lui montre ce qu'il doit voir, et tous les tokens des joueurs sont synchronisés entre les cartes.

    +

    La commande pour activer la synchonisation d'un (ou plusieurs) tokens séléctionnés est !cof-multi-cartes. Pour mettre fin à la synchronisation, on peut sélectionner ces tokens et faire !cof-multi-cartes false. Enfin, cette même commande sans selectionner aucun token met fin à toutes les synchronisations.

    -

    2.8 Lumi\xE8re

    +

    2.8 Lumière

    -

    Pour faire de la lumi\xE8re, on peut utiliser !cof-lumiere token_id portee. Cela va faire en sorte que le token fasse de la lumi\xE8re jusqu'\xE0 portee m\xE8tres. Il est possible d'avoir plusieurs sources de lumi\xE8re, et la commande est compatible avec la vision dans le noir. La commande admet un troisi\xE8me argument qui est la distance \xE0 laquelle la lumi\xE8re devient moins brillante, et un quatri\xE8me argument qui est le nom du type de lumi\xE8re (par d\xE9faut, lumiere), utilis\xE9 quand on \xE9teint les lumi\xE8res.

    -

    Pour \xE9teindre des lumi\xE8res, utiliser !cof-eteindre-lumiere en s\xE9lectionnant le ou les tokens d\xE9sir\xE9s. Il est possible de prendre un argument optionnel qui est le nom du groupe de lumi\xE8res que l'on souhaite \xE9teindre. Par exemple, on peut ainsi \xE9teindre toutes les torches et laisser les effets de lumi\xE8re magique actifs.

    -

    Pour les torches, le script propose d'automatiser la gestion en utilisant la commande !cof-torche token_id. Si le token tient une torche allum\xE9e, cela \xE9teint la torche (et propose au MJ d'indiquer combien de temps la torche est rest\xE9e allum\xE9e), et sinon, si le token poss\xE8de des torches, cela allume une torche. Le nombre de torche et leur \xE9tat est stock\xE9 dans un attribut torches, dont la valeur courante contient le nombre de torches dans l'inventaire, et la valeur max le temps restant pour la torche en cours d'utilisation (60 minutes pour une torche neuve). Si aucun attribut de ce nom n'existe, le script se contente d'allumer ou d'\xE9teindre une torche, sans g\xE9rer leur nombre.

    -

    Pour les armes qui font de la lumi\xE8re, on peut pr\xE9ciser un pr\xE9dicat eclaire dans le champ de pr\xE9dicats de l'arme. La valeur du pr\xE9dicat doit \xEAtre la distance \xE0 laquelle l'arme \xE9claire. On peut pr\xE9ciser dans un pr\xE9dicat eclaireFaible (toujours dans le champ de l'arme) le d\xE9but de la lumi\xE8re faible, si besoin. Ça peut aussi \xEAtre une fa\xE7on de g\xE9rer les torches.

    -

    Quand les personnages sont dans le brouillard, je mets la carte sans lumi\xE8re, et je s\xE9lectionne les tokens et lance la commande !cof-vision-nocturne 6 pour qu'ils voient \xE0 6 m.

    +

    Pour faire de la lumière, on peut utiliser !cof-lumiere token_id portee. Cela va faire en sorte que le token fasse de la lumière jusqu'à portee mètres. Il est possible d'avoir plusieurs sources de lumière, et la commande est compatible avec la vision dans le noir. La commande admet un troisième argument qui est la distance à laquelle la lumière devient moins brillante, et un quatrième argument qui est le nom du type de lumière (par défaut, lumiere), utilisé quand on éteint les lumières.

    +

    Pour éteindre des lumières, utiliser !cof-eteindre-lumiere en sélectionnant le ou les tokens désirés. Il est possible de prendre un argument optionnel qui est le nom du groupe de lumières que l'on souhaite éteindre. Par exemple, on peut ainsi éteindre toutes les torches et laisser les effets de lumière magique actifs.

    +

    Pour les torches, le script propose d'automatiser la gestion en utilisant la commande !cof-torche token_id. Si le token tient une torche allumée, cela éteint la torche (et propose au MJ d'indiquer combien de temps la torche est restée allumée), et sinon, si le token possède des torches, cela allume une torche. Le nombre de torche et leur état est stocké dans un attribut torches, dont la valeur courante contient le nombre de torches dans l'inventaire, et la valeur max le temps restant pour la torche en cours d'utilisation (60 minutes pour une torche neuve). Si aucun attribut de ce nom n'existe, le script se contente d'allumer ou d'éteindre une torche, sans gérer leur nombre.

    +

    Pour les armes qui font de la lumière, on peut préciser un prédicat eclaire dans le champ de prédicats de l'arme. La valeur du prédicat doit être la distance à laquelle l'arme éclaire. On peut préciser dans un prédicat eclaireFaible (toujours dans le champ de l'arme) le début de la lumière faible, si besoin. Ça peut aussi être une façon de gérer les torches.

    +

    Quand les personnages sont dans le brouillard, je mets la carte sans lumière, et je sélectionne les tokens et lance la commande !cof-vision-nocturne 6 pour qu'ils voient à 6 m.

    -

    2.9 Jet de caract\xE9ristiques

    +

    2.9 Jet de caractéristiques

    -

    !cof-jet ?{Faire un jet de |Charisme, CHA|Constitution, CON|Dext\xE9rit\xE9, DEX|Force, FOR|Intelligence, INT|Sagesse, SAG} : fait un simple jet pour la caract\xE9risique s\xE9lectionn\xE9e.

    -

    Il est aussi possible de donner en argument une difficult\xE9 au jet. Par exemple en faisant !cof-jet INT ?{difficult\xE9}.

    -

    Si on ne donne aucun argument (en dehors des options), la commande demande de pr\xE9ciser la caract\xE9ristique \xE0 tester. Pour chaque caract\xE9ristique, le script va proposer d'utiliser une des comp\xE9tences d\xE9finies sur la fiche (liste sous les capacit\xE9s). Si il existe un handout nomm\xE9 Comp\xE9tences, celui-ci sera aussi utilis\xE9 pour proposer pour chaque caract\xE9ristique un choix de comp\xE9tences \xE0 tester. Le handout doit contenir dans ses notes des lignes commen\xE7ant par une caract\xE9ristique (FOR, DEX, ...), suivi de :, puis des noms de comp\xE9tences, s\xE9par\xE9s par des blancs, des retours \xE0 la ligne, des virgules ou des /.

    +

    !cof-jet ?{Faire un jet de |Charisme, CHA|Constitution, CON|Dextérité, DEX|Force, FOR|Intelligence, INT|Sagesse, SAG} : fait un simple jet pour la caractérisique sélectionnée.

    +

    Il est aussi possible de donner en argument une difficulté au jet. Par exemple en faisant !cof-jet INT ?{difficulté}.

    +

    Si on ne donne aucun argument (en dehors des options), la commande demande de préciser la caractéristique à tester. Pour chaque caractéristique, le script va proposer d'utiliser une des compétences définies sur la fiche (liste sous les capacités). Si il existe un handout nommé Compétences, celui-ci sera aussi utilisé pour proposer pour chaque caractéristique un choix de compétences à tester. Le handout doit contenir dans ses notes des lignes commençant par une caractéristique (FOR, DEX, ...), suivi de :, puis des noms de compétences, séparés par des blancs, des retours à la ligne, des virgules ou des /.

    La fonction accepte les arguments suivants:

      -
    • --bonus pour sp\xE9cifier un bonus num\xE9rique au jet.
    • -
    • --attribut pour sp\xE9cifier un attribut dont la valeur doit \xEAtre ajout\xE9e au jet. Il est possible de sp\xE9cifier plusieurs attributs, comme par exemple --attribut perception --attribut vigilance pour un jet de vigilance.
    • -
    • --predicat pour sp\xE9cifier un pr\xE9dicat dont la valeur doit \xEAtre ajout\xE9e au jet. Il est possible de sp\xE9cifier plusieurs p\xE9dicats.
    • -
    • --nom pr\xE9cise le nom du jet \xE0 afficher. De plus, cela va aussi faire rechercher une comp\xE9tence de m\xEAme nom (sans tenir compte des majuscules) pour une fiche de PJ et un attribut ou un pr\xE9dicat pour une fiche de PNJ. Par exemple !cof-jet DEX --nom Discr\xE9tion va lancer un jet de DEX, qui sera affich\xE9 comme un jet de Discr\xE9tion, et qui va ajouter au jet le bonus d'une comp\xE9tence discr\xE9tion ou d'un \xE9ventuel pr\xE9dicat discr\xE9tion.
    • -
    • --secret : le jet n'est visible que par les personnes qui contr\xF4lent le personnage, plus le MJ. Si la personne qui a lanc\xE9 la commande est MJ, il sera le seul \xE0 voir le r\xE9sultat.
    • -
    • --competences : si la commande n'a pas d\xE9j\xE0 d'option --nom, invite l'utilisateur \xE0 choisir une comp\xE9tence parmis une liste correspondant \xE0 la caract\xE9ristique (incluant celles provenant du handout Comp\xE9tences tel que d\xE9fini plus haut).
    • -
    • --plageEchecCritique c : permet de consid\xE9rer tout jet de d\xE9 inf\xE9rieur ou \xE9gal \xE0 c comme un \xE9chec critique.
    • -
    • --succes message : affiche message en cas de succ\xE8s au jet. N'a pas d'effet si la difficult\xE9 du jet n'est pas d\xE9finie.
    • +
    • --bonus pour spécifier un bonus numérique au jet.
    • +
    • --attribut pour spécifier un attribut dont la valeur doit être ajoutée au jet. Il est possible de spécifier plusieurs attributs, comme par exemple --attribut perception --attribut vigilance pour un jet de vigilance.
    • +
    • --predicat pour spécifier un prédicat dont la valeur doit être ajoutée au jet. Il est possible de spécifier plusieurs pédicats.
    • +
    • --nom précise le nom du jet à afficher. De plus, cela va aussi faire rechercher une compétence de même nom (sans tenir compte des majuscules) pour une fiche de PJ et un attribut ou un prédicat pour une fiche de PNJ. Par exemple !cof-jet DEX --nom Discrétion va lancer un jet de DEX, qui sera affiché comme un jet de Discrétion, et qui va ajouter au jet le bonus d'une compétence discrétion ou d'un éventuel prédicat discrétion.
    • +
    • --secret : le jet n'est visible que par les personnes qui contrôlent le personnage, plus le MJ. Si la personne qui a lancé la commande est MJ, il sera le seul à voir le résultat.
    • +
    • --competences : si la commande n'a pas déjà d'option --nom, invite l'utilisateur à choisir une compétence parmis une liste correspondant à la caractéristique (incluant celles provenant du handout Compétences tel que défini plus haut).
    • +
    • --plageEchecCritique c : permet de considérer tout jet de dé inférieur ou égal à c comme un échec critique.
    • +
    • --succes message : affiche message en cas de succès au jet. N'a pas d'effet si la difficulté du jet n'est pas définie.
    -

    Si le personnage poss\xE8de un attribut num\xE9rique modificateurTests, ce modificateur sera pris en compte pour tous les tests.

    -

    Dans les options de jeu (affich\xE9s en utilisant !cof-options, dans le menu des options d'affichage, il est possible de choisir de ne faire afficher les r\xE9sultats qu'au MJ, qui peut alors en cliquant sur un bouton le montrer aux joueurs (ou pas).

    +

    Si le personnage possède un attribut numérique modificateurTests, ce modificateur sera pris en compte pour tous les tests.

    +

    Dans les options de jeu (affichés en utilisant !cof-options, dans le menu des options d'affichage, il est possible de choisir de ne faire afficher les résultats qu'au MJ, qui peut alors en cliquant sur un bouton le montrer aux joueurs (ou pas).

    -

    2.10 Anonymat et fausses identit\xE9s

    +

    2.10 Anonymat et fausses identités

    -

    La fiche de personnage propose deux noms par personnage : le nom principal (appel\xE9 simplement "nom") et un alias. Le nom principal est celui visible dans la liste des personnages de l'interface Roll20. C'est aussi celui qui est montr\xE9 quand on montre une fiche aux joueurs. La fiche propose de choisir le nom affich\xE9 lors des jets (champ "connu") : soit le nom principal, soit l'alias. Le script part toujours de l'hypoth\xE8se que c'est ce nom qui est connu des joueurs, et que le second est le "vrai" nom. Je laisse le choix au MJ de d\xE9cider lequel est quoi, car les deux m\xE9thodes ont leurs avantages et leurs inconv\xE9nients : si on choisit d'avoir l'alias en nom cach\xE9, on peut montrer la fiche aux joueurs, sans d\xE9voiler le vrai nom. En revanche, dans la liste des personnages, il peut \xEAtre plus difficile de s'y retrouver, car le MJ ne verra pas le vrai nom. Si on choisit d'avoir le vrai nom cach\xE9, tout est bien clair pour le MJ, mais il doit faire attention \xE0 ne pas montrer la fiche aux joueurs.

    +

    La fiche de personnage propose deux noms par personnage : le nom principal (appelé simplement "nom") et un alias. Le nom principal est celui visible dans la liste des personnages de l'interface Roll20. C'est aussi celui qui est montré quand on montre une fiche aux joueurs. La fiche propose de choisir le nom affiché lors des jets (champ "connu") : soit le nom principal, soit l'alias. Le script part toujours de l'hypothèse que c'est ce nom qui est connu des joueurs, et que le second est le "vrai" nom. Je laisse le choix au MJ de décider lequel est quoi, car les deux méthodes ont leurs avantages et leurs inconvénients : si on choisit d'avoir l'alias en nom caché, on peut montrer la fiche aux joueurs, sans dévoiler le vrai nom. En revanche, dans la liste des personnages, il peut être plus difficile de s'y retrouver, car le MJ ne verra pas le vrai nom. Si on choisit d'avoir le vrai nom caché, tout est bien clair pour le MJ, mais il doit faire attention à ne pas montrer la fiche aux joueurs.

    Concernant les tokens, le script suppose que vous mettez en "connu" le nom visible par les joueurs.

    -

    R\xE9v\xE9ler le vrai nom d'un personnage

    +

    Révéler le vrai nom d'un personnage

    -

    Pour r\xE9v\xE9ler le vrai nom d'un personnage au joueurs, vous pourrez utiliser !cof-reveler-nom. L'effet s'applique \xE0 tous les personnages s\xE9lectionn\xE9s (voir les m\xE9thodes de s\xE9lection). L'effet est le suivant :

    +

    Pour révéler le vrai nom d'un personnage au joueurs, vous pourrez utiliser !cof-reveler-nom. L'effet s'applique à tous les personnages sélectionnés (voir les méthodes de sélection). L'effet est le suivant :

      -
    • Si le personnage \xE9tait connu par son nom, et que l'alias \xE9tait non vide, alors on copie l'alias \xE0 la place du nom, et on efface l'alias.
    • -
    • Si le personnage \xE9tait connu par son alias, alors on le passe en connu par son nom et on efface l'alias.
    • -
    • Si on a fait un des deux changements ci-dessus, alors on change aussi les noms des tokens : si on a pass\xE9 un nom en argument \xE0 !cof-reveler-nom, alors on utilise ce nom. Sinon, on utilise le nouveau nom public. Tous les tokens li\xE9s prennent ce nom, et tous les tokens non li\xE9s gardent leur num\xE9ro et changent juste la partie avant le num\xE9ro en ce nom. On n'applique cette transformation qu'aux tokens dont les noms n'ont pas \xE9t\xE9 modifi\xE9s (par rapport au token par d\xE9faut d\xE9fini sur la fiche).
    • -
    • Et on change aussi le nom du token par d\xE9faut.
    • +
    • Si le personnage était connu par son nom, et que l'alias était non vide, alors on copie l'alias à la place du nom, et on efface l'alias.
    • +
    • Si le personnage était connu par son alias, alors on le passe en connu par son nom et on efface l'alias.
    • +
    • Si on a fait un des deux changements ci-dessus, alors on change aussi les noms des tokens : si on a passé un nom en argument à !cof-reveler-nom, alors on utilise ce nom. Sinon, on utilise le nouveau nom public. Tous les tokens liés prennent ce nom, et tous les tokens non liés gardent leur numéro et changent juste la partie avant le numéro en ce nom. On n'applique cette transformation qu'aux tokens dont les noms n'ont pas été modifiés (par rapport au token par défaut défini sur la fiche).
    • +
    • Et on change aussi le nom du token par défaut.

    2.11 Autres aspects du jeu

    Annuler une action : !cof-undo

    -

    Fait partie des fonctions que je met en macro dans la barre du MJ, \xE7a peut servir tr\xE8s souvent. Elle est d'ailleurs g\xE9n\xE9r\xE9e par la commande !cof-set-macros.

    +

    Fait partie des fonctions que je met en macro dans la barre du MJ, ça peut servir très souvent. Elle est d'ailleurs générée par la commande !cof-set-macros.

    Chance

    -

    Le script essaie de d\xE9tecter les cas o\xF9 un point de chance peut \xEAtre utile, et dans ce cas fournit un bouton (utilisable par les joueurs contr\xF4lant le perosnnage ou le GM), permettant de d\xE9penser un point de chance. Attention, pour l'instant, il n'est pas possible de faire juste un undo de la d\xE9pense de point de chnce. Le undo apr\xE8s la d\xE9pense de point de chance annule toute l'action. Il faut ensuite faire un undo par point de chance d\xE9pens\xE9.

    +

    Le script essaie de détecter les cas où un point de chance peut être utile, et dans ce cas fournit un bouton (utilisable par les joueurs contrôlant le perosnnage ou le GM), permettant de dépenser un point de chance. Attention, pour l'instant, il n'est pas possible de faire juste un undo de la dépense de point de chnce. Le undo après la dépense de point de chance annule toute l'action. Il faut ensuite faire un undo par point de chance dépensé.

    Surprise : !cof-surprise ?difficulte

    -

    Fait un test de surprise sur tous les tokens s\xE9lectionn\xE9. Si la difficult\xE9 n'est pas pr\xE9sente, ils sont automatiquement surpris. Les valeurs des comp\xE9tences vigilance et perception sont ajout\xE9s au test de sagesse.

    -

    Si vous souhaitez pr\xE9ciser que la surprise est le fait d'un personnage ou effet non vivant (pour ne pas faire b\xE9n\xE9ficier du bonus de la capacit\xE9 Radar mental), vous pouvez rajouter l'option --nonVivant.

    +

    Fait un test de surprise sur tous les tokens sélectionné. Si la difficulté n'est pas présente, ils sont automatiquement surpris. Les valeurs des compétences vigilance et perception sont ajoutés au test de sagesse.

    +

    Si vous souhaitez préciser que la surprise est le fait d'un personnage ou effet non vivant (pour ne pas faire bénéficier du bonus de la capacité Radar mental), vous pouvez rajouter l'option --nonVivant.

    Gestion de la bourse : !cof-bourse

    -

    La gestion de la bourse peut se faire sans ouvrir la fiche \xE0 l'aide de la commande !cof-bourse. Si un seul token est s\xE9lectionn\xE9 (quelle que soit la m\xE9thode de s\xE9lection), la commande affiche le montant de la bourse, avec la possibilit\xE9 de modifier directement les nombres de pi\xE8ces ou de d\xE9penser ou gagner un certain nombre de pi\xE8ces.

    -

    !cof-bourse depenser n permet de faire d\xE9penser de l'argent aux tokens s\xE9lectionn\xE9s. On peut pr\xE9ciser le type de pi\xE8ces (pc, pa, po ou pp) apr\xE8s le montant, par d\xE9faut le script utilise les pi\xE8ces d'argent. De m\xEAme, on peut utiliser !cof-bourse gagner n pour ajouter de l'argent.

    +

    La gestion de la bourse peut se faire sans ouvrir la fiche à l'aide de la commande !cof-bourse. Si un seul token est sélectionné (quelle que soit la méthode de sélection), la commande affiche le montant de la bourse, avec la possibilité de modifier directement les nombres de pièces ou de dépenser ou gagner un certain nombre de pièces.

    +

    !cof-bourse depenser n permet de faire dépenser de l'argent aux tokens sélectionnés. On peut préciser le type de pièces (pc, pa, po ou pp) après le montant, par défaut le script utilise les pièces d'argent. De même, on peut utiliser !cof-bourse gagner n pour ajouter de l'argent.

    Jouer un son

    -

    Les fonctions d'attaque peuvent jouer un son (options commen\xE7ant par --soundAttack). Une partie des actions admet aussi une option --son pour jouer un son. Finalement, il est aussi possible de simplement jouer un son en utilisant !cof-jouer-son son. Il est possible d'arr\xEAter tous les sons avec la commande !cof-jouer-son, sans argument.

    +

    Les fonctions d'attaque peuvent jouer un son (options commençant par --soundAttack). Une partie des actions admet aussi une option --son pour jouer un son. Finalement, il est aussi possible de simplement jouer un son en utilisant !cof-jouer-son son. Il est possible d'arrêter tous les sons avec la commande !cof-jouer-son, sans argument.

    -

    Le script est compatible avec Roll20AM, et si ce script est install\xE9, il fera appel \xE0 lui. Mais si il n'est pas install\xE9 (et seulement dans ce cas !), il va simplement utiliser les sons dans le jukebox.

    +

    Le script est compatible avec Roll20AM, et si ce script est installé, il fera appel à lui. Mais si il n'est pas installé (et seulement dans ce cas !), il va simplement utiliser les sons dans le jukebox.

    Changer la taille d'une page : !cof-agrandir-page

    - !cof-agrandir-carte coef permet de multiplier par coef les dimensions de tout ce qui se trouve sur la carte et le layer de la lumi\xE8re. Les tokens sont d\xE9plac\xE9s pour se retrouver \xE0 la m\xEAme position relative sur la carte. Je l'utilise pour les cartes que je trouve trop petites pour des groupes de 5-6 joueurs. + !cof-agrandir-carte coef permet de multiplier par coef les dimensions de tout ce qui se trouve sur la carte et le layer de la lumière. Les tokens sont déplacés pour se retrouver à la même position relative sur la carte. Je l'utilise pour les cartes que je trouve trop petites pour des groupes de 5-6 joueurs.

    Retarder l'affichage de la mort

    -

    Pour retarder l'affichage de la mort d'un personnage, ajoutez \xE0 ce personnage un pr\xE9dicat mortDemandeConfirmation. Ainsi, si le personnage meurt \xE0 la suite d'une attaque, les PVs finaux ne seront pas enlev\xE9s, et la croix rouge indiquant la mort ne sera pas dessin\xE9e. \xC0 la place, le MJ verra au bout de 2 secondes un bouton lui-demandant de confirmer la mort (par exemple le temps de d\xE9crire comment la mort advient).

    +

    Pour retarder l'affichage de la mort d'un personnage, ajoutez à ce personnage un prédicat mortDemandeConfirmation. Ainsi, si le personnage meurt à la suite d'une attaque, les PVs finaux ne seront pas enlevés, et la croix rouge indiquant la mort ne sera pas dessinée. À la place, le MJ verra au bout de 2 secondes un bouton lui-demandant de confirmer la mort (par exemple le temps de décrire comment la mort advient).

    -

    3. Capacit\xE9s par Classe

    +

    3. Capacités par Classe

    Arquebusier

    Voie de l'artilleur

      -
    1. M\xE9canismes : ajouter les bonus sur la fiche
    2. -
    3. Tir de semonce : utiliser le modificateur semonce aux attaques. On laisse le MJ v\xE9rifier si la derni\xE8re attaque du personnage \xE9tait bien un \xE9chec (devrait \xEAtre facile \xE0 voir dans le chat). Le plus pratique pour l'utilisation avec differentes armes, est de cr\xE9er une action Tir de barrage dans les actions du tour, avec comme code #Attaque -1 --semonce. -
    4. Tir de barrage : Utiliser l'option --tirDeBarrage. Ça multiplie les d\xE9g\xE2ts par 2, ignore la charge, et laisse un message demandant le undo si la cible d\xE9cide de ne pas bouger.
    5. -
    6. Couleuvrine : ajouter une attaque \xE0 distance, avec dans les modificateurs, poudre, limiteParCombat (ou en ligne de commande, avec l'option --limiteParCombat)
    7. -
    8. Feu nourri : faire les attaques comme pour le tirde barrage. Le script ne va pas v\xE9rifier que les cibles ne sont pas trop loin les unes des autres.
    9. +
    10. Mécanismes : ajouter les bonus sur la fiche
    11. +
    12. Tir de semonce : Ajouter une prédicat tirDeSemonce. Si vous affichez les attaques avec armes en main, cela va automatiquement proposer des tirs de semonces dans les tours suivants les attaques à distance ratées. Si vous préférez le faire à la main, utilisez le modificateur semonce aux attaques.
    13. +
    14. Tir de barrage : Utiliser l'option --tirDeBarrage. Ça multiplie les dégâts par 2, ignore la charge, et laisse un message demandant le undo si la cible décide de ne pas bouger.
    15. +
    16. Couleuvrine : ajouter une attaque à distance, avec dans les modificateurs, poudre, limiteParCombat (ou en ligne de commande, avec l'option --limiteParCombat)
    17. +
    18. Feu nourri : faire les attaques comme pour le tir de barrage. Le script ne va pas vérifier que les cibles ne sont pas trop loin les unes des autres.

    Voie des explosifs

      -
    1. Chimiste : ajoutez un pr\xE9dicat chimiste, ainsi que les comp\xE9tences de chimie et alchimie sur la fiche. Si vous utilisez la capacit\xE9 alternative Grenaille, vous pouvez soit g\xE9rer les charges de grenaille avec !cof-recharger L --grenaille, soit (si vous ne voulez pas faire g\xE9rer les charges) utiliser l'option --grenaille. Si vous utilisez la m\xEAme attaque pour plusieurs armes et que seule une partie est charg\xE9e de grenaille, il faudra aussi utiliser cette option pour utiliser l'arme charg\xE9e de grenaille.
    2. -
    3. D\xE9molition : pas de support particulier
    4. -
    5. Poudre puissante : ajuster les attaques
    6. -
    7. Pi\xE8ge explosif :
    8. -
    9. Boulet explosif : ajouter une attaque de type Arme de jet, d\xE9g\xE2ts 5d6 de type contondant (ou feu ?), port\xE9e 20, modificateurs auto, options --disque 5 --psave DEX [[12+@{selected|DEX}]]
    10. +
    11. Chimiste : ajoutez un prédicat chimiste, ainsi que les compétences de chimie et alchimie sur la fiche. Si vous utilisez la capacité alternative Grenaille, vous pouvez soit gérer les charges de grenaille avec !cof-recharger L --grenaille, soit (si vous ne voulez pas faire gérer les charges) utiliser l'option --grenaille. Si vous utilisez la même attaque pour plusieurs armes et que seule une partie est chargée de grenaille, il faudra aussi utiliser cette option pour utiliser l'arme chargée de grenaille.
    12. +
    13. Démolition : On peut noter le nombre de charges disponibles par jour dans un prédicat, par exemple nommé voieDesExplosifs. Pour poser une charge de démolition, faire !cof-poser-bombe @{selected|token_id} demolition voieDesExplosifs --limiteParJour voieDesExplosifs chargesExplosives. L'explosion a lieu automatiquement au bout de 4 tours de combat (3 pour poser, 1 pour s'éloigner). Si vous avez un son nommé Explosion dans votre liste de sons du jeu, il sera joué au moment de l'explosion.
    14. +
    15. Poudre puissante : ajouter un prédicat poudrePuissante.
    16. +
    17. Piège explosif : en supposant encore que le nombre maximum de charges par jour soit indiqué dans un prédicat voieDesExposifs, on peut poser une bombe à retardement avec !cof-poser-bombe @{selected|token_id} piege 5d6 retard ?{Nombre de round?|1|2|3|4|5|6|7|8|9|10} --limiteParJour voieDesExplosifs chargesExplosives, et pour la bombe à intrusion, !cof-poser-bombe @{selected|token_id} piege 5d6 intrusion --limiteParJour voieDesExplosifs chargesExplosives. Personnellement, j'aime bien utiliser des dégâts explosifs pour les charges (5d6!). Il est aussi possible de changer la distance d'intrusion en ajoutant le nombre de mètres après le mot clé intrusion. La détection des pièges est laissée à gérer par le MJ.
    18. +
    19. Boulet explosif : ajouter une attaque de type Arme de jet, dégâts 5d6 de type contondant (ou feu ?), portée 20, modificateurs auto, options --disque 5 --psave DEX [[12+@{selected|DEX}]] --limiteParJour 5 chargesExplosives

    Voie du champ de bataille

      -
    1. Action concert\xE9e : utiliser !cof-echange-init @{selected|token_id} @{target|token_id} n o\xF9 n peut valoir 0, 1 ou 2 selon le rang dans la voie.
    2. -
    3. \xC0 couvert : !cof-a-couvert @{selected|token_id} @{target|token_id} le target est l'alli\xE9 qui se d\xE9place avec l'arquebusier. Se s\xE9lectionner soi-m\xEAme si pas d'alli\xE9.
    4. -
    5. Combattant aguerri : se reporter \xE0 la capacit\xE9 choisie
    6. -
    7. Combat de masse : pas de support particulier, effectuer les actions suppl\xE9mentaires en fonction des situations.
    8. -
    9. Constitution h\xE9ro\xEFque : reporter le bonus sur la fiche
    10. +
    11. Action concertée : utiliser !cof-echange-init @{selected|token_id} @{target|token_id} nn peut valoir 0, 1 ou 2 selon le rang dans la voie.
    12. +
    13. À couvert : !cof-a-couvert @{selected|token_id} @{target|token_id} le target est l'allié qui se déplace avec l'arquebusier. Se sélectionner soi-même si pas d'allié.
    14. +
    15. Combattant aguerri : se reporter à la capacité choisie
    16. +
    17. Combat de masse : pas de support particulier, effectuer les actions supplémentaires en fonction des situations.
    18. +
    19. Constitution héroïque : reporter le bonus sur la fiche

    Voie du Pistolero

    1. - Plus vite que son ombre : ajouter un pr\xE9dicat plusViteQueSonOmbre. On peut associer un nombre \xE0 ce pr\xE9dicat pour modifier le bonus \xE0 l'initiative, ou bien lui donner la valeur arbalete pour activer le bonus sur les arbal\xE8tes au lieu des armes \xE0 poudre. + 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.
    2. Cadence de tir : pas de support
    3. -
    4. Tir double : utiliser l'option --tirDouble si deux tirs sur une m\xEAme cible. Si les deux armes sont diff\xE9rentes, rajouter le label de la deuxi\xE8me arme apr\xE8s l'option (si le label est l2, cela donne --tirDouble l2).
    5. -
    6. As de la g\xE2chette : utiliser l'option --asDeLaGachette pour les attaques avec des armes \xE0 poudre ou des arbal\xE8tes.
    7. -
    8. Dext\xE9rit\xE9 h\xE9ro\xEFque : reporter le bonus sur la fiche
    9. +
    10. 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).
    11. +
    12. As de la gâchette : utiliser l'option --asDeLaGachette pour les attaques avec des armes à poudre ou des arbalètes.
    13. +
    14. Dextérité héroïque : reporter le bonus sur la fiche
    -

    Voie de la pr\xE9cision

    +

    Voie de la précision

      -
    1. Joli coup ! : ajouter un pr\xE9dicat joliCoup sur la fiche.
    2. -
    3. Tir pr\xE9cis : ajouter un pr\xE9dicat tirPrecis, valeur 1 ou 2 (le bonus apport\xE9 par la capacit\xE9)
    4. -
    5. D\xE9faut dans la cuirasse : utiliser !cof-defaut-dans-la-cuirasse @{selected|token_id} @{target|token_id}
    6. -
    7. Tir parabolique : ajouter un pr\xE9dicat tirParabolique. Surtout ne pas changer la port\xE9e des armes, pour que le script g\xE8re correctement les distances entre port\xE9ex2 et port\xE9ex3.
    8. -
    9. Tir mortel : Ajouter ?{Tir mortel ?|Oui, --avecd12crit --plus 2d6|Non,} aux attaques \xE0 distance du personnage
    10. +
    11. Joli coup ! : ajouter un prédicat joliCoup sur la fiche.
    12. +
    13. Tir précis : ajouter un prédicat tirPrecis, valeur 1 ou 2 (le bonus apporté par la capacité)
    14. +
    15. Défaut dans la cuirasse : utiliser !cof-defaut-dans-la-cuirasse @{selected|token_id} @{target|token_id}
    16. +
    17. Tir parabolique : ajouter un prédicat tirParabolique. Surtout ne pas changer la portée des armes, pour que le script gère correctement les distances entre portéex2 et portéex3.
    18. +
    19. Tir mortel : Ajouter ?{Tir mortel ?|Oui, --avecd12crit --plus 2d6|Non,} aux attaques à distance du personnage

    Barbare

    Voie de la brute

      -
    1. Argument de taille : ajouter le bonus de PV sur la fiche. Ajouter un pr\xE9dicat argumentDeTaille. Le script devrait automatiquement tenir compte de cette capacit\xE9 pour les tests de n\xE9gociation, persuasion et intimidation. Pour s'assurer que la bonne comp\xE9tence est utilis\xE9e, vous pouvez ajouter ces noms au handout de comp\xE9tence (voir la partie sur les jet de caract\xE9ristiques, le handout Comp\xE9tences) ou sur les fiches de personnages.
    2. -
    3. Tour de force : ajouter un pr\xE9dicat tourDeForce. Le script ajoutera syst\xE9matique un bouton lors de tous les tests de FOR du personnage. Au MJ de d\xE9cider s'il peut \xEAtre utilis\xE9 ou non.
    4. +
    5. Argument de taille : ajouter le bonus de PV sur la fiche. Ajouter un prédicat argumentDeTaille. Le script devrait automatiquement tenir compte de cette capacité pour les tests de négociation, persuasion et intimidation. Pour s'assurer que la bonne compétence est utilisée, vous pouvez ajouter ces noms au handout de compétence (voir la partie sur les jet de caractéristiques, le handout Compétences) ou sur les fiches de personnages.
    6. +
    7. Tour de force : ajouter un prédicat tourDeForce. Le script ajoutera systématique un bouton lors de tous les tests de FOR du personnage. Au MJ de décider s'il peut être utilisé ou non.
    8. Attaque brutale : faire l'attaque avec les options --bonusAttaque -2 --plus 1d6
    9. -
    10. Briseur d'os : ajouter un pr\xE9dicat briseurDOs. Cela va automatiquement affecter les chances de coups critique au contact.
    11. -
    12. Force h\xE9ro\xEFque : reporter sur la fiche.
    13. +
    14. Briseur d'os : ajouter un prédicat briseurDOs. Cela va automatiquement affecter les chances de coups critique au contact.
    15. +
    16. Force héroïque : reporter sur la fiche.

    Voie du pagne

      -
    1. Vigueur : ajouter les comp\xE9tences avec leurs bonus sur la fiche
    2. -
    3. Peau de pierre : ajouter un pr\xE9dicat peauDePierre. La nouvelle DEF sera calcul\xE9e automatiquement.
    4. +
    5. Vigueur : ajouter les compétences avec leurs bonus sur la fiche
    6. +
    7. Peau de pierre : ajouter un prédicat peauDePierre. La nouvelle DEF sera calculée automatiquement.
    8. Tatouages : ajouter le bonus choisi sur la fiche
    9. Peau d'acier : ajouter dans la partie RD de la fiche, 3/1
    10. -
    11. Constitution h\xE9ro\xEFque : reporter les bonus sur la fiche
    12. +
    13. Constitution héroïque : reporter les bonus sur la fiche

    Voie du pourfendeur

      -
    1. R\xE9flexes f\xE9lins : ajouter un pr\xE9dicat reflexesFelins, avec comme valeur le bonus aux saves et \xE0 l'initiative.
    2. -
    3. Charge : faire une attaque avec les options --bonusAttaque 2 --plus 1d6. Pour g\xE9rer plusieurs armes, vous pouvez utiliser la commande #Attaque -1.
    4. -
    5. Encha\xEEnement : ajouter un pr\xE9dicat enchainement.
    6. -
    7. D\xE9cha\xEEnement d'acier : !cof-attack-line @{selected|token_id} --distanceMax 10. L'attaque va \xEAtre faite avec l'arme en main, mais on peut sp\xE9cifier un label d'attaque (avant les options) et toutes les options support\xE9es par !cof-attack.
    8. +
    9. Réflexes félins : ajouter un prédicat reflexesFelins, avec comme valeur le bonus aux saves et à l'initiative.
    10. +
    11. Charge : faire une attaque avec les options --deplaceDe 5 20 --bonusAttaque 2 --plus 1d6. Pour gérer plusieurs armes, vous pouvez utiliser la commande #Attaque -1.
    12. +
    13. Enchaînement : ajouter un prédicat enchainement.
    14. +
    15. Déchaînement d'acier : !cof-attack-line @{selected|token_id} --distanceMax 10. L'attaque va être faite avec l'arme en main, mais on peut spécifier un label d'attaque (avant les options) et toutes les options supportées par !cof-attack.
    16. Attaque tourbillon : Faite une action avec le code !cof-explosion -1 --auto --disque 5 --saufAllies --limiteParCombat 1 tourbillon.

    Voie du primitif

      -
    1. Proche de la nature : ajouter le rang \xE0 une comp\xE9tence perception
    2. -
    3. Armure de vent : Ajouter un pr\xE9dicat armureDeVent avec comme valeur le rang dans la voie du primitif. Cela augmente la DEF, mais seulement lorsque le barbare ne porte pas d'armure (ne se voit pas sur le total de DEF de la fiche)
    4. -
    5. Vigilance : ajouter 5 \xE0 une comp\xE9tence vigilance et ajouter un pr\xE9dicat immuniteAuxSournoises
    6. -
    7. R\xE9sistance \xE0 la magie : ajouter un pr\xE9dicat resistanceALaMagieBarbare.
    8. -
    9. Vitalit\xE9 d\xE9bordante : faire une ability de type token action, avec le code !cof-soin ?{Nombre d'heures \xE9coul\xE9es}d6 --message gu\xE9rit \xE0 une vitesse surnaturelle
    10. +
    11. Proche de la nature : ajouter le rang à une compétence perception
    12. +
    13. Armure de vent : Ajouter un prédicat armureDeVent avec comme valeur le rang dans la voie du primitif. Cela augmente la DEF, mais seulement lorsque le barbare ne porte pas d'armure (ne se voit pas sur le total de DEF de la fiche)
    14. +
    15. Vigilance : ajouter 5 à une compétence vigilance et ajouter un prédicat immuniteAuxSournoises
    16. +
    17. Résistance à la magie : ajouter un prédicat resistanceALaMagieBarbare.
    18. +
    19. Vitalité débordante : faire une ability de type token action, avec le code !cof-soin ?{Nombre d'heures écoulées}d6 --message guérit à une vitesse surnaturelle

    Voie de la rage

    1. Cri de guerre : !cof-effet-combat criDeGuerre
    2. -
    3. D\xE9fier la mort : ajouter un pr\xE9dicat defierLaMort.
    4. -
    5. Rage du berserk : utiliser !cof-rage-du-berserk, \xE0 la fois pour entrer en rage et pour tenter d'en sortir avant la fin du combat.
    6. -
    7. M\xEAme pas mal : ajouter un pr\xE9dicat memePasMal. Le joueur doit lui-m\xEAme activer la rage ou le furie si il souhaite en profiter.
    8. -
    9. Furie du berserk : utiliser !cof-rage-du-berserk --furie pour entrer en rage et pour tenter d'en sortir avant la fin du combat. Pour sortir de la rage, l'option --furie peut \xEAtre omise.
    10. +
    11. Défier la mort : ajouter un prédicat defierLaMort.
    12. +
    13. Rage du berserk : utiliser !cof-rage-du-berserk, à la fois pour entrer en rage et pour tenter d'en sortir avant la fin du combat.
    14. +
    15. Même pas mal : ajouter un prédicat memePasMal. Le joueur doit lui-même activer la rage ou le furie si il souhaite en profiter.
    16. +
    17. Furie du berserk : utiliser !cof-rage-du-berserk --furie pour entrer en rage et pour tenter d'en sortir avant la fin du combat. Pour sortir de la rage, l'option --furie peut être omise.
    - Note: en option, il est possible de diviser par 2 la p\xE9nalit\xE9 de d\xE9fense inflig\xE9e par la Rage ou la Furie en ajoutant un pr\xE9dicat rageDuBerserkAmelioree au personnage (par exemple pour la ceinture d'Anathazer\xEFn p. 341) + Note: en option, il est possible de diviser par 2 la pénalité de défense infligée par la Rage ou la Furie en ajoutant un prédicat rageDuBerserkAmelioree au personnage (par exemple pour la ceinture d'Anathazerïn p. 341)

    Barde

    Voie de l'escrime

      -
    1. Pr\xE9cision : simplement utiliser le bon score sur la fiche.
    2. -
    3. Intelligence du combat : ajouter un pr\xE9dicat intelligenceDuCombat.
    4. -
    5. Feinte : faire une attaque avec l'option --feinte pour profiter des effets de feinte au tour suivant. Par d\xE9faut, le bonus \xE0 l'attaque suivante est de +5 (r\xE8gles de base), mais vous pouvez sp\xE9cifier un bonus diff\xE9rent (par exemple 10 pour les r\xE8gles de la bo\xEEte d'initiation) avec un pr\xE9dicat bonusFeinte (la valeur du pr\xE9dicat remplace le bonus de +5 par d\xE9faut). Il est aussi possible de changer le nombre de d\xE9s de d\xE9g\xE2t bonus en utilisant un pr\xE9dicatnbDesFeinte.
    6. -
    7. Attaque flamboyante : faire une attaque avec le modificateur attaqueFlamboyante. Le plus pratique pour l'utilisation avec diff\xE9rentes armes, est d'ajouter \xE0 la liste des actions du tour une action de titre Attaque flamboyante et de code #Attaque -1 --attaqueFlamboyante. Attention, afin de garder un int\xE9r\xEAt \xE0 la feinte quand on dispose de cette attaque, j'ai choisi de rajouter encore le mod. de charisme aux DM en cas d'attaque flamboyante suivant une feinte r\xE9ussie. Si cela ne vous convient pas, vous pouvez \xE0 la place de cette option ajouter --bonusAttaque [[@{selected|CHA}]] --plus [[@{selected|CHA}]].
    8. -
    9. Botte mortelle : ajoutez un pr\xE9dicat botteMortelle.
    10. +
    11. Précision : simplement utiliser le bon score sur la fiche.
    12. +
    13. Intelligence du combat : ajouter un prédicat intelligenceDuCombat.
    14. +
    15. Feinte : faire une attaque avec l'option --feinte pour profiter des effets de feinte au tour suivant. Par défaut, le bonus à l'attaque suivante est de +5 (règles de base), mais vous pouvez spécifier un bonus différent (par exemple 10 pour les règles de la boîte d'initiation) avec un prédicat bonusFeinte (la valeur du prédicat remplace le bonus de +5 par défaut). Il est aussi possible de changer le nombre de dés de dégât bonus en utilisant un prédicatnbDesFeinte.
    16. +
    17. Attaque flamboyante : faire une attaque avec le modificateur attaqueFlamboyante. Le plus pratique pour l'utilisation avec différentes armes, est d'ajouter à la liste des actions du tour une action de titre Attaque flamboyante et de code #Attaque -1 --attaqueFlamboyante. Attention, afin de garder un intérêt à la feinte quand on dispose de cette attaque, j'ai choisi de rajouter encore le mod. de charisme aux DM en cas d'attaque flamboyante suivant une feinte réussie. Si cela ne vous convient pas, vous pouvez à la place de cette option ajouter --bonusAttaque [[@{selected|CHA}]] --plus [[@{selected|CHA}]].
    18. +
    19. Botte mortelle : ajoutez un prédicat botteMortelle.

    Voie du musicien

      -
    1. Chant des h\xE9ros : !cof-effet-temp chantDesHeros [[5+@{selected|CHA}]] --allies. Il faut avoir d\xE9fini une \xE9quipe avec le barde.
    2. +
    3. Chant des héros : !cof-effet-temp chantDesHeros [[5+@{selected|CHA}]] --allies. Il faut avoir défini une équipe avec le barde.
    4. Attaque sonore :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, DM 1d6+CHA, de port\xE9e 10, type Sortil\xE8ge, d\xE9g\xE2ts soniques, options --mana 0 --cone --fx breath-smoke.
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, DM 1d6+CHA, de portée 10, type Sortilège, dégâts soniques, options --mana 0 --cone --fx breath-smoke.
      • Objet de sort : #Attaque Attaque sonore --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|CHA}]] --portee 10 --sortilege --sonique --cone --fx breath-smoke
    5. -
    6. Zone de silence : !cof-effet-temp zoneDeSilence [[1d6+@{selected|CHA}]] --lanceur @{selected|token_id} --portee 35 --disque @{target|token_id} 3 --mana 1. Le script ne g\xE8re pas le moment o\xF9 les cibles sortent de la zone. Si cela arrive, le MJ doit enlever \xE0 la main l'attribut zoneDeSilence cr\xE9\xE9 par le script pour le personnage concern\xE9.
    7. -
    8. Danse irr\xE9sisitible : +
    9. Zone de silence : !cof-effet-temp zoneDeSilence [[1d6+@{selected|CHA}]] --lanceur @{selected|token_id} --portee 35 --disque @{target|token_id} 3 --mana 1. Le script ne gère pas le moment où les cibles sortent de la zone. Si cela arrive, le MJ doit enlever à la main l'attribut zoneDeSilence créé par le script pour le personnage concerné.
    10. +
    11. Danse irrésisitible :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateur pasDeDmg, options --mana 2 --effet danseIrresistible [[1d4+@{selected|CHA]].
      • -
      • Objet de sort : #Attaque Danse irr\xE9sisitible --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet danseIrresistible [[1d4+@{selected|CHA]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateur pasDeDmg, options --mana 2 --effet danseIrresistible [[1d4+@{selected|CHA]].
      • +
      • Objet de sort : #Attaque Danse irrésisitible --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet danseIrresistible [[1d4+@{selected|CHA]]
    12. -
    13. Musique fascinante : !cof-lancer-sort joue une musique fascinante qui contr\xF4le toutes les cr\xE9atures de son choix de moins de [[5+@{selected|CHA}]] PV --mana 3
    14. +
    15. Musique fascinante : !cof-lancer-sort joue une musique fascinante qui contrôle toutes les créatures de son choix de moins de [[5+@{selected|CHA}]] PV --mana 3

    Voie du saltimbanque

      -
    1. Acrobate : ajouter les comp\xE9tences sur la fiche
    2. -
    3. Gr\xE2ce f\xE9line : ajouter un pr\xE9dicat graceFeline. Cela va affecter l'initiative et la DEF, mais sans se voir sur la fiche.
    4. +
    5. Acrobate : ajouter les compétences sur la fiche
    6. +
    7. Grâce féline : ajouter un prédicat graceFeline. Cela va affecter l'initiative et la DEF, mais sans se voir sur la fiche.
    8. Lanceur de couteau : faire normalement l'attaque.
    9. -
    10. Esquive acrobatique : ajouter un pr\xE9dicat esquiveAcrobatique.
    11. -
    12. Libert\xE9 d'action : ajouter un pr\xE9dicat liberteDAction.
    13. +
    14. Esquive acrobatique : ajouter un prédicat esquiveAcrobatique.
    15. +
    16. Liberté d'action : ajouter un prédicat liberteDAction.
    -

    Voie de la s\xE9duction

    +

    Voie de la séduction

      -
    1. Charmant : ajouter les comp\xE9tences sur la fiche
    2. -
    3. Dentelles et rapi\xE8re : Ajouter un pr\xE9dicat dentellesEtRapiere avec comme valeur le rang dans la voie de la s\xE9duction. Cela augmente la DEF, mais seulement lorsque le barde ne porte pas d'armure et seulement contre les attaques au contact. (ne se voit pas sur le total de DEF de la fiche)
    4. -
    5. Arme secr\xE8te : !cof-arme-secrete @{selected|token_id} @{target|token_id}
    6. +
    7. Charmant : ajouter les compétences sur la fiche
    8. +
    9. Dentelles et rapière : Ajouter un prédicat dentellesEtRapiere avec comme valeur le rang dans la voie de la séduction. Cela augmente la DEF, mais seulement lorsque le barde ne porte pas d'armure et seulement contre les attaques au contact. (ne se voit pas sur le total de DEF de la fiche)
    10. +
    11. Arme secrète : !cof-arme-secrete @{selected|token_id} @{target|token_id}
    12. Suggestion :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg, options --mana 2 --difficultePVmax --attaqueMentale --if touche --message la cible doit faire l'action sugg\xE9r\xE9e --endif.
      • -
      • Objet de sort : #Attaque Suggestion --toucher [[@{selected|ATKMAG}]] --portee 20 --pasDeDmg --difficultePVmax --sortilege --attaqueMentale --if touche --message la cible doit faire l'action sugg\xE9r\xE9e --endif
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg, options --mana 2 --difficultePVmax --attaqueMentale --if touche --message la cible doit faire l'action suggérée --endif.
      • +
      • Objet de sort : #Attaque Suggestion --toucher [[@{selected|ATKMAG}]] --portee 20 --pasDeDmg --difficultePVmax --sortilege --attaqueMentale --if touche --message la cible doit faire l'action suggérée --endif
    13. -
    14. Charisme h\xE9ro\xEFque : Reporter le bonus sur la fiche.
    15. +
    16. Charisme héroïque : Reporter le bonus sur la fiche.

    Voie du vagabond

      -
    1. Rumeurs et l\xE9gendes : ajouter les comp\xE9tences sur la fiche
    2. -
    3. Compr\xE9hension des langues : !cof-lancer-sort lance un sort de compr\xE9hension des langues. --messageMJ la compr\xE9hension des langues va durer [[1d6+@{selected|CHA}]] minutes --mana 0
    4. -
    5. D\xE9brouillard : pas de support particulier. Ajouter le bonus aux comp\xE9tences que vous souhaitez noter.
    6. -
    7. D\xE9guisement :!cof-lancer-sort lance un sort de d\xE9guisement --mana 2
    8. -
    9. Touche \xE0 tout : se reporter aux capacit\xE9s choisies
    10. +
    11. Rumeurs et légendes : ajouter les compétences sur la fiche
    12. +
    13. Compréhension des langues : !cof-lancer-sort lance un sort de compréhension des langues. --messageMJ la compréhension des langues va durer [[1d6+@{selected|CHA}]] minutes --mana 0
    14. +
    15. Débrouillard : pas de support particulier. Ajouter le bonus aux compétences que vous souhaitez noter.
    16. +
    17. Déguisement :!cof-lancer-sort lance un sort de déguisement --mana 2
    18. +
    19. Touche à tout : se reporter aux capacités choisies

    Chevalier

    Voie du cavalier

      -
    1. Fid\xE8le monture : Faire un personnage pour la monture, avec un pr\xE9dicat monture. Pour monter sur la monture, on peut utiliser une ability de type token action, avec !cof-en-selle @{selected|token_id} nom_de_la_monture. Pour en descendre, il suffit de cliquer \xE0 nouveau sur le bouton de l'ability. Si vous souhaitez \xE9viter que la monture apparaisse dans le turn tracker, vous pouvez ajouter un pr\xE9dicat aucuneActionCombat \xE0 la monture.
    2. -
    3. Cavalier \xE9m\xE9rite : Ajouter au chevalier un pr\xE9dicat cavalierEmerite:2. Pour la d\xE9fense de la monture, ajouter \xE0 cellle-ci un pr\xE9dicat defDeriveeDe de valeur le nom du chevalier (exactement tel qu'il appara\xEEt sur la fiche, il est possible que cela demande d'utiliser la syntaxe avec ::).
    4. -
    5. Monture magique : pour les soins automatiques de la nuit, ajouter un pr\xE9dicat montureMagique.
    6. +
    7. Fidèle monture : Faire un personnage pour la monture, avec un prédicat monture. Pour monter sur la monture, on peut utiliser une ability de type token action, avec !cof-en-selle @{selected|token_id} nom_de_la_monture. Pour en descendre, il suffit de cliquer à nouveau sur le bouton de l'ability. Si vous souhaitez éviter que la monture apparaisse dans le turn tracker, vous pouvez ajouter un prédicat aucuneActionCombat à la monture.
    8. +
    9. Cavalier émérite : Ajouter au chevalier un prédicat cavalierEmerite:2. Pour la défense de la monture, ajouter à cellle-ci un prédicat defDeriveeDe de valeur le nom du chevalier (exactement tel qu'il apparaît sur la fiche, il est possible que cela demande d'utiliser la syntaxe avec ::).
    10. +
    11. Monture magique : pour les soins automatiques de la nuit, ajouter un prédicat montureMagique.
    12. - Charge : pas de support pour le d\xE9placement, mais + Charge : pas de support pour le déplacement, mais
      • Pour l'attaque : utiliser --m2d20 --plus 1d6
      • -
      • Pour les cr\xE9atures sur la trajectoire, utiliser !cof-jet FOR 18, et en cas de succ\xE8s, infliger les DM.
      • +
      • Pour les créatures sur la trajectoire, utiliser !cof-jet FOR 18, et en cas de succès, infliger les DM.
    13. -
    14. Monture fantastique : Faire un personnage pour la monture, avec un pr\xE9dicat monture.
    15. +
    16. Monture fantastique : Faire un personnage pour la monture, avec un prédicat monture.

    Voie de la guerre

      @@ -1158,38 +1162,38 @@

      Voie de la guerre

    1. Encaisser un coup :
      • utiliser !cof-effet-temp encaisserUnCoup 1 pour se mettre en position
      • -
      • Le script proposera un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le chevalier est en position.
      • +
      • Le script proposera un bouton à activer en cas d'attaque réussie alors que le chevalier est en position.
    2. -
    3. Coup de bouclier : faire une attaque de bouclier, de type Arme gauche, avec le modificateur avecd12crit. Pour que cette attaque soit propos\xE9e dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un pr\xE9dicat attaqueAuBouclier de valeur le label de l'attaque.
    4. +
    5. Coup de bouclier : faire une attaque de bouclier, de type Arme gauche, avec le modificateur avecd12crit. Pour que cette attaque soit proposée dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un prédicat attaqueAuBouclier de valeur le label de l'attaque.
    6. Frappe lourde : faire l'attaque avec les options --avecd12crit --plus 2d6 --ignoreMoitieRD --seulementContact
    7. -
    8. Force h\xE9ro\xEFque : reporter les bonus sur la fiche
    9. +
    10. Force héroïque : reporter les bonus sur la fiche
    -

    Voie du h\xE9ro

    +

    Voie du héro

      -
    1. Ignorer la douleur : Ajouter un pr\xE9dicat ignorerLaDouleur. Normalement, le script affiche un bouton quand cela est utilisable, mais on peut aussi le d\xE9clencher avec !cof-ignorer-la-douleur juste apr\xE8s le coup.
    2. -
    3. Piqures d'insectes : ajouter un pr\xE9dicat piquresDInsectes, avec comme valeur le rang dans la voie.
    4. -
    5. Laissez-le-moi ! : Ajouter un pr\xE9dicat laissezLeMoi. Le bonus sera accord\xE9 contre tous les tokens ayant le statut de chef (donn\xE9s avec !cof-set-state chef true, ou alors simplement en activant le marker sur le token).
    6. -
    7. Seul contre tous : Utiliser !cof-effet-temp seulContreTous 1 pour se mettre en position. Les actions affich\xE9es en cas de riposte seront normalement une attaque avec l'arme en main si il y en a, plus les attaques naturelles coch\xE9es sur la liste d'attaque. Si \xE7a ne convient pas, vous pouvez \xE9crire une liste d'actions nomm\xE9eRipostes (voir les actions du tour).
    8. -
    9. Charisme h\xE9ro\xEFque : reporter sur la fiche.
    10. +
    11. Ignorer la douleur : Ajouter un prédicat ignorerLaDouleur. Normalement, le script affiche un bouton quand cela est utilisable, mais on peut aussi le déclencher avec !cof-ignorer-la-douleur juste après le coup.
    12. +
    13. Piqures d'insectes : ajouter un prédicat piquresDInsectes, avec comme valeur le rang dans la voie.
    14. +
    15. Laissez-le-moi ! : Ajouter un prédicat laissezLeMoi. Le bonus sera accordé contre tous les tokens ayant le statut de chef (donnés avec !cof-set-state chef true, ou alors simplement en activant le marker sur le token).
    16. +
    17. Seul contre tous : Utiliser !cof-effet-temp seulContreTous 1 pour se mettre en position. Les actions affichées en cas de riposte seront normalement une attaque avec l'arme en main si il y en a, plus les attaques naturelles cochées sur la liste d'attaque. Si ça ne convient pas, vous pouvez écrire une liste d'actions nomméeRipostes (voir les actions du tour).
    18. +
    19. Charisme héroïque : reporter sur la fiche.

    Voie du meneur d'hommes

      -
    1. Sans peur : Ajouter un pr\xE9dicat sansPeur, utilis\xE9 quand on essaiera de faire peur \xE0 un alli\xE9.
    2. -
    3. Intercepter : Ajouter un pr\xE9dicat intercepter, et un autre voieDuMeneurDHomme de valeur le rang dans la voie, s'il est diff\xE9rent de 2.
    4. -
    5. Exemplaire : !cof-exemplaire, juste apr\xE8s l'attaque rat\xE9e.
    6. +
    7. Sans peur : Ajouter un prédicat sansPeur, utilisé quand on essaiera de faire peur à un allié.
    8. +
    9. Intercepter : Ajouter un prédicat intercepter, et un autre voieDuMeneurDHomme de valeur le rang dans la voie, s'il est différent de 2.
    10. +
    11. Exemplaire : !cof-exemplaire, juste après l'attaque ratée.
    12. Ordre de bataille : pas de support
    13. Charge fantastique : !cof-charge-fantastique @{selected|token_id} --alliesEnVue --self --limiteParCombat 1

    Voie de la noblesse

      -
    1. \xC9duqu\xE9 : pas de support particulier, juste reporter les bonus sur la fiche.
    2. -
    3. Autorit\xE9 naturelle : simplement reporter sur la fiche les bonus d'init et de DEF, et ajouter la capacit\xE9 intimider.
    4. -
    5. \xC9cuyer : +
    6. Éduqué : pas de support particulier, juste reporter les bonus sur la fiche.
    7. +
    8. Autorité naturelle : simplement reporter sur la fiche les bonus d'init et de DEF, et ajouter la capacité intimider.
    9. +
    10. Écuyer :
        -
      • Pour le bonus au critique, ajouter un pr\xE9dicat ecuyer.
      • -
      • Pour les soins de nuit, ajouter \xE0 l'\xE9cuyer un pr\xE9dicat ecuyerDe, avec comme valeur le nom du chevalier (attention \xE0 utiliser la syntaxe avec :: si ce nom contient des espaces). L'\xE9cuyer pourra soigner chaque nuit le chevalier et certains alli\xE9s, mais pour qu'il soigne les alli\xE9s, il ne faut pas oublier de le mettre dans la liste de l'\xE9quipe du chevalier.
      • -
      • Si on souhaite que l'\xE9cuyer puisse soigner gratuitement la monture, il faut aussi que celle-ci ait un pr\xE9dicat montureDe, avec comme valeur le nom du chevalier.
      • +
      • Pour le bonus au critique, ajouter un prédicat ecuyer.
      • +
      • Pour les soins de nuit, ajouter à l'écuyer un prédicat ecuyerDe, avec comme valeur le nom du chevalier (attention à utiliser la syntaxe avec :: si ce nom contient des espaces). L'écuyer pourra soigner chaque nuit le chevalier et certains alliés, mais pour qu'il soigne les alliés, il ne faut pas oublier de le mettre dans la liste de l'équipe du chevalier.
      • +
      • Si on souhaite que l'écuyer puisse soigner gratuitement la monture, il faut aussi que celle-ci ait un prédicat montureDe, avec comme valeur le nom du chevalier.
    @@ -1199,52 +1203,52 @@

    Druide

    Voie des animaux

    1. Langage des animaux : pas de support particulier
    2. -
    3. Nu\xE9e d'insectes : Pas de support particulier pour les DM de zone qui d\xE9truisent la nu\xE9e (enlever l'attribut nueeDInsecte sur la cible dans ce cas). +
    4. Nuée d'insectes : Pas de support particulier pour les DM de zone qui détruisent la nuée (enlever l'attribut nueeDInsecte sur la cible dans ce cas).
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateur pasDeDmg, options --mana 0 --effet nueeDInsectes [[5+@{selected|SAG}]].
      • -
      • Objet de sort : #Attaque Nu\xE9e d'insectes --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet nueeDInsectes [[5+@{selected|SAG}]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateur pasDeDmg, options --mana 0 --effet nueeDInsectes [[5+@{selected|SAG}]].
      • +
      • Objet de sort : #Attaque Nuée d'insectes --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet nueeDInsectes [[5+@{selected|SAG}]]
    5. -
    6. Le guetteur : Si elle n'est pas d\xE9j\xE0 pr\xE9sente dans votre handout de comp\xE9tences, ajouter au druide une comp\xE9tence perception (valeur 0 pour le moment). Cr\xE9er un personnage et un token pour l'oiseau. Ajouter au druide un pr\xE9dicat guetteur de valeur le nom exact de l'oiseau (sur la fiche, attention \xE0 utiliser la symtaxe avec :: si le nom comporte des espaces). Ajouter de m\xEAme un pr\xE9dicat PVPartagesAvec de valeur le nom de l'oiseau. Ajouter aussi \xE0 l'oiseau un pr\xE9dicat PVPartagesAvec de valeur le nom du druide. Pour le faire agir en m\xEAme temps que le druide, ajoutez aussi \xE0 l'oiseau un pr\xE9dicat initiativeDeriveeDe de valeur le nom du druide. Pour l'attaque, ajouter sur la fiche une attaque de contact faisant 1d4 DM, avec dans les options --attaqueMagiqueDe nom de personnage du druide. Si vous souhaitez que le guetteur rentre en combat en m\xEAme temps que le druide, ajoutez au druide un pr\xE9dicat nomm\xE9 entrerEnCombatAvec, de valeur le nom du token de l'oiseau.
    7. -
    8. Masque du pr\xE9dateur : !cof-effet-temp masqueDuPredateur [[5+@{selected|SAG}]] --mana 2
    9. +
    10. Le guetteur : Si elle n'est pas déjà présente dans votre handout de compétences, ajouter au druide une compétence perception (valeur 0 pour le moment). Créer un personnage et un token pour l'oiseau. Ajouter au druide un prédicat guetteur de valeur le nom exact de l'oiseau (sur la fiche, attention à utiliser la symtaxe avec :: si le nom comporte des espaces). Ajouter de même un prédicat PVPartagesAvec de valeur le nom de l'oiseau. Ajouter aussi à l'oiseau un prédicat PVPartagesAvec de valeur le nom du druide. Pour le faire agir en même temps que le druide, ajoutez aussi à l'oiseau un prédicat initiativeDeriveeDe de valeur le nom du druide. Pour l'attaque, ajouter sur la fiche une attaque de contact faisant 1d4 DM, avec dans les options --attaqueMagiqueDe nom de personnage du druide. Si vous souhaitez que le guetteur rentre en combat en même temps que le druide, ajoutez au druide un prédicat nommé entrerEnCombatAvec, de valeur le nom du token de l'oiseau.
    11. +
    12. Masque du prédateur : !cof-effet-temp masqueDuPredateur [[5+@{selected|SAG}]] --mana 2
    13. Forme animale : pas d'autre support que !cof-lancer-sort se transforme en ?{Transformation en ?} --mana 3

    Voie du fauve

      -
    1. Vitesse du f\xE9lin : ajouter un pr\xE9dicat vitesseDuFelin, de valeur le rang dans la voie. Pensez \xE0 ajouter des comp\xE9tences de saut, escalade et course sur la fiche (sans les bonus !) s'ils ne sont pas d\xE9j\xE0 pr\xE9sent dans votre handout de comp\xE9tences.
    2. -
    3. Panth\xE8re : ajouter un personnage pour la panth\xE8re, qui sera contr\xF4l\xE9 par le joueur. Si vous souhaitez que la panth\xE8re rentre en combat \xE0 chaque fois que le druide entre en combat, ajoutez au druide un pr\xE9dicat nomm\xE9 entrerEnCombatAvec, de valeur le nom du token de la panth\xE8re (il peut y avoir plusieurs pr\xE9dicats avec ce nom).
    4. -
    5. Attaque bondissante : faire l'attaque avec les options --bonusAttaque 5 --plus 1d6. Les conditions d'utilisation sont \xE0 v\xE9rifier par le MJ.
    6. -
    7. Grand f\xE9lin : ajuster la fiche de la panth\xE8re, et pour le soin, utiliser !cof-soin @{selected|token_id} nom_familier ?{Montant des soins} --transfer.
    8. -
    9. Les sept vies du chat : pas de support particulier, la commande Undo peut \xEAtre utilis\xE9e pour annuler l'action qui a men\xE9 le Druide \xE0 0 PV.
    10. +
    11. Vitesse du félin : ajouter un prédicat vitesseDuFelin, de valeur le rang dans la voie. Pensez à ajouter des compétences de saut, escalade et course sur la fiche (sans les bonus !) s'ils ne sont pas déjà présent dans votre handout de compétences.
    12. +
    13. Panthère : ajouter un personnage pour la panthère, qui sera contrôlé par le joueur. Si vous souhaitez que la panthère rentre en combat à chaque fois que le druide entre en combat, ajoutez au druide un prédicat nommé entrerEnCombatAvec, de valeur le nom du token de la panthère (il peut y avoir plusieurs prédicats avec ce nom).
    14. +
    15. Attaque bondissante : faire l'attaque avec les options --si premiereAttaque --deplaceDe 5 30 saut --bonusAttaque 5 --plus 1d6.
    16. +
    17. Grand félin : ajuster la fiche de la panthère, et pour le soin, utiliser !cof-soin @{selected|token_id} nom_familier ?{Montant des soins} --transfer.
    18. +
    19. Les sept vies du chat : pas de support particulier, la commande Undo peut être utilisée pour annuler l'action qui a mené le Druide à 0 PV.

    Voie de la nature

      -
    1. Ma\xEEtre de la survie : Ajouter +2 par rang \xE0 une comp\xE9tence vigilance
    2. -
    3. Marche sylvestre : ajouter un pr\xE9dicat marcheSylvestre. Pour indiquer un terrain difficile, on peut utiliser les objets graphiques sur le layer des cartes (map en anglais). Pour cela, \xE9diter l'objet, et ajouter dans les notes pour MJ une ligne terrainDifficile. Tout le dessin est consid\xE9r\xE9 comme un terrain difficile. On peut restreindre la partie consid\xE9r\xE9e comme difficile \xE0 un disque en \xE9crivant terrainDifficile: disque n o\xF9 n est le diam\xE8tre du disque en pixels. \xC0 noter que la zone d'une prison v\xE9g\xE9tale est consid\xE9r\xE9e difficile par le script. Le druide est consid\xE9r\xE9 en terrain difficile si vous le mettez dans l'\xE9tat conditionsHostiles (pour des valeurs inf\xE9rieures \xE0 5). Alternativement, si vous n'avez pas ajout\xE9 le type de terrain vous pouvez taper !cof-effet marcheSylvestre oui quand le druide entre dans un terrain que vous consid\xE9rez difficile. Dans ce cas, faire !cof-effet marcheSylvestre non quand il sort de cette zone.
    4. -
    5. R\xE9sistant : ajouter dans la RD sur la fiche, nature:v, avec comme valeur v la RD (donc deux fois le rang dans la voie). Cette RD s'applique \xE0 toute attaque ou dommages avec l'option --nature ou --naturel. Il s'applique aussi \xE0 toute attaque venant d'un personnage avec un pr\xE9dicat animal, ou insecte ou bien avec un profil animal ou insecte, ou avec une race reconnue comme \xE9tant un animal ou un insecte. Dans ce cas, si on souhaite qu'une attaque d'une telle cr\xE9ature ne soit pas consid\xE9r\xE9e comme naturelle, on peut utiliser l'option --artificiel \xE0 l'attaque.
    6. -
    7. B\xE2ton de druide : Simplement cr\xE9er l'attaque correspondante et permettre les deux attaques en action limit\xE9e.
    8. -
    9. Constitution h\xE9ro\xEFque : reporter sur la fiche
    10. +
    11. Maître de la survie : Ajouter +2 par rang à une compétence vigilance
    12. +
    13. Marche sylvestre : ajouter un prédicat marcheSylvestre. Pour indiquer un terrain difficile, on peut utiliser les objets graphiques sur le layer des cartes (map en anglais). Pour cela, éditer l'objet, et ajouter dans les notes pour MJ une ligne terrainDifficile. Tout le dessin est considéré comme un terrain difficile. On peut restreindre la partie considérée comme difficile à un disque en écrivant terrainDifficile: disque nn est le diamètre du disque en pixels. À noter que la zone d'une prison végétale est considérée difficile par le script. Le druide est considéré en terrain difficile si vous le mettez dans l'état conditionsHostiles (pour des valeurs inférieures à 5). Alternativement, si vous n'avez pas ajouté le type de terrain vous pouvez taper !cof-effet marcheSylvestre oui quand le druide entre dans un terrain que vous considérez difficile. Dans ce cas, faire !cof-effet marcheSylvestre non quand il sort de cette zone.
    14. +
    15. Résistant : ajouter dans la RD sur la fiche, nature:v, avec comme valeur v la RD (donc deux fois le rang dans la voie). Cette RD s'applique à toute attaque ou dommages avec l'option --nature ou --naturel. Il s'applique aussi à toute attaque venant d'un personnage avec un prédicat animal, ou insecte ou bien avec un profil animal ou insecte, ou avec une race reconnue comme étant un animal ou un insecte. Dans ce cas, si on souhaite qu'une attaque d'une telle créature ne soit pas considérée comme naturelle, on peut utiliser l'option --artificiel à l'attaque.
    16. +
    17. Bâton de druide : Simplement créer l'attaque correspondante et permettre les deux attaques en action limitée.
    18. +
    19. Constitution héroïque : reporter sur la fiche

    Voie du protecteur

      -
    1. Baies magiques : Pour simplement cr\xE9er les baies, on peut utiliser !cof-creer-baies, avec \xE9ventuellement des arguments pour la d\xE9pense de mana. Si le sort ne demande pas de d\xE9pense et que le temps pass\xE9 n'est pas important, il peut \xEAtre plus simple de directement utiliser !cof-distribuer-baies avec option --allies --self ou --target pour cr\xE9er et donner des baies (en ayant s\xE9lectionn\xE9 le druide, le mieux est d'utiliser une ability). Pour consommer ensuite une baie, il faut utiliser !cof-consommables.
    2. -
    3. For\xEAt vivante : on peut mettre un effet (avec !cof-effet) foretVivanteEnnemie aux personnages affect\xE9s. Par exemple, si on veut donner l'effet aux personnages non alli\xE9s du druide, on peut faire !cof-effet foretVivanteEnnemie oui --disque @{selected|token_id} 2000 --saufAllies --mana 0. Attention, l'effet ne dispara\xEEt que si on fait un !cof-effet foretVivanteEnnemie non sur les personnages.
    4. -
    5. R\xE9g\xE9n\xE9ration : !cof-effet-temp regeneration [[@{selected|niveau} + @{selected|SAG}]] --lanceur @{selected|token_id} --target @{target|token_id} --limiteCibleParJour 1 --portee 0 --mana 1.
    6. -
    7. Forme d'arbre : !cof-effet-temp formeDArbre [[5+@{selected|SAG}]] --mana 2. J'ai choisi de donner comme pouvoir suppl\xE9mentaire \xE0 cette forme d'avoir ses propres PVs, et le druide r\xE9cup\xE8re ses PVs originaux \xE0 la fin de l'effet. La transformation est annul\xE9e aussi si l'arbre perd tous ses PVs. Le nombre de PVs par d\xE9faut est de niveau x 5, mais il peut \xEAtre modifi\xE9 en ajoutant au argument --valeur pv. Pour augmenter un peu l'int\xE9r\xEAt de ce sort, je lui fais aussi augmenter de 50% le bonus de peau d'\xE9corce. Si vous utilisez les actions \xE0 afficher \xE0 chaque tour, vous pouvez aussi cr\xE9er une liste d'actions nomm\xE9e Forme d'arbre contenant les sorts et actions possibles en forme d'arbre. Si une telle liste existe, elle va toujours afficher au moins les actions d\xE9fensive, d'attente et d'attaque sous forme d'arbre (pas besoin de cr\xE9er une attaque d\xE9di\xE9e sur la fiche). Il est possible de sp\xE9cifier une image pour le token en forme d'arbre, en utilisant le valeur d'un pr\xE9dicat tokenFormeDArbre.
    8. -
    9. Sagesse h\xE9ro\xEFque : reporter sur la fiche
    10. +
    11. Baies magiques : Pour simplement créer les baies, on peut utiliser !cof-creer-baies, avec éventuellement des arguments pour la dépense de mana. Si le sort ne demande pas de dépense et que le temps passé n'est pas important, il peut être plus simple de directement utiliser !cof-distribuer-baies avec option --allies --self ou --target pour créer et donner des baies (en ayant sélectionné le druide, le mieux est d'utiliser une ability). Pour consommer ensuite une baie, il faut utiliser !cof-consommables.
    12. +
    13. Forêt vivante : on peut mettre un effet (avec !cof-effet) foretVivanteEnnemie aux personnages affectés. Par exemple, si on veut donner l'effet aux personnages non alliés du druide, on peut faire !cof-effet foretVivanteEnnemie oui --disque @{selected|token_id} 2000 --saufAllies --mana 0. Attention, l'effet ne disparaît que si on fait un !cof-effet foretVivanteEnnemie non sur les personnages.
    14. +
    15. Régénération : !cof-effet-temp regeneration [[@{selected|niveau} + @{selected|SAG}]] --lanceur @{selected|token_id} --target @{target|token_id} --limiteCibleParJour 1 --portee 0 --mana 1.
    16. +
    17. Forme d'arbre : !cof-effet-temp formeDArbre [[5+@{selected|SAG}]] --mana 2. J'ai choisi de donner comme pouvoir supplémentaire à cette forme d'avoir ses propres PVs, et le druide récupère ses PVs originaux à la fin de l'effet. La transformation est annulée aussi si l'arbre perd tous ses PVs. Le nombre de PVs par défaut est de niveau x 5, mais il peut être modifié en ajoutant au argument --valeur pv. Pour augmenter un peu l'intérêt de ce sort, je lui fais aussi augmenter de 50% le bonus de peau d'écorce. Si vous utilisez les actions à afficher à chaque tour, vous pouvez aussi créer une liste d'actions nommée Forme d'arbre contenant les sorts et actions possibles en forme d'arbre. Si une telle liste existe, elle va toujours afficher au moins les actions défensive, d'attente et d'attaque sous forme d'arbre (pas besoin de créer une attaque dédiée sur la fiche). Il est possible de spécifier une image pour le token en forme d'arbre, en utilisant le valeur d'un prédicat tokenFormeDArbre.
    18. +
    19. Sagesse héroïque : reporter sur la fiche
    -

    Voie des v\xE9g\xE9taux

    +

    Voie des végétaux

      -
    1. Peau d'\xE9corce : !cof-effet-temp peauDEcorce [[5+@{selected|SAG}]] --mana 0. Par d\xE9faut, utilise la valeur d'un pr\xE9dicat voieDesVegetaux (qui devrait avoir comme valeur le rang dans la voie). Il est possible de choisir une autre valeur en utilisant l'option --valeur, et si aucune des deux m\xE9thodes n'est utilis\xE9e, le bonus de DEF est de 1.
    2. -
    3. Prison v\xE9g\xE9tale : !cof-effet-temp prisonVegetale [[5+@{selected|SAG}]] --saveActifParTour FOR [[10+@{selected|SAG}]] --lanceur @{selected|token_id} --disque @{target|token_id} 5 20 --saufAllies --mana 0.
    4. -
    5. Animation d'un arbre : !cof-animer-arbre @{selected|token_id} @{target|token_id} --portee 0 --mana 1. Cela implique d'avoir un token repr\xE9sentant l'arbre sur la carte. Ce que je fais, c'est de passer un token d'arbre du layer map au layer tokens, puis je laisse le joueur faire le sort. Si c'est trop compliqu\xE9, vous pouvez aussi pr\xE9parer un personnage arbre, avec les caract\xE9ristiques d\xE9crites, et le faire arriver sur la carte \xE0 la main (ne pas oublier sa RD 10/feu_hache, dans ce cas).
    6. +
    7. Peau d'écorce : !cof-effet-temp peauDEcorce [[5+@{selected|SAG}]] --mana 0. Par défaut, utilise la valeur d'un prédicat voieDesVegetaux (qui devrait avoir comme valeur le rang dans la voie). Il est possible de choisir une autre valeur en utilisant l'option --valeur, et si aucune des deux méthodes n'est utilisée, le bonus de DEF est de 1.
    8. +
    9. Prison végétale : !cof-effet-temp prisonVegetale [[5+@{selected|SAG}]] --saveActifParTour FOR [[10+@{selected|SAG}]] --lanceur @{selected|token_id} --disque @{target|token_id} 5 20 --saufAllies --mana 0.
    10. +
    11. Animation d'un arbre : !cof-animer-arbre @{selected|token_id} @{target|token_id} --portee 0 --mana 1. Cela implique d'avoir un token représentant l'arbre sur la carte. Ce que je fais, c'est de passer un token d'arbre du layer map au layer tokens, puis je laisse le joueur faire le sort. Si c'est trop compliqué, vous pouvez aussi préparer un personnage arbre, avec les caractéristiques décrites, et le faire arriver sur la carte à la main (ne pas oublier sa RD 10/feu_hache, dans ce cas).
    12. Gland de pouvoir :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateur pasDeDmg, options --mana 2 --effet statueDeBois [[2d6+@{selected|SAG}]] --valeur 10 10. \xC0 noter qu'un pr\xE9dicat immunite_petrification permet d'\xEAtre immunis\xE9 \xE0 cet effet.
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateur pasDeDmg, options --mana 2 --effet statueDeBois [[2d6+@{selected|SAG}]] --valeur 10 10. À noter qu'un prédicat immunite_petrification permet d'être immunisé à cet effet.
      • Objet de sort : #Attaque Gland de pouvoir --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --effet statueDeBois [[2d6+@{selected|SAG}]] --valeur 10 10
    13. -
    14. Porte v\xE9g\xE9tale : Pas de support au niveau du script, \xE0 part !cof-lancer-sort lance un sort de porte v\xE9g\xE9tale --mana 3.
    15. +
    16. Porte végétale : Pas de support au niveau du script, à part !cof-lancer-sort lance un sort de porte végétale --mana 3.

    Ensorceleur

    @@ -1255,225 +1259,225 @@

    Voie de l'air

  • Sous tension :
    1. !cof-effet-temp sousTension [[5+@{selected|CHA}]] --mana 0 pour lancer le sort et mettre l'ensorceleur sous tension
    2. -
    3. Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+CHA, port\xE9e 10, type Sortil\xE8ge, d\xE9g\xE2ts \xE9lectriques, options --si etat sousTension --fx beam-holy.
    4. -
    5. Pour les objets de sorts, on peut mettre l'attaque directement sous la forme #Attaque D\xE9charge \xE9lectrique --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|CHA}]] --electrique --portee 10 --sortilege --si etat sousTension --fx beam-holy
    6. +
    7. Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+CHA, portée 10, type Sortilège, dégâts électriques, options --si etat sousTension --fx beam-holy.
    8. +
    9. Pour les objets de sorts, on peut mettre l'attaque directement sous la forme #Attaque Décharge électrique --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|CHA}]] --electrique --portee 10 --sortilege --si etat sousTension --fx beam-holy
  • - Note : Il est possible de sp\xE9cifier une autre valeur pour les DM automatiques quand le lanceur est touch\xE9 en contact, en rajoutant --valeur X \xE0 la premi\xE8re ability. + Note : Il est possible de spécifier une autre valeur pour les DM automatiques quand le lanceur est touché en contact, en rajoutant --valeur X à la première ability. -
  • T\xE9l\xE9kin\xE9sie : Pas de support autre que !cof-lancer-sort lance un sort de t\xE9l\xE9kin\xE9sie --mana 1
  • +
  • Télékinésie : Pas de support autre que !cof-lancer-sort lance un sort de télékinésie --mana 1
  • Foudre :
      -
    • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, 4d6+CHA, port\xE9e 10, type Sortil\xE8ge, options --mana 2 --psave DEX [[12+@{selected|DEX}]] --ligne --fx beam-holy.
    • +
    • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, 4d6+CHA, portée 10, type Sortilège, options --mana 2 --psave DEX [[12+@{selected|DEX}]] --ligne --fx beam-holy.
    • Objet de sort : #Attaque Foudre --toucher [[@{selected|ATKMAG}]] --dm 4d6+[[@{selected|CHA}]] --portee 10 --sortilege --psave DEX [[12+@{selected|DEX}]] --ligne --fx beam-holy
  • -
  • Forme \xE9th\xE9r\xE9e : !cof-effet-temp intangible [[5 + @{selected|CHA}]] --mana 3. Pour impl\xE9mentaer des variantes, il existe aussi un effet intangibleInvisible qui cumule les \xE9tats intangible et invisible, et l'option --puissant donne la possibilit\xE9 au personnage de passer entre l'\xE9tat tangible et intangible \xE0 chaque tour, tant que dure l'effet.
  • +
  • Forme éthérée : !cof-effet-temp intangible [[5 + @{selected|CHA}]] --mana 3. Pour implémentaer des variantes, il existe aussi un effet intangibleInvisible qui cumule les états intangible et invisible, et l'option --puissant donne la possibilité au personnage de passer entre l'état tangible et intangible à chaque tour, tant que dure l'effet.
  • Voie de la divination

      -
    1. 6eme sens : ajouter le bonus en DEF divers et initiative diver, ajouter une comp\xE9tence vigilance, de valeur 2*rang (le bonus aux jet de surprise).
    2. -
    3. D\xE9tection de l'invisible : !cof-effet-temp detectionDeLInvisible [[5+@{selected|CHA}]] --mana 0.
    4. -
    5. Clairvoyance : !cof-lancer-sort peut voir et entendre \xE0 distance --mana 1
    6. -
    7. Prescience : ajouter un pr\xE9dicat prescience (on peut y associer un nombre pour avoir plus d'une prescience par tour). Si le personnage \xE9tait sur la carte au moment de lancer le combat, il se verra proposer un bouton pour utiliser sa prescience \xE0 la fin de chaque tour. Attention, en l'\xE9tat, il est impossible d'annuler l'utilisation de ce bouton. De plus, ce bouton ne fera rien si le script a \xE9t\xE9 interrompu depuis le d\xE9but du tour (interruption de la partie, red\xE9marrage du script, etc...).
    8. +
    9. 6eme sens : ajouter le bonus en DEF divers et initiative diver, ajouter une compétence vigilance, de valeur 2*rang (le bonus aux jet de surprise).
    10. +
    11. Détection de l'invisible : !cof-effet-temp detectionDeLInvisible [[5+@{selected|CHA}]] --mana 0.
    12. +
    13. Clairvoyance : !cof-lancer-sort peut voir et entendre à distance --mana 1
    14. +
    15. Prescience : ajouter un prédicat prescience (on peut y associer un nombre pour avoir plus d'une prescience par tour). Si le personnage était sur la carte au moment de lancer le combat, il se verra proposer un bouton pour utiliser sa prescience à la fin de chaque tour. Attention, en l'état, il est impossible d'annuler l'utilisation de ce bouton. De plus, ce bouton ne fera rien si le script a été interrompu depuis le début du tour (interruption de la partie, redémarrage du script, etc...).
    16. Hyperconscience : reporter sur la fiche.
    -

    Voie de l'envo\xFBteur

    +

    Voie de l'envoûteur

    1. Injonction : utiliser !cof-injonction @{selected|token_id} @{target|token_id} --portee 20 --mana 0
    2. -
    3. Sommeil : !cof-sommeil @{selected|token_id} --disque @{target|token_id} 5 20 --mana 0. Pour s\xE9lectionner le centre de la zone, on peut utiliser un personnage fictif (avec un token repr\xE9sentant une cible, par exemple) ayant 0 de max de PV.
    4. +
    5. Sommeil : !cof-sommeil @{selected|token_id} --disque @{target|token_id} 5 20 --mana 0. Pour sélectionner le centre de la zone, on peut utiliser un personnage fictif (avec un token représentant une cible, par exemple) ayant 0 de max de PV.
    6. Confusion:
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg options --mana 1 --attaqueMentale --effet confusion [[3+@{selected|CHA}]] --saveParTour SAG [[10+@{selected|CHA}]].
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg options --mana 1 --attaqueMentale --effet confusion [[3+@{selected|CHA}]] --saveParTour SAG [[10+@{selected|CHA}]].
      • Objet de sort : #Attaque Confusion --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --attaqueMentale --effet confusion [[3+@{selected|CHA}]] --saveParTour SAG [[10+@{selected|CHA}]]
    7. -
    8. Amiti\xE9: +
    9. Amitié:
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg options --mana 2 --attaqueMentale --difficultePVmax --effet charme --save SAG [[12+@{selected|CHA}]] --saveParJour SAG [[12+@{selected|CHA}]].
      • -
      • Objet de sort : #Attaque Amiti\xE9 --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --attaqueMentale --difficultePVmax --effet charme --save SAG [[12+@{selected|CHA}]] --saveParJour SAG [[12+@{selected|CHA}]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg options --mana 2 --attaqueMentale --difficultePVmax --effet charme --save SAG [[12+@{selected|CHA}]] --saveParJour SAG [[12+@{selected|CHA}]].
      • +
      • Objet de sort : #Attaque Amitié --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --attaqueMentale --difficultePVmax --effet charme --save SAG [[12+@{selected|CHA}]] --saveParJour SAG [[12+@{selected|CHA}]]
    10. Domination : utiliser !cof-attaque-magique @{selected|token_id} @{target|token_id} --portee 20 --attaqueMentale

    Voie des illusions

      -
    1. Image d\xE9cal\xE9e : !cof-effet-temp imageDecalee [[5+@{selected|CHA}]] --mana 0.
    2. +
    3. Image décalée : !cof-effet-temp imageDecalee [[5+@{selected|CHA}]] --mana 0.
    4. Mirage : pas de support autre que !cof-lancer-sort lance un sort de mirage ([[5+@{selected|CHA}]] minutes) --mana 0
    5. Imitation : pas de support autre que !cof-lancer-sort lance un sort d'imitation ([[5+@{selected|CHA}]] minutes) --mana 1
    6. -
    7. D\xE9doublement : +
    8. Dédoublement :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg options --mana 2 --effet dedoublement [[5+@{selected|CHA}]].
      • -
      • Objet de sort : #Attaque D\xE9doublement --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet dedoublement [[5+@{selected|CHA}]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg options --mana 2 --effet dedoublement [[5+@{selected|CHA}]].
      • +
      • Objet de sort : #Attaque Dédoublement --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet dedoublement [[5+@{selected|CHA}]]
    9. -
    10. Tueur fantasmagorique : !cof-tueur-fantasmagorique @{selected|token_id} @{target|token_id} --portee 20 --mana 3. Attention, j'en ai fait une interpr\xE9tation un peu personnelle : au lieu de ne pas pouvoir toucher les cibles de niveau sup\xE9rieur au lanceur, les cible de niveau sup\xE9rieur gagnent un bonus de 5 par niveau au dessus de celui du lanceur pour r\xE9sister au tueur fantasmagorique. Et ceux de niveau inf\xE9rieur un malus de 1 par niveau de diff\xE9rence. Si cette interpr\xE9tation ne vous convient pas, n'h\xE9sitez pas \xE0 me demander des changements.
    11. +
    12. Tueur fantasmagorique : !cof-tueur-fantasmagorique @{selected|token_id} @{target|token_id} --portee 20 --mana 3. Attention, j'en ai fait une interprétation un peu personnelle : au lieu de ne pas pouvoir toucher les cibles de niveau supérieur au lanceur, les cible de niveau supérieur gagnent un bonus de 5 par niveau au dessus de celui du lanceur pour résister au tueur fantasmagorique. Et ceux de niveau inférieur un malus de 1 par niveau de différence. Si cette interprétation ne vous convient pas, n'hésitez pas à me demander des changements.

    Voie de l'invocation

      -
    1. Familier : cr\xE9er un personnage (de type PNJ) pour le familier, control\xE9 par le joueur et avec un token li\xE9 ayant la capacit\xE9 de voir. +
    2. Familier : créer un personnage (de type PNJ) pour le familier, controlé par le joueur et avec un token lié ayant la capacité de voir.
        -
      • Pour le bonus en initiative, ajouter un pr\xE9dicat familier au personnage, avec comme valeur le nom du compagnon (doit \xEAtre exactement le m\xEAme que celui du token du compagnon). Cela automatise l'initiative quand le familier est pr\xE9sent.
      • -
      • Pour les points de vie partag\xE9s avec le familier, il faut mettre un pr\xE9dicat PVPartagesAvec de valeur le nom du familier (celui de la fiche, pas forc\xE9ment le m\xEAme que le token) pour le personnage, et un pr\xE9dicat similaire chez le familier, de valeur le nom du personnage. Le partage de PVs ne fonctionne pas avec des mooks, et il ne fait pas le partage de d\xE9g\xE2ts temporaires. En revanche, le script devrait g\xE9rer correctement les d\xE9g\xE2ts de zone.
      • -
      • Pour la d\xE9fense du familier, lui ajouter un pr\xE9dicat defDeriveeDe, de valeur le nom du personnage (nom complet sur la fiche, attention \xE0 bien utiliser la syntaxe avec :: si ce nom contient des espaces ou autres caract\xE8res sp\xE9ciaux).
      • -
      • L'initiative ne devrait pas \xEAtre tr\xE8s utile, mais si besoin, ajoutez un pr\xE9dicat initiativeDeriveeDe de valeur le nom du personnage. En fait, pour les familiers normaux, je pr\xE9f\xE8res m\xEAme qu'ils n'apparaissent pas sur le turn tracker, et je leur met donc un pr\xE9dicat aucuneActionCombat.
      • +
      • Pour le bonus en initiative, ajouter un prédicat familier au personnage, avec comme valeur le nom du compagnon (doit être exactement le même que celui du token du compagnon). Cela automatise l'initiative quand le familier est présent.
      • +
      • Pour les points de vie partagés avec le familier, il faut mettre un prédicat PVPartagesAvec de valeur le nom du familier (celui de la fiche, pas forcément le même que le token) pour le personnage, et un prédicat similaire chez le familier, de valeur le nom du personnage. Le partage de PVs ne fonctionne pas avec des mooks, et il ne fait pas le partage de dégâts temporaires. En revanche, le script devrait gérer correctement les dégâts de zone.
      • +
      • Pour la défense du familier, lui ajouter un prédicat defDeriveeDe, de valeur le nom du personnage (nom complet sur la fiche, attention à bien utiliser la syntaxe avec :: si ce nom contient des espaces ou autres caractères spéciaux).
      • +
      • L'initiative ne devrait pas être très utile, mais si besoin, ajoutez un prédicat initiativeDeriveeDe de valeur le nom du personnage. En fait, pour les familiers normaux, je préfères même qu'ils n'apparaissent pas sur le turn tracker, et je leur met donc un prédicat aucuneActionCombat.
    3. -
    4. Serviteur invisible : pas de support autre que !cof-lancer-sort cr\xE9e une force invisible pour ([[5+@{selected|CHA}]] minutes) --mana 0
    5. -
    6. Mur de force : !cof-mur-de-force ?{Spherique?|Oui,&#32;|Non,mur} --mana 1. Cela affiche une image d'un champ de force, mais seulement si il est sph\xE9rique. Il est possible de ne pas afficher d'image avec la commande !cof-mur-de-force noImage. Il est possible d'utiliser une autre image que l'image par d\xE9faut en utilisant la commande !cof-mur-de-force path o\xF9 path est l'adresse url d'une image de la librairie Roll20 qui repr\xE9sente un mur de force sph\xE9rique. On peut aussi changer l'image par d\xE9faut dans les options de jeu.
    7. -
    8. \xC9p\xE9e dansante : +
    9. Serviteur invisible : pas de support autre que !cof-lancer-sort crée une force invisible pour ([[5+@{selected|CHA}]] minutes) --mana 0
    10. +
    11. Mur de force : !cof-mur-de-force ?{Spherique?|Oui,&#32;|Non,mur} --mana 1. Cela affiche une image d'un champ de force, mais seulement si il est sphérique. Il est possible de ne pas afficher d'image avec la commande !cof-mur-de-force noImage. Il est possible d'utiliser une autre image que l'image par défaut en utilisant la commande !cof-mur-de-force pathpath est l'adresse url d'une image de la librairie Roll20 qui représente un mur de force sphérique. On peut aussi changer l'image par défaut dans les options de jeu.
    12. +
    13. Épée dansante :
      • !cof-effet-temp epeeDansante [[5+@{selected|CHA}]] --mana 2 pour lancer le sort
      • -
      • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+CHA, port\xE9e 20, type Sortil\xE8ge, d\xE9g\xE2ts magiques, options --si etat epeeDansante --ignoreObstacles.
      • -
      • Pour les objets de sort, on peut utiliser une action #Attaque \xC9p\xE9e dansante --toucher [[@{selected|ATKMAG}]] --dm 1d8+[[@{selected|CHA}]] --magique --portee 20 --sortilege --si etat epeeDansante --ignoreObstacles
      • +
      • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+CHA, portée 20, type Sortilège, dégâts magiques, options --si etat epeeDansante --ignoreObstacles.
      • +
      • Pour les objets de sort, on peut utiliser une action #Attaque Épée dansante --toucher [[@{selected|ATKMAG}]] --dm 1d8+[[@{selected|CHA}]] --magique --portee 20 --sortilege --si etat epeeDansante --ignoreObstacles
      - Pour une rapi\xE8re dansante, il existe aussi un effet temporaire rapiereDansante. + Pour une rapière dansante, il existe aussi un effet temporaire rapiereDansante.
    14. -
    15. Charisme h\xE9ro\xEFque : reporter sur la fiche
    16. +
    17. Charisme héroïque : reporter sur la fiche

    Forgesort

    Voie des artefacts

      -
    1. B\xE2ton de mage : simplement adapter l'attaque, avec aussi le modificateur magique. Pour l'\xE9clair d'\xE9nergie, ajoutez dans les options ?{Attaque|Normale,--magieRapide 2|\xC9clair d'\xE9nergie (L),--eclairDEnergie}. Si vous autorisez les r\xE8gles de mana pour cette attaque, remplacez par ?{Attaque|Normale,&#32;|\xC9clair d'\xE9nergie (L),--eclairDEnergie|\xC9clair d'\xE9nergie rapide, --eclairDEnergie --magieRapide|\xC9clair d'\xE9nergie puissant (L), --eclairDEnergie --tempeteDeMana 1}.
    2. -
    3. Blocage : pas de support autre que !cof-lancer-sort scelle une porte ou un coffre (+5 solidit\xE9 & RD) pour [[@{selected|INT}]] minutes --mana 0
    4. +
    5. Bâton de mage : simplement adapter l'attaque, avec aussi le modificateur magique. Pour l'éclair d'énergie, ajoutez dans les options ?{Attaque|Normale,--magieRapide 2|Éclair d'énergie (L),--eclairDEnergie}. Si vous autorisez les règles de mana pour cette attaque, remplacez par ?{Attaque|Normale,&#32;|Éclair d'énergie (L),--eclairDEnergie|Éclair d'énergie rapide, --eclairDEnergie --magieRapide|Éclair d'énergie puissant (L), --eclairDEnergie --tempeteDeMana 1}.
    6. +
    7. Blocage : pas de support autre que !cof-lancer-sort scelle une porte ou un coffre (+5 solidité & RD) pour [[@{selected|INT}]] minutes --mana 0
    8. Sac sans fond : pas de support particulier
    9. -
    10. Frappe des arcanes : le plus simple est d'utiliser la m\xEAme ligne d'attaque (disons que son label est E) que pour l'attaque d'\xE9nergie (mais si besoin, rien n'emp\xEAche d'en utiliser une autre). La commande sera alors !cof-explosion E --auto --magique --sortilege --portee 10 --etat renverse --save FOR [[10+@{selected|INT}]].
    11. +
    12. Frappe des arcanes : le plus simple est d'utiliser la même ligne d'attaque (disons que son label est E) que pour l'attaque d'énergie (mais si besoin, rien n'empêche d'en utiliser une autre). La commande sera alors !cof-explosion E --auto --magique --sortilege --portee 10 --etat renverse --save FOR [[10+@{selected|INT}]].
    13. Artefact majeur : pas de support particulier
    -

    Voie des \xE9lixirs

    -

    Pour cr\xE9er ou juste voir ses \xE9lixirs, utiliser la commande !cof-elixirs. Pour cela, il faut aussi un pr\xE9dicat voieDesElixirs avec comme valeur le rang dans la voie. Noter que la commande !cof-elixirs affiche une liste d'\xE9lixirs, et que pour effectivement cr\xE9er un \xE9lixir, il faut cliquer sur le bouton correspondant dans cette liste. Le script propose les \xE9lixirs par d\xE9faut du jeu, mais vous pouvez modifier cette liste : pour changer un \xE9lixir de rang k (k<4), ajouter un attribut de nom Elixir k, de valeur courante le nom et de valeur maximale l'effet.

    +

    Voie des élixirs

    +

    Pour créer ou juste voir ses élixirs, utiliser la commande !cof-elixirs. Pour cela, il faut aussi un prédicat voieDesElixirs avec comme valeur le rang dans la voie. Noter que la commande !cof-elixirs affiche une liste d'élixirs, et que pour effectivement créer un élixir, il faut cliquer sur le bouton correspondant dans cette liste. Le script propose les élixirs par défaut du jeu, mais vous pouvez modifier cette liste : pour changer un élixir de rang k (k<4), ajouter un attribut de nom Elixir k, de valeur courante le nom et de valeur maximale l'effet.

      -
    1. Fortifiant : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables. Si vous souhaitez avoir une potion de fortifiant ind\xE9pendament de cette Voie (par exemple achet\xE9e dans une \xE9chope), vous pouvez ajouter un consommable avec l'effet !cof-fortifiant n, o\xF9 n est le rang dans la Voie du forgesort qui a cr\xE9\xE9 la potion.
    2. -
    3. Feu gr\xE9geois : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
    4. -
    5. \xC9lixir de gu\xE9rison : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
    6. -
    7. Potion magique : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
    8. -
    9. \xC9lixirs magiques : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
    10. +
    11. Fortifiant : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables. Si vous souhaitez avoir une potion de fortifiant indépendament de cette Voie (par exemple achetée dans une échope), vous pouvez ajouter un consommable avec l'effet !cof-fortifiant n, où n est le rang dans la Voie du forgesort qui a créé la potion.
    12. +
    13. Feu grégeois : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
    14. +
    15. Élixir de guérison : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
    16. +
    17. Potion magique : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
    18. +
    19. Élixirs magiques : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
    -

    Voie du m\xE9tal

    +

    Voie du métal

      -
    1. Forgeron : Il faut un pr\xE9dicat voieDuMetal pour conna\xEEtre le rang (ou utiliser l'option --valeur). Lancer le sort avec !cof-effet-temp forgeron(L) [[5+@{selected|INT}]] o\xF9 L est le label d'une attaque. Ensuite, chaque fois que cette attaque sera utilis\xE9e, les d\xE9g\xE2ts seront ajout\xE9s. Limitations : si deux attaques utilisent la m\xEAme arme, il faut faire deux fois l'action, une pour chaque attaque.
    2. -
    3. M\xE9tal br\xFBlant : +
    4. Forgeron : Il faut un prédicat voieDuMetal pour connaître le rang (ou utiliser l'option --valeur). Lancer le sort avec !cof-effet-temp forgeron(L) [[5+@{selected|INT}]]L est le label d'une attaque. Ensuite, chaque fois que cette attaque sera utilisée, les dégâts seront ajoutés. Limitations : si deux attaques utilisent la même arme, il faut faire deux fois l'action, une pour chaque attaque.
    5. +
    6. Métal brûlant :
        -
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg options --mana 0 --effet ?{Chauffer|une arme,armeBrulante|une armure,armureBrulante} [[5+@{selected|INT}]].
      • -
      • Objet de sort : #Attaque M\xE9tal br\xFBlant --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet ?{Chauffer|une arme,armeBrulante|une armure,armureBrulante} [[5+@{selected|INT}]]
      • +
      • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg options --mana 0 --effet ?{Chauffer|une arme,armeBrulante|une armure,armureBrulante} [[5+@{selected|INT}]].
      • +
      • Objet de sort : #Attaque Métal brûlant --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet ?{Chauffer|une arme,armeBrulante|une armure,armureBrulante} [[5+@{selected|INT}]]
      - Pour mettre fin \xE0 l'effet (si la cible l\xE2che son arme ou enl\xE8ve son armure), vous pouvez utiliser la macro !cof-effet-temp ?{Se d\xE9barrasser d'une |arme,armeBrulante|armure,armureBrulante} 0 + Pour mettre fin à l'effet (si la cible lâche son arme ou enlève son armure), vous pouvez utiliser la macro !cof-effet-temp ?{Se débarrasser d'une |arme,armeBrulante|armure,armureBrulante} 0
    7. -
    8. Magn\xE9tisme : !cof-effet-temp magnetisme [[3+@{selected|INT}]] --mana 1. L'effet n'est actif que contre les attaques ayant l'option --metal. Il est possible de changer le bonus de DEF apport\xE9 avec l'option --valeur.
    9. -
    10. M\xE9tal hurlant :
    11. +
    12. Magnétisme : !cof-effet-temp magnetisme [[3+@{selected|INT}]] --mana 1. L'effet n'est actif que contre les attaques ayant l'option --metal. Il est possible de changer le bonus de DEF apporté avec l'option --valeur.
    13. +
    14. Métal hurlant :
    15. Endurer : reporter les bonus sur la fiche

    Voie du golem

      -
    1. Grosse t\xEAte : Vous pouvez ajouter un pr\xE9dicat grosseTete. Normalement, le bonus devrait d\xE9pendre des actions du forgesort. Si vous souhaitez le faire, vous pouvez ne pas mettre le pr\xE9dicat, mais juste avant un jet de force pour lequel vous pensez que la grosse t\xEAte s'applique, faire !cof-set-predicate grosseTete true (en s\xE9lectionnant le token du forgesort), puis apr\xE8s le jet faire !cof-set-predicate grosseTete false. Si vous voulez l'ajout de grosse t\xEAte par d\xE9faut, vous pouvez aussi faire l'op\xE9ration dans l'ordre inverse pour les jets pour lesquels vous pensez que le bonus ne peut pas s'appliquer.
    2. -
    3. Golem : ajouter un personnage et un token pour le golem (ne pas oublier le pr\xE9dicat nonVivant pour le golem). Pour les r\xE9parations, utiliser !cof-soin @{selected|token_id} nom_du_golem rangd6+@{selected|INT}. Bien remplacer rang par le rang dans la voie, dans cette commande. Attention, le nom du golem est celui du token repr\xE9sentant le golem, et il ne doit pas contenir de blanc.
    4. -
    5. Protecteur : !cof-interposer permet de s'interposer \xE0 la place de la cible de la derni\xE8re attaque. (Attention, pas de undo pour cette action)
    6. -
    7. Golem sup\xE9rieur : reporter les avantages sur la fiche du golem.
    8. -
    9. Intelligence h\xE9ro\xEFque : reporter sur la fiche
    10. +
    11. Grosse tête : Vous pouvez ajouter un prédicat grosseTete. Normalement, le bonus devrait dépendre des actions du forgesort. Si vous souhaitez le faire, vous pouvez ne pas mettre le prédicat, mais juste avant un jet de force pour lequel vous pensez que la grosse tête s'applique, faire !cof-set-predicate grosseTete true (en sélectionnant le token du forgesort), puis après le jet faire !cof-set-predicate grosseTete false. Si vous voulez l'ajout de grosse tête par défaut, vous pouvez aussi faire l'opération dans l'ordre inverse pour les jets pour lesquels vous pensez que le bonus ne peut pas s'appliquer.
    12. +
    13. Golem : ajouter un personnage et un token pour le golem (ne pas oublier le prédicat nonVivant pour le golem). Pour les réparations, utiliser !cof-soin @{selected|token_id} nom_du_golem rangd6+@{selected|INT}. Bien remplacer rang par le rang dans la voie, dans cette commande. Attention, le nom du golem est celui du token représentant le golem, et il ne doit pas contenir de blanc.
    14. +
    15. Protecteur : !cof-interposer permet de s'interposer à la place de la cible de la dernière attaque. (Attention, pas de undo pour cette action)
    16. +
    17. Golem supérieur : reporter les avantages sur la fiche du golem.
    18. +
    19. Intelligence héroïque : reporter sur la fiche

    Voie des runes

    -

    Ajouter un pr\xE9dicat voieDesRunes pour le personnage avec comme valeur le niveau dans la voie des Runes.

    +

    Ajouter un prédicat voieDesRunes pour le personnage avec comme valeur le niveau dans la voie des Runes.

      -
    1. Runes de d\xE9fense : Rien \xE0 faire, le pr\xE9dicat voieDesRunes est pris en compte dans le calcule de la DEF.
    2. -
    3. Rune d'\xE9nergie : La fabrication des runes de combat est g\xE9r\xE9e par la commande !cof-runes (il est fortement conseill\xE9 de cr\xE9er une ability pour le forgesort). Le script tente de d\xE9tecter quand les runes peuvent \xEAtre utilis\xE9es en combat et propose un bouton (\xE0 la mani\xE8re des points de chance). Lors de chaque nuit (utilisation de la commande !cof-nouveau-jour) toutes les runes sont retir\xE9es, mais le script va sugg\xE9rer des raccourcis au forgesort pour les restaurer facilement \xE0 tous les tokens pr\xE9sents sur la page des joueurs (par personnage, type de rune, et aussi un bouton "Tout renouveler"). Les points de mana sont automatiquement d\xE9compt\xE9s.
    4. -
    5. Rune de protection : cf. ci-dessus. Le script impl\xE9mente par d\xE9faut un maximum de dommages absorb\xE9s par la rune \xE9quivalent au rang du forgesort dans la voie des Runes multipli\xE9 par 10. Il est possible de d\xE9sactiver cette limitation via !cof-options.
    6. -
    7. Rune de puissance : cf. ci-dessus. Cr\xE9er une rune de puissance vous demandera d'indiquer en plus le num\xE9ro de l'arme sur la fiche du propri\xE9taire.
    8. -
    9. Rune de pouvoir : pas de support particulier, cr\xE9er l'objet de pouvoir appropri\xE9.
    10. +
    11. Runes de défense : Rien à faire, le prédicat voieDesRunes est pris en compte dans le calcule de la DEF.
    12. +
    13. Rune d'énergie : La fabrication des runes de combat est gérée par la commande !cof-runes (il est fortement conseillé de créer une ability pour le forgesort). Le script tente de détecter quand les runes peuvent être utilisées en combat et propose un bouton (à la manière des points de chance). Lors de chaque nuit (utilisation de la commande !cof-nouveau-jour) toutes les runes sont retirées, mais le script va suggérer des raccourcis au forgesort pour les restaurer facilement à tous les tokens présents sur la page des joueurs (par personnage, type de rune, et aussi un bouton "Tout renouveler"). Les points de mana sont automatiquement décomptés.
    14. +
    15. Rune de protection : cf. ci-dessus. Le script implémente par défaut un maximum de dommages absorbés par la rune équivalent au rang du forgesort dans la voie des Runes multiplié par 10. Il est possible de désactiver cette limitation via !cof-options.
    16. +
    17. Rune de puissance : cf. ci-dessus. Créer une rune de puissance vous demandera d'indiquer en plus le numéro de l'arme sur la fiche du propriétaire.
    18. +
    19. Rune de pouvoir : pas de support particulier, créer l'objet de pouvoir approprié.

    Guerrier

    Voie du bouclier

      -
    1. Prot\xE9ger un alli\xE9 : !cof-proteger-un-allie @{selected|token_id} @{target|token_id}. Fonctionne aussi si on remplace le target par un nom de token. Le script ne v\xE9rifie pas que le guerrier ne change pas d'alli\xE9 plus d'une fois par tour.
    2. +
    3. Protéger un allié : !cof-proteger-un-allie @{selected|token_id} @{target|token_id}. Fonctionne aussi si on remplace le target par un nom de token. Le script ne vérifie pas que le guerrier ne change pas d'allié plus d'une fois par tour.
    4. Absorber un coup :
        -
      • utiliser !cof-effet-temp absorberUnCoup 1 pour se mettre en position. Attention, \xE7a ne v\xE9rifie pas si le guerrier porte son bouclier.
      • -
      • le script propose un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le guerrier est en position.
      • +
      • utiliser !cof-effet-temp absorberUnCoup 1 pour se mettre en position. Attention, ça ne vérifie pas si le guerrier porte son bouclier.
      • +
      • le script propose un bouton à activer en cas d'attaque réussie alors que le guerrier est en position.
    5. Absorber un sort :
        -
      • utiliser !cof-effet-temp absorberUnSort 1 pour se mettre en position. Attention, \xE7a ne v\xE9rifie pas si le guerrier porte son bouclier.
      • -
      • le script propose un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le guerrier est en position.
      • +
      • utiliser !cof-effet-temp absorberUnSort 1 pour se mettre en position. Attention, ça ne vérifie pas si le guerrier porte son bouclier.
      • +
      • le script propose un bouton à activer en cas d'attaque réussie alors que le guerrier est en position.
    6. -
    7. Armure lourde : Noter l'armure sur la feuille du personnage, et ajouter un pr\xE9dicat armureLourdeGuerrier au personnage. L'annulation du critique ne se produira que si l'armure est port\xE9e et que la valeur totale du bonus de d\xE9fense sup\xE9rieure ou \xE9gale \xE0 7 (le bonus de DEF d'une armure de plaques compl\xE8te).
    8. +
    9. Armure lourde : Noter l'armure sur la feuille du personnage, et ajouter un prédicat armureLourdeGuerrier au personnage. L'annulation du critique ne se produira que si l'armure est portée et que la valeur totale du bonus de défense supérieure ou égale à 7 (le bonus de DEF d'une armure de plaques complète).

    Voie du combat

      -
    1. Vivacit\xE9 : simplement augmenter l'init sur la fiche.
    2. -
    3. D\xE9sarmer : !cof-desarmer @{selected|token_id} @{target|token_id}. On peut utiliser un troisi\xE8me argument optionnel, qui est le label d'une arme par d\xE9faut, au cas o\xF9 le guerrier n'aurait pas d'arme en main.
    4. -
    5. Double attaque : faire deux attaques, avec l'option suppl\xE9mentaire --bonusAttaque -2.
    6. -
    7. Attaque circulaire : faire les attaques normalement, ce n'est pas consid\xE9r\xE9 comme une aoe.
    8. +
    9. Vivacité : simplement augmenter l'init sur la fiche.
    10. +
    11. Désarmer : !cof-desarmer @{selected|token_id} @{target|token_id}. On peut utiliser un troisième argument optionnel, qui est le label d'une arme par défaut, au cas où le guerrier n'aurait pas d'arme en main.
    12. +
    13. Double attaque : faire deux attaques, avec l'option supplémentaire --bonusAttaque -2.
    14. +
    15. Attaque circulaire : faire les attaques normalement, ce n'est pas considéré comme une aoe.
    16. Attaque puissante : #Attaque -1 --avecd12crit --plus 2d6 --seulementContact.
    -

    Voie du ma\xEEtre d'armes

    +

    Voie du maître d'armes

      -
    1. Arme de pr\xE9dilection : il est possible de pr\xE9ciser une famille d'armes de pr\xE9dilection (un peu plus large que dans les r\xE8gles), parmis arc, arbalete, hache, epee, marteau, masse, epieu, poudre, baton et rapiere. Si cela vous convient, ajoutez un pr\xE9dicat armeDePredilection de valeur une de ces familles. Sinon, simplement ajouter le bonus sur les attaques dans la fiche.
    2. -
    3. Science du critique : pour ne pas avoir \xE0 modifier les chances de critique pour toutes les attaques, utiliser un pr\xE9dicat scienceDuCritique. Attention \xE0 ne pas faire \xE7a ET modifier les chances de critiques de l'attaque, car \xE7a s'additionne.
    4. -
    5. Sp\xE9cialisation : reporter le bonus aux DM sur la fiche.
    6. +
    7. Arme de prédilection : il est possible de préciser une famille d'armes de prédilection (un peu plus large que dans les règles), parmis arc, arbalete, hache, epee, marteau, masse, epieu, poudre, baton et rapiere. Si cela vous convient, ajoutez un prédicat armeDePredilection de valeur une de ces familles. Sinon, simplement ajouter le bonus sur les attaques dans la fiche.
    8. +
    9. Science du critique : pour ne pas avoir à modifier les chances de critique pour toutes les attaques, utiliser un prédicat scienceDuCritique. Attention à ne pas faire ça ET modifier les chances de critiques de l'attaque, car ça s'additionne.
    10. +
    11. Spécialisation : reporter le bonus aux DM sur la fiche.
    12. Attaque parfaite : utiliser les options --m2d20 --plus 1d6.
    13. -
    14. Riposte : ajouter un pr\xE9dicat riposteGuerrier. Les actions affich\xE9es en cas de riposte seront normalement une attaque avec l'arme en main, et les attaques naturelles coch\xE9es du personnage. Si cela ne convient pas, \xE9crivez une liste d'actions nomm\xE9e Ripostes.
    15. +
    16. Riposte : ajouter un prédicat riposteGuerrier. Les actions affichées en cas de riposte seront normalement une attaque avec l'arme en main, et les attaques naturelles cochées du personnage. Si cela ne convient pas, écrivez une liste d'actions nommée Ripostes.
    -

    Voie de la r\xE9sistance

    +

    Voie de la résistance

    1. Robustesse : rajouter les PV sur la fiche.
    2. Armure naturelle : rajouter la DEF sur la fiche.
    3. -
    4. Second souffle : Ajouter un pr\xE9dicat secondSouffle permet de faire appara\xEEtre un bouton pour utiliser le second souffle quand le guerrier a perdu des PVs en combat, limite le gain de PVs \xE0 ceux perdus dans le combat en cours, et utilise automatiquement la capacit\xE9 en fin de combat si elle n'a pas \xE9t\xE9 utilis\xE9e. Si cette automatisation ne vous convient pas, vous pouvez utiliser la commande !cof-soin @{selected|token_id} secondSouffle \xE0 la place. Enfin, on peut pr\xE9ciser une valeur pour ce pr\xE9dicat, pour remplacer le niveau + CON (par exemple pour un PNJ).
    5. -
    6. Dur \xE0 cuire : rajouter un pr\xE9dicat durACuire sur la fiche.
    7. -
    8. Constitution h\xE9ro\xEFque : reporter les bonus sur la fiche.
    9. +
    10. Second souffle : Ajouter un prédicat secondSouffle permet de faire apparaître un bouton pour utiliser le second souffle quand le guerrier a perdu des PVs en combat, limite le gain de PVs à ceux perdus dans le combat en cours, et utilise automatiquement la capacité en fin de combat si elle n'a pas été utilisée. Si cette automatisation ne vous convient pas, vous pouvez utiliser la commande !cof-soin @{selected|token_id} secondSouffle à la place. Enfin, on peut préciser une valeur pour ce prédicat, pour remplacer le niveau + CON (par exemple pour un PNJ).
    11. +
    12. Dur à cuire : rajouter un prédicat durACuire sur la fiche.
    13. +
    14. Constitution héroïque : reporter les bonus sur la fiche.

    Voie du soldat

      -
    1. Posture de combat : !cof-posture-de-combat bonus attr1 attr2, o\xF9 les deux attr peuvent \xEAtre soit DEF soit ATT soit DM, et le bonus est retir\xE9 au premier attribut pour \xEAtre ajout\xE9 au second. Le bonus peut \xEAtre limit\xE9 si le guerrier a un pr\xE9dicat voieDuSoldat qui indique son rang dans la voie. Exemple d'utilisation : !cof-posture-de-combat ?{Bonus} ?{Baisser|D\xE9fense,DEF|Attaque,ATT|D\xE9g\xE2ts,DM} ?{Augmenter|D\xE9fense,DEF|Attaque,ATT|D\xE9g\xE2ts,DM}. Normalement, la r\xE8gle fait d\xE9cider de sa posture au guerrier \xE0 chaque tour, mais en pratique, il en change assez rarement. Une posture de combat reste donc active jusqu'\xE0 la fin du combat ou jusqu'\xE0 ce qu'on en change (elle est neutre si on a le m\xEAme attribut \xE0 buffer et d\xE9buffer).
    2. -
    3. Combat en phalange : ajouter un pr\xE9dicat combatEnPhalange. Les bonus seront ajout\xE9s automatiquement en fonctions des alli\xE9s d\xE9finis selon cette m\xE9thode.
    4. -
    5. Prouesse : ajouter un pr\xE9dicat prouesse (on peut y associer un nombre, si on souhaite plus d'une utilisation par tour). Le script g\xE9n\xE9rera automatiquement les boutons Prouesse sur les test appropri\xE9s.
    6. -
    7. Dernier rempart : pas de support particulier, le MJ doit g\xE9rer les attaques suppl\xE9mentaires.
    8. -
    9. Force h\xE9ro\xEFque : reporter sur la fiche.
    10. +
    11. Posture de combat : !cof-posture-de-combat bonus attr1 attr2, où les deux attr peuvent être soit DEF soit ATT soit DM, et le bonus est retiré au premier attribut pour être ajouté au second. Le bonus peut être limité si le guerrier a un prédicat voieDuSoldat qui indique son rang dans la voie. Exemple d'utilisation : !cof-posture-de-combat ?{Bonus} ?{Baisser|Défense,DEF|Attaque,ATT|Dégâts,DM} ?{Augmenter|Défense,DEF|Attaque,ATT|Dégâts,DM}. Normalement, la règle fait décider de sa posture au guerrier à chaque tour, mais en pratique, il en change assez rarement. Une posture de combat reste donc active jusqu'à la fin du combat ou jusqu'à ce qu'on en change (elle est neutre si on a le même attribut à buffer et débuffer).
    12. +
    13. Combat en phalange : ajouter un prédicat combatEnPhalange. Les bonus seront ajoutés automatiquement en fonctions des alliés définis selon cette méthode.
    14. +
    15. Prouesse : ajouter un prédicat prouesse (on peut y associer un nombre, si on souhaite plus d'une utilisation par tour). Le script générera automatiquement les boutons Prouesse sur les test appropriés.
    16. +
    17. Dernier rempart : pas de support particulier, le MJ doit gérer les attaques supplémentaires.
    18. +
    19. Force héroïque : reporter sur la fiche.

    Invocateur

    Voie de la conjuration

      -
    1. Conjuration de pr\xE9dateur : !cof-conjuration-de-predateur --mana 0.
    2. -
    3. Conjuration renforc\xE9e : vous pouvez soit utiliser un pr\xE9dicat voieDeLaConjuration, de valeur le rang dans la voie, soit ajouter ce rang en premier argument de !cof-conjuration-de-predateur.
    4. -
    5. Conjuration d'arm\xE9e : !cof-conjuration-armee --limiteParJour 1 --mana 1. Le niveau de puissance de l'arm\xE9e et d\xE9termin\xE9 par la valeur d'un pr\xE9dicat voieDeLaConjuration, ou sinon par un argument optionnel qui donne les DMs inflig\xE9s par l'arm\xE9e (par exemple, !cof-conjuration-armee 2d6). L'arm\xE9e va appara\xEEtre comme un token normal, mais avec une aura de 20m de cot\xE9 qui repr\xE9sente la place qu'elle occupe. Pour les d\xE9g\xE2ts qu'elle inflige, utiliser son attaque sur toutes les cibles d\xE9sign\xE9es par l'invocateur. Pour faire dispara\xEEtre l'arm\xE9e, il suffit de la tuer (par exemple en utilisant !cof-set-state mort true). Tous les personnages dans la zone de l'arm\xE9e et qui ne sont pas alli\xE9s de l'invocateurs ont automatiquement une nouvelle action dans leur liste pour attaquer l'arm\xE9e. Cette action leur permet aussi de b\xE9n\xE9ficier d'une division des DM par 2 lorsque l'arm\xE9e les attaque.
    6. +
    7. Conjuration de prédateur : !cof-conjuration-de-predateur --mana 0.
    8. +
    9. Conjuration renforcée : vous pouvez soit utiliser un prédicat voieDeLaConjuration, de valeur le rang dans la voie, soit ajouter ce rang en premier argument de !cof-conjuration-de-predateur.
    10. +
    11. Conjuration d'armée : !cof-conjuration-armee --limiteParJour 1 --mana 1. Le niveau de puissance de l'armée et déterminé par la valeur d'un prédicat voieDeLaConjuration, ou sinon par un argument optionnel qui donne les DMs infligés par l'armée (par exemple, !cof-conjuration-armee 2d6). L'armée va apparaître comme un token normal, mais avec une aura de 20m de coté qui représente la place qu'elle occupe. Pour les dégâts qu'elle inflige, utiliser son attaque sur toutes les cibles désignées par l'invocateur. Pour faire disparaître l'armée, il suffit de la tuer (par exemple en utilisant !cof-set-state mort true). Tous les personnages dans la zone de l'armée et qui ne sont pas alliés de l'invocateurs ont automatiquement une nouvelle action dans leur liste pour attaquer l'armée. Cette action leur permet aussi de bénéficier d'une division des DM par 2 lorsque l'armée les attaque.
    -

    Voie de l'entit\xE9

    +

    Voie de l'entité

      -
    1. Invocation d'une entit\xE9 : ajouter la fiche correspondante.
    2. -
    3. Lien magique : pour l'instant, g\xE9rer \xE0 la main le transfert de d\xE9g\xE2ts.
    4. -
    5. Am\xE9lioration : ajuster la fiche de l'entit\xE9.
    6. +
    7. Invocation d'une entité : ajouter la fiche correspondante.
    8. +
    9. Lien magique : pour l'instant, gérer à la main le transfert de dégâts.
    10. +
    11. Amélioration : ajuster la fiche de l'entité.

    Voie du familier

      -
    1. Familier : cr\xE9er un token pour le familier, avec vue et control\xE9 par le joueur. Le partage des PV n'est pas g\xE9r\xE9. Pour le bonus en initiative, ajouter un pr\xE9dicat familier, avec comme valeur le nom du compagnon (doit \xEAtre exactement le m\xEAme que celui du token du compagnon). Cela automatise l'initiative quand le familier est pr\xE9sent.
    2. -
    3. R\xE9sistance : ajouter la valeur de RD sur la fiche du familier.
    4. -
    5. Sens d\xE9velopp\xE9s : ajouter un pr\xE9dicat perception de valeur 5 (ou augmenter ce pr\xE9dicat, si il existe d\xE9j\xE0), et ajouter un pr\xE9dicat visionDansLeNoir de valeur 20 (40 si le personnage dispose d\xE9j\xE0 de la vision dans le noir).
    6. +
    7. Familier : créer un token pour le familier, avec vue et controlé par le joueur. Le partage des PV n'est pas géré. Pour le bonus en initiative, ajouter un prédicat familier, avec comme valeur le nom du compagnon (doit être exactement le même que celui du token du compagnon). Cela automatise l'initiative quand le familier est présent.
    8. +
    9. Résistance : ajouter la valeur de RD sur la fiche du familier.
    10. +
    11. Sens développés : ajouter un prédicat perception de valeur 5 (ou augmenter ce prédicat, si il existe déjà), et ajouter un prédicat visionDansLeNoir de valeur 20 (40 si le personnage dispose déjà de la vision dans le noir).

    Voie des mutations

    1. Mutation offensive :
      • !cof-effet-temp mutationOffensive [[5+@{selected|CHA}]] --mana 0 pour lancer le sort
      • -
      • Ajouter une attaque sur la fiche utilisant l'attaque au contact, dommages 1d6+FOR+3, type Naturel, d\xE9g\xE2ts magiques, options --si etat mutationOffensive
      • +
      • Ajouter une attaque sur la fiche utilisant l'attaque au contact, dommages 1d6+FOR+3, type Naturel, dégâts magiques, options --si etat mutationOffensive
      • Pour un objet de sort, vous pouvez utiliser une action avec le code #Attaque Mutation offensive --toucher [[@{selected|ATKCAC}]] --dm 1d6+[[3+@{selected|FOR}]] --magique --naturel --si etat mutationOffensive
    2. -
    3. Mutation protectrice : !cof-effet ?{Mutation protectrice|Cuirasse,mutationCuirasse|\xC9cailles rouges,mutationEcaillesRouges|Fourrure violette,mutationFourrureViolette|Ou\xEFes,mutationOuies|Sang noir,mutationSangNoir} true --classeEffet mutationProtectrice --mana 0. Pour la valeur de protection de la cuirasse, vous pouvez soit utiliser un pr\xE9dicat voieDesMutations, de valeur le rang dans la voie, soit remplacer mutationCuirasse par mutationCuirasse --valeur rang. Pour enlever la mutation, le MJ peut ensuite simplement s\xE9lectionner le personnage et utiliser !cof-fin-classe-effet mutationProtectrice.
    4. -
    5. Surpuissance physique : !cof-effet ?{Surpuissance physique|Muscles hypertrophi\xE9s,mutationMusclesHypertrophies|Silhouette filiforme,mutationSilhouetteFiliforme|Silhouette massive,mutationSilhouetteMassive} true --classeEffet surpuissancePhysique --mana 1. Pour enlever la mutation, le MJ peut ensuite simplement s\xE9lectionner le personnage et utiliser !cof-fin-classe-effet surpuissancePhysique.
    6. -
    7. Adaptation motrice : pas d'autre support que !cof-lancer-sort --message se fait pousser ?{Adaptation motrice ?|Ailes|des ailes|Pattes demesur\xE9es,des pattes demesur\xE9es|Queue de poisson,une queue de poisson} --mana 2
    8. +
    9. Mutation protectrice : !cof-effet ?{Mutation protectrice|Cuirasse,mutationCuirasse|Écailles rouges,mutationEcaillesRouges|Fourrure violette,mutationFourrureViolette|Ouïes,mutationOuies|Sang noir,mutationSangNoir} true --classeEffet mutationProtectrice --mana 0. Pour la valeur de protection de la cuirasse, vous pouvez soit utiliser un prédicat voieDesMutations, de valeur le rang dans la voie, soit remplacer mutationCuirasse par mutationCuirasse --valeur rang. Pour enlever la mutation, le MJ peut ensuite simplement sélectionner le personnage et utiliser !cof-fin-classe-effet mutationProtectrice.
    10. +
    11. Surpuissance physique : !cof-effet ?{Surpuissance physique|Muscles hypertrophiés,mutationMusclesHypertrophies|Silhouette filiforme,mutationSilhouetteFiliforme|Silhouette massive,mutationSilhouetteMassive} true --classeEffet surpuissancePhysique --mana 1. Pour enlever la mutation, le MJ peut ensuite simplement sélectionner le personnage et utiliser !cof-fin-classe-effet surpuissancePhysique.
    12. +
    13. Adaptation motrice : pas d'autre support que !cof-lancer-sort --message se fait pousser ?{Adaptation motrice ?|Ailes|des ailes|Pattes demesurées,des pattes demesurées|Queue de poisson,une queue de poisson} --mana 2

    Voie des portes

    1. Raccourci : pas de support autre que !cof-lancer-sort lance un sort de Raccourci --mana 0
    2. -
    3. Porte artificielle : pas de support autre que !cof-lancer-sort lance un sort de Porte artificielle --mana 0. Un jour, je compte lui faire cr\xE9er une porte.
    4. +
    5. Porte artificielle : pas de support autre que !cof-lancer-sort lance un sort de Porte artificielle --mana 0. Un jour, je compte lui faire créer une porte.
    6. Manoir d'outre-tombe : pas d'autre support que !cof-lancer-sort enchante une porte --mana 1
    7. Enkystement lointain : !cof-enkystement-lointain @{selected|token_id} @{target|token_id} --portee 20 --mana 2 --limiteParCombat 1 enkystement.
    8. Porte dimensionnelle : pas de support pour l'instant.
    9. @@ -1483,14 +1487,14 @@

      Magicien

      Voie de la magie des arcanes

        -
      1. Agrandissement : !cof-effet-temp agrandissement [[5+@{selected|INT}]] --target @{target|token_id} --lanceur @{selected|token_id} --portee 0 --mana 0. Si vous souhaitez qu'une arme puisse \xEAtre tenue \xE0 une main quand le personnage est agrandi, ajoutez \xE0 l'arme le pr\xE9dicat armeDeGrand.
      2. -
      3. Forme gazeuse : !cof-effet-temp formeGazeuse [[1d4 + @{selected|INT}]] --mana 0. Au MJ de faire attention que sous cette forme, toutes les capacit\xE9s sont interdites.
      4. -
      5. H\xE2te : !cof-effet-temp hate [[1d6+@{selected|INT}]] --mana 1, au MJ de g\xE9rer ensuite les actions possibles chaque tour.
      6. -
      7. T\xE9l\xE9portation : Pas de support autre que !cof-lancer-sort se t\xE9l\xE9porte (\xE0 [[@{selected|INTELLIGENCE}*10]] m maximum) --mana 2.
      8. -
      9. D\xE9sint\xE9gration : +
      10. Agrandissement : !cof-effet-temp agrandissement [[5+@{selected|INT}]] --target @{target|token_id} --lanceur @{selected|token_id} --portee 0 --mana 0. Si vous souhaitez qu'une arme puisse être tenue à une main quand le personnage est agrandi, ajoutez à l'arme le prédicat armeDeGrand.
      11. +
      12. Forme gazeuse : !cof-effet-temp formeGazeuse [[1d4 + @{selected|INT}]] --mana 0. Au MJ de faire attention que sous cette forme, toutes les capacités sont interdites.
      13. +
      14. Hâte : !cof-effet-temp hate [[1d6+@{selected|INT}]] --mana 1, au MJ de gérer ensuite les actions possibles chaque tour.
      15. +
      16. Téléportation : Pas de support autre que !cof-lancer-sort se téléporte (à [[@{selected|INTELLIGENCE}*10]] m maximum) --mana 2.
      17. +
      18. Désintégration :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 5D6+INT, port\xE9e 20, type Sortil\xE8ge, d\xE9g\xE2ts magiques, options --mana 3.
        • -
        • Objet de sort : #Attaque D\xE9sint\xE9gration --toucher [[@{selected|ATKMAG}]] --dm 5d6+[[@{selected|INT}]] --magique --portee 20 --sortilege
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 5D6+INT, portée 20, type Sortilège, dégâts magiques, options --mana 3.
        • +
        • Objet de sort : #Attaque Désintégration --toucher [[@{selected|ATKMAG}]] --dm 5d6+[[@{selected|INT}]] --magique --portee 20 --sortilege
      @@ -1498,519 +1502,527 @@

      Voie de la magie destructrice

      1. Projectile magique :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4, port\xE9e 50, type Sortil\xE8ge, modificateurs auto d\xE9g\xE2ts magiques, options --mana 0 --fx beam-magic.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4, portée 50, type Sortilège, modificateurs auto dégâts magiques, options --mana 0 --fx beam-magic.
        • Objet de sort : #Attaque Projectile Magique --auto --dm 1d4 --magique --portee 50 --sortilege --fx beam-magic
      2. Rayon affaiblissant :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateurs pasDeDmg d\xE9g\xE2ts magiques, options --mana 0 --effet rayonAffaiblissant [[1d6+@{selected|INT}]] --fx splatter-magic.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateurs pasDeDmg dégâts magiques, options --mana 0 --effet rayonAffaiblissant [[1d6+@{selected|INT}]] --fx splatter-magic.
        • Objet de sort : #Attaque Rayon affaiblissant --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --effet rayonAffaiblissant [[1d6+@{selected|INT}]] --fx splatter-magic
      3. -
      4. Fl\xE8che enflamm\xE9e : +
      5. Flèche enflammée :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, port\xE9e 30, type Sortil\xE8ge, d\xE9g\xE2ts feu, options --mana 1 --fx beam-fire --feu --enflamme.
        • -
        • Objet de sort : #Attaque Fl\xE8che enflamm\xE9e --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --feu --portee 30 --sortilege --fx beam-fire --enflamme
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, portée 30, type Sortilège, dégâts feu, options --mana 1 --fx beam-fire --feu --enflamme.
        • +
        • Objet de sort : #Attaque Flèche enflammée --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --feu --portee 30 --sortilege --fx beam-fire --enflamme
      6. Boule de feu :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 4d6+INT, port\xE9e 30, type Sortil\xE8ge, d\xE9g\xE2ts feu, options --mana 2 --demiAuto --disque 6 --psave DEX [[10+@{selected|INT}]] --targetFx explode-fire.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 4d6+INT, portée 30, type Sortilège, dégâts feu, options --mana 2 --demiAuto --disque 6 --psave DEX [[10+@{selected|INT}]] --targetFx explode-fire.
        • Objet de sort : #Attaque Boule de feu --toucher [[@{selected|ATKMAG}]] --dm 4d6+[[@{selected|INT}]] --feu --magique --portee 30 --sortilege --demiAuto --disque 6 --psave DEX [[10+@{selected|INT}]] --targetFx explode-fire
      7. -
      8. Rituel de puissance : faire l'appel aux attaques avec --avecd12crit --plus 2d6. On peut par exemple ajouter ceci dans les options des attaques lorsque le Rituel peut \xEAtre utilis\xE9 :?{Rituel de puissance?|Non,&#32;|Oui,--avecd12crit --plus 2d6}
      9. +
      10. Rituel de puissance : faire l'appel aux attaques avec --avecd12crit --plus 2d6. On peut par exemple ajouter ceci dans les options des attaques lorsque le Rituel peut être utilisé :?{Rituel de puissance?|Non,&#32;|Oui,--avecd12crit --plus 2d6}
      -

      Voie de la magie \xE9l\xE9mentaire

      +

      Voie de la magie élémentaire

      1. Asphyxie :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge,modificateurs pasDeDmg, options --mana 0 --effet asphyxie [[1+@{selected|INT}]].
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège,modificateurs pasDeDmg, options --mana 0 --effet asphyxie [[1+@{selected|INT}]].
        • Objet de sort : #Attaque Asphyxie --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --effet asphyxie [[1+@{selected|INT}]]
      2. -
      3. Protection contre les \xE9l\xE9ments : ajouter un pr\xE9dicat voieDeLaMagieElementaire avec comme valeur le rang dans la voie. Pour lancer le sort, faire !cof-effet-temp protectionContreLesElements [[5+@{selected|INT}]] --mana 0. Notez que si vous utilisez une option --valeur \xE0 la place d'utiliser le pr\xE9dicat, la RD sera cette valeur multipli\xE9e par 2.
      4. -
      5. Arme enflamm\xE9e : Lancer le sort avec !cof-effet-temp armeEnflammee [[5+@{selected|INT}]] --lanceur @{selected|token_id} --target @{target|token_id} --portee 0 --mana 1. Il faut que la cible tienne une arme en main (voir !cof-degainer). Limitations : si deux attaques utilisent la m\xEAme arme, il faut faire deux fois l'action, une pour chaque attaque. Si vous souhaitez faire le m\xEAme effet mais avec des d\xE9g\xE2ts de froid, vous pouvez utiliser armeGlacee \xE0 la place.
      6. -
      7. Respiration aquatique : pas de support autre que !cof-lancer-sort lance un sort de respiration aquatique (dur\xE9e 10 minutes, sur soi plus [[@{selected|INT}]] compagnons) --mana 2.
      8. -
      9. Peau de pierre : !cof-effet-temp peauDePierreMag [[5+@{selected|INT}]] --mana 3. Le script va appliquer une RD de [5+Mod. d'INT] en dernier lieu, et compter le maximum des 40 d\xE9g\xE2ts par d\xE9faut. Il est possible de changer la valeur de la RD et le nombre de points de d\xE9g\xE2ts absorb\xE9s en ajoutant l'option --valeur rd absorbe. \xC0 noter que le script rajoute +1 \xE0 la RD et +5 au total de d\xE9g\xE2ts absorb\xE9s en cas de magie puissante, ou par point de mana depens\xE9 en magie intense.
      10. +
      11. Protection contre les éléments : ajouter un prédicat voieDeLaMagieElementaire avec comme valeur le rang dans la voie. Pour lancer le sort, faire !cof-effet-temp protectionContreLesElements [[5+@{selected|INT}]] --mana 0. Notez que si vous utilisez une option --valeur à la place d'utiliser le prédicat, la RD sera cette valeur multipliée par 2.
      12. +
      13. Arme enflammée : Lancer le sort avec !cof-effet-temp armeEnflammee [[5+@{selected|INT}]] --lanceur @{selected|token_id} --target @{target|token_id} --portee 0 --mana 1. Il faut que la cible tienne une arme en main (voir !cof-degainer). Limitations : si deux attaques utilisent la même arme, il faut faire deux fois l'action, une pour chaque attaque. Si vous souhaitez faire le même effet mais avec des dégâts de froid, vous pouvez utiliser armeGlacee à la place.
      14. +
      15. Respiration aquatique : pas de support autre que !cof-lancer-sort lance un sort de respiration aquatique (durée 10 minutes, sur soi plus [[@{selected|INT}]] compagnons) --mana 2.
      16. +
      17. Peau de pierre : !cof-effet-temp peauDePierreMag [[5+@{selected|INT}]] --mana 3. Le script va appliquer une RD de [5+Mod. d'INT] en dernier lieu, et compter le maximum des 40 dégâts par défaut. Il est possible de changer la valeur de la RD et le nombre de points de dégâts absorbés en ajoutant l'option --valeur rd absorbe. À noter que le script rajoute +1 à la RD et +5 au total de dégâts absorbés en cas de magie puissante, ou par point de mana depensé en magie intense.

      Voie de la magie protectrice

      1. Armure du mage : !cof-effet-combat armureDuMage --mana 0.
      2. Chute ralentie : pas de support autre que !cof-lancer-sort lance un sort de Chute ralentie --mana 0
      3. Flou : !cof-effet-temp flou [[1d4+@{selected|INT}]] --mana 1.
      4. -
      5. Cercle de protection : Le script ne g\xE8re pas le cercle en lui-m\xEAme, mais vous pouvez cr\xE9er deux abilities. +
      6. Cercle de protection : Le script ne gère pas le cercle en lui-même, mais vous pouvez créer deux abilities.
        • !cof-effet-temp cercleDeProtection 100 --target @{target|token_id} --lanceur @{selected|token_id} --valeur @{selected|token_id} et cibler un personnage pour lui appliquer l'effet.
        • !cof-effet-temp cercleDeProtection fin --target @{target|token_id} --lanceur @{selected|token_id} pour supprimer l'effet sur un personnage.
        - Le script proposera alors automatiquement \xE0 ces personnages un bouton avec le nom du magicien si une cible prot\xE9g\xE9e est cibl\xE9e par une attaque magique. Le jet d'attaque magique oppos\xE9 sera automatis\xE9. Si vous utilisez les options de mana, rajoutez --mana {Co\xFBt ?} \xE0 la premi\xE8re ability. Indiquer le co\xFBt au lancement, et 0 pour les autres applications. + Le script proposera alors automatiquement à ces personnages un bouton avec le nom du magicien si une cible protégée est ciblée par une attaque magique. Le jet d'attaque magique opposé sera automatisé. Si vous utilisez les options de mana, rajoutez --mana {Coût ?} à la première ability. Indiquer le coût au lancement, et 0 pour les autres applications.
      7. -
      8. Arr\xEAt du temps : pas de support autre que !cof-lancer-sort arr\xEAte le temps pour [[1d6+@{selected|INT}]] tours --mana 3
      9. +
      10. Arrêt du temps : pas de support autre que !cof-lancer-sort arrête le temps pour [[1d6+@{selected|INT}]] tours --mana 3

      Voie de la magie universelle

        -
      1. Lumi\xE8re : !cof-lumiere @{target|token_id} 20 --mana 0. On peut utiliser une cible qui ne soit qu'un personnage sans PV, et dans ce cas le token dispara\xEEt, et pour \xE9teindre la lumi\xE8re, le MJ doit supprimer le token dans le layer de l'\xE9clairage dynamique. Si la cible est un personnage avec des PV, alors la lumi\xE8re se d\xE9placera avec lui, et pour \xE9teindre la lumi\xE8re, il faut s\xE9clectionner le ou les tokens et lancer !cof-eteindre-lumiere lumiere.
      2. -
      3. D\xE9tection de la magie : pas de support autre que !cof-lancer-sort lance un sort de D\xE9tection de la Magie --mana 0.
      4. -
      5. Invisibilit\xE9 : utiliser !cof-set-state invisible true --message se rend invisible --messageMJ l'invisibilit\xE9 va durer [[1d6+@{selected|INT}]] minutes --mana 1. Pour les ennemis, mettre dans le layer gm, pour les joueurs, ne pas les cibler. Reste le probl\xE8me des AOE...
      6. +
      7. Lumière : !cof-lumiere @{target|token_id} 20 --mana 0. On peut utiliser une cible qui ne soit qu'un personnage sans PV, et dans ce cas le token disparaît, et pour éteindre la lumière, le MJ doit supprimer le token dans le layer de l'éclairage dynamique. Si la cible est un personnage avec des PV, alors la lumière se déplacera avec lui, et pour éteindre la lumière, il faut séclectionner le ou les tokens et lancer !cof-eteindre-lumiere lumiere.
      8. +
      9. Détection de la magie : pas de support autre que !cof-lancer-sort lance un sort de Détection de la Magie --mana 0.
      10. +
      11. Invisibilité : utiliser !cof-set-state invisible true --message se rend invisible --messageMJ l'invisibilité va durer [[1d6+@{selected|INT}]] minutes --mana 1. Pour les ennemis, mettre dans le layer gm, pour les joueurs, ne pas les cibler. Reste le problème des AOE...
      12. Vol : pas de support autre que !cof-lancer-sort vole --messageMJ le vol va durer [[1d6+@{selected|INT}]] minutes --mana 2
      13. -
      14. Intelligence h\xE9ro\xEFque : reporter sur la fiche
      15. +
      16. Intelligence héroïque : reporter sur la fiche

      Moine

      -

      Voie de l\x2019\xE9nergie vitale

      +

      Voie de l’énergie vitale

        -
      1. Main d'\xE9nergie : utiliser l'attaque \xE0 mains nues avec l'option --mainsDEnergie. D'autre part, ajouter l'option --magique \xE0 toutes les attaques \xE0 mains nues.
      2. -
      3. Pression mortelle : utiliser l'option --pointsVitaux pour ne pas infliger imm\xE9diatement les d\xE9g\xE2ts, et l'option --pressionMortelle pour lib\xE9rer les d\xE9g\xE2ts.
      4. -
      5. Invuln\xE9rable: utiliser un pr\xE9dicat invulnerable
      6. -
      7. Projection du ki : ajouter simplement l'attaque sur la fiche, et utiliser le type d'attaque Sortilege et le type de d\xE9g\xE2ts magique.
      8. -
      9. Asc\xE9tisme : noter la constitution comme une caract\xE9ristique sup\xE9rieure sur la fiche.
      10. +
      11. Main d'énergie : utiliser l'attaque à mains nues avec l'option --mainsDEnergie. D'autre part, ajouter l'option --magique à toutes les attaques à mains nues.
      12. +
      13. Pression mortelle : utiliser l'option --pointsVitaux pour ne pas infliger immédiatement les dégâts, et l'option --pressionMortelle pour libérer les dégâts.
      14. +
      15. Invulnérable: utiliser un prédicat invulnerable
      16. +
      17. Projection du ki : ajouter simplement l'attaque sur la fiche, et utiliser le type d'attaque Sortilege et le type de dégâts magique.
      18. +
      19. Ascétisme : noter la constitution comme une caractéristique supérieure sur la fiche.
      -

      Voie de la ma\xEEtrise

      +

      Voie de la maîtrise

        -
      1. Esquive du singe : mettre \xE0 jour la d\xE9fense sur la fiche, et ajouter une comp\xE9tence acrobatie avec le bonus donn\xE9 par la capacit\xE9.
      2. -
      3. Morsure du serpent : pour ne pas avoir \xE0 modifier les chances de critique pour toutes les attaques au contact, utiliser un pr\xE9dicat morsureDuSerpent. Attention \xE0 ne pas faire \xE7a ET modifier les chances de critiques de l'attaque, car \xE7a s'additionne. (En revanche, pas de soucis avec la science du critique).
      4. -
      5. Griffes du tigre : rajouter l'option --explodeMax aux attaques \xE0 mains nues.
      6. -
      7. Fureur du dragon : Cr\xE9er une action : !cof-explosion Fureur du dragon --auto --portee 0 --disque 1 --saufAllies --dm 2D6+[[@{selected|FOR}]] --etat renverse --save FOR 10 --limiteParCombat 1 fureurDuDragon
      8. +
      9. Esquive du singe : mettre à jour la défense sur la fiche, et ajouter une compétence acrobatie avec le bonus donné par la capacité.
      10. +
      11. Morsure du serpent : pour ne pas avoir à modifier les chances de critique pour toutes les attaques au contact, utiliser un prédicat morsureDuSerpent. Attention à ne pas faire ça ET modifier les chances de critiques de l'attaque, car ça s'additionne. (En revanche, pas de soucis avec la science du critique).
      12. +
      13. Griffes du tigre : rajouter l'option --explodeMax aux attaques à mains nues.
      14. +
      15. Fureur du dragon : Créer une action : !cof-explosion Fureur du dragon --auto --portee 0 --disque 1 --saufAllies --dm 2D6+[[@{selected|FOR}]] --etat renverse --save FOR 10 --limiteParCombat 1 fureurDuDragon
      16. Moment de perfection : !cof-effet-temp momentDePerfection 1 --limiteParCombat 1
      -

      Voie de la m\xE9ditation

      +

      Voie de la méditation

        -
      1. Pacifisme : ajouter un pr\xE9dicat pacifisme. Il est possible d'y associer une valeur pour appliquer un bonus \xE0 la d\xE9fense diff\xE9rent de 5.
      2. -
      3. Transe de gu\xE9rison : !cof-transe-guerison
      4. -
      5. Ma\xEEtrise du ki : adapter les valeurs de DEF et init
      6. +
      7. Pacifisme : ajouter un prédicat pacifisme. Il est possible d'y associer une valeur pour appliquer un bonus à la défense différent de 5.
      8. +
      9. Transe de guérison : !cof-transe-guerison
      10. +
      11. Maîtrise du ki : adapter les valeurs de DEF et init
      12. Projection mentale : aucun support
      13. -
      14. Sagesse h\xE9ro\xEFque : reporter sur la fiche
      15. +
      16. Sagesse héroïque : reporter sur la fiche

      Voie du poing

        -
      1. Poings de fer : simplement enlever le --tempDmg et ajuster les d\xE9g\xE2ts
      2. -
      3. Parade de projectiles : ajouter un pr\xE9dicat paradeDeProjectiles. Le script proposera automatiquement un bouton pour parer l'attaque dans les cas appropri\xE9s.
      4. +
      5. Poings de fer : simplement enlever le --tempDmg et ajuster les dégâts
      6. +
      7. Parade de projectiles : ajouter un prédicat paradeDeProjectiles. Le script proposera automatiquement un bouton pour parer l'attaque dans les cas appropriés.
      8. Peau de fer : ajuster la DEF sur la fiche.
      9. -
      10. D\xE9luge de coups : le MJ g\xE8re le nombre d'attaques. Pour les attaques au d12, utiliser l'option --avecd12.
      11. +
      12. Déluge de coups : le MJ gère le nombre d'attaques. Pour les attaques au d12, utiliser l'option --avecd12.
      13. Puissance du ki : utiliser les options --avecd12crit --plus 2d6.

      Voie du vent

        -
      1. Pas du vent : un pr\xE9dicat pasDuVent avec comme valeur le rang dans la voie permet d'augmenter automatiquement l'initiative. Pour le reste, il n'y a pas de support particulier.
      2. -
      3. Course du vent : g\xE9r\xE9 par le MJ.
      4. +
      5. Pas du vent : un prédicat pasDuVent avec comme valeur le rang dans la voie permet d'augmenter automatiquement l'initiative. Pour le reste, il n'y a pas de support particulier.
      6. +
      7. Course du vent : géré par le MJ.
      8. Course des airs : pas de support.
      9. -
      10. L\xE9vitation : pas de support.
      11. +
      12. Lévitation : pas de support.
      13. Passe-muraille : pas de support.
      -

      N\xE9cromancien

      +

      Nécromancien

      -

      Voie du d\xE9mon

      +

      Voie du démon

        -
      1. Mal\xE9diction : +
      2. Malédiction :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg malediction, options --mana 0.
        • -
        • Objet de sort : #Attaque Mal\xE9diction --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --malediction
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg malediction, options --mana 0.
        • +
        • Objet de sort : #Attaque Malédiction --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --malediction
      3. Aspect de la succube :
        • !cof-effet-temp aspectDeLaSuccube [[5+@{selected|INT}]] --mana 0 pour lancer le sort
        • -
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4+CHA, port\xE9e 0, type Sortil\xE8ge, d\xE9g\xE2ts de drain, options --si etat aspectDeLaSuccube.
        • +
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4+CHA, portée 0, type Sortilège, dégâts de drain, options --si etat aspectDeLaSuccube.
        • Pour un objet de sort, le code sera #Attaque Attaque de la succube --toucher [[@{selected|ATKMAG}]] --dm 1d4+[[@{selected|CHA}]] --magique --portee 0 --sortilege --si etat aspectDeLaSuccube --drain
      4. -
      5. Pacte sanglant : cr\xE9er un pr\xE9dicat pacteSanglant de valeur 3 (rang 3) ou 5 (rang 5). Le script va automatiser l'ajout de boutons sur tous les tests a posteriori, y compris sur les attaques qui ciblent le personnage. Aux joueurs de s'accorder sur la n\xE9cessit\xE9 d'une d\xE9claration a priori n\xE9cessaire pour l'utilisation de la capacit\xE9.
      6. -
      7. Aspect du d\xE9mon : +
      8. Pacte sanglant : créer un prédicat pacteSanglant de valeur 3 (rang 3) ou 5 (rang 5). Le script va automatiser l'ajout de boutons sur tous les tests a posteriori, y compris sur les attaques qui ciblent le personnage. Aux joueurs de s'accorder sur la nécessité d'une déclaration a priori nécessaire pour l'utilisation de la capacité.
      9. +
      10. Aspect du démon :
        • !cof-effet-temp aspectDuDemon [[5+@{selected|INT}]] --mana 2 pour lancer le sort
        • -
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+4, port\xE9e 0, type Sortil\xE8ge, d\xE9g\xE2ts magiques, options --si etat aspectDuDemon
        • -
        • Pour un objet de sort, l'attaque pourra avoir le code #Attaque Attaque du d\xE9mon --toucher [[@{selected|ATKMAG}]] --dm 1d6+4 --magique --portee 0 --sortilege --si etat aspectDuDemon
        • +
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+4, portée 0, type Sortilège, dégâts magiques, options --si etat aspectDuDemon
        • +
        • Pour un objet de sort, l'attaque pourra avoir le code #Attaque Attaque du démon --toucher [[@{selected|ATKMAG}]] --dm 1d6+4 --magique --portee 0 --sortilege --si etat aspectDuDemon
      11. -
      12. Invocation d'un d\xE9mon : !cof-invoquer-demon @{selected|token_id} --mana 3
      13. +
      14. Invocation d'un démon : !cof-invoquer-demon @{selected|token_id} --mana 3

      Voie de la mort

        -
      1. Siphon des \xE2mes : ajouter un pr\xE9dicat siphonDesAmes. Par d\xE9faut, si il y a plusieurs personnages avec ce pouvoir, tous vont siphoner les \xE2mes sans interaction. Mais il est possible de d\xE9clarer un ordre de priorit\xE9, telle que si les personnages de plus haute priorit\xE9 ont siphon\xE9 tous les points de vie qu'ils pouvaient, il ne reste rien \xE0 siphoner pour les autre. Pour se faire, utilisez un pr\xE9dicat siphonDesAmesPrioritaire avec la valeur num\xE9rique de la priorit\xE9 (0 par d\xE9faut, plus la valeur est grande, plus le personnage est prioritaire).
      2. +
      3. Siphon des âmes : ajouter un prédicat siphonDesAmes. Par défaut, si il y a plusieurs personnages avec ce pouvoir, tous vont siphoner les âmes sans interaction. Mais il est possible de déclarer un ordre de priorité, telle que si les personnages de plus haute priorité ont siphoné tous les points de vie qu'ils pouvaient, il ne reste rien à siphoner pour les autre. Pour se faire, utilisez un prédicat siphonDesAmesPrioritaire avec la valeur numérique de la priorité (0 par défaut, plus la valeur est grande, plus le personnage est prioritaire).
      4. Masque mortuaire : !cof-effet-temp masqueMortuaire [[5+@{selected|INT}]] --mana 0
      5. Baiser du vampire :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+INT, port\xE9e 50, type Sortil\xE8ge, d\xE9g\xE2ts de drain, options --mana 1 --seulementVivant.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+INT, portée 50, type Sortilège, dégâts de drain, options --mana 1 --seulementVivant.
        • Objet de sort : #Attaque Baiser du vampire --toucher [[@{selected|ATKMAG}]] --dm 1d8+[[@{selected|INT}]] --portee 50 --sortilege --drain --seulementVivant
      6. Briser les coeurs :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 5d6+INT, port\xE9e 20, type Sortil\xE8ge, modificateurs seulementVivant necromancie, options --mana 2 --psave CON [[10+@{selected|INT}]] tempete 2.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 5d6+INT, portée 20, type Sortilège, modificateurs seulementVivant necromancie, options --mana 2 --psave CON [[10+@{selected|INT}]] tempete 2.
        • Objet de sort : #Attaque Briser les coeurs --toucher [[@{selected|ATKMAG}]] --dm 5d6+[[@{selected|INT}]] --portee 20 --sortilege --psave CON [[10+@{selected|INT}]] tempete 2 --seulementVivant --necromancie
        - \xC0 noter que la partie tempete 2 impl\xE9mente une chose qui n'est pas dans les r\xE8gles, \xE0 savoir augmenter la difficult\xE9 du test de constitution de 2 par point de mana investi en temp\xEAte de mana intense. Je trouvais en effet que sans cet ajout, \xE0 mana \xE9gale, le sort \xE9tait moins int\xE9ressant que le baiser du vampire. Il reste moins fort et plus situationnel que la d\xE9sint\xE9gration du magicien (\xE0 mana \xE9gale), m\xEAme avec ce changement. + À noter que la partie tempete 2 implémente une chose qui n'est pas dans les règles, à savoir augmenter la difficulté du test de constitution de 2 par point de mana investi en tempête de mana intense. Je trouvais en effet que sans cet ajout, à mana égale, le sort était moins intéressant que le baiser du vampire. Il reste moins fort et plus situationnel que la désintégration du magicien (à mana égale), même avec ce changement.
      7. Mot de mort :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateurs pasDeDmg necromancie difficultePV, options --mana 3 --etat mort --save CON [[10+@{selected|INT}]] tempete 2.
        • -
        • Objet de sort : #Attaque Mot de mort --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --necromancie --difficultePV --etat mort --save CON [[10+@{selected|INT}]] tempete 2
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateurs pasDeDmg necromancie difficultePV seulementVivant, options --mana 3 --etat mort --save CON [[10+@{selected|INT}]] tempete 2.
        • +
        • Objet de sort : #Attaque Mot de mort --toucher [[@{selected|ATKMAG}]] --pasDeDmg --seulementVivant --portee 20 --sortilege --necromancie --difficultePV --etat mort --save CON [[10+@{selected|INT}]] tempete 2
        - Comme pour Briser les coeurs, je pense qu'on peut augmenter la difficult\xE9 du jet de r\xE9sistance avec la puissance de la temp\xEAte de mana. + Comme pour Briser les coeurs, je pense qu'on peut augmenter la difficulté du jet de résistance avec la puissance de la tempête de mana.

      Voie de l'outre-tombe

      1. Peur :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg, options --mana 0 --peur [[10+@{selected|INT}]] [[1d4+r]]o\xF9 r est le rang dans la voie
        • -
        • Objet de sort : #Attaque Peur --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --peur [[10+@{selected|INT}]] [[1d4+r]]o\xF9 r est le niveau de l'objet
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg, options --mana 0 --peur [[10+@{selected|INT}]] [[1d4+r]]r est le rang dans la voie
        • +
        • Objet de sort : #Attaque Peur --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --peur [[10+@{selected|INT}]] [[1d4+r]]r est le niveau de l'objet
      2. -
      3. Animation d'un mort-vivant : !cof-animer-mort @{selected|token_id} --mana 0. Cela met directement le n\xE9cromant et le zombie en combat. Les Zombies perdent automatiquement 1 PV tous les 6 rounds. Lorsqu'ils atteignent 0 PV (quelle qu'en soit la raison) ou \xE0 la fin du combat, ils sont automatiquement d\xE9truits et supprim\xE9s. Si le lanceur a un pr\xE9dicat voieOutreTombe, le script g\xE8re le maximum de zombies qu'il peut invoquer. Mana, consommables et limites sont g\xE9r\xE9es, mais pas Temp\xEAte de Mana.
      4. -
      5. Putr\xE9faction : +
      6. Animation d'un mort-vivant : !cof-animer-mort @{selected|token_id} --mana 0. Cela met directement le nécromant et le zombie en combat. Les Zombies perdent automatiquement 1 PV tous les 6 rounds. Lorsqu'ils atteignent 0 PV (quelle qu'en soit la raison) ou à la fin du combat, ils sont automatiquement détruits et supprimés. Si le lanceur a un prédicat voieOutreTombe, le script gère le maximum de zombies qu'il peut invoquer. Mana, consommables et limites sont gérées, mais pas Tempête de Mana.
      7. +
      8. Putréfaction :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, port\xE9e 10, type Sortil\xE8ge, modificateurs necromancie, options --mana 1 --effet putrefactionOutreTombe --save CON [[12+@{selected|INT}]]
        • -
        • Objet de sort : #Attaque Putr\xE9faction --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --portee 10 --sortilege --necromancie --effet putrefactionOutreTombe --save CON [[12+@{selected|INT}]]
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, portée 10, type Sortilège, modificateurs necromancie, options --mana 1 --effet putrefactionOutreTombe --save CON [[12+@{selected|INT}]]
        • +
        • Objet de sort : #Attaque Putréfaction --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --portee 10 --sortilege --necromancie --effet putrefactionOutreTombe --save CON [[12+@{selected|INT}]]
      9. Ensevelissement :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg necromancie, options --mana 2 --etat enseveli FORDEX [[13+@{selected|INT}]]
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg necromancie, options --mana 2 --etat enseveli FORDEX [[13+@{selected|INT}]]
        • Objet de sort : #Attaque Ensevelissement --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --necromancie --etat enseveli FORDEX [[13+@{selected|INT}]]
        - Les d\xE9g\xE2ts sont inflig\xE9s au d\xE9but de chaque tour, et la cible recevra \xE0 son initiative un bouton lui permettant d'effectuer le jet pour sortir. Elle pourra \xE9galement ajouter un bonus manuel au jet, en fonction des actions r\xE9alis\xE9es pour l'aider \xE0 sortir. + Les dégâts sont infligés au début de chaque tour, et la cible recevra à son initiative un bouton lui permettant d'effectuer le jet pour sortir. Elle pourra également ajouter un bonus manuel au jet, en fonction des actions réalisées pour l'aider à sortir.
      10. -
      11. Arm\xE9e des morts : !cof-effet-temp armeeDesMorts @{selected|niveau} --limiteParJour 1 --mana 3. La zone couverte est symbolis\xE9e par l'activation d'une aura sur le token du lanceur. Le script utilisera pour cela l'aura 2 du token, donc attention si vous l'utilisez d\xE9j\xE0 sur le token du lanceur, elle sera \xE9cras\xE9e. Toute cible (le script ignore les alli\xE9s du lanceur) qui s'active dans une zone couverte par une arm\xE9e recevra dans ses actions un bouton sp\xE9cial pour se d\xE9fendre. Les d\xE9g\xE2ts sont inflig\xE9s automatiquement en d\xE9but de tour. En option, le script support l'argument --puissant des r\xE8gles de Mana de base, qui doublent la surface couverte (rayon 28m). Il est aussi possible d'utiliser l'option de Temp\xEAte de Mana ; la surface couverte sera multipli\xE9e par le nombre de PM investis en Magie Intense. Les adversaires avec un pr\xE9dicat volant ne seront pas affect\xE9s.
      12. +
      13. Armée des morts : !cof-effet-temp armeeDesMorts @{selected|niveau} --limiteParJour 1 --mana 3. La zone couverte est symbolisée par l'activation d'une aura sur le token du lanceur. Le script utilisera pour cela l'aura 2 du token, donc attention si vous l'utilisez déjà sur le token du lanceur, elle sera écrasée. Toute cible (le script ignore les alliés du lanceur) qui s'active dans une zone couverte par une armée recevra dans ses actions un bouton spécial pour se défendre. Les dégâts sont infligés automatiquement en début de tour. En option, le script support l'argument --puissant des règles de Mana de base, qui doublent la surface couverte (rayon 28m). Il est aussi possible d'utiliser l'option de Tempête de Mana ; la surface couverte sera multipliée par le nombre de PM investis en Magie Intense. Les adversaires avec un prédicat volant ne seront pas affectés.

      Voie du sang

      1. Saignements :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateurs pasDeDmg necromancie, options --mana 0 --effet saignementsSang rang, o\xF9 rang est le rang dans la Voie
        • -
        • Objet de sort : #Attaque Saignements --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --necromancie --effet saignementsSang rang, o\xF9 rang est le niveau de l'objet
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateurs pasDeDmg necromancie, options --mana 0 --effet saignementsSang rang, où rang est le rang dans la Voie
        • +
        • Objet de sort : #Attaque Saignements --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --necromancie --effet saignementsSang rang, où rang est le niveau de l'objet
        - Si vous souhaitez que le saignement ne puisse pas \xEAtre appliqu\xE9 \xE0 certains personnages (comme des golems ou des squelettes), vous pouvez leur ajouter un pr\xE9dicat immuniteSaignement. + Si vous souhaitez que le saignement ne puisse pas être appliqué à certains personnages (comme des golems ou des squelettes), vous pouvez leur ajouter un prédicat immuniteSaignement.
      2. Sang mordant : !cof-effet-temp sangMordant [[5+@{selected|INT}]] --mana 0.
      3. -
      4. Exsangue : ajouter un pr\xE9dicat exsangue.
      5. -
      6. H\xE9morragie : +
      7. Exsangue : ajouter un prédicat exsangue.
      8. +
      9. Hémorragie :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 10, type Sortil\xE8ge, modificateurs pasDeDmg necromancie, options --mana 2 --effet hemorragie [[5+@{selected|INT}]]
        • -
        • Objet de sort : #Attaque H\xE9morragie --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --necromancie --effet hemorragie [[5+@{selected|INT}]]
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 10, type Sortilège, modificateurs pasDeDmg necromancie, options --mana 2 --effet hemorragie [[5+@{selected|INT}]]
        • +
        • Objet de sort : #Attaque Hémorragie --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 10 --sortilege --necromancie --effet hemorragie [[5+@{selected|INT}]]
      10. Lien de sang :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg necromancie, options --mana 3 --effet lienDeSang [[5+@{selected|INT}]]
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg necromancie, options --mana 3 --effet lienDeSang [[5+@{selected|INT}]]
        • Objet de sort : #Attaque Lien de sang --toucher [[@{selected|ATKMAG}]] --pasDeDmg --portee 20 --sortilege --necromancie --effet lienDeSang [[5+@{selected|INT}]]
        Pas de support pour le lancement de sort sans ligne de vue.

      Voie de la sombre magie

      -

      Ajouter sur la fiche une comp\xE9tence Occultisme avec en bonus 2 fois le rang dans cette voie.

      +

      Ajouter sur la fiche une compétence Occultisme avec en bonus 2 fois le rang dans cette voie.

        -
      1. T\xE9n\xE8bres : !cof-tenebres @{selected|token_id} @{target|token_id} --mana 0. La commande pose un token transparent avec une aura noire visible par les joueurs pour visualiser la zone, et une petite aura jaune visible uniquement par le MJ (pour s\xE9lectionner le token si n\xE9cessaire). Tous les tokens pr\xE9sents dans la zone au lancement du sort sont automatiquement aveugl\xE9s. Au MJ ensuite d'enlever l'\xE9tat aveugl\xE9 quand les cibles sortent de la zone. A la fin de la dur\xE9e du sort, ou \xE0 la fin du combat, la zone et les \xE9tats aveugl\xE9s restant disparaissent automatiquement. Il est aussi possible de changer les valeurs par d\xE9faut du sort (port\xE9e 20m, rayon 5m) avec les options --portee X et --rayon X. En r\xE8gle custom, l'option puissant permet de doubler la superficie couverte (le script calcule le rayon appropri\xE9 si custom).
      2. -
      3. Pattes d'araign\xE9es : !cof-lancer-sort peut se d\xE9placer sur les murs pendants [[5+@{selected|INT}]] tours --mana 0
      4. -
      5. Strangulation : Le script va v\xE9rifier que la cible est bien vivante, en se basant sur la race, et sinon sur la pr\xE9sence \xE9ventuelle d'un pr\xE9dicat nonVivant. +
      6. Ténèbres : !cof-tenebres @{selected|token_id} @{target|token_id} --mana 0. La commande pose un token transparent avec une aura noire visible par les joueurs pour visualiser la zone, et une petite aura jaune visible uniquement par le MJ (pour sélectionner le token si nécessaire). Tous les tokens présents dans la zone au lancement du sort sont automatiquement aveuglés. Au MJ ensuite d'enlever l'état aveuglé quand les cibles sortent de la zone. A la fin de la durée du sort, ou à la fin du combat, la zone et les états aveuglés restant disparaissent automatiquement. Il est aussi possible de changer les valeurs par défaut du sort (portée 20m, rayon 5m) avec les options --portee X et --rayon X. En règle custom, l'option puissant permet de doubler la superficie couverte (le script calcule le rayon approprié si custom).
      7. +
      8. Pattes d'araignées : !cof-lancer-sort peut se déplacer sur les murs pendants [[5+@{selected|INT}]] tours --mana 0
      9. +
      10. Strangulation : Le script va vérifier que la cible est bien vivante, en se basant sur la race, et sinon sur la présence éventuelle d'un prédicat nonVivant.
          -
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, port\xE9e 20, type Sortil\xE8ge, d\xE9g\xE2ts magiques, modificateurs necromancie, options --mana 1 --effet strangulation rang
        • +
        • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, portée 20, type Sortilège, dégâts magiques, modificateurs necromancie, options --mana 1 --effet strangulation rang
        • !cof-strangulation @{selected|token_id} @{target|token_id} pour maintenir la strangulation
        • Pour un objet de sort, le code de l'attaque sera #Attaque Strangulation --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|INT}]] --magique --portee 20 --sortilege --effet strangulation rang
      11. -
      12. Ombre mortelle : !cof-ombre-mortelle @{selected|token_id} @{target|token_id} [[3+@{selected|INT}]] --portee 20 --mana 2 va cr\xE9er un double de la cible, (\xE0 condition de disposer de 2 points de mana) et ajouter ce double \xE0 l'initiative. Au MJ ensuite de la faire attaquer \xE0 son tour (pas d'aoe, juste attaquer le token dont elle est l'ombre). Le token dispara\xEEt lorsque le nombre de tours est \xE9coul\xE9. Il est possible de choisir l'image utilis\xE9e pour repr\xE9senter l'ombre en passant l'url de l'image avec l'option --image.
      13. -
      14. Intelligence h\xE9ro\xEFque : utiliser la fiche
      15. +
      16. Ombre mortelle : !cof-ombre-mortelle @{selected|token_id} @{target|token_id} [[3+@{selected|INT}]] --portee 20 --mana 2 va créer un double de la cible, (à condition de disposer de 2 points de mana) et ajouter ce double à l'initiative. Au MJ ensuite de la faire attaquer à son tour (pas d'aoe, juste attaquer le token dont elle est l'ombre). Le token disparaît lorsque le nombre de tours est écoulé. Il est possible de choisir l'image utilisée pour représenter l'ombre en passant l'url de l'image avec l'option --image.
      17. +
      18. Intelligence héroïque : utiliser la fiche
      -

      Pr\xEAtre

      +

      Prêtre

      Voie de la foi

        -
      1. Parole divine : ajouter une comp\xE9tence convaincre, de valeur 2 fois le rang dans la voie, et ajouter cette comp\xE9tence dans la liste.
      2. +
      3. Parole divine : ajouter une compétence convaincre, de valeur 2 fois le rang dans la voie, et ajouter cette compétence dans la liste.
      4. Arme d'argent :
          -
        • Pour attaquer avec l'arme d'argent, faire l'attaque avec les DM appropri\xE9s, les modificateurs armeDArgent, magique et l'option --si etat armeDArgent.
        • -
        • !cof-effet-combat armeDArgent --mana 0 pour lancer le sort. Vous pouvez ajouter l'option --degainer L (o\xF9 L est le label de l'attaque avec l'arme d'argent) si vous souhaitez que le pr\xEAtre puisse prendre l'arme en main dans le m\xEAme tour.
        • +
        • Pour attaquer avec l'arme d'argent, faire l'attaque avec les DM appropriés, les modificateurs armeDArgent, magique et l'option --si etat armeDArgent.
        • +
        • !cof-effet-combat armeDArgent --mana 0 pour lancer le sort. Vous pouvez ajouter l'option --degainer L (où L est le label de l'attaque avec l'arme d'argent) si vous souhaitez que le prêtre puisse prendre l'arme en main dans le même tour.
      5. -
      6. Ailes c\xE9lestes : !cof-effet-temp ailesCelestes [[5+@{selected|SAG}]] --mana 1.
      7. +
      8. Ailes célestes : !cof-effet-temp ailesCelestes [[5+@{selected|SAG}]] --mana 1.
      9. Foudres divines :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+SAG, port\xE9e 10, type Sortil\xE8ge, d\xE9g\xE2ts \xE9lectrique, modificateur saufAllies, option --mana 2. D\xE9cochez cette attaque, car elle sera appel\xE9e de mani\xE8re sp\xE9ciale : si le label de ce sort est L, il ne vous reste plus qu'\xE0 faire une action avec !cof-explosion L.
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+SAG, portée 10, type Sortilège, dégâts électrique, modificateur saufAllies, option --mana 2. Décochez cette attaque, car elle sera appelée de manière spéciale : si le label de ce sort est L, il ne vous reste plus qu'à faire une action avec !cof-explosion L.
        • Objet de sort : !cof-explosion Foudres divines --toucher [[@{selected|ATKMAG}]] --dm 1d6+[[@{selected|SAG}]] --electrique --sortilege --portee 10 --saufAllies
      10. -
      11. Charisme h\xE9ro\xEFque : reporter les bonus sur la fiche
      12. +
      13. Charisme héroïque : reporter les bonus sur la fiche

      Voie de la guerre sainte

        -
      1. Arme b\xE9nie : utiliser les modificateurs reroll1, beni et magique \xE0 l'attaque
      2. -
      3. Bouclier de la foi : ajouter un pr\xE9dicat bouclierDeLaFoi, de valeur le bonus en DEF. Ce bonus sera automatiquement ajout\xE9 quand le pr\xEAtre porte son bouclier.
      4. +
      5. Arme bénie : utiliser les modificateurs reroll1, beni et magique à l'attaque
      6. +
      7. Bouclier de la foi : ajouter un prédicat bouclierDeLaFoi, de valeur le bonus en DEF. Ce bonus sera automatiquement ajouté quand le prêtre porte son bouclier.
      8. Marteau sprirituel :
          -
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+SAG, port\xE9e 30, type Sortil\xE8ge, options --mana 1
        • +
        • Sort : Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d8+SAG, portée 30, type Sortilège, options --mana 1
        • Objet de sort : #Attaque Marteau sprirituel --toucher [[@{selected|ATKMAG}]] --dm 1d8+[[@{selected|SAG}]] --portee 30 --sortilege
      9. -
      10. Ch\xE2timent divin : Ajoutez dans la actions du tour une action nomm\xE9e Ch\xE2timent divin, de code #Attaque -1 --bonusAttaque [[@{selected|SAG}]] --plus [[@{selected|SAG}]].
      11. +
      12. Châtiment divin : Ajoutez dans la actions du tour une action nommée Châtiment divin, de code #Attaque -1 --bonusAttaque [[@{selected|SAG}]] --plus [[@{selected|SAG}]].
      13. Mot de pouvoir : !cof-effet-temp etourdi 1 --lanceur @{selected|token_id} --enVue --saufAllies --message @{selected|token_name} prononce un mot avec la voix de son dieu --mana 3
      -

      Voie de la pri\xE8re

      +

      Voie de la prière

        -
      1. B\xE9n\xE9diction : !cof-effet-temp benediction [[3+@{selected|SAG}]] --alliesEnVue --self --mana 0. Il faut avoir d\xE9fini une \xE9quipe avec le pr\xEAtre.
      2. -
      3. Destruction des morts-vivants : !cof-destruction-des-morts-vivants 2d6 --mana 0. Au rang 4 dans la voie, ajuster les d\xE9g\xE2ts. Notez que le script consid\xE8re comme mort-vivant tout personnage avec le champ race \xE0 squelette, zombie, momie, goule,vampire ou mort-vivant, ou alors qui poss\xE8de un pr\xE9dicat mortVivant. Pour \xE9viter la r\xE9p\xE9tition abusive du sort, vous pouvez augmenter la difficult\xE9 \xE0 chaque fois que le sort est r\xE9ussi pendant un m\xEAme combat, avec l'option --malusRepetition m. Un mort-vivant ayant le pr\xE9dicat immunite_destruction ne sera pas affect\xE9 par ce sort.
      4. +
      5. Bénédiction : !cof-effet-temp benediction [[3+@{selected|SAG}]] --alliesEnVue --self --mana 0. Il faut avoir défini une équipe avec le prêtre.
      6. +
      7. Destruction des morts-vivants : !cof-destruction-des-morts-vivants 2d6 --mana 0. Au rang 4 dans la voie, ajuster les dégâts. Notez que le script considère comme mort-vivant tout personnage avec le champ race à squelette, zombie, momie, goule,vampire ou mort-vivant, ou alors qui possède un prédicat mortVivant. Pour éviter la répétition abusive du sort, vous pouvez augmenter la difficulté à chaque fois que le sort est réussi pendant un même combat, avec l'option --malusRepetition m. Un mort-vivant ayant le prédicat immunite_destruction ne sera pas affecté par ce sort.
      8. Sanctuaire : !cof-effet-temp sanctuaire [[5+@{selected|SAG}]] --mana 1.
      9. -
      10. Intervention Divine : ajouter au personnage un pr\xE9dicat interventionDivine. Ensuite, utiliser !cof-intervention-divine ?{Type ?|rate|touche} juste apr\xE8s l'attaque en s\xE9lectionnant le token du Pr\xEAtre pour modifier le r\xE9sultat selon le choix. Il est tr\xE8s pratique de mettre cette commande dans une Ability \xE0 afficher en Token Action. Ne supporte que le jet de touche de la derni\xE8re attaque effectu\xE9e.
      11. -
      12. Sagesse h\xE9ro\xEFque : Reporter les bonus sur la fiche.
      13. +
      14. Intervention Divine : ajouter au personnage un prédicat interventionDivine. Ensuite, utiliser !cof-intervention-divine ?{Type ?|rate|touche} juste après l'attaque en sélectionnant le token du Prêtre pour modifier le résultat selon le choix. Il est très pratique de mettre cette commande dans une Ability à afficher en Token Action. Ne supporte que le jet de touche de la dernière attaque effectuée.
      15. +
      16. Sagesse héroïque : Reporter les bonus sur la fiche.

      Voie des soins

      -

      Ajouter un pr\xE9dicat voieDesSoins avec comme valeur le rang dans la voie.

      +

      Ajouter un prédicat voieDesSoins avec comme valeur le rang dans la voie.

        -
      1. Soins l\xE9gers : !cof-soin @{selected|token_id} @{target|token_id} leger --mana 0. Vous pouvez rajouter un petit effet visuel, par exemple avec --targetFx bubbling-holy. \xC0 titre personnel, j'ajoute --depasseLimite 1 pour permettre de lancer plus de sorts de soins l\xE9ger en une journ\xE9e (mais avec une augmentation cumulative du co\xFBt en mana de 1 \xE0 chaque d\xE9passement).
      2. -
      3. Soins mod\xE9r\xE9s : !cof-soin @{selected|token_id} @{target|token_id} modere --mana 0.
      4. -
      5. Soins de groupe : !cof-soin @{selected|token_id} groupe --mana 1 (ne pas oublier de d\xE9finir des alli\xE9s). Attention, toutefois, le sort ne va pas automatiquement soigner les personnages not\xE9s comme morts, ce qui est le cas g\xE9n\xE9ral si ils sont tomb\xE9s \xE0 0 PV. Si certains alli\xE9s not\xE9s morts ne sont pas vraiment morts, mais juste inconscient, il faudra que le MJ fasse la mise \xE0 jour de l'\xE9tat et des PV lui-m\xEAme.
      6. -
      7. Gu\xE9rison : !cof-guerison @{selected|token_id} @{target|token_id} --portee 0 --limiteParJour 1 --mana 2. Pour l'instant \xE7a ne fait que remettre les points de vie au maximum.
      8. -
      9. Rappel \xE0 la vie : pas de suport, simplement faire !cof-lancer-sort Rappel \xE0 la vie --mana 3 --limiteParJour 1 rappelALaVie.
      10. +
      11. Soins légers : !cof-soin @{selected|token_id} @{target|token_id} leger --mana 0. Vous pouvez rajouter un petit effet visuel, par exemple avec --targetFx bubbling-holy. À titre personnel, j'ajoute --depasseLimite 1 pour permettre de lancer plus de sorts de soins léger en une journée (mais avec une augmentation cumulative du coût en mana de 1 à chaque dépassement).
      12. +
      13. Soins modérés : !cof-soin @{selected|token_id} @{target|token_id} modere --mana 0.
      14. +
      15. Soins de groupe : !cof-soin @{selected|token_id} groupe --mana 1 (ne pas oublier de définir des alliés). Attention, toutefois, le sort ne va pas automatiquement soigner les personnages notés comme morts, ce qui est le cas général si ils sont tombés à 0 PV. Si certains alliés notés morts ne sont pas vraiment morts, mais juste inconscient, il faudra que le MJ fasse la mise à jour de l'état et des PV lui-même.
      16. +
      17. Guérison : !cof-guerison @{selected|token_id} @{target|token_id} --portee 0 --limiteParJour 1 --mana 2. Pour l'instant ça ne fait que remettre les points de vie au maximum.
      18. +
      19. Rappel à la vie : pas de suport, simplement faire !cof-lancer-sort Rappel à la vie --mana 3 --limiteParJour 1 rappelALaVie.
      -

      Voie de la spiritualit\xE9

      +

      Voie de la spiritualité

        -
      1. V\xEAtements sacr\xE9s : Ajouter un pr\xE9dicat vetementsSacres avec comme valeur le rang dans la voie de la spiritualit\xE9. Cela augmente la DEF, mais seulement lorsque le pr\xEAtre ne porte pas d'armure (ne se voit pas sur le total de DEF de la fiche)
      2. -
      3. Protection contre le mal : !cof-effet-combat protectionContreLeMal --lanceur @{selected|token_id} --target @{target|token_id} --portee 0 --mana 0. Donne le bonus contre toute cr\xE9ature dont l'attribut race est squelette, zombie, d\xE9mon, \xE9l\xE9mentaire, ou bien qui poss\xE8de un pr\xE9dicat mauvais.
      4. -
      5. D\xE9livrance : !cof-delivrance @{selected|token_id} @{target|token_id} --portee 0 --mana 1
      6. -
      7. Marche des plans : !cof-lancer-sort marche entre les plans (il peut se d\xE9placer de [[(3+@{selected|SAG})*10]] km) --mana 2.
      8. -
      9. Messie : pas d'autre support que !cof-lancer-sort entre directement en contact avec son dieu pour r\xE9aliser un miracle --mana 3
      10. +
      11. Vêtements sacrés : Ajouter un prédicat vetementsSacres avec comme valeur le rang dans la voie de la spiritualité. Cela augmente la DEF, mais seulement lorsque le prêtre ne porte pas d'armure (ne se voit pas sur le total de DEF de la fiche)
      12. +
      13. Protection contre le mal : !cof-effet-combat protectionContreLeMal --lanceur @{selected|token_id} --target @{target|token_id} --portee 0 --mana 0. Donne le bonus contre toute créature dont l'attribut race est squelette, zombie, démon, élémentaire, ou bien qui possède un prédicat mauvais.
      14. +
      15. Délivrance : !cof-delivrance @{selected|token_id} @{target|token_id} --portee 0 --mana 1
      16. +
      17. Marche des plans : !cof-lancer-sort marche entre les plans (il peut se déplacer de [[(3+@{selected|SAG})*10]] km) --mana 2.
      18. +
      19. Messie : pas d'autre support que !cof-lancer-sort entre directement en contact avec son dieu pour réaliser un miracle --mana 3

      Psionique

      Voie de l'attaque mentale

        -
      1. Attaque mentale : faire 2 attaques, une pour les DMs l\xE9taux, avec les options --sortilege --attaqueMentale --mana 0 et l'autre avec l'option suppl\xE9mentaire --tempDmg (et en ajustant les DM).
      2. -
      3. Bouclier psi : ajouter un pr\xE9dicat bouclierPsi.
      4. -
      5. Attaque \xE9tourdissante : faire une attaque mentale, avec les options --avecd12 --if moins niveau --if etatCible bouclierPsi --effet etourdi 1 --save CHA [[8+@{selected|CHA}]] --else --effet etourdi 1 --endif --endif --mana 1.
      6. +
      7. Attaque mentale : faire 2 attaques, une pour les DMs létaux, avec les options --sortilege --attaqueMentale --mana 0 et l'autre avec l'option supplémentaire --tempDmg (et en ajustant les DM).
      8. +
      9. Bouclier psi : ajouter un prédicat bouclierPsi.
      10. +
      11. Attaque étourdissante : faire une attaque mentale, avec les options --avecd12 --if moins niveau --if etatCible bouclierPsi --effet etourdi 1 --save CHA [[8+@{selected|CHA}]] --else --effet etourdi 1 --endif --endif --mana 1.
      12. Vague psionique : faire les attaques mentales sur toutes les cibles. En cas d'utilisation avec la Mana, le plus simple est de faire deux ability :
          -
        • !cof-lancer-sort lance une vague psychique --mana 2 qui lance le sort (pratique pour y mettre votre d\xE9pense de Mana unique)
        • -
        • Une ability qui permet de faire une attaque mentale (sans d\xE9pense de Mana)
        • +
        • !cof-lancer-sort lance une vague psychique --mana 2 qui lance le sort (pratique pour y mettre votre dépense de Mana unique)
        • +
        • Une ability qui permet de faire une attaque mentale (sans dépense de Mana)
      13. -
      14. Ego h\xE9ro\xEFque : reporter les bonus sur la fiche
      15. +
      16. Ego héroïque : reporter les bonus sur la fiche
      -

      Voie du contr\xF4le corporel

      +

      Voie du contrôle corporel

        -
      1. Proprioception : ajouter les PVs sur la fiche, et ajouter un pr\xE9dicat proprioception.
      2. -
      3. Transe de r\xE9g\xE9n\xE9ration : ajoutez une ability !cof-soin @{selected|token_id} 1d6+[[@{selected|niveau} + @{selected|CHA}]] --limiteParJour rang --mana 0 --message entre en transe de r\xE9g\xE9n\xE9ration pour [[2d6]] tours.
      4. -
      5. Contr\xF4le du m\xE9tabolisme : ajouter un pr\xE9dicat controleDuMetabolisme. Ne pas modifier l'initiative, le bonus de charisme sera pris en compte par le script.
      6. -
      7. Contr\xF4le sanguin : ajouter un pr\xE9dicat controleSanguin. Le script immunise aux poison, aux effets saignements automatis\xE9s, et divise par deux les dommages des attaques avec --vampirise.
      8. +
      9. Proprioception : ajouter les PVs sur la fiche, et ajouter un prédicat proprioception.
      10. +
      11. Transe de régénération : ajoutez une ability !cof-soin @{selected|token_id} 1d6+[[@{selected|niveau} + @{selected|CHA}]] --limiteParJour rang --mana 0 --message entre en transe de régénération pour [[2d6]] tours.
      12. +
      13. Contrôle du métabolisme : ajouter un prédicat controleDuMetabolisme. Ne pas modifier l'initiative, le bonus de charisme sera pris en compte par le script.
      14. +
      15. Contrôle sanguin : ajouter un prédicat controleSanguin. Le script immunise aux poison, aux effets saignements automatisés, et divise par deux les dommages des attaques avec --vampirise.

      Voie de l'empathie

        -
      1. Perception extra-sensorielle : ajuster l'initiative et ajouter le bonus \xE0 une comp\xE9tence perception (pour les jets).
      2. -
      3. D\xE9fense intuitive : ajouter un pr\xE9dicat defenseIntuitive. Ne pas modifier la DEF sur la fiche, la sagesse sera automatiquement prise en compte.
      4. -
      5. Perception du pass\xE9 : !cof-lancer-sort tente de percevoir le pass\xE9 --mana 1 pour lancer le sort. On peut faire le jet en utilisant !cof-jet SAG 15.
      6. -
      7. Vision lointaine : pas de support autre que !cof-lancer-sort projette son esprit \xE0 grande distance --mana 2. Utiliser !cof-jet SAG pour les jets de sagesse.
      8. -
      9. Perception h\xE9ro\xEFque : reporter les bonus sur la fiche
      10. +
      11. Perception extra-sensorielle : ajuster l'initiative et ajouter le bonus à une compétence perception (pour les jets).
      12. +
      13. Défense intuitive : ajouter un prédicat defenseIntuitive. Ne pas modifier la DEF sur la fiche, la sagesse sera automatiquement prise en compte.
      14. +
      15. Perception du passé : !cof-lancer-sort tente de percevoir le passé --mana 1 pour lancer le sort. On peut faire le jet en utilisant !cof-jet SAG 15.
      16. +
      17. Vision lointaine : pas de support autre que !cof-lancer-sort projette son esprit à grande distance --mana 2. Utiliser !cof-jet SAG pour les jets de sagesse.
      18. +
      19. Perception héroïque : reporter les bonus sur la fiche
      -

      Voie de la t\xE9l\xE9kin\xE9sie

      +

      Voie de la télékinésie

        -
      1. Manipulation \xE0 distance : pour les attaques \xE0 distance, le plus simple est d'utiliser une autre attaque en utilisant le score d'attaque magique et le bon modificateur de DMs.
      2. -
      3. Champ de protection : pour l'effet de base, si vous suivez les r\xE8gles, ajustez simplement la DEF sur la fiche. Si vous pr\xE9f\xE9rez en faire un sort, vous pouvez utiliser la commande !cof-effet-temp champDeProtection [[5+@{selected|CHA}]]. La valeur par d\xE9faut est celle d'un pr\xE9dicat voieDeLaTelekinesie, et pour utiliser une autre valeur, on peut utiliser l'option --valeur. Pour le champ \xE0 distance, faire !cof-effet-temp champDeProtection 1 --lanceur @{selected|token_id} --portee 10 --valeur n --target @{target|token_id}.
      4. +
      5. Manipulation à distance : pour les attaques à distance, le plus simple est d'utiliser une autre attaque en utilisant le score d'attaque magique et le bon modificateur de DMs.
      6. +
      7. Champ de protection : pour l'effet de base, si vous suivez les règles, ajustez simplement la DEF sur la fiche. Si vous préférez en faire un sort, vous pouvez utiliser la commande !cof-effet-temp champDeProtection [[5+@{selected|CHA}]]. La valeur par défaut est celle d'un prédicat voieDeLaTelekinesie, et pour utiliser une autre valeur, on peut utiliser l'option --valeur. Pour le champ à distance, faire !cof-effet-temp champDeProtection 1 --lanceur @{selected|token_id} --portee 10 --valeur n --target @{target|token_id}.
      8. Onde de choc :
          -
        • Sort : Ajouter une attaque sur la fiche dommages 1d8+CHA, port\xE9e 0, type Sortil\xE8ge, modificateurs auto, options --mana 1 --disque ?{Port\xE9e (max 10) ?|10} --etat renverse --save FOR [[10+@{selected|CHA}]] --targetFx explode-magic. D\xE9cochez cette attaque, et appelez la dans une action qui fait !cof-explosion l o\xF9 i est le label de l'attaque.
        • -
        • Objet de sort : !cof-explosion Onde de choc --auto --dm 1d8+[[@{selected|SAG}]] --portee 0 --sortilege --disque ?{Port\xE9e (max 10) ?|10} --etat renverse --save FOR [[10+@{selected|CHA}]] --targetFx explode-magic
        • +
        • Sort : Ajouter une attaque sur la fiche dommages 1d8+CHA, portée 0, type Sortilège, modificateurs auto, options --mana 1 --disque ?{Portée (max 10) ?|10} --etat renverse --save FOR [[10+@{selected|CHA}]] --targetFx explode-magic. Décochez cette attaque, et appelez la dans une action qui fait !cof-explosion li est le label de l'attaque.
        • +
        • Objet de sort : !cof-explosion Onde de choc --auto --dm 1d8+[[@{selected|SAG}]] --portee 0 --sortilege --disque ?{Portée (max 10) ?|10} --etat renverse --save FOR [[10+@{selected|CHA}]] --targetFx explode-magic
      9. -
      10. Combat kin\xE9tique : cr\xE9er un pr\xE9dicat combatKinetique. Cela appliquera automatiquement la RD dans tous les cas o\xF9 le personnage est attaqu\xE9 par un adversaire et qu'il est conscient. Pour l'augmentation des dommages, reporter sur les attaques sur la fiche.
      11. -
      12. Psychoportation : !cof-lancer-sort s'\xE9l\xE8ve dans les airs pendant [[5+@{selected|INT}]] tours --mana 3. Passer la FOR en caract\xE9ristique sup\xE9rieure via la fiche.
      13. +
      14. Combat kinétique : créer un prédicat combatKinetique. Cela appliquera automatiquement la RD dans tous les cas où le personnage est attaqué par un adversaire et qu'il est conscient. Pour l'augmentation des dommages, reporter sur les attaques sur la fiche.
      15. +
      16. Psychoportation : !cof-lancer-sort s'élève dans les airs pendant [[5+@{selected|INT}]] tours --mana 3. Passer la FOR en caractéristique supérieure via la fiche.
      -

      Voie de la t\xE9l\xE9pathie

      +

      Voie de la télépathie

        -
      1. T\xE9l\xE9pathie : pas de support autre que !cof-lancer-sort communique par t\xE9l\xE9pathie pendant [[5+@{selected|SAG}]] tours --mana 0
      2. -
      3. Radar mental : ajouter un pr\xE9dicat radarMental, de valeur le bonus procur\xE9 par le radar mental (2 fois le rang dans la voie). En cas de surprise provoqu\xE9e par quelque chose de non-vivant penser \xE0 utiliser l'option --nonVivant dans !cof-surprise.
      4. -
      5. Suggestion : Ajouter une attaque sur la fiche utilisant l'attaque magique, port\xE9e 20, type Sortil\xE8ge, modificateurs pasDeDmg, difficultePVmax, attaqueMentale, options --si moins niveau --if touche --message la cible doit faire l'action sugg\xE9r\xE9e --endif.
      6. -
      7. Lire les pens\xE9es: faire une attaque de type sortil\xE8ge, port\xE9e 10 m, avec l'option --difficulteCarac SAG --if touche --message lit les pens\xE9es de @{target|token_name} pendant [[1d6+@{selected|SAG}]] tours --endif.
      8. -
      9. Domination psy : faire une attaque de type sortil\xE8ge, port\xE9e 20 m, avec les modificateurs dominationPsy, attaqueMentale et pasDeDmg.
      10. +
      11. Télépathie : pas de support autre que !cof-lancer-sort communique par télépathie pendant [[5+@{selected|SAG}]] tours --mana 0
      12. +
      13. Radar mental : ajouter un prédicat radarMental, de valeur le bonus procuré par le radar mental (2 fois le rang dans la voie). En cas de surprise provoquée par quelque chose de non-vivant penser à utiliser l'option --nonVivant dans !cof-surprise.
      14. +
      15. Suggestion : Ajouter une attaque sur la fiche utilisant l'attaque magique, portée 20, type Sortilège, modificateurs pasDeDmg, difficultePVmax, attaqueMentale, options --si moins niveau --if touche --message la cible doit faire l'action suggérée --endif.
      16. +
      17. Lire les pensées: faire une attaque de type sortilège, portée 10 m, avec l'option --difficulteCarac SAG --if touche --message lit les pensées de @{target|token_name} pendant [[1d6+@{selected|SAG}]] tours --endif.
      18. +
      19. Domination psy : faire une attaque de type sortilège, portée 20 m, avec les modificateurs dominationPsy, attaqueMentale et pasDeDmg.
      -

      R\xF4deur

      +

      Rôdeur

      Voie de l'archer

        -
      1. Sens affut\xE9s : Cr\xE9ez un pr\xE9dicat sensAffutes. Cela va ajuster l'initiative (ne se voit pas sur la fiche), ainsi que les d\xE9g\xE2ts des arcs (attention \xE0 ne pas en plus le rajouter sur la fiche !). Ajoutez ensuite le bonus aux comp\xE9tences perception et vigilance (ou cr\xE9ez-les).
      2. +
      3. Sens affutés : Créez un prédicat sensAffutes. Cela va ajuster l'initiative (ne se voit pas sur la fiche), ainsi que les dégâts des arcs (attention à ne pas en plus le rajouter sur la fiche !). Ajoutez ensuite le bonus aux compétences perception et vigilance (ou créez-les).
      4. Tir aveugle : utiliser une attaque avec l'option --tirAveugle.
      5. Tir rapide : faire simplement deux attaques dans le tour
      6. -
      7. Fl\xE8che de mort : faire l'attaque avec les options --m2d20 --incrDmgCoef
      8. +
      9. Flèche de mort : faire l'attaque avec les options --m2d20 --incrDmgCoef
      10. Dans le mille : faire l'attaque avec les options --avecd12crit --plus 2d6

      Voie du compagnon animal

        -
      1. Odorat : ajouter une comp\xE9tence pistage, de valeur 5 (ou augment\xE9e de 5)
      2. -
      3. Surveillance : ajouter un pr\xE9dicat surveillance, avec comme valeur le nom du compagnon (doit \xEAtre exactement le m\xEAme que celui du token du compagnon). Cela automatise l'initiative et le bonus aux jets de surprise, le reste se g\xE8re manuellement
      4. -
      5. Combat : ajouter le loup sous contr\xF4le du joueur. Si vous souhaitez que le loup rentre en combat \xE0 chaque fois que le r\xF4deur entre en combat, ajoutez au r\xF4deur un pr\xE9dicat nomm\xE9 entrerEnCombatAvec, de valeur le nom du token du loup.
      6. +
      7. Odorat : ajouter une compétence pistage, de valeur 5 (ou augmentée de 5)
      8. +
      9. Surveillance : ajouter un prédicat surveillance, avec comme valeur le nom du compagnon (doit être exactement le même que celui du token du compagnon). Cela automatise l'initiative et le bonus aux jets de surprise, le reste se gère manuellement
      10. +
      11. Combat : ajouter le loup sous contrôle du joueur. Si vous souhaitez que le loup rentre en combat à chaque fois que le rôdeur entre en combat, ajoutez au rôdeur un prédicat nommé entrerEnCombatAvec, de valeur le nom du token du loup.
      12. Empathie animale : pour soigner, utiliser !cof-soin @{selected|token_id} nom_familier ?{Montant des soins} --transfer
      13. -
      14. Animal fabuleux : ajuster les caract\xE9ristiques du loup
      15. +
      16. Animal fabuleux : ajuster les caractéristiques du loup

      Voie de l'escarmouche

        -
      1. Chasseur \xE9m\xE9rite : ajouter un pr\xE9dicat chasseurEmerite. Puis, si dans le profil (attribut profil) de la cible, il y a animal (ou si la cible a un pr\xE9dicat animal), le bonus s'applique. Ajouter aussi le bonus \xE0 une comp\xE9tence pistage.
      2. -
      3. Traquenard : ajouter un pr\xE9dicat traquenard, puis option --traquenard pour l'attaque. Pour une utilisation pratique, le mieux est de faire une attaque d'arme en main avec l'option : #Attaque -1 --traquenard.
      4. -
      5. Attaque \xE9clair : --plus [[@{selected|DEX}]] --bonusAttaque [[@{selected|DEX}]]
      6. -
      7. Repli : simplement faire un jet en utilisant par exemple !cof-jet DEX 10, et d\xE9crire le r\xE9sultat.
      8. -
      9. Dext\xE9rit\xE9 h\xE9ro\xEFque : reporter sur la fiche.
      10. +
      11. Chasseur émérite : ajouter un prédicat chasseurEmerite. Puis, si dans le profil (attribut profil) de la cible, il y a animal (ou si la cible a un prédicat animal), le bonus s'applique. Ajouter aussi le bonus à une compétence pistage.
      12. +
      13. Traquenard : ajouter un prédicat traquenard, puis option --traquenard pour l'attaque. Pour une utilisation pratique, le mieux est de faire une attaque d'arme en main avec l'option : #Attaque -1 --traquenard.
      14. +
      15. Attaque éclair : --plus [[@{selected|DEX}]] --bonusAttaque [[@{selected|DEX}]]
      16. +
      17. Repli : simplement faire un jet en utilisant par exemple !cof-jet DEX 10, et décrire le résultat.
      18. +
      19. Dextérité héroïque : reporter sur la fiche.

      Voie de la survie

        -
      1. Endurant : ajouter une comp\xE9tence survie, de caract\xE9ristique CON, avec le bonus 2xrang dans la Voie.
      2. -
      3. Nature nourrici\xE8re : pour la recherche d'herbes, ajouter un pr\xE9dicat voieDeLaSurvie avec comme valeur le rang du personnage dans la voie. On peut utiliser !cof-nature-nourriciere pour lancer la recherche. Cela cr\xE9e automatiquement les doses de plantes m\xE9dicinales dans les consommables du personnage. Ces doses sont supprim\xE9es toutes les nuits. Pour les besoins d'un personnage, j'ai aussi donn\xE9 la possibilit\xE9 de trouver des baies magiques \xE0 la place des herbes m\xE9dicinales. Pour cela, il faut un pr\xE9dicat natureNourriciereBaies.
      4. -
      5. Grand pas : ajouter les comp\xE9tences natation et escalade, de valeur 5.
      6. -
      7. Increvable : ajouter un pr\xE9dicat increvable.
      8. -
      9. Constitution h\xE9ro\xEFque : reporter les bonus sur la fiche
      10. +
      11. Endurant : ajouter une compétence survie, de caractéristique CON, avec le bonus 2xrang dans la Voie.
      12. +
      13. Nature nourricière : pour la recherche d'herbes, ajouter un prédicat voieDeLaSurvie avec comme valeur le rang du personnage dans la voie. On peut utiliser !cof-nature-nourriciere pour lancer la recherche. Cela crée automatiquement les doses de plantes médicinales dans les consommables du personnage. Ces doses sont supprimées toutes les nuits. Pour les besoins d'un personnage, j'ai aussi donné la possibilité de trouver des baies magiques à la place des herbes médicinales. Pour cela, il faut un prédicat natureNourriciereBaies.
      14. +
      15. Grand pas : ajouter les compétences natation et escalade, de valeur 5.
      16. +
      17. Increvable : ajouter un prédicat increvable.
      18. +
      19. Constitution héroïque : reporter les bonus sur la fiche

      Voie du traqueur

        -
      1. Pas de loup : ajouter le bonus \xE0 une comp\xE9tence discr\xE9tion.
      2. -
      3. Ennemi jur\xE9 : ajouter un pr\xE9dicat ennemiJure avec comme valeur la race des ennemis. Cette race doit se retrouver dans le champ race de l'ennemi. Le script reconnait aussi le type mort-vivant (tout en minuscules) et dans ce cas va d\xE9terminer si la cible est un mort-vivant (pr\xE9dicat mortVivant ou race reconnue comme mort-vivant), ainsi que le type g\xE9ant (pour les g\xE9ants, ogres, trolls, etc.) et le type gobelin.
      4. +
      5. Pas de loup : ajouter le bonus à une compétence discrétion.
      6. +
      7. Ennemi juré : ajouter un prédicat ennemiJure avec comme valeur la race des ennemis. Cette race doit se retrouver dans le champ race de l'ennemi. Le script reconnait aussi le type mort-vivant (tout en minuscules) et dans ce cas va déterminer si la cible est un mort-vivant (prédicat mortVivant ou race reconnue comme mort-vivant), ainsi que le type géant (pour les géants, ogres, trolls, etc.) et le type gobelin.
      8. Embuscade : en cas d'attaque sur les ennemis, les mettre tous surpris avec la commande !cof-set-state surpris true
      9. -
      10. Second ennemi jur\xE9 : on peut renseigner une seconde race dans un nouveau pr\xE9dicat ennemiJure, ou alors le rajouter au pr\xE9dicat ennemiJure pr\xE9c\xE9dant, en la s\xE9parant de la premi\xE8re par une virgule (exemple : ennemiJure:: orque, araign\xE9e, sans rien ensuite sur la ligne)
      11. -
      12. Perception h\xE9ro\xEFque : reporter les bonus sur la fiche
      13. +
      14. Second ennemi juré : on peut renseigner une seconde race dans un nouveau prédicat ennemiJure, ou alors le rajouter au prédicat ennemiJure précédant, en la séparant de la première par une virgule (exemple : ennemiJure:: orque, araignée, sans rien ensuite sur la ligne)
      15. +
      16. Perception héroïque : reporter les bonus sur la fiche
      -

      Samoura\xEF

      +

      Samouraï

      Voie de l'arc et du cheval

        -
      1. Monture loyale : ajouter un pr\xE9dicat montureLoyale. Pour la monture, il faut faire un personnage avec un pr\xE9dicat monture. Pour monter sur la monture, utiliser !cof-en-selle @{selected|token_id} nom_de_la_monture, et pour en descendre, il suffit de faire la m\xEAme commande (utiliser une ability "token action" rend cela assez facile \xE0 l'usage).
      2. +
      3. Monture loyale : ajouter un prédicat montureLoyale. Pour la monture, il faut faire un personnage avec un prédicat monture. Pour monter sur la monture, utiliser !cof-en-selle @{selected|token_id} nom_de_la_monture, et pour en descendre, il suffit de faire la même commande (utiliser une ability "token action" rend cela assez facile à l'usage).
      4. Tir en mouvement : pas de support particulier.
      5. -
      6. Tir fatal : ajouter un pr\xE9dicat tirFatal. Pour tenir compte du bonus suppl\xE9mentaire avec le rang dans la voie, ajouter un pr\xE9dicat voieDeLArcEtDuCheval de valeur le rang atteint dans cette voie. Si vous souhaitez que cette capacit\xE9 s'applique \xE0 une autre classe d'arme que les arcs, vous pouvez associer ce nom au pr\xE9dicat tirfatal (attention, sans accent). Par exemple, pour les arbal\xE8tes, tirFatal:arbalete.
      7. +
      8. Tir fatal : ajouter un prédicat tirFatal. Pour tenir compte du bonus supplémentaire avec le rang dans la voie, ajouter un prédicat voieDeLArcEtDuCheval de valeur le rang atteint dans cette voie. Si vous souhaitez que cette capacité s'applique à une autre classe d'arme que les arcs, vous pouvez associer ce nom au prédicat tirfatal (attention, sans accent). Par exemple, pour les arbalètes, tirFatal:arbalete.

      Voie du dirigeant

        -
      1. \xC9duqu\xE9 : simplement noter les bonus et comp\xE9tences sur la fiche.
      2. -
      3. Homme de cour : ajouter une comp\xE9tence \xE9tiquette, de valeur 5.
      4. -
      5. Lame de lign\xE9e : pas de support particulier pour l'arme, mais quand le samoura\xEF perd l'arme, vous pouvez utiliser la commande !cof-effet lameDeLigneePerdue true (avec le samoura\xEF s\xE9lectionn\xE9). Quand il la retrouve, utilisez !cof-effet lameDeLigneePerdue false.
      6. +
      7. Éduqué : simplement noter les bonus et compétences sur la fiche.
      8. +
      9. Homme de cour : ajouter une compétence étiquette, de valeur 5.
      10. +
      11. Lame de lignée : pas de support particulier pour l'arme, mais quand le samouraï perd l'arme, vous pouvez utiliser la commande !cof-effet lameDeLigneePerdue true (avec le samouraï sélectionné). Quand il la retrouve, utilisez !cof-effet lameDeLigneePerdue false.

      Voie de l'honneur

        -
      1. Chef n\xE9 : ajouter un pr\xE9dicat immunite_peur, et des comp\xE9tences pour l'intimidation et commander.
      2. -
      3. D\xE9fi : !cof-defi-samourai @{selected|token_id} @{target|token_id} bonus. Le bonus en argument est optionnel. S'il n'est pas pr\xE9sent, le script utilise la valeur d'un pr\xE9dicat voieDeLHonneur.
      4. +
      5. Chef né : ajouter un prédicat immunite_peur, et des compétences pour l'intimidation et commander.
      6. +
      7. Défi : !cof-defi-samourai @{selected|token_id} @{target|token_id} bonus. Le bonus en argument est optionnel. S'il n'est pas présent, le script utilise la valeur d'un prédicat voieDeLHonneur.
      8. Honorable : pas de support particulier.

      Voie du ki

        -
      1. Esprit vide : ajouter un pr\xE9dicat espritVide. Si vous voulez un boonus diff\xE9rent (par exemple \xE0 partir du rang 4 dans la voie), associez les bonus au pr\xE9dicat.
      2. -
      3. Main vide : faire l'attaque \xE0 mains nues correspondant \xE0 la capacit\xE9.
      4. -
      5. Kiai : ajouter un pr\xE9dicat kiai, de valeur 1. Au rang 5, mettre cette valeur \xE0 2, le script se charge d'attendre 1d6 tours avant de proposer le deuxi\xE8me kiai.
      6. -
      7. Course mortelle : !cof-attack-line @{selected|token_id} --distanceMax 10. L'attaque va \xEAtre faite avec l'arme en main, mais on peut sp\xE9cifier un label d'attaque (avant les options) et toutes les options support\xE9es par !cof-attack.
      8. +
      9. Esprit vide : ajouter un prédicat espritVide. Si vous voulez un boonus différent (par exemple à partir du rang 4 dans la voie), associez les bonus au prédicat.
      10. +
      11. Main vide : faire l'attaque à mains nues correspondant à la capacité.
      12. +
      13. Kiai : ajouter un prédicat kiai, de valeur 1. Au rang 5, mettre cette valeur à 2, le script se charge d'attendre 1d6 tours avant de proposer le deuxième kiai.
      14. +
      15. Course mortelle : !cof-attack-line @{selected|token_id} --distanceMax 10. L'attaque va être faite avec l'arme en main, mais on peut spécifier un label d'attaque (avant les options) et toutes les options supportées par !cof-attack.
      16. Puissance du ki : #Attaque -1 --avecd12crit --plus 2d6 --seulementContact.

      Voie du sabre

        -
      1. Technique du sabre : ajouter un pr\xE9dicat techniqueDuSabre, de valeur le rang dans la Voie.
      2. -
      3. Frappe du vide : ajouter un pr\xE9dicat frappeDuVide.
      4. -
      5. Lames Jumelles : faire les attaques avec le modificateur lamesJumelles permet de prendre en compte la force courante de l'attaquant pour les malus \xE9ventuels \xE0 l'attaque. Comme le samoura\xEF va par d\xE9faut commencer le combat les mains vides, et qu'avec cette capacit\xE9 il voudra certainement d\xE9gainer \xE0 la fois le katana et le wakizachi, on peut utiliser un pr\xE9dicat pour lui faciliter la t\xE2che : si le label du katana est 5 et celui du wakizachi par exemple 3, ajouter un pr\xE9dicat actionDegainer1:5-3 (de cette fa\xE7on, le fait de d\xE9gainer le katana et le wakizachi sera en t\xEAte de liste).
      6. +
      7. Technique du sabre : ajouter un prédicat techniqueDuSabre, de valeur le rang dans la Voie.
      8. +
      9. Frappe du vide : ajouter un prédicat frappeDuVide.
      10. +
      11. Lames Jumelles : faire les attaques avec le modificateur lamesJumelles permet de prendre en compte la force courante de l'attaquant pour les malus éventuels à l'attaque. Comme le samouraï va par défaut commencer le combat les mains vides, et qu'avec cette capacité il voudra certainement dégainer à la fois le katana et le wakizachi, on peut utiliser un prédicat pour lui faciliter la tâche : si le label du katana est 5 et celui du wakizachi par exemple 3, ajouter un prédicat actionDegainer1:5-3 (de cette façon, le fait de dégainer le katana et le wakizachi sera en tête de liste).

      Voleur

      Voie de l'assassin

        -
      1. Discr\xE9tion : ajouter une comp\xE9tence discr\xE9tion sur la fiche, avec le bon bonus.
      2. -
      3. Attaque sournoise : Ajouter un pr\xE9dicat attaqueSournoise, de valeur le nombre de d\xE9s de l'attaque sournoise. Ensuite, faire des versions des attaques avec --sournoise. Au MJ de v\xE9rifier que les conditions de l'attaque sournoise sont remplies. Le plus pratique pour l'utilisation avec diff\xE9rentes armes, est d'ajouter \xE0 la liste des actions du tour une action de titre Attaque sournoise et de code #Attaque -1 --sournoise.
      4. -
      5. Ombre mouvante : utiliser la commande !cof-ombre-mouvante --fx burst-smoke (la partie --fx burst-smoke peut \xEAtre omise ou chang\xE9e, bien s\xFBr). Le script ne g\xE8re pas encore l'attaque sournoise qui peut suivre, au MJ de surveiller l'initiative du voleur par rapport \xE0 sa cible.
      6. -
      7. Surprise : ajouter un pr\xE9dicat immunite_surpris. Pour le reste, \xE0 g\xE9rer par le MJ.
      8. -
      9. Ouverture mortelle : ajouter les options --ouvertureMortelle --limiteParCombat 1 ouvertureMortelle --sournoise. Selon les indications de Kegron, ne mettre la partie --sournoise que si les conditions s'y pr\xEAtent (dans le dos, surprise, acrobatie, etc).
      10. +
      11. Discrétion : ajouter une compétence discrétion sur la fiche, avec le bon bonus.
      12. +
      13. Attaque sournoise : Ajouter un prédicat attaqueSournoise, de valeur le nombre de dés de l'attaque sournoise. Ensuite, faire des versions des attaques avec --sournoise. Au MJ de vérifier que les conditions de l'attaque sournoise sont remplies. Le plus pratique pour l'utilisation avec différentes armes, est d'ajouter à la liste des actions du tour une action de titre Attaque sournoise et de code #Attaque -1 --sournoise.
      14. +
      15. Ombre mouvante : utiliser la commande !cof-ombre-mouvante --fx burst-smoke (la partie --fx burst-smoke peut être omise ou changée, bien sûr). Le script ne gère pas encore l'attaque sournoise qui peut suivre, au MJ de surveiller l'initiative du voleur par rapport à sa cible.
      16. +
      17. Surprise : ajouter un prédicat immunite_surpris. Pour le reste, à gérer par le MJ.
      18. +
      19. Ouverture mortelle : ajouter les options --ouvertureMortelle --limiteParCombat 1 ouvertureMortelle --sournoise. Selon les indications de Kegron, ne mettre la partie --sournoise que si les conditions s'y prêtent (dans le dos, surprise, acrobatie, etc).

      Voie de l'aventurier

        -
      1. Sprint : Pour v\xE9rifier que ce n'est bien utilis\xE9 qu'une fois par combat, on pourra utiliser !cof-lancer-sort pousse un sprint --limiteParCombat 1 sprint.
      2. -
      3. Provocation : !cof-provocation @{selected|token_id} @{target|token_id}. Au joueur ensuite de faire son attaque gratuite si la provocation est r\xE9ussie et que l'adversaire l'attaque.
      4. -
      5. Gr\xE2ce f\xE9line : ajouter un pr\xE9dicat graceFeline. Cela va affecter l'initiative et la DEF, mais sans se voir sur la fiche. Pour les tests de d\xE9placement, ajouter un pr\xE9dicat graceFelineVoleur (penser \xE0 proposer l'utilisation de comp\xE9tences, en ajoutant les comp\xE9tences course, saut, acrobatie et escalade au voleur ou sur le handout de comp\xE9tences).
      6. +
      7. Sprint : Pour vérifier que ce n'est bien utilisé qu'une fois par combat, on pourra utiliser !cof-lancer-sort pousse un sprint --limiteParCombat 1 sprint.
      8. +
      9. Provocation : !cof-provocation @{selected|token_id} @{target|token_id}. Au joueur ensuite de faire son attaque gratuite si la provocation est réussie et que l'adversaire l'attaque.
      10. +
      11. Grâce féline : ajouter un prédicat graceFeline. Cela va affecter l'initiative et la DEF, mais sans se voir sur la fiche. Pour les tests de déplacement, ajouter un prédicat graceFelineVoleur (penser à proposer l'utilisation de compétences, en ajoutant les compétences course, saut, acrobatie et escalade au voleur ou sur le handout de compétences).
      -

      Voie du d\xE9placement

      +

      Voie du déplacement

        -
      1. Esquive : Ajouter un pr\xE9dicat esquiveVoleur, de valeur le rang dans la voie. Ne pas modifier la DEF sur la fiche, le script fera les ajustements (et montrera le total avec !cof-statut).
      2. +
      3. Esquive : Ajouter un prédicat esquiveVoleur, de valeur le rang dans la voie. Ne pas modifier la DEF sur la fiche, le script fera les ajustements (et montrera le total avec !cof-statut).
      4. Chute : pas de support particulier.
      5. -
      6. Acrobaties : faire !cof-jet DEX 15 --nom acrobatie pour le jet de dext\xE9rit\xE9, le reste est g\xE9r\xE9 par le MJ. Il est possible d'automatiser quand le personnage d\xE9cide de faire une attaque quel que soit le r\xE9sultat du jet d'acrobatie grace \xE0 la commande #Attaque -1 --attaqueAcrobatique.
      7. -
      8. Esquive de la magie : ajouter un pr\xE9dicat esquiveDeLaMagie.
      9. -
      10. Dext\xE9rit\xE9 h\xE9ro\xEFque : ajouter les bonus sur la fiche
      11. +
      12. Acrobaties : faire !cof-jet DEX 15 --nom acrobatie pour le jet de dextérité, le reste est géré par le MJ. Il est possible d'automatiser quand le personnage décide de faire une attaque quel que soit le résultat du jet d'acrobatie grace à la commande #Attaque -1 --attaqueAcrobatique.
      13. +
      14. Esquive de la magie : ajouter un prédicat esquiveDeLaMagie.
      15. +
      16. Dextérité héroïque : ajouter les bonus sur la fiche

      Voie du roublard

        -
      1. Doigts agiles : utiliser des comp\xE9tences sur la fiche de personnage
      2. -
      3. D\xE9tecter les pi\xE8ges : faire le jet avec !cof-jet INT ?{Pi\xE8ge normal?|Oui,10|Magique,15} --secret
      4. -
      5. Croc-en-jambe : ajouter un pr\xE9dicat crocEnJambe. Pour distinguer les adversaires quadrup\xE8des qui ne seraient pas connues du script, lui ajouter un pr\xE9dicat quadrupede. Les adversaires avec un pr\xE9dicat volant ne seront pas affect\xE9s.
      6. +
      7. Doigts agiles : utiliser des compétences sur la fiche de personnage
      8. +
      9. Détecter les pièges : faire le jet avec !cof-jet INT ?{Piège normal?|Oui,10|Magique,15} --secret
      10. +
      11. Croc-en-jambe : ajouter un prédicat crocEnJambe. Pour distinguer les adversaires quadrupèdes qui ne seraient pas connues du script, lui ajouter un prédicat quadrupede. Les adversaires avec un prédicat volant ne seront pas affectés.
      12. Attaque paralysante : lancer une des attaques de contact du voleur en rajoutant les options --limiteParCombat 1 attaqueParalysante --pasDeDmg --effet paralysieRoublard [[1d4]].
      13. -
      14. Attaque en tra\xEEtre : Ajouter un pr\xE9dicat attaqueEnTraitre. Les actions affich\xE9es en cas d'attaque en tra\xEEtre seront par d\xE9faut une attaque avec l'arme en main et les attaques naturelles de la fiche coch\xE9es. Si cela ne convient pas, vous pouvez cr\xE9er une liste d'actions nomm\xE9e Attaques en traitre contenant les attaques possibles pour l'attaque en tra\xEEtre.
      15. +
      16. Attaque en traître : Ajouter un prédicat attaqueEnTraitre. Les actions affichées en cas d'attaque en traître seront par défaut une attaque avec l'arme en main et les attaques naturelles de la fiche cochées. Si cela ne convient pas, vous pouvez créer une liste d'actions nommée Attaques en traitre contenant les attaques possibles pour l'attaque en traître.

      Voie du spadassin

      1. Attaque en finesse : faire les modifications sur la fiche
      2. -
      3. Esquive fatale : Ajouter un pr\xE9dicat esquiveFatale (on peut y associer un nombre pour permettre plus d'une utilisation par combat). En combat, si la situation s'y pr\xEAte, un bouton permettre d'utiliser l'esquive. Ne pas oublier de d\xE9finir les alli\xE9s du voleur pour que la v\xE9rification des cibles soit correcte.
      4. -
      5. Frappe chirurgicale : ajouter un pr\xE9dicat frappeChirurgicale.
      6. -
      7. Ambidextrie : pas g\xE9r\xE9 par le script.
      8. -
      9. Botte secr\xE8te : ajouter un pr\xE9dicat botteSecrete. Ne pas oublier le pr\xE9dicat attaqueSournoise qui doit \xEAtre associ\xE9 au nombre de d\xE9s des attaques sournoises du voleur.
      10. +
      11. Esquive fatale : Ajouter un prédicat esquiveFatale (on peut y associer un nombre pour permettre plus d'une utilisation par combat). En combat, si la situation s'y prête, un bouton permettre d'utiliser l'esquive. Ne pas oublier de définir les alliés du voleur pour que la vérification des cibles soit correcte.
      12. +
      13. Frappe chirurgicale : ajouter un prédicat frappeChirurgicale.
      14. +
      15. Ambidextrie : pas géré par le script.
      16. +
      17. Botte secrète : ajouter un prédicat botteSecrete. Ne pas oublier le prédicat attaqueSournoise qui doit être associé au nombre de dés des attaques sournoises du voleur.
    -

    4. Autres capacit\xE9s

    +

    4. Autres capacités

    -

    4.1 Voies et capacit\xE9s raciales

    +

    4.1 Voies et capacités raciales

    - Quelques capacit\xE9s communes \xE0 plusieurs races : + Quelques capacités communes à plusieurs races :
      -
    • Vision dans le noir : ajoutez un pr\xE9dicat visionDansLeNoir de valeur le nombre de metres \xE0 laquelle le personnage peut voir dans le noir. Le script va adapter la vison dans le noir \xE0 l'unit\xE9 de mesure utilis\xE9e sur la page o\xF9 le token du personnage est cr\xE9\xE9.
    • +
    • Vision dans le noir : ajoutez un prédicat visionDansLeNoir de valeur le nombre de metres à laquelle le personnage peut voir dans le noir. Le script va adapter la vison dans le noir à l'unité de mesure utilisée sur la page où le token du personnage est créé.
    -

    \xC2me forg\xE9e

    -

    Pour les capacit\xE9s raciales, un pr\xE9dicat vieArtificielle permet de diviser tous les soins par 2. Pour la r\xE9sistance aux effets de drains, au feu et au froid, ajouter dans la RD sur la fiche drain:5, feu:5, froid:5. Pour l'immunit\xE9 aux poisons et maladies, utiliser un pr\xE9dicat creatureArtificielle. Enfin pour le saignement, ajouter un pr\xE9dicat immuniteSaignement.

    +

    Âme forgée

    +

    Pour les capacités raciales, un prédicat vieArtificielle permet de diviser tous les soins par 2. Pour la résistance aux effets de drains, au feu et au froid, ajouter dans la RD sur la fiche drain:5, feu:5, froid:5. Pour l'immunité aux poisons et maladies, utiliser un prédicat creatureArtificielle. Enfin pour le saignement, ajouter un prédicat immuniteSaignement.

      -
    1. Main lourde : ajuster les DM, et enlever l'option --tempDmg pour l'attaque \xE0 mains nues.
    2. +
    3. Main lourde : ajuster les DM, et enlever l'option --tempDmg pour l'attaque à mains nues.

    Demi-ogre

    • Vision dans le noir.
    • -
    • \xC9norme : pas de support, ajuster les attaques
    • -
    • Grande taille : quand le demi-ogre rentre dans une construction de taille humaine, utiliser !cof-effet constructionTailleHumaine true. \xC0 la sortie du b\xE2timent, !cof-effet constructionTailleHumaine false. Pour les espaces exigus, de m\xEAme avec l'effet espaceExigu.
    • -
    • R\xE9action violente : en cas de provocation, ex\xE9cuter !cof-effet-temp reactionViolente [[1d6]] --save SAG 10. On peut par exemple mettre ce code en ability li\xE9e au token. Au MJ et au joueur de g\xE9rer les actions qui s'ensuivent. Le script propose une action \xE0 l'ogre pour prendre sur lui \xE0 chaque tour.
    • +
    • Énorme : pas de support, ajuster les attaques
    • +
    • Grande taille : quand le demi-ogre rentre dans une construction de taille humaine, utiliser !cof-effet constructionTailleHumaine true. À la sortie du bâtiment, !cof-effet constructionTailleHumaine false. Pour les espaces exigus, de même avec l'effet espaceExigu.
    • +
    • Réaction violente : en cas de provocation, exécuter !cof-effet-temp reactionViolente [[1d6]] --save SAG 10. On peut par exemple mettre ce code en ability liée au token. Au MJ et au joueur de gérer les actions qui s'ensuivent. Le script propose une action à l'ogre pour prendre sur lui à chaque tour.
      -
    1. Sang-froid : ajouter un pr\xE9dicat sangFroid. Modifier la commande pour les provocations en !cof-effet-temp reactionViolente [[1d4]] --save SAG 5.
    2. -
    3. Violence cibl\xE9e : ajouter un pr\xE9dicat violenceCiblee.
    4. +
    5. Sang-froid : ajouter un prédicat sangFroid. Modifier la commande pour les provocations en !cof-effet-temp reactionViolente [[1d4]] --save SAG 5.
    6. +
    7. Violence ciblée : ajouter un prédicat violenceCiblee.

    Demi-orque

    Vision dans le noir.
    1. Force de la nature : ajouter les bonus sur la fiche
    2. -
    3. Talent pour la violence : voir les capacit\xE9s choisies
    4. +
    5. Talent pour la violence : voir les capacités choisies
    6. Critique brutal : pour l'instant, ajouter le modificateur incrCritCoef pour toutes les attaques au contact.
    7. Attaque sanglante : faire une attaque (ou liste d'attaques) avec les options --effet blessureQuiSaigne --saveParTour CON [[12 + @{selected|FOR}]]
    8. -
    9. Colosse : augmenter les caract\xE9ristiques sur la fiche.
    10. +
    11. Colosse : augmenter les caractéristiques sur la fiche.
    12. +
    +

    Drakonide

    +
      +
    1. Souffle : ajouter une attaque naturelle cochée, faisant des dégâts du type du drakonide, de portée 10 m, avec comme option --cone 30 --psave DEX 12 --tempsRecharge rechargeSouffle [[1d4]].
    2. +
    3. Intimidant : ajouter la compétence intimidation sur la fiche, avec un bonus de +5.
    4. +
    5. Écailles robustes : ajouter le bonus sur la fiche.
    6. +
    7. Fureur drakonide : ajouter un prédicat fureurDrakonide.
    8. +
    9. Héritage draconique : ajuster les caractéristiques sur la fiche.

    Elfe sylvain

      -
    1. Gr\xE2ce elfique : simplement reporter sur la fiche
    2. -
    3. Enfant de la for\xEAt : voir les capacit\xE9s choisies
    4. -
    5. Archer \xE9m\xE9rite : ajuster les chances de critique sur les attaques \xE0 l'arc
    6. -
    7. Fl\xE8che sanglante : faire une attaque (ou liste d'attaques) avec les options --effet blessureQuiSaigne --saveParTour CON [[12 + @{selected|DEX}]]
    8. -
    9. Sup\xE9riorit\xE9 elfique : augmenter les caract\xE9ristiques sur la fiche.
    10. +
    11. Grâce elfique : simplement reporter sur la fiche
    12. +
    13. Enfant de la forêt : voir les capacités choisies
    14. +
    15. Archer émérite : ajuster les chances de critique sur les attaques à l'arc
    16. +
    17. Flèche sanglante : faire une attaque (ou liste d'attaques) avec les options --effet blessureQuiSaigne --saveParTour CON [[12 + @{selected|DEX}]]
    18. +
    19. Supériorité elfique : augmenter les caractéristiques sur la fiche.
    -

    F\xE9e et lutin

    +

    Fée et lutin

    • Vision dans le noir.
    • -
    • Tout petit : ajouter un pr\xE9dicat toutPetit qui va automatiquement ajuster la d\xE9fense et les jets de discr\xE9tion.
    • -
    • Vol et T\xE9l\xE9portation : pas de support.
    • -
    • Trop petit : ajouter un pr\xE9dicat tropPetit. Cela va aussi changer les d\xE9g\xE2ts de base des armes (il vaut mieux laisser les vrais DM pour que la capacit\xE9 Grande taille fonctionne).
    • +
    • Tout petit : ajouter un prédicat toutPetit qui va automatiquement ajuster la défense et les jets de discrétion.
    • +
    • Vol et Téléportation : pas de support.
    • +
    • Trop petit : ajouter un prédicat tropPetit. Cela va aussi changer les dégâts de base des armes (il vaut mieux laisser les vrais DM pour que la capacité Grande taille fonctionne).
    1. Langage des animaux : aucun support
    2. -
    3. Invisibilit\xE9 : !cof-set-state invisible true --message se rend invisible --messageMJ l'invisibilit\xE9 va durer [[1d6+@{selected|INT}]] minutes --limiteParJour r o\xF9 r est le rang dans la Voie.
    4. -
    5. Monture f\xE9\xE9rique : ajouter un ersonnage pour la monture. Ajoutez-lui le pr\xE9dicat monture. Pour monter sur la monture, utiliser !cof-en-selle @{selected|token_id} nom_de_la_monture, et pour en descendre, il suffit de faire la m\xEAme commande (utiliser une ability "token action" rend cela assez facile \xE0 l'usage). Si vous souhaitez que la monture rentre en combat \xE0 chaque fois que l'\xEAtre f\xE9\xE9rique entre en combat, ajoutez \xE0 l'\xEAtre f\xE9\xE9rique un pr\xE9dicat nomm\xE9 entrerEnCombatAvec, de valeur le nom du token de la monture (pensez \xE0 utiliser la syntaxe avec :: si ce nom contient des caract\xE8res sp\xE9ciaux).
    6. -
    7. Grande taille : !cof-effet grandeTaille oui --lanceur @{selected|token_id} --limiteParJour 3 --messageMJ La taille humaine durera [[1d6+@{selected|CHA}]] minutes. Le script ne g\xE8re pas les dur\xE9es en minutes, le MJ devra penser \xE0 supprimer l'effet, par exemple depuis le statut (!cof-statut).
    8. +
    9. Invisibilité : !cof-set-state invisible true --message se rend invisible --messageMJ l'invisibilité va durer [[1d6+@{selected|INT}]] minutes --limiteParJour rr est le rang dans la Voie.
    10. +
    11. Monture féérique : ajouter un ersonnage pour la monture. Ajoutez-lui le prédicat monture. Pour monter sur la monture, utiliser !cof-en-selle @{selected|token_id} nom_de_la_monture, et pour en descendre, il suffit de faire la même commande (utiliser une ability "token action" rend cela assez facile à l'usage). Si vous souhaitez que la monture rentre en combat à chaque fois que l'être féérique entre en combat, ajoutez à l'être féérique un prédicat nommé entrerEnCombatAvec, de valeur le nom du token de la monture (pensez à utiliser la syntaxe avec :: si ce nom contient des caractères spéciaux).
    12. +
    13. Grande taille : !cof-effet grandeTaille oui --lanceur @{selected|token_id} --limiteParJour 3 --messageMJ La taille humaine durera [[1d6+@{selected|CHA}]] minutes. Le script ne gère pas les durées en minutes, le MJ devra penser à supprimer l'effet, par exemple depuis le statut (!cof-statut).
    -

    F\xE9lis

    +

    Félis

      -
    1. \xC2me f\xE9line : ajouter un pr\xE9dicat ameFeline, de valeur le rang dans la voie. Pensez \xE0 ajouter des comp\xE9tences pour le mouvement sur la fiche si ils ne sont pas d\xE9j\xE0 pr\xE9sent dans votre handout de comp\xE9tences.
    2. +
    3. Âme féline : ajouter un prédicat ameFeline, de valeur le rang dans la voie. Pensez à ajouter des compétences pour le mouvement sur la fiche si ils ne sont pas déjà présent dans votre handout de compétences.
    4. Armes naturelles :
        -
      • Cr\xE9ez une attaque "Griffes et crocs" naturelle de contact avec en DM 1d6 + Mod de FOR et les options --si etat armesNaturelles --message Attaque de ses griffes et crocs !.
      • +
      • Créez une attaque "Griffes et crocs" naturelle de contact avec en DM 1d6 + Mod de FOR et les options --si etat armesNaturelles --message Attaque de ses griffes et crocs !.
      • Pour faire sortir les griffes, dans l'onglet script, ajouter une action "Sortir/rentrer les griffes" faisant !cof-effet armesNaturelles.
    5. @@ -2018,49 +2030,50 @@

      F\xE9lis

      Gnome

      1. Petit pote : ajouter le bonus de CHA sur la fiche
      2. -
      3. Don occulte : se reporter aux capacit\xE9s choisies.
      4. -
      5. Insignifiant : ajouter un pr\xE9dicat insignifiant. +
      6. Don occulte : se reporter aux capacités choisies.
      7. +
      8. Insignifiant : ajouter un prédicat insignifiant. +
      +

      Gobelin

      +
        +
      • Vision dans le noir.
      • +
      • Attaque en meute : ajouter un prédicat attaqueEnMeute.
      • +
      • Petite taille : ajouter un prédicat petiteTaille pour ajouter les bonus de DEF et discrétion. Pour la limitation des armes, je préfère laisser le MJ vérifier.
      • +
      +
        +
      1. Rapide comme son ombre : ajouter un prédicat rapideCommeSonOmbre de valeur le bonus en discrétion et initiative.

      Halfelin

      -

      Petite taille : ajouter le bonus de DEF sur la ficher, et ajouter 2 \xE0 une comp\xE9tence discr\xE9tion.

      +

      Petite taille : ajouter un prédicat petiteTaille pour ajouter les bonus de DEF et discrétion. Pour la limitation des armes, je préfère laisser le MJ vérifier.

        -
      1. Petit veinard : ajouter un pr\xE9dicat petitVeinard (on peut y associer un nombre si on veut plus d'une utilisation par combat). Le script ne va automatiser que les relancer de d\xE9s d'attaque ou de jets de caract\xE9ristiques (et encore, pas tous). Il propose d'utiliser la chance \xE0 chaque attaque, m\xEAme r\xE9ussie, mais dans ce cas, c'est au joueur de relancer le d\xE9 concern\xE9, et au MJ d'en appliquer les cons\xE9quences.
      2. -
      3. R\xE9sistance l\xE9gendaire : ajouter le bonus en CON sur la fiche, et ajouter un pr\xE9dicat DEF_magie avec comme valeur 5.
      4. +
      5. Petit veinard : ajouter un prédicat petitVeinard (on peut y associer un nombre si on veut plus d'une utilisation par combat). Le script ne va automatiser que les relancer de dés d'attaque ou de jets de caractéristiques (et encore, pas tous). Il propose d'utiliser la chance à chaque attaque, même réussie, mais dans ce cas, c'est au joueur de relancer le dé concerné, et au MJ d'en appliquer les conséquences.
      6. +
      7. Résistance légendaire : ajouter le bonus en CON sur la fiche, et ajouter un prédicat DEF_magie avec comme valeur 5.

      Haut elfe

        -
      1. Gr\xE2ce elfique : ajouter les bonus sur la fiche
      2. -
      3. Talent pour la magie : voir les capacit\xE9s choisies
      4. -
      5. Force d'\xE2me : ajouter des pr\xE9dicat immunite_peur et immunite_endormi. Ajouter aussi des pr\xE9dicats DEF_magie et bonusSagesseMagie de valeur 5.
      6. +
      7. Grâce elfique : ajouter les bonus sur la fiche
      8. +
      9. Talent pour la magie : voir les capacités choisies
      10. +
      11. Force d'âme : ajouter des prédicat immunite_peur et immunite_endormi. Ajouter aussi des prédicats DEF_magie et bonusSagesseMagie de valeur 5.

      Humain

      -

      Instinct de survie : cr\xE9er un pr\xE9dicat instinctDeSurvieHumain.

      -
        -
      1. Adaptable : ajouter un pr\xE9dicat adaptable, de valeur le bonus en cas de test rat\xE9. Le script ne va appliquer le bonus que pour les tests avec difficult\xE9 identifi\xE9e. Le MJ devra l'appliquer dans les cas rat\xE9s par le script.
      2. -
      3. Loup parmi les loups : ajouter un pr\xE9dicat loupParmiLesLoups avec comme valeur 1 ou 2 selon le rang dans la voie. Une cr\xE9ature sera consid\xE9r\xE9e comme humano\xEFde si elle a un pr\xE9dicat humanoide, ou si sa race est reconnue comme humano\xEFde.
      4. -
      5. Versatile : se reporter \xE0 la capacit\xE9 choisie.
      6. -
      7. Increvable : ajouter un pr\xE9dicat increvableHumain.
      8. -
      -

      Drakonide

      +

      Instinct de survie : créer un prédicat instinctDeSurvieHumain.

        -
      1. Souffle : ajouter une attaque naturelle coch\xE9e, faisant des d\xE9g\xE2ts du type du drakonide, de port\xE9e 10 m, avec comme option --cone 30 --psave DEX 12 --tempsRecharge rechargeSouffle [[1d4]].
      2. -
      3. Intimidant : ajouter la comp\xE9tence intimidation sur la fiche, avec un bonus de +5.
      4. -
      5. \xC9cailles robustes : ajouter le bonus sur la fiche.
      6. -
      7. Fureur drakonide : ajouter un pr\xE9dicat fureurDrakonide.
      8. -
      9. H\xE9ritage draconique : ajuster les caract\xE9ristiques sur la fiche.
      10. +
      11. Adaptable : ajouter un prédicat adaptable, de valeur le bonus en cas de test raté. Le script ne va appliquer le bonus que pour les tests avec difficulté identifiée. Le MJ devra l'appliquer dans les cas ratés par le script.
      12. +
      13. Loup parmi les loups : ajouter un prédicat loupParmiLesLoups avec comme valeur 1 ou 2 selon le rang dans la voie. Une créature sera considérée comme humanoïde si elle a un prédicat humanoide, ou si sa race est reconnue comme humanoïde.
      14. +
      15. Versatile : se reporter à la capacité choisie.
      16. +
      17. Increvable : ajouter un prédicat increvableHumain.

      Lutin

      - Voir les f\xE9es. + Voir les fées.

      Minotaure

      • Vision dans le noir.
      • Coup de corne : ajouter simplement l'attaque.
      • -
      • Sens de l'orientation : utiliser une comp\xE9tence/
      • -
      • Grande taille : quand le minotaure rentre dans une construction de taille humaine, utiliser !cof-effet constructionTailleHumaine true. \xC0 la sortie du b\xE2timent, !cof-effet constructionTailleHumaine false. Pour les espaces exigus, de m\xEAme avec l'effet espaceExigu. Si on veut un seul bouton, enlever simplement l'argument true.
      • +
      • Sens de l'orientation : utiliser une compétence/
      • +
      • Grande taille : quand le minotaure rentre dans une construction de taille humaine, utiliser !cof-effet constructionTailleHumaine true. À la sortie du bâtiment, !cof-effet constructionTailleHumaine false. Pour les espaces exigus, de même avec l'effet espaceExigu. Si on veut un seul bouton, enlever simplement l'argument true.
        -
      1. Charge : #Attaque -1 --bonusAttaque 2 --plus 1d6. Le d\xE9placement n'est pas encore g\xE9r\xE9. Modifier les bonus si le minotaure poss\xE8de la capacit\xE9 Charge du barbare.
      2. -
      3. Fr\xE9n\xE9sie : On peut faire passer en fr\xE9n\xE9sie avec la commande !cof-effet-temp frenesieMinotaure [[1d6]]. Quand j'aurai le temps, il devrait \xEAtre possible de faire appara\xEEtre un bouton quand le minotaure est bless\xE9.
      4. +
      5. Charge : #Attaque -1 --deplaceDe 5 20 --bonusAttaque 2 --plus 1d6. Modifier les bonus si le minotaure possède la capacité Charge du barbare.
      6. +
      7. Frénésie : On peut faire passer en frénésie avec la commande !cof-effet-temp frenesieMinotaure [[1d6]]. Quand j'aurai le temps, il devrait être possible de faire apparaître un bouton quand le minotaure est blessé.
      8. Orientation infaillible : pas de support particulier.
      9. Encorner : pas de support particulier.
      10. Colosse : reporter sur la fiche.
      11. @@ -2070,137 +2083,137 @@

        Nain

      12. Vision dans le noir.
        1. -
        2. R\xE9sistance : ajouter les bonus sur la fiche
        3. +
        4. Résistance : ajouter les bonus sur la fiche
        5. Solide comme un roc : ajouter le texte 2/1 dans la RD sur la fiche.
        6. -
        7. Haches et marteaux : ajouter un pr\xE9dicat hachesEtMarteaux. Ne pas oublier de mettre le modificateur hache ou marteau pour les attaques qui sont concern\xE9es.
        8. +
        9. Haches et marteaux : ajouter un prédicat hachesEtMarteaux. Ne pas oublier de mettre le modificateur hache ou marteau pour les attaques qui sont concernées.

        Tieflin

        • Vision dans le noir.
        • -
        • R\xE9sistance aux \xE9l\xE9ments : ajouter dans la RD sur la fiche feu:5, electrique:5, froid:5
        • +
        • Résistance aux éléments : ajouter dans la RD sur la fiche feu:5, electrique:5, froid:5
          -
        1. Se faire discret : ajouter les jets sur la fiche, ou bien des comp\xE9tences mentir et deguisement de valeur 5, \xE0 utiliser avec !cof-jet.
        2. +
        3. Se faire discret : ajouter les jets sur la fiche, ou bien des compétences mentir et deguisement de valeur 5, à utiliser avec !cof-jet.
    -

    4.2 Voies de prestige et capacit\xE9s \xE9piques

    +

    4.2 Voies de prestige et capacités épiques

    -

    Voie d'Arwend\xE9e

    +

    Voie d'Arwendée

      -
    1. Sens affut\xE9s : Cr\xE9ez un pr\xE9dicat sensAffutes. Cela va ajuster l'initiative (ne se voit pas sur la fiche), ainsi que les d\xE9g\xE2ts des arcs. Ajoutez ensuite le bonus aux comp\xE9tences perception et vigilance (ou cr\xE9ez-les).
    2. -
    3. Arc de ma\xEEtre : Cr\xE9ez un pr\xE9dicat arcDeMaitre pour automatiquement augmenter la port\xE9e des arcs de 20 m.
    4. +
    5. Sens affutés : Créez un prédicat sensAffutes. Cela va ajuster l'initiative (ne se voit pas sur la fiche), ainsi que les dégâts des arcs. Ajoutez ensuite le bonus aux compétences perception et vigilance (ou créez-les).
    6. +
    7. Arc de maître : Créez un prédicat arcDeMaitre pour automatiquement augmenter la portée des arcs de 20 m.
    8. Carquois magique : !cof-effet-temp carquoisMagique [[5+@{selected|SAG}]] --valeur ?{Type de DM?|feu|froid|foudre} --mana 1.
    9. -
    10. Protection contre les projectiles : Cr\xE9ez un pr\xE9dicat protectionContreLesProjectiles de valeur 10. Puis, pour lancer le sort, utilisez !cof-effet-temp protectionContreLesProjectiles [[6*(5+@{selected|SAG})]] --lanceur @{selected|token_id} --target @{target|token_id} --mana 2.
    11. -
    12. Pluie de fl\xE8ches : lancer l'attaque avec les options --limiteParCombat 1 pluieDeFleches --disque 5 --toucheDoubleDmg --mana 3.
    13. +
    14. Protection contre les projectiles : Créez un prédicat protectionContreLesProjectiles de valeur 10. Puis, pour lancer le sort, utilisez !cof-effet-temp protectionContreLesProjectiles [[6*(5+@{selected|SAG})]] --lanceur @{selected|token_id} --target @{target|token_id} --mana 2.
    15. +
    16. Pluie de flèches : lancer l'attaque avec les options --limiteParCombat 1 pluieDeFleches --disque 5 --toucheDoubleDmg --mana 3.

    Voie de l'archange

      -
    1. Forme d'ange : !cof-effet-temp formeDAnge [[5+@{selected|SAG}]] --mana 0. Le MJ devra g\xE9rer l'aspect en vol.
    2. -
    3. Soins am\xE9lior\xE9s : utiliser un pr\xE9dicat voieDeLArchange avec comme valeur le rang dans la voie.
    4. -
    5. \xC9p\xE9e c\xE9leste : rien \xE0 faire si le pr\xE9dicat voieDeLArchange a la bonne valeur. Si le personnage n'a pas d\xE9j\xE0 la capacit\xE9 Arme d'argent, ajouter une attaque pour cette arme, avec le modificateur armeDArgent et l'option --si etat armeDArgent.
    6. +
    7. Forme d'ange : !cof-effet-temp formeDAnge [[5+@{selected|SAG}]] --mana 0. Le MJ devra gérer l'aspect en vol.
    8. +
    9. Soins améliorés : utiliser un prédicat voieDeLArchange avec comme valeur le rang dans la voie.
    10. +
    11. Épée céleste : rien à faire si le prédicat voieDeLArchange a la bonne valeur. Si le personnage n'a pas déjà la capacité Arme d'argent, ajouter une attaque pour cette arme, avec le modificateur armeDArgent et l'option --si etat armeDArgent.

    Voie de l'archer arcanique

      -
    1. Fl\xE8che magique : vous pouvez ajouter une munition de type fl\xE8che, avec les modificateurs magique, reroll1.
    2. -
    3. Fl\xE8che tueuse : ajouter une munition d\xE9di\xE9e, avec les modificateurs magique, reroll1 et les options --bonusAttaque 3 --plus rd6. Au Mj et au joueur de v\xE9rifier que cette fl\xE8che n'est utilis\xE9e que contre la bonne cible...
    4. -
    5. Fl\xE8che intangible : ajouter une action avec le code #Attaque -1 --difficulteCarac DEX --ignoreObstacles. Attention, pour l'instant le script ne v\xE9rifie pas que l'arme utilis\xE9e est bien un arc.
    6. -
    7. Fl\xE8ches vivantes : ajoutez aux munitions du rang 1 et 2 l'option --if deAttaque 15 --plus 2d6 --message la fl\xE8che prend vie au contact du sang --endif.
    8. -
    9. Fl\xE8che chercheuse : faire une action avec le code #Attaque -1 --plus 2d6 --portee 1000 --limiteParJour 1 flecheChercheuse.
    10. +
    11. Flèche magique : vous pouvez ajouter une munition de type flèche, avec les modificateurs magique, reroll1.
    12. +
    13. Flèche tueuse : ajouter une munition dédiée, avec les modificateurs magique, reroll1 et les options --bonusAttaque 3 --plus rd6. Au Mj et au joueur de vérifier que cette flèche n'est utilisée que contre la bonne cible...
    14. +
    15. Flèche intangible : ajouter une action avec le code #Attaque -1 --difficulteCarac DEX --ignoreObstacles. Attention, pour l'instant le script ne vérifie pas que l'arme utilisée est bien un arc.
    16. +
    17. Flèches vivantes : ajoutez aux munitions du rang 1 et 2 l'option --if deAttaque 15 --plus 2d6 --message la flèche prend vie au contact du sang --endif.
    18. +
    19. Flèche chercheuse : faire une action avec le code #Attaque -1 --plus 2d6 --portee 1000 --limiteParJour 1 flecheChercheuse.

    Voie de l'expert

    - Reporter les bonus sur la fiche et cr\xE9er les comp\xE9tences ad\xE9quates. + Reporter les bonus sur la fiche et créer les compétences adéquates.

    Voie de l'expert du combat

      -
    1. Expertise du combat : cr\xE9er un pr\xE9dicat expertDuCombat avec comme valeur le rang dans la voie. La commande !cof-statut donne un \xE9tat des lieux des d\xE9s d\xE9pens\xE9s pendant le combat/le tour. Les d\xE9s ne sont actifs qu'en combat et sont r\xE9initialis\xE9s \xE0 l'utilisation de !cof-fin-combat. L'impl\xE9mentation part du principe que l'augmentation de la DEF doit \xEAtre d\xE9cid\xE9e avant le jet de dommages, comme une esquive acrobatique par exemple.
    2. +
    3. Expertise du combat : créer un prédicat expertDuCombat avec comme valeur le rang dans la voie. La commande !cof-statut donne un état des lieux des dés dépensés pendant le combat/le tour. Les dés ne sont actifs qu'en combat et sont réinitialisés à l'utilisation de !cof-fin-combat. L'implémentation part du principe que l'augmentation de la DEF doit être décidée avant le jet de dommages, comme une esquive acrobatique par exemple.
    4. Bousculer : !cof-expert-combat-bousculer @{selected|token_id} @{target|token_id}
    5. -
    6. Expertise sup\xE9rieure : il suffit de mettre \xE0 jour la valeur du pr\xE9dicat expertDuCombat ; le script automatise la mise \xE0 jour des limites et la possibilit\xE9 d'augmenter les DM.
    7. -
    8. D\xE9placement tactique : pas de support sp\xE9cifique pour le d\xE9placement, mais on peut pr\xE9voir une action !cof-expert-combat pour le personnage, qui ne fera qu'une d\xE9pense simple de d\xE9 d'expertise.
    9. -
    10. Expertise majeure : les limites de d\xE9s par tour sont automatiques avec la bonne valeur du pr\xE9dicat expertDuCombat. Pour l'instant le cumul de d\xE9s sur le m\xEAme jet n'est pas support\xE9.
    11. +
    12. Expertise supérieure : il suffit de mettre à jour la valeur du prédicat expertDuCombat ; le script automatise la mise à jour des limites et la possibilité d'augmenter les DM.
    13. +
    14. Déplacement tactique : pas de support spécifique pour le déplacement, mais on peut prévoir une action !cof-expert-combat pour le personnage, qui ne fera qu'une dépense simple de dé d'expertise.
    15. +
    16. Expertise majeure : les limites de dés par tour sont automatiques avec la bonne valeur du prédicat expertDuCombat. Pour l'instant le cumul de dés sur le même jet n'est pas supporté.

    Voie de l'homme du peuple

    - Reporter les bonus sur la fiche et cr\xE9er les comp\xE9tences ad\xE9quates. + Reporter les bonus sur la fiche et créer les compétences adéquates.

    Voie de la fusion lycanthropique

      -
    1. Lycanthropie : !cof-effet-temp lycanthropie [[5*@{selected|SAG}]]. Si vous souhaitez un changement d'image du token, utilisez un token \xE0 plusieurs faces. Dans la liste des faces, en partant de 0, on note n le num\xE9ro de la face qui contient l'image de loup-garou. Ajoutez alors --tokenSide n \xE0 la commande. Par exemple, si la premi\xE8re face est l'image normale du personnage, et la seconde face celle d'un loup-garou, on pourra utiliser !cof-effet-temp lycanthropie [[5*@{selected|SAG}]] --tokenSide 1.
    2. -
    3. \xC9ventration : ajouter un pr\xE9dicat lycanthropeEventre.
    4. +
    5. Lycanthropie : !cof-effet-temp lycanthropie [[5*@{selected|SAG}]]. Si vous souhaitez un changement d'image du token, utilisez un token à plusieurs faces. Dans la liste des faces, en partant de 0, on note n le numéro de la face qui contient l'image de loup-garou. Ajoutez alors --tokenSide n à la commande. Par exemple, si la première face est l'image normale du personnage, et la seconde face celle d'un loup-garou, on pourra utiliser !cof-effet-temp lycanthropie [[5*@{selected|SAG}]] --tokenSide 1.
    6. +
    7. Éventration : ajouter un prédicat lycanthropeEventre.

    Voie de Morn

      -
    1. Secrets de l'au-del\xE0 : !cof-effet-temp secretsDeLAuDela 1 --mana 0
    2. +
    3. Secrets de l'au-delà : !cof-effet-temp secretsDeLAuDela 1 --mana 0
    4. Souffle de vie : !cof-soin @{selected|token_id} @{target|token_id} souffleDeVie --mana 0
    5. -
    6. Souffle de mort : faire une attaque magique, de port\xE9e 20 m (la port\xE9e par d\xE9faut pour les sorts, mais rien n'est sp\xE9cifi\xE9 dans le texte), de d\xE9g\xE2ts 2d8+INT. Ajoutez auto dans les modificateurs. Pour les options, --disque 10 souffleDeMort --effet souffleDeMort 1 --save CON 10 --mana 1.
    7. +
    8. Souffle de mort : faire une attaque magique, de portée 20 m (la portée par défaut pour les sorts, mais rien n'est spécifié dans le texte), de dégâts 2d8+INT. Ajoutez auto dans les modificateurs. Pour les options, --disque 10 souffleDeMort --effet souffleDeMort 1 --save CON 10 --mana 1.
    -

    Voie de Prestige sp\xE9cialis\xE9e

    +

    Voie de Prestige spécialisée

      -
    1. Expertise : ajouter un pr\xE9dicat expertiseSpecialisee, de valeur soit une caract\xE9ristique, soit une comp\xE9tence, soit un mot-cl\xE9 pour une capacit\xE9. Pour l'instant, ne sont impl\xE9ment\xE9s que la rage du berserk (rageDuBerserk) et la furie du berserk (furieDuBerserk).
    2. +
    3. Expertise : ajouter un prédicat expertiseSpecialisee, de valeur soit une caractéristique, soit une compétence, soit un mot-clé pour une capacité. Pour l'instant, ne sont implémentés que la rage du berserk (rageDuBerserk) et la furie du berserk (furieDuBerserk).
    -

    Voie de P\xE9rind\xE9

    +

    Voie de Périndé

    1. Soutient
    2. -
    3. Pr\xE9sence r\xE9confortante
    4. +
    5. Présence réconfortante
    6. Prendre sur soit
    7. -
    8. D\xE9fendre les siens
    9. -
    10. Don de soi : !cof-soin @{selected|token_id} ?{Nombre de d\xE9s?|1|2|3|4|5}d6 --allies 10 --sacrifierPV --mana 3
    11. +
    12. Défendre les siens
    13. +
    14. Don de soi : !cof-soin @{selected|token_id} ?{Nombre de dés?|1|2|3|4|5}d6 --allies 10 --sacrifierPV --mana 3
    -

    Voie des armes \xE0 deux mains

    +

    Voie des armes à deux mains

      -
    1. Allonge : reporter le bonus d'attaque sur la fiche. Par facilit\xE9, j'ai consid\xE9r\xE9 que le bonus d'Init \xE9tait permanent et nous l'avons report\xE9 sur la fiche.
    2. -
    3. Gros Monstre, grosse arme : ajouter un pr\xE9dicat grosMonstreGrosseArme.
    4. -
    5. Tenir \xE0 distance (L) : !cof-effet-temp tenirADistance 1.
    6. -
    7. Attaque \xE0 outrance : !cof-attaque-a-outrance ?{Attaque \xE0 outrance ?|Non,0|-2 DEF / +1D6 DM,2}. Par facilit\xE9, cette "posture de combat" perdure jusqu'\xE0 la fin du combat ou jusqu'\xE0 ce que le guerrier en change. Au rang 5, on pourra utiliser !cof-attaque-a-outrance ?{Attaque \xE0 outrance ?|Non,0|-2 DEF/+1D6 DM,2|-5 DEF/+2D6 DM,5}
    8. -
    9. Critique destructeur : ajouter --plusCrit 2d6 aux attaques d'armes \xE0 2 mains
    10. +
    11. Allonge : reporter le bonus d'attaque sur la fiche. Par facilité, j'ai considéré que le bonus d'Init était permanent et nous l'avons reporté sur la fiche.
    12. +
    13. Gros Monstre, grosse arme : ajouter un prédicat grosMonstreGrosseArme.
    14. +
    15. Tenir à distance (L) : !cof-effet-temp tenirADistance 1.
    16. +
    17. Attaque à outrance : !cof-attaque-a-outrance ?{Attaque à outrance ?|Non,0|-2 DEF / +1D6 DM,2}. Par facilité, cette "posture de combat" perdure jusqu'à la fin du combat ou jusqu'à ce que le guerrier en change. Au rang 5, on pourra utiliser !cof-attaque-a-outrance ?{Attaque à outrance ?|Non,0|-2 DEF/+1D6 DM,2|-5 DEF/+2D6 DM,5}
    18. +
    19. Critique destructeur : ajouter --plusCrit 2d6 aux attaques d'armes à 2 mains

    Voie des vermines

      -
    1. Nu\xE9e de criquets : ajouter une attaque magique, de port\xE9e 20 m, type Sortilege, modificateur pasDeDmg et options --effet nueeDeCriquets [[5+@{selected|SAG}]]. Pas de support particulier pour les DM de zone qui d\xE9truisent la nu\xE9e (enlever l'attribut nueeDeCriquets sur la cible dans ce cas).
    2. +
    3. Nuée de criquets : ajouter une attaque magique, de portée 20 m, type Sortilege, modificateur pasDeDmg et options --effet nueeDeCriquets [[5+@{selected|SAG}]]. Pas de support particulier pour les DM de zone qui détruisent la nuée (enlever l'attribut nueeDeCriquets sur la cible dans ce cas).

    Voie du chasseur de corruption

    -

    Pour savoir si une cible est corrompue, le script va utiliser un pr\xE9dicat corrompu qu'il appartient au MJ d'ajouter pour les cr\xE9atures selon ses crit\xE8res.

    +

    Pour savoir si une cible est corrompue, le script va utiliser un prédicat corrompu qu'il appartient au MJ d'ajouter pour les créatures selon ses critères.

    1. Sentir la corruption : !cof-sentir-la-corruption @{selected|token_id} @{target|token_id}.
    2. -
    3. Combattre la corruption : ajouter un pr\xE9dicat combattreLaCorruption. Y associer la valeur 2 au rang 4 dans la voie.
    4. -
    5. Chasseur de sorci\xE8re : ajouter un pr\xE9dicat chasseurDeSorciere. Pour reconna\xEEtre les n\xE9cromanciens et autres pr\xEAtres mal\xE9fiques, il faut aussi leur ajouter un pr\xE9dicat necromancien.
    6. -
    7. Frappe pr\xE9ventive : pas de support du script.
    8. +
    9. Combattre la corruption : ajouter un prédicat combattreLaCorruption. Y associer la valeur 2 au rang 4 dans la voie.
    10. +
    11. Chasseur de sorcière : ajouter un prédicat chasseurDeSorciere. Pour reconnaître les nécromanciens et autres prêtres maléfiques, il faut aussi leur ajouter un prédicat necromancien.
    12. +
    13. Frappe préventive : pas de support du script.

    Voie du chevalier dragon

      -
    1. Ordre du chevalier dragon : cr\xE9er les comp\xE9tences Persuasion et Intimidation avec les bonus de base de +5. Ajouter un pr\xE9dicat ordreDuChevalierDragon. Quand le personnage est mont\xE9, le script rajoutera automatiquement un bonus de +5 via !cof-jet
    2. -
    3. \xC9p\xE9e de feu : !cof-effet-temp armeEnflammee [[5+@{selected|CHA}]] --lanceur @{selected|token_id} --target @{selected|token_id}. Ne se cumule pas avec l'Arme enflamm\xE9e du Magicien.
    4. -
    5. R\xE9sistance au feu : rajouter feu:5 (ou 10 au rang 5) dans la partie RD de la fiche
    6. +
    7. Ordre du chevalier dragon : créer les compétences Persuasion et Intimidation avec les bonus de base de +5. Ajouter un prédicat ordreDuChevalierDragon. Quand le personnage est monté, le script rajoutera automatiquement un bonus de +5 via !cof-jet
    8. +
    9. Épée de feu : !cof-effet-temp armeEnflammee [[5+@{selected|CHA}]] --lanceur @{selected|token_id} --target @{selected|token_id}. Ne se cumule pas avec l'Arme enflammée du Magicien.
    10. +
    11. Résistance au feu : rajouter feu:5 (ou 10 au rang 5) dans la partie RD de la fiche
    12. Monture puissante : modifier la fiche du Drake
    13. -
    14. Souffle enflamm\xE9 : ajouter une attaque au dragon, m\xEAme jet pour touche, dm 2d6, port\xE9e 40, arme naturelle qui inflige des d\xE9g\xE2ts de feu, avec comme options --disque 3 --dmSiRate 1d6 --dmCible 4d6
    15. +
    16. Souffle enflammé : ajouter une attaque au dragon, même jet pour touche, dm 2d6, portée 40, arme naturelle qui inflige des dégâts de feu, avec comme options --disque 3 --dmSiRate 1d6 --dmCible 4d6
    -

    Voie du combat \xE0 deux armes

    +

    Voie du combat à deux armes

      -
    1. Combat \xE0 deux armes am\xE9lior\xE9 : mettre une des attaques de type arme gauche, et y ajouter le modificateur avecd12crit. Pas encore de support pour la capacit\xE9 avanc\xE9e : dans ce cas, ajoutez le +1 dans la barre 3 du token ou sur les attaques.
    2. -
    3. Parade crois\xE9e : !cof-effet-temp paradeCroisee 1 --valeur rang --montreActions o\xF9 rang est le rang dans la Voie.
    4. +
    5. Combat à deux armes amélioré : mettre une des attaques de type arme gauche, et y ajouter le modificateur avecd12crit. Pas encore de support pour la capacité avancée : dans ce cas, ajoutez le +1 dans la barre 3 du token ou sur les attaques.
    6. +
    7. Parade croisée : !cof-effet-temp paradeCroisee 1 --valeur rang --montreActionsrang est le rang dans la Voie.

    Voie du danseur de guerre

      -
    1. Pirouettes : on peut rajouter les bonus sur la fiche, ou bien ajouter un pr\xE9dicat pirouettes, de valeur le bonus en d\xE9fense (qui ne s'applique que si le malus d'armure est inf\xE9rieur \xE0 4).
    2. -
    3. Vent des lames : pas de support du script, simplement ajouter les attaques adapt\xE9es sur la fiche
    4. +
    5. Pirouettes : on peut rajouter les bonus sur la fiche, ou bien ajouter un prédicat pirouettes, de valeur le bonus en défense (qui ne s'applique que si le malus d'armure est inférieur à 4).
    6. +
    7. Vent des lames : pas de support du script, simplement ajouter les attaques adaptées sur la fiche
    8. Attaque en mouvement : pas de support du script.
    9. -
    10. Danse des lames : !cof-effet-combat danseDesLames. Pour l'attaque gratuite suppl\xE9mentaire, on peut faire #Attaque -1 --si etat danseDesLames --avecd12crit.
    11. +
    12. Danse des lames : !cof-effet-combat danseDesLames. Pour l'attaque gratuite supplémentaire, on peut faire #Attaque -1 --si etat danseDesLames --avecd12crit.

    Voie du familier fantastique

      -
    1. Familier fantastique : cr\xE9er un personnage (de type PNJ) pour le familier, control\xE9 par le joueur et avec un token li\xE9 ayant la capacit\xE9 de voir. +
    2. Familier fantastique : créer un personnage (de type PNJ) pour le familier, controlé par le joueur et avec un token lié ayant la capacité de voir.
        -
      • Pour le bonus en initiative, ajouter au personnage un pr\xE9dicat familier de valeur le nom du compagnon (doit \xEAtre exactement le m\xEAme que celui du token du compagnon). Cela automatise l'initiative quand le familier est pr\xE9sent.
      • -
      • Pour les points de vie partag\xE9s avec le familier, il faut mettre un pr\xE9dicat PVPartagesAvec de valeur le nom du familier (celui de la fiche, pas forc\xE9ment le m\xEAme que le token) pour le personnage, et un pr\xE9dicat similaire chez le familier, de valeur le nom du personnage. Le partage de PVs ne fonctionne pas avec des mooks, et il ne fait pas le partage de d\xE9g\xE2ts temporaires. En revanche, le script devrait g\xE9rer correctement les d\xE9g\xE2ts de zone.
      • -
      • Pour la d\xE9fense du familier, ajouter lui un pr\xE9dicat defDeriveeDe, de valeur le nom du personnage (nom complet sur la fiche, attention \xE0 bien utiliser la syntaxe avec :: si ce nom contient des espaces ou d'autres caract\xE8res sp\xE9ciaux).
      • -
      • Pour l'initiative, ajoutez un pr\xE9dicat initiativeDeriveeDe de valeur le nom du personnage.
      • +
      • Pour le bonus en initiative, ajouter au personnage un prédicat familier de valeur le nom du compagnon (doit être exactement le même que celui du token du compagnon). Cela automatise l'initiative quand le familier est présent.
      • +
      • Pour les points de vie partagés avec le familier, il faut mettre un prédicat PVPartagesAvec de valeur le nom du familier (celui de la fiche, pas forcément le même que le token) pour le personnage, et un prédicat similaire chez le familier, de valeur le nom du personnage. Le partage de PVs ne fonctionne pas avec des mooks, et il ne fait pas le partage de dégâts temporaires. En revanche, le script devrait gérer correctement les dégâts de zone.
      • +
      • Pour la défense du familier, ajouter lui un prédicat defDeriveeDe, de valeur le nom du personnage (nom complet sur la fiche, attention à bien utiliser la syntaxe avec :: si ce nom contient des espaces ou d'autres caractères spéciaux).
      • +
      • Pour l'initiative, ajoutez un prédicat initiativeDeriveeDe de valeur le nom du personnage.
    3. Pouvoir mineur :
        -
      • Minimoi (\xC9gocentrisme) : T\xE9l\xE9portation, pas de support.
      • +
      • Minimoi (Égocentrisme) : Téléportation, pas de support.
    4. Canalisation : Lancer l'attaque avec l'option --canaliseParFamilier.
    5. -
    6. Pouvoir sup\xE9rieur : +
    7. Pouvoir supérieur :
        -
      • Minimoi (Clone) : \xE0 faire.
      • +
      • Minimoi (Clone) : à faire.
    @@ -2208,326 +2221,326 @@

    Voie du gel

    1. -
    2. C\xF4ne de froid : faire une attaque portee 20m, d\xE9g\xE2ts 2d6+INT de froid, avec comme modificateur auto et comme options --cone 30 --fx breath-frost --ifSaveFails CON 13 --effet ralenti 1 --else --diviseDmg 2 --endif. Pour un objet de sort : !cof-attack @{selected|token_id} @{target|token_id} C\xF4ne de froid --sortilege --auto --dm 2d6+[[@{selected|INT}]] --froid --portee 20 --cone 30 --fx breath-frost --ifSaveFails CON 13 --effet ralentiTemp 1 --else --diviseDmg 2 --endif
    3. -
    4. Pr\xE9sence glaciale : !cof-effet presenceGlaciale oui. Utiliser !cof-effet presenceGlaciale non pour mettre fin \xE0 l'effet. On peut pr\xE9ciser un bonus de DEF et des d\xE9g\xE2ts diff\xE9rents avec l'option --valeur. Ainsi, la version grimoire sera !cof-effet presenceGlaciale oui --valeur 3 1d4.
    5. +
    6. Cône de froid : faire une attaque portee 20m, dégâts 2d6+INT de froid, avec comme modificateur auto et comme options --cone 30 --fx breath-frost --ifSaveFails CON 13 --effet ralenti 1 --else --diviseDmg 2 --endif. Pour un objet de sort : !cof-attack @{selected|token_id} @{target|token_id} Cône de froid --sortilege --auto --dm 2d6+[[@{selected|INT}]] --froid --portee 20 --cone 30 --fx breath-frost --ifSaveFails CON 13 --effet ralentiTemp 1 --else --diviseDmg 2 --endif
    7. +
    8. Présence glaciale : !cof-effet presenceGlaciale oui. Utiliser !cof-effet presenceGlaciale non pour mettre fin à l'effet. On peut préciser un bonus de DEF et des dégâts différents avec l'option --valeur. Ainsi, la version grimoire sera !cof-effet presenceGlaciale oui --valeur 3 1d4.
    -

    Voie du gu\xE9risseur

    +

    Voie du guérisseur

      -
    1. Premiers soins : ajouter un pr\xE9dicat voieDuGuerisseur de valeur le rang dans cette voie pour le bonus aux soins de la Voie des soins. Pour le sort, faire !cof-soin @{selected|token_id} @{target|token_id} premiersSoins --mana 0.
    2. -
    3. Immunit\xE9 : utilisez !cof-immunite-guerisseur [[1d6+@{selected|SAG}]] --mana 0 --target @{target|token_id} dans les actions du tour. Si utilis\xE9 directement dans le chat, ajoutez --lanceur @{selected|token_id}.
    4. +
    5. Premiers soins : ajouter un prédicat voieDuGuerisseur de valeur le rang dans cette voie pour le bonus aux soins de la Voie des soins. Pour le sort, faire !cof-soin @{selected|token_id} @{target|token_id} premiersSoins --mana 0.
    6. +
    7. Immunité : utilisez !cof-immunite-guerisseur [[1d6+@{selected|SAG}]] --mana 0 --target @{target|token_id} dans les actions du tour. Si utilisé directement dans le chat, ajoutez --lanceur @{selected|token_id}.
    8. Soins rapides : pas de support au niveau du script.
    9. -
    10. Zone de vie : !cof-zone-de-vie [[1d6+@{selected|SAG}]] --mana 1 --limiteParJour 3 --lanceur @{selected|token_id}. Cela devrait respecter le sort, sauf pour le moment o\xF9 le soin prend effet : c'est au d\xE9but de chaque tour du pr\xEAtre.
    11. +
    12. Zone de vie : !cof-zone-de-vie [[1d6+@{selected|SAG}]] --mana 1 --limiteParJour 3 --lanceur @{selected|token_id}. Cela devrait respecter le sort, sauf pour le moment où le soin prend effet : c'est au début de chaque tour du prêtre.

    Voie du guerrier-mage

    -

    Penser \xE0 utiliser l'option --magieEnArmure pour le lancement des sorts affect\xE9s.

    +

    Penser à utiliser l'option --magieEnArmure pour le lancement des sorts affectés.

      -
    1. Magie en armure : Ajouter un pr\xE9dicat magieEnArmure de valeur la DEF totale \xE0 partir de laquelle le personnage peut lancer des sorts. Comme la fiche ne contient pas l'information de la DEF normale (sans magie) de l'armure port\xE9e, le script utilise la moyenne de la DEF et du malus d'armure. En ajoutant un pr\xE9dicat magieEnArmureFacilitee, le script diminue aussi la difficult\xE9 des jets d'INT pour les armures avec une DEF trop grande de la valeur du pr\xE9dicat de magie en armure.
    2. -
    3. Rituel Assur\xE9 : !cof-effet-temp rituelAssure 2 --mana 0. Le script ne permet pas de pr\xE9ciser le sort, le premier qui sera lanc\xE9 apr\xE8s le rituel assur\xE9 b\xE9n\xE9ficiera de l'effet.
    4. -
    5. MagieDeCombat : Ajouter un pr\xE9dicat magieDeCombat.
    6. +
    7. Magie en armure : Ajouter un prédicat magieEnArmure de valeur la DEF totale à partir de laquelle le personnage peut lancer des sorts. Comme la fiche ne contient pas l'information de la DEF normale (sans magie) de l'armure portée, le script utilise la moyenne de la DEF et du malus d'armure. En ajoutant un prédicat magieEnArmureFacilitee, le script diminue aussi la difficulté des jets d'INT pour les armures avec une DEF trop grande de la valeur du prédicat de magie en armure.
    8. +
    9. Rituel Assuré : !cof-effet-temp rituelAssure 2 --mana 0. Le script ne permet pas de préciser le sort, le premier qui sera lancé après le rituel assuré bénéficiera de l'effet.
    10. +
    11. MagieDeCombat : Ajouter un prédicat magieDeCombat.
    12. Frappe des arcanes : faire une attaque avec l'option --frappeDesArcanes, par exemple dans une action dont le code serait #Attaque -1 --frappeDesArcanes.
    13. Expertise du combat : aucun support du script.
    -

    Voie du h\xE9ro

    +

    Voie du héro

      -
    1. Destin h\xE9ro\xEFque : ajouter le bonus au bonus de points de chances sur la fiche (utiliser la roue crant\xE9e \xE0 droite de la section CHANCE de la fiche).
    2. -
    3. T\xE9nacit\xE9 : ajouter un pr\xE9dicat tenacite.
    4. +
    5. Destin héroïque : ajouter le bonus au bonus de points de chances sur la fiche (utiliser la roue crantée à droite de la section CHANCE de la fiche).
    6. +
    7. Ténacité : ajouter un prédicat tenacite.
    8. Homme de la situation : pas de support.
    9. -
    10. Meneur d'hommes : Ajouter une action : !cof-set-attribute meneurDHommesCible @{selected|token_id} --target @{target|token_id}. Le personnage peut utiliser cette action pour d\xE9signer sa cible. Tous les alli\xE9s du personnage recevront automatiquement les bonus sur le reste du combat.
    11. +
    12. Meneur d'hommes : Ajouter une action : !cof-set-attribute meneurDHommesCible @{selected|token_id} --target @{target|token_id}. Le personnage peut utiliser cette action pour désigner sa cible. Tous les alliés du personnage recevront automatiquement les bonus sur le reste du combat.
    -

    Voie du ma\xEEtre des poisons

    +

    Voie du maître des poisons

    Rappel : pour appliquer un poison, utiliser !cof-enduire-poison -1 type force save.
      -
    1. Connaissance du poison : ajouter un pr\xE9dicat connaissanceDuPoison pour \xE9viter le test d'INT quand le voleur applique du poison.
    2. -
    3. Poison rapide : faire les applications \xE0 la main (!cof-enduire-poison L rapide 2d6 12).
    4. -
    5. Poison affaiblissant : faire les applications \xE0 la main (!cof-enduire-poison L affaiblissant 0 15).
    6. +
    7. Connaissance du poison : ajouter un prédicat connaissanceDuPoison pour éviter le test d'INT quand le voleur applique du poison.
    8. +
    9. Poison rapide : faire les applications à la main (!cof-enduire-poison L rapide 2d6 12).
    10. +
    11. Poison affaiblissant : faire les applications à la main (!cof-enduire-poison L affaiblissant 0 15).

    Voie du messager

    1. Muet comme une tombe : pas de support pour l'instant.
    2. -
    3. Jusqu'\xE0 bon port : ajouter les comp\xE9tences correspondantes sur la fiche.
    4. -
    5. Conducteur de diligence : ajouter les comp\xE9tences, et en cas de combat depuis une diligence, utiliser la barre 3 pour le bonus \xE0 l'attaque.
    6. +
    7. Jusqu'à bon port : ajouter les compétences correspondantes sur la fiche.
    8. +
    9. Conducteur de diligence : ajouter les compétences, et en cas de combat depuis une diligence, utiliser la barre 3 pour le bonus à l'attaque.
    10. Sens du devoir : Activer avec !cof-effet sensDuDevoir true. On peut enlever cet effet depuis le statut, au changement de jour, ou avec la commande !cof-effet sensDuDevoir false.
    11. Attaque en mouvement : pas de support pour l'instant.

    Voie du pacte vampirique

      -
    1. Blessure sanglante : ajuter un pr\xE9dicat blessureSanglante.
    2. -
    3. Sang puissant : ajouter un pr\xE9dicat immuniteSaignement et un pr\xE9dicat immuniteAbsorptionVampire.
    4. -
    5. Drain de sang : ajouter un pr\xE9dicat drainDeSang.
    6. -
    7. Flot de sang : associer la valeur 2 au pr\xE9dicat blessureSanglante.
    8. -
    9. \xC9nergie impie : ajouter un pr\xE9dicat energieImpie.
    10. +
    11. Blessure sanglante : ajuter un prédicat blessureSanglante.
    12. +
    13. Sang puissant : ajouter un prédicat immuniteSaignement et un prédicat immuniteAbsorptionVampire.
    14. +
    15. Drain de sang : ajouter un prédicat drainDeSang.
    16. +
    17. Flot de sang : associer la valeur 2 au prédicat blessureSanglante.
    18. +
    19. Énergie impie : ajouter un prédicat energieImpie.

    Voie du porteur de bouclier

      -
    1. Expertise du bouclier : reporter le bonus sur la fiche dans le bonus de DEF conf\xE9r\xE9 par le bouclier.
    2. -
    3. Progresser \xE0 couvert : !cof-effet-temp progresserACouvert 1 --lanceur @{selected|token_id} --target @{target|token_id} --self --portee 1. A utiliser pour cibler un alli\xE9 \xE0 port\xE9e si n\xE9cessaire. Au MJ de v\xE9rifier qu'elle reste bien pr\xE8s du chevalier pour profiter du bonus.
    4. -
    5. Attaque au bouclier : Ajouter une arme avec son Bouclier en "Arme gauche" sur la fiche du personnage. Dans les modificateurs de l'arme, ajoutez avecd12crit. Pour que cette attaque soit propos\xE9e dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un pr\xE9dicat attaqueAuBouclier de valeur le label de l'attaque.
    6. -
    7. D\xE9vier les coups : Ajouter un pr\xE9dicat devierLesCoups (on peut y associer un nombre, si on souhaite plus d'une utlisation par tour). Le script ajoute automatiquement un bouton sur les attaques sur lesquelles cette capacit\xE9 peut-\xEAtre utilis\xE9e.
    8. -
    9. Parade au bouclier : Ajouter un pr\xE9dicat paradeAuBouclier. Sur l'ability Coup de bouclier cr\xE9\xE9 pour le rang 3, ajouter --attaqueBouclierRenverse --decrLimitePredicatParTour paradeAuBouclier. Le script ajoute automatiquement un bouton sur les attaques sur lesquelles cette capacit\xE9 peut-\xEAtre utilis\xE9e. Si le personnage poss\xE8de un bouclier en arme gauche, le script utilisera le bonus \xE9ventuel de l'arme en question sur le jet oppos\xE9.
    10. +
    11. Expertise du bouclier : reporter le bonus sur la fiche dans le bonus de DEF conféré par le bouclier.
    12. +
    13. Progresser à couvert : !cof-effet-temp progresserACouvert 1 --lanceur @{selected|token_id} --target @{target|token_id} --self --portee 1. A utiliser pour cibler un allié à portée si nécessaire. Au MJ de vérifier qu'elle reste bien près du chevalier pour profiter du bonus.
    14. +
    15. Attaque au bouclier : Ajouter une arme avec son Bouclier en "Arme gauche" sur la fiche du personnage. Dans les modificateurs de l'arme, ajoutez avecd12crit. Pour que cette attaque soit proposée dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un prédicat attaqueAuBouclier de valeur le label de l'attaque.
    16. +
    17. Dévier les coups : Ajouter un prédicat devierLesCoups (on peut y associer un nombre, si on souhaite plus d'une utlisation par tour). Le script ajoute automatiquement un bouton sur les attaques sur lesquelles cette capacité peut-être utilisée.
    18. +
    19. Parade au bouclier : Ajouter un prédicat paradeAuBouclier. Sur l'ability Coup de bouclier créé pour le rang 3, ajouter --attaqueBouclierRenverse --decrLimitePredicatParTour paradeAuBouclier. Le script ajoute automatiquement un bouton sur les attaques sur lesquelles cette capacité peut-être utilisée. Si le personnage possède un bouclier en arme gauche, le script utilisera le bonus éventuel de l'arme en question sur le jet opposé.
    -

    Voie du tueur de g\xE9ant

    +

    Voie du tueur de géant

      -
    1. R\xE9duire la distance : ajouter un pr\xE9dicat reduireLaDistance.
    2. -
    3. Ventre mou : ajouter un pr\xE9dicat ventreMou. Cela va diminuer la RD fixe de 3 maximum pour une cr\xE9ature grande, 6 maximum pour une cr\xE9ature \xE9norme et 10 maximum pour une cr\xE9ature colossale.
    4. -
    5. B\xFBcheron : ajouter un pr\xE9dicat bucheron.
    6. +
    7. Réduire la distance : ajouter un prédicat reduireLaDistance.
    8. +
    9. Ventre mou : ajouter un prédicat ventreMou. Cela va diminuer la RD fixe de 3 maximum pour une créature grande, 6 maximum pour une créature énorme et 10 maximum pour une créature colossale.
    10. +
    11. Bûcheron : ajouter un prédicat bucheron.
    -

    Capacit\xE9s \xE9piques

    +

    Capacités épiques

      -
    • Lib\xE9rateur de Dorn : ajouter un pr\xE9dicat liberateurDeDorn.
    • -
    • Lib\xE9rateur de Kerserac : ajouter un pr\xE9dicat liberateurDeKerserac.
    • -
    • Lib\xE9rateur d'Anathazer\xEFn : ajouter un pr\xE9dicat liberateurDAnathazerin. La capacit\xE9 donne le bonus de +2 quel que soit le poison.
    • -
    • Lien \xE9pique: ajouter pour chaque personnage un pr\xE9dicat lienEpique, qui contiennent la m\xEAme chose dans le champ courant (pensez \xE0 un nom d'\xE9quipe, par exemple).
    • -
    • Vitalit\xE9 \xE9pique : ajouter un pr\xE9dicat vitaliteEpique. Pas de support pour le coup mortel ou la r\xE9g\xE9n\xE9ration horaire. Attention, si vous utlisez !cof-soin pour cette r\xE9g\xE9n\xE9ration, les soins seront aussi doubl\xE9s.
    • +
    • Libérateur de Dorn : ajouter un prédicat liberateurDeDorn.
    • +
    • Libérateur de Kerserac : ajouter un prédicat liberateurDeKerserac.
    • +
    • Libérateur d'Anathazerïn : ajouter un prédicat liberateurDAnathazerin. La capacité donne le bonus de +2 quel que soit le poison.
    • +
    • Lien épique: ajouter pour chaque personnage un prédicat lienEpique, qui contiennent la même chose dans le champ courant (pensez à un nom d'équipe, par exemple).
    • +
    • Vitalité épique : ajouter un prédicat vitaliteEpique. Pas de support pour le coup mortel ou la régénération horaire. Attention, si vous utlisez !cof-soin pour cette régénération, les soins seront aussi doublés.
    -

    4.3 Voies de cr\xE9atures

    +

    4.3 Voies de créatures

    Voie du champion

    1. Imparable:
        -
      • Utiliser l'option --m2d20 pour l'action limit\xE9e.
      • -
      • Pour l'effet permanent, utiliser un pr\xE9dicat champion
      • +
      • Utiliser l'option --m2d20 pour l'action limitée.
      • +
      • Pour l'effet permanent, utiliser un prédicat champion
    2. -
    3. Riposte : Ajouter un pr\xE9dicat riposte. Les actions affich\xE9es en cas de riposte seront normalement une attaque avec l'arme en main si il y en a, plus les attaques naturelles coch\xE9es sur la liste d'attaque. Si \xE7a ne convient pas, vous pouvez \xE9crire une liste d'actions nomm\xE9eRipostes (voir les actions du tour).
    4. -
    5. Hausser le ton : ajouter un pr\xE9dicat hausserLeTon.
    6. +
    7. Riposte : Ajouter un prédicat riposte. Les actions affichées en cas de riposte seront normalement une attaque avec l'arme en main si il y en a, plus les attaques naturelles cochées sur la liste d'attaque. Si ça ne convient pas, vous pouvez écrire une liste d'actions nomméeRipostes (voir les actions du tour).
    8. +
    9. Hausser le ton : ajouter un prédicat hausserLeTon.
    -

    Voie du chef d'arm\xE9e

    +

    Voie du chef d'armée

      -
    1. Sergent : ne pas oublier l'action de plus donn\xE9e \xE0 un alli\xE9 par tour. Utiliser un pr\xE9dicat sergent (pour l'attaque ignor\xE9e par combat)
    2. -
    3. Capitaine : pour d\xE9signer le capitaine d'un ensemble de tokens s\xE9lectionn\xE9 (quelle que soit la m\xE9thode), on peut utiliser !cof-capitaine @{selected|token_id} 2, en ajoutant les options de s\xE9lection (comme --target @{target|token_id}). Au lieu de s\xE9lectionner une cible, on peut utiliser le nom d'un token. Si le capitaine fait parti de la s\xE9lection, il sera automatiquement exclu (on ne peut \xEAtre son propre capitaine). Si \xE0 la place de 2, le deuxi\xE8me argument est 0, cela enl\xE8ve le capitaine. L'attribut g\xE9n\xE9r\xE9 est li\xE9 \xE0 un personnage, pas un token sp\xE9cifique, il suffit donc de cibler un token repr\xE9sentant un personnage pour affecter tous les tokens qui repr\xE9sentent ce personnage. Pas de support particulier pour l'attaque suppl\xE9mentaire en cas d'action limit\xE9e.
    4. -
    5. Commandant : il faut ajouter un pr\xE9dicat commandant. La m\xE9thode pour d\xE9signer les personnages sous les ordres du commandant est la m\xEAme que pour le capitaine : !cof-capitaine @{selected|token_id} 3 (notez que la valeur est 3 pour le commandant, et 2 pour le capitaine).
    6. +
    7. Sergent : ne pas oublier l'action de plus donnée à un allié par tour. Utiliser un prédicat sergent (pour l'attaque ignorée par combat)
    8. +
    9. Capitaine : pour désigner le capitaine d'un ensemble de tokens sélectionné (quelle que soit la méthode), on peut utiliser !cof-capitaine @{selected|token_id} 2, en ajoutant les options de sélection (comme --target @{target|token_id}). Au lieu de sélectionner une cible, on peut utiliser le nom d'un token. Si le capitaine fait parti de la sélection, il sera automatiquement exclu (on ne peut être son propre capitaine). Si à la place de 2, le deuxième argument est 0, cela enlève le capitaine. L'attribut généré est lié à un personnage, pas un token spécifique, il suffit donc de cibler un token représentant un personnage pour affecter tous les tokens qui représentent ce personnage. Pas de support particulier pour l'attaque supplémentaire en cas d'action limitée.
    10. +
    11. Commandant : il faut ajouter un prédicat commandant. La méthode pour désigner les personnages sous les ordres du commandant est la même que pour le capitaine : !cof-capitaine @{selected|token_id} 3 (notez que la valeur est 3 pour le commandant, et 2 pour le capitaine).

    Voie du cogneur

      -
    1. Charge : Faire l'attaque avec les arguments --m2d20 --pietine.
    2. -
    3. Enrager : ajouter un pr\xE9dicat peutEnrager.
    4. +
    5. Charger : Faire l'attaque avec les arguments --deplaceDe 30 --m2d20 --pietine.
    6. +
    7. Enrager : ajouter un prédicat peutEnrager.
    8. Percuter : Remplacer --pietine par --percute dans l'attaque de Charge.

    Voie du colosse

      -
    1. Fauchage : ajouter la RD, et ajouter un pr\xE9dicat fauchage, qui va faire automatiquement le renversement si le d\xE9 d'attaque est entre 15 et 20. Il est possible de changer ce seuil associant au pr\xE9dicat la valeur \xE0 laquelle le d\xE9 d'attaque provoque le renversement (15 par d\xE9faut). Par d\xE9faut, le fauchage est impossible si la taille du d\xE9fenseur est sup\xE9rieure ou \xE9gale \xE0 celle de l'attaquant. Vous pouvez sp\xE9cifier un seuil de taille maximale dans un pr\xE9dicat tailleFauchage (5 = grand, 6 \xE9norme et 7 colossal).
    2. +
    3. Fauchage : ajouter la RD, et ajouter un prédicat fauchage, qui va faire automatiquement le renversement si le dé d'attaque est entre 15 et 20. Il est possible de changer ce seuil associant au prédicat la valeur à laquelle le dé d'attaque provoque le renversement (15 par défaut). Par défaut, le fauchage est impossible si la taille du défenseur est supérieure ou égale à celle de l'attaquant. Vous pouvez spécifier un seuil de taille maximale dans un prédicat tailleFauchage (5 = grand, 6 énorme et 7 colossal).
    4. Balayage : faire une version de l'attaque avec --target @{target|Cible 2|token_id}
    5. -
    6. Projection : ajouter un pr\xE9dicat projection.
    7. +
    8. Projection : ajouter un prédicat projection.
    -

    Voie des cr\xE9atures \xE9l\xE9mentaires

    -

    Ajouter un pr\xE9dicat immunite_type, o\xF9 type est le type de la cr\xE9ature \xE9l\xE9mentaire (feu, acide, froid, ...)

    +

    Voie des créatures élémentaires

    +

    Ajouter un prédicat immunite_type, où type est le type de la créature élémentaire (feu, acide, froid, ...)

      -
    1. Souffle : faire une attaque avec le bon nombre de d6 en DM, du type voulu, de port\xE9e la port\xE9e du souffle, \xE0 utiliser avec les modificateurs auto cone et les options --tempsRecharge rechargeSouffle [[1d4]] --psave DEX 13. Ne pas oublier la possibilit\xE9 d'utiliser un token cible temporaire pour le cone.
    2. -
    3. Corps \xE9l\xE9mentaire : ajouter un pr\xE9dicat corpsElementaire, de valeur l'\xE9l\xE9ment (feu, froid,...). Cela va automatiquement ajouter les d\xE9g\xE2ts aux attaques de contact, et faire des d\xE9g\xE2ts \xE0 ceux qui l'attaquent au contact. Cela va aussi faire appara\xEEtre dans les actions du tour une action de r\xE9g\xE9neration, que le MJ peut utiliser chaque tour, \xE0 lui de voir si les conditions s'y pr\xEAtent (source \xE9l\xE9mentaire proche). Pas de support g\xE9n\xE9rique pour les victimes saisies ou agripp\xE9es, \xE0 g\xE9rer au cas par cas.
    4. -
    5. Explosion finale : ajouter un pr\xE9dicat explosionFinale de valeur le label de l'attaque d'explosion. Cette attaque ne doit contenir aucune demande de valeur (de type ?{Munitions}). Par exemple, pour une explosion finale qui fait 3d6 DM \xE0 tout le monde dans les 10 m et qui permettrait de diviser les d\xE9g\xE2ts par 2 par un test de DEX difficulte 13 (18 si au contact) : on cr\xE9e une attaque Explosion, de d\xE9g\xE2ts 3d6 du type voulu, de port\xE9e 10, de modificateur auto et avec l'option --psave DEX 13 contact 18. Pour changer les d\xE9g\xE2ts du corps \xE9l\xE9mentaire, on peut utiliser un pr\xE9dicat nbCorpsElementaire de valeur le nombre de d6 \xE0 utiliser (2 normalement pour cette capacit\xE9).
    6. +
    7. Souffle : faire une attaque avec le bon nombre de d6 en DM, du type voulu, de portée la portée du souffle, à utiliser avec les modificateurs auto cone et les options --tempsRecharge rechargeSouffle [[1d4]] --psave DEX 13. Ne pas oublier la possibilité d'utiliser un token cible temporaire pour le cone.
    8. +
    9. Corps élémentaire : ajouter un prédicat corpsElementaire, de valeur l'élément (feu, froid,...). Cela va automatiquement ajouter les dégâts aux attaques de contact, et faire des dégâts à ceux qui l'attaquent au contact. Cela va aussi faire apparaître dans les actions du tour une action de régéneration, que le MJ peut utiliser chaque tour, à lui de voir si les conditions s'y prêtent (source élémentaire proche). Pas de support générique pour les victimes saisies ou agrippées, à gérer au cas par cas.
    10. +
    11. Explosion finale : ajouter un prédicat explosionFinale de valeur le label de l'attaque d'explosion. Cette attaque ne doit contenir aucune demande de valeur (de type ?{Munitions}). Par exemple, pour une explosion finale qui fait 3d6 DM à tout le monde dans les 10 m et qui permettrait de diviser les dégâts par 2 par un test de DEX difficulte 13 (18 si au contact) : on crée une attaque Explosion, de dégâts 3d6 du type voulu, de portée 10, de modificateur auto et avec l'option --psave DEX 13 contact 18. Pour changer les dégâts du corps élémentaire, on peut utiliser un prédicat nbCorpsElementaire de valeur le nombre de d6 à utiliser (2 normalement pour cette capacité).
    -

    Voie des cr\xE9atures magique

    +

    Voie des créatures magique

      -
    1. R\xE9duction des DM : Ajouter la RD sur la fiche 5/genre, o\xF9 genre peut \xEAtre magique ou un des types d'attaque (feu, acide, poison, etc...).
    2. -
    3. Vitalit\xE9 surnaturelle : ajouter un pr\xE9dicat vitaliteSurnaturelle, de valeur le nombre de PV r\xE9g\xE9n\xE9r\xE9 par tour. Si la r\xE9g\xE9n\xE9ration doit continuer m\xEAme \xE0 la mort du personnage, ajoutez un + \xE0 la fin de la valeur. Si un type de d\xE9g\xE2t emp\xEAche la r\xE9g\xE9n\xE9ration, faites suivre la valeur de r\xE9g\xE9n\xE9ration d'un / suivi du type (attention, \xE7a ne peut pas \xEAtre le type drain). Si plusieurs types de d\xE9g\xE2ts, les s\xE9parer par une virgule (et dans ce cas, penser \xE0 utiliser la syntaxe avec ::. Par exemple, un troll aura un pr\xE9dicat vitaliteSurnaturelle:: 5+ / feu, acide, en faisant attention \xE0 ne rien mettre ensuite sur la m\xEAme ligne. Si vous voulez r\xE9initialiser les d\xE9g\xE2ts qui ne peuvent pas se r\xE9g\xE9n\xE9rer sur un personnage, vous pouvez utiliser des soins normaux (!cof-soin), et si vous avez augment\xE9 \xE0 la main les PVs, vous pouvez effacer les attributs DMSuivistype qui ont \xE9t\xE9 cr\xE9\xE9s par le script. Pour emp\xEAcher la r\xE9g\xE9n\xE9ration m\xEAme mort, le mieux est d'enlever le token de la page (ou de le mettre en token g\xE9n\xE9rique).
    4. +
    5. Réduction des DM : Ajouter la RD sur la fiche 5/genre, où genre peut être magique ou un des types d'attaque (feu, acide, poison, etc...).
    6. +
    7. Vitalité surnaturelle : ajouter un prédicat vitaliteSurnaturelle, de valeur le nombre de PV régénéré par tour. Si la régénération doit continuer même à la mort du personnage, ajoutez un + à la fin de la valeur. Si un type de dégât empêche la régénération, faites suivre la valeur de régénération d'un / suivi du type (attention, ça ne peut pas être le type drain). Si plusieurs types de dégâts, les séparer par une virgule (et dans ce cas, penser à utiliser la syntaxe avec ::. Par exemple, un troll aura un prédicat vitaliteSurnaturelle:: 5+ / feu, acide, en faisant attention à ne rien mettre ensuite sur la même ligne. Si vous voulez réinitialiser les dégâts qui ne peuvent pas se régénérer sur un personnage, vous pouvez utiliser des soins normaux (!cof-soin), et si vous avez augmenté à la main les PVs, vous pouvez effacer les attributs DMSuivistype qui ont été créés par le script. Pour empêcher la régénération même mort, le mieux est d'enlever le token de la page (ou de le mettre en token générique).
    -

    Voie des cr\xE9atures volantes

    -

    On peut mettre un pr\xE9dicat volant pour immuniser la cr\xE9ature \xE0 certains effets qui ne peuvent affecter que des cr\xE9atures terrestres, comme l'arm\xE9e des morts ou le croc-en-jambe.

    +

    Voie des créatures volantes

    +

    On peut mettre un prédicat volant pour immuniser la créature à certains effets qui ne peuvent affecter que des créatures terrestres, comme l'armée des morts ou le croc-en-jambe.

      -
    1. Vol rapide : simplement faire une variante de l'attaque avec les options --bonusAttaque 5 --plus 1d6 \xE0 utiliser le premier tour de combat si a cr\xE9ature est en vol et attaque une cr\xE9ature au sol. Ne pas oublier l'action de mouvement suppl\xE9mentaire en vol.
    2. -
    3. Agripper : ajouter un pr\xE9dicat agripper (ne fera agripper que sur les attaques de contact).
    4. +
    5. Vol rapide : simplement faire une variante de l'attaque avec les options --bonusAttaque 5 --plus 1d6 à utiliser le premier tour de combat si a créature est en vol et attaque une créature au sol. Ne pas oublier l'action de mouvement supplémentaire en vol.
    6. +
    7. Agripper : ajouter un prédicat agripper (ne fera agripper que sur les attaques de contact).

    Voie de la magie de combat

    1. Attaque magique : simplement une attaque, avec les options --sortilege --magique --fx beam-magic. Pour la version de zone, utiliser les options --disque 5 --auto --psave DEX 10.
    2. Armure magique : utiliser !cof-effet-combat armureMagique
    -

    Voie de la magie de gu\xE9rison

    +

    Voie de la magie de guérison

    1. Soigner : !cof-soin @{selected|token_id} @{target|target1|token_id} [[ceil(@{target|target1|PV|max}/2)]] --limiteCibleParJour 1
    2. -
    3. Gu\xE9rir : !cof-guerir @{selected|token_id} @{target|token_id} --portee 0
    4. +
    5. Guérir : !cof-guerir @{selected|token_id} @{target|token_id} --portee 0
    -

    Voie de la magie mal\xE9fique

    +

    Voie de la magie maléfique

    1. Vampirisation :
        -
      • Ajouter une attaque magique avec les DMs de vampirisation, faisant des d\xE9g\xE2ts de type drain. (En objet, on utilisera les options --sortilege et --drain).
      • -
      • Ajouter un pr\xE9dicat siphonDesAmes, de valeur de NC de la cr\xE9ature (ou sans valeur, si le NC est 0). Si vous voulez que ce siphon emp\xEAche un autre siphon des \xE2mes, rajoutez un pr\xE9dicat siphonDesAmesPrioritaire de valeur un nombre positif et sup\xE9rieur \xE0 ceux sur lequel il est prioritaire.
      • +
      • Ajouter une attaque magique avec les DMs de vampirisation, faisant des dégâts de type drain. (En objet, on utilisera les options --sortilege et --drain).
      • +
      • Ajouter un prédicat siphonDesAmes, de valeur de NC de la créature (ou sans valeur, si le NC est 0). Si vous voulez que ce siphon empêche un autre siphon des âmes, rajoutez un prédicat siphonDesAmesPrioritaire de valeur un nombre positif et supérieur à ceux sur lequel il est prioritaire.
    2. -
    3. Animer un cadavre : !cof-animer-cadavre @{selected|token_id} @{target|token_id}. Au cas o\xF9 vous auriez besoin d'enlever l'\xE9tat de cadavre, il suffit d'enlever l'attribut nomm\xE9 cadavreAnime.
    4. +
    5. Animer un cadavre : !cof-animer-cadavre @{selected|token_id} @{target|token_id}. Au cas où vous auriez besoin d'enlever l'état de cadavre, il suffit d'enlever l'attribut nommé cadavreAnime.
    6. Injonction Mortelle : !cof-injonction-mortelle @{selected|token_id} @{target|token_id}

    Voie de la meute

      -
    1. Intergeanchables : Utiliser un pr\xE9dicat interchangeable, avec comme valeur le nombre d'opposants \xE0 partir duquel les cibles peuvent \xEAtre interverties. Par d\xE9faut, cela va donner un bonus de +2 en DEF et +3 an attaque. Pour retrouver la valeur normale de +5 en DEF, utilisez !cof-options.
    2. -
    3. Attaque en tra\xEEtre : Au MJ de d\xE9cider si une attaque est en tra\xEEtre ou pas. Pour une attaque en tra\xEEtre, rajouter les arguments --sournoise 2 --bonusAttaque 5.
    4. +
    5. Intergeanchables : Utiliser un prédicat interchangeable, avec comme valeur le nombre d'opposants à partir duquel les cibles peuvent être interverties. Par défaut, cela va donner un bonus de +2 en DEF et +3 an attaque. Pour retrouver la valeur normale de +5 en DEF, utilisez !cof-options.
    6. +
    7. Attaque en traître : Au MJ de décider si une attaque est en traître ou pas. Pour une attaque en traître, rajouter les arguments --sournoise 2 --bonusAttaque 5.
    -

    Voie du PNJ r\xE9current

    +

    Voie du PNJ récurrent

      -
    1. Instinct de survie : ajouter un pr\xE9dicat instinctDeSurvie avec comme valeur le nombre de PV en-dessous duquel le PNJ gagne un bonus de DEF. les autres effets sont \xE0 faire par le MJ.
    2. -
    3. Chair \xE0 canon : ajouter un pr\xE9dicat chairACanon. Ajouter ensuite \xE0 tous ses sous-fifres un pr\xE9dicat chairACanonDe de valeur le nom exact du token du PNJ. On peut y mettre plusieurs noms s\xE9par\xE9s par des virgules. Attention, dans ce cas (et aussi si le nom de token contient des espaces ou virgules, etc) pensez \xE0 utiliser :: au lieu de : pour le pr\xE9dicat.
    4. +
    5. Instinct de survie : ajouter un prédicat instinctDeSurvie avec comme valeur le nombre de PV en-dessous duquel le PNJ gagne un bonus de DEF. les autres effets sont à faire par le MJ.
    6. +
    7. Chair à canon : ajouter un prédicat chairACanon. Ajouter ensuite à tous ses sous-fifres un prédicat chairACanonDe de valeur le nom exact du token du PNJ. On peut y mettre plusieurs noms séparés par des virgules. Attention, dans ce cas (et aussi si le nom de token contient des espaces ou virgules, etc) pensez à utiliser :: au lieu de : pour le prédicat.
    -

    Voie du pr\xE9dateur

    +

    Voie du prédateur

      -
    1. Embuscade : S\xE9lectionner les ennemis du pr\xE9dateurs, et utiliser !cof-surprise. Par exemple, contre une \xE9quipe de joueurs dans le handout Equipe joueurs (cf la m\xE9thode de s\xE9lection de groupes), on pourra utiliser l'ability !cof-surprise [[15 + @{selected|DEX}]] --equipe joueurs. Pour les bonus en discr\xE9tion et init, reporter sur la fiche (et \xE0 un pr\xE9dicat discr\xE9tion), pour l'attaque en embuscade sur une cible surprise, rajouter \xE0 une attaque les options --sournoise 1 --if moins FOR --etat renverse --endif.
    2. -
    3. D\xE9vorer : ajouter un pr\xE9dicat devorer.
    4. -
    5. Gober : ajouter un pr\xE9dicat gober. Le script ne v\xE9rifie pas que le personnage fait son jet de force avant d'attaquer (mais il propose un bouton pour le faire), ni que l'arme utilis\xE9e n'est pas plus grande qu'une dague.
    6. +
    7. Embuscade : Sélectionner les ennemis du prédateurs, et utiliser !cof-surprise. Par exemple, contre une équipe de joueurs dans le handout Equipe joueurs (cf la méthode de sélection de groupes), on pourra utiliser l'ability !cof-surprise [[15 + @{selected|DEX}]] --equipe joueurs. Pour les bonus en discrétion et init, reporter sur la fiche (et à un prédicat discrétion), pour l'attaque en embuscade sur une cible surprise, rajouter à une attaque les options --sournoise 1 --if moins FOR --etat renverse --endif.
    8. +
    9. Dévorer : ajouter un prédicat devorer.
    10. +
    11. Gober : ajouter un prédicat gober. Le script ne vérifie pas que le personnage fait son jet de force avant d'attaquer (mais il propose un bouton pour le faire), ni que l'arme utilisée n'est pas plus grande qu'une dague.

    Voie du tueur

      -
    1. Attaque mortelle : donner la possibilit\xE9 de faire une attaque avec les options --bonusAttaque 5 --sournoise rang*2. Rajouter un pr\xE9dicat discr\xE9tion avec comme valeur 5.
    2. -
    3. Disparition : donner la possibilit\xE9 de faire une attaque avec les options --disparition rang*2.
    4. -
    5. Assassinat : rajouter --if etatCible surpris --etat mort --save CON 15 --endif \xE0 l'Attaque mortelle.
    6. +
    7. Attaque mortelle : donner la possibilité de faire une attaque avec les options --bonusAttaque 5 --sournoise rang*2. Rajouter un prédicat discrétion avec comme valeur 5.
    8. +
    9. Disparition : donner la possibilité de faire une attaque avec les options --disparition rang*2.
    10. +
    11. Assassinat : rajouter --if etatCible surpris --etat mort --save CON 15 --endif à l'Attaque mortelle.

    4.4 Autres sorts

    Sorts qui ne sont pas dans des voies, mais peuvent venir du grimoire (dans le compagnon) ou d'effets de parchemins.
      -
    • Animation des objets : !cof-animation-des-objets @{selected|token_id} ?{Taille d'objet|tabouret ou coffret,1|chaise ou coffre,2|meuble bas ou table,4|grande table,7|grosse armoire,10} On peut ajouter un troisi\xE8me argument, @{target|token_id} pour animer un token d'objet sur la carte.
    • -
    • Armure d'eau : !cof-effet-combat armureDEau. Le script automatise l'immunit\xE9 aux \xE9treintes (pas aux enveloppements) et \xE0 la capacit\xE9 Agripper des cr\xE9atures volantes.
    • -
    • Choc : Faire une attaque de port\xE9e 20 m, de type Sortil\xE8ge, DM contondants, port\xE9e 20 m, et avec les options --etat renverse --save FOR 10.
    • +
    • Animation des objets : !cof-animation-des-objets @{selected|token_id} ?{Taille d'objet|tabouret ou coffret,1|chaise ou coffre,2|meuble bas ou table,4|grande table,7|grosse armoire,10} On peut ajouter un troisième argument, @{target|token_id} pour animer un token d'objet sur la carte.
    • +
    • Armure d'eau : !cof-effet-combat armureDEau. Le script automatise l'immunité aux étreintes (pas aux enveloppements) et à la capacité Agripper des créatures volantes.
    • +
    • Choc : Faire une attaque de portée 20 m, de type Sortilège, DM contondants, portée 20 m, et avec les options --etat renverse --save FOR 10.
    • Coup au but : !cof-effet-temp bonusAttaqueTemp 1 --valeur 10 --lanceur @{selected|token_id} --portee 10 --mana 0 --target @{target|token_id}.
    • -
    • Force de g\xE9ant : !cof-effet-temp forceDeGeant 10. Le bonus est de 2 par d\xE9faut, mais peut \xEAtre modifi\xE9 en utilisant l'option --valeur.
    • -
    • Mur de vent : !cof-mur-de-force vent. Par d\xE9faut, la dur\xE9e sera de 5+mod. d'INT, mais on peut donner une autre valeur en argument, apr\xE8s vent. On peut aussi changer le rayon du mur en utilisant --portee. Cela ne g\xE8re ni les immunit\xE9s, ni le jet de force pour passer le mur.
    • -
    • Nu\xE9e de scorpions : ajouter une attaque magique, de port\xE9e 20 m, type Sortil\xE8ge, modificateur --pasDeDmg et option --effet nueeDeScorpions 10. Pas de support particulier pour les DM de zone qui d\xE9truisent la nu\xE9e (enlever l'attribut nueeDeScorpions sur la cible dans ce cas).
    • -
    • R\xE9sistance \xE0 la magie : pour l'augmentation de la DEF contre la magie, utiliser un pr\xE9dicat DEF_magie et pour le bonus aux tests, resistanceALaMagie
    • +
    • Force de géant : !cof-effet-temp forceDeGeant 10. Le bonus est de 2 par défaut, mais peut être modifié en utilisant l'option --valeur.
    • +
    • Mur de vent : !cof-mur-de-force vent. Par défaut, la durée sera de 5+mod. d'INT, mais on peut donner une autre valeur en argument, après vent. On peut aussi changer le rayon du mur en utilisant --portee. Cela ne gère ni les immunités, ni le jet de force pour passer le mur.
    • +
    • Nuée de scorpions : ajouter une attaque magique, de portée 20 m, type Sortilège, modificateur --pasDeDmg et option --effet nueeDeScorpions 10. Pas de support particulier pour les DM de zone qui détruisent la nuée (enlever l'attribut nueeDeScorpions sur la cible dans ce cas).
    • +
    • Résistance à la magie : pour l'augmentation de la DEF contre la magie, utiliser un prédicat DEF_magie et pour le bonus aux tests, resistanceALaMagie
    • Simulacre de vie : !cof-set-attribute PVTemporaires [[1d10 + @{selected|niveau}]] --message simulacre de vie
    • -
    • Sixi\xE8me sens : !cof-effet sixiemeSens true. Pour mettre fin \xE0 l'effet du sort (qui a une dur\xE9e en heures), on peut effacer l'attribut sixiemeSens, ou mieux encore, s\xE9lectionner le token et faire !cof-effet sixiemeSens false.
    • +
    • Sixième sens : !cof-effet sixiemeSens true. Pour mettre fin à l'effet du sort (qui a une durée en heures), on peut effacer l'attribut sixiemeSens, ou mieux encore, sélectionner le token et faire !cof-effet sixiemeSens false.
    • Toiles : !cof-effet-temp toiles [[5+@{selected|SAG}]] --saveActifParTour FOR [[10+@{selected|SAG}]] --lanceur @{selected|token_id} --disque @{target|token_id} 5 20 --saufAllies --mana 0.
    -

    4.5 Capacit\xE9s diverses

    +

    4.5 Capacités diverses

      -
    • Absorption d'\xE9nergie (spectres et vampires) : ajouter un pr\xE9dicat absorptionEnergie de valeur la valeur du soin accord\xE9 \xE0 l'attaquant \xE0 chaque fois qu'il endommage une cible (5 par d\xE9faut, si vous ne mettez aucune valeur). Pour l'absorption des vampires, ajouter un pr\xE9dicat vampire.
    • -
    • Action libre : ajouter un pr\xE9dicat actionLibre.
    • -
    • Agripper (d\xE9mon dans Noirbois) : !cof-agripper-de-demon @{selected|token_id} @{target|token_id}
    • -
    • Apparition : un pr\xE9dicat apparition immunise \xE0 tous les DMs, sauf ceux de canalisation (voir plus bas), ou les attaques avec l'option energiePositive.
    • -
    • Armes de l'\xE9t\xE9 (Les seigneurs de l'hiver) : pour le bonus d\xE9fensif contre le seigneur de l'hivers, ajoutez sur les arme un pr\xE9dicat armeDeLEte et sur la cr\xE9ature qui attaque (a priori seulement le seigneur de l'hiver) le pr\xE9dicat creatureDeLHiver. Pour la Flamme de l'\xE9t\xE9, on peut rajouter dans les options --if predicatCible CreatureDeLHiver --incrDmgCoef 3 --incrCritCoef 3 --else --plus 1d6 --feu --enflamme --endif, et pour la Lance de l'aubre, --if predicatCible CreatureDeLHiver --incrDmgCoef 1 --incrCritCoef 1 --else --plus 1d6 --feu --enflamme --endif
    • -
    • Attaque en meute : ajouter un pr\xE9dicat attaqueEnMeute de valeur le bonus d'attaque (2 pour un gobelin). Cela conf\xE8re le bonus pour toutes les attaques de personnages avec ce pr\xE9dicat suivant une effectu\xE9e par un autre personnage avec ce pr\xE9dicat, jusqu'au prochain tour de ce personnage. Ainsi, si 2 cr\xE9atures continuent d'attaquer la m\xEAme cible, elles b\xE9n\xE9ficieront du bonus tout le temps, sauf la toute premi\xE8re attaque.
    • -
    • Attaque violente (Invicible) : ajouter un pr\xE9dicat attaqueViolente.
    • -
    • Auras : pour les capacit\xE9s qui font un effet permanent \xE0 une certaine port\xE9e, comme l'aura glaciale des spectres, utiliser un attribut nomm\xE9 aura, de valeur courante la port\xE9e en m\xE8tres de l'aura, et de valeur maximale l'effet \xE0 appliquer. Si cet effet contient la cha\xEEne de caract\xE8re $TOKEN, cette cha\xEEne sera remplac\xE9e par le nom du token \xE0 l'origine de l'aura. Pour un exemple d'utilisation, voyez la ligne Aura glaciale en dessous.
    • -
    • Aura glaciale : ajouter un attribut aura, de valeur courante 5, et de valeur maximale !cof-effet-temp ralenti [[1d6]] --save CON 12 --magique --seulementVivant --message une aura de froid intense \xE9mane de $TOKEN.
    • -
    • Aura de profanation : ajouter un pr\xE9dicat auraDeProfanation.
    • -
    • Baroud d'honneur : ajouter un pr\xE9dicat baroudHonneur (Quand le personnage arrive \xE0 0 PV, il ne meurt pas jusqu'\xE0 sa prochaine attaque, qui se fait avec un bonus de +5)
    • -
    • B\xE2ton des runes mortes (Invincible) : ajoutez dans les pr\xE9dicats de l'arme le pr\xE9dicat batonDesRunesMortes. Dans la fiche de Swarathnak, ajoutez le pr\xE9dicat ennemiDuBatonDesRunesMortes.
    • -
    • Bonus \xE0 l'attaque magique : utiliser un pr\xE9dicat bonusAttaqueMagique de valeur le bonus permet d'ajouter ce bonus aux attaques magiques. Utile en particulier en pr\xE9dicat d'arme.
    • -
    • Boutefeu (Invincible) : utilisez un pr\xE9dicat boutefeu. -
    • Canalisation : !cof-canaliser type o\xF9 type peut \xEAtre positif ou n\xE9gatif, selon le type d'\xE9nergie canalis\xE9e. Il faut au moins soit une option --soin expr ou --dm expr (il est possible d'avoir les deux), pour exprimer le montant des soins ou des d\xE9g\xE2ts. Si vous souhaitez avoir un certain nombre de d\xE9g\xE2ts par point de mana d\xE9pens\xE9, vous pouvez utiliser un pr\xE9dicat deCanalisation contenant l'expression des d\xE9g\xE2ts (ou soins) par point de mana, et utiliser la syntaxe --soin n pm.
    • -
    • Ch\xE2timent du m\xE2le : utiliser un pr\xE9dicat chatimentDuMale.
    • -
    • Cibles multiples (nu\xE9es) : ajouter un pr\xE9dicat ciblesMultiples.
    • +
    • Absorption d'énergie (spectres et vampires) : ajouter un prédicat absorptionEnergie de valeur la valeur du soin accordé à l'attaquant à chaque fois qu'il endommage une cible (5 par défaut, si vous ne mettez aucune valeur). Pour l'absorption des vampires, ajouter un prédicat vampire.
    • +
    • Action libre : ajouter un prédicat actionLibre.
    • +
    • Agripper (démon dans Noirbois) : !cof-agripper-de-demon @{selected|token_id} @{target|token_id}
    • +
    • Apparition : un prédicat apparition immunise à tous les DMs, sauf ceux de canalisation (voir plus bas), ou les attaques avec l'option energiePositive.
    • +
    • Armes de l'été (Les seigneurs de l'hiver) : pour le bonus défensif contre le seigneur de l'hivers, ajoutez sur les arme un prédicat armeDeLEte et sur la créature qui attaque (a priori seulement le seigneur de l'hiver) le prédicat creatureDeLHiver. Pour la Flamme de l'été, on peut rajouter dans les options --if predicatCible CreatureDeLHiver --incrDmgCoef 3 --incrCritCoef 3 --else --plus 1d6 --feu --enflamme --endif, et pour la Lance de l'aubre, --if predicatCible CreatureDeLHiver --incrDmgCoef 1 --incrCritCoef 1 --else --plus 1d6 --feu --enflamme --endif
    • +
    • Attaque en meute : ajouter un prédicat attaqueEnMeute de valeur le bonus d'attaque (2 pour un gobelin). Cela confère le bonus pour toutes les attaques de personnages avec ce prédicat suivant une effectuée par un autre personnage avec ce prédicat, ou un de leurs alliés, jusqu'au prochain tour de ce personnage. Ainsi, si 2 créatures continuent d'attaquer la même cible, elles bénéficieront du bonus tout le temps, sauf la toute première attaque.
    • +
    • Attaque violente (Invicible) : ajouter un prédicat attaqueViolente.
    • +
    • Auras : pour les capacités qui font un effet permanent à une certaine portée, comme l'aura glaciale des spectres, utiliser un attribut nommé aura, de valeur courante la portée en mètres de l'aura, et de valeur maximale l'effet à appliquer. Si cet effet contient la chaîne de caractère $TOKEN, cette chaîne sera remplacée par le nom du token à l'origine de l'aura. Pour un exemple d'utilisation, voyez la ligne Aura glaciale en dessous.
    • +
    • Aura glaciale : ajouter un attribut aura, de valeur courante 5, et de valeur maximale !cof-effet-temp ralenti [[1d6]] --save CON 12 --magique --seulementVivant --message une aura de froid intense émane de $TOKEN.
    • +
    • Aura de profanation : ajouter un prédicat auraDeProfanation.
    • +
    • Baroud d'honneur : ajouter un prédicat baroudHonneur (Quand le personnage arrive à 0 PV, il ne meurt pas jusqu'à sa prochaine attaque, qui se fait avec un bonus de +5)
    • +
    • Bâton des runes mortes (Invincible) : ajoutez dans les prédicats de l'arme le prédicat batonDesRunesMortes. Dans la fiche de Swarathnak, ajoutez le prédicat ennemiDuBatonDesRunesMortes.
    • +
    • Bonus à l'attaque magique : utiliser un prédicat bonusAttaqueMagique de valeur le bonus permet d'ajouter ce bonus aux attaques magiques. Utile en particulier en prédicat d'arme.
    • +
    • Boutefeu (Invincible) : utilisez un prédicat boutefeu. +
    • Canalisation : !cof-canaliser typetype peut être positif ou négatif, selon le type d'énergie canalisée. Il faut au moins soit une option --soin expr ou --dm expr (il est possible d'avoir les deux), pour exprimer le montant des soins ou des dégâts. Si vous souhaitez avoir un certain nombre de dégâts par point de mana dépensé, vous pouvez utiliser un prédicat deCanalisation contenant l'expression des dégâts (ou soins) par point de mana, et utiliser la syntaxe --soin n pm.
    • +
    • Châtiment du mâle : utiliser un prédicat chatimentDuMale.
    • +
    • Cibles multiples (nuées) : ajouter un prédicat ciblesMultiples.
    • Clignotement : !cof-effet-temp clignotement [[1d6+2]].
    • -
    • Cr\xE9ature non-vivante : ajouter un pr\xE9dicat nonVivant.
    • -
    • Cr\xE9ature v\xE9g\xE9tative : ajouter un pr\xE9dicat vegetatif.
    • -
    • Cyclone (pour les \xE9lementaires) : !cof-effet-temp cyclone [[1d4+1]] --limiteParCombat 1. Cela va proposer une attaque Traverser dans les actions de l'\xE9l\xE9mentaire, qui ne peut fonctionner que si le personnage a au moins une attaque sur sa fiche. Par d\xE9faut, l'attaque utilis\xE9e en traversant est l'attaque de label 1, mais on peut pr\xE9ciser un autre label en utilisant l'option --valeur.
    • -
    • D\xE9g\xE2ts si touch\xE9 au contact (\xE9l\xE9mentaire de feu,...) : ajouter un pr\xE9dicat nomm\xE9 dmSiToucheContact, de valeur les d\xE9g\xE2ts, suivis de -- et du type si besoin. Par exemple, pour un \xE9l\xE9mentaire de feu, le pr\xE9dicat dmSiToucheContact:: 1d6 --feu, en fin de ligne (rien ne doit suivre sur cette ligne).
    • -
    • Drain de force (pour la campagne Invincible) : ajouter un pr\xE9dicat auraDrainDeForce
    • -
    • \xC9craser (pour la campagne Invincible) : ajouter un pr\xE9dicat ecraser de valeur le label de l'attaque utilis\xE9e pour \xE9craser.
    • -
    • Effroi (dragons) : !cof-peur [[10+@{selected|FOR}]] 1d4 --effroi --ralenti --disque @{selected|token_id} 50 \xE0 utiliser au premier tour de jeu.
    • -
    • \xC9nergie de la mort (pour la campagne Vengeance) : ajouter un pr\xE9dicat energieDeLaMort. Le MJ devra \xEAtre attentif au message indiquant le retour \xE0 la vie, car c'est lui qui devra enlever l'\xE9tat mort et ajuster les PVs.
    • -
    • Enveloppement (cube g\xE9latineux) : ajouter l'option --enveloppe, puis quand le bouton appara\xEEt si l'attaque r\xE9ussit, cliquer dessus. En cas d'enveloppement, la cible ne peut plus bouger et se d\xE9place avec le cube (d\xE9placer le cube met la cible dans le cube), et au tour du cube, il faut presser les boutons de d\xE9g\xE2ts pour les infliger aux cibles envelopp\xE9es.
    • -
    • \xC9treinte (serpents) : ajouter l'option --etreinte difficulte, puis quand le bouton appara\xEEt si l'attaque r\xE9ussit, cliquer dessus. En cas d'\xE9treinte r\xE9ussie, la cible ne peut plus bouger et se d\xE9place avec le serpent, et au tour du serpent, il faut presser les boutons de d\xE9g\xE2ts pour les infliger aux cibles \xE9treintes.
    • -
    • \xC9treinte (scorpions) : ajouter l'option --etreinteScorpion. Le script prend le parti de ne pas \xE9tourdir la cible, mais le -5 en DEF, le jet de FOR et les d\xE9g\xE2ts sont automatis\xE9s. La cible est lib\xE9r\xE9e automatiquement \xE0 la mort du scorpion.
    • -
    • \xC9treinte avec immolation (d\xE9mon gardien) : pour l'attaque limit\xE9e qui immole, ajouter l'option --etreinteImmole. Cette attaque r\xE9ussira automatiquement contre une cible qui est d\xE9j\xE0 \xE9treinte.
    • -
    • Faucheuse de g\xE9ants: ajouter le modifcateur tueurDeGrands aux attaques.
    • -
    • Fi\xE8vre du ch\xEAne : pour ajouter encore une RD de 5 contre le feu, ajouter un pr\xE9dicat fievreChene.
    • -
    • Fi\xE9vreux : !cof-effet fievreux donne -2 en attaque, au d\xE9g\xE2ts et aux tests.
    • -
    • 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\xE9faut (13) par un autre jet de d\xE9s. Un deuxi\xE8me 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\xE9 Foudre (avec la majuscule), le son sera jou\xE9 \xE0 chaque fois que la foudre frappera. Finalement, !cof-effet-chaque-d20 foudresDuTemps fin met fin aux foudres du temps.
    • -
    • Fr\xE9n\xE9sie : Ajouter un pr\xE9dicat frenesie avec comme valeur le nombre de PV en-dessous duquel la cr\xE9ature devient fr\xE9n\xE9tique (+2 aus jets d'attaque).
    • -
    • Hors de port\xE9e : ajouter un pr\xE9dicat horsDePortee
    • -
    • Huile de fort assaut : !cof-effet-temp dmgArme(L) 10 --valeur 1d6 o\xF9 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\xF4mes, !cof-peur 12 1d6 --titre Hurlement terrible --immuniseSiResiste hurlement --disque 10 --saufAllies.
    • -
    • Illusion : Pour les illusions qui disparaissent et r\xE9apparaissent un peu plus loin quand on essaie de les toucher, ajouter un pr\xE9dicat estUneIllusion.
    • -
    • Immunit\xE9 aux armes : ajouter un pr\xE9dicat immuniteAuxArmes. \xC0 noter qu'il est possible de sp\xE9cifier le niveau de magie d'une attaque en donnant un argument \xE0 l'option --magique. Ainsi une arme de niveau magique 3 aura en argument --magique 3.
    • -
    • Immunit\xE9 aux attaques non magiques : ajouter un pr\xE9dicat immunite_nonMagique
    • -
    • Immunit\xE9 aux critiques : ajouter un pr\xE9dicat immuniteAuxCritiques.
    • -
    • Ind\xE9racinable : ajouter un pr\xE9dicat inderacinable.
    • -
    • Insensible : ajouter un pr\xE9dicat insensibleAffaibli.
    • -
    • Intangible (\xE0 la Pathfinder 1) : ajouter un un pr\xE9dicat creatureIntangible pour l'immunit\xE9 aux armes non-magiques et la division des autres d\xE9g\xE2ts.
    • -
    • Invisible : passer le personnage invisible (!cof-set-state invisible true, ou mettre directment le statut sur le token). Si il peut rester invisible en combat, lui ajouter un pr\xE9dicat invisibleEnCombat. Si il est attaqu\xE9 autrement qu'avec tir en aveugle par quelqu'un qui ne voit pas l'invisble (\xE0 vous de montrer au moins temporairement le token), un malus de +5 en DEF au contact et +10 \xE0 distance sera appliqu\xE9, de m\xEAme que le bonus de +5 en attaque contre ceux qui ne voient pas l'invisible. Le script suppose toujours qu'un personnage qui dispose de tir aveugle utilise sa capacit\xE9 contre les cibles invisibles: \xE0 vous de v\xE9rifier qu'il ne cumule pas \xE7a avec une capacit\xE9 limit\xE9e.
    • -
    • Langage sombre : en plus de comprendre les elfes noirs, j'ai d\xE9cid\xE9 d'octroyer un bonus de +1 en DEF et +1 aux DM contre les elfes noirs, bonus justifi\xE9 par la meilleure compr\xE9hension de leur culture et de leurs tactiques. Pour cela, j'utiliser un pr\xE9dicat langageSombreHetre.
    • -
    • Message en cas de coup critique re\xE7u : on peut utiliser un pr\xE9dicat messageSiCritique avec en valeur un message \xE0 afficher en cas d'echec critique subit. Pensez \xE0 bien utiliser la syntaxe avec ::.
    • +
    • Créature non-vivante : ajouter un prédicat nonVivant.
    • +
    • Créature végétative : ajouter un prédicat vegetatif.
    • +
    • Cyclone (pour les élementaires) : !cof-effet-temp cyclone [[1d4+1]] --limiteParCombat 1. Cela va proposer une attaque Traverser dans les actions de l'élémentaire, qui ne peut fonctionner que si le personnage a au moins une attaque sur sa fiche. Par défaut, l'attaque utilisée en traversant est l'attaque de label 1, mais on peut préciser un autre label en utilisant l'option --valeur.
    • +
    • Dégâts si touché au contact (élémentaire de feu,...) : ajouter un prédicat nommé dmSiToucheContact, de valeur les dégâts, suivis de -- et du type si besoin. Par exemple, pour un élémentaire de feu, le prédicat dmSiToucheContact:: 1d6 --feu, en fin de ligne (rien ne doit suivre sur cette ligne).
    • +
    • Drain de force (pour la campagne Invincible) : ajouter un prédicat auraDrainDeForce
    • +
    • Écraser (pour la campagne Invincible) : ajouter un prédicat ecraser de valeur le label de l'attaque utilisée pour écraser.
    • +
    • Effroi (dragons) : !cof-peur [[10+@{selected|FOR}]] 1d4 --effroi --ralenti --disque @{selected|token_id} 50 à utiliser au premier tour de jeu.
    • +
    • Énergie de la mort (pour la campagne Vengeance) : ajouter un prédicat energieDeLaMort. Le MJ devra être attentif au message indiquant le retour à la vie, car c'est lui qui devra enlever l'état mort et ajuster les PVs.
    • +
    • Enveloppement (cube gélatineux) : ajouter l'option --enveloppe, puis quand le bouton apparaît si l'attaque réussit, cliquer dessus. En cas d'enveloppement, la cible ne peut plus bouger et se déplace avec le cube (déplacer le cube met la cible dans le cube), et au tour du cube, il faut presser les boutons de dégâts pour les infliger aux cibles enveloppées.
    • +
    • Étreinte (serpents) : ajouter l'option --etreinte difficulte, puis quand le bouton apparaît si l'attaque réussit, cliquer dessus. En cas d'étreinte réussie, la cible ne peut plus bouger et se déplace avec le serpent, et au tour du serpent, il faut presser les boutons de dégâts pour les infliger aux cibles étreintes.
    • +
    • Étreinte (scorpions) : ajouter l'option --etreinteScorpion. Le script prend le parti de ne pas étourdir la cible, mais le -5 en DEF, le jet de FOR et les dégâts sont automatisés. La cible est libérée automatiquement à la mort du scorpion.
    • +
    • Étreinte avec immolation (démon gardien) : pour l'attaque limitée qui immole, ajouter l'option --etreinteImmole. Cette attaque réussira automatiquement contre une cible qui est déjà étreinte.
    • +
    • Faucheuse de géants: ajouter le modifcateur tueurDeGrands aux attaques.
    • +
    • Fièvre du chêne : pour ajouter encore une RD de 5 contre le feu, ajouter un prédicat fievreChene.
    • +
    • Fiévreux : !cof-effet fievreux donne -2 en attaque, au dégâts et aux tests.
    • +
    • 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).
    • +
    • Hors de portée : ajouter un prédicat horsDePortee
    • +
    • Huile de fort assaut : !cof-effet-temp dmgArme(L) 10 --valeur 1d6L 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.
    • +
    • Illusion : Pour les illusions qui disparaissent et réapparaissent un peu plus loin quand on essaie de les toucher, ajouter un prédicat estUneIllusion.
    • +
    • Immunité aux armes : ajouter un prédicat immuniteAuxArmes. À noter qu'il est possible de spécifier le niveau de magie d'une attaque en donnant un argument à l'option --magique. Ainsi une arme de niveau magique 3 aura en argument --magique 3.
    • +
    • Immunité aux attaques non magiques : ajouter un prédicat immunite_nonMagique
    • +
    • Immunité aux critiques : ajouter un prédicat immuniteAuxCritiques.
    • +
    • Indéracinable : ajouter un prédicat inderacinable.
    • +
    • Insensible : ajouter un prédicat insensibleAffaibli.
    • +
    • Intangible (à la Pathfinder 1) : ajouter un un prédicat creatureIntangible pour l'immunité aux armes non-magiques et la division des autres dégâts.
    • +
    • Invisible : passer le personnage invisible (!cof-set-state invisible true, ou mettre directment le statut sur le token). Si il peut rester invisible en combat, lui ajouter un prédicat invisibleEnCombat. Si il est attaqué autrement qu'avec tir en aveugle par quelqu'un qui ne voit pas l'invisble (à vous de montrer au moins temporairement le token), un malus de +5 en DEF au contact et +10 à distance sera appliqué, de même que le bonus de +5 en attaque contre ceux qui ne voient pas l'invisible. Le script suppose toujours qu'un personnage qui dispose de tir aveugle utilise sa capacité contre les cibles invisibles: à vous de vérifier qu'il ne cumule pas ça avec une capacité limitée.
    • +
    • Langage sombre : en plus de comprendre les elfes noirs, j'ai décidé d'octroyer un bonus de +1 en DEF et +1 aux DM contre les elfes noirs, bonus justifié par la meilleure compréhension de leur culture et de leurs tactiques. Pour cela, j'utiliser un prédicat langageSombreHetre.
    • +
    • Message en cas de coup critique reçu : on peut utiliser un prédicat messageSiCritique avec en valeur un message à afficher en cas d'echec critique subit. Pensez à bien utiliser la syntaxe avec ::.
    • Mot de pouvoir qui immobilise : !cof-mot-de-pouvoir-immobilise --lanceur @{selected|token_id} --enVue --saufAllies
    • -
    • N'abandonne jamais : ajouter un pr\xE9dicat nAbandonnejamais.
    • -
    • Noirbois : \xC0 l'entr\xE9e dans des t\xE9n\xE8bres magiques, utiliser la commande !cof-tenebres-magiques. \xC0 la sortie ou la fin de ces t\xE9n\xE8bres, faire !cof-tenebres-magiques fin. Pour allumer la fiole de lumi\xE8re, s\xE9lectionner un token est faire !cof-fiole-de-lumiere d o\xF9 d est la distance \xE0 laquelle la fiole \xE9claire. On peut ajouter un troisi\xE8me argument, qui est la distance \xE0 laquelle la lumi\xE8re devient moins brillante (pas d'effet sur la m\xE9canique de jeu). Pour \xE9teindre la lumi\xE8re, il faut mettre utiliser !cof-fiole-de-lumiere fin.
    • -
    • Noyade (plante carnivore) : il existe un effet de combat nomm\xE9 noyade (pas de dur\xE9e, il dure par d\xE9faut tout le combat) qui fait perdre 1d6 PV par tour, sauf \xE0 r\xE9ussir un test de CON difficult\xE9 15, et qui impose un malus de -3 aux attaques et aux DMs.
    • -
    • Ondes corruptrices (Anathazer\xEFn) : Pour simplement le premier effet, faire !cof-effet ondesCorruptrices 2, puis pour augmeter l'effet !cof-effet ondesCorruptrices +2. L'effet peut \xEAtre annul\xE9 avec !cof-effet ondesCorruptrices 0. Pour le porteur du bouclier de Grabuge, on peut mettre un pr\xE9dicat porteurDuBouclierDeGrabuge.
    • -
    • Paralysie des goules : ajouter \xE0 l'attaque de morsure --effet paralyseGoule [[1d6]] --save CON 10.
    • -
    • Perte de substance (Invincible) : Ajouter pour tous les personnages concern\xE9s un pr\xE9dicat perteDeSubstance. Le changement de jour va augmenter un compteur, \xE0 condition que les tokens des joueurs soient sur la page, et soit on ne s\xE9lectionne aucun token quand on lance la commande de changement de jour, soit on s\xE9lectionne au moins tous les tokens des joueurs. Le test de CHA n'est pas automatis\xE9, mais le script en rappelle la difficult\xE9. Pour les ancres, ajouter un pr\xE9dicat ancreInvincible (par exemple dans les pr\xE9dicats de l'arme). Pour la r\xE9duction des d\xE9g\xE2ts, ajouter au dragon un pr\xE9dicat dragonInvincible. Pour les DM indirects, il faudra g\xE9rer \xE0 la main la r\xE9duction de DM.
    • -
    • Phylact\xE8re de canalisation : ajouter un pr\xE9dicat phylacterePositif pour un phylact\xE8re de canalisation positive, ou phylactereNegatif pour un phylact\xE8re de canalisation n\xE9gative. Associez \xE0 ce pr\xE9dicat la valeur ajout\xE9e pour chaque PM d\xE9pens\xE9 (n\xE9cessite l'utilisation du pr\xE9dicat deCanalisation). Une valeur de 1d4 semble adapt\xE9e pour le phylact\xE8re de canalisation de Pathfinder 1.
    • -
    • Piq\xFBres d'insectes : Rajouter un pr\xE9dicat piquresDInsectes avec comme valeur la r\xE9sistance aux d\xE9g\xE2ts \xE0 distance appropri\xE9e
    • +
    • N'abandonne jamais : ajouter un prédicat nAbandonnejamais.
    • +
    • Noirbois : À l'entrée dans des ténèbres magiques, utiliser la commande !cof-tenebres-magiques. À la sortie ou la fin de ces ténèbres, faire !cof-tenebres-magiques fin. Pour allumer la fiole de lumière, sélectionner un token est faire !cof-fiole-de-lumiere dd est la distance à laquelle la fiole éclaire. On peut ajouter un troisième argument, qui est la distance à laquelle la lumière devient moins brillante (pas d'effet sur la mécanique de jeu). Pour éteindre la lumière, il faut mettre utiliser !cof-fiole-de-lumiere fin.
    • +
    • Noyade (plante carnivore) : il existe un effet de combat nommé noyade (pas de durée, il dure par défaut tout le combat) qui fait perdre 1d6 PV par tour, sauf à réussir un test de CON difficulté 15, et qui impose un malus de -3 aux attaques et aux DMs.
    • +
    • Ondes corruptrices (Anathazerïn) : Pour simplement le premier effet, faire !cof-effet ondesCorruptrices 2, puis pour augmeter l'effet !cof-effet ondesCorruptrices +2. L'effet peut être annulé avec !cof-effet ondesCorruptrices 0. Pour le porteur du bouclier de Grabuge, on peut mettre un prédicat porteurDuBouclierDeGrabuge.
    • +
    • Paralysie des goules : ajouter à l'attaque de morsure --effet paralyseGoule [[1d6]] --save CON 10.
    • +
    • Perte de substance (Invincible) : Ajouter pour tous les personnages concernés un prédicat perteDeSubstance. Le changement de jour va augmenter un compteur, à condition que les tokens des joueurs soient sur la page, et soit on ne sélectionne aucun token quand on lance la commande de changement de jour, soit on sélectionne au moins tous les tokens des joueurs. Le test de CHA n'est pas automatisé, mais le script en rappelle la difficulté. Pour les ancres, ajouter un prédicat ancreInvincible (par exemple dans les prédicats de l'arme). Pour la réduction des dégâts, ajouter au dragon un prédicat dragonInvincible. Pour les DM indirects, il faudra gérer à la main la réduction de DM.
    • +
    • 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 \xEAtre que rapide ou affaiblissant. Pour un poison rapide, force est une expression pour les d\xE9g\xE2ts (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\xE9e en heures, \xE0 g\xE9rer par le MJ). save est la difficult\xE9 du jet de CON pour r\xE9sister 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 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 :
        -
      • --testINT n: fixe la difficult\xE9 du jet d'INT pour r\xE9ussir \xE0 poser le poison. La difficult\xE9 par d\xE9faut 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\xE9d\xE9es.
      • +
      • --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.
      - Il est aussi possible d'enduire de poison des munitions. Pour ce faire, remplacer le label de l'attaque par munition_L o\xF9 L est le label de la munition. Le script suppose que toute munition lanc\xE9e perd son poison. + Il est aussi possible d'enduire de poison des munitions. Pour ce faire, remplacer le label de l'attaque par munition_LL est le label de la munition. Le script suppose que toute munition lancée perd son poison.

      Il existe les effets suivants pour simuler directement des poisons affaiblissants :

      • poisonAffaiblissant est un effet qui rend affaibli pendant tout un combat.
      • -
      • poisonAffaiblissantLong, le m\xEAme effet mais sans limite de dur\xE9e (\xE0 g\xE9rer par le MJ).
      • -
      • poisonAffaiblissantLatent est un effet \xE0 dur\xE9e en tours. Quand l'effet prend fin, le personnage devient empoisonn\xE9 et affaibli.
      • +
      • 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.
    • -
    • Potion de sang de l'Arbre-Coeur : !cof-effet sangDeLArbreCoeur true, \xE0 enlever quand les 24h sont pass\xE9es.
    • -
    • Protection contre les souffles et d\xE9g\xE2ts de zone : ajouter un pr\xE9dicat protectionDMZone. Pour une protection contre un seul \xE9l\xE9ment (feu, froid, etc), ajouter _ et le nom de l'\xE9l\xE9ment. Par exemple, contre le feu, on aura un pr\xE9dicat protectionDMZone_feu. On peut aussi avoir une protection contre les souffles de dragons uniquement, mais qui annule les DM en cas de succ\xE8s au test de DEX, avec le pr\xE9dicat protectionSouffleDeDragon. On peut aussi donner une RD contre les souffles de dragons avec un pr\xE9dicat num\xE9rique rdSouffleDeDragon.
    • -
    • Putr\xE9faction : ajouter \xE0 l'attaque --effet putrefaction 5 --save CON 14 (pour les donn\xE9es des momies)
    • +
    • Potion de sang de l'Arbre-Coeur : !cof-effet sangDeLArbreCoeur true, à enlever quand les 24h sont passées.
    • +
    • Protection contre les souffles et dégâts de zone : ajouter un prédicat protectionDMZone. Pour une protection contre un seul élément (feu, froid, etc), ajouter _ et le nom de l'élément. Par exemple, contre le feu, on aura un prédicat protectionDMZone_feu. On peut aussi avoir une protection contre les souffles de dragons uniquement, mais qui annule les DM en cas de succès au test de DEX, avec le prédicat protectionSouffleDeDragon. On peut aussi donner une RD contre les souffles de dragons avec un prédicat numérique rdSouffleDeDragon.
    • +
    • Putréfaction : ajouter à l'attaque --effet putrefaction 5 --save CON 14 (pour les données des momies)
    • Rage (pour la campagne Invincible) : pour entrer en rage, faire !cof-effet-combat rage. On peut par exemple mettre cette commande dans une ability.
    • -
    • R\xE9action allergique : il existe un effet reactionAllergique qui fait le malus en DEX et CHA et dispara\xEEt en cas de soin magique. Pour une attaque, on peut par exemple mettre --effet reactionAllergique --save CON 11.
    • -
    • R\xE9sistant (insectes) : ajouter un pr\xE9dicat durACuire.
    • -
    • Regard p\xE9trifiant : ajouter un pr\xE9dicat regardPetrifiant. Comme il est difficile de savoir qui est affect\xE9 et quand, le pr\xE9dicat g\xE9n\xE8re juste une action pour la cr\xE9ature et le MJ doit d\xE9cider \xE0 qui l'appliquer et quand. \xC0 noter qu'on peut associer une valeur au pr\xE9dicat pour changer la difficult\xE9 de 16 par d\xE9faut (-4 quand un adversaire est conscient du pouvoir et \xE9vite de croiser le regard). Pour d\xE9tourner le regard d'une cible, utiliser !cof-effet-combat detournerLeRegard. Pour fermer les yeux, !cof-effet-combat detournerLeRegard --valeur 5. Pour arr\xEAter de d\xE9tourner le regard !cof-effet-combat detournerLeRegard fin. Si vous souhaitez enlever un effet de p\xE9trification, vous pouvez utiliser la commande !cof-effet petrifie false.
    • -
    • Saisir et broyer : ajouter un pr\xE9dicat saisirEtBroyer
    • -
    • Sang de fer : ajouter un pr\xE9dicat sangDeFerIf.
    • -
    • Sans esprit : ajouter un pr\xE9dicat sansEsprit permet la r\xE9ussite automatique des jets de r\xE9sistance bas\xE9s sur INT, SAG ou CHA.
    • -
    • Sph\xE8re de feu : !cof-sphere-de-feu.
    • -
    • Tremblements de terre : !cof-effet-chaque-d20 tremblementsDeTerre permet d'activer les tremblements de terre. On peut donner un argument pour remplacer la valeur par d\xE9faut (13) par un autre jet de d\xE9s. Un deuxi\xE8me argument permet de faire trembler la terre pour tout jet entre les deux valeurs. Si votre jeu contient un son (ou playlist) nomm\xE9 TremblementTerre (avec la majuscule), le son sera jou\xE9 \xE0 chaque fois que la terre tremblera. Finalement, !cof-effet-chaque-d20 tremblementsDeTerre fin met fin aux tremblements de terre.
    • +
    • Réaction allergique : il existe un effet reactionAllergique qui fait le malus en DEX et CHA et disparaît en cas de soin magique. Pour une attaque, on peut par exemple mettre --effet reactionAllergique --save CON 11.
    • +
    • Résistant (insectes) : ajouter un prédicat durACuire.
    • +
    • Regard pétrifiant : ajouter un prédicat regardPetrifiant. Comme il est difficile de savoir qui est affecté et quand, le prédicat génère juste une action pour la créature et le MJ doit décider à qui l'appliquer et quand. À noter qu'on peut associer une valeur au prédicat pour changer la difficulté de 16 par défaut (-4 quand un adversaire est conscient du pouvoir et évite de croiser le regard). Pour détourner le regard d'une cible, utiliser !cof-effet-combat detournerLeRegard. Pour fermer les yeux, !cof-effet-combat detournerLeRegard --valeur 5. Pour arrêter de détourner le regard !cof-effet-combat detournerLeRegard fin. Si vous souhaitez enlever un effet de pétrification, vous pouvez utiliser la commande !cof-effet petrifie false.
    • +
    • Saisir et broyer : ajouter un prédicat saisirEtBroyer
    • +
    • Sang de fer : ajouter un prédicat sangDeFerIf.
    • +
    • Sans esprit : ajouter un prédicat sansEsprit permet la réussite automatique des jets de résistance basés sur INT, SAG ou CHA.
    • +
    • Sphère de feu : !cof-sphere-de-feu.
    • +
    • Tremblements de terre : !cof-effet-chaque-d20 tremblementsDeTerre permet d'activer les tremblements de terre. 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 trembler la terre pour tout jet entre les deux valeurs. Si votre jeu contient un son (ou playlist) nommé TremblementTerre (avec la majuscule), le son sera joué à chaque fois que la terre tremblera. Finalement, !cof-effet-chaque-d20 tremblementsDeTerre fin met fin aux tremblements de terre.
    • Vision nocturne : on peut utiliser !cof-vision-nocturne 18 pour un effet de potion de vision nocturne. Attention, pour remettre la vision habituelle, il faut encore effacer le token et remettre le token du personnage depuis la fiche.
    • -
    • Vuln\xE9rabilit\xE9 aux coups critiques : si la cr\xE9ature poss\xE8de un pr\xE9dicat vulnerableCritique, le script interpr\xE8te la valeur de ce pr\xE9dicat comme les chances (sur 100) qu'un coup critique tue directment la cr\xE9ature. Par exemple, la valeur sera de 25 pour un esprit du givre.
    • -
    • Vuln\xE9rabilit\xE9 \xE0 un type de d\xE9g\xE2ts : ajouter un pr\xE9dicat vulnerableA_type, pour augmenter de 50% les d\xE9g\xE2ts re\xE7us de ce type.
    • +
    • Vulnérabilité aux coups critiques : si la créature possède un prédicat vulnerableCritique, le script interprète la valeur de ce prédicat comme les chances (sur 100) qu'un coup critique tue directment la créature. Par exemple, la valeur sera de 25 pour un esprit du givre.
    • +
    • Vulnérabilité à un type de dégâts : ajouter un prédicat vulnerableA_type, pour augmenter de 50% les dégâts reçus de ce type.

    5. Terres d'Arran

    -

    Le script determine s'il doit utiliser les r\xE8gles par d\xE9faut des Terres d'Arran ou celles de COF g\xE9n\xE9rique en fonction des fiches de personnages pr\xE9sentes sur la partie. Pour que toutes vox fiches soient bien adapt\xE9es au setting des Terres d'Arran, assurez-vous de bien s\xE9lectionner ce setting dans les r\xE9glages du jeu (accessibles avant de lancer la partie "Options de jeu" ou "Game Settings".

    +

    Le script determine s'il doit utiliser les règles par défaut des Terres d'Arran ou celles de COF générique en fonction des fiches de personnages présentes sur la partie. Pour que toutes vox fiches soient bien adaptées au setting des Terres d'Arran, assurez-vous de bien sélectionner ce setting dans les réglages du jeu (accessibles avant de lancer la partie "Options de jeu" ou "Game Settings".

    -

    Le fait d'\xEAtre dans ce mode de r\xE8gles change le calcul de l'initiative et des mods d'attaque.

    +

    Le fait d'être dans ce mode de règles change le calcul de l'initiative et des mods d'attaque.

    5.1 Les peuples d'Arran

    5.1.1 Elfes

    Voie du peuple des Elfes
      -
    1. Gr\xE2ce Elfique : Ajouter le bonus au jets de charisme sur la fiche, et une comp\xE9tence discr\xE9tion pour les d\xE9placements silencieux.
    2. -
    3. Essence magique : ajouter un pr\xE9dicat DEF_magie de valeur 2, et un pr\xE9dicat resistanceALaMagie de valeur 2 aussi. Passer ces valeurs \xE0 4 au rang 4 dans la voie.
    4. -
    5. Ma\xEEtrise des armes elfiques : Pas de support pour l'instant
    6. +
    7. Grâce Elfique : Ajouter le bonus au jets de charisme sur la fiche, et une compétence discrétion pour les déplacements silencieux.
    8. +
    9. Essence magique : ajouter un prédicat DEF_magie de valeur 2, et un prédicat resistanceALaMagie de valeur 2 aussi. Passer ces valeurs à 4 au rang 4 dans la voie.
    10. +
    11. Maîtrise des armes elfiques : Pas de support pour l'instant
    12. Empathie elfique : Pas de support
    13. -
    14. Immortalit\xE9 :TODO
    15. +
    16. Immortalité :TODO
    Voie culturelle des elfes blancs
      -
    1. M\xE9moire du monde : En Attente
    2. -
    3. Pr\xE9dispositions magiques : En Attente
    4. -
    5. Lancier d\x2019\xE9lite : En Attente
    6. -
    7. Blancheur immacul\xE9e : En Attente
    8. +
    9. Mémoire du monde : En Attente
    10. +
    11. Prédispositions magiques : En Attente
    12. +
    13. Lancier d’élite : En Attente
    14. +
    15. Blancheur immaculée : En Attente
    16. Parangon elfe blanc : En Attente
    Voie culturelle des elfes bleus
      -
    1. \xC9quilibre parfait : Ajouter une comp\xE9tence \xE9quilibre avec le bonus.
    2. -
    3. Natif d\x2019Els\xE9mur : voir la capacit\xE9 choisie.
    4. +
    5. Équilibre parfait : Ajouter une compétence équilibre avec le bonus.
    6. +
    7. Natif d’Elsémur : voir la capacité choisie.
    8. Imperturbable : En Attente
    9. -
    10. Les enseignements de l\x2019eau : En Attente
    11. +
    12. Les enseignements de l’eau : En Attente
    13. Parangon elfe bleu : En Attente
    Voie culturelle des elfes noirs
      -
    1. Artiste de l\x2019ombre : En Attente
    2. +
    3. Artiste de l’ombre : En Attente
    4. Apprenti de Slurce : En Attente
    5. -
    6. Armes secr\xE8tes : En Attente
    7. +
    8. Armes secrètes : En Attente
    9. Noir comme le sang : En Attente
    10. Parangon elfe noir : En Attente
    Voie culturelle des elfes sylvains
    1. Le chant de la Terre : En Attente
    2. -
    3. Enfant de la for\xEAt : voir la capacit\xE9 choisie
    4. -
    5. Archer \xE9m\xE9rite : ajuster les chances de critique pour les attaques utilisant les arcs.
    6. -
    7. Compagnon animal sup\xE9rieur : En Attente
    8. +
    9. Enfant de la forêt : voir la capacité choisie
    10. +
    11. Archer émérite : ajuster les chances de critique pour les attaques utilisant les arcs.
    12. +
    13. Compagnon animal supérieur : En Attente
    14. Parangon elfe vert : En Attente
    @@ -2535,21 +2548,21 @@

    5.1.2 Nains

    Voie du peuple des Nains
      -
    1. R\xE9sistance : En Attente
    2. +
    3. Résistance : En Attente
    4. Solide comme un roc : En Attente
    5. -
    6. Ma\xEEtrise des armes runiques : En Attente
    7. -
    8. R\xE9sistance \xE0 la magie : En Attente
    9. -
    10. T\xE9nacit\xE9 naine : En Attente
    11. +
    12. Maîtrise des armes runiques : En Attente
    13. +
    14. Résistance à la magie : En Attente
    15. +
    16. Ténacité naine : En Attente
    -
    Voie culturelle de l\x2019ordre de la Forge
    +
    Voie culturelle de l’ordre de la Forge
    1. Artisan de la forge : En Attente
    2. Forgeron runique : En Attente
    3. -
    4. Marteler le m\xE9tal : En Attente
    5. -
    6. Runes de d\xE9fense : En Attente
    7. -
    8. Ma\xEEtre artisan : En Attente
    9. +
    10. Marteler le métal : En Attente
    11. +
    12. Runes de défense : En Attente
    13. +
    14. Maître artisan : En Attente
    -
    Voie culturelle de l\x2019ordre du Talion
    +
    Voie culturelle de l’ordre du Talion
    1. Plein aux as : En Attente
    2. Le sens des affaires : En Attente
    3. @@ -2557,15 +2570,15 @@
      Voie culturelle de l\x2019ordre du Talion
    4. La Loge noire : En Attente
    5. Seigneur du Talion : En Attente
    -
    Voie culturelle de l\x2019ordre du Temple
    +
    Voie culturelle de l’ordre du Temple
      -
    1. Grosse t\xEAte : En Attente
    2. +
    3. Grosse tête : En Attente
    4. Enseigne du Temple : En Attente
    5. -
    6. Invention \xE9trange : En Attente
    7. -
    8. Rites fun\xE9raires (L) : En Attente
    9. -
    10. Ma\xEEtre du temple : En Attente
    11. +
    12. Invention étrange : En Attente
    13. +
    14. Rites funéraires (L) : En Attente
    15. +
    16. Maître du temple : En Attente
    -
    Voie culturelle de l\x2019ordre du Bouclier
    +
    Voie culturelle de l’ordre du Bouclier
    1. Combat en phalange : En Attente
    2. Formation militaire : En Attente
    3. @@ -2573,13 +2586,13 @@
      Voie culturelle de l\x2019ordre du Bouclier
    4. Fuite interdite : En Attente
    5. Veilleur du roi : En Attente
    -
    Voie culturelle de l\x2019ordre des Errants
    +
    Voie culturelle de l’ordre des Errants
    1. Moins que rien : En Attente
    2. -
    3. Pass\xE9 r\xE9volu : En Attente
    4. +
    5. Passé révolu : En Attente
    6. Paysan aguerri : En Attente
    7. -
    8. Solidarit\xE9 des Errants : En Attente
    9. -
    10. Volont\xE9 h\xE9ro\xEFque : En Attente
    11. +
    12. Solidarité des Errants : En Attente
    13. +
    14. Volonté héroïque : En Attente
    @@ -2591,7 +2604,7 @@
    Voie du peuple des Humains
  • Loup parmi les loups : En Attente
  • Enseignement exotique : En Attente
  • Versatile : En Attente
  • -
  • D\xE9passement : En Attente
  • +
  • Dépassement : En Attente
  • Voie culturelle des ruines nordiques
      @@ -2599,28 +2612,28 @@
      Voie culturelle des ruines nordiques
    1. Barbare : En Attente
    2. Expertise des haches : En Attente
    3. Homme des clans : En Attente
    4. -
    5. Conqu\xE9ran: En Attente
    6. +
    7. Conquéran: En Attente
    Voie culturelle du Mitan
      -
    1. Homme des cit\xE9s : En Attente
    2. -
    3. Entre tradition et progr\xE8s : En Attente
    4. +
    5. Homme des cités : En Attente
    6. +
    7. Entre tradition et progrès : En Attente
    8. Modernisme : En Attente
    9. Conspirateur : En Attente
    10. -
    11. Ma\xEEtre marchand : En Attente
    12. +
    13. Maître marchand : En Attente
    Voie culturelle des empires austraux
      -
    1. \xC9rudition : En Attente
    2. -
    3. \xC9tudes arcaniques : En Attente
    4. -
    5. Autorit\xE9 culturelle : En Attente
    6. -
    7. Pr\xE9dispositions arcaniques : En Attente
    8. +
    9. Érudition : En Attente
    10. +
    11. Études arcaniques : En Attente
    12. +
    13. Autorité culturelle : En Attente
    14. +
    15. Prédispositions arcaniques : En Attente
    16. Mage : En Attente
    Voie culturelle des Terres orientales
    1. Connaissances cosmopolites : En Attente
    2. -
    3. Rejeton de la cit\xE9 des Sang-m\xEAl\xE9s : En Attente
    4. +
    5. Rejeton de la cité des Sang-mêlés : En Attente
    6. Sentir la magie : En Attente
    7. Chevaucheur de dragons : En Attente
    8. Expert en filouterie : En Attente
    9. @@ -2630,16 +2643,16 @@

      5.1.3 Peaux Vertes

      Voie du peuple des Peaux Vertes
        -
      1. Pour l\x2019honneur : En Attente
      2. -
      3. Frappe d\xE9loyale : En Attente
      4. -
      5. Ma\xEEtrise des armes sauvages : En Attente
      6. -
      7. Croyances pa\xEFennes : En Attente
      8. -
      9. H\xE9ros tribal : En Attente
      10. +
      11. Pour l’honneur : En Attente
      12. +
      13. Frappe déloyale : En Attente
      14. +
      15. Maîtrise des armes sauvages : En Attente
      16. +
      17. Croyances païennes : En Attente
      18. +
      19. Héros tribal : En Attente
      Voie culturelle des Ogres
        -
      1. \xC9norme : En Attente
      2. +
      3. Énorme : En Attente
      4. Brute : En Attente
      5. Attaque massive (L) : En Attente
      6. Intuable : En Attente
      7. @@ -2668,80 +2681,80 @@

        5.2 Voies de la f

        Voie du bastion

          -
        1. Prot\xE9ger un alli\xE9 : !cof-proteger-un-allie @{selected|token_id} @{target|token_id}. Fonctionne aussi si on remplace le target par un nom de token. Le script ne v\xE9rifie pas que le combattant ne change pas d'alli\xE9 plus d'une fois par tour. Pour la capacit\xE9 avanc\xE9e, ajouter un pr\xE9dicat protegerUnAllieAvance.
        2. +
        3. Protéger un allié : !cof-proteger-un-allie @{selected|token_id} @{target|token_id}. Fonctionne aussi si on remplace le target par un nom de token. Le script ne vérifie pas que le combattant ne change pas d'allié plus d'une fois par tour. Pour la capacité avancée, ajouter un prédicat protegerUnAllieAvance.
        4. Absorber un coup (L) :
            -
          • utiliser !cof-effet-temp absorberUnCoup 1 pour se mettre en position. Attention, \xE7a ne v\xE9rifie pas si le combattant porte son bouclier.
          • -
          • le script propose un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le combattant est en position.
          • +
          • utiliser !cof-effet-temp absorberUnCoup 1 pour se mettre en position. Attention, ça ne vérifie pas si le combattant porte son bouclier.
          • +
          • le script propose un bouton à activer en cas d'attaque réussie alors que le combattant est en position.
        5. -
        6. Coup de bouclier : faire une attaque de bouclier, de type Arme gauche, avec le modificateur avecd12crit. Pour que cette attaque soit propos\xE9e dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un pr\xE9dicat attaqueAuBouclier de valeur le label de l'attaque.
        7. +
        8. Coup de bouclier : faire une attaque de bouclier, de type Arme gauche, avec le modificateur avecd12crit. Pour que cette attaque soit proposée dans les listes d'action seulement quand le personnage porte son bouclier, ajouter un prédicat attaqueAuBouclier de valeur le label de l'attaque.
        9. Absorber un sort (L) :
            -
          • utiliser !cof-effet-temp absorberUnSort 1 pour se mettre en position. Attention, \xE7a ne v\xE9rifie pas si le combattant porte son bouclier.
          • -
          • le script propose un bouton \xE0 activer en cas d'attaque r\xE9ussie alors que le combattant est en position.
          • +
          • utiliser !cof-effet-temp absorberUnSort 1 pour se mettre en position. Attention, ça ne vérifie pas si le combattant porte son bouclier.
          • +
          • le script propose un bouton à activer en cas d'attaque réussie alors que le combattant est en position.
        10. -
        11. Armure lourde : Noter l'armure sur la feuille du personnage, et ajouter un pr\xE9dicat armureLourdeGuerrier au personnage. L'annulation du critique ne se produira que si l'armure est port\xE9e et que la valeur totale du bonus de d\xE9fense sup\xE9rieure ou \xE9gale \xE0 7 (le bonus de DEF d'une armure de plaques compl\xE8te).
        12. +
        13. Armure lourde : Noter l'armure sur la feuille du personnage, et ajouter un prédicat armureLourdeGuerrier au personnage. L'annulation du critique ne se produira que si l'armure est portée et que la valeur totale du bonus de défense supérieure ou égale à 7 (le bonus de DEF d'une armure de plaques complète).

        Voie de la bravoure

        1. Robustesse : rajouter les PVs sur la fiche.
        2. Armure naturelle : rajouter la DEF sur la fiche
        3. -
        4. Prouesse : ajouter un pr\xE9dicat prouesse (on peut y associer un nombre, si on souhaite plus d'une utilisation par tour). Le script g\xE9n\xE9rera automatiquement les boutons Prouesse sur les test appropri\xE9s.
        5. -
        6. Dernier rempart (L) : pas de support particulier, le MJ doit g\xE9rer les attaques suppl\xE9mentaires.
        7. -
        8. Constitution h\xE9ro\xEFque : reporter les bonus sur la fiche.
        9. +
        10. Prouesse : ajouter un prédicat prouesse (on peut y associer un nombre, si on souhaite plus d'une utilisation par tour). Le script générera automatiquement les boutons Prouesse sur les test appropriés.
        11. +
        12. Dernier rempart (L) : pas de support particulier, le MJ doit gérer les attaques supplémentaires.
        13. +
        14. Constitution héroïque : reporter les bonus sur la fiche.
        -

        Voie du combat \xE0 deux armes

        +

        Voie du combat à deux armes

          -
        1. Combat \xE0 deux armes (L) : mettre une des attaques de type arme gauche, et y ajouter le modificateur avecd12crit. Pas encore de support pour la capacit\xE9 avanc\xE9e : dans ce cas, ajoutez le +1 dans la barre 3 du token ou sur les attaques.
        2. -
        3. Parade crois\xE9e (L) : !cof-effet-temp paradeCroisee 1 --valeur 2 --montreActions. Pour la capacit\xE9 avanc\xE9e, !cof-effet-temp paradeCroisee 1 --valeur 4 --montreActions.
        4. -
        5. Sym\xE9trie : En Attente
        6. +
        7. Combat à deux armes (L) : mettre une des attaques de type arme gauche, et y ajouter le modificateur avecd12crit. Pas encore de support pour la capacité avancée : dans ce cas, ajoutez le +1 dans la barre 3 du token ou sur les attaques.
        8. +
        9. Parade croisée (L) : !cof-effet-temp paradeCroisee 1 --valeur 2 --montreActions. Pour la capacité avancée, !cof-effet-temp paradeCroisee 1 --valeur 4 --montreActions.
        10. +
        11. Symétrie : En Attente
        12. Double peine : En Attente
        13. -
        14. Combat \xE0 deux armes parfait : En Attente
        15. +
        16. Combat à deux armes parfait : En Attente
        -

        Voie du combat mont\xE9

        +

        Voie du combat monté

          -
        1. Fid\xE8le monture : Faire un personnage pour la monture, avec un pr\xE9dicat monture. Pour monter sur la monture, on peut utiliser une ability de type token action, avec !cof-en-selle @{selected|token_id} nom_de_la_monture. Pour en descendre, il suffit de cliquer \xE0 nouveau sur le bouton de l'ability. Si vous souhaitez \xE9viter que la monture apparaisse dans le turn tracker, vous pouvez ajouter un pr\xE9dicat aucuneActionCombat \xE0 la monture.
        2. -
        3. Cavalier \xE9m\xE9rite : Ajouter au combattant un pr\xE9dicat cavalierEmerite:2. Pour la d\xE9fense de la monture, ajouter \xE0 cellle-ci un pr\xE9dicat defDeriveeDe de valeur le nom du combattant (exactement tel qu'il appara\xEEt sur la fiche, il est possible que cela demande d'utiliser la syntaxe avec ::). Attention, cela suppose que le combattant a une meilleure DEF que sa monture. Si ce n'est pas le cas, faire les ajustements sur la fiche du combattant.
        4. -
        5. Massacrer la pi\xE9taille : En Attente
        6. -
        7. Charge : pas de support pour le d\xE9placement, mais +
        8. Fidèle monture : Faire un personnage pour la monture, avec un prédicat monture. Pour monter sur la monture, on peut utiliser une ability de type token action, avec !cof-en-selle @{selected|token_id} nom_de_la_monture. Pour en descendre, il suffit de cliquer à nouveau sur le bouton de l'ability. Si vous souhaitez éviter que la monture apparaisse dans le turn tracker, vous pouvez ajouter un prédicat aucuneActionCombat à la monture.
        9. +
        10. Cavalier émérite : Ajouter au combattant un prédicat cavalierEmerite:2. Pour la défense de la monture, ajouter à cellle-ci un prédicat defDeriveeDe de valeur le nom du combattant (exactement tel qu'il apparaît sur la fiche, il est possible que cela demande d'utiliser la syntaxe avec ::). Attention, cela suppose que le combattant a une meilleure DEF que sa monture. Si ce n'est pas le cas, faire les ajustements sur la fiche du combattant.
        11. +
        12. Massacrer la piétaille : En Attente
        13. +
        14. Charge : pas de support pour le déplacement, mais
          • Pour l'attaque : utiliser --m2d20 --plus 1d6
          • -
          • Pour les cr\xE9atures sur la trajectoire, utiliser !cof-jet FOR 18, et en cas de succ\xE8s, infliger les DM (!cof-dmg 1d6)
          • +
          • Pour les créatures sur la trajectoire, utiliser !cof-jet FOR 18, et en cas de succès, infliger les DM (!cof-dmg 1d6)
        15. -
        16. Monture fantastique : faire un personnage pour la monture, avec un pr\xE9dicat monture.
        17. +
        18. Monture fantastique : faire un personnage pour la monture, avec un prédicat monture.

        Voie du commandement

          -
        1. Action concert\xE9e : utiliser !cof-echange-init @{selected|token_id} @{target|token_id} n o\xF9 n peut valoir 0, 1, 2 ou 3 selon le rang dans la voie et si la capacit\xE9 est avanc\xE9e.
        2. -
        3. \xC0 couvert (L) : !cof-a-couvert @{selected|token_id} @{target|token_id} le target est l'alli\xE9 qui se d\xE9place avec l'arquebusier. Se s\xE9lectionner soi-m\xEAme si pas d'alli\xE9. Pas encore de support pour la capacit\xE9 avanc\xE9e.
        4. -
        5. Exemplaire : faire !cof-exemplaire, juste apr\xE8s l'attaque rat\xE9e.
        6. +
        7. Action concertée : utiliser !cof-echange-init @{selected|token_id} @{target|token_id} nn peut valoir 0, 1, 2 ou 3 selon le rang dans la voie et si la capacité est avancée.
        8. +
        9. À couvert (L) : !cof-a-couvert @{selected|token_id} @{target|token_id} le target est l'allié qui se déplace avec l'arquebusier. Se sélectionner soi-même si pas d'allié. Pas encore de support pour la capacité avancée.
        10. +
        11. Exemplaire : faire !cof-exemplaire, juste après l'attaque ratée.
        12. Ordre de bataille : pas de support
        13. Charge fantastique (L) : !cof-charge-fantastique @{selected|token_id} --alliesEnVue --self --limiteParCombat 1
        -

        Voie de la f\xE9rocit\xE9

        +

        Voie de la férocité

        1. Cri de guerre : !cof-effet-combat criDeGuerre
        2. -
        3. Charge (L) : #Attaque -1 --bonusAttaque 2 --plus 1d6. Le d\xE9placement n'est pas encore g\xE9r\xE9.
        4. -
        5. Rage du berserk (L) : utiliser !cof-rage-du-berserk, \xE0 la fois pour entrer en rage et pour tenter d'en sortir avant la fin du combat. Si le MJ souhaite mettre fin \xE0 la rage \xE0 cause d'un effet ext\xE9rieur, il peut utiliser la commande !cof-effet-combat rageDuBerserk fin.
        6. -
        7. M\xEAme pas mal : ajouter un pr\xE9dicat memePasMal. Le joueur doit lui-m\xEAme activer la rage ou le furie si il souhaite en profiter.
        8. +
        9. Charge (L) : #Attaque -1 --deplaceDe 5 20 --bonusAttaque 2 --plus 1d6.
        10. +
        11. Rage du berserk (L) : utiliser !cof-rage-du-berserk, à la fois pour entrer en rage et pour tenter d'en sortir avant la fin du combat. Si le MJ souhaite mettre fin à la rage à cause d'un effet extérieur, il peut utiliser la commande !cof-effet-combat rageDuBerserk fin.
        12. +
        13. Même pas mal : ajouter un prédicat memePasMal. Le joueur doit lui-même activer la rage ou le furie si il souhaite en profiter.
        14. Attaque tourbillon (L) : !cof-explosion -1 --auto --disque 5 --saufAllies --limiteParCombat 1 tourbillon.

        Voie de la guerre

          -
        1. Posture de combat : !cof-posture-de-combat bonus attr1 attr2, o\xF9 les deux attr peuvent \xEAtre soit DEF soit ATT soit DM, et le bonus est retir\xE9 au premier attribut pour \xEAtre ajout\xE9 au second. Le bonus peut \xEAtre limit\xE9 si le combattant a un pr\xE9dicat voieDuSoldat qui indique son rang dans la voie. Exemple d'utilisation : !cof-posture-de-combat ?{Bonus|1|2|3|4|5} ?{Baisser|D\xE9fense,DEF|Attaque,ATT|D\xE9g\xE2ts,DM} ?{Augmenter|D\xE9fense,DEF|Attaque,ATT|D\xE9g\xE2ts,DM}. Normalement, la r\xE8gle fait d\xE9cider de sa posture au combattant \xE0 chaque tour, mais en pratique, il en change assez rarement. Une posture de combat reste donc active jusqu'\xE0 la fin du combat ou jusqu'\xE0 ce qu'on en change (elle est neutre si on a le m\xEAme attribut \xE0 buffer et d\xE9buffer).
        2. -
        3. D\xE9sarmer (L) : !cof-desarmer @{selected|token_id} @{target|token_id}.
        4. -
        5. Double attaque (L) : faire deux attaques, avec l'option suppl\xE9mentaire --bonusAttaque -2.
        6. -
        7. Attaque circulaire (L) : faire les attaques normalement, ce n'est pas consid\xE9r\xE9 comme une aoe.
        8. +
        9. Posture de combat : !cof-posture-de-combat bonus attr1 attr2, où les deux attr peuvent être soit DEF soit ATT soit DM, et le bonus est retiré au premier attribut pour être ajouté au second. Le bonus peut être limité si le combattant a un prédicat voieDuSoldat qui indique son rang dans la voie. Exemple d'utilisation : !cof-posture-de-combat ?{Bonus|1|2|3|4|5} ?{Baisser|Défense,DEF|Attaque,ATT|Dégâts,DM} ?{Augmenter|Défense,DEF|Attaque,ATT|Dégâts,DM}. Normalement, la règle fait décider de sa posture au combattant à chaque tour, mais en pratique, il en change assez rarement. Une posture de combat reste donc active jusqu'à la fin du combat ou jusqu'à ce qu'on en change (elle est neutre si on a le même attribut à buffer et débuffer).
        10. +
        11. Désarmer (L) : !cof-desarmer @{selected|token_id} @{target|token_id}.
        12. +
        13. Double attaque (L) : faire deux attaques, avec l'option supplémentaire --bonusAttaque -2.
        14. +
        15. Attaque circulaire (L) : faire les attaques normalement, ce n'est pas considéré comme une aoe.
        16. Attaque puissante : #Attaque -1 --avecd12crit --plus 2d6 --seulementContact.
        -

        Voie de la ma\xEEtrise des armes

        +

        Voie de la maîtrise des armes

          -
        1. Arme de pr\xE9dilection : il est possible de pr\xE9ciser une famille d'armes de pr\xE9dilection (un peu plus large que dans les r\xE8gles), parmis arc, arbalete, fronde, hache, epee, marteau, masse, sabre, epieu, poudre, baton et rapiere. Si cela vous convient, ajoutez un pr\xE9dicat armeDePredilection de valeur une de ces familles. Sinon, simplement ajouter le bonus sur les attaques dans la fiche.
        2. +
        3. Arme de prédilection : il est possible de préciser une famille d'armes de prédilection (un peu plus large que dans les règles), parmis arc, arbalete, fronde, hache, epee, marteau, masse, sabre, epieu, poudre, baton et rapiere. Si cela vous convient, ajoutez un prédicat armeDePredilection de valeur une de ces familles. Sinon, simplement ajouter le bonus sur les attaques dans la fiche.
        4. Science du critique : En Attente
        5. -
        6. Sp\xE9cialisation : En Attente
        7. +
        8. Spécialisation : En Attente
        9. Attaque parfaite (L) : En Attente
        10. Riposte : En Attente
        @@ -2749,61 +2762,61 @@

        Voie du pugilat

        1. Poings de fer : En Attente
        2. Peau de pierre : En Attente
        3. -
        4. Peau d\x2019acier : En Attente
        5. -
        6. D\xE9luge de coups (L) : En Attente
        7. -
        8. Force h\xE9ro\xEFque : En Attente
        9. +
        10. Peau d’acier : En Attente
        11. +
        12. Déluge de coups (L) : En Attente
        13. +
        14. Force héroïque : En Attente

        Voie de la puissance

        1. Argument de taille : En Attente
        2. Tour de force : En Attente
        3. Attaque brutale (L) : En Attente
        4. -
        5. Briseur d\x2019os : En Attente
        6. -
        7. Vitalit\xE9 d\xE9bordante : En Attente
        8. +
        9. Briseur d’os : En Attente
        10. +
        11. Vitalité débordante : En Attente

        5.3 Voies de la famille des aventuriers

        -

        Voie de l\x2019acrobatie

        +

        Voie de l’acrobatie

        1. Acrobate : En Attente
        2. -
        3. Gr\xE2ce f\xE9line : En Attente
        4. +
        5. Grâce féline : En Attente
        6. Lanceur de couteau : En Attente
        7. Esquive acrobatique : En Attente
        8. -
        9. Dext\xE9rit\xE9 h\xE9ro\xEFque : En Attente
        10. +
        11. Dextérité héroïque : En Attente
        -

        Voie de l\x2019arbal\xE8trie

        +

        Voie de l’arbalètrie

        1. Joli coup! : En Attente
        2. Cadence de tir : En Attente
        3. Tir double (L) : En Attente
        4. -
        5. As de la g\xE2chette : En Attente
        6. +
        7. As de la gâchette : En Attente
        8. Tir mortel : En Attente
        -

        Voie de l\x2019archerie

        +

        Voie de l’archerie

          -
        1. Sens aff\xFBt\xE9s : En Attente
        2. +
        3. Sens affûtés : En Attente
        4. Tir aveugle (L) : En Attente
        5. Tir rapide (L) : En Attente
        6. -
        7. Fl\xE8che de mort (L) : En Attente
        8. +
        9. Flèche de mort (L) : En Attente
        10. Dans le mille : En Attente
        -

        Voie de l\x2019assassinat

        +

        Voie de l’assassinat

          -
        1. Discr\xE9tion : En Attente
        2. +
        3. Discrétion : En Attente
        4. Attaque sournoise (L) : En Attente
        5. Frappe chirurgicale : En Attente
        6. Surprise : En Attente
        7. -
        8. Botte secr\xE8te : En Attente
        9. +
        10. Botte secrète : En Attente
        -

        Voie du boh\xE8me

        +

        Voie du bohème

          -
        1. Rumeurs et l\xE9gendes : En Attente
        2. +
        3. Rumeurs et légendes : En Attente
        4. Argumenter : En Attente
        5. -
        6. D\xE9brouillard : En Attente
        7. -
        8. D\xE9guisement : En Attente
        9. -
        10. Touche-\xE0-tout : En Attente
        11. +
        12. Débrouillard : En Attente
        13. +
        14. Déguisement : En Attente
        15. +
        16. Touche-à-tout : En Attente

        Voie du charme

          @@ -2811,15 +2824,15 @@

          Voie du charme

        1. Provocation (L) : En Attente
        2. Attaque flamboyante (L) : En Attente
        3. Suggestion (L) : En Attente
        4. -
        5. Charisme h\xE9ro\xEFque : En Attente
        6. +
        7. Charisme héroïque : En Attente

        Voie de la chasse

        1. Proche de la nature : En Attente
        2. -
        3. Nature nourrici\xE8re : En Attente
        4. -
        5. Attaque \xE9clair (L) : En Attente
        6. -
        7. Ennemis jur\xE9s : En Attente
        8. -
        9. Perception h\xE9ro\xEFque : En Attente
        10. +
        11. Nature nourricière : En Attente
        12. +
        13. Attaque éclair (L) : En Attente
        14. +
        15. Ennemis jurés : En Attente
        16. +
        17. Perception héroïque : En Attente

        Voie du compagnon animal

          @@ -2829,7 +2842,7 @@

          Voie du compagnon animal

        1. Empathie animale : En Attente
        2. Animal fabuleux : En Attente
        -

        Voie de l\x2019escrime

        +

        Voie de l’escrime

        1. Attaque en finesse : En Attente
        2. Intelligence du combat : En Attente
        3. @@ -2840,10 +2853,10 @@

          Voie de l\x2019escrime

          Voie de la fourberie

          1. Doigts agiles : En Attente
          2. -
          3. D\xE9tecter les pi\xE8ges : En Attente
          4. +
          5. Détecter les pièges : En Attente
          6. Croc-en-jambe : En Attente
          7. Attaque paralysante (L) : En Attente
          8. -
          9. Attaque en tra\xEEtre : En Attente
          10. +
          11. Attaque en traître : En Attente
        @@ -2851,193 +2864,193 @@

        5.4 Voies de la fam

        Talents magiques

          -
        • D\xE9tection de la magie : pas de support.
        • +
        • Détection de la magie : pas de support.
        • Flamme : Faire une attaque magique de type feu pour l'attaque au contact. Pour l'illumination, !cof-lumiere @{selected|token_id} 5 1 --mana 0.
        • -
        • Inspiration : !cof-effet-temp inspiration [[2+@{selected|SAG}]] --target @{target|token_id} --lanceur @{selected|token_id} --portee 10. Pour l'instant le script ne v\xE9rifie pas que le sort n'est pas actif sur trop de cibles \xE0 la fois.
        • -
        • Lumi\xE8res dansantes : !cof-lumiere @{selected|token_id} 20 15 --mana 0. Le script ne g\xE8re pas encore l'annulation de l'effet au moindre choc.
        • +
        • Inspiration : !cof-effet-temp inspiration [[2+@{selected|SAG}]] --target @{target|token_id} --lanceur @{selected|token_id} --portee 10. Pour l'instant le script ne vérifie pas que le sort n'est pas actif sur trop de cibles à la fois.
        • +
        • Lumières dansantes : !cof-lumiere @{selected|token_id} 20 15 --mana 0. Le script ne gère pas encore l'annulation de l'effet au moindre choc.
        • Projectile de force : - Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4, port\xE9e 50, type Sortil\xE8ge, modificateur auto d\xE9g\xE2ts contondants, option --mana 0. + Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d4, portée 50, type Sortilège, modificateur auto dégâts contondants, option --mana 0.
        -

        Voie de l\x2019alchimie

        -

        Pour cr\xE9er ou juste voir ses \xE9lixirs, utiliser la commande !cof-elixirs. Pour cela, il faut aussi un pr\xE9dicat voieDeLAlchimie avec comme valeur le rang dans la voie. Noter que la commande !cof-elixirs affiche une liste d'\xE9lixirs, et que pour effectivement cr\xE9er un \xE9lixir, il faut cliquer sur le bouton correspondant dans cette liste.

        +

        Voie de l’alchimie

        +

        Pour créer ou juste voir ses élixirs, utiliser la commande !cof-elixirs. Pour cela, il faut aussi un prédicat voieDeLAlchimie avec comme valeur le rang dans la voie. Noter que la commande !cof-elixirs affiche une liste d'élixirs, et que pour effectivement créer un élixir, il faut cliquer sur le bouton correspondant dans cette liste.

          -
        1. Fortifiant : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables. Pour la version avanc\xE9e, ajouter un pr\xE9dicat fortiviantAvance
        2. -
        3. Feu gr\xE9geois : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables. Pas de support pour la version avanc\xE9e pour l'instant : utiliser !cof-dmg rang --feu pour les personnages qui auraient rat\xE9 leur jet de DEX.
        4. -
        5. Huile instable : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
        6. -
        7. \xC9lixir de gu\xE9rison : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
        8. -
        9. \xC9lixirs de Protection : cr\xE9ation \xE0 l'aide de !cof-elixirs, et utilisation avec la m\xEAme commande, ou bien en utilisant !cof-consommables.
        10. +
        11. Fortifiant : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables. Pour la version avancée, ajouter un prédicat fortiviantAvance
        12. +
        13. Feu grégeois : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables. Pas de support pour la version avancée pour l'instant : utiliser !cof-dmg rang --feu pour les personnages qui auraient raté leur jet de DEX.
        14. +
        15. Huile instable : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
        16. +
        17. Élixir de guérison : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.
        18. +
        19. Élixirs de Protection : création à l'aide de !cof-elixirs, et utilisation avec la même commande, ou bien en utilisant !cof-consommables.

        Voie des arts druidiques

        1. Langage des animaux : En Attente
        2. -
        3. Nu\xE9e d\x2019insectes* : En Attente
        4. +
        5. Nuée d’insectes* : En Attente
        6. Le guetteur : En Attente
        7. -
        8. Masque du pr\xE9dateur* : En Attente
        9. -
        10. Sagesse h\xE9ro\xEFque : En Attente
        11. +
        12. Masque du prédateur* : En Attente
        13. +
        14. Sagesse héroïque : En Attente

        Voie de la divination

          -
        1. Sixi\xE8me sens : ajouter le bonus en DEF divers et initiative divers, ajouter une comp\xE9tence vigilance, de valeur 5 (le bonus aux jet de surprise).
        2. -
        3. D\xE9tection de l\x2019invisible* : En Attente
        4. +
        5. Sixième sens : ajouter le bonus en DEF divers et initiative divers, ajouter une compétence vigilance, de valeur 5 (le bonus aux jet de surprise).
        6. +
        7. Détection de l’invisible* : En Attente
        8. Clairvoyance* : En Attente
        9. Prescience* : En Attente
        10. Hyperconscience : En Attente
        -

        Voie de l\x2019envo\xFBtement

        +

        Voie de l’envoûtement

        1. Injonction* : En Attente
        2. Sommeil* : En Attente
        3. Confusion* : En Attente
        4. -
        5. Amiti\xE9* : En Attente
        6. +
        7. Amitié* : En Attente
        8. Domination* : En Attente
        -

        Voie des for\xEAts

        +

        Voie des forêts

          -
        1. Peau d\x2019\xE9corce* : - !cof-effet-temp peauDEcorce [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 1|\xC9conome (L),--mana 0|\xC9tendue (L),--puissant duree --mana 1}. Si le personnage a un pr\xE9dicat voieDesForets de valeur 4 ou plus, le bonus sera de +4 en DEF. Ajouter un pr\xE9dicat peauDEcorceAvancee pour la version en capacit\xE9 avanc\xE9e.
        2. -
        3. Prison v\xE9g\xE9tale* : En Attente
        4. +
        5. Peau d’écorce* : + !cof-effet-temp peauDEcorce [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 1|Économe (L),--mana 0|Étendue (L),--puissant duree --mana 1}. Si le personnage a un prédicat voieDesForets de valeur 4 ou plus, le bonus sera de +4 en DEF. Ajouter un prédicat peauDEcorceAvancee pour la version en capacité avancée.
        6. +
        7. Prison végétale* : En Attente
        8. Baies magiques* : En Attente
        9. -
        10. Animation d\x2019un arbre* : En Attente
        11. -
        12. R\xE9g\xE9n\xE9ration* : En Attente
        13. +
        14. Animation d’un arbre* : En Attente
        15. +
        16. Régénération* : En Attente

        Voie des illusions

          -
        1. Image d\xE9cal\xE9e* : !cof-effet-temp imageDecalee [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 1|\xC9conome (L),--mana 0|\xC9tendue (L),--puissant duree --mana 1}. Pour la version avanc\xE9e de la capacit\xE9, ajouter un pr\xE9dicat imageDecaleeAvancee.
        2. +
        3. Image décalée* : !cof-effet-temp imageDecalee [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 1|Économe (L),--mana 0|Étendue (L),--puissant duree --mana 1}. Pour la version avancée de la capacité, ajouter un prédicat imageDecaleeAvancee.
        4. Mirage* : En Attente
        5. Imitation* : En Attente
        6. -
        7. D\xE9doublement* : En Attente
        8. +
        9. Dédoublement* : En Attente
        10. Tueur fantasmagorique* : En Attente
        -

        Voie de la magie \xE9l\xE9mentaliste

        +

        Voie de la magie élémentaliste

        1. Brumes* : - !cof-tenebres @{selected|token_id} @{target|token_id} --brumes --mana 1. La commande pose un token de brouillard pour visualiser la zone. Tous les tokens pr\xE9sents dans la zone au lancement du sort sont automatiquement dans l'\xE9tat p\xE9nombre. Au MJ ensuite d'enlever l'\xE9tat p\xE9nombre quand les cibles sortent de la zone. A la fin de la dur\xE9e du sort, ou \xE0 la fin du combat, la zone et les \xE9tats p\xE9nombre restant disparaissent automatiquement. Il est aussi possible de changer les valeurs par d\xE9faut du sort (port\xE9e 20m, rayon 20m) avec les options --portee X et --rayon X. En r\xE8gle custom, l'option puissant permet de doubler la superficie couverte (le script calcule le rayon appropri\xE9 si custom).
        2. + !cof-tenebres @{selected|token_id} @{target|token_id} --brumes --mana 1. La commande pose un token de brouillard pour visualiser la zone. Tous les tokens présents dans la zone au lancement du sort sont automatiquement dans l'état pénombre. Au MJ ensuite d'enlever l'état pénombre quand les cibles sortent de la zone. A la fin de la durée du sort, ou à la fin du combat, la zone et les états pénombre restant disparaissent automatiquement. Il est aussi possible de changer les valeurs par défaut du sort (portée 20m, rayon 20m) avec les options --portee X et --rayon X. En règle custom, l'option puissant permet de doubler la superficie couverte (le script calcule le rayon approprié si custom).
        3. Sous tension* :
            -
          • !cof-effet-temp sousTension [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 2|\xC9conome (L),--mana 0|\xC9tendue (L),--puissant duree --mana 2|Puissante (L),--puissant --mana 2} pour lancer le sort et mettre le personnage sous tension
          • -
          • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, port\xE9e 10, type Sortil\xE8ge, d\xE9g\xE2ts \xE9lectriques, options --si etat sousTension --fx beam-holy.
          • -
          • Utiliser un pr\xE9dicat voieDeLaMagieElementaliste de valeur le rang dans la voie pour le passage des d\xE9g\xE2ts \xE0 2d6 quand le personnage est touch\xE9.
          • -
          • Pas de support particulier pour la version avanc\xE9e.
          • +
          • !cof-effet-temp sousTension [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 2|Économe (L),--mana 0|Étendue (L),--puissant duree --mana 2|Puissante (L),--puissant --mana 2} pour lancer le sort et mettre le personnage sous tension
          • +
          • Ajouter une attaque sur la fiche utilisant l'attaque magique, dommages 1d6+INT, portée 10, type Sortilège, dégâts électriques, options --si etat sousTension --fx beam-holy.
          • +
          • Utiliser un prédicat voieDeLaMagieElementaliste de valeur le rang dans la voie pour le passage des dégâts à 2d6 quand le personnage est touché.
          • +
          • Pas de support particulier pour la version avancée.
        4. Armure de terre* : - bien utiliser un pr\xE9dicat voieDeLaMagieElementaliste avec comme valeur le rang dans la voie. Pour lancer le sort, faire !cof-effet-temp protectionContreLesElements [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 3|\xC9conome (L),--mana 1|\xC9tendue (L),--puissant duree --mana 3}.
        5. + bien utiliser un prédicat voieDeLaMagieElementaliste avec comme valeur le rang dans la voie. Pour lancer le sort, faire !cof-effet-temp protectionContreLesElements [[5+@{selected|SAG}]] ?{Magie|Normale,--mana 3|Économe (L),--mana 1|Étendue (L),--puissant duree --mana 3}.
        6. Boule de feu* : En Attente
        7. -
        8. Intelligence h\xE9ro\xEFque : En Attente
        9. +
        10. Intelligence héroïque : En Attente

        Voie de la magie runique

          -
        1. Forgeron* : Il faut un pr\xE9dicat voieDuMetal pour conna\xEEtre le rang (ou utiliser l'option --valeur). Lancer le sort avec !cof-effet-temp forgeron(L) [[5+@{selected|SAG}]] o\xF9 L est le label d'une attaque. Ensuite, chaque fois que cette attaque sera utilis\xE9e, les d\xE9g\xE2ts seront ajout\xE9s. Limitations : si deux attaques utilisent la m\xEAme arme, il faut faire deux fois l'action, une pour chaque attaque.
        2. -
        3. Rune d\x2019\xE9nergie* : En Attente
        4. +
        5. Forgeron* : Il faut un prédicat voieDuMetal pour connaître le rang (ou utiliser l'option --valeur). Lancer le sort avec !cof-effet-temp forgeron(L) [[5+@{selected|SAG}]]L est le label d'une attaque. Ensuite, chaque fois que cette attaque sera utilisée, les dégâts seront ajoutés. Limitations : si deux attaques utilisent la même arme, il faut faire deux fois l'action, une pour chaque attaque.
        6. +
        7. Rune d’énergie* : En Attente
        8. Rune de puissance* : En Attente
        9. Rune de garde* : En Attente
        10. Rune de tradition : En Attente

        Voie du mysticisme

          -
        1. B\xE9n\xE9diction* : En Attente
        2. +
        3. Bénédiction* : En Attente
        4. Protection contre le mal* : En Attente
        5. -
        6. D\xE9livrance* : En Attente
        7. +
        8. Délivrance* : En Attente
        9. Sanctuaire* : En Attente
        10. Rituel de puissance : En Attente

        Voie des sombres savoirs

        1. Saignements* : En Attente
        2. -
        3. Mal\xE9diction* : En Attente
        4. +
        5. Malédiction* : En Attente
        6. Pacte sanglant* : En Attente
        7. -
        8. H\xE9morragie* : En Attente
        9. -
        10. Invocation d\x2019un d\xE9mon* : En Attente
        11. +
        12. Hémorragie* : En Attente
        13. +
        14. Invocation d’un démon* : En Attente

        5.4 Voies de prestige

        -

        6. Markers Personnalis\xE9s

        -

        6.1 Pr\xE9sentation

        +

        6. Markers Personnalisés

        +

        6.1 Présentation

        -

        Roll20 peut \xEAtre d\xE9routant lors des premi\xE8res utilisations pour des joueurs plus habitu\xE9s au Jeu de R\xF4le sur table. Il introduit des notions peu courantes du fait que les combats vont se d\xE9rouler sur des "battlemaps" quadrill\xE9es ou non. Aussi on va prendre quelques minutes pour expliquer deux notions importantes : les tokens et les tokens markers (plus simplement appel\xE9s markers par la suite).

        -

        Le token : Un token est la repr\xE9sentation graphique d'un personnage (PJ ou PNJ) sur la battlemap. Gr\xE2ce au token on sait \xE0 tout moment o\xF9 se trouve le personnage, s'il subit un sort \xE0 effet de zone ou si sa ligne de tir est d\xE9gag\xE9e par exemple.

        -

        Le marker : Un marker est forc\xE9ment attach\xE9 \xE0 un token. Il repr\xE9sente un "\xE9tat" qui affecte le personnage (liste des \xE9tats). Il se mat\xE9rialise par une ic\xF4ne dans le coin en haut \xE0 doite du token. Un token peut afficher plusieurs markers au m\xEAme moment. Ils repr\xE9sentent plusieurs \xE9tats qui se cumulent pour ce personnage. +

        Roll20 peut être déroutant lors des premières utilisations pour des joueurs plus habitués au Jeu de Rôle sur table. Il introduit des notions peu courantes du fait que les combats vont se dérouler sur des "battlemaps" quadrillées ou non. Aussi on va prendre quelques minutes pour expliquer deux notions importantes : les tokens et les tokens markers (plus simplement appelés markers par la suite).

        +

        Le token : Un token est la représentation graphique d'un personnage (PJ ou PNJ) sur la battlemap. Grâce au token on sait à tout moment où se trouve le personnage, s'il subit un sort à effet de zone ou si sa ligne de tir est dégagée par exemple.

        +

        Le marker : Un marker est forcément attaché à un token. Il représente un "état" qui affecte le personnage (liste des états). Il se matérialise par une icône dans le coin en haut à doite du token. Un token peut afficher plusieurs markers au même moment. Ils représentent plusieurs états qui se cumulent pour ce personnage.

        -

        Dans l'image ci-dessus le token c'est le personnage \xE0 la cape bleue qui repr\xE9sente un PJ et le marker c'est le petit escargot qui signifie que ce m\xEAme PJ est "ralenti". Le script g\xE8re les \xE9tats des PJ et PNJ et il mat\xE9rialisera leurs \xE9tats gr\xE2ce aux markers. Par exemple le MJ va demande un jet de surprise, le script effectue les jets de d\xE9s n\xE9cessaire et mat\xE9rialise l'\xE9tat "surpris" gr\xE2ce \xE0 un marker pour les personnages qui ont rat\xE9 leur jet de d\xE9. Le script applique automatiquement le malus -5 \xE0 la DEF. Au bout d'un tour l'\xE9tat "surpris" et le marker seront retir\xE9s automatiquement par le script. Le MJ peut aussi mettre directement un \xE9tat \xE0 un personnage. Par exemple s'il consid\xE8re que ses PJs voyagent trop charg\xE9s il peut ajouter le marker "encombr\xE9" qui lui rappelera que dor\xE9navant les jets de DEX se font sur un d12 et plus sur un d20.

        -

        Il existe des markers qui ne repr\xE9sentent pas un \xE9tat mais ils sont rares. On peut souligner les ronds de couleurs qui permmettent au joueur de retrouver son token plus facilement. De la m\xEAme mani\xE8re dans les markers cof il y existent deux marqueurs cof-init... qui permettent de rep\xE9rer le prochain joueur pendant les combats. Ce n'est pas un \xE9tat.

        +

        Dans l'image ci-dessus le token c'est le personnage à la cape bleue qui représente un PJ et le marker c'est le petit escargot qui signifie que ce même PJ est "ralenti". Le script gère les états des PJ et PNJ et il matérialisera leurs états grâce aux markers. Par exemple le MJ va demande un jet de surprise, le script effectue les jets de dés nécessaire et matérialise l'état "surpris" grâce à un marker pour les personnages qui ont raté leur jet de dé. Le script applique automatiquement le malus -5 à la DEF. Au bout d'un tour l'état "surpris" et le marker seront retirés automatiquement par le script. Le MJ peut aussi mettre directement un état à un personnage. Par exemple s'il considère que ses PJs voyagent trop chargés il peut ajouter le marker "encombré" qui lui rappelera que dorénavant les jets de DEX se font sur un d12 et plus sur un d20.

        +

        Il existe des markers qui ne représentent pas un état mais ils sont rares. On peut souligner les ronds de couleurs qui permmettent au joueur de retrouver son token plus facilement. De la même manière dans les markers cof il y existent deux marqueurs cof-init... qui permettent de repérer le prochain joueur pendant les combats. Ce n'est pas un état.

        -

        6.2 R\xE9cup\xE9ration des markers d\xE9di\xE9s COF

        +

        6.2 Récupération des markers dédiés COF

        -

        Roll20 poss\xE8de des markers par d\xE9faut mais ils ne sont pas toujours adapt\xE9s pour Chroniques Oubli\xE9es Fantasy. La communaut\xE9 a vot\xE9 pour choisir les tokens les plus pertinents dans le contexte COF. Voici le lien vers le post dans le forum BBE. N'h\xE9sitez pas \xE0 venir poser vos questions ou proposer vos talents de graphiste \xE0 la communaut\xE9.

        -

        Avant de pouvoir cr\xE9er votre propre jeu de markers sur Roll20, vous devez pr\xE9alablement t\xE9l\xE9charger ceux mis \xE0 disposition par la communaut\xE9 depuis le repository GitHub du projet. Proc\xE9dez comme suit :

        +

        Roll20 possède des markers par défaut mais ils ne sont pas toujours adaptés pour Chroniques Oubliées Fantasy. La communauté a voté pour choisir les tokens les plus pertinents dans le contexte COF. Voici le lien vers le post dans le forum BBE. N'hésitez pas à venir poser vos questions ou proposer vos talents de graphiste à la communauté.

        +

        Avant de pouvoir créer votre propre jeu de markers sur Roll20, vous devez préalablement télécharger ceux mis à disposition par la communauté depuis le repository GitHub du projet. Procédez comme suit :

        -

        Une fois le fichier t\xE9l\xE9charg\xE9 sur votre PC d\xE9zippez le r\xE9pertoire cof-marker-set et son sous-r\xE9pertoire

        +

        Une fois le fichier téléchargé sur votre PC dézippez le répertoire cof-marker-set et son sous-répertoire

        6.3 Importation des markers dans Roll20

        -

        Dans le r\xE9pertoire cof-marker-set vous trouverez tous les markers qui ont \xE9t\xE9 choisis par la communaut\xE9. Dans le r\xE9pertoire markers-alternatifs vous trouverez les glorieux seconds au vote que vous pouvez utiliser en lieu et place du marker choisi s'il vous pla\xEEt plus. Il vous suffit alors de glisser-d\xE9poser le fichier dans le r\xE9pertoire principal et de confirmer l'\xE9crasement de l'autre marker. Vous pouvez aussi choisir vos propres markers dans cette g\xE9niale biblioth\xE9que d'ic\xF4nes. Vous pouvez aussi d\xE9ssiner vos propre marker. Les limites sont que la taille de l'image doit \xEAtre exactement de 512x512 px. Un fichier PNG est pr\xE9f\xE9rable pour g\xE9rer la transparence. Enfin votre fichier doit porter exactement le m\xEAme nom qu'indiqu\xE9 dans cette documentation.

        +

        Dans le répertoire cof-marker-set vous trouverez tous les markers qui ont été choisis par la communauté. Dans le répertoire markers-alternatifs vous trouverez les glorieux seconds au vote que vous pouvez utiliser en lieu et place du marker choisi s'il vous plaît plus. Il vous suffit alors de glisser-déposer le fichier dans le répertoire principal et de confirmer l'écrasement de l'autre marker. Vous pouvez aussi choisir vos propres markers dans cette géniale bibliothéque d'icônes. Vous pouvez aussi déssiner vos propre marker. Les limites sont que la taille de l'image doit être exactement de 512x512 px. Un fichier PNG est préférable pour gérer la transparence. Enfin votre fichier doit porter exactement le même nom qu'indiqué dans cette documentation.

        Dans Roll20 rendez-vous dans le menu "Outils" puis "Token Marker Library". Appuyez sur "Create Set". Puis renseignez le nom du marker set. "cof markers" par exemple. Appuyez sur "Create Set".

        -

        Vous arrivez alors sur la fen\xEAtre suivante o\xF9 il suffit de d\xE9poser les fichiers pour qu'ils soient upload\xE9s sur Roll20

        +

        Vous arrivez alors sur la fenêtre suivante où il suffit de déposer les fichiers pour qu'ils soient uploadés sur Roll20

        -

        A ce moment il y a deux \xE9coles de vie : ceux qui l\xE2chent tous leurs markers en m\xEAme temps et qui laisse le soin aux serveurs de Roll20 de d\xE9cider dans quel ordre ils verront appara\xEEtre les markers dans leur interface pour le restant de leur jour. Et ceux qui posent les fichiers un par un pour que l'ordre qu'ils souhaitent soit respect\xE9 par Roll20. Quand tout est pr\xEAt cliquez sur "Upload". Vous avez un message "Fichiers en cours de traitement" pendant 1 \xE0 2 minutes. Ensuite Roll20 vous propose de renommer vos tokens. Ne changez rien et fa\xEEtes "Save". Ca y est, vos markers personnalis\xE9s sont enfin pr\xEAts !

        +

        A ce moment il y a deux écoles de vie : ceux qui lâchent tous leurs markers en même temps et qui laisse le soin aux serveurs de Roll20 de décider dans quel ordre ils verront apparaître les markers dans leur interface pour le restant de leur jour. Et ceux qui posent les fichiers un par un pour que l'ordre qu'ils souhaitent soit respecté par Roll20. Quand tout est prêt cliquez sur "Upload". Vous avez un message "Fichiers en cours de traitement" pendant 1 à 2 minutes. Ensuite Roll20 vous propose de renommer vos tokens. Ne changez rien et faîtes "Save". Ca y est, vos markers personnalisés sont enfin prêts !

        -

        6.4 Activation et V\xE9rification

        +

        6.4 Activation et Vérification

        -

        Mais ce n'est pas fini il vous faut encore affecter vos markers \xE0 votre campagne. Cela se passe sur la page d'acceuil de votre campagne:

        +

        Mais ce n'est pas fini il vous faut encore affecter vos markers à votre campagne. Cela se passe sur la page d'acceuil de votre campagne:

        -

        Lancez votre campagne et v\xE9rifiez que les nouveaux markers apparaissent bien. Lancez ensuite la commande !cof-options pour cocher "Markers Personnalises". Enfin comme dernier contr\xF4le allez dans la console des API, fa\xEEtes "restart API sandbox" et v\xE9rifiez que le message "Markers personnalis\xE9s activ\xE9s" est bien pr\xE9sent. Si ce n'est pas le cas vous avez probablement oubli\xE9 des markers "obligatoires" et le script n'a pas pu activer les markers cof pour cette raison. La liste des markers manquants devrait appara\xEEtre dans la console.

        +

        Lancez votre campagne et vérifiez que les nouveaux markers apparaissent bien. Lancez ensuite la commande !cof-options pour cocher "Markers Personnalises". Enfin comme dernier contrôle allez dans la console des API, faîtes "restart API sandbox" et vérifiez que le message "Markers personnalisés activés" est bien présent. Si ce n'est pas le cas vous avez probablement oublié des markers "obligatoires" et le script n'a pas pu activer les markers cof pour cette raison. La liste des markers manquants devrait apparaître dans la console.

        7. Console API

        -

        7.1 G\xE9n\xE9ralit\xE9s sur la Console

        +

        7.1 Généralités sur la Console

        -

        Il est recommand\xE9 quand vous jouez de garder un onglet de votre navigateur ouvert sur la Console API de votre campagne (Param\xE8tres -> Scripts API). En cas d'absence de r\xE9ponse du jeu il vous permet de facilement prendre connaissance d'une \xE9ventuelle erreur et de prendre rapidement les actions correctives n\xE9cessaires.

        -

        Un message bloquant est \xE9crit dans un bloc rouge en dehors de la fen\xEAtre API Output Console et ressemble \xE0 l'image suivante :

        +

        Il est recommandé quand vous jouez de garder un onglet de votre navigateur ouvert sur la Console API de votre campagne (Paramètres -> Scripts API). En cas d'absence de réponse du jeu il vous permet de facilement prendre connaissance d'une éventuelle erreur et de prendre rapidement les actions correctives nécessaires.

        +

        Un message bloquant est écrit dans un bloc rouge en dehors de la fenêtre API Output Console et ressemble à l'image suivante :

        -

        Lorsqu'un message rouge comme celui-ci interrompt votre partie v\xE9rifiez s'il poss\xE8de une solution identifi\xE9e dans le paragraphe ci-dessous. "Restart API sandbox" permet de relancer le script mais les m\xEAmes causes provoqueront la m\xEAme erreur. Si le message d'erreur n'est pas encore r\xE9f\xE9renc\xE9 ou ne propose pas de solution, essayez de comprendre quelle est votre derni\xE8re action ou quel bouton provoque cette erreur et terminez votre s\xE9ance en \xE9vitant de l'utiliser. Retestez plus tard et si l'erreur se reproduit expliquez-nous votre probl\xE8me sur ce post dans le forum BBE. Essayez d'\xEAtre le plus exhaustif possible dans vos explications car malheureusement les messages de Roll20 ne sont pas pr\xE9cis du tout quant au contexte de l'erreur. Par exemple le num\xE9ro de la ligne de code incrimin\xE9e ne nous est pas connue et l'on a donc besoin de toutes les pr\xE9cisions possibles pour comprendre le probl\xE8me et \xEAtre en capacit\xE9 de le reproduire afin de le corriger.

        -

        Les messages qui sont \xE0 l'interieur de la fen\xEAtre API Output Console sont des messages d'information ou d'alerte comme sur l'image suivante :

        +

        Lorsqu'un message rouge comme celui-ci interrompt votre partie vérifiez s'il possède une solution identifiée dans le paragraphe ci-dessous. "Restart API sandbox" permet de relancer le script mais les mêmes causes provoqueront la même erreur. Si le message d'erreur n'est pas encore référencé ou ne propose pas de solution, essayez de comprendre quelle est votre dernière action ou quel bouton provoque cette erreur et terminez votre séance en évitant de l'utiliser. Retestez plus tard et si l'erreur se reproduit expliquez-nous votre problème sur ce post dans le forum BBE. Essayez d'être le plus exhaustif possible dans vos explications car malheureusement les messages de Roll20 ne sont pas précis du tout quant au contexte de l'erreur. Par exemple le numéro de la ligne de code incriminée ne nous est pas connue et l'on a donc besoin de toutes les précisions possibles pour comprendre le problème et être en capacité de le reproduire afin de le corriger.

        +

        Les messages qui sont à l'interieur de la fenêtre API Output Console sont des messages d'information ou d'alerte comme sur l'image suivante :

        -

        Malgr\xE9 la gravit\xE9 apparente de certains de ces messages (SyntaxError) ils n'emp\xEAchent jamais le bon fonctionnement du script. Seuls les messages bloquants apparaissants en rouge emp\xEAche le bon fonctionnement du script. Nous n'avons pas compl\xE9tement la main sur l'apparition de ces messages d'alerte et nous travaillons activement avec Roll20 pour les \xE9liminer. Des messages d'informations sont aussi pr\xE9sents comme par exemple le num\xE9ro de version du script que vous utilisez actuellement.

        +

        Malgré la gravité apparente de certains de ces messages (SyntaxError) ils n'empêchent jamais le bon fonctionnement du script. Seuls les messages bloquants apparaissants en rouge empêche le bon fonctionnement du script. Nous n'avons pas complétement la main sur l'apparition de ces messages d'alerte et nous travaillons activement avec Roll20 pour les éliminer. Des messages d'informations sont aussi présents comme par exemple le numéro de version du script que vous utilisez actuellement.

        7.2 Principaux messages bloquants

          -
        • There was an error communicating with the QuantumRoll server Erreur Roll20 courante. "Restart API Sandbox" r\xE8gle normalement ce probl\xE8me.
        • -
        • docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host? Erreur Roll20. "Restart API Sandbox" r\xE8gle normalement ce probl\xE8me.
        • -
        • SyntaxError: Invalid or unexpected token ... Erreur dans le code. Pas de solution \xE9vidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • -
        • SyntaxError: Unexpected token ... Erreur dans le code. Pas de solution \xE9vidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • -
        • TypeError: Cannot read property '...' of undefined Erreur dans le code. Pas de solution \xE9vidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • +
        • There was an error communicating with the QuantumRoll server Erreur Roll20 courante. "Restart API Sandbox" règle normalement ce problème.
        • +
        • docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host? Erreur Roll20. "Restart API Sandbox" règle normalement ce problème.
        • +
        • SyntaxError: Invalid or unexpected token ... Erreur dans le code. Pas de solution évidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • +
        • SyntaxError: Unexpected token ... Erreur dans le code. Pas de solution évidente. Le signaler uniquement si c'est un message bloquant (rouge).
        • +
        • TypeError: Cannot read property '...' of undefined Erreur dans le code. Pas de solution évidente. Le signaler uniquement si c'est un message bloquant (rouge).

        7.3 Principaux messages d'information et d'alerte

          -
        • COFantasy X.XX loaded Information : Le script a correctement d\xE9marr\xE9. Vous indique le num\xE9ro de version utilis\xE9.
        • -
        • Markers personnalis\xE9s activ\xE9s Information : Succ\xE8s de l'activation des Markers Personnalis\xE9s.
        • +
        • COFantasy X.XX loaded Information : Le script a correctement démarré. Vous indique le numéro de version utilisé.
        • +
        • Markers personnalisés activés Information : Succès de l'activation des Markers Personnalisés.
        • API sandbox shutdown due to campaign inactivity Information : "Restart API Sandbox" ou l'utilisation de la campagne remet en route la sandbox.
        • -
        • XXX dans l'\xE9quipe XXX est inconnu Alerte : Erreur dans le handout servant de s\xE9lection d'\xE9quipe. V\xE9rifiez l'orthographe de vos personnages.
        • -
        • Markers personnalis\xE9s manquants -> Retour aux markers standards Roll20. Voir erreur(s) ci-dessus. Alerte : Impossibilit\xE9 d'activer les Markers Personnalis\xE9s pour cause d'un marker obligatoire absent.
        • -
        • Marker cof-XXX introuvable Alerte : Erreur dans le nom d'un marker. Voir Markers Personnalis\xE9s ou liste des \xE9tats.
        • -
        • Comp\xE9tences sans caract\xE9ristique associ\xE9eAlerte : Erreur de d\xE9claration dans le handout de jets de caract\xE9ristique.
        • +
        • XXX dans l'équipe XXX est inconnu Alerte : Erreur dans le handout servant de sélection d'équipe. Vérifiez l'orthographe de vos personnages.
        • +
        • Markers personnalisés manquants -> Retour aux markers standards Roll20. Voir erreur(s) ci-dessus. Alerte : Impossibilité d'activer les Markers Personnalisés pour cause d'un marker obligatoire absent.
        • +
        • Marker cof-XXX introuvable Alerte : Erreur dans le nom d'un marker. Voir Markers Personnalisés ou liste des états.
        • +
        • Compétences sans caractéristique associéeAlerte : Erreur de déclaration dans le handout de jets de caractéristique.
        -

        7.4 Purger les variables d'\xE9tat du jeu

        +

        7.4 Purger les variables d'état du jeu

        -

        Pour son bon fonctionnement, le script stoque des donn\xE9es, parfois complexes, et il peut arriver que ces donn\xE9es soient corrompues. Dans ce cas, le script peut planter de mani\xE8re syst\xE9matique, m\xEAme sur des actions simples. Si vous soup\xE7onnez une corruption des donn\xE9es, vous pouvez tenter de lancer la commande !cof-clean-global-state. +

        Pour son bon fonctionnement, le script stoque des données, parfois complexes, et il peut arriver que ces données soient corrompues. Dans ce cas, le script peut planter de manière systématique, même sur des actions simples. Si vous soupçonnez une corruption des données, vous pouvez tenter de lancer la commande !cof-clean-global-state.

        8. Utiliser des personnages Pathfinder

        -

        Il existe un support basique des fiches Roll20 venant du syst\xE8me Pathfinder 1. La fonction !cof-pathfinder1 se lance en s\xE9lectionnant un ou plusieurs tokens li\xE9s \xE0 des fiches Pathfinder (par exemple obtenues en achetant des aventures Pathfinder sur le marketplace de Roll20). L'effet est d'une part de transformer une partie des attributs de la fiche en attributs compris par la fiche COF et le script COFantasy, de changer un peu le token associ\xE9 \xE0 la fiche, mais surtout d'effacer les attributs inutiles pour COF. En effet, le script est relativement sensible au nombre total d'attributs en jeu, et les fiches Pathfinder ont tendence \xE0 en avoir vraiment beaucoup. Tout ce qui n'est pas compris par le script se retrouve dans un attribut Attributs Pathfinder. Mais le mieux est de compl\xE9ter la fiche COF en se basant sur la fiche Pathfinder ouverte dans une autre partie.

        +

        Il existe un support basique des fiches Roll20 venant du système Pathfinder 1. La fonction !cof-pathfinder1 se lance en sélectionnant un ou plusieurs tokens liés à des fiches Pathfinder (par exemple obtenues en achetant des aventures Pathfinder sur le marketplace de Roll20). L'effet est d'une part de transformer une partie des attributs de la fiche en attributs compris par la fiche COF et le script COFantasy, de changer un peu le token associé à la fiche, mais surtout d'effacer les attributs inutiles pour COF. En effet, le script est relativement sensible au nombre total d'attributs en jeu, et les fiches Pathfinder ont tendence à en avoir vraiment beaucoup. Tout ce qui n'est pas compris par le script se retrouve dans un attribut Attributs Pathfinder. Mais le mieux est de compléter la fiche COF en se basant sur la fiche Pathfinder ouverte dans une autre partie.

        9. Statistiques

        Il est possible d'activer la collecte de statistiques en utilisant la commande !cof-demarrer-statistiques.

        -

        On peut arr\xEAter la collecte avec !cof-arreter-statistiques, et la mettre en pause avec !cof-pause-statistiques.
        - Si on red\xE9marre apr\xE8s une mise en pause, on reprend les statistiques comme elles \xE9taient au moment de la pause. Si on red\xE9marre des statistiques en court, cela remet les statistiques \xE0 z\xE9ro. +

        On peut arrêter la collecte avec !cof-arreter-statistiques, et la mettre en pause avec !cof-pause-statistiques.
        + Si on redémarre après une mise en pause, on reprend les statistiques comme elles étaient au moment de la pause. Si on redémarre des statistiques en court, cela remet les statistiques à zéro.

    -

    Ce site utilise des marques d\xE9pos\xE9es et des droits d\x2019auteurs qui sont la propri\xE9t\xE9 de Black Book Editions comme l\x2019y autorisent les conditions d\x2019utilisation de Black Book Editions. Ce site n\x2019est pas publi\xE9 par Black Book Editions et n\x2019a pas re\xE7u son aval ni une quelconque approbation de sa part. Pour de plus amples informations sur Black Book Editions, consultez www.black-book-editions.fr.

    +

    Ce site utilise des marques déposées et des droits d’auteurs qui sont la propriété de Black Book Editions comme l’y autorisent les conditions d’utilisation de Black Book Editions. Ce site n’est pas publié par Black Book Editions et n’a pas reçu son aval ni une quelconque approbation de sa part. Pour de plus amples informations sur Black Book Editions, consultez www.black-book-editions.fr.