1
0
Fork 0
mirror of https://github.com/em-squared/5e-drs.git synced 2025-10-30 13:14:20 +00:00

ajout du bestiaire

This commit is contained in:
Maxime Moraine 2020-04-15 16:27:16 +02:00
parent 637b99110c
commit dc30394196
380 changed files with 18521 additions and 635 deletions

View file

@ -39,6 +39,8 @@
crumbs.push({to: page.path, disabled: disabled, text: 'Grimoire'})
} else if (page.path == '/classes/') {
crumbs.push({to: page.path, disabled: disabled, text: 'Classes'})
} else if (page.path == '/bestiaire/') {
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 {

View file

@ -0,0 +1,24 @@
<template>
<div class="">
<v-divider class="my-4"/>
<v-btn v-if="reposity && !$page.frontmatter.notEditable" link depressed :href="source" target="_blank" color="accent" outlined><v-icon left>mdi-pencil</v-icon> Modifier</v-btn>
</div>
</template>
<script>
export default {
name: 'Edit',
computed: {
reposity () {
return this.$site.themeConfig.repository
},
source () {
return this.reposity + '/tree/master/docs' + this.$route.path + 'README.md'
}
}
}
</script>
<style lang="scss">
</style>

View file

@ -3,52 +3,130 @@
<div class="theme-default-content">
<h1>{{ $page.title }}</h1>
<div class="monster-hit-points">
<strong>Points de vie</strong>
<span>{{ displayHP() }}</span>
<div class="monster-type-size-alignment">
{{ displayMonsterTypeSizeAlignment() }}
</div>
<div class="monster-details">
<!-- Statblock -->
<div class="monster-ability-scores">
<div class="ability-str">
{{ displayAbilityScore(monster.abilityScores.for) }}
<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 px-2">
<div class="ability-label">
<strong>For</strong>
</div>
<div class="ability-score">
{{ displayAbilityScore(monster.abilityScores.for) }}
</div>
</div>
<div class="ability-dex text-center px-2">
<div class="ability-label">
<strong>Dex</strong>
</div>
<div class="ability-score">
{{ displayAbilityScore(monster.abilityScores.dex) }}
</div>
</div>
<div class="ability-con text-center px-2">
<div class="ability-label">
<strong>Con</strong>
</div>
<div class="ability-score">
{{ displayAbilityScore(monster.abilityScores.con) }}
</div>
</div>
</div>
<div class="ability-dex">
{{ displayAbilityScore(monster.abilityScores.dex) }}
</div>
<div class="ability-con">
{{ displayAbilityScore(monster.abilityScores.con) }}
</div>
<div class="ability-int">
{{ displayAbilityScore(monster.abilityScores.int) }}
</div>
<div class="ability-wis">
{{ displayAbilityScore(monster.abilityScores.sag) }}
</div>
<div class="ability-cha">
{{ displayAbilityScore(monster.abilityScores.cha) }}
<div class="monster-ability-scores-mental d-flex">
<div class="ability-int text-center px-2">
<div class="ability-label">
<strong>Int</strong>
</div>
<div class="ability-score">
{{ displayAbilityScore(monster.abilityScores.int) }}
</div>
</div>
<div class="ability-wis text-center px-2">
<div class="ability-label">
<strong>Sag</strong>
</div>
<div class="ability-score">
{{ displayAbilityScore(monster.abilityScores.sag) }}
</div>
</div>
<div class="ability-cha text-center px-2">
<div class="ability-label">
<strong>Cha</strong>
</div>
<div class="ability-score">
{{ displayAbilityScore(monster.abilityScores.cha) }}
</div>
</div>
</div>
</div>
<div class="monster-saving-throws">
<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">
<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>
</div>
</div>
<Content slot-key="special-traits" class="mt-4" />
<Content slot-key="actions" class="mt-4" />
<Content slot-key="reactions" class="mt-4" />
<Content slot-key="legendary-actions" class="mt-4" />
<Content/>
<Content class="mt-4"/>
<p v-if="$page.frontmatter.source" class="source">Source : <em>{{ monster.source }}</em></p>
@ -60,15 +138,18 @@ import {
displayBonus,
getModifier,
displayAbilityScore,
getProficiencyBonus
getProficiencyBonus,
displayChallenge
} from '@theme/util/monsterHelpers'
import {stats} from '../../data/stats.js'
import {armorTypes} from '../../data/armorTypes.js'
export default {
data () {
return {
}
},
@ -78,13 +159,48 @@ export default {
},
proficiencyBonus () {
return this.getProficiencyBonus()
}
},
passivePerception () {
let result = 10 + getModifier(this.monster.abilityScores.sag)
if (this.monster.skills) {
this.monster.skills.forEach((skill, idx) => {
if (skill.name == 'perception') {
if (skill.isExpert) {
result += this.proficiencyBonus * 2
} else {
result += this.proficiencyBonus
}
}
})
}
return result
},
},
methods: {
displayList (list) { return list.join(', ') },
displayAbilityScore (value) { return displayAbilityScore(value) },
getModifier (value) { return getModifier(value) },
getProficiencyBonus () { return getProficiencyBonus(this.monster.level) },
getProficiencyBonus () { return getProficiencyBonus(this.monster.challenge) },
displayMonsterTypeSizeAlignment () {
let result = ''
if (this.monster.isSwarm) {
result = 'Nuée de taille '+ this.monster.size + ' composée ' + stats.monsterTypes[this.monster.type].swarm
if (this.monster.subtype) {
result += ' (' + this.monster.subtype + ')'
}
result += ' de taille ' + this.monster.swarmSize
} else {
result = this.monster.type
if (this.monster.subtype) {
result += ' (' + this.monster.subtype + ')'
}
result += ' de taille ' + this.monster.size
}
result += ', ' + this.monster.alignment
return result
},
displaySavingThrowBonus (ability) {
let result = stats.abilities[ability].abbr
@ -94,8 +210,15 @@ export default {
},
displaySkillBonus (skill) {
let result = skill.name
let bonus = getModifier(this.monster.abilityScores[skill.ability]) + this.proficiencyBonus
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
if (skill.isExpert) {
bonus += this.proficiencyBonus // Bonus de maître doublé pour les experts
}
@ -107,27 +230,209 @@ export default {
displayHP () {
if (this.monster.customHP) {
return this.monster.customHP
} else if (this.monster.level) {
} 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 hitDiceBonus = 1
if (this.monster.level > 1) {
hitDiceBonus = Math.floor(this.monster.level / 2)
let hitPointsBonus = 1
if (this.monster.hitDiceCount > 1) {
hitPointsBonus = Math.floor(this.monster.hitDiceCount / 2)
}
let averageHP = this.monster.level * (hitDieSize / 2) + this.monster.level * getModifier(this.monster.abilityScores.con) + hitDiceBonus
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.level * getModifier(this.monster.abilityScores.con)
conMod = this.monster.hitDiceCount * getModifier(this.monster.abilityScores.con)
conMod = displayBonus(conMod)
}
return averageHP + ' (' + this.monster.level + "d" + hitDieSize + conMod + ')'
return averageHP + ' (' + this.monster.hitDiceCount + "d" + hitDieSize + conMod + ')'
}
return ""
},
displayChallenge () {
return displayChallenge(this.monster.challenge, true)
},
displayMovement () {
let result = ''
if (this.monster.movement.walk) {
result += this.monster.movement.walk + ' m'
} else {
result += '0 m'
}
if (this.monster.movement.climb) {
if (result != '') {
result += ', '
}
result += 'escalade ' + this.monster.movement.climb + ' m'
}
if (this.monster.movement.burrow) {
if (result != '') {
result += ', '
}
result += 'fouissement ' + this.monster.movement.burrow + ' m'
}
if (this.monster.movement.swim) {
if (result != '') {
result += ', '
}
result += 'nage ' + this.monster.movement.swim + ' m'
}
if (this.monster.movement.fly) {
if (result != '') {
result += ', '
}
result += 'vol ' + this.monster.movement.fly + ' m'
if (this.monster.movement.hover) {
result += ' (vol stationnaire)'
}
}
return result
},
displayAC () {
let ac = 10
let hasMageArmor = false
let mageArmorAc = 13
let mageArmor = ''
let armor = ''
// Le monstre n'a pas d'armure.
// CA = 10 + Dex
if (!this.monster.ac.armorType) {
ac = 10 + getModifier(this.monster.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
}
// 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') {
hasMageArmor = true
ac = ac + getModifier(this.monster.abilityScores.dex)
mageArmorAc = mageArmorAc + getModifier(this.monster.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]
// Le type d'armure n'existe pas. On l'ignore.
// CA = 10 + Dex
if (!armorType) {
ac = ac + getModifier(this.monster.abilityScores.dex)
} else {
// L'armure n'impose pas de limite de Dex
armor = this.monster.ac.armorType
if (armorType.maxDex === false) {
ac = armorType.value + getModifier(this.monster.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)) {
ac = armorType.value + armorType.maxDex
} else {
ac = armorType.value + getModifier(this.monster.abilityScores.dex)
}
}
}
}
}
// Le monstre a un bouclier. Sa CA augmente de 2.
if (this.monster.ac.hasShield) {
ac = ac + 2
mageArmorAc = mageArmorAc + 2
if (armor != '') {
armor += ', '
}
armor += 'bouclier'
if (hasMageArmor) {
armor = mageArmorAc + ' avec armure du mage, bouclier'
}
}
if (armor != '') {
ac += ' (' + armor + ')'
}
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.monster.senses.blindsight) {
if (result != '') {
result += ', '
}
result += 'vision aveugle ' + this.monster.senses.blindsight + ' m'
}
if (this.monster.senses.darkvision) {
if (result != '') {
result += ', '
}
result += 'vision dans le noir ' + this.monster.senses.darkvision + ' m'
}
if (this.monster.senses.truesight) {
if (result != '') {
result += ', '
}
result += 'vision parfaite ' + this.monster.senses.truesight + ' m'
}
if (result != '') {
result += ', '
}
}
result += 'Perception passive ' + this.passivePerception
return result
},
displayConditionImmunities () {
let result = ''
this.monster.conditionImmunities.forEach((condition, idx) => {
if (result != '') {
if (idx == this.monster.conditionImmunities.length - 1) {
result += ' et '
} else {
result += ', '
}
}
result += '<em>' + stats.conditions[condition].label + '</em>'
})
return result
},
displayDamageTypes (damageTypes) {
let result = ''
damageTypes.forEach((damageType, idx) => {
if (result != '') {
if (idx == damageTypes.length - 1) {
result += ' et '
} else {
result += ', '
}
}
result += stats.damageTypes[damageType].label
})
return result
}
},
mounted () {

View file

@ -0,0 +1,133 @@
<template>
<div class="monster-filters pa-1">
<v-text-field
class="mb-1"
v-model="search"
label="Filtrer"
single-line
hide-details
color="accent"
></v-text-field>
<v-expansion-panels multiple flat hover v-model="panels">
<v-expansion-panel>
<v-expansion-panel-header>Types</v-expansion-panel-header>
<v-expansion-panel-content>
<v-btn class="mb-2 mt-2" small color="primary" @click="resetTypes" dark>Réinitialiser</v-btn>
<v-switch v-for="(type, idx) in types" v-model="type.value" :label="type.label" dense class="ma-0" @change="switchType" color="accent"></v-switch>
</v-expansion-panel-content>
</v-expansion-panel>
<v-expansion-panel>
<v-expansion-panel-header>Tailles</v-expansion-panel-header>
<v-expansion-panel-content>
<v-btn class="mb-2 mt-2" small color="primary" @click="resetSizes" dark>Réinitialiser</v-btn>
<v-switch v-for="size in sizes" v-model="size.value" :label="size.label" dense class="ma-0" @change="switchSize" color="accent"></v-switch>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</div>
</template>
<script>
// import { mapMutations } from 'vuex'
import { setUrlParams, getUrlParameter, setBooleanMutation, setListMutation } from '@theme/util/filterHelpers'
export default {
name: 'MonsterFilters',
data () {
return {
panels: [],
}
},
computed: {
search: {
get () {
return this.$store.state.monsterFilters.search
},
set (newValue) {
this.$store.commit('monsterFilters/setSearch', newValue)
}
},
types: {
get () {
return this.$store.state.monsterFilters.types
},
set (newValue) {
this.$store.commit('monsterFilters/setTypes', newValue)
}
},
sizes: {
get () {
return this.$store.state.monsterFilters.sizes
},
set (newValue) {
this.$store.commit('monsterFilters/setSizes', newValue)
}
},
},
methods: {
switchType () {
let list = []
for (var i = 0; i < this.types.length; i++) {
if (this.types[i].value) {
list.push(this.types[i].label)
}
}
setUrlParams('types', list)
},
switchSize () {
let list = []
for (var i = 0; i < this.sizes.length; i++) {
if (this.sizes[i].value) {
list.push(this.sizes[i].label)
}
}
setUrlParams('raretes', list)
},
setColor (value, compare, color) {
if (value === compare) {
return color
}
return this.$site.themeConfig.primaryColor
},
resetTypes () {
this.$store.commit('monsterFilters/resetTypes')
this.switchType()
},
resetSizes () {
this.$store.commit('monsterFilters/resetSizes')
this.switchSize()
},
},
mounted () {
this.$store.dispatch('monsterFilters/reset')
let selectedSizes = getUrlParameter(window.location.href, "raretes").split(",")
let selectedTypes = getUrlParameter(window.location.href, "types").split(",")
setListMutation(selectedTypes, this.$store, 'monsterFilters/setTypesFromList')
setListMutation(selectedSizes, this.$store, 'monsterFilters/setSizesFromList')
}
}
</script>
<style lang="scss">
</style>

View file

@ -29,6 +29,7 @@
</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-content>
<v-list-item-title>
@ -38,7 +39,11 @@
</v-list-item>
</template>
</v-list-group>
<v-divider v-else-if="item.type == 'divider'" />
<v-list-item v-else :key="item.title" link :to="{path: item.path}" color="accent" :exact="item.exact">
<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 }}
@ -46,6 +51,26 @@
</v-list-item-content>
</v-list-item>
</template>
<v-list-item v-if="$site.themeConfig.repository" link :href="$site.themeConfig.repository" target="_blank">
<v-list-item-icon>
<v-icon>mdi-github</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>
Sources GitHub
</v-list-item-title>
</v-list-item-content>
</v-list-item>
<v-list-item v-if="$site.themeConfig.kofi" link :href="$site.themeConfig.kofi" target="_blank">
<v-list-item-icon>
<v-icon>mdi-glass-mug-variant</v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>
Encouragez le développement
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-navigation-drawer>
</template>
@ -68,7 +93,7 @@ export default {
set (newValue) {
this.$store.commit('setDrawer', newValue)
}
}
},
},
mounted () {
@ -99,6 +124,10 @@ export default {
if ((item.title == "Pour les joueurs") && (this.$route.path.includes('/grimoire/'))) {
return true
}
// Bestiaire
if ((item.title == "Pour les meneurs") && (this.$route.path.includes('/bestiaire/'))) {
return true
}
// Liste des objets magiques
if ((item.title == "Pour les meneurs") && (this.$route.path.includes('/liste-objets-magiques/'))) {
return true

View file

@ -7,9 +7,24 @@
<SRDSearchBox v-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false" />
<!-- <v-text-field flat solo-inverted hide-details prepend-inner-icon="mdi-magnify" label="Search" class="hidden-sm-and-down" /> -->
<v-spacer />
<v-btn @click.stop="aboutDialog = true" icon><v-icon>mdi-information</v-icon></v-btn>
<v-btn @click.stop="setRightDrawer" icon v-if="hasRightDrawer">
<v-icon>{{ rightDrawerIcon }}</v-icon>
</v-btn>
<v-dialog v-model="aboutDialog" max-width="600">
<v-card>
<v-card-title class="headline">À propos de H&D DRS</v-card-title>
<v-card-text>
<p>Ce site a été développé par <strong>Maxime Moraine</strong> alias <strong>Em-squared</strong>.</p>
<p>Les sources de ce site sont disponibles sur <a :href="$site.themeConfig.repository" target="_blank">GitHub</a> sous Licence GPLv3.</p>
<p><strong><em>Héros & Dragons</em></strong> est un jeu de rôle basé sur les mécaniques de l<a href="/licence-ogl">OGL5</a> et développé par les talents de la rédaction de <em><a href="https://www.black-book-editions.fr/catalogue.php?id=40" target="_blank">Casus Belli</a></em>, le magazine de référence des jeux de rôle.</p>
<p>Les textes de cette documentation appartiennent à <a href="https://www.black-book-editions.fr/catalogue.php?id=365" target="_blank">Black Book Éditions</a>.</p>
<p>Casus Belli et Black Book Éditions sont des marques déposées par <a href="https://www.black-book-editions.fr/" target="_blank">Black Book Éditions</a>. Tous droits réservés.</p>
</v-card-text>
</v-card>
</v-dialog>
</v-app-bar>
</template>
@ -27,6 +42,7 @@ export default {
data () {
return {
aboutDialog: false
}
},

View file

@ -7,10 +7,9 @@
</template>
<script>
export default {
name: 'Page',
components: { }
components: { }
}
</script>

View file

@ -3,6 +3,7 @@
<PageToc v-if="hasPageToc" />
<SpellFilters v-if="hasSpellFilters" />
<MagicItemFilters v-if="hasMagicItemFilters" />
<MonsterFilters v-if="hasMonsterFilters" />
</v-navigation-drawer>
</template>
@ -10,6 +11,7 @@
import PageToc from '@theme/components/PageToc'
import SpellFilters from '@theme/components/SpellFilters'
import MagicItemFilters from '@theme/components/MagicItemFilters'
import MonsterFilters from '@theme/components/MonsterFilters'
export default {
name: 'RightDrawer',
@ -17,6 +19,7 @@ export default {
components: {
SpellFilters,
MagicItemFilters,
MonsterFilters,
PageToc
},
@ -43,6 +46,9 @@ export default {
hasMagicItemFilters () {
return this.$store.state.inRightDrawer == 'magicItemFilters'
},
hasMonsterFilters () {
return this.$store.state.inRightDrawer == 'monsterFilters'
},
},
mounted () {