Improved ability dialogs
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import Characters from "/imports/api/creature/Creatures.js";
|
||||
import Creatures from "/imports/api/creature/Creatures.js";
|
||||
import Actions from "/imports/api/creature/properties/Actions.js";
|
||||
import Attacks from "/imports/api/creature/properties/Attacks.js";
|
||||
import Attributes from "/imports/api/creature/properties/Attributes.js";
|
||||
@@ -18,10 +18,10 @@ import Proficiencies from "/imports/api/creature/properties/Proficiencies.js";
|
||||
import Containers from "/imports/api/inventory/Containers.js";
|
||||
import Items from "/imports/api/inventory/Items.js";
|
||||
|
||||
Meteor.publish("singleCharacter", function(characterId){
|
||||
Meteor.publish("singleCharacter", function(charId){
|
||||
userId = this.userId;
|
||||
var char = Characters.findOne({
|
||||
_id: characterId,
|
||||
var char = Creatures.findOne({
|
||||
_id: charId,
|
||||
$or: [
|
||||
{readers: userId},
|
||||
{writers: userId},
|
||||
@@ -31,27 +31,26 @@ Meteor.publish("singleCharacter", function(characterId){
|
||||
});
|
||||
if (char){
|
||||
return [
|
||||
Characters.find({_id: characterId}),
|
||||
Creatures.find({_id: charId}),
|
||||
//get all the assets for this character including soft deleted ones
|
||||
Actions.find ({charId: characterId}, {removed: true}),
|
||||
Attacks.find ({charId: characterId}, {removed: true}),
|
||||
Attributes.find ({charId: characterId}, {removed: true}),
|
||||
Buffs.find ({charId: characterId}, {removed: true}),
|
||||
Classes.find ({charId: characterId}, {removed: true}),
|
||||
Conditions.find ({charId: characterId}, {removed: true}),
|
||||
Containers.find ({charId: characterId}, {removed: true}),
|
||||
CustomBuffs.find ({charId: characterId}, {removed: true}),
|
||||
DamageMultipliers.find ({charId: characterId}, {removed: true}),
|
||||
Effects.find ({charId: characterId}, {removed: true}),
|
||||
Experiences.find ({charId: characterId}, {removed: true}),
|
||||
Features.find ({charId: characterId}, {removed: true}),
|
||||
Items.find ({charId: characterId}, {removed: true}),
|
||||
Notes.find ({charId: characterId}, {removed: true}),
|
||||
Skills.find ({charId: characterId}, {removed: true}),
|
||||
Spells.find ({charId: characterId}, {removed: true}),
|
||||
SpellLists.find ({charId: characterId}, {removed: true}),
|
||||
TemporaryHitPoints.find ({charId: characterId}, {removed: true}),
|
||||
Proficiencies.find ({charId: characterId}, {removed: true}),
|
||||
Actions.find ({charId}, {removed: true}),
|
||||
Attacks.find ({charId}, {removed: true}),
|
||||
Attributes.find ({charId}, {removed: true}),
|
||||
Buffs.find ({charId}, {removed: true}),
|
||||
Classes.find ({charId}, {removed: true}),
|
||||
Conditions.find ({charId}, {removed: true}),
|
||||
Containers.find ({charId}, {removed: true}),
|
||||
CustomBuffs.find ({charId}, {removed: true}),
|
||||
DamageMultipliers.find ({charId}, {removed: true}),
|
||||
Effects.find ({charId}, {removed: true}),
|
||||
Experiences.find ({charId}, {removed: true}),
|
||||
Features.find ({charId}, {removed: true}),
|
||||
Items.find ({charId}, {removed: true}),
|
||||
Notes.find ({charId}, {removed: true}),
|
||||
Skills.find ({charId}, {removed: true}),
|
||||
Spells.find ({charId}, {removed: true}),
|
||||
SpellLists.find ({charId}, {removed: true}),
|
||||
Proficiencies.find ({charId}, {removed: true}),
|
||||
];
|
||||
} else {
|
||||
return [];
|
||||
@@ -69,10 +68,10 @@ DDPRateLimiter.addRule({
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.publish("singleCharacterName", function(characterId){
|
||||
Meteor.publish("singleCharacterName", function(charId){
|
||||
userId = this.userId;
|
||||
return Characters.find({
|
||||
_id: characterId,
|
||||
return Creatures.find({
|
||||
_id: charId,
|
||||
$or: [
|
||||
{readers: userId},
|
||||
{writers: userId},
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
components: {
|
||||
StatsTab,
|
||||
},
|
||||
watch: {
|
||||
charId(newValue){
|
||||
console.log(newValue)
|
||||
},
|
||||
},
|
||||
data(){return {
|
||||
theme,
|
||||
}},
|
||||
@@ -48,7 +53,9 @@
|
||||
},
|
||||
meteor: {
|
||||
$subscribe: {
|
||||
'singleCharacter': [this.charId],
|
||||
'singleCharacter'(){
|
||||
return [this.charId];
|
||||
},
|
||||
},
|
||||
character(){
|
||||
return Creatures.findOne(this.charId) || {};
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<health-bar
|
||||
v-for="healthBar in healthBars"
|
||||
:key="healthBar._id"
|
||||
:value="healthBar.value + (healthBar.adjustment || 0)"
|
||||
:maxValue="healthBar.value"
|
||||
v-for="healthBar in healthBars"
|
||||
:key="healthBar._id"
|
||||
:value="healthBar.value + (healthBar.adjustment || 0)"
|
||||
:maxValue="healthBar.value"
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
@@ -22,10 +22,10 @@
|
||||
<template v-for="(ability, index) in abilities">
|
||||
<v-divider v-if="index !== 0"/>
|
||||
<ability-list-tile
|
||||
:key="ability._id"
|
||||
:name="ability.name"
|
||||
:score="ability.value"
|
||||
:modifier="ability.mod"
|
||||
v-bind="ability"
|
||||
:key="ability._id"
|
||||
:id="`${_uid}-${ability._id}`"
|
||||
@click="clickAbility({elementId: `${_uid}-${ability._id}`, abilityId: ability._id})"
|
||||
/>
|
||||
</template>
|
||||
</v-list>
|
||||
@@ -177,6 +177,15 @@
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clickAbility({elementId, abilityId}){
|
||||
this.$store.commit("pushDialogStack", {
|
||||
component: "ability-dialog-container",
|
||||
elementId,
|
||||
data: {_id: abilityId},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,44 +3,54 @@
|
||||
<div slot="toolbar">
|
||||
{{name}}
|
||||
</div>
|
||||
<v-layout align-center>
|
||||
<div class="display-1 modifier">
|
||||
{{numberToSignedString(modifier)}}
|
||||
<v-layout align-center column>
|
||||
<div class="display-3 mod">
|
||||
{{numberToSignedString(mod)}}
|
||||
</div>
|
||||
<div class="title score">
|
||||
{{score}}
|
||||
<div class="display-1 value">
|
||||
{{value}}
|
||||
</div>
|
||||
</v-layout>
|
||||
<div v-if="effects && effects.length">
|
||||
<h6 class="title">Effects</h6>
|
||||
<attribute-effect-list :effects="effects" @click="clickedEffect"/>
|
||||
</div>
|
||||
</dialog-base>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import store from "/imports/ui/vuexStore.js";
|
||||
import DialogBase from "/imports/ui/dialogStack/DialogBase.vue";
|
||||
import AttributeEffectList from '/imports/ui/components/AttributeEffectList.vue';
|
||||
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
name: String,
|
||||
score: Number,
|
||||
modifier: Number,
|
||||
value: Number,
|
||||
mod: Number,
|
||||
effects: Array,
|
||||
},
|
||||
methods: {
|
||||
numberToSignedString,
|
||||
clickedEffect(e){
|
||||
this.$emit('clickedEffect', e);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
DialogBase,
|
||||
AttributeEffectList,
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.score {
|
||||
.value {
|
||||
font-weight: 600;
|
||||
font-size: 24px !important;
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
}
|
||||
.modifier, .score {
|
||||
.mod, .value {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
32
app/imports/ui/components/AbilityDialogContainer.vue
Normal file
32
app/imports/ui/components/AbilityDialogContainer.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<template lang="html">
|
||||
<ability-dialog
|
||||
v-bind="ability"
|
||||
v-on="{clickedEffect}"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AbilityDialog from '/imports/ui/components/AbilityDialog.vue';
|
||||
import Attributes from '/imports/api/creature/properties/Attributes.js';
|
||||
export default {
|
||||
components: {
|
||||
AbilityDialog,
|
||||
},
|
||||
props: {
|
||||
_id: String,
|
||||
},
|
||||
meteor: {
|
||||
ability(){
|
||||
return Attributes.findOne(this._id);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clickedEffect(e){
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
</style>
|
||||
@@ -4,9 +4,9 @@
|
||||
<v-divider v-if="index !== 0"/>
|
||||
<ability-list-tile
|
||||
:key="ability.name"
|
||||
:id="_uid + ability.name"
|
||||
:id="`${_uid}-${ability.name}`"
|
||||
v-bind="ability"
|
||||
@click="click(_uid + ability.name, ability)"
|
||||
@click="click({ability, elementId: `${_uid}-${ability.name}`})"
|
||||
/>
|
||||
</template>
|
||||
</v-list>
|
||||
@@ -21,28 +21,79 @@
|
||||
abilities: [
|
||||
{
|
||||
name: "Strength",
|
||||
score: 8,
|
||||
modifier: -1,
|
||||
value: 8,
|
||||
mod: -1,
|
||||
effects: [
|
||||
{
|
||||
name: "Ghost Touch",
|
||||
operation: "add",
|
||||
value: -2,
|
||||
enabled: true,
|
||||
_id: Random.id(),
|
||||
},{
|
||||
name: "Some Base",
|
||||
operation: "base",
|
||||
value: 15,
|
||||
enabled: true,
|
||||
_id: Random.id(),
|
||||
},{
|
||||
name: "Some Multiply",
|
||||
operation: "mul",
|
||||
value: 1.5,
|
||||
enabled: true,
|
||||
_id: Random.id(),
|
||||
},{
|
||||
name: "Some Min",
|
||||
operation: "min",
|
||||
value: 8,
|
||||
enabled: true,
|
||||
_id: Random.id(),
|
||||
},{
|
||||
name: "Some Advantage",
|
||||
operation: "advantage",
|
||||
value: 1,
|
||||
enabled: true,
|
||||
_id: Random.id(),
|
||||
},{
|
||||
name: "Some Disadvantage",
|
||||
operation: "disadvantage",
|
||||
value: 1,
|
||||
enabled: true,
|
||||
_id: Random.id(),
|
||||
},{
|
||||
name: "Some Passive",
|
||||
operation: "passiveAdd",
|
||||
value: -2,
|
||||
calculation: "3-5",
|
||||
_id: Random.id(),
|
||||
},{
|
||||
name: "Some Conditional",
|
||||
operation: "conditional",
|
||||
calculation: "+8 Only when asleep",
|
||||
enabled: true,
|
||||
_id: Random.id(),
|
||||
},
|
||||
]
|
||||
}, {
|
||||
name: "Dexterity",
|
||||
score: 18,
|
||||
modifier: 4,
|
||||
value: 18,
|
||||
mod: 4,
|
||||
}, {
|
||||
name: "Constitution",
|
||||
score: 12,
|
||||
modifier: 1,
|
||||
value: 12,
|
||||
mod: 1,
|
||||
}, {
|
||||
name: "Intelligence",
|
||||
score: 20,
|
||||
modifier: 5,
|
||||
value: 20,
|
||||
mod: 5,
|
||||
}, {
|
||||
name: "Wisdom",
|
||||
score: 6,
|
||||
modifier: -2,
|
||||
value: 6,
|
||||
mod: -2,
|
||||
}, {
|
||||
name: "Charisma",
|
||||
score: 28,
|
||||
modifier: 9,
|
||||
value: 28,
|
||||
mod: 9,
|
||||
},
|
||||
]
|
||||
}},
|
||||
@@ -50,11 +101,11 @@
|
||||
AbilityListTile,
|
||||
},
|
||||
methods: {
|
||||
click(elementId, data){
|
||||
click({ability, elementId}){
|
||||
store.commit("pushDialogStack", {
|
||||
component: "ability-dialog",
|
||||
elementId,
|
||||
data,
|
||||
data: ability,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
<v-list-tile class="ability-list-tile white" v-on="hasClickListener ? {click} : {}">
|
||||
|
||||
<v-list-tile-action class="mr-4">
|
||||
<div class="display-1 modifier">
|
||||
{{numberToSignedString(modifier)}}
|
||||
<div class="display-1 mod">
|
||||
{{numberToSignedString(mod)}}
|
||||
</div>
|
||||
<div class="title score">
|
||||
{{score}}
|
||||
<div class="title value">
|
||||
{{value}}
|
||||
</div>
|
||||
</v-list-tile-action>
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
|
||||
export default {
|
||||
props: {
|
||||
score: Number,
|
||||
modifier: Number,
|
||||
value: Number,
|
||||
mod: Number,
|
||||
name: String,
|
||||
},
|
||||
methods: {
|
||||
@@ -48,12 +48,12 @@ export default {
|
||||
.ability-list-tile >>> .v-list__tile__action--stack {
|
||||
justify-content: center;
|
||||
}
|
||||
.score {
|
||||
.value {
|
||||
font-weight: 600;
|
||||
font-size: 24px !important;
|
||||
color: rgba(0, 0, 0, 0.54);
|
||||
}
|
||||
.modifier, .score {
|
||||
.mod, .value {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
139
app/imports/ui/components/AttributeEffectList.vue
Normal file
139
app/imports/ui/components/AttributeEffectList.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<template lang="html">
|
||||
<v-list two-line v-if="this.effects && this.effects.length">
|
||||
<v-list-tile
|
||||
v-for="effect in sortedEffects"
|
||||
:class="{effect: true, disabled: !effect.enabled}"
|
||||
:id="`${_uid}-${effect._id}`"
|
||||
:key="effect._id"
|
||||
@click="(e) => click({effect, elementId: `${_uid}-${effect._id}`})"
|
||||
>
|
||||
<v-layout row align-center class="net-effect">
|
||||
<v-icon class="black--text icon">
|
||||
{{getIcon(effect.operation, effect.value)}}
|
||||
</v-icon>
|
||||
<div class="value display-1 pr-2" v-if="showValue(effect.operation)">
|
||||
{{getValue(effect.operation, effect.value)}}
|
||||
</div>
|
||||
<div class="calculation body-2 pr-2" v-else>
|
||||
{{effect.calculation}}
|
||||
</div>
|
||||
</v-layout>
|
||||
<v-list-tile-content>
|
||||
<v-list-tile-title class="name">
|
||||
{{effect.name}}
|
||||
</v-list-tile-title>
|
||||
<v-list-tile-sub-title class="operation">
|
||||
{{getOperation(effect.operation)}}
|
||||
</v-list-tile-sub-title>
|
||||
</v-list-tile-content>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import numberToSignedString from '/imports/ui/utility/numberToSignedString.js';
|
||||
const SORT_INDEX = {
|
||||
"base": 1,
|
||||
"add": 2,
|
||||
"mul": 3,
|
||||
"min": 4,
|
||||
"max": 5,
|
||||
"advantage": 6,
|
||||
"disadvantage": 7,
|
||||
"passiveAdd": 8,
|
||||
"fail": 9,
|
||||
"conditional": 10,
|
||||
};
|
||||
|
||||
export default {
|
||||
props: {
|
||||
effects: Array,
|
||||
},
|
||||
computed: {
|
||||
sortedEffects(){
|
||||
if (!this.effects || !this.effects.length) return [];
|
||||
return [...this.effects].sort(
|
||||
(a, b) => (SORT_INDEX[a.operation] || 99) - (SORT_INDEX[b.operation] || 99)
|
||||
);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
sortedEffects(newValue){
|
||||
console.log(newValue);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
click(event){
|
||||
this.$emit('click', event);
|
||||
},
|
||||
getIcon(op, value){
|
||||
switch(op) {
|
||||
case 'base': return 'forward';
|
||||
case 'add': return value < 0 ? 'remove' : 'add';
|
||||
case 'mul': return 'clear';
|
||||
case 'min': return 'unfold_less';
|
||||
case 'max': return 'unfold_more';
|
||||
case 'advantage': return 'arrow_upward';
|
||||
case 'disadvantage': return 'arrow_downward';
|
||||
case 'passiveAdd': return value < 0 ? 'remove_circle_outline' : 'add_circle_outline';
|
||||
case 'fail': return 'block';
|
||||
case 'conditional': return '*' ;
|
||||
}
|
||||
},
|
||||
getOperation(op, value){
|
||||
switch(op) {
|
||||
case 'base': return 'Base value';
|
||||
case 'add': return 'Add';
|
||||
case 'mul': return 'Multiply';
|
||||
case 'min': return 'Minimum';
|
||||
case 'max': return 'Maximum';
|
||||
case 'advantage': return 'Advantage';
|
||||
case 'disadvantage': return 'Disadvantage';
|
||||
case 'passiveAdd': return 'Passive bonus';
|
||||
case 'fail': return 'Always fail';
|
||||
case 'conditional': return 'Conditional benefit' ;
|
||||
}
|
||||
},
|
||||
showValue(op){
|
||||
switch(op) {
|
||||
case 'base': return true;
|
||||
case 'add': return true;
|
||||
case 'mul': return true;
|
||||
case 'min': return true;
|
||||
case 'max': return true;
|
||||
case 'advantage': return false;
|
||||
case 'disadvantage': return false;
|
||||
case 'passiveAdd': return true;
|
||||
case 'fail': return false;
|
||||
case 'conditional': return false;
|
||||
}
|
||||
},
|
||||
getValue(op, value){
|
||||
switch(op) {
|
||||
case 'base': return value;
|
||||
case 'add': return Math.abs(value);
|
||||
case 'mul': return value;
|
||||
case 'min': return value;
|
||||
case 'max': return value;
|
||||
case 'advantage': return;
|
||||
case 'disadvantage': return;
|
||||
case 'passiveAdd': return Math.abs(value);
|
||||
case 'fail': return;
|
||||
case 'conditional': return;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.icon {
|
||||
min-width: 30px;
|
||||
}
|
||||
.net-effect {
|
||||
flex-grow: 0;
|
||||
}
|
||||
.value, .calculation {
|
||||
min-width: 80px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,7 @@
|
||||
import AbilityDialog from '/imports/ui/components/AbilityDialog.vue';
|
||||
import AbilityDialogContainer from '/imports/ui/components/AbilityDialogContainer.vue';
|
||||
|
||||
export default {
|
||||
AbilityDialog,
|
||||
AbilityDialogContainer,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user