import SimpleSchema from 'simpl-schema'; import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties.js'; import Creatures from '/imports/api/creature/creatures/Creatures.js'; import { damagePropertyWork } from '/imports/api/creature/creatureProperties/methods/damageProperty.js'; import { assertEditPermission } from '/imports/api/creature/creatures/creaturePermissions.js'; import { recomputeCreatureByDoc } from '/imports/api/creature/computation/methods/recomputeCreature.js'; import { doActionWork } from '/imports/api/creature/actions/doAction.js'; import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor.js'; import getAncestorContext from '/imports/api/creature/actions/getAncestorContext.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 = getRootCreatureAncestor(spell); assertEditPermission(creature, this.userId); let target = undefined; if (targetId) { target = Creatures.findOne(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, }); } let actionContext = getAncestorContext(spell); doActionWork({ action: spell, actionContext: {slotLevel, ...actionContext}, creature, targets: target ? [target] : [], method: this, }); // Note this only recomputes the top-level creature, not the nearest one recomputeCreatureByDoc(creature); if (target){ recomputeCreatureByDoc(target); } }, }); export default castSpellWithSlot;