90 lines
2.9 KiB
JavaScript
90 lines
2.9 KiB
JavaScript
import SimpleSchema from 'simpl-schema';
|
|
import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
|
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
|
|
import CreatureProperties, { getCreature, damagePropertyWork, adjustQuantityWork } from '/imports/api/creature/CreatureProperties.js';
|
|
import { assertEditPermission } from '/imports/api/creature/creaturePermissions.js';
|
|
import { recomputeCreatureByDoc } from '/imports/api/creature/computation/recomputeCreature.js';
|
|
|
|
const doAction = new ValidatedMethod({
|
|
name: 'creatureProperties.doAction',
|
|
validate: new SimpleSchema({
|
|
actionId: SimpleSchema.RegEx.Id,
|
|
}).validator(),
|
|
mixins: [RateLimiterMixin],
|
|
rateLimit: {
|
|
numRequests: 10,
|
|
timeInterval: 5000,
|
|
},
|
|
run({actionId}) {
|
|
let action = CreatureProperties.findOne(actionId);
|
|
// Check permissions
|
|
let creature = getCreature(action);
|
|
assertEditPermission(creature, this.userId);
|
|
doActionWork(action);
|
|
// Note this only recomputes the top-level creature, not the nearest one
|
|
recomputeCreatureByDoc(creature);
|
|
},
|
|
});
|
|
|
|
function doActionWork(action){
|
|
spendResources(action);
|
|
}
|
|
|
|
function spendResources(action){
|
|
// Check Uses
|
|
if (action.usesUsed >= action.usesResult){
|
|
throw new Meteor.Error('Insufficient Uses',
|
|
'This action has no uses left');
|
|
}
|
|
// Resources
|
|
if (action.insufficientResources){
|
|
throw new Meteor.Error('Insufficient Resources',
|
|
'This creature doesn\'t have sufficient resources to perform this action');
|
|
}
|
|
// Items
|
|
let itemQuantityAdjustments = [];
|
|
action.resources.itemsConsumed.forEach(itemConsumed => {
|
|
if (!itemConsumed.itemId){
|
|
throw new Meteor.Error('Ammo not selected',
|
|
'No ammo was selected for this action');
|
|
}
|
|
let item = CreatureProperties.findOne(itemConsumed.itemId);
|
|
if (!item || item.ancestors[0].id !== action.ancestors[0].id){
|
|
throw new Meteor.Error('Ammo not found',
|
|
'The action\'s ammo was not found on the creature');
|
|
}
|
|
if (!item.equipped){
|
|
throw new Meteor.Error('Ammo not equipped',
|
|
'The selected ammo is not equipped');
|
|
}
|
|
if (!itemConsumed.quantity) return;
|
|
itemQuantityAdjustments.push({
|
|
property: item,
|
|
operation: 'increment',
|
|
value: itemConsumed.quantity,
|
|
});
|
|
});
|
|
// No more errors should be thrown after this line
|
|
// Now that we have confirmed that there are no errors, do actual work
|
|
//Items
|
|
itemQuantityAdjustments.forEach(adjustQuantityWork);
|
|
// Use uses
|
|
CreatureProperties.update(action._id, {
|
|
$inc: {usesUsed: 1}
|
|
}, {
|
|
selector: action
|
|
});
|
|
// Damage stats
|
|
action.resources.attributesConsumed.forEach(attConsumed => {
|
|
if (!attConsumed.quantity) return;
|
|
let stat = CreatureProperties.findOne(attConsumed.statId);
|
|
damagePropertyWork({
|
|
property: stat,
|
|
operation: 'increment',
|
|
value: attConsumed.quantity,
|
|
});
|
|
});
|
|
}
|
|
|
|
export default doAction;
|