Fixed skill and attribute effect lists

Now using effectId lists
This commit is contained in:
ThaumRystra
2023-11-12 17:38:51 +02:00
parent b32b6db21a
commit 2e3e6e22b6
8 changed files with 94 additions and 88 deletions

View File

@@ -1,21 +1,28 @@
export default function aggregateProficiency({node, linkedNode, link}){ export default function aggregateProficiency({ node, linkedNode, link }) {
if ( if (
link.data !== 'proficiency' && link.data !== 'proficiency' &&
!(link.data === 'definition' && linkedNode.data.type === 'skill') !(link.data === 'definition' && linkedNode.data.type === 'skill')
) return; ) return;
let proficiency; let proficiency;
if (link.data === 'proficiency'){ if (link.data === 'proficiency') {
proficiency = linkedNode.data.value || 0; proficiency = linkedNode.data.value || 0;
} else if (link.data === 'definition' && linkedNode.data.type === 'skill'){ } else if (link.data === 'definition' && linkedNode.data.type === 'skill') {
proficiency = linkedNode.data.baseProficiency || 0; proficiency = linkedNode.data.baseProficiency || 0;
} else { } else {
return; return;
} }
if (proficiency) {
// Store a link to the proficiency
node.data.proficiencyIds = node.data.proficiencyIds || [];
node.data.proficiencyIds.push(linkedNode.data._id);
}
// Store the highest proficiency // Store the highest proficiency
if ( if (
node.data.proficiency === undefined || node.data.proficiency === undefined ||
proficiency > node.data.proficiency proficiency > node.data.proficiency
){ ) {
node.data.proficiency = proficiency; node.data.proficiency = proficiency;
} }
} }

View File

@@ -48,6 +48,7 @@ export default function computeVariableAsAttribute(computation, node, prop) {
prop.baseValue === undefined || prop.baseValue === undefined ||
undefined undefined
// Store effects // Store effects and proficiencies
prop.effectIds = node.data.effectIds; prop.effectIds = node.data.effectIds;
prop.proficiencyIds = node.data.proficiencyIds;
} }

View File

@@ -33,8 +33,9 @@ export default function computeVariableAsSkill(computation, node, prop) {
const aggregator = node.data.effectAggregator; const aggregator = node.data.effectAggregator;
const aggregatorBase = aggregator?.base || 0; const aggregatorBase = aggregator?.base || 0;
// Store effects // Store effects and proficiencies
prop.effectIds = node.data.effectIds; prop.effectIds = node.data.effectIds;
prop.proficiencyIds = node.data.proficiencyIds;
// If there is no aggregator, determine if the prop can hide, then exit // If there is no aggregator, determine if the prop can hide, then exit
if (!aggregator) { if (!aggregator) {

View File

@@ -44,7 +44,7 @@
import getEffectIcon from '/imports/client/ui/utility/getEffectIcon.js'; import getEffectIcon from '/imports/client/ui/utility/getEffectIcon.js';
import Breadcrumbs from '/imports/client/ui/creature/creatureProperties/Breadcrumbs.vue'; import Breadcrumbs from '/imports/client/ui/creature/creatureProperties/Breadcrumbs.vue';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import { isFinite } from 'lodash'; import { isFinite, find } from 'lodash';
export default { export default {
components: { components: {
@@ -56,13 +56,17 @@ export default {
type: Object, type: Object,
required: true, required: true,
}, },
attribute: {
type: Object,
required: true,
},
}, },
computed: { computed: {
hasClickListener(){ hasClickListener(){
return this.$listeners && this.$listeners.click return this.$listeners && this.$listeners.click
}, },
displayedText(){ displayedText(){
if (this.model.operation === 'conditional'){ if (this.operation === 'conditional'){
return this.model.text || this.model.name || this.operation return this.model.text || this.model.name || this.operation
} else { } else {
return this.model.name || this.operation return this.model.name || this.operation
@@ -75,10 +79,16 @@ export default {
}, },
effectIcon(){ effectIcon(){
let value = this.resolvedValue; let value = this.resolvedValue;
return getEffectIcon(this.model.operation, value); return getEffectIcon(this.operation, value);
}, },
operation(){ operation() {
switch(this.model.operation) { if (this.model.type === 'pointBuy' || this.model.type === 'attribute') {
return 'base'
}
return this.model.operation;
},
operationText() {
switch(this.operation) {
case 'base': return 'Base value'; case 'base': return 'Base value';
case 'add': return 'Add'; case 'add': return 'Add';
case 'mul': return 'Multiply'; case 'mul': return 'Multiply';
@@ -93,7 +103,7 @@ export default {
} }
}, },
showValue(){ showValue(){
switch(this.model.operation) { switch(this.operation) {
case 'base': return true; case 'base': return true;
case 'add': return true; case 'add': return true;
case 'mul': return true; case 'mul': return true;
@@ -109,7 +119,12 @@ export default {
}, },
displayedValue(){ displayedValue(){
let value = this.resolvedValue; let value = this.resolvedValue;
switch(this.model.operation) { if (this.model.type === 'pointBuy') {
return find(this.model.values, row => this.attribute.variableName === row.variableName)?.value;
} else if (this.model.type === 'attribute') {
return this.model.baseValue?.value;
}
switch(this.operation) {
case 'base': return value; case 'base': return value;
case 'add': return isFinite(value) ? Math.abs(value) : value; case 'add': return isFinite(value) ? Math.abs(value) : value;
case 'mul': return value; case 'mul': return value;

View File

@@ -44,6 +44,7 @@
import propertyViewerMixin from '/imports/client/ui/properties/viewers/shared/propertyViewerMixin.js'; import propertyViewerMixin from '/imports/client/ui/properties/viewers/shared/propertyViewerMixin.js';
import Breadcrumbs from '/imports/client/ui/creature/creatureProperties/Breadcrumbs.vue'; import Breadcrumbs from '/imports/client/ui/creature/creatureProperties/Breadcrumbs.vue';
import getProficiencyIcon from '/imports/client/ui/utility/getProficiencyIcon.js'; import getProficiencyIcon from '/imports/client/ui/utility/getProficiencyIcon.js';
import numberToSignedString from '/imports/api/utility/numberToSignedString';
export default { export default {
components: { components: {
@@ -54,15 +55,22 @@
hideBreadcrumbs: Boolean, hideBreadcrumbs: Boolean,
proficiencyBonus: { proficiencyBonus: {
type: Number, type: Number,
default: null, default: 0,
}, },
}, },
computed: { computed: {
icon(){ icon(){
return getProficiencyIcon(this.model.value); return getProficiencyIcon(this.proficiency);
},
proficiency() {
switch (this.model.type) {
case 'proficiency': return this.model.value;
case 'skill': return this.model.proficiency;
default: return 0;
}
}, },
proficiencyText(){ proficiencyText(){
switch (this.model.value){ switch (this.proficiency){
case 0.49: return 'Half proficiency bonus rounded down'; case 0.49: return 'Half proficiency bonus rounded down';
case 0.5: return 'Half proficiency bonus rounded up'; case 0.5: return 'Half proficiency bonus rounded up';
case 1: return 'Proficient'; case 1: return 'Proficient';
@@ -71,11 +79,11 @@
} }
}, },
proficiencyValue(){ proficiencyValue(){
if (!this.proficiencyBonus) return; if (!this.proficiencyBonus) return numberToSignedString(0);
if (this.model.value === 0.49){ if (this.proficiency === 0.49){
return Math.floor(0.5 * this.proficiencyBonus); return numberToSignedString(Math.floor(0.5 * this.proficiencyBonus));
} else { } else {
return Math.ceil(this.model.value * this.proficiencyBonus); return numberToSignedString(Math.ceil(this.proficiency * this.proficiencyBonus));
} }
}, },
}, },

View File

@@ -126,6 +126,7 @@
v-for="effect in effects" v-for="effect in effects"
:key="effect._id" :key="effect._id"
:model="effect" :model="effect"
:attribute="model"
:data-id="effect._id" :data-id="effect._id"
:hide-breadcrumbs="effect._id === model._id" :hide-breadcrumbs="effect._id === model._id"
@click="effect._id !== model._id && clickEffect(effect._id)" @click="effect._id !== model._id && clickEffect(effect._id)"
@@ -145,6 +146,7 @@
import getProficiencyIcon from '/imports/client/ui/utility/getProficiencyIcon.js'; import getProficiencyIcon from '/imports/client/ui/utility/getProficiencyIcon.js';
import {snackbar} from '/imports/client/ui/components/snackbars/SnackbarQueue.js'; import {snackbar} from '/imports/client/ui/components/snackbars/SnackbarQueue.js';
import sortEffects from '/imports/client/ui/utility/sortEffects.js'; import sortEffects from '/imports/client/ui/utility/sortEffects.js';
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties';
export default { export default {
components: { components: {
@@ -189,7 +191,9 @@
return getProficiencyIcon(this.model.proficiency); return getProficiencyIcon(this.model.proficiency);
}, },
effects() { effects() {
return sortEffects(this.model.effects); if (!this.model.effectIds) return [];
const effects = CreatureProperties.find({ _id: { $in: this.model.effectIds } }).fetch();
return sortEffects(effects);
}, },
fallbackValue() { fallbackValue() {
return this.model.baseValue?.value ?? this.model.baseValue?.calculation; return this.model.baseValue?.value ?? this.model.baseValue?.calculation;

View File

@@ -76,6 +76,7 @@
v-if="ability" v-if="ability"
:key="ability._id" :key="ability._id"
:model="ability" :model="ability"
:attribute="model"
:data-id="ability._id" :data-id="ability._id"
@click="clickEffect(ability._id)" @click="clickEffect(ability._id)"
/> />
@@ -83,6 +84,7 @@
v-for="effect in effects" v-for="effect in effects"
:key="effect._id" :key="effect._id"
:model="effect" :model="effect"
:attribute="model"
:data-id="effect._id" :data-id="effect._id"
@click="clickEffect(effect._id)" @click="clickEffect(effect._id)"
/> />
@@ -90,7 +92,7 @@
</property-field> </property-field>
</v-row> </v-row>
<v-row <v-row
v-if="baseProficiencies.length || proficiencies.length" v-if="proficiencies.length"
dense dense
> >
<property-field <property-field
@@ -98,15 +100,6 @@
name="Proficiencies" name="Proficiencies"
> >
<v-list style="width: 100%"> <v-list style="width: 100%">
<skill-proficiency
v-for="proficiency in baseProficiencies"
:key="proficiency._id"
:model="proficiency"
:proficiency-bonus="proficiencyBonus"
:hide-breadcrumbs="proficiency._id === model._id"
:data-id="proficiency._id"
@click="clickEffect(proficiency._id)"
/>
<skill-proficiency <skill-proficiency
v-for="proficiency in proficiencies" v-for="proficiency in proficiencies"
:key="proficiency._id" :key="proficiency._id"
@@ -127,7 +120,6 @@ import numberToSignedString from '../../../../api/utility/numberToSignedString.j
import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js';
import AttributeEffect from '/imports/client/ui/properties/components/attributes/AttributeEffect.vue'; import AttributeEffect from '/imports/client/ui/properties/components/attributes/AttributeEffect.vue';
import SkillProficiency from '/imports/client/ui/properties/components/skills/SkillProficiency.vue'; import SkillProficiency from '/imports/client/ui/properties/components/skills/SkillProficiency.vue';
import CreatureVariables from '/imports/api/creature/creatures/CreatureVariables.js';
import getProficiencyIcon from '/imports/client/ui/utility/getProficiencyIcon.js'; import getProficiencyIcon from '/imports/client/ui/utility/getProficiencyIcon.js';
import sortEffects from '/imports/client/ui/utility/sortEffects.js'; import sortEffects from '/imports/client/ui/utility/sortEffects.js';
import PropertyTargetTags from '/imports/client/ui/properties/viewers/shared/PropertyTargetTags.vue'; import PropertyTargetTags from '/imports/client/ui/properties/viewers/shared/PropertyTargetTags.vue';
@@ -179,7 +171,9 @@ export default {
return 10 + this.model.value + this.model.passiveBonus; return 10 + this.model.value + this.model.passiveBonus;
}, },
effects() { effects() {
return sortEffects(this.model.effects); if (!this.model.effectIds) return [];
const effects = CreatureProperties.find({ _id: { $in: this.model.effectIds } }).fetch();
return sortEffects(effects);
}, },
}, },
methods: { methods: {
@@ -194,70 +188,44 @@ export default {
}, },
}, },
meteor: { meteor: {
variables() {
return CreatureVariables.findOne({ _creatureId: this.context.creatureId }) || {};
},
baseProficiencies() {
if (this.context.creatureId) {
let creatureId = this.context.creatureId;
return CreatureProperties.find({
'ancestors.id': creatureId,
type: 'skill',
variableName: this.model.variableName,
removed: { $ne: true },
inactive: { $ne: true },
}).map(prop => ({
_id: prop._id,
name: 'Skill base proficiency',
value: prop.baseProficiency,
stats: [prop.variableName],
ancestors: prop.ancestors,
})).filter(prof => prof.value);
} else {
return [];
}
},
proficiencies() { proficiencies() {
let creatureId = this.context.creatureId; if (!this.model.proficiencyIds) return [];
if (creatureId) { return CreatureProperties.find({
return CreatureProperties.find({ _id: {$in: this.model.proficiencyIds},
'ancestors.id': creatureId, }, {
stats: this.model.variableName, sort: {order: 1}
type: 'proficiency', }).fetch();
removed: { $ne: true },
inactive: { $ne: true },
}).fetch();
} else {
return [];
}
}, },
ability() { ability() {
let creatureId = this.context.creatureId; let creatureId = this.context.creatureId;
let ability = this.model.ability; let ability = this.model.ability;
if (!creatureId || !ability) return; if (!creatureId || !ability) return;
let abilityProp = CreatureProperties.findOne({ let abilityProp = CreatureProperties.findOne({
'ancestors.id': creatureId,
variableName: ability, variableName: ability,
type: 'attribute', type: 'attribute',
removed: { $ne: true }, removed: { $ne: true },
inactive: { $ne: true }, inactive: { $ne: true },
overridden: { $ne: true }, overridden: { $ne: true },
'ancestors.id': creatureId,
}); });
if (!abilityProp) return; if (!abilityProp) return;
return { return {
_id: abilityProp._id, _id: abilityProp._id,
name: abilityProp.name, name: abilityProp.name,
operation: 'add', operation: 'base',
amount: { value: abilityProp.modifier }, amount: { value: abilityProp.modifier },
stats: [this.model.variableName], stats: [this.model.variableName],
ancestors: abilityProp.ancestors, ancestors: abilityProp.ancestors,
} }
}, },
proficiencyBonus() { proficiencyBonus() {
let creatureId = this.context.creatureId; return CreatureProperties.findOne({
if (!creatureId) return; variableName: 'proficiencyBonus',
return this.variables.proficiencyBonus && overridden: { $ne: true },
this.variables.proficiencyBonus.value; removed: { $ne: true },
inactive: { $ne: true },
'ancestors.id': this.context.creatureId,
})?.value;
}, },
}, },
} }

View File

@@ -1,20 +1,22 @@
const INDEX = { const INDEX = {
'base': 1, 'attribute': 1,
'add': 2, 'pointBuy': 2,
'mul': 3, 'base': 3,
'min': 4, 'add': 4,
'max': 5, 'mul': 5,
'advantage': 6, 'min': 6,
'disadvantage': 7, 'max': 7,
'passiveAdd': 8, 'advantage': 8,
'fail': 9, 'disadvantage': 9,
'conditional': 10, 'passiveAdd': 10,
'fail': 11,
'conditional': 12,
}; };
function sortEffects(effects){ function sortEffects(effects) {
if (!effects || !effects.length) return []; if (!effects || !effects.length) return [];
return [...effects].sort( return effects.sort(
(a, b) => (INDEX[a.operation] || 99) - (INDEX[b.operation] || 99) (a, b) => (INDEX[a.operation || a.type] || 99) - (INDEX[b.operation || b.type] || 99)
); );
} }