Added saving throws, messed with data structure a bunch, and updated forms to suit

This commit is contained in:
Stefan Zermatten
2019-09-25 14:38:20 +02:00
parent 4fcae9b3f9
commit 21030d186a
18 changed files with 262 additions and 155 deletions

View File

@@ -13,6 +13,7 @@ import { NoteSchema } from '/imports/api/properties/Notes.js';
import { ProficiencySchema } from '/imports/api/properties/Proficiencies.js';
import { RollSchema } from '/imports/api/properties/Rolls.js';
import { SkillSchema } from '/imports/api/properties/Skills.js';
import { SavingThrowSchema } from '/imports/api/properties/SavingThrows.js';
import { SpellListSchema } from '/imports/api/properties/SpellLists.js';
import { SpellSchema } from '/imports/api/properties/Spells.js';
import { ContainerSchema } from '/imports/api/properties/Containers.js';
@@ -32,6 +33,7 @@ const librarySchemas = {
note: NoteSchema,
proficiency: ProficiencySchema,
roll: RollSchema,
savingThrow: SavingThrowSchema,
skill: SkillSchema,
spellList: SpellListSchema,
spell: SpellSchema,

View File

@@ -1,4 +1,6 @@
import creatureCollections from '/imports/api/creature/creatureCollections.js';
import LibraryNodes from '/imports/api/library/LibraryNodes.js';
let collections = [LibraryNodes];
if (Meteor.isServer) Meteor.startup(() => {
/**
@@ -8,7 +10,7 @@ if (Meteor.isServer) Meteor.startup(() => {
const deleteOldSoftRemovedDocs = function(){
const now = new Date();
const thirtyMinutesAgo = new Date(now.getTime() - 30*60000);
creatureCollections.forEach(collection => {
collections.forEach(collection => {
collection.remove({
removed: true,
removedAt: {$lt: thirtyMinutesAgo} // dates *before* 30 minutes ago

View File

@@ -1,7 +1,5 @@
import SimpleSchema from 'simpl-schema';
import AdjustmentSchema from '/imports/api/properties/subSchemas/AdjustmentSchema.js';
import DamageSchema from '/imports/api/properties/subSchemas/DamageSchema.js';
import { StoredBuffWithIdSchema } from '/imports/api/properties/Buffs.js';
import ResultsSchema from '/imports/api/properties/subSchemas/ResultsSchema.js';
/*
* Actions are things a character can do
@@ -35,8 +33,6 @@ let ActionSchema = new SimpleSchema({
'multipleTargets',
],
},
// Effects can apply to this tag specifically
// Ranged spell attack, Ranged weapon attack, etc.
tags: {
type: Array,
defaultValue: [],
@@ -44,29 +40,9 @@ let ActionSchema = new SimpleSchema({
'tags.$': {
type: String,
},
// Adjustments applied when taking this action
// Ideally, if these adjustments can't be made, the action should be unusable
adjustments: {
type: Array,
defaultValue: [],
},
'adjustments.$': {
type: AdjustmentSchema,
},
damages: {
type: Array,
defaultValue: [],
},
'damages.$': {
type: DamageSchema,
},
// Buffs applied when taking this action
buffs: {
type: Array,
defaultValue: [],
},
'buffs.$': {
type: StoredBuffWithIdSchema,
results: {
type: ResultsSchema,
defaultValue: {},
},
// Calculation of how many times this action can be used
// Only set if this action tracks its own uses, rather than adjusting

View File

@@ -34,11 +34,11 @@ let RollSchema = new SimpleSchema({
'tags.$': {
type: String,
},
results: {
rollResults: {
type: Array,
defaultValue: [],
},
'results.$': {
'rollResults.$': {
type: RollResultsSchema,
},
});

View File

@@ -1,6 +1,5 @@
import SimpleSchema from 'simpl-schema';
import AdjustmentSchema from '/imports/api/properties/subSchemas/AdjustmentSchema.js';
import { StoredBuffWithIdSchema } from '/imports/api/properties/Buffs.js';
import ResultsSchema from '/imports/api/properties/subSchemas/ResultsSchema.js';
// These are the rolls made when saves are called for
// For the saving throw bonus or proficiency, see ./Skills.js
@@ -14,34 +13,14 @@ let SavingThrowSchema = new SimpleSchema ({
type: String,
optional: true,
},
passAdjustments: {
type: Array,
defaultValue: [],
},
'passAdjustments.$': {
type: AdjustmentSchema,
},
passBuffs: {
type: Array,
defaultValue: [],
},
'passBuffs.$': {
type: StoredBuffWithIdSchema,
},
failAdjustments: {
type: Array,
defaultValue: [],
},
'failAdjustments.$': {
type: AdjustmentSchema,
},
failBuffs: {
type: Array,
defaultValue: [],
},
'failBuffs.$': {
type: StoredBuffWithIdSchema,
passResults: {
type: ResultsSchema,
defaultValue: {},
},
failResults: {
type: ResultsSchema,
defaultValue: {},
},
});
export { SavingThrowSchema };

View File

@@ -1,5 +1,5 @@
import { ActionSchema } from '/imports/api/properties/Actions.js';
import { AttackSchema } from 'app/imports/api/properties/Attacks.js';
import { AttackSchema } from '/imports/api/properties/Attacks.js';
import { AttributeSchema } from '/imports/api/properties/Attributes.js';
import { StoredBuffSchema } from '/imports/api/properties/Buffs.js';
import { ClassLevelSchema } from '/imports/api/properties/ClassLevels.js';
@@ -11,7 +11,6 @@ import { FolderSchema } from '/imports/api/properties/Folders.js';
import { NoteSchema } from '/imports/api/properties/Notes.js';
import { ProficiencySchema } from '/imports/api/properties/Proficiencies.js';
import { RollSchema } from '/imports/api/properties/Rolls.js';
import { RollResultSchema } from '/imports/api/properties/RollResult.js';
import { SavingThrowSchema } from '/imports/api/properties/SavingThrows.js';
import { SkillSchema } from '/imports/api/properties/Skills.js';
import { SpellListSchema } from '/imports/api/properties/SpellLists.js';
@@ -33,7 +32,6 @@ const propertySchemas = {
note: NoteSchema,
proficiency: ProficiencySchema,
roll: RollSchema,
rollResult: RollResultSchema,
savingThrow: SavingThrowSchema,
skill: SkillSchema,
spellList: SpellListSchema,

View File

@@ -0,0 +1,36 @@
import SimpleSchema from 'simpl-schema';
import AdjustmentSchema from '/imports/api/properties/subSchemas/AdjustmentSchema.js';
import DamageSchema from '/imports/api/properties/subSchemas/DamageSchema.js';
import { StoredBuffWithIdSchema } from '/imports/api/properties/Buffs.js';
let ResultsSchema = new SimpleSchema({
// Adjustments applied when taking this action
// Ideally, if these adjustments can't be made, the action should be unusable
adjustments: {
type: Array,
defaultValue: [],
},
'adjustments.$': {
type: AdjustmentSchema,
},
// Damage is done to hitpoints or hitpoint-like stats
// has a damage type, can be mitigated by resistances, etc.
damages: {
type: Array,
defaultValue: [],
},
'damages.$': {
type: DamageSchema,
},
// Buffs applied when taking this action
buffs: {
type: Array,
defaultValue: [],
},
'buffs.$': {
type: StoredBuffWithIdSchema,
},
});
export default ResultsSchema;

View File

@@ -1,7 +1,5 @@
import SimpleSchema from 'simpl-schema';
import AdjustmentSchema from '/imports/api/properties/subSchemas/AdjustmentSchema.js';
import DamageSchema from '/imports/api/properties/subSchemas/AdjustmentSchema.js';
import { StoredBuffWithIdSchema } from '/imports/api/properties/Buffs.js';
import ResultsSchema from '/imports/api/properties/subSchemas/ResultsSchema.js';
let RollResultsSchema = new SimpleSchema ({
// Expression of whether or not to apply the roll
@@ -11,26 +9,9 @@ let RollResultsSchema = new SimpleSchema ({
type: String,
optional: true,
},
damages: {
type: Array,
defaultValue: [],
},
'damages.$': {
type: DamageSchema,
},
adjustments: {
type: Array,
defaultValue: [],
},
'adjustments.$': {
type: AdjustmentSchema,
},
buffs: {
type: Array,
defaultValue: [],
},
'buffs.$': {
type: StoredBuffWithIdSchema,
results: {
type: ResultsSchema,
defaultValue: {},
},
});

View File

@@ -51,6 +51,10 @@ const PROPERTIES = Object.freeze({
icon: 'flare',
name: 'Roll'
},
savingThrow: {
icon: 'all_out',
name: 'Saving throw'
},
skill: {
icon: 'check_box',
name: 'Skill'

View File

@@ -35,8 +35,8 @@
:class="selected && 'primary--text'"
/>
<div class="text-no-wrap text-truncate">
{{node && node.order}}
{{node && node.name}}
<!--{{node && node.order}}-->
{{getTitle}}
</div>
</div>
</div>
@@ -67,6 +67,7 @@
**/
import PropertyIcon from '/imports/ui/properties/PropertyIcon.vue';
import { canBeParent } from '/imports/api/parenting/parenting.js';
import PROPERTIES from '/imports/constants/PROPERTIES.js'
export default {
name: 'tree-node',
@@ -107,6 +108,13 @@
},
canExpand(){
return canBeParent(this.node.type);
},
getTitle(){
let node = this.node;
if (!node) return;
if (node.name) return node.name;
let prop = PROPERTIES[this.node.type]
return prop && prop.name;
}
},
methods: {

View File

@@ -1,9 +1,9 @@
<template lang="html">
<div>
<v-container fluid grid-list-lg fill-height>
<v-layout row wrap>
<v-flex v-for="(property, type) in PROPERTIES" :key="type" xs4>
<v-card hover @click="$emit('select', type)">
<v-layout row wrap fill-height>
<v-flex v-for="(property, type) in PROPERTIES" :key="type" sm4 xs6>
<v-card hover @click="$emit('select', type)" style="height: 100%; overflow: hidden;">
<div class="layout row align-center justify-center" style="min-height: 70px;">
<v-icon x-large>{{property.icon}}</v-icon>
</div>

View File

@@ -26,16 +26,13 @@
:debounce-time="debounceTime"
/>
<form-sections>
<form-section name="Damage">
<div class="caption">
Damage to deal when this action is taken
</div>
<damage-list-form
:model="model.damages"
<form-section name="Results">
<results-form
:model="model.results"
:parent-target="model.target"
@change="({path, value, ack}) => $emit('change', {path: ['damages', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['damages', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['damages', ...path], ack})"
@change="({path, value, ack}) => $emit('change', {path: ['results', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['results', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['results', ...path], ack})"
/>
</form-section>
<form-section name="Advanced">
@@ -100,49 +97,19 @@
:debounce-time="debounceTime"
/>
</form-section>
<form-section name="Adjustments">
<div class="caption">
Adjustments can be used to automatically spend resources or gain
resources when taking an action.
</div>
<adjustment-list-form
:model="model.adjustments"
:parent-target="model.target"
@change="({path, value, ack}) => $emit('change', {path: ['adjustments', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['adjustments', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['adjustments', ...path], ack})"
/>
</form-section>
<form-section name="Buffs">
<div class="caption">
Buffs apply temporary effects to characters when taking an action.
</div>
<buff-list-form
:model="model.buffs"
:parent-target="model.target"
:stored="stored"
@change="({path, value, ack}) => $emit('change', {path: ['buffs', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['buffs', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['buffs', ...path], ack})"
/>
</form-section>
</form-sections>
</div>
</template>
<script>
import FormSection, {FormSections} from '/imports/ui/properties/forms/shared/FormSection.vue';
import AdjustmentListForm from '/imports/ui/properties/forms/AdjustmentListForm.vue';
import DamageListForm from '/imports/ui/properties/forms/DamageListForm.vue';
import BuffListForm from '/imports/ui/properties/forms/BuffListForm.vue';
import ResultsForm from '/imports/ui/properties/forms/ResultsForm.vue';
export default {
components: {
FormSection,
FormSections,
AdjustmentListForm,
DamageListForm,
BuffListForm,
ResultsForm,
},
props: {
stored: {

View File

@@ -6,28 +6,30 @@
:key="adjustment._id || i"
>
<v-divider v-if="i !== 0"/>
<adjustment-form
class="mt-4"
:model="adjustment"
:parent-target="parentTarget"
@change="({path, value, ack}) => $emit('change', {path: [i, ...path], value, ack})"
/>
<div>
<div class="layout row align-center">
<div style="flex-grow: 1;">
<adjustment-form
class="mt-4"
:model="adjustment"
:parent-target="parentTarget"
@change="({path, value, ack}) => $emit('change', {path: [i, ...path], value, ack})"
/>
</div>
<v-btn outline icon large class="ma-3" @click="$emit('pull', {path: [i]})">
<v-icon>delete</v-icon>
</v-btn>
</div>
</div>
</v-slide-x-transition>
<div class="layout row justify-end">
<div class="layout row justify-center">
<v-btn
:loading="addAdjustmentLoading"
:disabled="addAdjustmentLoading"
outline
icon
@click="addAdjustment"
>
<v-icon>add</v-icon>
Add Adjustment
</v-btn>
</div>
</div>

View File

@@ -24,15 +24,15 @@
</div>
</div>
</v-slide-x-transition>
<div class="layout row justify-end">
<div class="layout row justify-center">
<v-btn
:loading="addBuffLoading"
:disabled="addBuffLoading"
outline
icon
@click="addBuff"
>
<v-icon>add</v-icon>
Add Buff
</v-btn>
</div>
</div>

View File

@@ -6,28 +6,30 @@
:key="damage._id || i"
>
<v-divider v-if="i !== 0"/>
<damage-form
class="mt-4"
:model="damage"
:parent-target="parentTarget"
@change="({path, value, ack}) => $emit('change', {path: [i, ...path], value, ack})"
/>
<div>
<div class="layout row align-center">
<div style="flex-grow: 1;">
<damage-form
class="mt-4"
:model="damage"
:parent-target="parentTarget"
@change="({path, value, ack}) => $emit('change', {path: [i, ...path], value, ack})"
/>
</div>
<v-btn outline icon large class="ma-3" @click="$emit('pull', {path: [i]})">
<v-icon>delete</v-icon>
</v-btn>
</div>
</div>
</v-slide-x-transition>
<div class="layout row justify-end">
<div class="layout row justify-center">
<v-btn
:loading="addDamageLoading"
:disabled="addDamageLoading"
outline
icon
@click="addDamage"
>
<v-icon>add</v-icon>
Add Damage
</v-btn>
</div>
</div>

View File

@@ -0,0 +1,86 @@
<template lang="html">
<div class="results-form">
<div class="subheading">
Damage
</div>
<damage-list-form
:model="model.damages"
:parent-target="parentTarget"
@change="({path, value, ack}) => $emit('change', {path: ['damages', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['damages', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['damages', ...path], ack})"
/>
<div class="subheading">
Adjustments
</div>
<adjustment-list-form
:model="model.adjustments"
:parent-target="parentTarget"
@change="({path, value, ack}) => $emit('change', {path: ['adjustments', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['adjustments', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['adjustments', ...path], ack})"
/>
<div class="subheading">
Buffs
</div>
<buff-list-form
:model="model.buffs"
:parent-target="parentTarget"
:stored="buffsStored"
@change="({path, value, ack}) => $emit('change', {path: ['buffs', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['buffs', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['buffs', ...path], ack})"
/>
</div>
</template>
<script>
import FormSection, {FormSections} from '/imports/ui/properties/forms/shared/FormSection.vue';
import AdjustmentListForm from '/imports/ui/properties/forms/AdjustmentListForm.vue';
import DamageListForm from '/imports/ui/properties/forms/DamageListForm.vue';
import BuffListForm from '/imports/ui/properties/forms/BuffListForm.vue';
import ResultsSchema from '/imports/api/properties/subSchemas/ResultsSchema.js';
export default {
components: {
FormSection,
FormSections,
AdjustmentListForm,
DamageListForm,
BuffListForm,
},
data(){return {
addDamageLoading: false,
showAddToolbar: false,
}},
props: {
model: {
type: Object,
default: () => (ResultsSchema.clean({})),
},
parentTarget: {
type: String,
},
buffsStored: {
type: Boolean,
},
debounceTime: Number,
},
methods: {
acknowledgeAddDamage(){
this.addDamageLoading = false;
},
addDamage(){
this.addDamageLoading = true;
this.$emit('push', {
path: [],
value: DamageSchema.clean({}),
ack: this.acknowledgeAddDamage,
});
},
},
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -0,0 +1,64 @@
<template lang="html">
<div class="saving-throw-form">
<text-field
label="DC"
:value="model.dc"
@change="(value, ack) => $emit('change', {path: ['dc'], value, ack})"
:error-messages="errors.dc"
:debounce-time="debounceTime"
/>
<text-field
label="Ability"
hint="Which ability the saving throw targets"
:value="model.ability"
@change="(value, ack) => $emit('change', {path: ['ability'], value, ack})"
:error-messages="errors.ability"
:debounce-time="debounceTime"
/>
<form-sections>
<form-section name="Results on successful save">
<results-form
:model="model.passResults"
@change="({path, value, ack}) => $emit('change', {path: ['passResults', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['passResults', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['passResults', ...path], ack})"
/>
</form-section>
<form-section name="Results on failed save">
<results-form
:model="model.failResults"
@change="({path, value, ack}) => $emit('change', {path: ['failResults', ...path], value, ack})"
@push="({path, value, ack}) => $emit('push', {path: ['failResults', ...path], value, ack})"
@pull="({path, ack}) => $emit('pull', {path: ['failResults', ...path], ack})"
/>
</form-section>
</form-sections>
</div>
</template>
<script>
import FormSection, {FormSections} from '/imports/ui/properties/forms/shared/FormSection.vue';
import ResultsForm from '/imports/ui/properties/forms/ResultsForm.vue';
export default {
components: {
FormSection,
FormSections,
ResultsForm,
},
props: {
model: {
type: Object,
default: () => ({}),
},
errors: {
type: Object,
default: () => ({}),
},
debounceTime: Number,
},
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -1,7 +1,6 @@
import ActionForm from '/imports/ui/properties/forms/ActionForm.vue';
import AttackForm from '/imports/ui/properties/forms/AttackForm.vue';
import AttributeForm from '/imports/ui/properties/forms/AttributeForm.vue';
import BuffForm from '/imports/ui/properties/forms/BuffForm.vue';
import ContainerForm from '/imports/ui/properties/forms/ContainerForm.vue';
import ClassLevelForm from '/imports/ui/properties/forms/ClassLevelForm.vue';
import DamageMultiplierForm from '/imports/ui/properties/forms/DamageMultiplierForm.vue';
@@ -13,6 +12,7 @@ import ItemForm from '/imports/ui/properties/forms/ItemForm.vue';
import NoteForm from '/imports/ui/properties/forms/NoteForm.vue';
import ProficiencyForm from '/imports/ui/properties/forms/ProficiencyForm.vue';
import RollForm from '/imports/ui/properties/forms/RollForm.vue';
import SavingThrowForm from '/imports/ui/properties/forms/SavingThrowForm.vue';
import SkillForm from '/imports/ui/properties/forms/SkillForm.vue';
import SpellListForm from '/imports/ui/properties/forms/SpellListForm.vue';
import SpellForm from '/imports/ui/properties/forms/SpellForm.vue';
@@ -21,7 +21,6 @@ export default {
action: ActionForm,
attack: AttackForm,
attribute: AttributeForm,
buff: BuffForm,
container: ContainerForm,
classLevel: ClassLevelForm,
damageMultiplier: DamageMultiplierForm,
@@ -33,6 +32,7 @@ export default {
note: NoteForm,
proficiency: ProficiencyForm,
roll: RollForm,
savingThrow: SavingThrowForm,
skill: SkillForm,
spellList: SpellListForm,
spell: SpellForm,