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

calculateur de rencontres

This commit is contained in:
Maxime Moraine 2021-02-15 12:17:44 +01:00
parent 82fc936b2d
commit 07b671b99d
10 changed files with 391 additions and 41 deletions

View file

@ -57,6 +57,8 @@
crumbs.push({to: page.path, disabled: disabled, text: 'Création de monstre ou PNJ'})
} else if (page.path == '/calculateur-de-caracteristiques/') {
crumbs.push({to: page.path, disabled: disabled, text: 'Calculateur de caractéristiques'})
} else if (page.path == '/calculateur-de-rencontres/') {
crumbs.push({to: page.path, disabled: disabled, text: 'Calculateur de rencontres'})
} else {
crumbs.push({to: page.path, disabled: disabled, text: page.frontmatter.breadcrumb || page.title})
}

View file

@ -0,0 +1,147 @@
<template>
<div class="encounter-calculator pa-1">
<v-expansion-panels multiple flat hover v-model="panels">
<v-expansion-panel>
<v-expansion-panel-header><strong>Calculateur de rencontre</strong></v-expansion-panel-header>
<v-expansion-panel-content class="pt-1">
<div>
<v-select :items="encounterLevels" item-text="level" item-value="level" label="Niveau moyen du groupe" outlined dense v-model="level"></v-select>
</div>
<div>
<v-text-field label="Nombre de PJ" type="number" min="1" outlined dense v-model="pc"></v-text-field>
</div>
<div v-if="creatures.length == 0" class="body-2 font-italic">
Aucune créature sélectionnée
</div>
<div v-else>
<div class="body-2 mb-4">
<span class="subtitle-2">Difficulté: </span>{{challenge.label}}
<v-progress-linear
:color="challenge.color"
:value="challengeRate"
></v-progress-linear>
</div>
<v-row class="d-flex align-center my-0" v-for="c in creatures">
<v-col class="px-0 py-1">
<div class="subtitle-2">{{c.title}}</div>
<!-- <div><span class="subtitle-2">ID : </span>{{c.frontmatter.challenge}}</div> -->
</v-col>
<v-col class="px-0 py-1">
<v-btn dense icon small @click="removeCreatureInEncounter(c)">
<v-icon color="red">mdi-delete</v-icon>
</v-btn>
</v-col>
</v-row>
</div>
</v-expansion-panel-content>
</v-expansion-panel>
</v-expansion-panels>
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex'
import { CHALLENGES, ENCOUNTERLEVELS } from '../../data/monsters'
import { getPCbyChallenge } from '@theme/util/monsterHelpers'
export default {
name: 'EncounterCalculator',
data () {
return {
panels: [0],
challenges: CHALLENGES,
encounterLevels: ENCOUNTERLEVELS,
}
},
computed: {
...mapState({
creatures: state => state.encounterCalculator.creatures,
}),
...mapGetters({
totalPC: 'encounterCalculator/totalPC',
}),
pc: {
get () {
return this.$store.state.encounterCalculator.pc
},
set (newValue) {
this.$store.commit('encounterCalculator/setPC', newValue)
}
},
level: {
get () {
return this.$store.state.encounterCalculator.level
},
set (newValue) {
this.$store.commit('encounterCalculator/setLevel', Number(newValue))
}
},
challenge () {
let label = "Aisée"
let color = 'green'
if (this.totalPC > this.challengeForGroup.easy) {
label = "Ordinaire"
color = 'amber'
}
if (this.totalPC > this.challengeForGroup.normal) {
label = "Ardue"
color = 'orange'
}
if (this.totalPC > this.challengeForGroup.hard) {
label = "Abominable"
color = 'red'
}
if (this.totalPC > this.challengeForGroup.deadly) {
label = "Impossible"
color = 'purple'
}
return {label, color}
},
totalPC () {
let pc = 0
for (let c of this.creatures) {
pc += getPCbyChallenge(Number(c.frontmatter.challenge))
}
return pc
},
challengeForGroup () {
let level = this.encounterLevels[this.encounterLevels.findIndex((item) => { return item.level == this.level })]
return {
easy: (level.easy*this.pc)/4,
normal: (level.normal*this.pc)/4,
hard: (level.hard*this.pc)/4,
deadly: (level.deadly*this.pc)/4,
}
},
challengeRate () {
return (this.totalPC/this.challengeForGroup.deadly)*100
},
},
methods: {
removeCreatureInEncounter (creature) {
this.$store.commit('encounterCalculator/removeCreature', creature)
}
},
mounted () {
}
}
</script>
<style lang="scss">
</style>

View file

@ -4,6 +4,7 @@
<SpellFilters v-if="hasSpellFilters" />
<MagicItemFilters v-if="hasMagicItemFilters" />
<MonsterFilters v-if="hasMonsterFilters" />
<EncounterCalculator v-if="hasMonsterFilters" />
</v-navigation-drawer>
</template>
@ -12,6 +13,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'
import EncounterCalculator from '@theme/components/EncounterCalculator'
export default {
name: 'RightDrawer',
@ -20,6 +22,7 @@ export default {
SpellFilters,
MagicItemFilters,
MonsterFilters,
EncounterCalculator,
PageToc
},

View file

@ -39,11 +39,13 @@ export default ({
primary: '#4c6477', // Dragons (Bleu)
navbar: '#435a3f', // Héros (Vert)
accent: '#435a3f', // Héros
gold: "#bab468",
},
dark: {
primary: '#6c8599', // Dragons (Bleu)
navbar: '#435a3f', // Héros (Vert)
accent: '#6c8599', // Dragons
gold: "#bab468",
}
}
},

View file

@ -12,6 +12,52 @@
<h1>Bestiaire</h1>
<div class="columns-toggles d-md-flex d-none align-center mb-2">
<div><strong>Colonnes affichées :</strong></div>
<v-checkbox
class="mt-0 mr-4"
v-model="showColumn.type"
label="Type"
hide-details
@change="setShowColumn"
></v-checkbox>
<v-checkbox
class="mt-0 mr-4"
v-model="showColumn.size"
label="Taille"
hide-details
@change="setShowColumn"
></v-checkbox>
<v-checkbox
class="mt-0 mr-4"
v-model="showColumn.subtype"
label="Sous-type"
hide-details
@change="setShowColumn"
></v-checkbox>
<v-checkbox
class="mt-0 mr-4"
v-model="showColumn.environments"
label="Environnements"
hide-details
@change="setShowColumn"
></v-checkbox>
<v-checkbox
class="mt-0 mr-4"
v-model="showColumn.dungeonTypes"
label="Type de donjons"
hide-details
@change="setShowColumn"
></v-checkbox>
<v-checkbox
class="mt-0 mr-4"
v-model="showColumn.encounter"
label="Rencontre"
hide-details
@change="setShowColumn"
></v-checkbox>
</div>
<div class="active-filters mb-2">
<div class="challengeRange-filter" v-if="Number(challengeRange[0]) >= 0 && Number(challengeRange[1]) <= challenges.length-1">
<strong>Indice de dangerosité</strong> entre {{ challenges[challengeRange[0]].label }} et {{ challenges[challengeRange[1]].label }}
@ -74,6 +120,12 @@
<span v-if="item.frontmatter.dungeonTypes">{{ displayList(item.frontmatter.dungeonTypes) }}</span>
</template>
<template v-slot:item.isInEncounter="{ item }">
<v-btn dense icon @click.stop="addCreatureInEncounter(item)">
<v-icon>mdi-sword-cross</v-icon>
</v-btn>
</template>
</v-data-table>
<v-row class="align-center mb-12 pb-6">
@ -96,6 +148,7 @@ import { isResourceInLibrary } from '@theme/util'
import Monster from '@theme/components/Monster'
import MyMonstersButton from '@theme/global-components/MyMonstersButton'
import { CHALLENGES } from '../../data/monsters'
import Cookies from 'js-cookie'
export default {
components: { Breadcrumb, Monster, MyMonstersButton },
@ -116,9 +169,10 @@ export default {
showColumn: {
type: true,
size: true,
subtype: true,
environments: true,
dungeonTypes: true,
subtype: false,
environments: false,
dungeonTypes: false,
encounter: true,
},
challenges: CHALLENGES
}
@ -138,7 +192,7 @@ export default {
let 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: "ID", align: 'center', sortable: true, value: 'frontmatter.challenge' },
]
if (this.showColumn.type && this.$vuetify.breakpoint.mdAndUp) {
headers.push({ text: "Type", align: 'start', sortable: false, value: 'frontmatter.type' })
@ -155,6 +209,9 @@ export default {
if (this.showColumn.dungeonTypes && this.$vuetify.breakpoint.mdAndUp) {
headers.push({ text: "Type de donjons", align: 'start', sortable: false, value: 'frontmatter.dungeonTypes' })
}
if (this.showColumn.encounter && this.$vuetify.breakpoint.mdAndUp) {
headers.push({ text: "Rencontre", align: 'center', sortable: false, value: 'isInEncounter' })
}
return headers
},
@ -306,6 +363,13 @@ export default {
}
},
isCreatureInEncounter (creature) {
return isResourceInLibrary(creature, this.$store.state.encounterCalculator.creatures)
},
addCreatureInEncounter (creature) {
this.$store.commit('encounterCalculator/addCreature', creature)
},
selectItemPerPage (value) {
setUrlParams("lignes", [value])
},
@ -317,7 +381,11 @@ export default {
onClickRow (row, item) {
item.expand(!item.isExpanded)
}
},
setShowColumn () {
Cookies.set('5e-drs-bestiaire-colonnes', this.showColumn, { expires: 365 })
},
},
mounted () {
@ -333,6 +401,11 @@ export default {
if (page) {
this.page = page
}
const showColumn = Cookies.get('5e-drs-bestiaire-colonnes')
if (showColumn) {
this.showColumn = JSON.parse(showColumn)
}
}
}
</script>

View file

@ -1,4 +1,5 @@
import {stats} from '../../data/stats'
import {CHALLENGES} from '../../data/monsters'
// Calcul du modificateur de caractéristique
export function getModifier (score) {
@ -68,3 +69,12 @@ export function displayMonsterTypeSizeAlignment (monster, hideAlignment = false,
}
return result
}
// Retourne le nombre de points de combat pour un indice de dangerosité
export function getPCbyChallenge(challenge) {
let challengeIndex = CHALLENGES.findIndex(item => item.value == challenge)
if (challengeIndex > -1) {
return CHALLENGES[challengeIndex].pc
}
return false
}