mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 07:07:35 +01:00
shared-code-update-stats
This commit is contained in:
@@ -1,22 +1,19 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {
|
import {
|
||||||
MAX_HEALTH,
|
MAX_HEALTH,
|
||||||
MAX_STAT_POINTS
|
MAX_STAT_POINTS,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { toNextLevel } from '../statHelpers';
|
import { toNextLevel } from '../statHelpers';
|
||||||
|
import autoAllocate from './autoAllocate';
|
||||||
|
|
||||||
module.exports = function updateStats (user, stats, req, analytics) {
|
module.exports = function updateStats (user, stats, req = {}, analytics) {
|
||||||
let allocatedStatPoints;
|
let allocatedStatPoints;
|
||||||
let totalStatPoints;
|
let totalStatPoints;
|
||||||
let experienceToNextLevel;
|
let experienceToNextLevel;
|
||||||
|
|
||||||
if (stats.hp <= 0) {
|
user.stats.hp = stats.hp > 0 ? stats.hp : 0;
|
||||||
user.stats.hp = 0;
|
user.stats.gp = stats.gp > 0 ? stats.gp : 0;
|
||||||
return user.stats.hp;
|
if (!user._tmp) user._tmp = {};
|
||||||
}
|
|
||||||
|
|
||||||
user.stats.hp = stats.hp;
|
|
||||||
user.stats.gp = stats.gp >= 0 ? stats.gp : 0;
|
|
||||||
|
|
||||||
experienceToNextLevel = toNextLevel(user.stats.lvl);
|
experienceToNextLevel = toNextLevel(user.stats.lvl);
|
||||||
|
|
||||||
@@ -36,7 +33,7 @@ module.exports = function updateStats (user, stats, req, analytics) {
|
|||||||
continue; // eslint-disable-line no-continue
|
continue; // eslint-disable-line no-continue
|
||||||
}
|
}
|
||||||
if (user.preferences.automaticAllocation) {
|
if (user.preferences.automaticAllocation) {
|
||||||
user.fns.autoAllocate();
|
autoAllocate(user);
|
||||||
} else {
|
} else {
|
||||||
user.stats.points = user.stats.lvl - allocatedStatPoints;
|
user.stats.points = user.stats.lvl - allocatedStatPoints;
|
||||||
totalStatPoints = user.stats.points + allocatedStatPoints;
|
totalStatPoints = user.stats.points + allocatedStatPoints;
|
||||||
@@ -53,7 +50,6 @@ module.exports = function updateStats (user, stats, req, analytics) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user.stats.exp = stats.exp;
|
user.stats.exp = stats.exp;
|
||||||
user.flags = user.flags || {};
|
|
||||||
|
|
||||||
if (!user.flags.customizationsNotification && (user.stats.exp > 5 || user.stats.lvl > 1)) {
|
if (!user.flags.customizationsNotification && (user.stats.exp > 5 || user.stats.lvl > 1)) {
|
||||||
user.flags.customizationsNotification = true;
|
user.flags.customizationsNotification = true;
|
||||||
@@ -63,48 +59,39 @@ module.exports = function updateStats (user, stats, req, analytics) {
|
|||||||
}
|
}
|
||||||
if (!user.flags.dropsEnabled && user.stats.lvl >= 3) {
|
if (!user.flags.dropsEnabled && user.stats.lvl >= 3) {
|
||||||
user.flags.dropsEnabled = true;
|
user.flags.dropsEnabled = true;
|
||||||
if (user.items.eggs["Wolf"] > 0) {
|
if (user.items.eggs.Wolf > 0) {
|
||||||
user.items.eggs["Wolf"]++;
|
user.items.eggs.Wolf++;
|
||||||
} else {
|
} else {
|
||||||
user.items.eggs["Wolf"] = 1;
|
user.items.eggs.Wolf = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!user.flags.classSelected && user.stats.lvl >= 10) {
|
|
||||||
user.flags.classSelected;
|
|
||||||
}
|
|
||||||
_.each({
|
_.each({
|
||||||
vice1: 30,
|
vice1: 30,
|
||||||
atom1: 15,
|
atom1: 15,
|
||||||
moonstone1: 60,
|
moonstone1: 60,
|
||||||
goldenknight1: 40
|
goldenknight1: 40,
|
||||||
}, function(lvl, k) {
|
}, (lvl, k) => {
|
||||||
var analyticsData, base, base1, ref;
|
if (user.stats.lvl >= lvl && !user.flags.levelDrops[k]) {
|
||||||
if (!((ref = user.flags.levelDrops) != null ? ref[k] : void 0) && user.stats.lvl >= lvl) {
|
user.flags.levelDrops[k] = true;
|
||||||
if ((base = user.items.quests)[k] == null) {
|
if (!user.items.quests[k])
|
||||||
base[k] = 0;
|
user.items.quests[k] = 0;
|
||||||
}
|
|
||||||
user.items.quests[k]++;
|
user.items.quests[k]++;
|
||||||
((base1 = user.flags).levelDrops != null ? base1.levelDrops : base1.levelDrops = {})[k] = true;
|
user.markModified('flags.levelDrops');
|
||||||
if (typeof user.markModified === "function") {
|
if (analytics) {
|
||||||
user.markModified('flags.levelDrops');
|
analytics.track('acquire item', {
|
||||||
|
uuid: user._id,
|
||||||
|
itemKey: k,
|
||||||
|
acquireMethod: 'Level Drop',
|
||||||
|
category: 'behavior',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
analyticsData = {
|
user._tmp.drop = {
|
||||||
uuid: user._id,
|
|
||||||
itemKey: k,
|
|
||||||
acquireMethod: 'Level Drop',
|
|
||||||
category: 'behavior'
|
|
||||||
};
|
|
||||||
if (analytics != null) {
|
|
||||||
analytics.track('acquire item', analyticsData);
|
|
||||||
}
|
|
||||||
if (!user._tmp) user._tmp = {}
|
|
||||||
return user._tmp.drop = {
|
|
||||||
type: 'Quest',
|
type: 'Quest',
|
||||||
key: k
|
key: k,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!user.flags.rebirthEnabled && (user.stats.lvl >= 50 || user.achievements.beastMaster)) {
|
if (!user.flags.rebirthEnabled && (user.stats.lvl >= 50 || user.achievements.beastMaster)) {
|
||||||
return user.flags.rebirthEnabled = true;
|
user.flags.rebirthEnabled = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ const COMMON_FILES = [
|
|||||||
'!./common/script/fns/nullify.js',
|
'!./common/script/fns/nullify.js',
|
||||||
'!./common/script/fns/preenUserHistory.js',
|
'!./common/script/fns/preenUserHistory.js',
|
||||||
'!./common/script/fns/randomDrop.js',
|
'!./common/script/fns/randomDrop.js',
|
||||||
'!./common/script/fns/updateStats.js',
|
|
||||||
'!./common/script/libs/appliedTags.js',
|
'!./common/script/libs/appliedTags.js',
|
||||||
'!./common/script/libs/countExists.js',
|
'!./common/script/libs/countExists.js',
|
||||||
'!./common/script/libs/dotGet.js',
|
'!./common/script/libs/dotGet.js',
|
||||||
|
|||||||
170
test/common/fns/updateStats.test.js
Normal file
170
test/common/fns/updateStats.test.js
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import updateStats from '../../../common/script/fns/updateStats';
|
||||||
|
import {
|
||||||
|
generateUser,
|
||||||
|
} from '../../helpers/common.helper';
|
||||||
|
|
||||||
|
describe('common.fns.updateStats', () => {
|
||||||
|
let user;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
user = generateUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
context('No Hp', () => {
|
||||||
|
it('updates user\s hp', () => {
|
||||||
|
let stats = { hp: 0 };
|
||||||
|
expect(user.stats.hp).to.not.eql(0);
|
||||||
|
updateStats(user, stats);
|
||||||
|
expect(user.stats.hp).to.eql(0);
|
||||||
|
updateStats(user, { hp: 2 });
|
||||||
|
expect(user.stats.hp).to.eql(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not lower hp below 0', () => {
|
||||||
|
let stats = {
|
||||||
|
hp: -5,
|
||||||
|
};
|
||||||
|
updateStats(user, stats);
|
||||||
|
expect(user.stats.hp).to.eql(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('Stat Allocation', () => {
|
||||||
|
it('adds only attribute points up to user\'s level', () => {
|
||||||
|
let stats = {
|
||||||
|
exp: 261,
|
||||||
|
};
|
||||||
|
expect(user.stats.points).to.eql(0);
|
||||||
|
|
||||||
|
user.stats.lvl = 10;
|
||||||
|
|
||||||
|
updateStats(user, stats);
|
||||||
|
|
||||||
|
expect(user.stats.points).to.eql(11);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds an attibute point when user\'s stat points are less than max level', () => {
|
||||||
|
let stats = {
|
||||||
|
exp: 3581,
|
||||||
|
};
|
||||||
|
|
||||||
|
user.stats.lvl = 99;
|
||||||
|
user.stats.str = 25;
|
||||||
|
user.stats.int = 25;
|
||||||
|
user.stats.con = 25;
|
||||||
|
user.stats.per = 24;
|
||||||
|
|
||||||
|
updateStats(user, stats);
|
||||||
|
|
||||||
|
expect(user.stats.points).to.eql(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not add an attibute point when user\'s stat points are equal to max level', () => {
|
||||||
|
let stats = {
|
||||||
|
exp: 3581,
|
||||||
|
};
|
||||||
|
|
||||||
|
user.stats.lvl = 99;
|
||||||
|
user.stats.str = 25;
|
||||||
|
user.stats.int = 25;
|
||||||
|
user.stats.con = 25;
|
||||||
|
user.stats.per = 25;
|
||||||
|
|
||||||
|
updateStats(user, stats);
|
||||||
|
|
||||||
|
expect(user.stats.points).to.eql(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not add an attibute point when user\'s stat points + unallocated points are equal to max level', () => {
|
||||||
|
let stats = {
|
||||||
|
exp: 3581,
|
||||||
|
};
|
||||||
|
|
||||||
|
user.stats.lvl = 99;
|
||||||
|
user.stats.str = 25;
|
||||||
|
user.stats.int = 25;
|
||||||
|
user.stats.con = 25;
|
||||||
|
user.stats.per = 15;
|
||||||
|
user.stats.points = 10;
|
||||||
|
|
||||||
|
updateStats(user, stats);
|
||||||
|
|
||||||
|
expect(user.stats.points).to.eql(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('only awards stat points up to level 100 if user is missing unallocated stat points and is over level 100', () => {
|
||||||
|
let stats = {
|
||||||
|
exp: 5581,
|
||||||
|
};
|
||||||
|
|
||||||
|
user.stats.lvl = 104;
|
||||||
|
user.stats.str = 25;
|
||||||
|
user.stats.int = 25;
|
||||||
|
user.stats.con = 25;
|
||||||
|
user.stats.per = 15;
|
||||||
|
user.stats.points = 0;
|
||||||
|
|
||||||
|
updateStats(user, stats);
|
||||||
|
|
||||||
|
expect(user.stats.points).to.eql(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
context('assigns flags.levelDrops', () => {
|
||||||
|
it('for atom1', () => {
|
||||||
|
user.stats.lvl = 16;
|
||||||
|
user.flags.levelDrops.atom1 = false;
|
||||||
|
expect(user.items.quests.atom1).to.eql(undefined);
|
||||||
|
updateStats(user, { atom1: true });
|
||||||
|
expect(user.items.quests.atom1).to.eql(1);
|
||||||
|
expect(user.flags.levelDrops.atom1).to.eql(true);
|
||||||
|
updateStats(user, { atom1: true });
|
||||||
|
expect(user.items.quests.atom1).to.eql(1); // no change
|
||||||
|
});
|
||||||
|
it('for vice1', () => {
|
||||||
|
user.stats.lvl = 31;
|
||||||
|
user.flags.levelDrops.vice1 = false;
|
||||||
|
expect(user.items.quests.vice1).to.eql(undefined);
|
||||||
|
updateStats(user, { vice1: true });
|
||||||
|
expect(user.items.quests.vice1).to.eql(1);
|
||||||
|
expect(user.flags.levelDrops.vice1).to.eql(true);
|
||||||
|
updateStats(user, { vice1: true });
|
||||||
|
expect(user.items.quests.vice1).to.eql(1);
|
||||||
|
});
|
||||||
|
it('moonstone', () => {
|
||||||
|
user.stats.lvl = 60;
|
||||||
|
user.flags.levelDrops.moonstone1 = false;
|
||||||
|
expect(user.items.quests.moonstone1).to.eql(undefined);
|
||||||
|
updateStats(user, { moonstone1: true });
|
||||||
|
expect(user.flags.levelDrops.moonstone1).to.eql(true);
|
||||||
|
expect(user.items.quests.moonstone1).to.eql(1);
|
||||||
|
updateStats(user, { moonstone1: true });
|
||||||
|
expect(user.items.quests.moonstone1).to.eql(1);
|
||||||
|
});
|
||||||
|
it('for goldenknight1', () => {
|
||||||
|
user.stats.lvl = 40;
|
||||||
|
user.flags.levelDrops.goldenknight1 = false;
|
||||||
|
expect(user.items.quests.goldenknight1).to.eql(undefined);
|
||||||
|
updateStats(user, { goldenknight1: true });
|
||||||
|
expect(user.items.quests.goldenknight1).to.eql(1);
|
||||||
|
expect(user.flags.levelDrops.goldenknight1).to.eql(true);
|
||||||
|
updateStats(user, { goldenknight1: true });
|
||||||
|
expect(user.items.quests.goldenknight1).to.eql(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// @TODO: Set up sinon sandbox
|
||||||
|
xit('auto allocates stats if automaticAllocation is turned on', () => {
|
||||||
|
sandbox.stub(user.fns, 'autoAllocate');
|
||||||
|
|
||||||
|
let stats = {
|
||||||
|
exp: 261,
|
||||||
|
};
|
||||||
|
|
||||||
|
user.stats.lvl = 10;
|
||||||
|
|
||||||
|
user.fns.updateStats(stats);
|
||||||
|
|
||||||
|
expect(user.fns.autoAllocate).to.be.calledOnce;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user