port spells to api-v3

This commit is contained in:
Matteo Pagliazzi
2016-03-02 13:05:17 +01:00
parent 8920b05f9e
commit 05b6e25c28
2 changed files with 125 additions and 3 deletions

View File

@@ -218,10 +218,10 @@ spells.healer = {
text: t('spellHealerBrightnessText'),
mana: 15,
lvl: 12,
target: 'self',
target: 'tasks',
notes: t('spellHealerBrightnessNotes'),
cast (user) {
_.each(user.tasks, (task) => {
cast (user, tasks) {
_.each(tasks, (task) => {
if (task.type !== 'reward') {
task.value += 4 * (user._statsComputed.int / (user._statsComputed.int + 40));
}

View File

@@ -1,6 +1,15 @@
import { authWithHeaders } from '../../middlewares/api-v3/auth';
import cron from '../../middlewares/api-v3/cron';
import common from '../../../../common';
import {
NotFound,
BadRequest,
} from '../../libs/api-v3/errors';
import * as Tasks from '../../models/task';
import { model as Group } from '../../models/group';
import { model as User } from '../../models/user';
import Q from 'q';
import _ from 'lodash';
let api = {};
@@ -31,4 +40,117 @@ api.getUser = {
},
};
const partyMembersFields = 'profile.name stats achievements items.special';
/**
* @api {post} /user/class/cast/:spell Cast a spell on a target.
* @apiVersion 3.0.0
* @apiName UserCast
* @apiGroup User
*
* @apiParam {string} spellId The spell to cast.
* @apiParam {UUID} targetId Optional query parameter, the id of the target when casting a spell on a party member or a task.
*
* @apiSuccess {Object|Array} mixed Will return the modified targets. For party members only the necessary fields will be populated.
*/
api.castSpell = {
method: 'POST',
middlewares: [authWithHeaders(), cron],
url: '/user/class/cast/:spell',
async handler (req, res) {
let user = res.locals.user;
let spellId = req.params.spellId;
let targetId = req.query.targetId;
// optional because not required by all targetTypes, presence is checked later if necessary
req.checkQuery('targetId', res.t('targetIdUUID')).optional().isUUID();
let reqValidationErrors = req.validationErrors();
if (reqValidationErrors) throw reqValidationErrors;
let klass = common.content.spells.special[spellId] ? 'special' : user.stats.class;
let spell = common.content.spells[klass][spellId];
if (!spell) throw new NotFound(res.t('spellNotFound', {spell: spellId}));
if (spell.mana > user.stats.mp) throw new BadRequest(res.t('notEnoughMana'));
let targetType = spell.target;
if (targetType === 'task') {
if (!targetId) throw new BadRequest(res.t('targetIdUUID'));
// TODO what about challenge tasks? should casting be disabled on them?
let task = await Tasks.Task.findOne({
_id: targetId,
userId: user._id,
}).exec();
if (!task) throw new NotFound(res.t('taskNotFound'));
if (task.challenge.id) throw new BadRequest(res.t('challengeTasksNoCast'));
spell.cast(user, task);
await task.save();
res.respond(200, task);
} else if (targetType === 'self') {
spell.cast(user);
await user.save();
res.respond(200, user);
} else if (targetType === 'tasks') { // new target type when all the user's tasks are necessary
let tasks = await Tasks.Task.find({
userId: user._id,
'challenge.id': {$exists: false}, // exclude challenge tasks
$or: [ // Exclude completed todos
{type: 'todo', completed: false},
{type: {$in: ['habit', 'daily', 'reward']}},
],
}).exec();
spell.cast(user, tasks);
let toSave = tasks.filter(t => t.isModified());
let isUserModified = user.isModified();
toSave.unshift(user.save());
let saved = await Q.all(toSave);
let response = {
tasks: isUserModified ? _.rest(saved) : saved,
};
if (isUserModified) res.user = user;
res.respond(200, response);
} else if (targetType === 'party' || targetType === 'user') {
let party = await Group.getGroup({_id: 'party', user});
// arrays of users when targetType is 'party' otherwise single users
let partyMembers;
if (targetType === 'party') {
if (!party) {
partyMembers = [user]; // Act as solo party
} else {
partyMembers = await User.find({'party._id': party._id}).select(partyMembersFields).exec();
}
spell.cast(user, partyMembers);
await Q.all(partyMembers.map(m => m.save()));
} else {
if (!party && (!targetId || user._id === targetId)) {
partyMembers = user;
} else {
if (!targetId) throw new BadRequest(res.t('targetIdUUID'));
partyMembers = await User.findOne({_id: targetId, 'party._id': party._id}).select(partyMembersFields).exec();
}
if (!partyMembers) throw new NotFound(res.t('userWithIDNotFound', {userId: targetId}));
spell.cast(user, partyMembers);
await partyMembers.save();
}
res.respond(200, partyMembers);
if (party && !spell.silent) {
let message = `\`${user.profile.name} casts ${spell.text()}${targetType === 'user' ? ` on ${partyMembers.profile.name}` : ' for the party'}.\``;
party.sendChat(message);
await party.save();
}
}
},
};
export default api;