mirror of
https://github.com/em-squared/5e-drs.git
synced 2025-10-29 04:34:19 +00:00
outils de création de sorts/monstres/objets
This commit is contained in:
parent
6237f0e6a2
commit
a6986c42c6
48 changed files with 2743 additions and 259 deletions
|
|
@ -89,17 +89,17 @@ module.exports = {
|
|||
hostname: 'https://heros-et-dragons.fr'
|
||||
}
|
||||
],
|
||||
[
|
||||
'@vuepress/pwa',
|
||||
{
|
||||
serviceWorker: true,
|
||||
updatePopup: true,
|
||||
generateSWConfig: {
|
||||
cacheId: 'hddrs',
|
||||
globIgnores: ['**/*.js', '**/*.css', '**/*.html']
|
||||
}
|
||||
}
|
||||
],
|
||||
// [
|
||||
// '@vuepress/pwa',
|
||||
// {
|
||||
// serviceWorker: true,
|
||||
// updatePopup: true,
|
||||
// generateSWConfig: {
|
||||
// cacheId: 'hddrs',
|
||||
// globIgnores: ['**/*.js', '**/*.css', '**/*.html']
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
[
|
||||
'seo',
|
||||
{
|
||||
|
|
@ -117,10 +117,16 @@ module.exports = {
|
|||
// modifiedAt: $page => $page.lastUpdated && new Date($page.lastUpdated),
|
||||
}
|
||||
],
|
||||
// [
|
||||
// '@vuepress/google-analytics',
|
||||
// {
|
||||
// 'ga': '' // UA-00000000-0
|
||||
// }
|
||||
// ]
|
||||
],
|
||||
// extendPageData ($page) {
|
||||
// $page.rawContent = ($page._strippedContent)
|
||||
// },
|
||||
extendPageData ($page) {
|
||||
$page.rawContent = ($page._strippedContent)
|
||||
},
|
||||
markdown: {
|
||||
anchor: {
|
||||
permalinkBefore: false,
|
||||
|
|
@ -135,6 +141,44 @@ module.exports = {
|
|||
})
|
||||
}
|
||||
},
|
||||
additionalPages: [
|
||||
{
|
||||
path: '/mon-grimoire/',
|
||||
frontmatter: {
|
||||
layout: 'MySpellsLayout'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/mon-bestiaire/',
|
||||
frontmatter: {
|
||||
layout: 'MyMonstersLayout'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/mes-objets-magiques/',
|
||||
frontmatter: {
|
||||
layout: 'MyMagicItemsLayout'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/creation-de-sort/',
|
||||
frontmatter: {
|
||||
layout: 'CreateSpellLayout'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/creation-de-monstre-pnj/',
|
||||
frontmatter: {
|
||||
layout: 'CreateMonsterLayout'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/creation-d-objet-magique/',
|
||||
frontmatter: {
|
||||
layout: 'CreateMagicItemLayout'
|
||||
}
|
||||
}
|
||||
],
|
||||
themeConfig: {
|
||||
domain: 'https://staging.heros-et-dragons.fr',
|
||||
repository: 'https://github.com/em-squared/heros-et-dragons-drs',
|
||||
|
|
@ -150,7 +194,7 @@ module.exports = {
|
|||
sidebar: [
|
||||
{
|
||||
title: 'Pour les joueurs',
|
||||
expanded: true,
|
||||
icon: 'mdi-book-open-variant',
|
||||
children: [
|
||||
{
|
||||
title: "Création du personnage",
|
||||
|
|
@ -426,6 +470,7 @@ module.exports = {
|
|||
},
|
||||
{
|
||||
title: 'Pour les meneurs',
|
||||
icon: 'mdi-map',
|
||||
children: [
|
||||
{
|
||||
title: "Créatures & oppositions",
|
||||
|
|
@ -487,6 +532,46 @@ module.exports = {
|
|||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
{
|
||||
title: 'Bibliothèques',
|
||||
icon: 'mdi-book',
|
||||
children: [
|
||||
{
|
||||
title: 'Mon grimoire',
|
||||
path: '/mon-grimoire/',
|
||||
badge: 'mySpells'
|
||||
},
|
||||
{
|
||||
title: 'Mon bestiaire',
|
||||
path: '/mon-bestiaire/',
|
||||
badge: 'myMonsters'
|
||||
},
|
||||
{
|
||||
title: 'Mes objets magiques',
|
||||
path: '/mes-objets-magiques/',
|
||||
badge: 'myMagicItems'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Outils de création',
|
||||
icon: 'mdi-tools',
|
||||
children: [
|
||||
{
|
||||
title: 'Création de sort',
|
||||
path: '/creation-de-sort/'
|
||||
},
|
||||
{
|
||||
title: 'Création de monstre/PNJ',
|
||||
path: '/creation-de-monstre-pnj/'
|
||||
},
|
||||
{
|
||||
title: "Création d'objet magique",
|
||||
path: '/creation-d-objet-magique/'
|
||||
},
|
||||
]
|
||||
},
|
||||
{type: 'divider'},
|
||||
{
|
||||
title: "Licence OGL",
|
||||
path: '/licence-ogl/',
|
||||
|
|
|
|||
|
|
@ -12,3 +12,22 @@ export const armorTypes = {
|
|||
"clibanion": { value: 17, maxDex: 0 },
|
||||
"harnois": { value: 18, maxDex: 0 },
|
||||
}
|
||||
|
||||
export const ARMORTYPES = [
|
||||
{ label: "Aucune", value: null },
|
||||
{ label: "Armure du mage", value: 'armure du mage' },
|
||||
{ label: "Armure naturelle", value: 'armure naturelle' },
|
||||
{ label: "Armure matelassée", value: 'armure matelassée' },
|
||||
{ label: "Armure de cuir", value: 'armure de cuir' },
|
||||
{ label: "Armure de cuir clouté", value: 'armure de cuir clouté' },
|
||||
{ label: "Armure de peau", value: 'armure de peau' },
|
||||
{ label: "Chemise de maille", value: 'chemise de maille' },
|
||||
{ label: "Armure d'écailles", value: "armure d'écailles" },
|
||||
{ label: "Cuirasse", value: 'cuirasse' },
|
||||
{ label: "Demi-plate", value: 'demi-plate' },
|
||||
{ label: "Armure annelée", value: 'armure annelée' },
|
||||
{ label: "Cotte de mailles", value: 'cotte de mailles' },
|
||||
{ label: "Clibanion", value: 'clibanion' },
|
||||
{ label: "Harnois", value: 'harnois' },
|
||||
{ label: "Autre", value: 'custom' },
|
||||
]
|
||||
|
|
|
|||
11
docs/.vuepress/data/classes.js
Normal file
11
docs/.vuepress/data/classes.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
export const CLASSES = [
|
||||
"Barde",
|
||||
"Clerc",
|
||||
"Druide",
|
||||
"Ensorceleur/Sorcelame",
|
||||
"Magicien",
|
||||
"Ombrelame",
|
||||
"Paladin",
|
||||
"Rôdeur",
|
||||
"Sorcier",
|
||||
]
|
||||
17
docs/.vuepress/data/conditions.js
Normal file
17
docs/.vuepress/data/conditions.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
export const CONDITIONS = [
|
||||
{ text: "À terre", value:'a-terre' },
|
||||
{ text: "Assourdi", value: 'assourdi' },
|
||||
{ text: "Aveuglé", value: 'aveugle' },
|
||||
{ text: "Charmé", value: 'charme' },
|
||||
{ text: "Épuisé", value: 'epuise' },
|
||||
{ text: "Empoigné", value: 'empoigne' },
|
||||
{ text: "Empoisonné", value: 'empoisonne' },
|
||||
{ text: "Entravé", value: 'entrave' },
|
||||
{ text: "Étourdi", value: 'etourdi' },
|
||||
{ text: "Inconscient", value: 'inconscient' },
|
||||
{ text: "Invisible", value: 'invisible' },
|
||||
{ text: "Neutralisé", value: 'neutralise' },
|
||||
{ text: "Paralysé", value: 'paralyse' },
|
||||
{ text: "Pétrifié", value: 'petrifie' },
|
||||
{ text: "Terrorisé", value: 'terrorise' },
|
||||
]
|
||||
36
docs/.vuepress/data/damageTypes.js
Normal file
36
docs/.vuepress/data/damageTypes.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
export const DAMAGETYPES = [
|
||||
{ text: "contondants, perforants et tranchants infligés par des attaques non-magiques", value: 'c-p-t-non-magique' },
|
||||
{ text: "contondants, perforants et tranchants infligés par des attaques non-magiques qui ne sont pas en argent", value: 'c-p-t-non-argent' },
|
||||
{ text: "contondants, perforants et tranchants infligés par des attaques non-magiques qui ne sont pas en adamantite", value: 'c-p-t-non-adamantite' },
|
||||
{ text: "contondants et perforants infligés par des attaques non-magiques qui ne sont pas en argent", value: 'c-p-non-argent' },
|
||||
{ text: "contondants et perforants infligés par des attaques non-magiques qui ne sont pas en adamantite", value: 'c-p-non-adamantite' },
|
||||
{ text: "contondants et perforants infligés par des attaques non-magiques", value: 'c-p-non-magique' },
|
||||
{ text: "contondants et tranchants infligés par des attaques non-magiques qui ne sont pas en argent", value: 'c-t-non-argent' },
|
||||
{ text: "contondants et tranchants infligés par des attaques non-magiques qui ne sont pas en adamantite", value: 'c-t-non-adamantite' },
|
||||
{ text: "contondants et tranchants infligés par des attaques non-magiques", value: 'c-t-non-magique' },
|
||||
{ text: "perforants et tranchants infligés par des attaques non-magiques qui ne sont pas en argent", value: 'p-t-non-argent' },
|
||||
{ text: "perforants et tranchants infligés par des attaques non-magiques qui ne sont pas en adamantite", value: 'p-t-non-adamantite' },
|
||||
{ text: "perforants et tranchants infligés par des attaques non-magiques", value: 'p-t-non-magique' },
|
||||
{ text: "tranchants infligés par des attaques non-magiques qui ne sont pas en argent", value: 't-non-argent' },
|
||||
{ text: "tranchants infligés par des attaques non-magiques qui ne sont pas en adamantite", value: 't-non-adamantite' },
|
||||
{ text: "tranchants infligés par des attaques non-magiques", value: 't-non-magique' },
|
||||
{ text: "perforants infligés par des attaques non-magiques qui ne sont pas en argent", value: 'p-non-argent' },
|
||||
{ text: "perforants infligés par des attaques non-magiques qui ne sont pas en adamantite", value: 'p-non-adamantite' },
|
||||
{ text: "perforants infligés par des attaques non-magiques", value: 'p-non-magique' },
|
||||
{ text: "contondants infligés par des attaques non-magiques qui ne sont pas en argent", value: 'c-non-argent' },
|
||||
{ text: "contondants infligés par des attaques non-magiques qui ne sont pas en adamantite", value: 'c-non-adamantite' },
|
||||
{ text: "contondants infligés par des attaques non-magiques", value: 'c-non-magique' },
|
||||
{ text: "d'acide", value: 'acide' },
|
||||
{ text: "contondants", value: 'contondant' },
|
||||
{ text: "de feu", value: 'feu' },
|
||||
{ text: "de force", value: 'force' },
|
||||
{ text: "de foudre", value: 'foudre' },
|
||||
{ text: "de froid", value: 'froid' },
|
||||
{ text: "nécrotiques", value: 'necrotique' },
|
||||
{ text: "perforants", value: 'perforant' },
|
||||
{ text: "de poison", value: 'poison' },
|
||||
{ text: "psychiques", value: 'psychique' },
|
||||
{ text: "radiants", value: 'radiant' },
|
||||
{ text: "de tonnerre", value: 'tonnerre' },
|
||||
{ text: "tranchants", value: 'tranchant' },
|
||||
]
|
||||
19
docs/.vuepress/data/languages.js
Normal file
19
docs/.vuepress/data/languages.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
export const LANGUAGES = [
|
||||
{ text: 'Commun', value: 'commun' },
|
||||
{ text: 'Elfe', value: 'elfe' },
|
||||
{ text: 'Géant', value: 'géant' },
|
||||
{ text: 'Gnome', value: 'gnome' },
|
||||
{ text: 'Gobelin', value: 'gobelin' },
|
||||
{ text: 'Halfelin', value: 'halfelin' },
|
||||
{ text: 'Nain', value: 'nain' },
|
||||
{ text: 'Orc', value: 'orc' },
|
||||
{ text: 'Abyssal', value: 'abyssal' },
|
||||
{ text: 'Céleste', value: 'céleste' },
|
||||
{ text: 'Commun des profondeurs', value: 'commun des profondeurs' },
|
||||
{ text: 'Draconique', value: 'draconique' },
|
||||
{ text: 'Infernal', value: 'infernal' },
|
||||
{ text: 'Primordial', value: 'primordial' },
|
||||
{ text: 'Noir parler', value: 'noir parler' },
|
||||
{ text: 'Sselish', value: 'sselish' },
|
||||
{ text: 'Sylvestre', value: 'sylvestre' },
|
||||
]
|
||||
20
docs/.vuepress/data/magicItems.js
Normal file
20
docs/.vuepress/data/magicItems.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
export const MAGICITEMTYPES = [
|
||||
"Anneau",
|
||||
"Arme",
|
||||
"Armure",
|
||||
"Baguette",
|
||||
"Bâton",
|
||||
"Objet merveilleux",
|
||||
"Parchemin",
|
||||
"Potion",
|
||||
"Sceptre",
|
||||
]
|
||||
|
||||
export const RARITIES = [
|
||||
"Courant",
|
||||
"Peu courant",
|
||||
"Rare",
|
||||
"Très rare",
|
||||
"Légendaire",
|
||||
"Artefact",
|
||||
]
|
||||
92
docs/.vuepress/data/monsters.js
Normal file
92
docs/.vuepress/data/monsters.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
export const MONSTERTYPES = [
|
||||
"Aberration",
|
||||
"Bête",
|
||||
"Céleste",
|
||||
"Créature artificielle",
|
||||
"Créature monstrueuse",
|
||||
"Dragon",
|
||||
"Élémentaire",
|
||||
"Fées",
|
||||
"Fiélon",
|
||||
"Géant",
|
||||
"Humanoide",
|
||||
"Mort-vivant",
|
||||
"Plante",
|
||||
"Vase",
|
||||
]
|
||||
|
||||
export const MONSTERSIZES = [
|
||||
{ label: "Très petit", abbr: "TP", hitDie: 4 },
|
||||
{ label: "Petit", abbr: "P", hitDie: 6 },
|
||||
{ label: "Moyen", abbr: "M", hitDie: 8 },
|
||||
{ label: "Grand", abbr: "G", hitDie: 10 },
|
||||
{ label: "Très grand", abbr: "TG", hitDie: 12 },
|
||||
{ label: "Gigantesque", abbr: "Gig", hitDie: 20 },
|
||||
]
|
||||
|
||||
export const CHALLENGES = [
|
||||
{ label: "0", value:'0', xp: "0 ou 10" },
|
||||
{ label: "1/8", value:'0.125', xp: 25 },
|
||||
{ label: "1/4", value:'0.25', xp: 50 },
|
||||
{ label: "1/2", value:'0.5', xp: 100 },
|
||||
{ label: "1", value:'1', xp: 200 },
|
||||
{ label: "2", value:'2', xp: 450 },
|
||||
{ label: "3", value:'3', xp: 700 },
|
||||
{ label: "4", value:'4', xp: 1100 },
|
||||
{ label: "5", value:'5', xp: 1800 },
|
||||
{ label: "6", value:'6', xp: 2300 },
|
||||
{ label: "7", value:'7', xp: 2900 },
|
||||
{ label: "8", value:'8', xp: 3900 },
|
||||
{ label: "9", value:'9', xp: 5000 },
|
||||
{ label: "10", value:'10', xp: 5900 },
|
||||
{ label: "11", value:'11', xp: 7200 },
|
||||
{ label: "12", value:'12', xp: 8400 },
|
||||
{ label: "13", value:'13', xp: 10000 },
|
||||
{ label: "14", value:'14', xp: 11500 },
|
||||
{ label: "15", value:'15', xp: 13000 },
|
||||
{ label: "16", value:'16', xp: 15000 },
|
||||
{ label: "17", value:'17', xp: 18000 },
|
||||
{ label: "18", value:'18', xp: 20000 },
|
||||
{ label: "19", value:'19', xp: 22000 },
|
||||
{ label: "20", value:'20', xp: 25000 },
|
||||
{ label: "21", value:'21', xp: 33000 },
|
||||
{ label: "22", value:'22', xp: 41000 },
|
||||
{ label: "23", value:'23', xp: 50000 },
|
||||
{ label: "24", value:'24', xp: 62000 },
|
||||
{ label: "25", value:'25', xp: 75000 },
|
||||
{ label: "26", value:'26', xp: 90000 },
|
||||
{ label: "27", value:'27', xp: 105000 },
|
||||
{ label: "28", value:'28', xp: 120000 },
|
||||
{ label: "29", value:'29', xp: 135000 },
|
||||
{ label: "30", value:'30', xp: 155000 },
|
||||
]
|
||||
|
||||
export const ABILITIES = [
|
||||
{ label: 'Force', value: 'for', abbr: 'For' },
|
||||
{ label: 'Dextérité', value: 'dex', abbr: 'Dex' },
|
||||
{ label: 'Constitution', value: 'con', abbr: 'Con' },
|
||||
{ label: 'Intelligence', value: 'int', abbr: 'Int' },
|
||||
{ label: 'Sagesse', value: 'sag', abbr: 'Sag' },
|
||||
{ label: 'Charisme', value: 'cha', abbr: 'Cha' },
|
||||
]
|
||||
|
||||
export const SKILLS = [
|
||||
{ label: "Acrobaties", value:"acrobaties", ability: "dex" },
|
||||
{ label: "Arcanes", value:"arcanes", ability: "int" },
|
||||
{ label: "Athlétisme", value:"athletisme", ability: "for" },
|
||||
{ label: "Discrétion", value:"discretion", ability: "dex" },
|
||||
{ label: "Dressage", value:"dressage", ability: "sag" },
|
||||
{ label: "Escamotage", value:"escamotage", ability: "dex" },
|
||||
{ label: "Histoire", value:"histoire", ability: "int" },
|
||||
{ label: "Intimidation", value:"intimidation", ability: "cha" },
|
||||
{ label: "Investigation", value:"investigation", ability: "int" },
|
||||
{ label: "Médecine", value:"medecine", ability: "sag" },
|
||||
{ label: "Nature", value:"nature", ability: "int" },
|
||||
{ label: "Perception", value:"perception", ability: "sag" },
|
||||
{ label: "Perspicacité", value:"perspicacite", ability: "sag" },
|
||||
{ label: "Persuasion", value:"persuasion", ability: "cha" },
|
||||
{ label: "Religion", value:"religion", ability: "int" },
|
||||
{ label: "Représentation", value:"representation", ability: "cha" },
|
||||
{ label: "Supercherie", value:"supercherie", ability: "cha" },
|
||||
{ label: "Survie", value:"survie", ability: "sag" },
|
||||
]
|
||||
23
docs/.vuepress/data/spells.js
Normal file
23
docs/.vuepress/data/spells.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
export const SPELLSCHOOLS = [
|
||||
"Abjuration",
|
||||
"Enchantement",
|
||||
"Divination",
|
||||
"Évocation",
|
||||
"Illusion",
|
||||
"Invocation",
|
||||
"Nécromancie",
|
||||
"Transmutation",
|
||||
]
|
||||
|
||||
export const SPELLLEVELS = [
|
||||
{ value: 0, label: "Tour de magie" },
|
||||
{ value: 1, label: "1" },
|
||||
{ value: 2, label: "2" },
|
||||
{ value: 3, label: "3" },
|
||||
{ value: 4, label: "4" },
|
||||
{ value: 5, label: "5" },
|
||||
{ value: 6, label: "6" },
|
||||
{ value: 7, label: "7" },
|
||||
{ value: 8, label: "8" },
|
||||
{ value: 9, label: "9" },
|
||||
]
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
export const stats = {
|
||||
monsterTypes: {
|
||||
"Aberration": { plural: "Aberrations", swarm: "d'aberrations" },
|
||||
"Bête": { plural: "Bêtes", swarm: "de bêtes"},
|
||||
"Céleste": { plural: "Célestes", swarm: "de célestes" },
|
||||
"Créature artificielle": { plural: "Créatures artificielles", swarm: "de créatures artificielles"},
|
||||
"Créature monstrueuse": { plural: "Créatures monstrueuses", swarm: "de créatures monstrueuses"},
|
||||
"Dragon": { plural: "Dragons", swarm: "de dragons"},
|
||||
"Élémentaire": { plural: "Élémentaires", swarm: "d'élémentaires"},
|
||||
"Fées": { plural: "Fées", swarm: "de fées"},
|
||||
"Fiélon": { plural: "Fiélons", swarm: "de fiélons"},
|
||||
"Géant": { plural: "Géants", swarm: "de géants"},
|
||||
"Humanoide": { plural: "Humanoïdes", swarm: "d'humanoïdes"},
|
||||
"Mort-vivant": { plural: "Morts-vivants", swarm: "de morts-vivants"},
|
||||
"Plante": { plural: "Plantes", swarm: "de plantes"},
|
||||
"Vase": { plural: "Vases", swarm: "de vases"}
|
||||
"Aberration": { plural: "Aberrations", swarm: "d'aberrations" , label: "Aberration"},
|
||||
"Bête": { plural: "Bêtes", swarm: "de bêtes", label: "Bête"},
|
||||
"Céleste": { plural: "Célestes", swarm: "de célestes" , label: "Céleste"},
|
||||
"Créature artificielle": { plural: "Créatures artificielles", swarm: "de créatures artificielles", label: "Créature artificielle"},
|
||||
"Créature monstrueuse": { plural: "Créatures monstrueuses", swarm: "de créatures monstrueuses", label: "Créature monstrueuse"},
|
||||
"Dragon": { plural: "Dragons", swarm: "de dragons", label: "Dragon"},
|
||||
"Élémentaire": { plural: "Élémentaires", swarm: "d'élémentaires", label: "Élémentaire"},
|
||||
"Fées": { plural: "Fées", swarm: "de fées", label: "Fées"},
|
||||
"Fiélon": { plural: "Fiélons", swarm: "de fiélons", label: "Fiélon"},
|
||||
"Géant": { plural: "Géants", swarm: "de géants", label: "Géant"},
|
||||
"Humanoide": { plural: "Humanoïdes", swarm: "d'humanoïdes", label: "Humanoide"},
|
||||
"Mort-vivant": { plural: "Morts-vivants", swarm: "de morts-vivants", label: "Mort-vivant"},
|
||||
"Plante": { plural: "Plantes", swarm: "de plantes", label: "Plante"},
|
||||
"Vase": { plural: "Vases", swarm: "de vases", label: "Vase"},
|
||||
},
|
||||
|
||||
abilities: {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ import spellFilters from './modules/spellFilters'
|
|||
import magicItemFilters from './modules/magicItemFilters'
|
||||
import monsterFilters from './modules/monsterFilters'
|
||||
|
||||
import mySpells from './modules/mySpells'
|
||||
import myMonsters from './modules/myMonsters'
|
||||
import myMagicItems from './modules/myMagicItems'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
|
|
@ -13,7 +17,10 @@ export default new Vuex.Store({
|
|||
modules: {
|
||||
spellFilters,
|
||||
magicItemFilters,
|
||||
monsterFilters
|
||||
monsterFilters,
|
||||
mySpells,
|
||||
myMonsters,
|
||||
myMagicItems
|
||||
},
|
||||
|
||||
state: {
|
||||
|
|
|
|||
63
docs/.vuepress/store/modules/myMagicItems.js
Normal file
63
docs/.vuepress/store/modules/myMagicItems.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import {sortByString} from '@theme/util/filterHelpers'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
|
||||
state: {
|
||||
magicItems: [],
|
||||
},
|
||||
|
||||
getters: {
|
||||
magicItems: state => state.magicItems,
|
||||
},
|
||||
|
||||
actions: {
|
||||
reset: ({ commit }) => {
|
||||
commit('resetMagicItems')
|
||||
},
|
||||
updateMagicItems: ({ commit }, payload) => {
|
||||
commit('setMagicItems', payload)
|
||||
},
|
||||
addMagicItem: ({ commit }, payload) => {
|
||||
commit('addMagicItem', payload)
|
||||
},
|
||||
removeMagicItem: ({ commit }, payload) => {
|
||||
commit('removeMagicItem', payload)
|
||||
},
|
||||
},
|
||||
|
||||
mutations: {
|
||||
initialiseStore (state) {
|
||||
// Récupération des données utilisateurs depuis le navigateur
|
||||
if(localStorage.getItem('myMagicItems') && localStorage.getItem('myMagicItems') !== undefined) {
|
||||
let localStorageData = JSON.parse(localStorage.getItem('myMagicItems'))
|
||||
state.magicItems = localStorageData.magicItems
|
||||
}
|
||||
},
|
||||
setMagicItems: (state, payload) => {
|
||||
state.magicItems = payload
|
||||
},
|
||||
resetMagicItems: (state) => {
|
||||
state.magicItems = []
|
||||
},
|
||||
addMagicItem: (state, payload) => {
|
||||
state.magicItems.push(payload)
|
||||
state.magicItems.sort((a, b) => { return sortByString(a.title, b.title) })
|
||||
},
|
||||
updateMagicItem: (state, payload) => {
|
||||
state.magicItems.forEach((magicItem, idx) => {
|
||||
if (magicItem.key == payload.key) {
|
||||
state.magicItems[idx] = payload
|
||||
}
|
||||
})
|
||||
},
|
||||
removeMagicItem: (state, payload) => {
|
||||
state.magicItems.forEach((magicItem, idx) => {
|
||||
if (magicItem.key == payload.key) {
|
||||
state.magicItems.splice(idx, 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
63
docs/.vuepress/store/modules/myMonsters.js
Normal file
63
docs/.vuepress/store/modules/myMonsters.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import {sortByString} from '@theme/util/filterHelpers'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
|
||||
state: {
|
||||
monsters: [],
|
||||
},
|
||||
|
||||
getters: {
|
||||
monsters: state => state.monsters,
|
||||
},
|
||||
|
||||
actions: {
|
||||
reset: ({ commit }) => {
|
||||
commit('resetMonsters')
|
||||
},
|
||||
updateMonsters: ({ commit }, payload) => {
|
||||
commit('setMonsters', payload)
|
||||
},
|
||||
addMonster: ({ commit }, payload) => {
|
||||
commit('addMonster', payload)
|
||||
},
|
||||
removeMonster: ({ commit }, payload) => {
|
||||
commit('removeMonster', payload)
|
||||
},
|
||||
},
|
||||
|
||||
mutations: {
|
||||
initialiseStore (state) {
|
||||
// Récupération des données utilisateurs depuis le navigateur
|
||||
if(localStorage.getItem('myMonsters') && localStorage.getItem('myMonsters') !== undefined) {
|
||||
let localStorageData = JSON.parse(localStorage.getItem('myMonsters'))
|
||||
state.monsters = localStorageData.monsters
|
||||
}
|
||||
},
|
||||
setMonsters: (state, payload) => {
|
||||
state.monsters = payload
|
||||
},
|
||||
resetMonsters: (state) => {
|
||||
state.monsters = []
|
||||
},
|
||||
addMonster: (state, payload) => {
|
||||
state.monsters.push(payload)
|
||||
state.monsters.sort((a, b) => { return sortByString(a.title, b.title) })
|
||||
},
|
||||
updateMonster: (state, payload) => {
|
||||
state.monsters.forEach((monster, idx) => {
|
||||
if (monster.key == payload.key) {
|
||||
state.monsters[idx] = payload
|
||||
}
|
||||
})
|
||||
},
|
||||
removeMonster: (state, payload) => {
|
||||
state.monsters.forEach((monster, idx) => {
|
||||
if (monster.key == payload.key) {
|
||||
state.monsters.splice(idx, 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
63
docs/.vuepress/store/modules/mySpells.js
Normal file
63
docs/.vuepress/store/modules/mySpells.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import {sortByString} from '@theme/util/filterHelpers'
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
|
||||
state: {
|
||||
spells: [],
|
||||
},
|
||||
|
||||
getters: {
|
||||
spells: state => state.spells,
|
||||
},
|
||||
|
||||
actions: {
|
||||
reset: ({ commit }) => {
|
||||
commit('resetSpells')
|
||||
},
|
||||
updateSpells: ({ commit }, payload) => {
|
||||
commit('setSpells', payload)
|
||||
},
|
||||
addSpell: ({ commit }, payload) => {
|
||||
commit('addSpell', payload)
|
||||
},
|
||||
removeSpell: ({ commit }, payload) => {
|
||||
commit('removeSpell', payload)
|
||||
},
|
||||
},
|
||||
|
||||
mutations: {
|
||||
initialiseStore (state) {
|
||||
// Récupération des données utilisateurs depuis le navigateur
|
||||
if(localStorage.getItem('mySpells') && localStorage.getItem('mySpells') !== undefined) {
|
||||
let localStorageData = JSON.parse(localStorage.getItem('mySpells'))
|
||||
state.spells = localStorageData.spells
|
||||
}
|
||||
},
|
||||
setSpells: (state, payload) => {
|
||||
state.spells = payload
|
||||
},
|
||||
resetSpells: (state) => {
|
||||
state.spells = []
|
||||
},
|
||||
addSpell: (state, payload) => {
|
||||
state.spells.push(payload)
|
||||
state.spells.sort((a, b) => { return sortByString(a.title, b.title) })
|
||||
},
|
||||
updateSpell: (state, payload) => {
|
||||
state.spells.forEach((spell, idx) => {
|
||||
if (spell.key == payload.key) {
|
||||
state.spells[idx] = payload
|
||||
}
|
||||
})
|
||||
},
|
||||
removeSpell: (state, payload) => {
|
||||
state.spells.forEach((spell, idx) => {
|
||||
if (spell.key == payload.key) {
|
||||
state.spells.splice(idx, 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -43,6 +43,16 @@
|
|||
crumbs.push({to: page.path, disabled: disabled, text: 'Bestiaire'})
|
||||
} else if (page.path == '/liste-objets-magiques/') {
|
||||
crumbs.push({to: page.path, disabled: disabled, text: 'Liste des objets magiques'})
|
||||
} else if (page.path == '/mon-grimoire/') {
|
||||
crumbs.push({to: page.path, disabled: disabled, text: 'Mon grimoire'})
|
||||
} else if (page.path == '/mon-bestiaire/') {
|
||||
crumbs.push({to: page.path, disabled: disabled, text: 'Mon bestiaire'})
|
||||
} else if (page.path == '/mes-objets-magiques/') {
|
||||
crumbs.push({to: page.path, disabled: disabled, text: 'Mes objets magiques'})
|
||||
} else if (page.path == '/creation-de-sort/') {
|
||||
crumbs.push({to: page.path, disabled: disabled, text: 'Création de sort'})
|
||||
} else if (page.path == '/creation-de-monstre-pnj/') {
|
||||
crumbs.push({to: page.path, disabled: disabled, text: 'Création de monstre ou PNJ'})
|
||||
} else {
|
||||
crumbs.push({to: page.path, disabled: disabled, text: page.frontmatter.breadcrumb || page.title})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,17 @@
|
|||
<main class="page content">
|
||||
|
||||
<div class="theme-default-content">
|
||||
<h1>{{ $page.title }}</h1>
|
||||
<div class="magic-item-details">
|
||||
<template v-if="!hideTitle">
|
||||
<h1 v-if="!isList">{{ magicItem.title }}</h1>
|
||||
<h2 v-else>{{ magicItem.title }}</h2>
|
||||
</template>
|
||||
<div class="magic-item-details title">
|
||||
{{displayItemMeta()}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Content class="mt-4" />
|
||||
<Content v-if="!magicItem.custom" :pageKey="magicItem.key" class="mt-4" />
|
||||
<div v-else v-html="md.render(magicItem.content)" class="mt-4"></div>
|
||||
|
||||
<p v-if="$page.frontmatter.source" class="source">Source : <em>{{ $page.frontmatter.source }}</em></p>
|
||||
|
||||
|
|
@ -17,11 +21,22 @@
|
|||
|
||||
<script>
|
||||
import {displayItemMeta} from '@theme/util/magicItemHelpers'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
export default {
|
||||
name: 'MagicItem',
|
||||
|
||||
data () {
|
||||
return {
|
||||
md: new MarkdownIt()
|
||||
}
|
||||
},
|
||||
|
||||
props: ['magicItem', 'isList', 'hideTitle'],
|
||||
|
||||
methods : {
|
||||
displayItemMeta () {
|
||||
return displayItemMeta(this.$page.frontmatter)
|
||||
return displayItemMeta(this.magicItem.frontmatter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
64
docs/.vuepress/theme/components/MagicItemCard.vue
Normal file
64
docs/.vuepress/theme/components/MagicItemCard.vue
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<template>
|
||||
<v-card class="d-flex flex-column mb-6 magic-item-card">
|
||||
<v-card-title>
|
||||
{{ magicItem.title }}
|
||||
<v-spacer></v-spacer>
|
||||
<v-card-actions v-if="showActions">
|
||||
<v-btn dark icon class="d-print-none mr-2" link :to="{ path: '/creation-d-objet-magique/', query: { key: magicItem.key } }"><v-icon>mdi-pencil</v-icon></v-btn>
|
||||
<v-btn dark icon class="d-print-none" @click="$store.commit('myMagicItems/removeMagicItem', magicItem)"><v-icon>mdi-delete</v-icon></v-btn>
|
||||
</v-card-actions>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="magic-item-details mt-3">
|
||||
<div class="magic-item-rarity-attunement title" v-html="displayItemMeta()"></div>
|
||||
</div>
|
||||
|
||||
<v-divider class="mt-3" />
|
||||
|
||||
<Content v-if="!magicItem.custom" :pageKey="magicItem.key" class="mt-4" />
|
||||
<div v-else v-html="md.render(magicItem.content)" class="mt-4"></div>
|
||||
|
||||
<p v-if="magicItem.frontmatter.source" class="source">Source : <em>{{ magicItem.frontmatter.source }}</em></p>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { displayItemMeta } from '@theme/util/magicItemHelpers'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
export default {
|
||||
name: 'MagicItemCard',
|
||||
|
||||
props: ['magicItem', 'showActions', 'isShort'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
md: new MarkdownIt()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
displayItemMeta () {
|
||||
return displayItemMeta(this.magicItem.frontmatter)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../styles/colors';
|
||||
|
||||
.magic-item-card {
|
||||
.v-card__title {
|
||||
background-color: $color-dragon;
|
||||
color: #fff;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
p.source {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,133 +2,140 @@
|
|||
<main class="page content">
|
||||
|
||||
<div class="theme-default-content">
|
||||
<h1>{{ $page.title }}</h1>
|
||||
<div class="monster-type-size-alignment">
|
||||
<template v-if="!hideTitle">
|
||||
<h1 v-if="!isList">{{ monster.title }}</h1>
|
||||
<h2 v-else>{{ monster.title }}</h2>
|
||||
</template>
|
||||
<div class="monster-type-size-alignment title">
|
||||
{{ displayMonsterTypeSizeAlignment() }}
|
||||
</div>
|
||||
<div class="monster-details">
|
||||
<!-- Statblock -->
|
||||
<div class="monster-armor-class">
|
||||
<strong>Classe d'armure</strong>
|
||||
<span>{{ displayAC() }}</span>
|
||||
</div>
|
||||
<div class="monster-hit-points">
|
||||
<strong>Points de vie</strong>
|
||||
<span>{{ displayHP() }}</span>
|
||||
</div>
|
||||
<div class="monster-movement">
|
||||
<strong>Vitesse</strong>
|
||||
<template>{{ displayMovement() }}</template>
|
||||
</div>
|
||||
<div class="monster-ability-scores d-flex">
|
||||
<div class="monster-ability-scores-physical d-flex">
|
||||
<div class="ability-str text-center">
|
||||
<div class="ability-label">
|
||||
<strong>For</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monster.abilityScores.for) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-dex text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Dex</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monster.abilityScores.dex) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-con text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Con</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monster.abilityScores.con) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="break-avoid">
|
||||
<!-- Statblock -->
|
||||
<div class="monster-armor-class">
|
||||
<strong>Classe d'armure</strong>
|
||||
<span>{{ displayAC() }}</span>
|
||||
</div>
|
||||
<div class="monster-ability-scores-mental d-flex">
|
||||
<div class="ability-int text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Int</strong>
|
||||
<div class="monster-hit-points">
|
||||
<strong>Points de vie</strong>
|
||||
<span>{{ hp }}</span>
|
||||
</div>
|
||||
<div class="monster-movement">
|
||||
<strong>Vitesse</strong>
|
||||
<template>{{ displayMovement() }}</template>
|
||||
</div>
|
||||
<div class="monster-ability-scores d-flex">
|
||||
<div class="monster-ability-scores-physical d-flex">
|
||||
<div class="ability-str text-center">
|
||||
<div class="ability-label">
|
||||
<strong>For</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monsterStats.abilityScores.for) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monster.abilityScores.int) }}
|
||||
<div class="ability-dex text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Dex</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monsterStats.abilityScores.dex) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-con text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Con</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monsterStats.abilityScores.con) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-wis text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Sag</strong>
|
||||
<div class="monster-ability-scores-mental d-flex">
|
||||
<div class="ability-int text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Int</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monsterStats.abilityScores.int) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monster.abilityScores.sag) }}
|
||||
<div class="ability-wis text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Sag</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monsterStats.abilityScores.sag) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ability-cha text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Cha</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monster.abilityScores.cha) }}
|
||||
<div class="ability-cha text-center">
|
||||
<div class="ability-label">
|
||||
<strong>Cha</strong>
|
||||
</div>
|
||||
<div class="ability-score">
|
||||
{{ displayAbilityScore(monsterStats.abilityScores.cha) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="monster-saving-throws" v-if="monster.savingThrows">
|
||||
<strong>Jets de sauvegarde</strong>
|
||||
<span class="monster-saving-throw" v-for="(savingThrow, idx) in monster.savingThrows">
|
||||
<template>{{displaySavingThrowBonus(savingThrow)}}</template><template v-if="idx < monster.savingThrows.length - 1">, </template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="monster-skills" v-if="monster.skills">
|
||||
<strong>Compétences</strong>
|
||||
<span class="monster-skill" v-for="(skill, idx) in monster.skills">
|
||||
<template>{{displaySkillBonus(skill)}}</template><template v-if="idx < monster.skills.length - 1">, </template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="monster-damage-type-vulnerabilities" v-if="monster.damageTypeVulnerabilities">
|
||||
<strong>Vulnérabilité aux dégâts</strong>
|
||||
<span v-html="displayDamageTypes(monster.damageTypeVulnerabilities)"></span>
|
||||
</div>
|
||||
<div class="monster-damage-type-resistances" v-if="monster.damageTypeResistances">
|
||||
<strong>Résistance aux dégâts</strong>
|
||||
<span v-html="displayDamageTypes(monster.damageTypeResistances)"></span>
|
||||
</div>
|
||||
<div class="monster-damage-type-immunities" v-if="monster.damageTypeImmunities">
|
||||
<strong>Immunité contre les dégâts</strong>
|
||||
<span v-html="displayDamageTypes(monster.damageTypeImmunities)"></span>
|
||||
</div>
|
||||
<div class="monster-condition-immunities" v-if="monster.conditionImmunities">
|
||||
<strong>Immunité contre les états</strong>
|
||||
<span v-html="displayConditionImmunities()"></span>
|
||||
</div>
|
||||
<div class="monster-senses">
|
||||
<strong>Sens</strong>
|
||||
<template>{{ displaySenses() }}</template>
|
||||
</div>
|
||||
<div class="monster-languages">
|
||||
<strong>Langes</strong>
|
||||
<template v-if="monster.languages">{{ displayLanguages() }}</template>
|
||||
<template v-else>—</template>
|
||||
</div>
|
||||
<div class="monster-challenge">
|
||||
<strong>Dangerosité</strong>
|
||||
<template>{{ displayChallenge() }}</template>
|
||||
</div>
|
||||
<div class="monster-environments" v-if="monster.environments">
|
||||
<strong>Environnements :</strong>
|
||||
<span v-html="displayList(monster.environments)"></span>
|
||||
</div>
|
||||
<div class="monster-dungeon-types" v-if="monster.dungeonTypes">
|
||||
<strong>Types de donjons :</strong>
|
||||
<span v-html="displayList(monster.dungeonTypes)"></span>
|
||||
<div class="break-avoid">
|
||||
<div class="monster-saving-throws" v-if="monsterStats.savingThrows && monsterStats.savingThrows.length > 0">
|
||||
<strong>Jets de sauvegarde</strong>
|
||||
<span class="monster-saving-throw" v-for="(savingThrow, idx) in monsterStats.savingThrows">
|
||||
<template>{{displaySavingThrowBonus(savingThrow)}}</template><template v-if="idx < monsterStats.savingThrows.length - 1">, </template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="monster-skills" v-if="monsterStats.skills && monsterStats.skills.length > 0">
|
||||
<strong>Compétences</strong>
|
||||
<span class="monster-skill" v-for="(skill, idx) in monsterStats.skills">
|
||||
<template>{{displaySkillBonus(skill)}}</template><template v-if="idx < monsterStats.skills.length - 1">, </template>
|
||||
</span>
|
||||
</div>
|
||||
<div class="monster-damage-type-vulnerabilities" v-if="monsterStats.damageTypeVulnerabilities && monsterStats.damageTypeVulnerabilities.length > 0">
|
||||
<strong>Vulnérabilité aux dégâts</strong>
|
||||
<span v-html="displayDamageTypes(monsterStats.damageTypeVulnerabilities)"></span>
|
||||
</div>
|
||||
<div class="monster-damage-type-resistances" v-if="monsterStats.damageTypeResistances && monsterStats.damageTypeResistances.length > 0">
|
||||
<strong>Résistance aux dégâts</strong>
|
||||
<span v-html="displayDamageTypes(monsterStats.damageTypeResistances)"></span>
|
||||
</div>
|
||||
<div class="monster-damage-type-immunities" v-if="monsterStats.damageTypeImmunities && monsterStats.damageTypeImmunities.length > 0">
|
||||
<strong>Immunité contre les dégâts</strong>
|
||||
<span v-html="displayDamageTypes(monsterStats.damageTypeImmunities)"></span>
|
||||
</div>
|
||||
<div class="monster-condition-immunities" v-if="monsterStats.conditionImmunities && monsterStats.conditionImmunities.length > 0">
|
||||
<strong>Immunité contre les états</strong>
|
||||
<span v-html="displayConditionImmunities()"></span>
|
||||
</div>
|
||||
<div class="monster-senses">
|
||||
<strong>Sens</strong>
|
||||
<template>{{ displaySenses() }}</template>
|
||||
</div>
|
||||
<div class="monster-languages">
|
||||
<strong>Langes</strong>
|
||||
<template>{{ languages }}</template>
|
||||
</div>
|
||||
<div class="monster-challenge">
|
||||
<strong>Dangerosité</strong>
|
||||
<template>{{ displayChallenge() }}</template>
|
||||
</div>
|
||||
<div class="monster-environments" v-if="monsterStats.environments">
|
||||
<strong>Environnements :</strong>
|
||||
<span v-html="displayList(monsterStats.environments)"></span>
|
||||
</div>
|
||||
<div class="monster-dungeon-types" v-if="monsterStats.dungeonTypes">
|
||||
<strong>Types de donjons :</strong>
|
||||
<span v-html="displayList(monsterStats.dungeonTypes)"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Content class="mt-4"/>
|
||||
<Content v-if="!monster.custom" :pageKey="monster.key" class="mt-4" />
|
||||
<div v-else v-html="md.render(monster.content)" class="mt-4"></div>
|
||||
|
||||
<p v-if="$page.frontmatter.source" class="source">Source : <em>{{ monster.source }}</em></p>
|
||||
<p v-if="$page.frontmatter.source" class="source">Source : <em>{{ monsterStats.source }}</em><template v-if="monsterStats.source_page">, page {{ monsterStats.source_page }}</template></p>
|
||||
|
||||
</main>
|
||||
</template>
|
||||
|
|
@ -145,26 +152,29 @@ import {
|
|||
|
||||
import {stats} from '../../data/stats.js'
|
||||
import {armorTypes} from '../../data/armorTypes.js'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
export default {
|
||||
|
||||
props: ['monster', 'isList', 'hideTitle'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
|
||||
md: new MarkdownIt()
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
monster () {
|
||||
return this.$page.frontmatter
|
||||
monsterStats () {
|
||||
return this.monster.frontmatter
|
||||
},
|
||||
proficiencyBonus () {
|
||||
return this.getProficiencyBonus()
|
||||
},
|
||||
passivePerception () {
|
||||
let result = 10 + getModifier(this.monster.abilityScores.sag)
|
||||
if (this.monster.skills) {
|
||||
this.monster.skills.forEach((skill, idx) => {
|
||||
let result = 10 + getModifier(this.monsterStats.abilityScores.sag)
|
||||
if (this.monsterStats.skills) {
|
||||
this.monsterStats.skills.forEach((skill, idx) => {
|
||||
if (skill.name == 'perception') {
|
||||
if (skill.isExpert) {
|
||||
result += this.proficiencyBonus * 2
|
||||
|
|
@ -176,35 +186,73 @@ export default {
|
|||
}
|
||||
return result
|
||||
},
|
||||
|
||||
hp () {
|
||||
if (this.monsterStats.customHP) {
|
||||
return this.monsterStats.customHP
|
||||
} else if (this.monsterStats.hitDiceCount) {
|
||||
let hitDieSize = 8 // Dé de vie moyen par défaut
|
||||
if (this.monsterStats.hitDieSize) {
|
||||
hitDieSize = this.monsterStats.hitDieSize
|
||||
} else if (this.monsterStats.size) {
|
||||
hitDieSize = stats.sizes[this.monsterStats.size].hitDie
|
||||
}
|
||||
let hitPointsBonus = 1
|
||||
if (this.monsterStats.hitDiceCount > 1) {
|
||||
hitPointsBonus = Math.floor(this.monsterStats.hitDiceCount / 2)
|
||||
}
|
||||
let averageHP = this.monsterStats.hitDiceCount * (hitDieSize / 2) + this.monsterStats.hitDiceCount * getModifier(this.monsterStats.abilityScores.con) + hitPointsBonus
|
||||
let conMod = ""
|
||||
if (getModifier(this.monsterStats.abilityScores.con) != 0) {
|
||||
conMod = this.monsterStats.hitDiceCount * getModifier(this.monsterStats.abilityScores.con)
|
||||
conMod = displayBonus(conMod)
|
||||
}
|
||||
return averageHP + ' (' + this.monsterStats.hitDiceCount + "d" + hitDieSize + conMod + ')'
|
||||
}
|
||||
return ""
|
||||
},
|
||||
|
||||
languages () {
|
||||
let result = this.monsterStats.languages.join(', ')
|
||||
if (this.monsterStats.customLanguage) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += this.monsterStats.customLanguage
|
||||
}
|
||||
if (this.monsterStats.telepathy) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += 'télépathie ' + this.monsterStats.telepathy + ' m'
|
||||
}
|
||||
if (result == '') {
|
||||
return '—'
|
||||
}
|
||||
return result
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
displayList (list) { return list.join(', ') },
|
||||
displayAbilityScore (value) { return displayAbilityScore(value) },
|
||||
getModifier (value) { return getModifier(value) },
|
||||
getProficiencyBonus () { return getProficiencyBonus(this.monster.challenge) },
|
||||
getProficiencyBonus () { return getProficiencyBonus(this.monsterStats.challenge) },
|
||||
|
||||
displayMonsterTypeSizeAlignment () {
|
||||
return displayMonsterTypeSizeAlignment(this.monster)
|
||||
return displayMonsterTypeSizeAlignment(this.monsterStats)
|
||||
},
|
||||
|
||||
displaySavingThrowBonus (ability) {
|
||||
let result = stats.abilities[ability].abbr
|
||||
let bonus = displayBonus(getModifier(this.monster.abilityScores[ability]) + this.proficiencyBonus)
|
||||
let bonus = displayBonus(getModifier(this.monsterStats.abilityScores[ability]) + this.proficiencyBonus)
|
||||
result += ' ' + bonus
|
||||
return result
|
||||
},
|
||||
|
||||
displaySkillBonus (skill) {
|
||||
if (skill.name == 'Perception') {
|
||||
if (skill.isExpert) {
|
||||
this.monster.perceptionProficiency == 'expert'
|
||||
} else {
|
||||
this.monster.perceptionProficiency == 'proficient'
|
||||
}
|
||||
}
|
||||
let result = stats.skills[skill.name].label
|
||||
let bonus = getModifier(this.monster.abilityScores[stats.skills[skill.name].ability]) + this.proficiencyBonus
|
||||
let bonus = getModifier(this.monsterStats.abilityScores[stats.skills[skill.name].ability]) + this.proficiencyBonus
|
||||
if (skill.isExpert) {
|
||||
bonus += this.proficiencyBonus // Bonus de maître doublé pour les experts
|
||||
}
|
||||
|
|
@ -213,66 +261,41 @@ export default {
|
|||
return result
|
||||
},
|
||||
|
||||
displayHP () {
|
||||
if (this.monster.customHP) {
|
||||
return this.monster.customHP
|
||||
} else if (this.monster.hitDiceCount) {
|
||||
let hitDieSize = 8 // Dé de vie moyen par défaut
|
||||
if (this.monster.hitDieSize) {
|
||||
hitDieSize = this.monster.hitDieSize
|
||||
} else if (this.monster.size) {
|
||||
hitDieSize = stats.sizes[this.monster.size].hitDie
|
||||
}
|
||||
let hitPointsBonus = 1
|
||||
if (this.monster.hitDiceCount > 1) {
|
||||
hitPointsBonus = Math.floor(this.monster.hitDiceCount / 2)
|
||||
}
|
||||
let averageHP = this.monster.hitDiceCount * (hitDieSize / 2) + this.monster.hitDiceCount * getModifier(this.monster.abilityScores.con) + hitPointsBonus
|
||||
let conMod = ""
|
||||
if (getModifier(this.monster.abilityScores.con) != 0) {
|
||||
conMod = this.monster.hitDiceCount * getModifier(this.monster.abilityScores.con)
|
||||
conMod = displayBonus(conMod)
|
||||
}
|
||||
return averageHP + ' (' + this.monster.hitDiceCount + "d" + hitDieSize + conMod + ')'
|
||||
}
|
||||
return ""
|
||||
},
|
||||
|
||||
displayChallenge () {
|
||||
return displayChallenge(this.monster.challenge, true)
|
||||
return displayChallenge(this.monsterStats.challenge, true)
|
||||
},
|
||||
|
||||
displayMovement () {
|
||||
let result = ''
|
||||
if (this.monster.movement.walk) {
|
||||
result += this.monster.movement.walk + ' m'
|
||||
if (this.monsterStats.movement.walk) {
|
||||
result += this.monsterStats.movement.walk + ' m'
|
||||
} else {
|
||||
result += '0 m'
|
||||
}
|
||||
if (this.monster.movement.climb) {
|
||||
if (this.monsterStats.movement.climb) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += 'escalade ' + this.monster.movement.climb + ' m'
|
||||
result += 'escalade ' + this.monsterStats.movement.climb + ' m'
|
||||
}
|
||||
if (this.monster.movement.burrow) {
|
||||
if (this.monsterStats.movement.burrow) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += 'fouissement ' + this.monster.movement.burrow + ' m'
|
||||
result += 'fouissement ' + this.monsterStats.movement.burrow + ' m'
|
||||
}
|
||||
if (this.monster.movement.swim) {
|
||||
if (this.monsterStats.movement.swim) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += 'nage ' + this.monster.movement.swim + ' m'
|
||||
result += 'nage ' + this.monsterStats.movement.swim + ' m'
|
||||
}
|
||||
if (this.monster.movement.fly) {
|
||||
if (this.monsterStats.movement.fly) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += 'vol ' + this.monster.movement.fly + ' m'
|
||||
if (this.monster.movement.hover) {
|
||||
result += 'vol ' + this.monsterStats.movement.fly + ' m'
|
||||
if (this.monsterStats.movement.hover) {
|
||||
result += ' (vol stationnaire)'
|
||||
}
|
||||
}
|
||||
|
|
@ -287,44 +310,48 @@ export default {
|
|||
let armor = ''
|
||||
// Le monstre n'a pas d'armure.
|
||||
// CA = 10 + Dex
|
||||
if (!this.monster.ac.armorType) {
|
||||
ac = 10 + getModifier(this.monster.abilityScores.dex)
|
||||
if (!this.monsterStats.ac.armorType) {
|
||||
ac = 10 + getModifier(this.monsterStats.abilityScores.dex)
|
||||
} else {
|
||||
// Le type d'armure n'est pas formalisé. On prend la valeur brute
|
||||
if (this.monster.ac.armorType == 'custom') {
|
||||
return this.monster.ac.value
|
||||
if (this.monsterStats.ac.armorType == 'custom') {
|
||||
return this.monsterStats.ac.value
|
||||
}
|
||||
|
||||
// Le monstre a une armure naturelle.
|
||||
// CA = 10 + Armure naturelle + Dex
|
||||
if (this.monster.ac.armorType == 'armure naturelle') {
|
||||
armor = this.monster.ac.armorType
|
||||
ac = ac + this.monster.ac.value + getModifier(this.monster.abilityScores.dex)
|
||||
} else if (this.monster.ac.armorType == 'armure du mage') {
|
||||
if (this.monsterStats.ac.armorType == 'armure naturelle') {
|
||||
armor = this.monsterStats.ac.armorType
|
||||
if (parseInt(this.monsterStats.ac.value)) {
|
||||
ac = ac + parseInt(this.monsterStats.ac.value) + getModifier(this.monsterStats.abilityScores.dex)
|
||||
} else {
|
||||
ac = ac + getModifier(this.monsterStats.abilityScores.dex)
|
||||
}
|
||||
} else if (this.monsterStats.ac.armorType == 'armure du mage') {
|
||||
hasMageArmor = true
|
||||
ac = ac + getModifier(this.monster.abilityScores.dex)
|
||||
mageArmorAc = mageArmorAc + getModifier(this.monster.abilityScores.dex)
|
||||
ac = ac + getModifier(this.monsterStats.abilityScores.dex)
|
||||
mageArmorAc = mageArmorAc + getModifier(this.monsterStats.abilityScores.dex)
|
||||
armor = mageArmorAc + ' avec armure du mage'
|
||||
} else {
|
||||
// Le monstre a un type d'armure défini.
|
||||
// On calcule sa CA selon le type
|
||||
let armorType = armorTypes[this.monster.ac.armorType]
|
||||
let armorType = armorTypes[this.monsterStats.ac.armorType]
|
||||
|
||||
// Le type d'armure n'existe pas. On l'ignore.
|
||||
// CA = 10 + Dex
|
||||
if (!armorType) {
|
||||
ac = ac + getModifier(this.monster.abilityScores.dex)
|
||||
ac = ac + getModifier(this.monsterStats.abilityScores.dex)
|
||||
} else {
|
||||
// L'armure n'impose pas de limite de Dex
|
||||
armor = this.monster.ac.armorType
|
||||
armor = this.monsterStats.ac.armorType
|
||||
if (armorType.maxDex === false) {
|
||||
ac = armorType.value + getModifier(this.monster.abilityScores.dex)
|
||||
ac = armorType.value + getModifier(this.monsterStats.abilityScores.dex)
|
||||
} else {
|
||||
// La limite de Dex de l'armure est inférieure à la Dex du monstre
|
||||
if (armorType.maxDex <= getModifier(this.monster.abilityScores.dex)) {
|
||||
if (armorType.maxDex <= getModifier(this.monsterStats.abilityScores.dex)) {
|
||||
ac = armorType.value + armorType.maxDex
|
||||
} else {
|
||||
ac = armorType.value + getModifier(this.monster.abilityScores.dex)
|
||||
ac = armorType.value + getModifier(this.monsterStats.abilityScores.dex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -333,7 +360,7 @@ export default {
|
|||
|
||||
|
||||
// Le monstre a un bouclier. Sa CA augmente de 2.
|
||||
if (this.monster.ac.hasShield) {
|
||||
if (this.monsterStats.ac.hasShield) {
|
||||
ac = ac + 2
|
||||
mageArmorAc = mageArmorAc + 2
|
||||
if (armor != '') {
|
||||
|
|
@ -353,33 +380,29 @@ export default {
|
|||
return ac
|
||||
},
|
||||
|
||||
displayLanguages () {
|
||||
return this.monster.languages.join(', ')
|
||||
},
|
||||
|
||||
displaySenses () {
|
||||
let result = ''
|
||||
if (this.monster.senses) {
|
||||
if (this.monster.senses.tremorsense) {
|
||||
result += 'perception des vibrations ' + this.monster.senses.tremorsense + ' m'
|
||||
if (this.monsterStats.senses) {
|
||||
if (this.monsterStats.senses.tremorsense) {
|
||||
result += 'perception des vibrations ' + this.monsterStats.senses.tremorsense + ' m'
|
||||
}
|
||||
if (this.monster.senses.blindsight) {
|
||||
if (this.monsterStats.senses.blindsight) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += 'vision aveugle ' + this.monster.senses.blindsight + ' m'
|
||||
result += 'vision aveugle ' + this.monsterStats.senses.blindsight + ' m'
|
||||
}
|
||||
if (this.monster.senses.darkvision) {
|
||||
if (this.monsterStats.senses.darkvision) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += 'vision dans le noir ' + this.monster.senses.darkvision + ' m'
|
||||
result += 'vision dans le noir ' + this.monsterStats.senses.darkvision + ' m'
|
||||
}
|
||||
if (this.monster.senses.truesight) {
|
||||
if (this.monsterStats.senses.truesight) {
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
}
|
||||
result += 'vision parfaite ' + this.monster.senses.truesight + ' m'
|
||||
result += 'vision parfaite ' + this.monsterStats.senses.truesight + ' m'
|
||||
}
|
||||
if (result != '') {
|
||||
result += ', '
|
||||
|
|
@ -392,9 +415,9 @@ export default {
|
|||
|
||||
displayConditionImmunities () {
|
||||
let result = ''
|
||||
this.monster.conditionImmunities.forEach((condition, idx) => {
|
||||
this.monsterStats.conditionImmunities.forEach((condition, idx) => {
|
||||
if (result != '') {
|
||||
if (idx == this.monster.conditionImmunities.length - 1) {
|
||||
if (idx == this.monsterStats.conditionImmunities.length - 1) {
|
||||
result += ' et '
|
||||
} else {
|
||||
result += ', '
|
||||
|
|
@ -432,7 +455,7 @@ export default {
|
|||
|
||||
.monster-ability-scores {
|
||||
margin: 12px 0;
|
||||
|
||||
|
||||
.ability-label, .ability-score {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
|
|
|||
76
docs/.vuepress/theme/components/MonsterCard.vue
Normal file
76
docs/.vuepress/theme/components/MonsterCard.vue
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<v-card class="d-flex flex-column mb-6 monster-card">
|
||||
<v-card-title>
|
||||
{{ monster.title }}
|
||||
<v-spacer></v-spacer>
|
||||
<v-card-actions v-if="showActions">
|
||||
<v-btn dark icon class="d-print-none mr-2" link :to="{ path: '/creation-de-monstre-pnj/', query: { key: monster.key } }"><v-icon>mdi-pencil</v-icon></v-btn>
|
||||
<v-btn dark icon class="d-print-none" @click="$store.commit('myMonsters/removeMonster', monster)"><v-icon>mdi-delete</v-icon></v-btn>
|
||||
</v-card-actions>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="monster-card-details mt-3">
|
||||
<Monster :monster="monster" :hideTitle="true" />
|
||||
</div>
|
||||
|
||||
<v-divider class="mt-3" />
|
||||
|
||||
<p v-if="monster.frontmatter.source" class="source">Source : <em>{{ monster.frontmatter.source }}</em></p>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Monster from '@theme/components/Monster'
|
||||
import { displaySchoolLevel } from '@theme/util/monsterHelpers'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
export default {
|
||||
name: 'MonsterCard',
|
||||
|
||||
components: { Monster },
|
||||
|
||||
props: ['monster', 'showActions', 'isShort'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
md: new MarkdownIt()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
displaySchoolLevel () {
|
||||
return displaySchoolLevel(this.monster.frontmatter)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../styles/colors';
|
||||
|
||||
.monster-card {
|
||||
.v-card__title {
|
||||
background-color: $color-dragon;
|
||||
color: #fff;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.monster-card-details {
|
||||
column-count: 2;
|
||||
|
||||
.monster-ability-scores, .break-avoid {
|
||||
break-inside: avoid;
|
||||
}
|
||||
}
|
||||
|
||||
p.source {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.break-avoid {
|
||||
break-inside: avoid;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
58
docs/.vuepress/theme/components/MyMagicItems.vue
Normal file
58
docs/.vuepress/theme/components/MyMagicItems.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<main class="page content">
|
||||
<div class="theme-default-content">
|
||||
<div v-if="magicItems.length > 0">
|
||||
<masonry class="d-print-none" :cols="{'default': 2, 960: 1}" :gutter="24">
|
||||
<MagicItemCard v-for="(magicItem, idx) in magicItems" :magicItem="magicItem" :showActions="true" :key="idx">
|
||||
</MagicItemCard>
|
||||
</masonry>
|
||||
<div class="d-none d-print-block" v-for="magicItem in magicItems">
|
||||
<div>
|
||||
<h2 class="d-flex align-center">
|
||||
<div class="mr-4">{{ magicItem.title }}</div>
|
||||
<v-btn class="d-print-none mr-2" small depressed link :to="{ path: '/creation-de-sort/', query: { key: magicItem.key } }"><v-icon left>mdi-pencil</v-icon> Modifier</v-btn>
|
||||
<v-btn color="error" class="d-print-none" small depressed @click="$store.commit('myMagicItems/removeMagicItem', magicItem)"><v-icon left>mdi-delete</v-icon> Supprimer</v-btn>
|
||||
</h2>
|
||||
</div>
|
||||
<MagicItem :magicItem="magicItem" :isList="true" :hideTitle="true" />
|
||||
</div>
|
||||
</div>
|
||||
<template v-else>
|
||||
Vous n'avez aucun objet magique.
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MagicItem from '@theme/components/MagicItem'
|
||||
import MagicItemCard from '@theme/components/MagicItemCard'
|
||||
|
||||
export default {
|
||||
name: 'MyMagicItems',
|
||||
|
||||
components: {
|
||||
MagicItem,
|
||||
MagicItemCard
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
magicItems () {
|
||||
return this.$store.state.myMagicItems.magicItems
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
56
docs/.vuepress/theme/components/MyMonsters.vue
Normal file
56
docs/.vuepress/theme/components/MyMonsters.vue
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<main class="page content">
|
||||
<div class="theme-default-content">
|
||||
<template v-if="monsters.length > 0">
|
||||
<MonsterCard v-for="(monster, idx) in monsters" :monster="monster" :showActions="true" :key="idx">
|
||||
</MonsterCard>
|
||||
<div class="d-none d-print-block" v-for="monster in monsters">
|
||||
<div>
|
||||
<h1 class="d-flex align-center">
|
||||
<div class="mr-4">{{ monster.title }}</div>
|
||||
<v-btn class="d-print-none mr-2" small depressed link :to="{ path: '/creation-de-monstre-pnj/', query: { key: monster.key } }"><v-icon left>mdi-pencil</v-icon> Modifier</v-btn>
|
||||
<v-btn color="error" class="d-print-none" small depressed @click="$store.commit('myMonsters/removeMonster', monster)"><v-icon left>mdi-delete</v-icon> Supprimer</v-btn>
|
||||
</h1>
|
||||
</div>
|
||||
<Monster :monster="monster" :isList="true" :hideTitle="true" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
Vous n'avez recensé aucun monstre dans votre bestiaire.
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Monster from '@theme/components/Monster'
|
||||
import MonsterCard from '@theme/components/MonsterCard'
|
||||
|
||||
export default {
|
||||
name: 'MyMonsters',
|
||||
|
||||
components: {
|
||||
Monster,
|
||||
MonsterCard
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
monsters () {
|
||||
return this.$store.state.myMonsters.monsters
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
58
docs/.vuepress/theme/components/MySpells.vue
Normal file
58
docs/.vuepress/theme/components/MySpells.vue
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<template>
|
||||
<main class="page content">
|
||||
<div class="theme-default-content">
|
||||
<div v-if="spells.length > 0">
|
||||
<masonry class="d-print-none" :cols="{'default': 2, 960: 1}" :gutter="24">
|
||||
<SpellCard v-for="(spell, idx) in spells" :spell="spell" :showActions="true" :key="idx">
|
||||
</SpellCard>
|
||||
</masonry>
|
||||
<div class="d-none d-print-block" v-for="spell in spells">
|
||||
<div>
|
||||
<h2 class="d-flex align-center">
|
||||
<div class="mr-4">{{ spell.title }}</div>
|
||||
<v-btn class="d-print-none mr-2" small depressed link :to="{ path: '/creation-de-sort/', query: { key: spell.key } }"><v-icon left>mdi-pencil</v-icon> Modifier</v-btn>
|
||||
<v-btn color="error" class="d-print-none" small depressed @click="$store.commit('mySpells/removeSpell', spell)"><v-icon left>mdi-delete</v-icon> Supprimer</v-btn>
|
||||
</h2>
|
||||
</div>
|
||||
<Spell :spell="spell" :isList="true" :hideTitle="true" />
|
||||
</div>
|
||||
</div>
|
||||
<template v-else>
|
||||
Vous n'avez écrit aucun sort dans votre grimoire.
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Spell from '@theme/components/Spell'
|
||||
import SpellCard from '@theme/components/SpellCard'
|
||||
|
||||
export default {
|
||||
name: 'MySpells',
|
||||
|
||||
components: {
|
||||
Spell,
|
||||
SpellCard
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
spells () {
|
||||
return this.$store.state.mySpells.spells
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
|
|
@ -16,6 +16,9 @@
|
|||
<template v-for="item in items">
|
||||
<v-list-group v-if="item.children" :key="item.title" :value="isExpanded(item)" color="accent">
|
||||
<template v-slot:activator>
|
||||
<v-list-item-icon v-if="item.icon">
|
||||
<v-icon v-text="item.icon"></v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ item.title }}
|
||||
|
|
@ -26,25 +29,37 @@
|
|||
<template v-for="child in item.children">
|
||||
<v-list-group v-if="child.children" :key="child.title" sub-group :value="isExpanded(child)" color="accent">
|
||||
<template v-slot:activator>
|
||||
<v-list-item-icon v-if="child.icon">
|
||||
<v-icon v-text="child.icon"></v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ child.title }}
|
||||
<v-chip v-if="child.badge" class="ml-2" color="primary" x-small label v-html="displayBadge(child.badge)"></v-chip>
|
||||
</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</template>
|
||||
<v-list-item v-for="subchild in child.children" link :to="{path: subchild.path}" :exact="subchild.exact">
|
||||
<v-list-item-icon v-if="subchild.icon">
|
||||
<v-icon v-text="subchild.icon"></v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ subchild.title }}
|
||||
<v-chip v-if="subchild.badge" class="ml-2" color="primary" x-small label v-html="displayBadge(subchild.badge)"></v-chip>
|
||||
</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list-group>
|
||||
<v-divider v-else-if="child.type == 'divider'" />
|
||||
<v-list-item v-else :key="child.title" link :to="{path: child.path}" :exact="child.exact">
|
||||
<v-list-item-icon v-if="child.icon">
|
||||
<v-icon v-text="child.icon"></v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ child.title }}
|
||||
<v-chip v-if="child.badge" class="ml-2" color="primary" x-small label v-html="displayBadge(child.badge)"></v-chip>
|
||||
</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
|
@ -195,6 +210,15 @@ export default {
|
|||
setIsThemeDark () {
|
||||
this.$vuetify.theme.dark = !this.$vuetify.theme.dark
|
||||
this.$store.commit('setIsThemeDark', this.$vuetify.theme.dark)
|
||||
},
|
||||
displayBadge (badge) {
|
||||
if (badge == 'mySpells') {
|
||||
return this.$store.state.mySpells.spells.length
|
||||
} else if (badge == 'myMonsters') {
|
||||
return this.$store.state.myMonsters.monsters.length
|
||||
} else if (badge == 'myMagicItems') {
|
||||
return this.$store.state.myMagicItems.magicItems.length
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<v-btn class="hidden-sm-and-down site-title" text link :to="{ path: '/' }"><img src="/dragon_blanc.svg" /> {{ $site.title }}</v-btn>
|
||||
</v-toolbar-title>
|
||||
<SRDSearchBox v-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false" />
|
||||
<v-spacer />
|
||||
<v-spacer class="hidden-sm-and-down" />
|
||||
<v-btn class="hidden-sm-and-down" @click.stop="setIsThemeDark" icon>
|
||||
<v-icon v-html="$vuetify.theme.dark ? 'mdi-brightness-4' : 'mdi-brightness-7'"></v-icon>
|
||||
</v-btn>
|
||||
|
|
|
|||
|
|
@ -2,37 +2,64 @@
|
|||
<main class="page content">
|
||||
|
||||
<div class="theme-default-content">
|
||||
<h1>{{ $page.title }}</h1>
|
||||
<template v-if="!hideTitle">
|
||||
<h1 v-if="!isList">{{ spell.title }}</h1>
|
||||
<h2 v-else>{{ spell.title }}</h2>
|
||||
</template>
|
||||
<div class="spell-details">
|
||||
<div class="spell-school-level" v-html="displaySchoolLevel()"></div>
|
||||
<div class="spell-casting-time"><strong>Temps d'incantation</strong> : {{ $page.frontmatter.casting_time }}</div>
|
||||
<div class="spell-range"><strong>Portée</strong> : {{ $page.frontmatter.range }}</div>
|
||||
<div class="spell-school-level title" v-html="displaySchoolLevel()"></div>
|
||||
<div class="spell-casting-time"><strong>Temps d'incantation</strong> : {{ spell.frontmatter.casting_time }}</div>
|
||||
<div class="spell-range"><strong>Portée</strong> : {{ spell.frontmatter.range }}</div>
|
||||
<div class="spell-components"><strong>Composantes</strong> :
|
||||
<template v-if="$page.frontmatter.components.verbal">V</template><template v-if="$page.frontmatter.components.somatic || $page.frontmatter.components.material">,</template>
|
||||
<template v-if="$page.frontmatter.components.somatic">S</template><template v-if="$page.frontmatter.components.material">,</template>
|
||||
<template v-if="$page.frontmatter.components.material">M</template>
|
||||
<template v-if="$page.frontmatter.components.materials">({{$page.frontmatter.components.materials}})</template>
|
||||
<template v-if="spell.frontmatter.components.verbal">V</template><template v-if="spell.frontmatter.components.somatic || spell.frontmatter.components.material">,</template>
|
||||
<template v-if="spell.frontmatter.components.somatic">S</template><template v-if="spell.frontmatter.components.material">,</template>
|
||||
<template v-if="spell.frontmatter.components.material">M</template>
|
||||
<template v-if="spell.frontmatter.components.material && spell.frontmatter.components.materials">({{spell.frontmatter.components.materials}})</template>
|
||||
</div>
|
||||
<div class="spell-duration"><strong>Durée</strong> : <span v-if="spell.frontmatter.concentration">concentration, </span>{{ spell.frontmatter.duration }}</div>
|
||||
<div class="spell-classes" v-if="!isShort">
|
||||
<strong>Classe</strong> : <span v-for="(c, idx) in spell.frontmatter.classes" :key="idx">{{c}}<template v-if="idx != spell.frontmatter.classes.length-1">, </template><template v-if="idx == spell.frontmatter.classes.length-1 && spell.frontmatter.customClasses">, </template></span>
|
||||
<template v-if="spell.frontmatter.customClasses">
|
||||
<template>{{ spell.frontmatter.customClasses }}</template>
|
||||
</template>
|
||||
</div>
|
||||
<div class="spell-duration"><strong>Durée</strong> : <span v-if="$page.frontmatter.concentration">concentration, </span>{{ $page.frontmatter.duration }}</div>
|
||||
<div class="spell-classes"><strong>Classe</strong> : <span v-for="(c, idx) in $page.frontmatter.classes" :key="idx">{{c}}<template v-if="idx != $page.frontmatter.classes.length-1">, </template></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Content class="mt-4" />
|
||||
<template v-if="!isShort">
|
||||
<Content v-if="!spell.custom" :pageKey="spell.key" class="mt-4" />
|
||||
<div v-else v-html="md.render(spell.content)" class="mt-4"></div>
|
||||
</template>
|
||||
<div v-else v-html="spell.frontmatter.description" class="mt-4"></div>
|
||||
|
||||
<p v-if="$page.frontmatter.source" class="source">Source : <em>{{ $page.frontmatter.source }}</em></p>
|
||||
<p v-if="spell.frontmatter.source" class="source">Source : <em>{{ spell.frontmatter.source }}</em></p>
|
||||
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { displaySchoolLevel } from '@theme/util/spellHelpers'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
export default {
|
||||
name: 'Spell',
|
||||
|
||||
props: ['spell', 'isList', 'hideTitle', 'isShort'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
md: new MarkdownIt()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
displaySchoolLevel () {
|
||||
return displaySchoolLevel(this.$page.frontmatter)
|
||||
return displaySchoolLevel(this.spell.frontmatter)
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
// console.log(this.spell)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
91
docs/.vuepress/theme/components/SpellCard.vue
Normal file
91
docs/.vuepress/theme/components/SpellCard.vue
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<template>
|
||||
<v-card class="d-flex flex-column mb-6 spell-card">
|
||||
<v-card-title>
|
||||
{{ spell.title }}
|
||||
<v-spacer></v-spacer>
|
||||
<v-card-actions v-if="showActions">
|
||||
<v-btn dark icon class="d-print-none mr-2" link :to="{ path: '/creation-de-sort/', query: { key: spell.key } }"><v-icon>mdi-pencil</v-icon></v-btn>
|
||||
<v-btn dark icon class="d-print-none" @click="$store.commit('mySpells/removeSpell', spell)"><v-icon>mdi-delete</v-icon></v-btn>
|
||||
</v-card-actions>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="spell-details mt-3">
|
||||
<div class="spell-school-level title" v-html="displaySchoolLevel()"></div>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6" class="pb-0">
|
||||
<div class="spell-casting-time"><strong>Temps d'incantation</strong> : {{ spell.frontmatter.casting_time }}</div>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6" class="pb-0">
|
||||
<div class="spell-range"><strong>Portée</strong> : {{ spell.frontmatter.range }}</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6" class="pb-0">
|
||||
<div class="spell-components"><strong>Composantes</strong> :
|
||||
<template v-if="spell.frontmatter.components.verbal">V</template><template v-if="spell.frontmatter.components.somatic || spell.frontmatter.components.material">,</template>
|
||||
<template v-if="spell.frontmatter.components.somatic">S</template><template v-if="spell.frontmatter.components.material">,</template>
|
||||
<template v-if="spell.frontmatter.components.material">M</template>
|
||||
<template v-if="spell.frontmatter.components.material && spell.frontmatter.components.materials">({{spell.frontmatter.components.materials}})</template>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6" class="pb-0">
|
||||
<div class="spell-duration"><strong>Durée</strong> : <span v-if="spell.frontmatter.concentration">concentration, </span>{{ spell.frontmatter.duration }}</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
|
||||
<v-divider class="mt-3" />
|
||||
|
||||
<Content v-if="!spell.custom" :pageKey="spell.key" class="mt-4" />
|
||||
<div v-else v-html="md.render(spell.content)" class="mt-4"></div>
|
||||
|
||||
<div class="spell-classes" v-if="!isShort">
|
||||
<strong>Classe</strong> : <span v-for="(c, idx) in spell.frontmatter.classes" :key="idx">{{c}}<template v-if="idx != spell.frontmatter.classes.length-1">, </template><template v-if="idx == spell.frontmatter.classes.length-1 && spell.frontmatter.customClasses">, </template></span>
|
||||
<template v-if="spell.frontmatter.customClasses">
|
||||
<template>{{ spell.frontmatter.customClasses }}</template>
|
||||
</template>
|
||||
</div>
|
||||
<p v-if="spell.frontmatter.source" class="source">Source : <em>{{ spell.frontmatter.source }}</em></p>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { displaySchoolLevel } from '@theme/util/spellHelpers'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
export default {
|
||||
name: 'SpellCard',
|
||||
|
||||
props: ['spell', 'showActions', 'isShort'],
|
||||
|
||||
data () {
|
||||
return {
|
||||
md: new MarkdownIt()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
displaySchoolLevel () {
|
||||
return displaySchoolLevel(this.spell.frontmatter)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../styles/colors';
|
||||
|
||||
.spell-card {
|
||||
.v-card__title {
|
||||
background-color: $color-dragon;
|
||||
color: #fff;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
p.source {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -4,9 +4,21 @@ import 'vuetify/dist/vuetify.min.css'
|
|||
import '@mdi/font/css/materialdesignicons.css'
|
||||
import Vuetify from 'vuetify'
|
||||
import fr from 'vuetify/es5/locale/fr'
|
||||
import VueMasonry from 'vue-masonry-css'
|
||||
|
||||
import colors from 'vuetify/es5/util/colors'
|
||||
|
||||
// Stockage des donneés utilisateur dans le navigateur
|
||||
store.subscribe((mutation, state) => {
|
||||
if (mutation.type.includes('mySpells')) {
|
||||
localStorage.setItem('mySpells', JSON.stringify(state.mySpells))
|
||||
} else if (mutation.type.includes('myMonsters')) {
|
||||
localStorage.setItem('myMonsters', JSON.stringify(state.myMonsters))
|
||||
} else if (mutation.type.includes('myMagicItems')) {
|
||||
localStorage.setItem('myMagicItems', JSON.stringify(state.myMagicItems))
|
||||
}
|
||||
})
|
||||
|
||||
export default ({
|
||||
Vue,
|
||||
options,
|
||||
|
|
@ -15,7 +27,10 @@ export default ({
|
|||
}) => {
|
||||
require('./styles/main.scss')
|
||||
Vue.use(Vuex)
|
||||
Vue.mixin({ store: store })
|
||||
Vue.use(VueMasonry)
|
||||
Vue.mixin({
|
||||
store: store
|
||||
})
|
||||
Vue.use(Vuetify)
|
||||
options.vuetify = new Vuetify({
|
||||
theme: {
|
||||
|
|
|
|||
231
docs/.vuepress/theme/layouts/CreateMagicItemLayout.vue
Normal file
231
docs/.vuepress/theme/layouts/CreateMagicItemLayout.vue
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
<template>
|
||||
<div class="create-magic-item">
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/mes-objets-magiques/">Mes objets magiques</v-btn>
|
||||
<v-btn color="primary" depressed link to="/liste-objets-magiques/">Liste des objets magiques</v-btn>
|
||||
</div>
|
||||
|
||||
<h1 class="d-print-none">Création de sort</h1>
|
||||
|
||||
<div class="my-4 d-flex flex-wrap d-print-none">
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="print"><v-icon>mdi-printer</v-icon> Imprimer</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="download"><v-icon>mdi-file-download</v-icon> Sauvegarder</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed :loading="isUploading" @click="onUploadClick">
|
||||
<v-icon left>mdi-file-upload</v-icon> Charger
|
||||
</v-btn>
|
||||
<input ref="uploader" class="d-none" type="file" @change="upload">
|
||||
<v-btn :outlined="!isMagicItemInTreasureChest" color="accent" class="mr-1 mb-1" depressed @click="toggleMagicItemInTreasureChest"><v-icon>mdi-book</v-icon> {{ displayToggleMagicItemButton }}</v-btn>
|
||||
<v-btn :disabled="!isMagicItemInTreasureChest" outlined color="accent" class="mr-1 mb-1" depressed @click="updateMagicItemInTreasureChest"><v-icon>mdi-update</v-icon> MàJ dans le grimoire</v-btn>
|
||||
<v-btn outlined color="error" class="mb-1" depressed @click="reset"><v-icon>mdi-eraser</v-icon> Réinitialiser</v-btn>
|
||||
</div>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-print-none" :col="6">
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-text-field label="Nom" outlined dense v-model="magicItem.title"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select :items="types" label="Type" outlined dense v-model="magicItem.frontmatter.type"></v-select>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select :items="rarities" label="Rareté" outlined dense v-model="magicItem.frontmatter.rarity"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-text-field label="Sous-type" outlined dense v-model="magicItem.frontmatter.subtype"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-switch class="my-0" v-model="magicItem.hasAttunement" label="Harmonisation" @change="switchAttunement" dense></v-switch>
|
||||
</v-col>
|
||||
<v-col v-if="magicItem.hasAttunement">
|
||||
<v-text-field label="Type d'armonisation" outlined dense v-model="magicItem.frontmatter.attunement"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-textarea outlined label="Description" v-model="magicItem.content"></v-textarea>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</v-col>
|
||||
|
||||
<v-col :col="6">
|
||||
<MagicItem :magicItem="magicItem" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@theme/components/Breadcrumb'
|
||||
import MagicItem from '@theme/components/MagicItem'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { MAGICITEMTYPES, RARITIES } from '../../data/magicItems'
|
||||
import { getUrlParameter } from '@theme/util/filterHelpers'
|
||||
|
||||
export default {
|
||||
name: 'CreateMagicItemLayout',
|
||||
|
||||
components: {
|
||||
Breadcrumb,
|
||||
MagicItem
|
||||
},
|
||||
|
||||
computed: {
|
||||
isMagicItemInTreasureChest () {
|
||||
let isInTreasureChest = false
|
||||
for (let s of this.$store.state.myMagicItems.magicItems) {
|
||||
if (s.key == this.magicItem.key) {
|
||||
isInTreasureChest = true
|
||||
}
|
||||
}
|
||||
return isInTreasureChest
|
||||
},
|
||||
|
||||
displayToggleMagicItemButton () {
|
||||
if (this.isMagicItemInTreasureChest) {
|
||||
return 'Supprimer de mes objets magiques'
|
||||
}
|
||||
return 'Ajouter à mes objets magiques'
|
||||
},
|
||||
|
||||
displayAttunement () {
|
||||
if (this.customAttunement !== "") {
|
||||
return this.customAttunement
|
||||
} else {
|
||||
return 'harmonisation requise'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
isUploading: false,
|
||||
types: MAGICITEMTYPES,
|
||||
rarities: RARITIES,
|
||||
customAttunement: '',
|
||||
magicItem: {
|
||||
custom: true,
|
||||
pid: 'magicItem',
|
||||
key: null,
|
||||
title: '',
|
||||
content: '',
|
||||
hasAttunement: false,
|
||||
frontmatter: {
|
||||
type: '',
|
||||
subtype: '',
|
||||
rarity: '',
|
||||
attunement: '',
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
download () {
|
||||
saveAs(new Blob([JSON.stringify(this.magicItem)], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
}), "objet-magique.json")
|
||||
},
|
||||
|
||||
upload (e) {
|
||||
let file = e.target.files[0]
|
||||
let reader = new FileReader()
|
||||
let self = this
|
||||
|
||||
reader.onload = function() {
|
||||
let result = JSON.parse(reader.result)
|
||||
if (result.pid == 'magicItem') {
|
||||
self.magicItem = result
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsText(file)
|
||||
},
|
||||
|
||||
onUploadClick () {
|
||||
this.isUploading = true
|
||||
window.addEventListener('focus', () => {
|
||||
this.isUploading = false
|
||||
}, { once: true })
|
||||
|
||||
this.$refs.uploader.click()
|
||||
},
|
||||
|
||||
print () {
|
||||
window.print()
|
||||
},
|
||||
|
||||
toggleMagicItemInTreasureChest () {
|
||||
if (this.isMagicItemInTreasureChest) {
|
||||
this.$store.commit('myMagicItems/removeMagicItem', this.magicItem)
|
||||
} else {
|
||||
this.$store.commit('myMagicItems/addMagicItem', this.magicItem)
|
||||
}
|
||||
},
|
||||
|
||||
updateMagicItemInTreasureChest () {
|
||||
if (this.isMagicItemInTreasureChest) {
|
||||
this.$store.commit('myMagicItems/updateMagicItem', this.magicItem)
|
||||
}
|
||||
},
|
||||
|
||||
switchAttunement () {
|
||||
if (this.magicItem.hasAttunement) {
|
||||
this.magicItem.frontmatter.attunement = "harmonisation requise"
|
||||
} else {
|
||||
this.magicItem.frontmatter.attunement = ""
|
||||
}
|
||||
},
|
||||
|
||||
reset () {
|
||||
this.customAttunement = '',
|
||||
this.magicItem = {
|
||||
custom: true,
|
||||
pid: 'magicItem',
|
||||
key: Math.random().toString(36).substr(2, 9),
|
||||
title: '',
|
||||
content: '',
|
||||
hasAttunement: false,
|
||||
frontmatter: {
|
||||
type: '',
|
||||
subtype: '',
|
||||
rarity: '',
|
||||
attunement: '',
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', false)
|
||||
this.$store.commit('setRightDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
this.$store.commit('setInRightDrawer', null)
|
||||
|
||||
let magicItemKey = getUrlParameter(window.location.href, "key")
|
||||
|
||||
if (magicItemKey) {
|
||||
for (let magicItem of this.$store.state.myMagicItems.magicItems) {
|
||||
if (magicItem.key == magicItemKey) {
|
||||
this.magicItem = magicItem
|
||||
if (!this.magicItem.custom) {
|
||||
this.magicItem.content = magicItem.rawContent
|
||||
this.magicItem.custom = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.magicItem.key = Math.random().toString(36).substr(2, 9)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
402
docs/.vuepress/theme/layouts/CreateMonsterLayout.vue
Normal file
402
docs/.vuepress/theme/layouts/CreateMonsterLayout.vue
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
<template>
|
||||
<div class="create-monster">
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/mon-bestiaire/">Mon Bestiaire</v-btn>
|
||||
<v-btn color="primary" depressed link to="/bestiaire/">Bestiaire</v-btn>
|
||||
</div>
|
||||
|
||||
<h1 class="d-print-none">Création de monstre/PNJ</h1>
|
||||
|
||||
<div class="my-4 d-flex flex-wrap d-print-none">
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="print"><v-icon>mdi-printer</v-icon> Imprimer</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="download"><v-icon>mdi-file-download</v-icon> Sauvegarder</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed :loading="isUploading" @click="onUploadClick">
|
||||
<v-icon left>mdi-file-upload</v-icon> Charger
|
||||
</v-btn>
|
||||
<input ref="uploader" class="d-none" type="file" @change="upload">
|
||||
<v-btn :outlined="!isMonsterInBestiary" color="accent" class="mr-1 mb-1" depressed @click="toggleMonsterInBestiary"><v-icon>mdi-book</v-icon> {{ displayToggleMonsterButton }}</v-btn>
|
||||
<v-btn :disabled="!isMonsterInBestiary" outlined color="accent" class="mr-1 mb-1" depressed @click="updateMonsterInBestiary"><v-icon>mdi-update</v-icon> MàJ dans le bestiaire</v-btn>
|
||||
<v-btn outlined color="error" class="mb-1" depressed @click="reset"><v-icon>mdi-eraser</v-icon> Réinitialiser</v-btn>
|
||||
</div>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-print-none" :col="6">
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-text-field label="Nom" placeholder="Elfe noir" outlined dense v-model="monster.title"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select :items="sizes" item-text="label" item-value="abbr" label="Taille" outlined dense v-model="monster.frontmatter.size" @change="selectMonsterSize"></v-select>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select :items="challenges" item-text="label" item-value="value" label="Dangerosité" persistent-hint :hint="challengeHint" outlined dense v-model="monster.frontmatter.challenge"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-select :items="monsterTypes" label="Type" outlined dense v-model="monster.frontmatter.type"></v-select>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Sous-type" outlined dense v-model="monster.frontmatter.subtype"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Alignement" placeholder="Chaotique mauvais" outlined dense v-model="monster.frontmatter.alignment"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-flex justify-space-between">
|
||||
<v-switch :disabled="!monster.frontmatter.type" class="my-0 mr-4" v-model="monster.frontmatter.isSwarm" label="Nuée" dense @change="switchIsSwarm"></v-switch>
|
||||
<v-select :disabled="!monster.frontmatter.isSwarm" :items="sizes" item-text="label" item-value="abbr" label="Taille des créatures" outlined dense v-model="monster.frontmatter.swarmSize"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-flex align-center">
|
||||
<v-text-field class="mr-1" label="Force" type="number" min="1" outlined dense v-model="monster.frontmatter.abilityScores.for"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Dextérité" type="number" min="1" outlined dense v-model="monster.frontmatter.abilityScores.dex"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Constitution" type="number" min="1" outlined dense v-model="monster.frontmatter.abilityScores.con"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Intelligence" type="number" min="1" outlined dense v-model="monster.frontmatter.abilityScores.int"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Sagesse" type="number" min="1" outlined dense v-model="monster.frontmatter.abilityScores.sag"></v-text-field>
|
||||
<v-text-field class="mr-0" label="Charisme" type="number" min="1" outlined dense v-model="monster.frontmatter.abilityScores.cha"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-flex align-center">
|
||||
<v-text-field label="Dés de vie" type="number" min="1" outlined dense v-model="monster.frontmatter.hitDiceCount"></v-text-field>
|
||||
<v-switch class="my-0 mx-1" v-model="customHitDieSize" label="Dé de vie personnalisé" dense @change="switchCustomHitDizeSize"></v-switch>
|
||||
<v-select :disabled="!customHitDieSize" :items="sizes" item-text="hitDie" item-value="hitDie" label="Taille du dé de vie" outlined dense v-model="monster.frontmatter.hitDieSize"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-flex align-center">
|
||||
<v-select class="mr-1" :items="armorTypes" item-text="label" item-value="value" label="Type d'armure" outlined dense v-model="monster.frontmatter.ac.armorType" @change="selectArmorType"></v-select>
|
||||
<v-text-field v-if="monster.frontmatter.ac.armorType == 'armure naturelle'" label="Armure naturelle" type="number" min="0" outlined dense v-model="monster.frontmatter.ac.value"></v-text-field>
|
||||
<v-text-field v-if="monster.frontmatter.ac.armorType == 'custom'" label="Armure personnalisée" outlined dense v-model="monster.frontmatter.ac.value"></v-text-field>
|
||||
<v-switch class="my-0 ml-1" v-if="monster.frontmatter.ac.armorType != 'custom'" v-model="monster.frontmatter.ac.hasShield" label="Bouclier" dense></v-switch>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-flex align-center">
|
||||
<v-select class="mr-1" multiple clearable :items="abilities" item-text="label" item-value="value" label="Jets de sauvegarde" outlined dense v-model="monster.frontmatter.savingThrows"></v-select>
|
||||
<v-select class="mr-1" multiple clearable return-object :items="skills" item-text="label" item-value="value" label="Compétences" outlined dense v-model="selectedSkillsProficient" @change="selectSkill"></v-select>
|
||||
<v-select class="mr-1" multiple clearable :items="selectedSkillsProficient" item-text="label" item-value="value" label="Compétences expert" outlined dense v-model="selectedSkillsExpert" @change="selectSkillExpert"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row>
|
||||
<v-col class="d-flex align-center flex-wrap">
|
||||
<v-select class="mr-1" multiple clearable :items="conditions" label="Immunité états spéciaux" outlined dense v-model="monster.frontmatter.conditionImmunities"></v-select>
|
||||
<v-select class="mr-1" multiple clearable :items="damageTypes" label="Vulnérabilité au dégâts" outlined dense v-model="monster.frontmatter.damageTypeVulnerabilities"></v-select>
|
||||
<v-select class="mr-1" multiple clearable :items="damageTypes" label="Résistance au dégâts" outlined dense v-model="monster.frontmatter.damageTypeResistances"></v-select>
|
||||
<v-select class="mr-1" multiple clearable :items="damageTypes" label="Immunité au dégâts" outlined dense v-model="monster.frontmatter.damageTypeImmunities"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-flex align-center">
|
||||
<v-text-field class="mr-1" label="Au sol" type="number" min="0" outlined dense v-model="monster.frontmatter.movement.walk"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Escalade" type="number" min="0" outlined dense v-model="monster.frontmatter.movement.climb"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Fouissement" type="number" min="0" outlined dense v-model="monster.frontmatter.movement.burrow"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Nage" type="number" min="0" outlined dense v-model="monster.frontmatter.movement.swim"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Vol" type="number" min="0" outlined dense v-model="monster.frontmatter.movement.fly"></v-text-field>
|
||||
<v-switch class="my-0" v-model="monster.frontmatter.movement.hover" label="Vol stationnaire" dense></v-switch>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-flex align-center">
|
||||
<v-text-field class="mr-1" label="Perception des vibrations" type="number" min="0" outlined dense v-model="monster.frontmatter.senses.tremorsense"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Vision aveugle" type="number" min="0" outlined dense v-model="monster.frontmatter.senses.blindsight"></v-text-field>
|
||||
<v-text-field class="mr-1" label="Vision dans le noir" type="number" min="0" outlined dense v-model="monster.frontmatter.senses.darkvision"></v-text-field>
|
||||
<v-text-field class="mr-0" label="Vision parfaite" type="number" min="0" outlined dense v-model="monster.frontmatter.senses.truesight"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-flex align-center">
|
||||
<v-select class="mr-1" multiple clearable :items="languages" label="Langues" outlined dense v-model="monster.frontmatter.languages"></v-select>
|
||||
<v-text-field class="mr-1" label="Langue personnalisée" outlined dense v-model="monster.frontmatter.customLanguage"></v-text-field>
|
||||
<v-text-field label="Télépathie" type="number" min="0" outlined dense v-model="monster.frontmatter.telepathy"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-textarea outlined label="Capacités, Actions, Réactions, Actions légendaires" v-model="monster.content"></v-textarea>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</v-col>
|
||||
|
||||
<v-col :col="6">
|
||||
<Monster :monster="monster" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@theme/components/Breadcrumb'
|
||||
import Monster from '@theme/components/Monster'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { MONSTERTYPES, MONSTERSIZES, CHALLENGES, ABILITIES, SKILLS } from '../../data/monsters'
|
||||
import { stats } from '../../data/stats'
|
||||
import { ARMORTYPES } from '../../data/armorTypes'
|
||||
import { CONDITIONS } from '../../data/conditions'
|
||||
import { DAMAGETYPES } from '../../data/damageTypes'
|
||||
import { LANGUAGES } from '../../data/languages'
|
||||
import { getUrlParameter } from '@theme/util/filterHelpers'
|
||||
import { getProficiencyBonus, displayBonus } from '@theme/util/monsterHelpers'
|
||||
|
||||
export default {
|
||||
name: 'CreateMonsterLayout',
|
||||
|
||||
components: {
|
||||
Breadcrumb,
|
||||
Monster
|
||||
},
|
||||
|
||||
computed: {
|
||||
isMonsterInBestiary () {
|
||||
let isInBestiary = false
|
||||
for (let s of this.$store.state.myMonsters.monsters) {
|
||||
if (s.key == this.monster.key) {
|
||||
isInBestiary = true
|
||||
}
|
||||
}
|
||||
return isInBestiary
|
||||
},
|
||||
|
||||
displayToggleMonsterButton () {
|
||||
if (this.isMonsterInBestiary) {
|
||||
return 'Supprimer de mon bestiaire'
|
||||
}
|
||||
return 'Ajouter à mon bestiaire'
|
||||
},
|
||||
|
||||
challengeHint () {
|
||||
return 'Bonus de maîtrise : ' + displayBonus(getProficiencyBonus(this.monster.frontmatter.challenge))
|
||||
},
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
isUploading: false,
|
||||
monsterTypes: MONSTERTYPES,
|
||||
sizes: MONSTERSIZES,
|
||||
armorTypes: ARMORTYPES,
|
||||
abilities: ABILITIES,
|
||||
skills: SKILLS,
|
||||
skillObjects: stats.skills,
|
||||
conditions: CONDITIONS,
|
||||
damageTypes: DAMAGETYPES,
|
||||
challenges: CHALLENGES,
|
||||
languages: LANGUAGES,
|
||||
customHitDieSize: false,
|
||||
selectedSkillsProficient: [],
|
||||
selectedSkillsExpert: [],
|
||||
monster: {
|
||||
custom: true,
|
||||
pid: 'monster',
|
||||
key: null,
|
||||
title: '',
|
||||
content: '',
|
||||
frontmatter: {
|
||||
type: '',
|
||||
subtype: '',
|
||||
size: '',
|
||||
challenge: '0',
|
||||
alignment: '',
|
||||
isSwarm: false,
|
||||
swarmSize: '',
|
||||
hitDiceCount: 1,
|
||||
hitDieSize: '',
|
||||
abilityScores: {
|
||||
for: 10,
|
||||
dex: 10,
|
||||
con: 10,
|
||||
int: 10,
|
||||
sag: 10,
|
||||
cha: 10,
|
||||
},
|
||||
ac: {
|
||||
armorType: null,
|
||||
value: null, // Dans le cas du type d'armure "Armure naturelle"
|
||||
hasShield: false,
|
||||
},
|
||||
savingThrow: null,
|
||||
skills: null,
|
||||
movement: {
|
||||
walk: '',
|
||||
climb: '',
|
||||
burrow: '',
|
||||
swim: '',
|
||||
fly: '',
|
||||
hover: false,
|
||||
},
|
||||
senses: {
|
||||
tremorsense: '',
|
||||
blindsight: '',
|
||||
darkvision: '',
|
||||
truesight: '',
|
||||
},
|
||||
conditionImmunities: [],
|
||||
damageTypeVulnerabilities: [],
|
||||
damageTypeResistances: [],
|
||||
damageTypeImmunities: [],
|
||||
languages: [],
|
||||
customLanguage: '',
|
||||
telepathy: null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
download () {
|
||||
saveAs(new Blob([JSON.stringify(this.monster)], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
}), "monstre.json")
|
||||
},
|
||||
|
||||
upload (e) {
|
||||
let file = e.target.files[0]
|
||||
let reader = new FileReader()
|
||||
let self = this
|
||||
|
||||
reader.onload = function() {
|
||||
let result = JSON.parse(reader.result)
|
||||
if (result.pid == 'monster') {
|
||||
self.monster = result
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsText(file)
|
||||
},
|
||||
|
||||
onUploadClick () {
|
||||
this.isUploading = true
|
||||
window.addEventListener('focus', () => {
|
||||
this.isUploading = false
|
||||
}, { once: true })
|
||||
|
||||
this.$refs.uploader.click()
|
||||
},
|
||||
|
||||
print () {
|
||||
window.print()
|
||||
},
|
||||
|
||||
toggleMonsterInBestiary () {
|
||||
if (this.isMonsterInBestiary) {
|
||||
this.$store.commit('myMonsters/removeMonster', this.monster)
|
||||
} else {
|
||||
this.$store.commit('myMonsters/addMonster', this.monster)
|
||||
}
|
||||
},
|
||||
|
||||
updateMonsterInBestiary () {
|
||||
if (this.isMonsterInBestiary) {
|
||||
this.$store.commit('myMonsters/updateMonster', this.monster)
|
||||
}
|
||||
},
|
||||
|
||||
reset () {
|
||||
this.monster = {
|
||||
custom: true,
|
||||
pid: 'monster',
|
||||
key: Math.random().toString(36).substr(2, 9),
|
||||
title: '',
|
||||
content: '',
|
||||
frontmatter: {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
switchIsSwarm () {
|
||||
if (!this.monster.frontmatter.isSwarm) {
|
||||
this.monster.frontmatter.swarmSize = ''
|
||||
}
|
||||
},
|
||||
|
||||
selectMonsterSize (selected) {
|
||||
|
||||
},
|
||||
|
||||
switchCustomHitDizeSize () {
|
||||
if (!this.customHitDieSize) {
|
||||
this.monster.frontmatter.hitDieSize = ''
|
||||
}
|
||||
},
|
||||
|
||||
selectArmorType () {
|
||||
if (this.monster.frontmatter.ac.armorType == 'armure naturelle' || this.monster.frontmatter.ac.armorType == 'custom') {
|
||||
this.monster.frontmatter.ac.value = null
|
||||
}
|
||||
},
|
||||
|
||||
selectSkill () {
|
||||
this.monster.frontmatter.skills = []
|
||||
this.selectedSkillsProficient.forEach((skill, idx) => {
|
||||
this.monster.frontmatter.skills.push({name: skill.value})
|
||||
})
|
||||
this.setSkillsExpert()
|
||||
},
|
||||
|
||||
selectSkillExpert () {
|
||||
this.selectSkill()
|
||||
this.setSkillsExpert()
|
||||
},
|
||||
|
||||
setSkillsExpert () {
|
||||
this.monster.frontmatter.skills.forEach((mskill, idx) => {
|
||||
this.monster.frontmatter.skills[idx].isExpert = this.selectedSkillsExpert.indexOf(mskill.name) >= 0
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', false)
|
||||
this.$store.commit('setRightDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
this.$store.commit('setInRightDrawer', null)
|
||||
|
||||
let monsterKey = getUrlParameter(window.location.href, "key")
|
||||
|
||||
if (monsterKey) {
|
||||
for (let monster of this.$store.state.myMonsters.monsters) {
|
||||
if (monster.key == monsterKey) {
|
||||
this.monster = monster
|
||||
if (!this.monster.custom) {
|
||||
this.monster.content = monster.rawContent
|
||||
this.monster.custom = true
|
||||
}
|
||||
if (this.monster.frontmatter.skills) {
|
||||
this.monster.frontmatter.skills.forEach((mskill, idx) => {
|
||||
SKILLS.forEach((skill, jdx) => {
|
||||
if (mskill.name == skill.value) {
|
||||
this.selectedSkillsProficient.push(skill)
|
||||
if (mskill.isExpert) {
|
||||
this.selectedSkillsExpert.push(skill.value)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.monster.key = Math.random().toString(36).substr(2, 9)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
276
docs/.vuepress/theme/layouts/CreateSpellLayout.vue
Normal file
276
docs/.vuepress/theme/layouts/CreateSpellLayout.vue
Normal file
|
|
@ -0,0 +1,276 @@
|
|||
<template>
|
||||
<div class="create-spell">
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/mon-grimoire/">Mon Grimoire</v-btn>
|
||||
<v-btn color="primary" depressed link to="/grimoire/">Grimoire</v-btn>
|
||||
</div>
|
||||
|
||||
<h1 class="d-print-none">Création de sort</h1>
|
||||
|
||||
<div class="my-4 d-flex flex-wrap d-print-none">
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="print"><v-icon>mdi-printer</v-icon> Imprimer</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="download"><v-icon>mdi-file-download</v-icon> Sauvegarder</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed :loading="isUploading" @click="onUploadClick">
|
||||
<v-icon left>mdi-file-upload</v-icon> Charger
|
||||
</v-btn>
|
||||
<input ref="uploader" class="d-none" type="file" @change="upload">
|
||||
<v-btn :outlined="!isSpellInSpellBook" color="accent" class="mr-1 mb-1" depressed @click="toggleSpellInSpellBook"><v-icon>mdi-book</v-icon> {{ displayToggleSpellButton }}</v-btn>
|
||||
<v-btn :disabled="!isSpellInSpellBook" outlined color="accent" class="mr-1 mb-1" depressed @click="updateSpellInSpellBook"><v-icon>mdi-update</v-icon> MàJ dans le grimoire</v-btn>
|
||||
<v-btn outlined color="error" class="mb-1" depressed @click="reset"><v-icon>mdi-eraser</v-icon> Réinitialiser</v-btn>
|
||||
</div>
|
||||
|
||||
<v-row>
|
||||
<v-col class="d-print-none" :col="6">
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-text-field label="Nom" placeholder="Projectile magique" outlined dense v-model="spell.title"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select :items="schools" label="École" outlined dense v-model="spell.frontmatter.school"></v-select>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-select :items="levels" item-text="label" item-value="value" label="Niveau" outlined dense v-model="spell.frontmatter.level"></v-select>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-switch class="my-0" v-model="spell.frontmatter.ritual" label="Rituel" dense></v-switch>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-text-field label="Temps d'incantation" placeholder="1 action" outlined dense v-model="spell.frontmatter.casting_time"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Portée" placeholder="36 m" outlined dense v-model="spell.frontmatter.range"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field label="Duration" placeholder="instantanée" outlined dense v-model="spell.frontmatter.duration"></v-text-field>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-switch class="my-0" v-model="spell.frontmatter.concentration" label="Concentration" dense></v-switch>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-switch class="my-0" v-model="spell.frontmatter.components.verbal" label="Verbale" dense></v-switch>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-switch class="my-0" v-model="spell.frontmatter.components.somatic" label="Somatique" dense></v-switch>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-switch class="my-0" v-model="spell.frontmatter.components.material" label="Matérielle" dense></v-switch>
|
||||
</v-col>
|
||||
<v-col v-if="spell.frontmatter.components.material">
|
||||
<v-text-field label="Composantes matérielles" outlined dense v-model="spell.frontmatter.components.materials"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-select :items="classes" multiple clearable label="Disponible pour les classes de :" outlined dense v-model="spell.frontmatter.classes"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-text-field label="Classes personnalisées" placeholder="Forgesort" outlined dense v-model="spell.frontmatter.customClasses"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-text-field outlined label="Résumé" v-model="spell.frontmatter.description"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-textarea outlined label="Description" v-model="spell.content"></v-textarea>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</v-col>
|
||||
|
||||
<v-col :col="6">
|
||||
<Spell :spell="spell" />
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@theme/components/Breadcrumb'
|
||||
import Spell from '@theme/components/Spell'
|
||||
import { saveAs } from 'file-saver'
|
||||
import { CLASSES } from '../../data/classes'
|
||||
import { SPELLSCHOOLS, SPELLLEVELS } from '../../data/spells'
|
||||
import { getUrlParameter } from '@theme/util/filterHelpers'
|
||||
|
||||
export default {
|
||||
name: 'CreateSpellLayout',
|
||||
|
||||
components: {
|
||||
Breadcrumb,
|
||||
Spell
|
||||
},
|
||||
|
||||
computed: {
|
||||
isSpellInSpellBook () {
|
||||
let isInSpellBook = false
|
||||
for (let s of this.$store.state.mySpells.spells) {
|
||||
if (s.key == this.spell.key) {
|
||||
isInSpellBook = true
|
||||
}
|
||||
}
|
||||
return isInSpellBook
|
||||
},
|
||||
|
||||
displayToggleSpellButton () {
|
||||
if (this.isSpellInSpellBook) {
|
||||
return 'Supprimer de mon grimoire'
|
||||
}
|
||||
return 'Ajouter à mon grimoire'
|
||||
}
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
isUploading: false,
|
||||
schools: SPELLSCHOOLS,
|
||||
levels: SPELLLEVELS,
|
||||
classes: CLASSES,
|
||||
spell: {
|
||||
custom: true,
|
||||
pid: 'spell',
|
||||
key: null,
|
||||
title: '',
|
||||
content: '',
|
||||
frontmatter: {
|
||||
description: '',
|
||||
classes: '',
|
||||
customClasses: '',
|
||||
school: '',
|
||||
level: '',
|
||||
ritual: false,
|
||||
casting_time: '',
|
||||
range: '',
|
||||
duration: '',
|
||||
concentration: false,
|
||||
components: {
|
||||
verbal: false,
|
||||
somatic: false,
|
||||
material: false,
|
||||
materials: null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
download () {
|
||||
saveAs(new Blob([JSON.stringify(this.spell)], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
}), "sort.json")
|
||||
},
|
||||
|
||||
upload (e) {
|
||||
let file = e.target.files[0]
|
||||
let reader = new FileReader()
|
||||
let self = this
|
||||
|
||||
reader.onload = function() {
|
||||
let result = JSON.parse(reader.result)
|
||||
if (result.pid == 'spell') {
|
||||
self.spell = result
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsText(file)
|
||||
},
|
||||
|
||||
onUploadClick () {
|
||||
this.isUploading = true
|
||||
window.addEventListener('focus', () => {
|
||||
this.isUploading = false
|
||||
}, { once: true })
|
||||
|
||||
this.$refs.uploader.click()
|
||||
},
|
||||
|
||||
print () {
|
||||
window.print()
|
||||
},
|
||||
|
||||
toggleSpellInSpellBook () {
|
||||
if (this.isSpellInSpellBook) {
|
||||
this.$store.commit('mySpells/removeSpell', this.spell)
|
||||
} else {
|
||||
this.$store.commit('mySpells/addSpell', this.spell)
|
||||
}
|
||||
},
|
||||
|
||||
updateSpellInSpellBook () {
|
||||
if (this.isSpellInSpellBook) {
|
||||
this.$store.commit('mySpells/updateSpell', this.spell)
|
||||
}
|
||||
},
|
||||
|
||||
reset () {
|
||||
this.spell = {
|
||||
custom: true,
|
||||
pid: 'spell',
|
||||
key: Math.random().toString(36).substr(2, 9),
|
||||
title: '',
|
||||
content: '',
|
||||
frontmatter: {
|
||||
description: '',
|
||||
classes: '',
|
||||
customClasses: '',
|
||||
school: '',
|
||||
level: '',
|
||||
ritual: false,
|
||||
casting_time: '',
|
||||
range: '',
|
||||
duration: '',
|
||||
concentration: false,
|
||||
components: {
|
||||
verbal: false,
|
||||
somatic: false,
|
||||
material: false,
|
||||
materials: null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', false)
|
||||
this.$store.commit('setRightDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
this.$store.commit('setInRightDrawer', null)
|
||||
|
||||
let spellKey = getUrlParameter(window.location.href, "key")
|
||||
|
||||
if (spellKey) {
|
||||
for (let spell of this.$store.state.mySpells.spells) {
|
||||
if (spell.key == spellKey) {
|
||||
this.spell = spell
|
||||
if (!this.spell.custom) {
|
||||
this.spell.content = spell.rawContent
|
||||
this.spell.custom = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.spell.key = Math.random().toString(36).substr(2, 9)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -101,6 +101,12 @@ export default {
|
|||
if (THEMEISDARK === 'true') {
|
||||
this.$vuetify.theme.dark = true
|
||||
}
|
||||
|
||||
// Chargement des donées utilisateur depuis le navigateur
|
||||
this.$store.commit('mySpells/initialiseStore')
|
||||
this.$store.commit('myMonsters/initialiseStore')
|
||||
this.$store.commit('myMagicItems/initialiseStore')
|
||||
|
||||
// this.$vuetify.theme.dark = this.$store.state.isThemeDark
|
||||
|
||||
// let conditionLinks = document.links
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
<template>
|
||||
<div class="magic-item">
|
||||
<Breadcrumb />
|
||||
<MagicItem />
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/creation-d-objet-magique/"><v-icon left>mdi-plus</v-icon> Créer un objet magique</v-btn>
|
||||
<v-btn :outlined="!isMagicItemInTreasureChest" color="accent" class="mr-4" depressed @click="toggleMagicItemInTreasureChest"><v-icon>mdi-book</v-icon> {{ displayToggleMagicItemButton }}</v-btn>
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/mon-grimoire/">Mes objets magiques</v-btn>
|
||||
</div>
|
||||
<MagicItem :magicItem="$page" />
|
||||
<Edit />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -20,6 +25,35 @@ export default {
|
|||
Edit
|
||||
},
|
||||
|
||||
computed: {
|
||||
isMagicItemInTreasureChest () {
|
||||
let isInTreasureChest = false
|
||||
for (let s of this.$store.state.myMagicItems.magicItems) {
|
||||
if (s.key == this.$page.key) {
|
||||
isInTreasureChest = true
|
||||
}
|
||||
}
|
||||
return isInTreasureChest
|
||||
},
|
||||
|
||||
displayToggleMagicItemButton () {
|
||||
if (this.isMagicItemInTreasureChest) {
|
||||
return 'Supprimer de mes objets magiques'
|
||||
}
|
||||
return 'Ajouter à mes objets magiques'
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleMagicItemInTreasureChest () {
|
||||
if (this.isMagicItemInTreasureChest) {
|
||||
this.$store.commit('myMagicItems/removeMagicItem', this.$page)
|
||||
} else {
|
||||
this.$store.commit('myMagicItems/addMagicItem', this.$page)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', false)
|
||||
this.$store.commit('setRightDrawer', false)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
<template>
|
||||
<div class="magic-items">
|
||||
|
||||
<Breadcrumb />
|
||||
<div class="d-flex align-center mb-4">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/creation-d-objet-magique/"><v-icon left>mdi-plus</v-icon> Créer un objet magique</v-btn>
|
||||
<v-btn color="primary" depressed link to="/mes-objets-magiques/">Mes objets magiques</v-btn>
|
||||
</div>
|
||||
|
||||
<h1>Liste des objets magiques</h1>
|
||||
|
||||
|
|
@ -16,6 +20,10 @@
|
|||
:search="search"
|
||||
>
|
||||
|
||||
<template v-slot:item.isInTreasureChest="{ item }">
|
||||
<v-simple-checkbox off-icon="mdi-bookmark-outline" on-icon="mdi-bookmark" @input="toggleItemInTreasureChest(item)" :value="isItemInTreasureChest(item)"></v-simple-checkbox>
|
||||
</template>
|
||||
|
||||
<template v-slot:item.title="{ item }">
|
||||
<router-link :to="{ path: item.path }" class="subtitle-2">{{ item.title }}</router-link>
|
||||
</template>
|
||||
|
|
@ -40,6 +48,7 @@ export default {
|
|||
sortBy: 'title',
|
||||
sortDesc: false,
|
||||
headers: [
|
||||
{ text: "", align: 'center', sortable: false, value: 'isInTreasureChest' },
|
||||
{ text: "Nom", align: 'start', sortable: true, value: 'title' },
|
||||
{ text: "Type", align: 'start', sortable: false, value: 'frontmatter.type' },
|
||||
{ text: "Rareté", align: 'start', sortable: false, value: 'frontmatter.rarity' },
|
||||
|
|
@ -102,6 +111,25 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
isItemInTreasureChest (magicItem) {
|
||||
let isInTreasureChest = false
|
||||
for (let mi of this.$store.state.myMagicItems.magicItems) {
|
||||
if (mi.key == magicItem.key) {
|
||||
isInTreasureChest = true
|
||||
}
|
||||
}
|
||||
return isInTreasureChest
|
||||
},
|
||||
toggleItemInTreasureChest (magicItem) {
|
||||
if (this.isItemInTreasureChest(magicItem)) {
|
||||
this.$store.commit('myMagicItems/removeMagicItem', magicItem)
|
||||
} else {
|
||||
this.$store.commit('myMagicItems/addMagicItem', magicItem)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', true)
|
||||
this.$store.commit('setRightDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
|
|
|
|||
|
|
@ -1,20 +1,57 @@
|
|||
<template>
|
||||
<div class="monster">
|
||||
<Breadcrumb />
|
||||
<Monster />
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/creation-de-monstre-pnj/"><v-icon left>mdi-plus</v-icon> Créer un monstre</v-btn>
|
||||
<v-btn :outlined="!isMonsterInBestiary" color="accent" class="mr-4" depressed @click="toggleMonsterInBestiary"><v-icon>mdi-book</v-icon> {{ displayToggleMonsterButton }}</v-btn>
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/mon-bestiaire/">Mon Bestiaire</v-btn>
|
||||
</div>
|
||||
<Monster :monster="$page" />
|
||||
<Edit />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@theme/components/Breadcrumb'
|
||||
import Monster from '@theme/components/Monster'
|
||||
import Edit from '@theme/components/Edit'
|
||||
|
||||
export default {
|
||||
name: 'MonsterLayout',
|
||||
|
||||
components: {
|
||||
Breadcrumb,
|
||||
Monster
|
||||
Monster,
|
||||
Edit
|
||||
},
|
||||
|
||||
computed: {
|
||||
isMonsterInBestiary () {
|
||||
let isInBestiary = false
|
||||
for (let s of this.$store.state.myMonsters.monsters) {
|
||||
if (s.key == this.$page.key) {
|
||||
isInBestiary = true
|
||||
}
|
||||
}
|
||||
return isInBestiary
|
||||
},
|
||||
|
||||
displayToggleMonsterButton () {
|
||||
if (this.isMonsterInBestiary) {
|
||||
return 'Supprimer de mon grimoire'
|
||||
}
|
||||
return 'Ajouter à mon grimoire'
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleMonsterInBestiary () {
|
||||
if (this.isMonsterInBestiary) {
|
||||
this.$store.commit('myMonsters/removeMonster', this.$page)
|
||||
} else {
|
||||
this.$store.commit('myMonsters/addMonster', this.$page)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
<template>
|
||||
<div class="monsters">
|
||||
|
||||
<Breadcrumb />
|
||||
<div class="d-flex align-center mb-4">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/creation-de-monstre-pnj/"><v-icon left>mdi-plus</v-icon> Créer un monstre</v-btn>
|
||||
<v-btn color="primary" depressed link to="/mon-bestiaire/">Mon bestiaire</v-btn>
|
||||
</div>
|
||||
|
||||
<h1>Bestiaire</h1>
|
||||
|
||||
|
|
@ -16,6 +20,10 @@
|
|||
:search="search"
|
||||
>
|
||||
|
||||
<template v-slot:item.isInBestiary="{ item }">
|
||||
<v-simple-checkbox off-icon="mdi-bookmark-outline" on-icon="mdi-bookmark" @input="toggleMonsterInBestiary(item)" :value="isMonsterInBestiary(item)"></v-simple-checkbox>
|
||||
</template>
|
||||
|
||||
<template v-slot:item.title="{ item }">
|
||||
<router-link :to="{ path: item.path }" class="subtitle-2">{{ item.title }}</router-link>
|
||||
</template>
|
||||
|
|
@ -51,6 +59,7 @@ export default {
|
|||
sortBy: 'title',
|
||||
sortDesc: false,
|
||||
headers: [
|
||||
{ text: "", align: 'center', sortable: false, value: 'isInBestiary' },
|
||||
{ text: "Nom", align: 'start', sortable: true, value: 'title' },
|
||||
{ text: "ID", align: 'center', sortable: true, value: 'frontmatter.challenge' },
|
||||
{ text: "Type", align: 'start', sortable: false, value: 'frontmatter.type' },
|
||||
|
|
@ -153,6 +162,22 @@ export default {
|
|||
methods: {
|
||||
displayList (list) { return list.join(', ') },
|
||||
displayChallenge (challenge) { return displayChallenge(challenge) },
|
||||
isMonsterInBestiary (monster) {
|
||||
let isInBestiary = false
|
||||
for (let m of this.$store.state.myMonsters.monsters) {
|
||||
if (m.key == monster.key) {
|
||||
isInBestiary = true
|
||||
}
|
||||
}
|
||||
return isInBestiary
|
||||
},
|
||||
toggleMonsterInBestiary (monster) {
|
||||
if (this.isMonsterInBestiary(monster)) {
|
||||
this.$store.commit('myMonsters/removeMonster', monster)
|
||||
} else {
|
||||
this.$store.commit('myMonsters/addMonster', monster)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
|
|
|
|||
96
docs/.vuepress/theme/layouts/MyMagicItemsLayout.vue
Normal file
96
docs/.vuepress/theme/layouts/MyMagicItemsLayout.vue
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<template>
|
||||
<div class="my-magic-items">
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" depressed link to="/liste-objets-magiques/">Liste des objets magiques</v-btn>
|
||||
</div>
|
||||
|
||||
<h1>Mes objets magiques</h1>
|
||||
|
||||
<div class="my-4 d-flex flex-wrap d-print-none">
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="print"><v-icon>mdi-printer</v-icon> Imprimer</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="download"><v-icon>mdi-file-download</v-icon> Sauvegarder</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed :loading="isUploading" @click="onUploadClick">
|
||||
<v-icon left>mdi-file-upload</v-icon> Charger
|
||||
</v-btn>
|
||||
<input ref="uploader" class="d-none" type="file" @change="upload">
|
||||
<v-btn outlined color="error" class="mb-1" depressed @click="$store.commit('myMagicItems/resetMagicItems')"><v-icon>mdi-delete</v-icon> Effacer les objets magiques</v-btn>
|
||||
</div>
|
||||
|
||||
<MyMagicItems />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@theme/components/Breadcrumb'
|
||||
import MyMagicItems from '@theme/components/MyMagicItems'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
export default {
|
||||
name: 'MyMagicItemsLayout',
|
||||
|
||||
components: {
|
||||
Breadcrumb,
|
||||
MyMagicItems
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
isUploading: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
download () {
|
||||
saveAs(new Blob([JSON.stringify(this.$store.state.myMagicItems.magicItems)], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
}), "objets-magiques.json")
|
||||
},
|
||||
|
||||
upload (e) {
|
||||
let file = e.target.files[0]
|
||||
let reader = new FileReader()
|
||||
let self = this
|
||||
|
||||
reader.onload = function() {
|
||||
let result = JSON.parse(reader.result)
|
||||
let isValid = true
|
||||
if (result.length >= 1) {
|
||||
for (var s of result) {
|
||||
if (s.pid !== 'magicItem') {
|
||||
isValid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isValid) {
|
||||
self.$store.commit('myMagicItems/setMagicItems', result)
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsText(file)
|
||||
},
|
||||
|
||||
onUploadClick () {
|
||||
this.isUploading = true
|
||||
window.addEventListener('focus', () => {
|
||||
this.isUploading = false
|
||||
}, { once: true })
|
||||
|
||||
this.$refs.uploader.click()
|
||||
},
|
||||
|
||||
print () {
|
||||
window.print()
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', false)
|
||||
this.$store.commit('setRightDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
this.$store.commit('setInRightDrawer', null)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
96
docs/.vuepress/theme/layouts/MyMonstersLayout.vue
Normal file
96
docs/.vuepress/theme/layouts/MyMonstersLayout.vue
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<template>
|
||||
<div class="my-monsters">
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" depressed link to="/bestiaire/">Bestiaire</v-btn>
|
||||
</div>
|
||||
|
||||
<h1>Mon bestiaire</h1>
|
||||
|
||||
<div class="my-4 d-flex flex-wrap d-print-none">
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="print"><v-icon>mdi-printer</v-icon> Imprimer</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="download"><v-icon>mdi-file-download</v-icon> Sauvegarder</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed :loading="isUploading" @click="onUploadClick">
|
||||
<v-icon left>mdi-file-upload</v-icon> Charger
|
||||
</v-btn>
|
||||
<input ref="uploader" class="d-none" type="file" @change="upload">
|
||||
<v-btn outlined color="error" class="mb-1" depressed @click="$store.commit('myMonsters/resetMonsters')"><v-icon>mdi-delete</v-icon> Effacer le bestiaire</v-btn>
|
||||
</div>
|
||||
|
||||
<MyMonsters />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@theme/components/Breadcrumb'
|
||||
import MyMonsters from '@theme/components/MyMonsters'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
export default {
|
||||
name: 'MyMonstersLayout',
|
||||
|
||||
components: {
|
||||
Breadcrumb,
|
||||
MyMonsters
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
isUploading: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
download () {
|
||||
saveAs(new Blob([JSON.stringify(this.$store.state.myMonsters.monsters)], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
}), "bestiaire.json")
|
||||
},
|
||||
|
||||
upload (e) {
|
||||
let file = e.target.files[0]
|
||||
let reader = new FileReader()
|
||||
let self = this
|
||||
|
||||
reader.onload = function() {
|
||||
let result = JSON.parse(reader.result)
|
||||
let isValid = true
|
||||
if (result.length >= 1) {
|
||||
for (var s of result) {
|
||||
if (s.pid !== 'monster') {
|
||||
isValid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isValid) {
|
||||
self.$store.commit('myMonsters/setMonsters', result)
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsText(file)
|
||||
},
|
||||
|
||||
onUploadClick () {
|
||||
this.isUploading = true
|
||||
window.addEventListener('focus', () => {
|
||||
this.isUploading = false
|
||||
}, { once: true })
|
||||
|
||||
this.$refs.uploader.click()
|
||||
},
|
||||
|
||||
print () {
|
||||
window.print()
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', false)
|
||||
this.$store.commit('setRightDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
this.$store.commit('setInRightDrawer', null)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
96
docs/.vuepress/theme/layouts/MySpellsLayout.vue
Normal file
96
docs/.vuepress/theme/layouts/MySpellsLayout.vue
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<template>
|
||||
<div class="my-spells">
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" depressed link to="/grimoire/">Grimoire</v-btn>
|
||||
</div>
|
||||
|
||||
<h1>Mon grimoire</h1>
|
||||
|
||||
<div class="my-4 d-flex flex-wrap d-print-none">
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="print"><v-icon>mdi-printer</v-icon> Imprimer</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed @click="download"><v-icon>mdi-file-download</v-icon> Sauvegarder</v-btn>
|
||||
<v-btn outlined color="accent" class="mr-1 mb-1" depressed :loading="isUploading" @click="onUploadClick">
|
||||
<v-icon left>mdi-file-upload</v-icon> Charger
|
||||
</v-btn>
|
||||
<input ref="uploader" class="d-none" type="file" @change="upload">
|
||||
<v-btn outlined color="error" class="mb-1" depressed @click="$store.commit('mySpells/resetSpells')"><v-icon>mdi-delete</v-icon> Effacer le grimoire</v-btn>
|
||||
</div>
|
||||
|
||||
<MySpells />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@theme/components/Breadcrumb'
|
||||
import MySpells from '@theme/components/MySpells'
|
||||
import { saveAs } from 'file-saver'
|
||||
|
||||
export default {
|
||||
name: 'MySpellsLayout',
|
||||
|
||||
components: {
|
||||
Breadcrumb,
|
||||
MySpells
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
isUploading: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
download () {
|
||||
saveAs(new Blob([JSON.stringify(this.$store.state.mySpells.spells)], {
|
||||
type: "text/plain;charset=utf-8"
|
||||
}), "grimoire.json")
|
||||
},
|
||||
|
||||
upload (e) {
|
||||
let file = e.target.files[0]
|
||||
let reader = new FileReader()
|
||||
let self = this
|
||||
|
||||
reader.onload = function() {
|
||||
let result = JSON.parse(reader.result)
|
||||
let isValid = true
|
||||
if (result.length >= 1) {
|
||||
for (var s of result) {
|
||||
if (s.pid !== 'spell') {
|
||||
isValid = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isValid) {
|
||||
self.$store.commit('mySpells/setSpells', result)
|
||||
}
|
||||
}
|
||||
|
||||
reader.readAsText(file)
|
||||
},
|
||||
|
||||
onUploadClick () {
|
||||
this.isUploading = true
|
||||
window.addEventListener('focus', () => {
|
||||
this.isUploading = false
|
||||
}, { once: true })
|
||||
|
||||
this.$refs.uploader.click()
|
||||
},
|
||||
|
||||
print () {
|
||||
window.print()
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', false)
|
||||
this.$store.commit('setRightDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
this.$store.commit('setInRightDrawer', null)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -1,7 +1,12 @@
|
|||
<template>
|
||||
<div class="spell">
|
||||
<Breadcrumb />
|
||||
<Spell />
|
||||
<div class="d-flex align-center mb-4 d-print-none">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/creation-de-sort/"><v-icon left>mdi-plus</v-icon> Créer un sort</v-btn>
|
||||
<v-btn :outlined="!isSpellInSpellBook" color="accent" class="mr-4" depressed @click="toggleSpellInSpellBook"><v-icon>mdi-book</v-icon> {{ displayToggleSpellButton }}</v-btn>
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/mon-grimoire/">Mon Grimoire</v-btn>
|
||||
</div>
|
||||
<Spell :spell="$page" />
|
||||
<Edit />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -20,6 +25,35 @@ export default {
|
|||
Edit
|
||||
},
|
||||
|
||||
computed: {
|
||||
isSpellInSpellBook () {
|
||||
let isInSpellBook = false
|
||||
for (let s of this.$store.state.mySpells.spells) {
|
||||
if (s.key == this.$page.key) {
|
||||
isInSpellBook = true
|
||||
}
|
||||
}
|
||||
return isInSpellBook
|
||||
},
|
||||
|
||||
displayToggleSpellButton () {
|
||||
if (this.isSpellInSpellBook) {
|
||||
return 'Supprimer de mon grimoire'
|
||||
}
|
||||
return 'Ajouter à mon grimoire'
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleSpellInSpellBook () {
|
||||
if (this.isSpellInSpellBook) {
|
||||
this.$store.commit('mySpells/removeSpell', this.$page)
|
||||
} else {
|
||||
this.$store.commit('mySpells/addSpell', this.$page)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setHasRightDrawer', false)
|
||||
this.$store.commit('setRightDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
<template>
|
||||
<div class="spells">
|
||||
|
||||
<Breadcrumb />
|
||||
<div class="d-flex align-center mb-4">
|
||||
<Breadcrumb class="mr-auto" />
|
||||
<v-btn color="primary" class="mr-4" depressed link to="/creation-de-sort/"><v-icon left>mdi-plus</v-icon> Créer un sort</v-btn>
|
||||
<v-btn color="primary" depressed link to="/mon-grimoire/">Mon grimoire</v-btn>
|
||||
</div>
|
||||
|
||||
<h1>Grimoire</h1>
|
||||
|
||||
|
||||
<v-data-table
|
||||
class="data-table"
|
||||
:headers="headers"
|
||||
|
|
@ -16,6 +21,10 @@
|
|||
:search="search"
|
||||
>
|
||||
|
||||
<template v-slot:item.isInSpellBook="{ item }">
|
||||
<v-simple-checkbox off-icon="mdi-bookmark-outline" on-icon="mdi-bookmark" @input="toggleSpellInSpellBook(item)" :value="isSpellInSpellBook(item)"></v-simple-checkbox>
|
||||
</template>
|
||||
|
||||
<template v-slot:item.title="{ item }">
|
||||
<router-link :to="{ path: item.path }" class="subtitle-2">{{ item.title }}</router-link>
|
||||
</template>
|
||||
|
|
@ -61,6 +70,7 @@ export default {
|
|||
sortBy: 'title',
|
||||
sortDesc: false,
|
||||
headers: [
|
||||
{ text: "", align: 'center', sortable: false, value: 'isInSpellBook' },
|
||||
{ text: "Nom", align: 'start', sortable: true, value: 'title' },
|
||||
{ text: "Niveau", align: 'center', sortable: true, value: 'frontmatter.level' },
|
||||
{ text: "École", align: 'start', sortable: false, value: 'frontmatter.school' },
|
||||
|
|
@ -172,6 +182,25 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
isSpellInSpellBook (spell) {
|
||||
let isInSpellBook = false
|
||||
for (let s of this.$store.state.mySpells.spells) {
|
||||
if (s.key == spell.key) {
|
||||
isInSpellBook = true
|
||||
}
|
||||
}
|
||||
return isInSpellBook
|
||||
},
|
||||
toggleSpellInSpellBook (spell) {
|
||||
if (this.isSpellInSpellBook(spell)) {
|
||||
this.$store.commit('mySpells/removeSpell', spell)
|
||||
} else {
|
||||
this.$store.commit('mySpells/addSpell', spell)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.$store.commit('setDrawer', this.$vuetify.breakpoint.lgAndUp)
|
||||
this.$store.commit('setHasRightDrawer', true)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,27 @@
|
|||
font-family: serif;
|
||||
padding-top: 0;
|
||||
margin-top: 0;
|
||||
overflow: visible !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.d-flex {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.scroll-y {
|
||||
overflow: visible !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.application {
|
||||
display: block !important;
|
||||
}
|
||||
.application--wrap {
|
||||
display: block !important;
|
||||
}
|
||||
.content--wrap {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.p2c {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
}
|
||||
|
||||
.theme--light {
|
||||
h1, h2 {
|
||||
h1, h2, .v-card__title {
|
||||
color: $color-dragon;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,3 +73,19 @@ export function setBooleanMutation (param, store, mutation) {
|
|||
store.commit(mutation, value)
|
||||
}
|
||||
}
|
||||
|
||||
export function sortByString (a, b, direction = 'ASC') {
|
||||
const titleA = a.toUpperCase()
|
||||
const titleB = b.toUpperCase()
|
||||
let comparison = 0
|
||||
if (titleA > titleB) {
|
||||
comparison = 1
|
||||
} else if (titleA < titleB) {
|
||||
comparison = -1
|
||||
}
|
||||
if (direction == 'ASC') {
|
||||
return comparison
|
||||
} else {
|
||||
return comparison * -1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,11 @@ export function displayMonsterTypeSizeAlignment (monster, hideAlignment = false,
|
|||
result += ' de taille ' + monster.size
|
||||
}
|
||||
if (!hideAlignment) {
|
||||
result += ', ' + monster.alignment
|
||||
if (monster.alignment) {
|
||||
result += ', ' + monster.alignment
|
||||
} else {
|
||||
result += ', non alignée'
|
||||
}
|
||||
}
|
||||
if (showChallenge) {
|
||||
result += ', Dangerosité : ' + displayChallenge(monster.challenge)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ title: Magicien
|
|||
|**4**|+2|[Amélioration de caractéristiques](#amelioration-de-caracteristiques)|4|4|3|-|-|-|-|-|-|-|
|
||||
|**5**|+3|-|4|4|3|2|-|-|-|-|-|-|
|
||||
|**6**|+3|[Aptitude de tradition arcanique](#tradition-arcanique)|4|4|3|3|-|-|-|-|-|-|
|
||||
|**7**|+3|-|3|4|3|3|1|-|-|-|-|-|
|
||||
|**7**|+3|-|4|4|3|3|1|-|-|-|-|-|
|
||||
|**8**|+3|[Amélioration de caractéristiques](#amelioration-de-caracteristiques)|4|4|3|3|2|-|-|-|-|-|
|
||||
|**9**|+4|-|4|4|3|3|3|1|-|-|-|-|
|
||||
|**10**|+4|[Aptitude de tradition arcanique](#tradition-arcanique)|5|4|3|3|3|2|-|-|-|-|
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ title: Rôdeur
|
|||
|**5**|+3|[Attaque supplémentaire](#attaque-supplementaire)|4|4|2|-|-|-|
|
||||
|**6**|+3|[Amélioration d'ennemi juré](#ennemi-jure)|4|4|2|-|-|-|
|
||||
|**7**|+3|[Aptitude d'archétype de rôdeur](#archetype-de-rodeur)|5|4|3|-|-|-|
|
||||
|**8**|+3|[Amélioration de caractéristiques](#amelioration-de-caracteristiques)|5|4|3|-|-|-|
|
||||
|**8**|+3|[Amélioration de caractéristiques](#amelioration-de-caracteristiques), [Traversée des terrains](#traversee-des-terrains)|5|4|3|-|-|-|
|
||||
|**9**|+4|-|6|4|3|2|-|-|
|
||||
|**10**|+4|[Amélioration d'explorateur né](#explorateur-ne)|6|4|3|2|-|-|
|
||||
|**11**|+4|[Aptitude d'archétype de rôdeur](#archetype-de-rodeur)|7|4|3|3|-|-|
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
"dependencies": {
|
||||
"@mdi/font": "^5.0.45",
|
||||
"@vuepress/plugin-blog": "^1.9.2",
|
||||
"@vuepress/plugin-google-analytics": "^1.4.1",
|
||||
"@vuepress/plugin-pwa": "^1.4.1",
|
||||
"file-saver": "^2.0.2",
|
||||
"flexsearch": "nextapps-de/flexsearch",
|
||||
"js-cookie": "^2.2.1",
|
||||
"markdown-it-div": "^1.1.0",
|
||||
|
|
@ -22,6 +24,7 @@
|
|||
"sass-loader": "^8.0.2",
|
||||
"slugify": "^1.4.0",
|
||||
"vue": "^2.6.11",
|
||||
"vue-masonry-css": "^1.0.3",
|
||||
"vuepress": "^1.4.0",
|
||||
"vuepress-plugin-clean-urls": "^1.1.1",
|
||||
"vuepress-plugin-dehydrate": "^1.1.3",
|
||||
|
|
|
|||
15
yarn.lock
15
yarn.lock
|
|
@ -1110,6 +1110,11 @@
|
|||
vuepress-plugin-mailchimp "^1.4.1"
|
||||
vuepress-plugin-sitemap "^2.3.1"
|
||||
|
||||
"@vuepress/plugin-google-analytics@^1.4.1":
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@vuepress/plugin-google-analytics/-/plugin-google-analytics-1.4.1.tgz#d537e7ed026e7808d1d9d186880e595b04fe0868"
|
||||
integrity sha512-s43V5QHdTz0ayfy5vZrfMPpZzJBsj9L79TaxyMux1jOviS7oeWqkvNSblaHwP4Y8BxISehsKte8qsblQEN3zvQ==
|
||||
|
||||
"@vuepress/plugin-last-updated@1.4.1":
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@vuepress/plugin-last-updated/-/plugin-last-updated-1.4.1.tgz#89a9a4cbc242f9e0c5d380f73edb85ac4a7186c6"
|
||||
|
|
@ -3498,6 +3503,11 @@ file-loader@^3.0.1:
|
|||
loader-utils "^1.0.2"
|
||||
schema-utils "^1.0.0"
|
||||
|
||||
file-saver@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.2.tgz#06d6e728a9ea2df2cce2f8d9e84dfcdc338ec17a"
|
||||
integrity sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==
|
||||
|
||||
file-uri-to-path@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||
|
|
@ -8310,6 +8320,11 @@ vue-loader@^15.7.1:
|
|||
vue-hot-reload-api "^2.3.0"
|
||||
vue-style-loader "^4.1.0"
|
||||
|
||||
vue-masonry-css@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/vue-masonry-css/-/vue-masonry-css-1.0.3.tgz#a5e7bb248570eeedcd358637d3f1f4fc7f0c5f86"
|
||||
integrity sha512-viecHQiHVLez7HlYUQsv1wJb2MT/RDSzkDp6m3In41vPrk6OsBmT2qRE8LZqYIA4daIwrnx/Xm8h4fjOpuE3hw==
|
||||
|
||||
vue-property-decorator@^8.1.1:
|
||||
version "8.4.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-property-decorator/-/vue-property-decorator-8.4.1.tgz#fd8045b8678e1348fed57f9149279e00e404ed38"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue