- 
+

+

- 
+

+

| - + | -+ | @@ -165,9 +165,9 @@ | - + | -+ | @@ -183,9 +183,9 @@ | - + | -+ | @@ -203,9 +203,9 @@ | - + | -+ | @@ -223,9 +223,9 @@ | - + | -+ | @@ -326,7 +326,7 @@ |
| - | + |
@@ -1452,17 +1452,17 @@
@@ -1954,10 +1954,10 @@
setAttrs({
type_personnage: 'PJ'
});
- getAttrs(["CHARISME", "option_pc", "pc", "pc_max"], function(values) {
+ getAttrs(["charisme", "option_pc", "pc", "pc_max"], function(values) {
var option_pc = values.option_pc;
if (option_pc == 1 || option_pc == 'on') {
- var charisme = parseInt(values.CHARISME);
+ var charisme = parseInt(values.charisme);
if (!isNaN(charisme) && charisme > 0) {
var pc_base = 3 + Math.floor((charisme - 10) / 2);
var toSet = {
@@ -2086,12 +2086,35 @@
setAttrs(sa);
});
}
+ if (verfdp < 4.01) { //changement de nom des attributs de consommables
+ getSectionIDs('repeating_equipement', function(idArray) {
+ idArray.forEach(function(id) {
+ var prefix = 'repeating_equipement_' + id + '_';
+ getAttrs([prefix + 'equip-nom', prefix + 'equip-qte', prefix + 'equip-effet'], function(values) {
+ var sa = {};
+ sa[prefix + 'equip_nom'] = values[prefix + 'equip-nom'];
+ sa[prefix + 'equip_qte'] = values[prefix + 'equip-qte'];
+ sa[prefix + 'equip_effet'] = values[prefix + 'equip-effet'];
+ sa[prefix + 'equip-nom'] = '';
+ sa[prefix + 'equip-qte'] = '';
+ sa[prefix + 'equip-effet'] = '';
+ setAttrs(sa);
+ });
+ });
+ });
+ getAttrs(['equip-div'], function(value) {
+ if (values['equip-div'] !== undefined)
+ setAttrs({
+ equip_div: values['equip-div'],
+ });
+ });
+ }
setAttrs({
- version: 4.00
+ version: 4.01
});
if (values.option_setting == 'arran') {
//Quelques valeurs de départ selon la famille de profil par défaut
- getAttrs(['famille_par_defaut', 'famille', 'CHARISME', 'SAGESSE', 'niveau'], function(values) {
+ getAttrs(['famille_par_defaut', 'famille', 'charisme', 'sagesse', 'niveau'], function(values) {
if (values.famille_par_defaut == 1 && values.famille == 'aventurier') {
var attr = {
fanille_par_defaut: 0,
@@ -2107,13 +2130,13 @@
titrecapaciteraciale: "Trait de peuple",
formations_martiales_check: 1,
};
- var charisme = parseInt(values.CHARISME);
+ var charisme = parseInt(values.charisme);
if (!isNaN(charisme) && charisme > 0) {
attr.pc_base = 4 + Math.floor((charisme - 10) / 2);
attr.pc_max = attr.pc_base;
attr.pc = attr.pc_base;
}
- var sagesse = parseInt(values.SAGESSE);
+ var sagesse = parseInt(values.sagesse);
var niveau = parseInt(values.niveau);
if (!isNaN(sagesse) && sagesse > 0 && !isNaN(niveau) && niveau >= 0) {
attr.pm_max = niveau + Math.floor((sagesse - 10) / 2);
@@ -2274,9 +2297,9 @@
//Conversion quand on passe de PJ à PNJ
if (eventinfo.newValue == 'PNJ') {
getAttrs(
- ["force", "FOR_BONUS", "DEXTERITE", "DEX_BONUS", "CONSTITUTION",
- "CON_BONUS", "INTELLIGENCE", "INT_BONUS", "SAGESSE", "SAG_BONUS",
- "CHARISME", "CHA_BONUS", "INIT_DIV", "DEFARMURE", "DEFARMUREON",
+ ["force", "FOR_BONUS", "dexterite", "DEX_BONUS", "constitution",
+ "CON_BONUS", "intelligence", "INT_BONUS", "sagesse", "SAG_BONUS",
+ "charisme", "CHA_BONUS", "INIT_DIV", "DEFARMURE", "DEFARMUREON",
"DEFBOUCLIER", "DEFBOUCLIERON", "DEFDIV", "PV_max", "FOR_SUP",
"DEX_SUP", "CON_SUP", "INT_SUP", "SAG_SUP", "CHA_SUP", "PV", "RDS",
"jets_caches", "pnj_default_jets_caches",
@@ -2289,25 +2312,25 @@
if (isNaN(attrs.pnj_for)) attrs.pnj_for = 0;
var bonus = parseInt(values.FOR_BONUS);
if (!isNaN(bonus)) attrs.pnj_for += bonus;
- attrs.pnj_init = parseInt(values.DEXTERITE);
+ attrs.pnj_init = parseInt(values.dexterite);
if (isNaN(attrs.pnj_init)) attrs.pnj_init = 10;
attrs.pnj_dex = Math.floor((attrs.pnj_init - 10) / 2);
attrs.pnj_def = 10 + attrs.pnj_dex;
bonus = parseInt(values.DEX_BONUS);
if (!isNaN(bonus)) attrs.pnj_dex += bonus;
- attrs.pnj_con = Math.floor((parseInt(values.CONSTITUTION) - 10) / 2);
+ attrs.pnj_con = Math.floor((parseInt(values.constitution) - 10) / 2);
if (isNaN(attrs.pnj_con)) attrs.pnj_con = 0;
bonus = parseInt(values.CON_BONUS);
if (!isNaN(bonus)) attrs.pnj_con += bonus;
- attrs.pnj_int = Math.floor((parseInt(values.INTELLIGENCE) - 10) / 2);
+ attrs.pnj_int = Math.floor((parseInt(values.intelligence) - 10) / 2);
if (isNaN(attrs.pnj_int)) attrs.pnj_int = 0;
bonus = parseInt(values.INT_BONUS);
if (!isNaN(bonus)) attrs.pnj_int += bonus;
- attrs.pnj_sag = Math.floor((parseInt(values.SAGESSE) - 10) / 2);
+ attrs.pnj_sag = Math.floor((parseInt(values.sagesse) - 10) / 2);
if (isNaN(attrs.pnj_sag)) attrs.pnj_sag = 0;
bonus = parseInt(values.SAG_BONUS);
if (!isNaN(bonus)) attrs.pnj_sag += bonus;
- attrs.pnj_cha = Math.floor((parseInt(values.CHARISME) - 10) / 2);
+ attrs.pnj_cha = Math.floor((parseInt(values.charisme) - 10) / 2);
if (isNaN(attrs.pnj_cha)) attrs.pnj_cha = 0;
bonus = parseInt(values.CHA_BONUS);
if (!isNaN(bonus)) attrs.pnj_cha += bonus;
@@ -2340,7 +2363,7 @@
getSectionIDs('repeating_armes', function(idArray) {
idArray.forEach(function(id) {
var prefix = 'repeating_armes_' + id + '_';
- getAttrs([prefix + 'armelabel', prefix + 'armenom', prefix + 'armeatk', prefix + 'armeatkdiv', prefix + 'armecrit', prefix + 'armedmnbde', prefix + 'armedmde', prefix + 'armedmcar', prefix + 'armedmdiv', prefix + 'armeportee', prefix + 'armespec', prefix + 'armeoptflag', 'niveau', 'force', 'DEXTERITE', 'CONSTITUTION', 'INTELLIGENCE', 'SAGESSE', 'CHARISME', 'ATKCAC_CARAC', 'ATKCAC_DIV', 'ATKTIR_CARAC', 'ATKTIR_DIV', 'ATKMAG_CARAC', 'ATKMAG_DIV'], function(values) {
+ getAttrs([prefix + 'armelabel', prefix + 'armenom', prefix + 'armeatk', prefix + 'armeatkdiv', prefix + 'armecrit', prefix + 'armedmnbde', prefix + 'armedmde', prefix + 'armedmcar', prefix + 'armedmdiv', prefix + 'armeportee', prefix + 'armespec', prefix + 'armeoptflag', 'niveau', 'force', 'dexterite', 'constitution', 'intelligence', 'sagesse', 'charisme', 'ATKCAC_CARAC', 'ATKCAC_DIV', 'ATKTIR_CARAC', 'ATKTIR_DIV', 'ATKMAG_CARAC', 'ATKMAG_DIV'], function(values) {
var label = values[prefix + 'armelabel'];
if (!pnjLabels[label]) {
var attrs = {};
@@ -2370,19 +2393,19 @@
caracAtk = 'force';
break;
case '@{DEX}':
- caracAtk = 'DEXTERITE';
+ caracAtk = 'dexterite';
break;
case '@{CON}':
- caracAtk = 'CONSTITUTION';
+ caracAtk = 'constitution';
break;
case '@{INT}':
- caracAtk = 'INTELLIGENCE';
+ caracAtk = 'intelligence';
break;
case '@{SAG}':
- caracAtk = 'SAGESSE';
+ caracAtk = 'sagesse';
break;
case '@{CHA}':
- caracAtk = 'CHARISME';
+ caracAtk = 'charisme';
break;
default:
return;
@@ -2405,19 +2428,19 @@
caracAtk = 'force';
break;
case '@{DEX}':
- caracAtk = 'DEXTERITE';
+ caracAtk = 'dexterite';
break;
case '@{CON}':
- caracAtk = 'CONSTITUTION';
+ caracAtk = 'constitution';
break;
case '@{INT}':
- caracAtk = 'INTELLIGENCE';
+ caracAtk = 'intelligence';
break;
case '@{SAG}':
- caracAtk = 'SAGESSE';
+ caracAtk = 'sagesse';
break;
case '@{CHA}':
- caracAtk = 'CHARISME';
+ caracAtk = 'charisme';
break;
default:
caracAtk = 0;
@@ -2477,14 +2500,14 @@
if (!isNaN(bonus)) defense += bonus;
bonus = parseInt(values.DEFBOUCLIER) * parseInt(values.DEFBOUCLIERON);
if (!isNaN(bonus)) defense += bonus;
- bonus = Math.floor((parseInt(values.DEXTERITE) - 10) / 2);
+ bonus = Math.floor((parseInt(values.dexterite) - 10) / 2);
if (!isNaN(bonus)) defense += bonus;
setAttrs({
DEFDIV: def - defense
});
}
setAttrs({
- DEXTERITE: carac,
+ dexterite: carac,
});
});
});
@@ -2495,7 +2518,7 @@
var pre_bonus = parseInt(values.CON_BONUS);
if (!isNaN(pre_bonus)) bonus_carac -= pre_bonus;
setAttrs({
- CONSTITUTION: 10 + 2 * bonus_carac,
+ constitution: 10 + 2 * bonus_carac,
});
});
});
@@ -2506,7 +2529,7 @@
var pre_bonus = parseInt(values.INT_BONUS);
if (!isNaN(pre_bonus)) bonus_carac -= pre_bonus;
setAttrs({
- INTELLIGENCE: 10 + 2 * bonus_carac,
+ intelligence: 10 + 2 * bonus_carac,
});
});
});
@@ -2517,7 +2540,7 @@
var pre_bonus = parseInt(values.SAG_BONUS);
if (!isNaN(pre_bonus)) bonus_carac -= pre_bonus;
setAttrs({
- SAGESSE: 10 + 2 * bonus_carac,
+ sagesse: 10 + 2 * bonus_carac,
});
});
});
@@ -2528,12 +2551,12 @@
var pre_bonus = parseInt(values.CHA_BONUS);
if (!isNaN(pre_bonus)) bonus_carac -= pre_bonus;
setAttrs({
- CHARISME: 10 + 2 * bonus_carac,
+ charisme: 10 + 2 * bonus_carac,
});
});
});
on('change:pnj_def', function(eventinfo) {
- getAttrs(["DEFARMURE", "DEFARMUREON", "DEFBOUCLIER", "DEFBOUCLIERON", "DEXTERITE", "pnj_def"], function(values) {
+ getAttrs(["DEFARMURE", "DEFARMUREON", "DEFBOUCLIER", "DEFBOUCLIERON", "dexterite", "pnj_def"], function(values) {
var new_def = parseInt(values.pnj_def);
if (isNaN(new_def)) {
console.log("DEF pnj non définie");
@@ -2544,7 +2567,7 @@
if (!isNaN(bonus)) defense += bonus;
bonus = parseInt(values.DEFBOUCLIER) * parseInt(values.DEFBOUCLIERON);
if (!isNaN(bonus)) defense += bonus;
- bonus = Math.floor((parseInt(values.DEXTERITE) - 10) / 2);
+ bonus = Math.floor((parseInt(values.dexterite) - 10) / 2);
if (!isNaN(bonus)) defense += bonus;
setAttrs({
DEFDIV: new_def - defense,
@@ -2553,16 +2576,16 @@
});
});
on('change:pnj_init', function(eventinfo) {
- getAttrs(["DEXTERITE", "pnj_init"], function(values) {
+ getAttrs(["dexterite", "pnj_init"], function(values) {
var new_init = parseInt(values.pnj_init);
if (isNaN(new_init)) {
console.log("Initiative de PNJ incorrecte");
return;
}
- var dex = parseInt(values.DEXTERITE);
+ var dex = parseInt(values.dexterite);
if (isNaN(dex)) {
setAttrs({
- DEXTERITE: new_init,
+ dexterite: new_init,
INIT_DIV: 0
});
return;
@@ -2571,13 +2594,13 @@
if (new_init % 2 === 0) {
dex--;
setAttrs({
- DEXTERITE: dex
+ dexterite: dex
});
}
} else if (new_init % 2 == 1) {
dex++;
setAttrs({
- DEXTERITE: dex
+ dexterite: dex
});
}
setAttrs({
@@ -2696,13 +2719,13 @@
});
//Mise à jour des stats dérivées
- on('change:CHARISME change:option_pc change:pc_bonus change:famille', function(eventinfo) {
- getAttrs(["CHARISME", "option_pc", "pc_bonus", "pc_base", "pc", "pc_max", "option_setting", "famille"], function(values) {
+ on('change:charisme change:option_pc change:pc_bonus change:famille', function(eventinfo) {
+ getAttrs(['charisme', 'option_pc', 'pc_bonus', 'pc_base', 'pc', 'pc_max', 'option_setting', 'famille'], function(values) {
var toSet = {};
var change;
var option_pc = values.option_pc;
if (option_pc == 1 || option_pc == 'on') {
- var charisme = parseInt(values.CHARISME);
+ var charisme = parseInt(values.charisme);
var pc_bonus = parseInt(values.pc_bonus);
if (!isNaN(charisme) && charisme > 0) {
var pc_base = 3 + Math.floor((charisme - 10) / 2);
@@ -2738,7 +2761,7 @@
});
//Importation de statblocks
- var statsReconnues = {
+ const statsReconnues = {
for: 'pnj_for',
dex: 'pnj_dex',
con: 'pnj_con',
@@ -2772,9 +2795,9 @@
return new RegExp(res, 'gi');
}
- var patternStats = buildRegexp(statsReconnues);
+ const patternStats = buildRegexp(statsReconnues);
- var listeArmes = [{
+ const listeArmes = [{
keys: ['épée', 'epee', 'hache'],
typeattaque: 'Arme 1 main',
typedegats: 'tranchant',
@@ -2806,12 +2829,39 @@
modificateurs: ''
}];
- var mapArmes = listeArmes.reduce(function(res, s) {
- s.keys.forEach(function(k) {
- res[k] = s;
+ function keyListToMap(l) {
+ var res = {};
+ l.forEach(function(s) {
+ s.keys.forEach(function(k) {
+ res[k] = s;
+ });
+ if (s.variantes) {
+ s.variantes = keyListToMap(s.variantes);
+ }
});
return res;
- }, {});
+ }
+
+ const mapArmes = keyListToMap(listeArmes);
+
+ function guessAttackType(nomAttaque, prefix, newAttrs) {
+ var na = nomAttaque.toLowerCase();
+ na.split(' ').forEach(function(mot) {
+ mot = mot.trim();
+ if (mot === '') return;
+ var s = mapArmes[mot];
+ if (s) {
+ newAttrs[prefix + 'typeattaque'] = s.typeattaque;
+ newAttrs[prefix + 'modificateurs'] = s.modificateurs;
+ newAttrs[prefix + 'typedegats'] = s.typedegats;
+ }
+ });
+ if (na.includes('2 mains') || na.includes('deux mains'))
+ newAttrs[prefix + 'typeattaque'] = 'Arme 2 mains';
+ else if (na.includes('attaque magique')) {
+ newAttrs[prefix + 'typeattaque'] = 'Sortilège';
+ }
+ }
on('change:statblock', function(eventinfo) {
getAttrs(['max_attack_label', 'scriptVersion'], function(values) {
@@ -2944,19 +2994,7 @@
if (values.scriptVersion && values.scriptVersion !== '')
newAttrs[prefix + 'optflag'] = 'on';
// On essaie de trouver des valeurs pour le type de l'attaque
- var na = nomAttaque.toLowerCase();
- na.split(' ').forEach(function(mot) {
- mot = mot.trim();
- if (mot === '') return;
- var s = mapArmes[mot];
- if (s) {
- newAttrs[prefix + 'typeattaque'] = s.typeattaque;
- newAttrs[prefix + 'modificateurs'] = s.modificateurs;
- newAttrs[prefix + 'typedegats'] = s.typedegats;
- }
- });
- if (na.includes('2 mains') || na.includes('deux mains'))
- newAttrs[prefix + 'typeattaque'] = 'Arme 2 mains';
+ guessAttackType(nomAttaque, prefix, newAttrs);
lastPrefix = prefix;
previousContainsDM = false;
previousLine = '';
@@ -3022,19 +3060,19 @@
newAttrs.force = caracVal;
break;
case 'pnj_dex':
- newAttrs.DEXTERITE = caracVal;
+ newAttrs.dexterite = caracVal;
break;
case 'pnj_con':
- newAttrs.CONSTITUTION = caracVal;
+ newAttrs.constitution = caracVal;
break;
case 'pnj_int':
- newAttrs.INTELLIGENCE = caracVal;
+ newAttrs.intelligence = caracVal;
break;
case 'pnj_sag':
- newAttrs.SAGESSE = caracVal;
+ newAttrs.sagesse = caracVal;
break;
case 'pnj_cha':
- newAttrs.CHARISME = caracVal;
+ newAttrs.charisme = caracVal;
break;
}
} else {
@@ -3120,7 +3158,7 @@
//Numérotaion des attaques
on('change:repeating_armes:armenom', function(eventinfo) {
- getAttrs(['max_attack_label', 'repeating_armes_armelabel', 'scriptVersion'], function(values) {
+ getAttrs(['max_attack_label', 'repeating_armes_armelabel', 'repeating_armes_armenom', 'scriptVersion'], function(values) {
var currentLabel = parseInt(values.repeating_armes_armelabel);
if (isNaN(currentLabel) || currentLabel === 0) {
currentLabel = parseInt(values.max_attack_label);
@@ -3130,6 +3168,7 @@
max_attack_label: currentLabel,
repeating_armes_armelabel: currentLabel
};
+ guessAttackType(values.repeating_armes_armenom, 'repeating_armes_arme', sa);
if (values.scriptVersion && values.scriptVersion !== '')
sa.repeating_armes_armeoptflag = 'on';
setAttrs(sa);
@@ -3137,7 +3176,7 @@
});
});
on('change:repeating_pnjatk:armenom', function(eventinfo) {
- getAttrs(['max_attack_label', 'repeating_pnjatk_armelabel', 'scriptVersion'], function(values) {
+ getAttrs(['max_attack_label', 'repeating_pnjatk_armelabel', 'repeating_pnjatk_armenom', 'scriptVersion'], function(values) {
var currentLabel = parseInt(values.repeating_pnjatk_armelabel);
if (isNaN(currentLabel) || currentLabel === 0) {
currentLabel = parseInt(values.max_attack_label);
@@ -3147,6 +3186,7 @@
max_attack_label: currentLabel,
repeating_pnjatk_armelabel: currentLabel
};
+ guessAttackType(values.repeating_pnjatk_armenom, 'repeating_pnjatk_arme', sa);
if (values.scriptVersion && values.scriptVersion !== '')
sa.repeating_pnjatk_armeoptflag = 'on';
setAttrs(sa);
@@ -3466,16 +3506,85 @@
});
});
+ //Consommables
+ var listeConsommables = [{
+ keys: ['flèche', 'fleche'],
+ variantes: [{
+ keys: ['enflammée', 'enflammee'],
+ effet: "!cof-attack @{selected|token_id} @{target|token_id} Flèche enflammée --toucher [[@{selected|ATKMAG}]] --dm 1d6 + [[@{selected|INT}]] --portee 30 --fx beam-fire --feu --sortilege --enflamme"
+ }],
+ },{
+ keys: ['force'],
+ variantes: [{
+ keys: ['géant', 'geant'],
+ effet: "!cof-effet-temp forceDeGeant 10",
+ }],
+ },{
+ keys: ['soin', 'soins'],
+ effet: "!cof-soin 1d8",
+ variantes: [{
+ keys: ['léger', 'leger', 'légers', 'legers'],
+ effet: "!cof-soin 1d8+@{selected|niveau}",
+ }, {
+ keys: ['modéré', 'modere', 'modérés', 'moderes'],
+ effet: "!cof-soin 2d8+@{selected|niveau}",
+ }],
+ }];
+
+ const mapConsommables = keyListToMap(listeConsommables);
+
+ on('change:repeating_equipement:equip_nom', function(eventinf) {
+ getAttrs(['repeating_equipement_equip_nom', 'scriptVersion'], function(values) {
+ var tokens = values.repeating_equipement_equip_nom.toLowerCase().trim();
+ if (tokens === '') return;
+ tokens = tokens.split(' ');
+ var parse = [
+ [mapConsommables]
+ ];
+ var effet;
+ tokens.forEach(function(t) {console.log("On traite le token "+t);
+ var updateParse = {};
+ parse.forEach(function(pa, i) {
+ pa.forEach(function(p) {
+ var s = p[t];
+ if (s === undefined) return;
+ if (s.effet && (effet === undefined || effet.rang < i))
+ effet = {
+ rang: i,
+ effet: s.effet
+ };
+ if (s.variantes) {
+ updateParse[i+1] = updateParse[i+1] || [];
+ updateParse[i+1].push(s.variantes);
+ }
+ });
+ });
+ console.log("On a regardé tous les parses");
+ console.log(effet);
+ console.log(updateParse);
+ for (var i in updateParse) {
+ if (i == parse.length) parse.push([]);
+ parse[i] = parse[i].concat(updateParse[i]);
+ }
+ console.log(parse);
+ });
+ if (effet === undefined) return;
+ setAttrs({
+ repeating_equipement_equip_effet: effet.effet,
+ });
+ });
+ });
+
//Fonctions spécifiques aux terres d'Arran
on('change:option_setting', function(eventinfo) {
- getAttrs(['option_setting', 'famille', 'CHARISME', 'pc_bonus'], function(values) {
+ getAttrs(['option_setting', 'famille', 'charisme', 'pc_bonus'], function(values) {
var attrs = {
option_setting_cac: values.option_setting,
option_setting_tir: values.option_setting,
option_setting_mag: values.option_setting,
option_setting_init: values.option_setting,
};
- var charisme = parseInt(values.CHARISME);
+ var charisme = parseInt(values.charisme);
if (!isNaN(charisme) && charisme > 0) {
attrs.pc_base = 3 + Math.floor((charisme - 10) / 2);
} else attrs.pc_base = 0;
@@ -3598,13 +3707,13 @@
});
//Mise à jour de la mana
- on('change:SAGESSE change:option_pm change:niveau change:famille', function(eventinfo) {
- getAttrs(["SAGESSE", "option_pm", "niveau", "pm", "pm_max", "option_setting", "famille"], function(values) {
+ on('change:sagesse change:option_pm change:niveau change:famille', function(eventinfo) {
+ getAttrs(["sagesse", "option_pm", "niveau", "pm", "pm_max", "option_setting", "famille"], function(values) {
if (values.option_setting != 'arran') return;
var toSet = {};
var option_pm = values.option_pm;
if (option_pm == 1 || option_pm == 'on') {
- var sagesse = parseInt(values.SAGESSE);
+ var sagesse = parseInt(values.sagesse);
var niveau = parseInt(values.niveau);
if (!isNaN(sagesse) && sagesse > 0 && !isNaN(niveau) && niveau >= 0) {
var new_pm_max = niveau + Math.floor((sagesse - 10) / 2);
diff --git a/ChroniquesOubliees/sheet.json b/ChroniquesOubliees/sheet.json
index 737109a894..373fcdabde 100644
--- a/ChroniquesOubliees/sheet.json
+++ b/ChroniquesOubliees/sheet.json
@@ -4,7 +4,7 @@
"authors": "Natha, Ulti",
"roll20userid": "75857, 1794854",
"preview": "co_v3.jpg",
- "instructions": "Feuille de Personnage (avec jets) pour [Chroniques Oubliées Fantasy](http://www.black-book-editions.fr/catalogue.php?id=13). Chroniques Oubliées Fantasy est un jeu de rôle médiéval-fantastique complet basé sur le système d20/OGL 3.5. Feuille version 4.00 (14/10/2020). [Lisez-moi](https://github.com/Roll20/roll20-character-sheets/blob/master/ChroniquesOubliees/ReadMe.md). Maintenant compatible avec le setting des terres d'Arran (voir les options de fiche)",
+ "instructions": "Feuille de Personnage (avec jets) pour [Chroniques Oubliées Fantasy](http://www.black-book-editions.fr/catalogue.php?id=13). Chroniques Oubliées Fantasy est un jeu de rôle médiéval-fantastique complet basé sur le système d20/OGL 3.5. Feuille version 4.01 (20/10/2020). [Lisez-moi](https://github.com/Roll20/roll20-character-sheets/blob/master/ChroniquesOubliees/ReadMe.md). Maintenant compatible avec le setting des terres d'Arran (voir les options de fiche)",
"useroptions": [
{
"attribute": "option_pc",
|