Files
DiceCloud/app/imports/api/creature/properties/Attributes.js
2019-01-30 13:34:45 +02:00

185 lines
4.7 KiB
JavaScript

import {makeChild} from "/imports/api/parenting.js";
import SimpleSchema from 'simpl-schema';
import ColorSchema from "/imports/api/creature/subSchemas/ColorSchema.js";
import { canEditCreature } from '/imports/api/creature/creaturePermission.js';
import { recomputeCreatureById } from '/imports/api/creature/creatureComputation.js'
import pickKeysAsOptional from '/imports/api/pickKeysAsOptional.js';
let Attributes = new Mongo.Collection("attributes");
/*
* Attributes are numbered stats of a character
*/
attributeSchema = new SimpleSchema({
charId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
index: 1,
},
// The nice-to-read name
name: {
type: String,
index: 1,
},
// The technical, lowercase, single-word name used in formulae
variableName: {
type: String,
},
// Attributes need to store their order to keep the sheet consistent
order: {
type: SimpleSchema.Integer,
index: 1,
},
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
"resource", // Rages, sorcery points
"spellSlot", // Level 1, 2, 3... spell slots
"utility", // Aren't displayed, Jump height, Carry capacity
],
index: 1,
},
baseValue: {
type: Number,
optional: true,
},
value: {
type: Number,
defaultValue: 0,
},
mod: {
type: SimpleSchema.Integer,
optional: true,
},
adjustment: {
type: SimpleSchema.Integer,
optional: true,
},
// Can the value be decimal?
decimal: {
type: Boolean,
optional: true,
},
reset: {
type: String,
optional: true,
allowedValues: ["shortRest", "longRest"],
},
// Some things are only reset by half on rest
resetMultiplier: {
type: Number,
optional: true,
},
color: ColorSchema(),
});
Attributes.attachSchema(attributeSchema);
//Attributes.attachBehaviour("softRemovable");
makeChild(Attributes, ["enabled"]); //children of lots of things
let updateAttributeSchema = pickKeysAsOptional(attributeSchema, [
'name',
'variableName',
'type',
'baseValue',
'decimal',
'reset',
'resetMultiplier',
'color',
]);
const updateAttribute = new ValidatedMethod({
name: "Attributes.methods.update",
validate: new SimpleSchema({
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id,
},
update: updateAttributeSchema,
}).validator(),
run({_id, update}) {
let currentAttribute = Attributes.findOne(_id);
if (!currentAttribute){
throw new Meteor.Error("Attributes.methods.update.denied",
`No attributes exist with the id: ${_id}`);
}
let charId = currentAttribute.charId;
if (canEditCreature(charId, this.userId)){
Attributes.update(_id, {$set: update});
recomputeCreatureById(charId);
}
},
});
const adjustAttribute = new ValidatedMethod({
name: "Attributes.methods.adjust",
validate: new SimpleSchema({
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id,
},
increment: {
type: Number,
optional: true
},
set: {
type: Number,
optional: true,
custom() {
if (!this.isSet && !this.field('increment').isSet) {
// either set or increment must exist
return SimpleSchema.ErrorTypes.REQUIRED;
} else if (this.isSet && this.field('increment').isSet){
return 'Can\'t increment and set an attritbute adjustment in one operation';
}
},
},
}).validator(),
run({_id, increment, set}) {
let currentAttribute = Attributes.findOne(_id);
if (!currentAttribute){
throw new Meteor.Error("Attributes.methods.update.denied",
`No attributes exist with the id: ${_id}`);
}
let charId = currentAttribute.charId;
if (canEditCreature(charId, this.userId)){
if (typeof set === 'number'){
let val = 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 = set - val;
// Ajustment can't exceed total value
if (-adjustment > val) adjustment = -val;
// Adjustment must be negative
if (adjustment > 0) adjustment = 0;
Attributes.update(_id, {$set: {adjustment}});
} else if (typeof increment === 'number'){
let remaining = currentAttribute.value + currentAttribute.adjustment;
let adj = currentAttribute.adjustment;
// Can't decrease adjustment below remaining value
if (-increment > remaining) increment = -remaining;
// Can't increase adjustment above zero
if (increment > -adj) increment = -adj;
Attributes.update(_id, {$inc: {adjustment: increment}});
}
}
},
});
export default Attributes;
export { updateAttribute, adjustAttribute };