Added spellcasting to the stats page, click the icon next to a spell slot to cast

This commit is contained in:
Stefan Zermatten
2021-01-19 16:10:34 +02:00
parent 1b3b6362f7
commit a4e6dd1d66
11 changed files with 445 additions and 117 deletions

View File

@@ -22,6 +22,7 @@ import { storedIconsSchema } from '/imports/api/icons/Icons.js';
import { reorderDocs } from '/imports/api/parenting/order.js';
import '/imports/api/creature/actions/doAction.js';
import '/imports/api/creature/actions/castSpellWithSlot.js';
import '/imports/api/creature/creatureProperties/manageEquipment.js';
let CreatureProperties = new Mongo.Collection('creatureProperties');

View File

@@ -0,0 +1,75 @@
import SimpleSchema from 'simpl-schema';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
import CreatureProperties, { getCreature, damagePropertyWork } from '/imports/api/creature/CreatureProperties.js';
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
import { recomputeCreatureByDoc } from '/imports/api/creature/computation/recomputeCreature.js';
import { doActionWork } from '/imports/api/creature/actions/doAction.js';
const castSpellWithSlot = new ValidatedMethod({
name: 'creatureProperties.castSpellWithSlot',
validate: new SimpleSchema({
spellId: SimpleSchema.RegEx.Id,
slotId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
optional: true,
},
targetId: {
type: String,
regEx: SimpleSchema.RegEx.Id,
optional: true,
},
}).validator(),
mixins: [RateLimiterMixin],
rateLimit: {
numRequests: 10,
timeInterval: 5000,
},
run({spellId, slotId, targetId}) {
let spell = CreatureProperties.findOne(spellId);
// Check permissions
let creature = getCreature(spell);
assertEditPermission(creature, this.userId);
let target = undefined;
if (targetId) {
target = getCreature(targetId);
assertEditPermission(target, this.userId);
}
let slotLevel = spell.level || 0;
if (slotLevel !== 0){
let slot = CreatureProperties.findOne(slotId);
if (!slot){
throw new Meteor.Error('No slot',
'Slot not found to cast spell');
}
if (!slot.currentValue){
throw new Meteor.Error('No slot',
'Slot depleted');
}
if (!(slot.spellSlotLevelValue >= spell.level)){
throw new Meteor.Error('Slot too small',
'Slot is not large enough to cast spell');
}
slotLevel = slot.spellSlotLevelValue;
damagePropertyWork({
property: slot,
operation: 'increment',
value: 1,
});
}
doActionWork({
action: spell,
context: {slotLevel},
creature,
target,
});
// Note this only recomputes the top-level creature, not the nearest one
recomputeCreatureByDoc(creature);
if (target){
recomputeCreatureByDoc(target);
}
},
});
export default castSpellWithSlot;

View File

@@ -41,8 +41,7 @@ const doAction = new ValidatedMethod({
},
});
function doActionWork({action, creature, target}){
let actionContext = {};
export function doActionWork({action, creature, target, context = {}}){
let decendantForest = nodesToTree({
collection: CreatureProperties,
ancestorId: action._id,
@@ -53,9 +52,9 @@ function doActionWork({action, creature, target}){
}];
applyProperties({
forest: startingForest,
actionContext: context,
creature,
target,
actionContext
});
}