185 lines
5.4 KiB
JavaScript
185 lines
5.4 KiB
JavaScript
import PropertySchema from '/imports/api/creature/subSchemas/PropertySchema.js';
|
|
import ChildSchema from '/imports/api/parenting/ChildSchema.js';
|
|
import ColorSchema from '/imports/api/creature/subSchemas/ColorSchema.js';
|
|
import SimpleSchema from 'simpl-schema';
|
|
import schema from '/imports/api/schema.js';
|
|
import VARIABLE_NAME_REGEX from '/imports/constants/VARIABLE_NAME_REGEX.js';
|
|
import getModifierFields from '/imports/api/getModifierFields.js';
|
|
|
|
// Mixins
|
|
import recomputeCreatureMixin from '/imports/api/mixins/recomputeCreatureMixin.js';
|
|
import creaturePermissionMixin from '/imports/api/mixins/creaturePermissionMixin.js';
|
|
import { setDocToLastMixin } from '/imports/api/mixins/setDocToLastMixin.js';
|
|
import {
|
|
setDocAncestryMixin,
|
|
ensureAncestryContainsCharIdMixin
|
|
} from '/imports/api/parenting/parenting.js';
|
|
import simpleSchemaMixin from '/imports/api/mixins/simpleSchemaMixin.js';
|
|
import updateSchemaMixin from '/imports/api/mixins/updateSchemaMixin.js';
|
|
import propagateInheritanceUpdateMixin from '/imports/api/mixins/propagateInheritanceUpdateMixin.js';
|
|
|
|
let Attributes = new Mongo.Collection('attributes');
|
|
|
|
/*
|
|
* Attributes are numbered stats of a character
|
|
*/
|
|
let AttributeSchema = schema({
|
|
name: {
|
|
type: String,
|
|
optional: true,
|
|
},
|
|
// The technical, lowercase, single-word name used in formulae
|
|
variableName: {
|
|
type: String,
|
|
regEx: VARIABLE_NAME_REGEX,
|
|
},
|
|
// How it is displayed and computed is determined by type
|
|
type: {
|
|
type: String,
|
|
allowedValues: [
|
|
'ability', //Strength, Dex, Con, etc.
|
|
'stat', // Speed, Armor Class
|
|
'modifier', // Proficiency Bonus, Initiative
|
|
'hitDice', // d12 hit dice
|
|
'healthBar', // Hitpoints, Temporary Hitpoints, can take damage
|
|
'bar', // Displayed as a health bar, can't take damage
|
|
'resource', // Rages, sorcery points
|
|
'spellSlot', // Level 1, 2, 3... spell slots
|
|
'utility', // Aren't displayed, Jump height, Carry capacity
|
|
],
|
|
index: 1,
|
|
},
|
|
// The starting value, before effects
|
|
baseValue: {
|
|
type: Number,
|
|
optional: true,
|
|
},
|
|
// The damage done to the attribute, always negative
|
|
adjustment: {
|
|
type: SimpleSchema.Integer,
|
|
optional: true,
|
|
max: 0,
|
|
},
|
|
// Can the value be decimal?
|
|
decimal: {
|
|
type: Boolean,
|
|
optional: true,
|
|
},
|
|
// Automatically zero the adjustment on these conditions
|
|
reset: {
|
|
type: String,
|
|
optional: true,
|
|
allowedValues: ['shortRest', 'longRest'],
|
|
},
|
|
// Some things are only reset their adjustment by up to half of the value
|
|
resetMultiplier: {
|
|
type: Number,
|
|
optional: true,
|
|
},
|
|
});
|
|
|
|
AttributeSchema.extend(ColorSchema);
|
|
|
|
const ComputedAttributeSchema = schema({
|
|
// The computed value of the attribute
|
|
value: {
|
|
type: Number,
|
|
defaultValue: 0,
|
|
},
|
|
// The computed modifier, provided the attribute type is `ability`
|
|
mod: {
|
|
type: SimpleSchema.Integer,
|
|
optional: true,
|
|
},
|
|
}).extend(AttributeSchema);
|
|
|
|
Attributes.attachSchema(PropertySchema);
|
|
Attributes.attachSchema(ComputedAttributeSchema);
|
|
Attributes.attachSchema(ChildSchema);
|
|
|
|
const insertAttribute = new ValidatedMethod({
|
|
name: 'Attributes.methods.insert',
|
|
mixins: [
|
|
setDocAncestryMixin,
|
|
ensureAncestryContainsCharIdMixin,
|
|
recomputeCreatureMixin,
|
|
creaturePermissionMixin,
|
|
setDocToLastMixin,
|
|
simpleSchemaMixin,
|
|
],
|
|
collection: Attributes,
|
|
permission: 'edit',
|
|
schema: AttributeSchema,
|
|
run(attribute) {
|
|
return Attributes.insert(attribute);
|
|
},
|
|
});
|
|
|
|
const updateAttribute = new ValidatedMethod({
|
|
name: 'Attributes.methods.update',
|
|
mixins: [
|
|
recomputeCreatureMixin,
|
|
propagateInheritanceUpdateMixin,
|
|
updateSchemaMixin,
|
|
creaturePermissionMixin,
|
|
],
|
|
collection: Attributes,
|
|
permission: 'edit',
|
|
schema: AttributeSchema.omit(['adjutment']),
|
|
skipRecompute({update}){
|
|
let fields = getModifierFields(update);
|
|
return !fields.hasAny([
|
|
'variableName',
|
|
'type',
|
|
'baseValue',
|
|
]);
|
|
},
|
|
});
|
|
|
|
const adjustAttribute = new ValidatedMethod({
|
|
name: 'Attributes.methods.adjust',
|
|
mixins: [
|
|
simpleSchemaMixin,
|
|
creaturePermissionMixin,
|
|
],
|
|
collection: Attributes,
|
|
permission: 'edit',
|
|
schema: new SimpleSchema({
|
|
_id: SimpleSchema.RegEx.Id,
|
|
type: {
|
|
type: String,
|
|
allowedValues: ['set', 'increment']
|
|
},
|
|
value: Number,
|
|
}),
|
|
run({_id, type, value}) {
|
|
if (type === 'set'){
|
|
let currentValue = currentAttribute.value;
|
|
// Set represents what we want the value to be after adjustment
|
|
// So we need the actual adjustment to get to that value
|
|
let adjustment = value - currentValue;
|
|
// Ajustment can't exceed total value
|
|
if (-adjustment > currentValue) adjustment = -currentValue;
|
|
// Adjustment must be negative
|
|
if (adjustment > 0) adjustment = 0;
|
|
return Attributes.update(_id, {$set: {adjustment}});
|
|
} else if (type === 'increment'){
|
|
let remaining = currentAttribute.value + (currentAttribute.adjustment || 0);
|
|
let adj = currentAttribute.adjustment;
|
|
// Can't decrease adjustment below remaining value
|
|
let increment = value;
|
|
if (-increment > remaining) increment = -remaining;
|
|
// Can't increase adjustment above zero
|
|
if (increment > -adj) increment = -adj;
|
|
if (typeof currentAttribute.adjustment === 'number'){
|
|
return Attributes.update(_id, {$inc: {adjustment: increment}});
|
|
} else {
|
|
return Attributes.update(_id, {$set: {adjustment: increment}});
|
|
}
|
|
}
|
|
},
|
|
});
|
|
|
|
export default Attributes;
|
|
export { AttributeSchema, insertAttribute, updateAttribute, adjustAttribute };
|