mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
wip: split shared ops
This commit is contained in:
@@ -32,7 +32,6 @@
|
||||
"no-octal": 2,
|
||||
"no-process-env": 2,
|
||||
"no-proto": 2,
|
||||
"no-implied-eval": 2,
|
||||
"yoda": 2,
|
||||
"wrap-iife": 2,
|
||||
"radix": 2,
|
||||
@@ -59,7 +58,6 @@
|
||||
"no-path-concat": 2,
|
||||
"arrow-spacing": 2,
|
||||
"constructor-super": 2,
|
||||
"generator-star-spacing": 2,
|
||||
"no-arrow-condition": 2,
|
||||
"no-class-assign": 2,
|
||||
"no-const-assign": 2,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
15
common/script/libs/index.js
Normal file
15
common/script/libs/index.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import uuid from './uuid';
|
||||
import taskDefaults from './taskDefaults';
|
||||
import refPush from './refPush';
|
||||
import splitWhitespace from './splitWhitespace';
|
||||
import planGemLimits from './planGemLimits';
|
||||
import preenTodos from './preenTodos';
|
||||
|
||||
module.exports = {
|
||||
uuid,
|
||||
taskDefaults,
|
||||
refPush,
|
||||
splitWhitespace,
|
||||
planGemLimits,
|
||||
preenTodos,
|
||||
};
|
||||
4
common/script/libs/planGemLimits.js
Normal file
4
common/script/libs/planGemLimits.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
convRate: 20,
|
||||
convCap: 25,
|
||||
};
|
||||
14
common/script/libs/preenTodos.js
Normal file
14
common/script/libs/preenTodos.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
Preen 3-day past-completed To-Dos from Angular & mobile app
|
||||
*/
|
||||
|
||||
module.exports = function(tasks) {
|
||||
return _.filter(tasks, function(t) {
|
||||
return !t.completed || (t.challenge && t.challenge.id) || moment(t.dateCompleted).isAfter(moment().subtract({
|
||||
days: 3
|
||||
}));
|
||||
});
|
||||
};
|
||||
19
common/script/libs/refPush.js
Normal file
19
common/script/libs/refPush.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import _ from 'lodash';
|
||||
import uuid from './uuid';
|
||||
|
||||
/*
|
||||
Reflists are arrays, but stored as objects. Mongoose has a helluvatime working with arrays (the main problem for our
|
||||
syncing issues) - so the goal is to move away from arrays to objects, since mongoose can reference elements by ID
|
||||
no problem. To maintain sorting, we use these helper functions:
|
||||
*/
|
||||
|
||||
module.exports = function(reflist, item, prune) {
|
||||
if (prune == null) {
|
||||
prune = 0;
|
||||
}
|
||||
item.sort = _.isEmpty(reflist) ? 0 : _.max(reflist, 'sort').sort + 1;
|
||||
if (!(item.id && !reflist[item.id])) {
|
||||
item.id = uuid();
|
||||
}
|
||||
return reflist[item.id] = item;
|
||||
};
|
||||
3
common/script/libs/splitWhitespace.js
Normal file
3
common/script/libs/splitWhitespace.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function(s) {
|
||||
return s.split(' ');
|
||||
};
|
||||
71
common/script/libs/taskDefaults.js
Normal file
71
common/script/libs/taskDefaults.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import uuid from './uuid';
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
Even though Mongoose handles task defaults, we want to make sure defaults are set on the client-side before
|
||||
sending up to the server for performance
|
||||
*/
|
||||
|
||||
// TODO revisit
|
||||
|
||||
module.exports = function(task) {
|
||||
var defaults, ref, ref1, ref2;
|
||||
if (task == null) {
|
||||
task = {};
|
||||
}
|
||||
if (!(task.type && ((ref = task.type) === 'habit' || ref === 'daily' || ref === 'todo' || ref === 'reward'))) {
|
||||
task.type = 'habit';
|
||||
}
|
||||
defaults = {
|
||||
id: uuid(),
|
||||
text: task.id != null ? task.id : '',
|
||||
notes: '',
|
||||
priority: 1,
|
||||
challenge: {},
|
||||
attribute: 'str',
|
||||
dateCreated: new Date()
|
||||
};
|
||||
_.defaults(task, defaults);
|
||||
if (task.type === 'habit') {
|
||||
_.defaults(task, {
|
||||
up: true,
|
||||
down: true
|
||||
});
|
||||
}
|
||||
if ((ref1 = task.type) === 'habit' || ref1 === 'daily') {
|
||||
_.defaults(task, {
|
||||
history: []
|
||||
});
|
||||
}
|
||||
if ((ref2 = task.type) === 'daily' || ref2 === 'todo') {
|
||||
_.defaults(task, {
|
||||
completed: false
|
||||
});
|
||||
}
|
||||
if (task.type === 'daily') {
|
||||
_.defaults(task, {
|
||||
streak: 0,
|
||||
repeat: {
|
||||
su: true,
|
||||
m: true,
|
||||
t: true,
|
||||
w: true,
|
||||
th: true,
|
||||
f: true,
|
||||
s: true
|
||||
}
|
||||
}, {
|
||||
startDate: new Date(),
|
||||
everyX: 1,
|
||||
frequency: 'weekly'
|
||||
});
|
||||
}
|
||||
task._id = task.id;
|
||||
if (task.value == null) {
|
||||
task.value = task.type === 'reward' ? 10 : 0;
|
||||
}
|
||||
if (!_.isNumber(task.priority)) {
|
||||
task.priority = 1;
|
||||
}
|
||||
return task;
|
||||
};
|
||||
9
common/script/libs/uuid.js
Normal file
9
common/script/libs/uuid.js
Normal file
@@ -0,0 +1,9 @@
|
||||
// TODO use node-uuid module
|
||||
module.exports = function() {
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
var r, v;
|
||||
r = Math.random() * 16 | 0;
|
||||
v = (c === "x" ? r : r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
};
|
||||
20
common/script/ops/addPushDevice.js
Normal file
20
common/script/ops/addPushDevice.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function(user, req, cb) {
|
||||
var i, item, pd;
|
||||
if (!user.pushDevices) {
|
||||
user.pushDevices = [];
|
||||
}
|
||||
pd = user.pushDevices;
|
||||
item = {
|
||||
regId: req.body.regId,
|
||||
type: req.body.type
|
||||
};
|
||||
i = _.findIndex(pd, {
|
||||
regId: item.regId
|
||||
});
|
||||
if (i === -1) {
|
||||
pd.push(item);
|
||||
}
|
||||
return typeof cb === "function" ? cb(null, user.pushDevices) : void 0;
|
||||
};
|
||||
12
common/script/ops/addTag.js
Normal file
12
common/script/ops/addTag.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import uuid from '../libs/uuid';
|
||||
|
||||
module.exports = function(user, req, cb) {
|
||||
if (user.tags == null) {
|
||||
user.tags = [];
|
||||
}
|
||||
user.tags.push({
|
||||
name: req.body.name,
|
||||
id: req.body.id || api.uuid()
|
||||
});
|
||||
return typeof cb === "function" ? cb(null, user.tags) : void 0;
|
||||
};
|
||||
27
common/script/ops/addTask.js
Normal file
27
common/script/ops/addTask.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import taskDefaults from '../libs/taskDefaults';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function(user, req, cb) {
|
||||
var task;
|
||||
task = api.taskDefaults(req.body);
|
||||
if (user.tasks[task.id] != null) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 409,
|
||||
message: i18n.t('messageDuplicateTaskID', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
user[task.type + "s"].unshift(task);
|
||||
if (user.preferences.newTaskEdit) {
|
||||
task._editing = true;
|
||||
}
|
||||
if (user.preferences.tagsCollapsed) {
|
||||
task._tags = true;
|
||||
}
|
||||
if (!user.preferences.advancedCollapsed) {
|
||||
task._advanced = true;
|
||||
}
|
||||
if (typeof cb === "function") {
|
||||
cb(null, task);
|
||||
}
|
||||
return task;
|
||||
};
|
||||
15
common/script/ops/addWebhook.js
Normal file
15
common/script/ops/addWebhook.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import refPush from '../libs/refPush';
|
||||
|
||||
module.exports = function(user, req, cb) {
|
||||
var wh;
|
||||
wh = user.preferences.webhooks;
|
||||
api.refPush(wh, {
|
||||
url: req.body.url,
|
||||
enabled: req.body.enabled || true,
|
||||
id: req.body.id
|
||||
});
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('preferences.webhooks');
|
||||
}
|
||||
return typeof cb === "function" ? cb(null, user.preferences.webhooks) : void 0;
|
||||
};
|
||||
15
common/script/ops/allocate.js
Normal file
15
common/script/ops/allocate.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
module.exports = function(user, req, cb) {
|
||||
var stat;
|
||||
stat = req.query.stat || 'str';
|
||||
if (user.stats.points > 0) {
|
||||
user.stats[stat]++;
|
||||
user.stats.points--;
|
||||
if (stat === 'int') {
|
||||
user.stats.mp++;
|
||||
}
|
||||
}
|
||||
return typeof cb === "function" ? cb(null, _.pick(user, $w('stats'))) : void 0;
|
||||
};
|
||||
10
common/script/ops/allocateNow.js
Normal file
10
common/script/ops/allocateNow.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function(user, req, cb) {
|
||||
_.times(user.stats.points, user.fns.autoAllocate);
|
||||
user.stats.points = 0;
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('stats');
|
||||
}
|
||||
return typeof cb === "function" ? cb(null, user.stats) : void 0;
|
||||
};
|
||||
13
common/script/ops/blockUser.js
Normal file
13
common/script/ops/blockUser.js
Normal file
@@ -0,0 +1,13 @@
|
||||
module.exports = function(user, req, cb) {
|
||||
var i;
|
||||
i = user.inbox.blocks.indexOf(req.params.uuid);
|
||||
if (~i) {
|
||||
user.inbox.blocks.splice(i, 1);
|
||||
} else {
|
||||
user.inbox.blocks.push(req.params.uuid);
|
||||
}
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('inbox.blocks');
|
||||
}
|
||||
return typeof cb === "function" ? cb(null, user.inbox.blocks) : void 0;
|
||||
};
|
||||
119
common/script/ops/buy.js
Normal file
119
common/script/ops/buy.js
Normal file
@@ -0,0 +1,119 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
import count from '../count';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
module.exports = function(user, req, cb, analytics) {
|
||||
var analyticsData, armoireExp, armoireResp, armoireResult, base, buyResp, drop, eligibleEquipment, item, key, message, name;
|
||||
key = req.params.key;
|
||||
item = key === 'potion' ? content.potion : key === 'armoire' ? content.armoire : content.gear.flat[key];
|
||||
if (!item) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 404,
|
||||
message: "Item '" + key + " not found (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.js)"
|
||||
}) : void 0;
|
||||
}
|
||||
if (user.stats.gp < item.value) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('messageNotEnoughGold', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if ((item.canOwn != null) && !item.canOwn(user)) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 401,
|
||||
message: "You can't buy this item"
|
||||
}) : void 0;
|
||||
}
|
||||
armoireResp = void 0;
|
||||
if (item.key === 'potion') {
|
||||
user.stats.hp += 15;
|
||||
if (user.stats.hp > 50) {
|
||||
user.stats.hp = 50;
|
||||
}
|
||||
} else if (item.key === 'armoire') {
|
||||
armoireResult = user.fns.predictableRandom(user.stats.gp);
|
||||
eligibleEquipment = _.filter(content.gear.flat, (function(i) {
|
||||
return i.klass === 'armoire' && !user.items.gear.owned[i.key];
|
||||
}));
|
||||
if (!_.isEmpty(eligibleEquipment) && (armoireResult < .6 || !user.flags.armoireOpened)) {
|
||||
eligibleEquipment.sort();
|
||||
drop = user.fns.randomVal(eligibleEquipment);
|
||||
user.items.gear.owned[drop.key] = true;
|
||||
user.flags.armoireOpened = true;
|
||||
message = i18n.t('armoireEquipment', {
|
||||
image: '<span class="shop_' + drop.key + ' pull-left"></span>',
|
||||
dropText: drop.text(req.language)
|
||||
}, req.language);
|
||||
if (api.count.remainingGearInSet(user.items.gear.owned, 'armoire') === 0) {
|
||||
user.flags.armoireEmpty = true;
|
||||
}
|
||||
armoireResp = {
|
||||
type: "gear",
|
||||
dropKey: drop.key,
|
||||
dropText: drop.text(req.language)
|
||||
};
|
||||
} else if ((!_.isEmpty(eligibleEquipment) && armoireResult < .8) || armoireResult < .5) {
|
||||
drop = user.fns.randomVal(_.where(content.food, {
|
||||
canDrop: true
|
||||
}));
|
||||
if ((base = user.items.food)[name = drop.key] == null) {
|
||||
base[name] = 0;
|
||||
}
|
||||
user.items.food[drop.key] += 1;
|
||||
message = i18n.t('armoireFood', {
|
||||
image: '<span class="Pet_Food_' + drop.key + ' pull-left"></span>',
|
||||
dropArticle: drop.article,
|
||||
dropText: drop.text(req.language)
|
||||
}, req.language);
|
||||
armoireResp = {
|
||||
type: "food",
|
||||
dropKey: drop.key,
|
||||
dropArticle: drop.article,
|
||||
dropText: drop.text(req.language)
|
||||
};
|
||||
} else {
|
||||
armoireExp = Math.floor(user.fns.predictableRandom(user.stats.exp) * 40 + 10);
|
||||
user.stats.exp += armoireExp;
|
||||
message = i18n.t('armoireExp', req.language);
|
||||
armoireResp = {
|
||||
"type": "experience",
|
||||
"value": armoireExp
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (user.preferences.autoEquip) {
|
||||
user.items.gear.equipped[item.type] = item.key;
|
||||
message = user.fns.handleTwoHanded(item, null, req);
|
||||
}
|
||||
user.items.gear.owned[item.key] = true;
|
||||
if (message == null) {
|
||||
message = i18n.t('messageBought', {
|
||||
itemText: item.text(req.language)
|
||||
}, req.language);
|
||||
}
|
||||
if (item.last) {
|
||||
user.fns.ultimateGear();
|
||||
}
|
||||
}
|
||||
user.stats.gp -= item.value;
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: key,
|
||||
acquireMethod: 'Gold',
|
||||
goldCost: item.value,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics != null) {
|
||||
analytics.track('acquire item', analyticsData);
|
||||
}
|
||||
buyResp = _.pick(user, $w('items achievements stats flags'));
|
||||
if (armoireResp) {
|
||||
buyResp["armoire"] = armoireResp;
|
||||
}
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 200,
|
||||
message: message
|
||||
}, buyResp) : void 0;
|
||||
};
|
||||
43
common/script/ops/buyMysterySet.js
Normal file
43
common/script/ops/buyMysterySet.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import i18n from '../i18n';
|
||||
import content from '../content/index';
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
module.exports = function(user, req, cb, analytics) {
|
||||
var mysterySet, ref;
|
||||
if (!(user.purchased.plan.consecutive.trinkets > 0)) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughHourglasses', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
mysterySet = (ref = content.timeTravelerStore(user.items.gear.owned)) != null ? ref[req.params.key] : void 0;
|
||||
if ((typeof window !== "undefined" && window !== null ? window.confirm : void 0) != null) {
|
||||
if (!window.confirm(i18n.t('hourglassBuyEquipSetConfirm'))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!mysterySet) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 404,
|
||||
message: "Mystery set not found, or set already owned"
|
||||
}) : void 0;
|
||||
}
|
||||
_.each(mysterySet.items, function(i) {
|
||||
var analyticsData;
|
||||
user.items.gear.owned[i.key] = true;
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: i.key,
|
||||
itemType: 'Subscriber Gear',
|
||||
acquireMethod: 'Hourglass',
|
||||
category: 'behavior'
|
||||
};
|
||||
return analytics != null ? analytics.track('acquire item', analyticsData) : void 0;
|
||||
});
|
||||
user.purchased.plan.consecutive.trinkets--;
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 200,
|
||||
message: i18n.t('hourglassPurchaseSet', req.language)
|
||||
}, _.pick(user, $w('items purchased.plan.consecutive'))) : void 0;
|
||||
};
|
||||
49
common/script/ops/buyQuest.js
Normal file
49
common/script/ops/buyQuest.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import i18n from '../i18n';
|
||||
import content from '../content/index';
|
||||
|
||||
module.exports = function(user, req, cb, analytics) {
|
||||
var analyticsData, base, item, key, message, name;
|
||||
key = req.params.key;
|
||||
item = content.quests[key];
|
||||
if (!item) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 404,
|
||||
message: "Quest '" + key + " not found (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.js)"
|
||||
}) : void 0;
|
||||
}
|
||||
if (!(item.category === 'gold' && item.goldValue)) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 404,
|
||||
message: "Quest '" + key + " is not a Gold-purchasable quest (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.js)"
|
||||
}) : void 0;
|
||||
}
|
||||
if (user.stats.gp < item.goldValue) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('messageNotEnoughGold', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
message = i18n.t('messageBought', {
|
||||
itemText: item.text(req.language)
|
||||
}, req.language);
|
||||
if ((base = user.items.quests)[name = item.key] == null) {
|
||||
base[name] = 0;
|
||||
}
|
||||
user.items.quests[item.key] += 1;
|
||||
user.stats.gp -= item.goldValue;
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: item.key,
|
||||
itemType: 'Market',
|
||||
goldCost: item.goldValue,
|
||||
acquireMethod: 'Gold',
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics != null) {
|
||||
analytics.track('acquire item', analyticsData);
|
||||
}
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 200,
|
||||
message: message
|
||||
}, user.items.quests) : void 0;
|
||||
};
|
||||
31
common/script/ops/buySpecialSpell.js
Normal file
31
common/script/ops/buySpecialSpell.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import i18n from '../i18n';
|
||||
import content from '../content/index';
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
module.exports = function(user, req, cb) {
|
||||
var base, item, key, message;
|
||||
key = req.params.key;
|
||||
item = content.special[key];
|
||||
if (user.stats.gp < item.value) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('messageNotEnoughGold', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
user.stats.gp -= item.value;
|
||||
if ((base = user.items.special)[key] == null) {
|
||||
base[key] = 0;
|
||||
}
|
||||
user.items.special[key]++;
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('items.special');
|
||||
}
|
||||
message = i18n.t('messageBought', {
|
||||
itemText: item.text(req.language)
|
||||
}, req.language);
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 200,
|
||||
message: message
|
||||
}, _.pick(user, $w('items stats'))) : void 0;
|
||||
};
|
||||
59
common/script/ops/changeClass.js
Normal file
59
common/script/ops/changeClass.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
import { capByLevel } from '../statHelpers';
|
||||
|
||||
module.exports = function(user, req, cb, analytics) {
|
||||
var analyticsData, klass, ref;
|
||||
klass = (ref = req.query) != null ? ref["class"] : void 0;
|
||||
if (klass === 'warrior' || klass === 'rogue' || klass === 'wizard' || klass === 'healer') {
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
"class": klass,
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: 3,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics != null) {
|
||||
analytics.track('change class', analyticsData);
|
||||
}
|
||||
user.stats["class"] = klass;
|
||||
user.flags.classSelected = true;
|
||||
_.each(["weapon", "armor", "shield", "head"], function(type) {
|
||||
var foundKey;
|
||||
foundKey = false;
|
||||
_.findLast(user.items.gear.owned, function(v, k) {
|
||||
if (~k.indexOf(type + "_" + klass) && v === true) {
|
||||
return foundKey = k;
|
||||
}
|
||||
});
|
||||
user.items.gear.equipped[type] = foundKey ? foundKey : type === "weapon" ? "weapon_" + klass + "_0" : type === "shield" && klass === "rogue" ? "shield_rogue_0" : type + "_base_0";
|
||||
if (type === "weapon" || (type === "shield" && klass === "rogue")) {
|
||||
user.items.gear.owned[type + "_" + klass + "_0"] = true;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
if (user.preferences.disableClasses) {
|
||||
user.preferences.disableClasses = false;
|
||||
user.preferences.autoAllocate = false;
|
||||
} else {
|
||||
if (!(user.balance >= .75)) {
|
||||
return typeof cb === "function" ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
user.balance -= .75;
|
||||
}
|
||||
_.merge(user.stats, {
|
||||
str: 0,
|
||||
con: 0,
|
||||
per: 0,
|
||||
int: 0,
|
||||
points: api.capByLevel(user.stats.lvl)
|
||||
});
|
||||
user.flags.classSelected = false;
|
||||
}
|
||||
return typeof cb === "function" ? cb(null, _.pick(user, $w('stats flags items preferences'))) : void 0;
|
||||
};
|
||||
12
common/script/ops/clearCompleted.js
Normal file
12
common/script/ops/clearCompleted.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function(user, req, cb) {
|
||||
_.remove(user.todos, function(t) {
|
||||
var ref;
|
||||
return t.completed && !((ref = t.challenge) != null ? ref.id : void 0);
|
||||
});
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('todos');
|
||||
}
|
||||
return typeof cb === "function" ? cb(null, user.todos) : void 0;
|
||||
};
|
||||
7
common/script/ops/clearPMs.js
Normal file
7
common/script/ops/clearPMs.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = function(user, req, cb) {
|
||||
user.inbox.messages = {};
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('inbox.messages');
|
||||
}
|
||||
return typeof cb === "function" ? cb(null, user.inbox.messages) : void 0;
|
||||
};
|
||||
7
common/script/ops/deletePM.js
Normal file
7
common/script/ops/deletePM.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = function (user, req, cb) {
|
||||
delete user.inbox.messages[req.params.id];
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('inbox.messages.' + req.params.id);
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user.inbox.messages) : void 0;
|
||||
};
|
||||
26
common/script/ops/deleteTag.js
Normal file
26
common/script/ops/deleteTag.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var i, tag, tid;
|
||||
tid = req.params.id;
|
||||
i = _.findIndex(user.tags, {
|
||||
id: tid
|
||||
});
|
||||
if (!~i) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messageTagNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
tag = user.tags[i];
|
||||
delete user.filters[tag.id];
|
||||
user.tags.splice(i, 1);
|
||||
_.each(user.tasks, function (task) {
|
||||
return delete task.tags[tag.id];
|
||||
});
|
||||
_.each(['habits', 'dailys', 'todos', 'rewards'], function (type) {
|
||||
return typeof user.markModified === 'function' ? user.markModified(type) : void 0;
|
||||
});
|
||||
return typeof cb === 'function' ? cb(null, user.tags) : void 0;
|
||||
};
|
||||
17
common/script/ops/deleteTask.js
Normal file
17
common/script/ops/deleteTask.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var i, ref, task;
|
||||
task = user.tasks[(ref = req.params) !== null ? ref.id : void 0];
|
||||
if (!task) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messageTaskNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
i = user[task.type + 's'].indexOf(task);
|
||||
if (~i) {
|
||||
user[task.type + 's'].splice(i, 1);
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, {}) : void 0;
|
||||
};
|
||||
7
common/script/ops/deleteWebhook.js
Normal file
7
common/script/ops/deleteWebhook.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = function (user, req, cb) {
|
||||
delete user.preferences.webhooks[req.params.id];
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('preferences.webhooks');
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user.preferences.webhooks) : void 0;
|
||||
};
|
||||
13
common/script/ops/disableClasses.js
Normal file
13
common/script/ops/disableClasses.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
import { capByLevel } from '../statHelpers';
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
user.stats['class'] = 'warrior';
|
||||
user.flags.classSelected = true;
|
||||
user.preferences.disableClasses = true;
|
||||
user.preferences.autoAllocate = true;
|
||||
user.stats.str = capByLevel(user.stats.lvl);
|
||||
user.stats.points = 0;
|
||||
return typeof cb === 'function' ? cb(null, _.pick(user, splitWhitespace('stats flags preferences'))) : void 0;
|
||||
};
|
||||
52
common/script/ops/equip.js
Normal file
52
common/script/ops/equip.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var item, key, message, ref, type;
|
||||
ref = [req.params.type || 'equipped', req.params.key], type = ref[0], key = ref[1];
|
||||
switch (type) {
|
||||
case 'mount':
|
||||
if (!user.items.mounts[key]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: ':You do not own this mount.'
|
||||
}) : void 0;
|
||||
}
|
||||
user.items.currentMount = user.items.currentMount === key ? '' : key;
|
||||
break;
|
||||
case 'pet':
|
||||
if (!user.items.pets[key]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: ':You do not own this pet.'
|
||||
}) : void 0;
|
||||
}
|
||||
user.items.currentPet = user.items.currentPet === key ? '' : key;
|
||||
break;
|
||||
case 'costume':
|
||||
case 'equipped':
|
||||
item = content.gear.flat[key];
|
||||
if (!user.items.gear.owned[key]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: ':You do not own this gear.'
|
||||
}) : void 0;
|
||||
}
|
||||
if (user.items.gear[type][item.type] === key) {
|
||||
user.items.gear[type][item.type] = item.type + '_base_0';
|
||||
message = i18n.t('messageUnEquipped', {
|
||||
itemText: item.text(req.language)
|
||||
}, req.language);
|
||||
} else {
|
||||
user.items.gear[type][item.type] = item.key;
|
||||
message = user.fns.handleTwoHanded(item, type, req);
|
||||
}
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('items.gear.' + type);
|
||||
}
|
||||
}
|
||||
return typeof cb === 'function' ? cb((message ? {
|
||||
code: 200,
|
||||
message: message
|
||||
} : null), user.items) : void 0;
|
||||
};
|
||||
78
common/script/ops/feed.js
Normal file
78
common/script/ops/feed.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var egg, eggText, evolve, food, message, pet, petDisplayName, potion, potionText, ref, ref1, ref2, userPets;
|
||||
ref = req.params, pet = ref.pet, food = ref.food;
|
||||
food = content.food[food];
|
||||
ref1 = pet.split('-'), egg = ref1[0], potion = ref1[1];
|
||||
userPets = user.items.pets;
|
||||
potionText = content.hatchingPotions[potion] ? content.hatchingPotions[potion].text() : potion;
|
||||
eggText = content.eggs[egg] ? content.eggs[egg].text() : egg;
|
||||
petDisplayName = i18n.t('petName', {
|
||||
potion: potionText,
|
||||
egg: eggText
|
||||
});
|
||||
if (!userPets[pet]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messagePetNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (!((ref2 = user.items.food) !== null ? ref2[food.key] : void 0)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messageFoodNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (content.specialPets[pet]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('messageCannotFeedPet', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (user.items.mounts[pet]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('messageAlreadyMount', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
message = '';
|
||||
evolve = function () {
|
||||
userPets[pet] = -1;
|
||||
user.items.mounts[pet] = true;
|
||||
if (pet === user.items.currentPet) {
|
||||
user.items.currentPet = '';
|
||||
}
|
||||
return message = i18n.t('messageEvolve', {
|
||||
egg: petDisplayName
|
||||
}, req.language);
|
||||
};
|
||||
if (food.key === 'Saddle') {
|
||||
evolve();
|
||||
} else {
|
||||
if (food.target === potion || content.hatchingPotions[potion].premium) {
|
||||
userPets[pet] += 5;
|
||||
message = i18n.t('messageLikesFood', {
|
||||
egg: petDisplayName,
|
||||
foodText: food.text(req.language)
|
||||
}, req.language);
|
||||
} else {
|
||||
userPets[pet] += 2;
|
||||
message = i18n.t('messageDontEnjoyFood', {
|
||||
egg: petDisplayName,
|
||||
foodText: food.text(req.language)
|
||||
}, req.language);
|
||||
}
|
||||
if (userPets[pet] >= 50 && !user.items.mounts[pet]) {
|
||||
evolve();
|
||||
}
|
||||
}
|
||||
user.items.food[food.key]--;
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 200,
|
||||
message: message
|
||||
}, {
|
||||
value: userPets[pet]
|
||||
}) : void 0;
|
||||
};
|
||||
17
common/script/ops/getTag.js
Normal file
17
common/script/ops/getTag.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import _ from 'lodash';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var i, tid;
|
||||
tid = req.params.id;
|
||||
i = _.findIndex(user.tags, {
|
||||
id: tid
|
||||
});
|
||||
if (!~i) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messageTagNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user.tags[i]) : void 0;
|
||||
};
|
||||
3
common/script/ops/getTags.js
Normal file
3
common/script/ops/getTags.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function (user, req, cb) {
|
||||
return typeof cb === 'function' ? cb(null, user.tags) : void 0;
|
||||
};
|
||||
39
common/script/ops/hatch.js
Normal file
39
common/script/ops/hatch.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var egg, hatchingPotion, pet, ref;
|
||||
ref = req.params, egg = ref.egg, hatchingPotion = ref.hatchingPotion;
|
||||
if (!(egg && hatchingPotion)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 400,
|
||||
message: 'Please specify query.egg & query.hatchingPotion'
|
||||
}) : void 0;
|
||||
}
|
||||
if (!(user.items.eggs[egg] > 0 && user.items.hatchingPotions[hatchingPotion] > 0)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t('messageMissingEggPotion', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (content.hatchingPotions[hatchingPotion].premium && !content.dropEggs[egg]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t('messageInvalidEggPotionCombo', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
pet = egg + '-' + hatchingPotion;
|
||||
if (user.items.pets[pet] && user.items.pets[pet] > 0) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t('messageAlreadyPet', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
user.items.pets[pet] = 5;
|
||||
user.items.eggs[egg]--;
|
||||
user.items.hatchingPotions[hatchingPotion]--;
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 200,
|
||||
message: i18n.t('messageHatched', req.language)
|
||||
}, user.items) : void 0;
|
||||
};
|
||||
54
common/script/ops/hourglassPurchase.js
Normal file
54
common/script/ops/hourglassPurchase.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData, key, ref, type;
|
||||
ref = req.params, type = ref.type, key = ref.key;
|
||||
if (!content.timeTravelStable[type]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t('typeNotAllowedHourglass', req.language) + JSON.stringify(_.keys(content.timeTravelStable))
|
||||
}) : void 0;
|
||||
}
|
||||
if (!_.contains(_.keys(content.timeTravelStable[type]), key)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t(type + 'NotAllowedHourglass', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (user.items[type][key]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t(type + 'AlreadyOwned', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (!(user.purchased.plan.consecutive.trinkets > 0)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t('notEnoughHourglasses', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
user.purchased.plan.consecutive.trinkets--;
|
||||
if (type === 'pets') {
|
||||
user.items.pets[key] = 5;
|
||||
}
|
||||
if (type === 'mounts') {
|
||||
user.items.mounts[key] = true;
|
||||
}
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: key,
|
||||
itemType: type,
|
||||
acquireMethod: 'Hourglass',
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics) {
|
||||
analytics.track('acquire item', analyticsData);
|
||||
}
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 200,
|
||||
message: i18n.t('hourglassPurchase', req.language)
|
||||
}, _.pick(user, splitWhitespace('items purchased.plan.consecutive'))) : void 0;
|
||||
};
|
||||
@@ -1,5 +1,93 @@
|
||||
import update from './update';
|
||||
import sleep from './sleep';
|
||||
import revive from './revive';
|
||||
import reset from './reset';
|
||||
import reroll from './reroll';
|
||||
import rebirth from './rebirth';
|
||||
import allocateNow from './allocateNow';
|
||||
import clearCompleted from './clearCompleted';
|
||||
import sortTask from './sortTask';
|
||||
import updateTask from './updateTask';
|
||||
import deleteTask from './deleteTask';
|
||||
import addTask from './addTask';
|
||||
import addTag from './addTag';
|
||||
import sortTag from './sortTag';
|
||||
import getTags from './getTags';
|
||||
import getTag from './getTag';
|
||||
import updateTag from './updateTag';
|
||||
import deleteTag from './deleteTag';
|
||||
import addWebhook from './addWebhook';
|
||||
import updateWebhook from './updateWebhook';
|
||||
import deleteWebhook from './deleteWebhook';
|
||||
import addPushDevice from './addPushDevice';
|
||||
import clearPMs from './clearPMs';
|
||||
import deletePM from './deletePM';
|
||||
import blockUser from './blockUser';
|
||||
import feed from './feed';
|
||||
import buySpecialSpell from './buySpecialSpell';
|
||||
import purchase from './purchase';
|
||||
import releasePets from './releasePets';
|
||||
import releaseMounts from './releaseMounts';
|
||||
import releaseBoth from './releaseBoth';
|
||||
import buy from './buy';
|
||||
import buyQuest from './buyQuest';
|
||||
import buyMysterySet from './buyMysterySet';
|
||||
import hourglassPurchase from './hourglassPurchase';
|
||||
import sell from './sell';
|
||||
import equip from './equip';
|
||||
import hatch from './hatch';
|
||||
import unlock from './unlock';
|
||||
import changeClass from './changeClass';
|
||||
import disableClasses from './disableClasses';
|
||||
import allocate from './allocate';
|
||||
import readCard from './readCard';
|
||||
import openMysteryItem from './openMysteryItem';
|
||||
import score from './score';
|
||||
|
||||
module.exports = {
|
||||
update,
|
||||
sleep,
|
||||
revive,
|
||||
reset,
|
||||
reroll,
|
||||
rebirth,
|
||||
allocateNow,
|
||||
clearCompleted,
|
||||
sortTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
addTask,
|
||||
addTag,
|
||||
sortTag,
|
||||
getTags,
|
||||
getTag,
|
||||
updateTag,
|
||||
deleteTag,
|
||||
addWebhook,
|
||||
updateWebhook,
|
||||
deleteWebhook,
|
||||
addPushDevice,
|
||||
clearPMs,
|
||||
deletePM,
|
||||
blockUser,
|
||||
feed,
|
||||
buySpecialSpell,
|
||||
purchase,
|
||||
releasePets,
|
||||
releaseMounts,
|
||||
releaseBoth,
|
||||
buy,
|
||||
buyQuest,
|
||||
buyMysterySet,
|
||||
hourglassPurchase,
|
||||
sell,
|
||||
equip,
|
||||
hatch,
|
||||
unlock,
|
||||
changeClass,
|
||||
disableClasses,
|
||||
allocate,
|
||||
readCard,
|
||||
openMysteryItem,
|
||||
score,
|
||||
};
|
||||
|
||||
32
common/script/ops/openMysteryItem.js
Normal file
32
common/script/ops/openMysteryItem.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import content from '../content/index';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData, item, ref, ref1;
|
||||
item = (ref = user.purchased.plan) !== null ? (ref1 = ref.mysteryItems) !== null ? ref1.shift() : void 0 : void 0;
|
||||
if (!item) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 400,
|
||||
message: 'Empty'
|
||||
}) : void 0;
|
||||
}
|
||||
item = content.gear.flat[item];
|
||||
user.items.gear.owned[item.key] = true;
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('purchased.plan.mysteryItems');
|
||||
}
|
||||
item.notificationType = 'Mystery';
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: item,
|
||||
itemType: 'Subscriber Gear',
|
||||
acquireMethod: 'Subscriber',
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics !== null) {
|
||||
analytics.track('open mystery item', analyticsData);
|
||||
}
|
||||
if (typeof window !== 'undefined') {
|
||||
(user._tmp !== null ? user._tmp : user._tmp = {}).drop = item;
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user.items.gear.owned) : void 0;
|
||||
};
|
||||
107
common/script/ops/purchase.js
Normal file
107
common/script/ops/purchase.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
import planGemLimits from '../libs/planGemLimits';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData, convCap, convRate, item, key, price, ref, ref1, ref2, ref3, type;
|
||||
ref = req.params, type = ref.type, key = ref.key;
|
||||
if (type === 'gems' && key === 'gem') {
|
||||
ref1 = planGemLimits, convRate = ref1.convRate, convCap = ref1.convCap;
|
||||
convCap += user.purchased.plan.consecutive.gemCapExtra;
|
||||
if (!((ref2 = user.purchased) !== null ? (ref3 = ref2.plan) !== null ? ref3.customerId : void 0 : void 0)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: 'Must subscribe to purchase gems with GP'
|
||||
}, req) : void 0;
|
||||
}
|
||||
if (!(user.stats.gp >= convRate)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: 'Not enough Gold'
|
||||
}) : void 0;
|
||||
}
|
||||
if (user.purchased.plan.gemsBought >= convCap) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: 'You\'ve reached the Gold=>Gem conversion cap (' + convCap + ') for this month. We have this to prevent abuse / farming. The cap will reset within the first three days of next month.'
|
||||
}) : void 0;
|
||||
}
|
||||
user.balance += .25;
|
||||
user.purchased.plan.gemsBought++;
|
||||
user.stats.gp -= convRate;
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: key,
|
||||
acquireMethod: 'Gold',
|
||||
goldCost: convRate,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics !== null) {
|
||||
analytics.track('purchase gems', analyticsData);
|
||||
}
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 200,
|
||||
message: '+1 Gem'
|
||||
}, _.pick(user, splitWhitespace('stats balance'))) : void 0;
|
||||
}
|
||||
if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food' && type !== 'quests' && type !== 'gear') {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: ':type must be in [eggs,hatchingPotions,food,quests,gear]'
|
||||
}, req) : void 0;
|
||||
}
|
||||
if (type === 'gear') {
|
||||
item = content.gear.flat[key];
|
||||
if (user.items.gear.owned[key]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('alreadyHave', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
price = (item.twoHanded || item.gearSet === 'animal' ? 2 : 1) / 4;
|
||||
} else {
|
||||
item = content[type][key];
|
||||
price = item.value / 4;
|
||||
}
|
||||
if (!item) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: ':key not found for Content.' + type
|
||||
}, req) : void 0;
|
||||
}
|
||||
if (!item.canBuy(user)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t('messageNotAvailable', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if ((user.balance < price) || !user.balance) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 403,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
user.balance -= price;
|
||||
if (type === 'gear') {
|
||||
user.items.gear.owned[key] = true;
|
||||
} else {
|
||||
if (!(user.items[type][key] > 0)) {
|
||||
user.items[type][key] = 0;
|
||||
}
|
||||
user.items[type][key]++;
|
||||
}
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: key,
|
||||
itemType: 'Market',
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: item.value,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics !== null) {
|
||||
analytics.track('acquire item', analyticsData);
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, _.pick(user, splitWhitespace('items balance'))) : void 0;
|
||||
};
|
||||
100
common/script/ops/rebirth.js
Normal file
100
common/script/ops/rebirth.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
import { capByLevel } from '../statHelpers';
|
||||
import { MAX_LEVEL } from '../constants';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData, flags, gear, lvl, stats;
|
||||
if (user.balance < 2 && user.stats.lvl < MAX_LEVEL) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (user.stats.lvl < MAX_LEVEL) {
|
||||
user.balance -= 2;
|
||||
analyticsData.acquireMethod = 'Gems';
|
||||
analyticsData.gemCost = 8;
|
||||
} else {
|
||||
analyticsData.gemCost = 0;
|
||||
analyticsData.acquireMethod = '> 100';
|
||||
}
|
||||
if (analytics !== null) {
|
||||
analytics.track('Rebirth', analyticsData);
|
||||
}
|
||||
lvl = capByLevel(user.stats.lvl);
|
||||
_.each(user.tasks, function (task) {
|
||||
if (task.type !== 'reward') {
|
||||
task.value = 0;
|
||||
}
|
||||
if (task.type === 'daily') {
|
||||
return task.streak = 0;
|
||||
}
|
||||
});
|
||||
stats = user.stats;
|
||||
stats.buffs = {};
|
||||
stats.hp = 50;
|
||||
stats.lvl = 1;
|
||||
stats['class'] = 'warrior';
|
||||
_.each(['per', 'int', 'con', 'str', 'points', 'gp', 'exp', 'mp'], function (value) {
|
||||
return stats[value] = 0;
|
||||
});
|
||||
// TODO during refactoring: move all gear code from rebirth() to its own function and then call it in reset() as well
|
||||
gear = user.items.gear;
|
||||
_.each(['equipped', 'costume'], function (type) {
|
||||
gear[type] = {};
|
||||
gear[type].armor = 'armor_base_0';
|
||||
gear[type].weapon = 'weapon_warrior_0';
|
||||
gear[type].head = 'head_base_0';
|
||||
return gear[type].shield = 'shield_base_0';
|
||||
});
|
||||
if (user.items.currentPet) {
|
||||
user.ops.equip({
|
||||
params: {
|
||||
type: 'pet',
|
||||
key: user.items.currentPet
|
||||
}
|
||||
});
|
||||
}
|
||||
if (user.items.currentMount) {
|
||||
user.ops.equip({
|
||||
params: {
|
||||
type: 'mount',
|
||||
key: user.items.currentMount
|
||||
}
|
||||
});
|
||||
}
|
||||
_.each(gear.owned, function (v, k) {
|
||||
if (gear.owned[k] && content.gear.flat[k].value) {
|
||||
gear.owned[k] = false;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
gear.owned.weapon_warrior_0 = true;
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('items.gear.owned');
|
||||
}
|
||||
user.preferences.costume = false;
|
||||
flags = user.flags;
|
||||
if (!user.achievements.beastMaster) {
|
||||
flags.rebirthEnabled = false;
|
||||
}
|
||||
flags.itemsEnabled = false;
|
||||
flags.dropsEnabled = false;
|
||||
flags.classSelected = false;
|
||||
flags.levelDrops = {};
|
||||
if (!user.achievements.rebirths) {
|
||||
user.achievements.rebirths = 1;
|
||||
user.achievements.rebirthLevel = lvl;
|
||||
} else if (lvl > user.achievements.rebirthLevel || lvl === 100) {
|
||||
user.achievements.rebirths++;
|
||||
user.achievements.rebirthLevel = lvl;
|
||||
}
|
||||
user.stats.buffs = {};
|
||||
return typeof cb === 'function' ? cb(null, user) : void 0;
|
||||
};
|
||||
50
common/script/ops/releaseBoth.js
Normal file
50
common/script/ops/releaseBoth.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData, animal, giveTriadBingo;
|
||||
if (user.balance < 1.5 && !user.achievements.triadBingo) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
} else {
|
||||
giveTriadBingo = true;
|
||||
if (!user.achievements.triadBingo) {
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: 6,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (typeof analytics !== 'undefined' && analytics !== null) {
|
||||
analytics.track('release pets & mounts', analyticsData);
|
||||
}
|
||||
user.balance -= 1.5;
|
||||
}
|
||||
user.items.currentMount = '';
|
||||
user.items.currentPet = '';
|
||||
for (animal in content.pets) {
|
||||
if (user.items.pets[animal] === -1) {
|
||||
giveTriadBingo = false;
|
||||
}
|
||||
user.items.pets[animal] = 0;
|
||||
user.items.mounts[animal] = null;
|
||||
}
|
||||
if (!user.achievements.beastMasterCount) {
|
||||
user.achievements.beastMasterCount = 0;
|
||||
}
|
||||
user.achievements.beastMasterCount++;
|
||||
if (!user.achievements.mountMasterCount) {
|
||||
user.achievements.mountMasterCount = 0;
|
||||
}
|
||||
user.achievements.mountMasterCount++;
|
||||
if (giveTriadBingo) {
|
||||
if (!user.achievements.triadBingoCount) {
|
||||
user.achievements.triadBingoCount = 0;
|
||||
}
|
||||
user.achievements.triadBingoCount++;
|
||||
}
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user) : void 0;
|
||||
};
|
||||
32
common/script/ops/releaseMounts.js
Normal file
32
common/script/ops/releaseMounts.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData, mount;
|
||||
if (user.balance < 1) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
} else {
|
||||
user.balance -= 1;
|
||||
user.items.currentMount = '';
|
||||
for (mount in content.pets) {
|
||||
user.items.mounts[mount] = null;
|
||||
}
|
||||
if (!user.achievements.mountMasterCount) {
|
||||
user.achievements.mountMasterCount = 0;
|
||||
}
|
||||
user.achievements.mountMasterCount++;
|
||||
}
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: 4,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics !== null) {
|
||||
analytics.track('release mounts', analyticsData);
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user) : void 0;
|
||||
};
|
||||
32
common/script/ops/releasePets.js
Normal file
32
common/script/ops/releasePets.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData, pet;
|
||||
if (user.balance < 1) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
} else {
|
||||
user.balance -= 1;
|
||||
for (pet in content.pets) {
|
||||
user.items.pets[pet] = 0;
|
||||
}
|
||||
if (!user.achievements.beastMasterCount) {
|
||||
user.achievements.beastMasterCount = 0;
|
||||
}
|
||||
user.achievements.beastMasterCount++;
|
||||
user.items.currentPet = '';
|
||||
}
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: 4,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics !== null) {
|
||||
analytics.track('release pets', analyticsData);
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user) : void 0;
|
||||
};
|
||||
29
common/script/ops/reroll.js
Normal file
29
common/script/ops/reroll.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData;
|
||||
if (user.balance < 1) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
user.balance--;
|
||||
_.each(user.tasks, function (task) {
|
||||
if (task.type !== 'reward') {
|
||||
return task.value = 0;
|
||||
}
|
||||
});
|
||||
user.stats.hp = 50;
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: 4,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics !== null) {
|
||||
analytics.track('Fortify Potion', analyticsData);
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user) : void 0;
|
||||
};
|
||||
35
common/script/ops/reset.js
Normal file
35
common/script/ops/reset.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var gear;
|
||||
user.habits = [];
|
||||
user.dailys = [];
|
||||
user.todos = [];
|
||||
user.rewards = [];
|
||||
user.stats.hp = 50;
|
||||
user.stats.lvl = 1;
|
||||
user.stats.gp = 0;
|
||||
user.stats.exp = 0;
|
||||
gear = user.items.gear;
|
||||
_.each(['equipped', 'costume'], function (type) {
|
||||
gear[type].armor = 'armor_base_0';
|
||||
gear[type].weapon = 'weapon_base_0';
|
||||
gear[type].head = 'head_base_0';
|
||||
return gear[type].shield = 'shield_base_0';
|
||||
});
|
||||
if (typeof gear.owned === 'undefined') {
|
||||
gear.owned = {};
|
||||
}
|
||||
_.each(gear.owned, function (v, k) {
|
||||
if (gear.owned[k]) {
|
||||
gear.owned[k] = false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
gear.owned.weapon_warrior_0 = true;
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('items.gear.owned');
|
||||
}
|
||||
user.preferences.costume = false;
|
||||
return typeof cb === 'function' ? cb(null, user) : void 0;
|
||||
};
|
||||
72
common/script/ops/revive.js
Normal file
72
common/script/ops/revive.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var analyticsData, base, cl, gearOwned, item, losableItems, lostItem, lostStat;
|
||||
if (!(user.stats.hp <= 0)) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 400,
|
||||
message: 'Cannot revive if not dead'
|
||||
}) : void 0;
|
||||
}
|
||||
_.merge(user.stats, {
|
||||
hp: 50,
|
||||
exp: 0,
|
||||
gp: 0
|
||||
});
|
||||
if (user.stats.lvl > 1) {
|
||||
user.stats.lvl--;
|
||||
}
|
||||
lostStat = user.fns.randomVal(_.reduce(['str', 'con', 'per', 'int'], (function (m, k) {
|
||||
if (user.stats[k]) {
|
||||
m[k] = k;
|
||||
}
|
||||
return m;
|
||||
}), {}));
|
||||
if (lostStat) {
|
||||
user.stats[lostStat]--;
|
||||
}
|
||||
cl = user.stats['class'];
|
||||
gearOwned = (typeof (base = user.items.gear.owned).toObject === 'function' ? base.toObject() : void 0) || user.items.gear.owned;
|
||||
losableItems = {};
|
||||
_.each(gearOwned, function (v, k) {
|
||||
var itm;
|
||||
if (v) {
|
||||
itm = content.gear.flat['' + k];
|
||||
if (itm) {
|
||||
if ((itm.value > 0 || k === 'weapon_warrior_0') && (itm.klass === cl || (itm.klass === 'special' && (!itm.specialClass || itm.specialClass === cl)) || itm.klass === 'armoire')) {
|
||||
return losableItems['' + k] = '' + k;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
lostItem = user.fns.randomVal(losableItems);
|
||||
if (item = content.gear.flat[lostItem]) {
|
||||
user.items.gear.owned[lostItem] = false;
|
||||
if (user.items.gear.equipped[item.type] === lostItem) {
|
||||
user.items.gear.equipped[item.type] = item.type + '_base_0';
|
||||
}
|
||||
if (user.items.gear.costume[item.type] === lostItem) {
|
||||
user.items.gear.costume[item.type] = item.type + '_base_0';
|
||||
}
|
||||
}
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('items.gear');
|
||||
}
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
lostItem: lostItem,
|
||||
gaLabel: lostItem,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics !== null) {
|
||||
analytics.track('Death', analyticsData);
|
||||
}
|
||||
return typeof cb === 'function' ? cb((item ? {
|
||||
code: 200,
|
||||
message: i18n.t('messageLostItem', {
|
||||
itemText: item.text(req.language)
|
||||
}, req.language)
|
||||
} : null), user) : void 0;
|
||||
};
|
||||
221
common/script/ops/score.js
Normal file
221
common/script/ops/score.js
Normal file
@@ -0,0 +1,221 @@
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var addPoints, calculateDelta, calculateReverseDelta, changeTaskValue, delta, direction, gainMP, id, multiplier, num, options, ref, stats, subtractPoints, task, th;
|
||||
ref = req.params, id = ref.id, direction = ref.direction;
|
||||
task = user.tasks[id];
|
||||
options = req.query || {};
|
||||
_.defaults(options, {
|
||||
times: 1,
|
||||
cron: false
|
||||
});
|
||||
user._tmp = {};
|
||||
stats = {
|
||||
gp: +user.stats.gp,
|
||||
hp: +user.stats.hp,
|
||||
exp: +user.stats.exp
|
||||
};
|
||||
task.value = +task.value;
|
||||
task.streak = ~~task.streak;
|
||||
if (task.priority === null) {
|
||||
task.priority = 1;
|
||||
}
|
||||
if (task.value > stats.gp && task.type === 'reward') {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('messageNotEnoughGold', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
delta = 0;
|
||||
calculateDelta = function () {
|
||||
var currVal, nextDelta, ref1;
|
||||
currVal = task.value < -47.27 ? -47.27 : task.value > 21.27 ? 21.27 : task.value;
|
||||
nextDelta = Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1);
|
||||
if (((ref1 = task.checklist) !== null ? ref1.length : void 0) > 0) {
|
||||
if (direction === 'down' && task.type === 'daily' && options.cron) {
|
||||
nextDelta *= 1 - _.reduce(task.checklist, (function (m, i) {
|
||||
return m + (i.completed ? 1 : 0);
|
||||
}), 0) / task.checklist.length;
|
||||
}
|
||||
if (task.type === 'todo') {
|
||||
nextDelta *= 1 + _.reduce(task.checklist, (function (m, i) {
|
||||
return m + (i.completed ? 1 : 0);
|
||||
}), 0);
|
||||
}
|
||||
}
|
||||
return nextDelta;
|
||||
};
|
||||
calculateReverseDelta = function () {
|
||||
var calc, closeEnough, currVal, diff, nextDelta, ref1, testVal;
|
||||
currVal = task.value < -47.27 ? -47.27 : task.value > 21.27 ? 21.27 : task.value;
|
||||
testVal = currVal + Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1);
|
||||
closeEnough = 0.00001;
|
||||
while (true) {
|
||||
calc = testVal + Math.pow(0.9747, testVal);
|
||||
diff = currVal - calc;
|
||||
if (Math.abs(diff) < closeEnough) {
|
||||
break;
|
||||
}
|
||||
if (diff > 0) {
|
||||
testVal -= diff;
|
||||
} else {
|
||||
testVal += diff;
|
||||
}
|
||||
}
|
||||
nextDelta = testVal - currVal;
|
||||
if (((ref1 = task.checklist) !== null ? ref1.length : void 0) > 0) {
|
||||
if (task.type === 'todo') {
|
||||
nextDelta *= 1 + _.reduce(task.checklist, (function (m, i) {
|
||||
return m + (i.completed ? 1 : 0);
|
||||
}), 0);
|
||||
}
|
||||
}
|
||||
return nextDelta;
|
||||
};
|
||||
changeTaskValue = function () {
|
||||
return _.times(options.times, function () {
|
||||
var nextDelta, ref1;
|
||||
nextDelta = !options.cron && direction === 'down' ? calculateReverseDelta() : calculateDelta();
|
||||
if (task.type !== 'reward') {
|
||||
if (user.preferences.automaticAllocation === true && user.preferences.allocationMode === 'taskbased' && !(task.type === 'todo' && direction === 'down')) {
|
||||
user.stats.training[task.attribute] += nextDelta;
|
||||
}
|
||||
if (direction === 'up') {
|
||||
user.party.quest.progress.up = user.party.quest.progress.up || 0;
|
||||
if ((ref1 = task.type) === 'daily' || ref1 === 'todo') {
|
||||
user.party.quest.progress.up += nextDelta * (1 + (user._statsComputed.str / 200));
|
||||
}
|
||||
if (task.type === 'habit') {
|
||||
user.party.quest.progress.up += nextDelta * (0.5 + (user._statsComputed.str / 400));
|
||||
}
|
||||
}
|
||||
task.value += nextDelta;
|
||||
}
|
||||
return delta += nextDelta;
|
||||
});
|
||||
};
|
||||
addPoints = function () {
|
||||
var _crit, afterStreak, currStreak, gpMod, intBonus, perBonus, streakBonus;
|
||||
_crit = (delta > 0 ? user.fns.crit() : 1);
|
||||
if (_crit > 1) {
|
||||
user._tmp.crit = _crit;
|
||||
}
|
||||
intBonus = 1 + (user._statsComputed.int * .025);
|
||||
stats.exp += Math.round(delta * intBonus * task.priority * _crit * 6);
|
||||
perBonus = 1 + user._statsComputed.per * .02;
|
||||
gpMod = delta * task.priority * _crit * perBonus;
|
||||
return stats.gp += task.streak ? (currStreak = direction === 'down' ? task.streak - 1 : task.streak, streakBonus = currStreak / 100 + 1, afterStreak = gpMod * streakBonus, currStreak > 0 ? gpMod > 0 ? user._tmp.streakBonus = afterStreak - gpMod : void 0 : void 0, afterStreak) : gpMod;
|
||||
};
|
||||
subtractPoints = function () {
|
||||
var conBonus, hpMod;
|
||||
conBonus = 1 - (user._statsComputed.con / 250);
|
||||
if (conBonus < .1) {
|
||||
conBonus = 0.1;
|
||||
}
|
||||
hpMod = delta * conBonus * task.priority * 2;
|
||||
return stats.hp += Math.round(hpMod * 10) / 10;
|
||||
};
|
||||
gainMP = function (delta) {
|
||||
delta *= user._tmp.crit || 1;
|
||||
user.stats.mp += delta;
|
||||
if (user.stats.mp >= user._statsComputed.maxMP) {
|
||||
user.stats.mp = user._statsComputed.maxMP;
|
||||
}
|
||||
if (user.stats.mp < 0) {
|
||||
return user.stats.mp = 0;
|
||||
}
|
||||
};
|
||||
switch (task.type) {
|
||||
case 'habit':
|
||||
changeTaskValue();
|
||||
if (delta > 0) {
|
||||
addPoints();
|
||||
} else {
|
||||
subtractPoints();
|
||||
}
|
||||
gainMP(_.max([0.25, .0025 * user._statsComputed.maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
th = (task.history !== null ? task.history : task.history = []);
|
||||
if (th[th.length - 1] && moment(th[th.length - 1].date).isSame(new Date, 'day')) {
|
||||
th[th.length - 1].value = task.value;
|
||||
} else {
|
||||
th.push({
|
||||
date: +(new Date),
|
||||
value: task.value
|
||||
});
|
||||
}
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('habits.' + (_.findIndex(user.habits, {
|
||||
id: task.id
|
||||
})) + '.history');
|
||||
}
|
||||
break;
|
||||
case 'daily':
|
||||
if (options.cron) {
|
||||
changeTaskValue();
|
||||
subtractPoints();
|
||||
if (!user.stats.buffs.streaks) {
|
||||
task.streak = 0;
|
||||
}
|
||||
} else {
|
||||
changeTaskValue();
|
||||
if (direction === 'down') {
|
||||
delta = calculateDelta();
|
||||
}
|
||||
addPoints();
|
||||
gainMP(_.max([1, .01 * user._statsComputed.maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
if (direction === 'up') {
|
||||
task.streak = task.streak ? task.streak + 1 : 1;
|
||||
if ((task.streak % 21) === 0) {
|
||||
user.achievements.streak = user.achievements.streak ? user.achievements.streak + 1 : 1;
|
||||
}
|
||||
} else {
|
||||
if ((task.streak % 21) === 0) {
|
||||
user.achievements.streak = user.achievements.streak ? user.achievements.streak - 1 : 0;
|
||||
}
|
||||
task.streak = task.streak ? task.streak - 1 : 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'todo':
|
||||
if (options.cron) {
|
||||
changeTaskValue();
|
||||
} else {
|
||||
task.dateCompleted = direction === 'up' ? new Date : void 0;
|
||||
changeTaskValue();
|
||||
if (direction === 'down') {
|
||||
delta = calculateDelta();
|
||||
}
|
||||
addPoints();
|
||||
multiplier = _.max([
|
||||
_.reduce(task.checklist, (function (m, i) {
|
||||
return m + (i.completed ? 1 : 0);
|
||||
}), 1), 1
|
||||
]);
|
||||
gainMP(_.max([multiplier, .01 * user._statsComputed.maxMP * multiplier]) * (direction === 'down' ? -1 : 1));
|
||||
}
|
||||
break;
|
||||
case 'reward':
|
||||
changeTaskValue();
|
||||
stats.gp -= Math.abs(task.value);
|
||||
num = parseFloat(task.value).toFixed(2);
|
||||
if (stats.gp < 0) {
|
||||
stats.hp += stats.gp;
|
||||
stats.gp = 0;
|
||||
}
|
||||
}
|
||||
user.fns.updateStats(stats, req);
|
||||
if (typeof window === 'undefined') {
|
||||
if (direction === 'up') {
|
||||
user.fns.randomDrop({
|
||||
task: task,
|
||||
delta: delta
|
||||
}, req);
|
||||
}
|
||||
}
|
||||
if (typeof cb === 'function') {
|
||||
cb(null, user);
|
||||
}
|
||||
return delta;
|
||||
};
|
||||
23
common/script/ops/sell.js
Normal file
23
common/script/ops/sell.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import content from '../content/index';
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var key, ref, type;
|
||||
ref = req.params, key = ref.key, type = ref.type;
|
||||
if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food') {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: ':type not found. Must bes in [eggs, hatchingPotions, food]'
|
||||
}) : void 0;
|
||||
}
|
||||
if (!user.items[type][key]) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: ':key not found for user.items.' + type
|
||||
}) : void 0;
|
||||
}
|
||||
user.items[type][key]--;
|
||||
user.stats.gp += content[type][key].value;
|
||||
return typeof cb === 'function' ? cb(null, _.pick(user, splitWhitespace('stats items'))) : void 0;
|
||||
};
|
||||
4
common/script/ops/sleep.js
Normal file
4
common/script/ops/sleep.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = function (user, req, cb) {
|
||||
user.preferences.sleep = !user.preferences.sleep;
|
||||
return typeof cb === 'function' ? cb(null, {}) : void 0;
|
||||
};
|
||||
9
common/script/ops/sortTag.js
Normal file
9
common/script/ops/sortTag.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = function (user, req, cb) {
|
||||
var from, ref, to;
|
||||
ref = req.query, to = ref.to, from = ref.from;
|
||||
if (!((to !== null) && (from !== null))) {
|
||||
return typeof cb === 'function' ? cb('?to=__&from=__ are required') : void 0;
|
||||
}
|
||||
user.tags.splice(to, 0, user.tags.splice(from, 1)[0]);
|
||||
return typeof cb === 'function' ? cb(null, user.tags) : void 0;
|
||||
};
|
||||
39
common/script/ops/sortTask.js
Normal file
39
common/script/ops/sortTask.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import i18n from '../i18n';
|
||||
import preenTodos from '../libs/preenTodos';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var from, id, movedTask, preenedTasks, ref, task, tasks, to;
|
||||
id = req.params.id;
|
||||
ref = req.query, to = ref.to, from = ref.from;
|
||||
task = user.tasks[id];
|
||||
if (!task) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messageTaskNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (!((to !== null) && (from !== null))) {
|
||||
return typeof cb === 'function' ? cb('?to=__&from=__ are required') : void 0;
|
||||
}
|
||||
tasks = user[task.type + 's'];
|
||||
if (task.type === 'todo' && tasks[from] !== task) {
|
||||
preenedTasks = preenTodos(tasks);
|
||||
if (to !== -1) {
|
||||
to = tasks.indexOf(preenedTasks[to]);
|
||||
}
|
||||
from = tasks.indexOf(preenedTasks[from]);
|
||||
}
|
||||
if (tasks[from] !== task) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messageTaskNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
movedTask = tasks.splice(from, 1)[0];
|
||||
if (to === -1) {
|
||||
tasks.push(movedTask);
|
||||
} else {
|
||||
tasks.splice(to, 0, movedTask);
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, tasks) : void 0;
|
||||
};
|
||||
63
common/script/ops/unlock.js
Normal file
63
common/script/ops/unlock.js
Normal file
@@ -0,0 +1,63 @@
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
module.exports = function (user, req, cb, analytics) {
|
||||
var alreadyOwns, analyticsData, cost, fullSet, k, path, split, v;
|
||||
path = req.query.path;
|
||||
fullSet = ~path.indexOf(',');
|
||||
cost = ~path.indexOf('background.') ? fullSet ? 3.75 : 1.75 : fullSet ? 1.25 : 0.5;
|
||||
alreadyOwns = !fullSet && user.fns.dotGet('purchased.' + path) === true;
|
||||
if ((user.balance < cost || !user.balance) && !alreadyOwns) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 401,
|
||||
message: i18n.t('notEnoughGems', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
if (fullSet) {
|
||||
_.each(path.split(','), function (p) {
|
||||
if (~path.indexOf('gear.')) {
|
||||
user.fns.dotSet('' + p, true);
|
||||
true;
|
||||
} else {
|
||||
|
||||
}
|
||||
user.fns.dotSet('purchased.' + p, true);
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
if (alreadyOwns) {
|
||||
split = path.split('.');
|
||||
v = split.pop();
|
||||
k = split.join('.');
|
||||
if (k === 'background' && v === user.preferences.background) {
|
||||
v = '';
|
||||
}
|
||||
user.fns.dotSet('preferences.' + k, v);
|
||||
return typeof cb === 'function' ? cb(null, req) : void 0;
|
||||
}
|
||||
user.fns.dotSet('purchased.' + path, true);
|
||||
}
|
||||
user.balance -= cost;
|
||||
if (~path.indexOf('gear.')) {
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('gear.owned');
|
||||
}
|
||||
} else {
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('purchased');
|
||||
}
|
||||
}
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: path,
|
||||
itemType: 'customization',
|
||||
acquireMethod: 'Gems',
|
||||
gemCost: cost / .25,
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics !== null) {
|
||||
analytics.track('acquire item', analyticsData);
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, _.pick(user, splitWhitespace('purchased preferences items'))) : void 0;
|
||||
};
|
||||
9
common/script/ops/update.js
Normal file
9
common/script/ops/update.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
_.each(req.body, function (v, k) {
|
||||
user.fns.dotSet(k, v);
|
||||
return true;
|
||||
});
|
||||
return typeof cb === 'function' ? cb(null, user) : void 0;
|
||||
};
|
||||
18
common/script/ops/updateTag.js
Normal file
18
common/script/ops/updateTag.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var i, tid;
|
||||
tid = req.params.id;
|
||||
i = _.findIndex(user.tags, {
|
||||
id: tid
|
||||
});
|
||||
if (!~i) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messageTagNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
user.tags[i].name = req.body.name;
|
||||
return typeof cb === 'function' ? cb(null, user.tags[i]) : void 0;
|
||||
};
|
||||
20
common/script/ops/updateTask.js
Normal file
20
common/script/ops/updateTask.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import i18n from '../i18n';
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
var ref, task;
|
||||
if (!(task = user.tasks[(ref = req.params) !== null ? ref.id : void 0])) {
|
||||
return typeof cb === 'function' ? cb({
|
||||
code: 404,
|
||||
message: i18n.t('messageTaskNotFound', req.language)
|
||||
}) : void 0;
|
||||
}
|
||||
_.merge(task, _.omit(req.body, ['checklist', 'id', 'type']));
|
||||
if (req.body.checklist) {
|
||||
task.checklist = req.body.checklist;
|
||||
}
|
||||
if (typeof task.markModified === 'function') {
|
||||
task.markModified('tags');
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, task) : void 0;
|
||||
};
|
||||
9
common/script/ops/updateWebhook.js
Normal file
9
common/script/ops/updateWebhook.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function (user, req, cb) {
|
||||
_.merge(user.preferences.webhooks[req.params.id], req.body);
|
||||
if (typeof user.markModified === 'function') {
|
||||
user.markModified('preferences.webhooks');
|
||||
}
|
||||
return typeof cb === 'function' ? cb(null, user.preferences.webhooks) : void 0;
|
||||
};
|
||||
@@ -107,7 +107,7 @@ describe('user.ops.hourglassPurchase', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('buys a mount', (done) => {
|
||||
it.only('buys a mount', (done) => {
|
||||
user.purchased.plan.consecutive.trinkets = 2;
|
||||
|
||||
user.ops.hourglassPurchase({params: {type: 'mounts', key: 'MantisShrimp-Base'}}, (response) => {
|
||||
|
||||
Reference in New Issue
Block a user