Made spells into a special kind of action

This commit is contained in:
Thaum Rystra
2020-04-16 15:21:31 +02:00
parent e06196a54c
commit 1717ee4bc7
7 changed files with 389 additions and 251 deletions

View File

@@ -1,4 +1,4 @@
import { AttackSchema } from '/imports/api/properties/Attacks.js'; import { ActionSchema } from '/imports/api/properties/Actions.js';
import SimpleSchema from 'simpl-schema'; import SimpleSchema from 'simpl-schema';
const magicSchools = [ const magicSchools = [
@@ -13,7 +13,7 @@ const magicSchools = [
]; ];
let SpellSchema = new SimpleSchema({}) let SpellSchema = new SimpleSchema({})
.extend(AttackSchema) .extend(ActionSchema)
.extend({ .extend({
name: { name: {
type: String, type: String,
@@ -29,6 +29,10 @@ let SpellSchema = new SimpleSchema({})
castWithoutSpellSlots: { castWithoutSpellSlots: {
type: Boolean, type: Boolean,
optional: true, optional: true,
},
hasAttackRoll: {
type: Boolean,
optional: true,
}, },
// Spell lists that this spell appears on // Spell lists that this spell appears on
spellLists: { spellLists: {
@@ -87,6 +91,11 @@ let SpellSchema = new SimpleSchema({})
defaultValue: 'abjuration', defaultValue: 'abjuration',
allowedValues: magicSchools, allowedValues: magicSchools,
}, },
// Set better defaults for the action
actionType: {
type: String,
defaultValue: 'spell',
},
}); });
export { SpellSchema }; export { SpellSchema };

View File

@@ -1,20 +1,40 @@
<template> <template>
<div class="character-sheet layout column"> <div class="character-sheet layout column">
<v-toolbar <v-toolbar
app clipped-left app
clipped-left
:color="character.color || 'secondary'" :color="character.color || 'secondary'"
:dark="isDarkColor(character.color || theme.primary)" :dark="isDarkColor(character.color || theme.primary)"
> >
<v-btn v-if="showMenuButton" flat icon @click="toggleDrawer"> <v-btn
v-if="showMenuButton"
flat
icon
@click="toggleDrawer"
>
<v-icon>menu</v-icon> <v-icon>menu</v-icon>
</v-btn> </v-btn>
<div class="flex">{{character.name}}</div> <div class="flex">
<v-btn flat icon @click="recompute(character._id)"> {{ character.name }}
</div>
<v-btn
flat
icon
@click="recompute(character._id)"
>
<v-icon>refresh</v-icon> <v-icon>refresh</v-icon>
</v-btn> </v-btn>
<v-menu bottom left transition="slide-y-transition" data-id="creature-menu"> <v-menu
<template v-slot:activator="{ on }"> bottom
<v-btn icon v-on="on"> left
transition="slide-y-transition"
data-id="creature-menu"
>
<template #activator="{ on }">
<v-btn
icon
v-on="on"
>
<v-icon>more_vert</v-icon> <v-icon>more_vert</v-icon>
</v-btn> </v-btn>
</template> </template>
@@ -37,8 +57,8 @@
</v-list> </v-list>
</v-menu> </v-menu>
<v-tabs <v-tabs
v-model="tab"
slot="extension" slot="extension"
v-model="tab"
centered centered
grow grow
> >
@@ -62,7 +82,10 @@
</v-tab> </v-tab>
</v-tabs> </v-tabs>
</v-toolbar> </v-toolbar>
<v-content class="flex" v-if="$subReady.singleCharacter"> <v-content
v-if="$subReady.singleCharacter"
class="flex"
>
<v-tabs-items v-model="tab"> <v-tabs-items v-model="tab">
<v-tab-item> <v-tab-item>
<stats-tab :creature-id="creatureId" /> <stats-tab :creature-id="creatureId" />
@@ -94,7 +117,7 @@
import Creatures from '/imports/api/creature/Creatures.js'; import Creatures from '/imports/api/creature/Creatures.js';
import removeCreature from '/imports/api/creature/removeCreature.js'; import removeCreature from '/imports/api/creature/removeCreature.js';
import isDarkColor from '/imports/ui/utility/isDarkColor.js'; import isDarkColor from '/imports/ui/utility/isDarkColor.js';
import { mapMutations } from "vuex"; import { mapMutations } from 'vuex';
import { theme } from '/imports/ui/theme.js'; import { theme } from '/imports/ui/theme.js';
import StatsTab from '/imports/ui/creature/character/characterSheetTabs/StatsTab.vue'; import StatsTab from '/imports/ui/creature/character/characterSheetTabs/StatsTab.vue';
import FeaturesTab from '/imports/ui/creature/character/characterSheetTabs/FeaturesTab.vue'; import FeaturesTab from '/imports/ui/creature/character/characterSheetTabs/FeaturesTab.vue';
@@ -105,10 +128,6 @@
import { recomputeCreature } from '/imports/api/creature/computation/recomputeCreature.js'; import { recomputeCreature } from '/imports/api/creature/computation/recomputeCreature.js';
export default { export default {
props: {
showMenuButton: Boolean,
creatureId: String,
},
components: { components: {
StatsTab, StatsTab,
FeaturesTab, FeaturesTab,
@@ -117,13 +136,20 @@
PersonaTab, PersonaTab,
TreeTab, TreeTab,
}, },
props: {
showMenuButton: Boolean,
creatureId: {
type: String,
required: true,
},
},
data(){return { data(){return {
theme, theme,
tab: 0, tab: 0,
}}, }},
methods: { methods: {
...mapMutations([ ...mapMutations([
"toggleDrawer", 'toggleDrawer',
]), ]),
recompute(charId){ recompute(charId){
recomputeCreature.call({charId}); recomputeCreature.call({charId});
@@ -160,7 +186,7 @@
}, },
callback(confirmation){ callback(confirmation){
if(!confirmation) return; if(!confirmation) return;
removeCreature.call({charId: that.creatureId}, (error, result) => { removeCreature.call({charId: that.creatureId}, (error) => {
if (error) { if (error) {
console.error(error); console.error(error);
} else { } else {
@@ -182,6 +208,9 @@
return Creatures.findOne(this.creatureId) || {}; return Creatures.findOne(this.creatureId) || {};
}, },
}, },
provide: {
creature: this.character,
}
} }
</script> </script>

View File

@@ -1,20 +1,21 @@
<template lang="html"> <template lang="html">
<div class="stats-tab ma-2"> <div class="stats-tab ma-2">
<div class="px-2 pt-2"> <div class="px-2 pt-2">
<health-bar-card-container :creature-id="creatureId" /> <health-bar-card-container :creature-id="creatureId" />
</div> </div>
<column-layout> <column-layout>
<div class="ability-scores"> <div class="ability-scores">
<v-card> <v-card>
<v-list> <v-list>
<template v-for="(ability, index) in abilities"> <template v-for="(ability, index) in abilities">
<v-divider v-if="index !== 0"/> <v-divider
v-if="index !== 0"
:key="index"
/>
<ability-list-tile <ability-list-tile
v-bind="ability"
:key="ability._id" :key="ability._id"
v-bind="ability"
:data-id="ability._id" :data-id="ability._id"
@click="clickProperty({_id: ability._id})" @click="clickProperty({_id: ability._id})"
/> />
@@ -23,7 +24,11 @@
</v-card> </v-card>
</div> </div>
<div v-for="stat in stats" class="stat" :key="stat._id"> <div
v-for="stat in stats"
:key="stat._id"
class="stat"
>
<attribute-card <attribute-card
v-bind="stat" v-bind="stat"
:data-id="stat._id" :data-id="stat._id"
@@ -31,16 +36,26 @@
/> />
</div> </div>
<div v-for="modifier in modifiers" class="modifier" :key="modifier._id"> <div
<attribute-card modifier v-for="modifier in modifiers"
:key="modifier._id"
class="modifier"
>
<attribute-card
modifier
v-bind="modifier" v-bind="modifier"
:data-id="modifier._id" :data-id="modifier._id"
@click="clickProperty({_id: modifier._id})" @click="clickProperty({_id: modifier._id})"
/> />
</div> </div>
<div v-for="check in checks" class="check" :key="check._id"> <div
<attribute-card modifier v-for="check in checks"
:key="check._id"
class="check"
>
<attribute-card
modifier
v-bind="check" v-bind="check"
:data-id="check._id" :data-id="check._id"
@click="clickProperty({_id: check._id})" @click="clickProperty({_id: check._id})"
@@ -52,11 +67,14 @@
<v-list> <v-list>
<v-subheader>Hit Dice</v-subheader> <v-subheader>Hit Dice</v-subheader>
<template v-for="(hitDie, index) in hitDice"> <template v-for="(hitDie, index) in hitDice">
<v-divider v-if="index !== 0" :key="hitDice._id + 'divider'"/> <v-divider
v-if="index !== 0"
:key="hitDie._id + 'divider'"
/>
<hit-dice-list-tile <hit-dice-list-tile
:key="hitDie._id"
v-bind="hitDie" v-bind="hitDie"
:data-id="hitDie._id" :data-id="hitDie._id"
:key="hitDice._id"
@click="clickProperty({_id: hitDie._id})" @click="clickProperty({_id: hitDie._id})"
@change="e => incrementChange(hitDie._id, e)" @change="e => incrementChange(hitDie._id, e)"
/> />
@@ -65,14 +83,17 @@
</v-card> </v-card>
</div> </div>
<div class="saving-throws" v-show="true"> <div
v-show="true"
class="saving-throws"
>
<v-card> <v-card>
<v-list> <v-list>
<v-subheader>Saving Throws</v-subheader> <v-subheader>Saving Throws</v-subheader>
<skill-list-tile <skill-list-tile
v-for="save in savingThrows" v-for="save in savingThrows"
v-bind="save"
:key="save._id" :key="save._id"
v-bind="save"
:data-id="save._id" :data-id="save._id"
@click="clickProperty({_id: save._id})" @click="clickProperty({_id: save._id})"
/> />
@@ -86,8 +107,8 @@
<v-subheader>Skills</v-subheader> <v-subheader>Skills</v-subheader>
<skill-list-tile <skill-list-tile
v-for="skill in skills" v-for="skill in skills"
v-bind="skill"
:key="skill._id" :key="skill._id"
v-bind="skill"
:data-id="skill._id" :data-id="skill._id"
@click="clickProperty({_id: skill._id})" @click="clickProperty({_id: skill._id})"
/> />
@@ -108,14 +129,17 @@
/> />
</div> </div>
<div class="spell-slots" v-if="spellSlots.length"> <div
v-if="spellSlots.length"
class="spell-slots"
>
<v-card> <v-card>
<v-list> <v-list>
<v-subheader>Spell Slots</v-subheader> <v-subheader>Spell Slots</v-subheader>
<spell-slot-list-tile <spell-slot-list-tile
v-for="spellSlot in spellSlots" v-for="spellSlot in spellSlots"
v-bind="spellSlot"
:key="spellSlot._id" :key="spellSlot._id"
v-bind="spellSlot"
:data-id="spellSlot._id" :data-id="spellSlot._id"
@click="clickProperty({_id: spellSlot._id})" @click="clickProperty({_id: spellSlot._id})"
@change="e => incrementChange(spellSlot._id, e)" @change="e => incrementChange(spellSlot._id, e)"
@@ -123,6 +147,24 @@
</v-list> </v-list>
</v-card> </v-card>
</div> </div>
<div
v-if="actions.length"
class="actions"
>
<v-card>
<v-list>
<v-subheader>Actions</v-subheader>
<action-list-tile
v-for="action in actions"
:key="action._id"
:model="action"
:data-id="action._id"
@click="clickProperty({_id: action._id})"
/>
</v-list>
</v-card>
</div>
</column-layout> </column-layout>
</div> </div>
</template> </template>
@@ -137,8 +179,7 @@
import SkillListTile from '/imports/ui/properties/components/skills/SkillListTile.vue'; import SkillListTile from '/imports/ui/properties/components/skills/SkillListTile.vue';
import ResourceCard from '/imports/ui/properties/components/attributes/ResourceCard.vue'; import ResourceCard from '/imports/ui/properties/components/attributes/ResourceCard.vue';
import SpellSlotListTile from '/imports/ui/properties/components/attributes/SpellSlotListTile.vue'; import SpellSlotListTile from '/imports/ui/properties/components/attributes/SpellSlotListTile.vue';
import ActionListTile from '/imports/ui/properties/components/actions/ActionListTile.vue';
let adjustAttribute = insertAttribute = () => console.error("this shit isn't defined");
const getAttributeOfType = function(charId, type){ const getAttributeOfType = function(charId, type){
return CreatureProperties.find({ return CreatureProperties.find({
@@ -164,9 +205,6 @@
}; };
export default { export default {
props: {
creatureId: String,
},
components: { components: {
AbilityListTile, AbilityListTile,
AttributeCard, AttributeCard,
@@ -176,6 +214,13 @@
SkillListTile, SkillListTile,
ResourceCard, ResourceCard,
SpellSlotListTile, SpellSlotListTile,
ActionListTile,
},
props: {
creatureId: {
type: String,
required: true,
},
}, },
meteor: { meteor: {
abilities(){ abilities(){
@@ -247,6 +292,14 @@
sort: {order: 1}, sort: {order: 1},
}); });
}, },
actions(){
return CreatureProperties.find({
'ancestors.id': this.creatureId,
type: 'action',
}, {
sort: {order: 1},
});
},
}, },
methods: { methods: {
clickProperty({_id}){ clickProperty({_id}){

View File

@@ -0,0 +1,34 @@
<template lang="html">
<v-list-tile
class="ability-list-tile"
v-on="hasClickListener ? {click} : {}"
>
<v-list-tile-content>
{{ model.name }}
</v-list-tile-content>
</v-list-tile>
</template>
<script>
export default {
props: {
model: {
type: Object,
required: true,
}
},
computed: {
hasClickListener(){
return this.$listeners && this.$listeners.click
},
},
methods: {
click(e){
this.$emit('click', e);
},
}
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -1,6 +1,8 @@
<template lang="html"> <template lang="html">
<v-list-tile class="ability-list-tile" v-on="hasClickListener ? {click} : {}"> <v-list-tile
class="ability-list-tile"
v-on="hasClickListener ? {click} : {}"
>
<v-list-tile-action class="mr-4"> <v-list-tile-action class="mr-4">
<div class="display-1 mod"> <div class="display-1 mod">
{{ numberToSignedString(mod) }} {{ numberToSignedString(mod) }}
@@ -15,7 +17,6 @@
{{ name }} {{ name }}
</v-list-tile-title> </v-list-tile-title>
</v-list-tile-content> </v-list-tile-content>
</v-list-tile> </v-list-tile>
</template> </template>
@@ -27,16 +28,16 @@ export default {
mod: Number, mod: Number,
name: String, name: String,
}, },
computed: {
hasClickListener(){
return this.$listeners && this.$listeners.click
},
},
methods: { methods: {
numberToSignedString, numberToSignedString,
click(e){ click(e){
this.$emit('click', e); this.$emit('click', e);
}, },
},
computed: {
hasClickListener(){
return this.$listeners && this.$listeners.click
},
} }
} }
</script> </script>

View File

@@ -100,9 +100,9 @@
:debounce-time="debounceTime" :debounce-time="debounceTime"
@change="(value, ack) => $emit('change', {path: ['description'], value, ack})" @change="(value, ack) => $emit('change', {path: ['description'], value, ack})"
/> />
<form-sections>
<form-section <form-section
name="Advanced" name="Advanced"
standalone
> >
<v-combobox <v-combobox
label="Spell lists" label="Spell lists"
@@ -115,15 +115,27 @@
@change="(value) => $emit('change', {path: ['spellLists'], value})" @change="(value) => $emit('change', {path: ['spellLists'], value})"
/> />
</form-section> </form-section>
<form-section
name="Casting"
>
<action-form
v-bind="$props"
v-on="$listeners"
/>
</form-section>
</form-sections>
</div> </div>
</template> </template>
<script> <script>
import FormSection from '/imports/ui/properties/forms/shared/FormSection.vue'; import FormSection, { FormSections } from '/imports/ui/properties/forms/shared/FormSection.vue';
import ActionForm from '/imports/ui/properties/forms/ActionForm.vue'
export default { export default {
components: { components: {
FormSections,
FormSection, FormSection,
ActionForm,
}, },
props: { props: {
model: { model: {

View File

@@ -68,7 +68,7 @@
} }
], ],
"parserOptions": { "parserOptions": {
"ecmaVersion": 6 "ecmaVersion": 2018
}, },
"env": { "env": {
"es6": true, "es6": true,