Upgrade lodash to v4 and lint more files (#8495)
* common: import lodash modules separately * remove test/content from .eslintignore, fix with eslint --fix content/index * lint test/content * lint content/index except for lodash methods * upgrade server/models * upgrade server/middlewares and server/libs * port server/controllers/top-level * port server/controllers/api-v3 * port views and tests * client old port lodash and _(, missing _. * upgrade client-old * port common/script (root level files only) * port common/script/fns * port common/libs * port common/script/ops * port common/script/content and common/script/libs/shops.js * misc fixes * misc fixes * misc fixes * more tests fixes * fix payments test stubbing, down to 2 failing tests * remove more instances of lodash wrapping * fix bug where toObject does not clone object * fix tests * upgrade migration or add lodash 4 note * update shrinkwrap * fix linting * upgrade eslint-config-habitrpg * update shrinkwrap * recompile shrinkwrap
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
import _ from 'lodash';
|
||||
import min from 'lodash/min';
|
||||
import pick from 'lodash/pick';
|
||||
import values from 'lodash/values';
|
||||
import invert from 'lodash/invert';
|
||||
import findIndex from 'lodash/findIndex';
|
||||
import max from 'lodash/max';
|
||||
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
/*
|
||||
@@ -14,8 +20,8 @@ function getStatToAllocate (user) {
|
||||
|
||||
switch (user.preferences.allocationMode) {
|
||||
case 'flat': {
|
||||
let stats = _.pick(statsObj, splitWhitespace('con str per int'));
|
||||
return _.invert(stats)[_.min(stats)];
|
||||
let stats = pick(statsObj, splitWhitespace('con str per int'));
|
||||
return invert(stats)[min(values(stats))];
|
||||
}
|
||||
case 'classbased': {
|
||||
let preference;
|
||||
@@ -47,14 +53,14 @@ function getStatToAllocate (user) {
|
||||
statsObj[preference[3]] - ideal[3],
|
||||
];
|
||||
|
||||
suggested = _.findIndex(diff, (val) => {
|
||||
if (val === _.min(diff)) return true;
|
||||
suggested = findIndex(diff, (val) => {
|
||||
if (val === min(diff)) return true;
|
||||
});
|
||||
|
||||
return suggested !== -1 ? preference[suggested] : 'str';
|
||||
}
|
||||
case 'taskbased': {
|
||||
suggested = _.invert(statsObj.training)[_.max(statsObj.training)];
|
||||
suggested = invert(statsObj.training)[max(values(statsObj.training))];
|
||||
|
||||
user.stats.training.str = 0;
|
||||
user.stats.training.int = 0;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import _ from 'lodash';
|
||||
import omit from 'lodash/omit';
|
||||
import reduce from 'lodash/reduce';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
|
||||
// Because the same op needs to be performed on the client and the server (critical hits, item drops, etc),
|
||||
// we need things to be "random", but technically predictable so that they don't go out-of-sync
|
||||
@@ -8,10 +10,10 @@ module.exports = function predictableRandom (user, seed) {
|
||||
let stats = user.stats.toObject ? user.stats.toObject() : user.stats;
|
||||
// These items are not part of the stat object but exists on the server (see controllers/user#getUser)
|
||||
// we remove them in order to use the same user.stats both on server and on client
|
||||
stats = _.omit(stats, 'toNextLevel', 'maxHealth', 'maxMP');
|
||||
stats = omit(stats, ['toNextLevel', 'maxHealth', 'maxMP']);
|
||||
|
||||
seed = _.reduce(stats, (accumulator, val) => {
|
||||
if (_.isNumber(val)) {
|
||||
seed = reduce(stats, (accumulator, val) => {
|
||||
if (isNumber(val)) {
|
||||
return accumulator + val;
|
||||
} else {
|
||||
return accumulator;
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import _ from 'lodash';
|
||||
import cloneDeepWith from 'lodash/cloneDeepWith';
|
||||
import isFunction from 'lodash/isFunction';
|
||||
import min from 'lodash/min';
|
||||
import reduce from 'lodash/reduce';
|
||||
import filter from 'lodash/filter';
|
||||
import pickBy from 'lodash/pickBy';
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
import { daysSince } from '../cron';
|
||||
@@ -10,8 +15,8 @@ import randomVal from '../libs/randomVal';
|
||||
|
||||
// Clone a drop object maintaining its functions so that we can change it without affecting the original item
|
||||
function cloneDropItem (drop) {
|
||||
return _.cloneDeep(drop, (val) => {
|
||||
return _.isFunction(val) ? val : undefined; // undefined will be handled by lodash
|
||||
return cloneDeepWith(drop, (val) => {
|
||||
return isFunction(val) ? val : undefined; // undefined will be handled by lodash
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,14 +33,14 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
let predictableRandom = options.predictableRandom || trueRandom;
|
||||
let task = options.task;
|
||||
|
||||
let chance = _.min([Math.abs(task.value - 21.27), 37.5]) / 150 + 0.02;
|
||||
let chance = min([Math.abs(task.value - 21.27), 37.5]) / 150 + 0.02;
|
||||
chance *= task.priority * // Task priority: +50% for Medium, +100% for Hard
|
||||
(1 + (task.streak / 100 || 0)) * // Streak bonus: +1% per streak
|
||||
(1 + user._statsComputed.per / 100) * // PERception: +1% per point
|
||||
(1 + (user.contributor.level / 40 || 0)) * // Contrib levels: +2.5% per level
|
||||
(1 + (user.achievements.rebirths / 20 || 0)) * // Rebirths: +5% per achievement
|
||||
(1 + (user.achievements.streak / 200 || 0)) * // Streak achievements: +0.5% per achievement
|
||||
(user._tmp.crit || 1) * (1 + 0.5 * (_.reduce(task.checklist, (m, i) => {
|
||||
(user._tmp.crit || 1) * (1 + 0.5 * (reduce(task.checklist, (m, i) => {
|
||||
return m + (i.completed ? 1 : 0); // +50% per checklist item complete. TODO: make this into X individual drop chances instead
|
||||
}, 0) || 0));
|
||||
chance = diminishingReturns(chance, 0.75);
|
||||
@@ -63,7 +68,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
rarity = predictableRandom();
|
||||
|
||||
if (rarity > 0.6) { // food 40% chance
|
||||
drop = cloneDropItem(randomVal(_.where(content.food, {
|
||||
drop = cloneDropItem(randomVal(filter(content.food, {
|
||||
canDrop: true,
|
||||
})));
|
||||
|
||||
@@ -98,7 +103,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
} else { // common, 40% of 30%
|
||||
acceptableDrops = ['Base', 'White', 'Desert'];
|
||||
}
|
||||
drop = cloneDropItem(randomVal(_.pick(content.hatchingPotions, (v, k) => {
|
||||
drop = cloneDropItem(randomVal(pickBy(content.hatchingPotions, (v, k) => {
|
||||
return acceptableDrops.indexOf(k) >= 0;
|
||||
})));
|
||||
if (!user.items.hatchingPotions[drop.key]) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import _ from 'lodash';
|
||||
import each from 'lodash/each';
|
||||
import content from '../content/index';
|
||||
|
||||
module.exports = function resetGear (user) {
|
||||
let gear = user.items.gear;
|
||||
|
||||
_.each(['equipped', 'costume'], function resetUserGear (type) {
|
||||
each(['equipped', 'costume'], function resetUserGear (type) {
|
||||
gear[type] = {};
|
||||
gear[type].armor = 'armor_base_0';
|
||||
gear[type].weapon = 'weapon_warrior_0';
|
||||
@@ -14,7 +14,7 @@ module.exports = function resetGear (user) {
|
||||
|
||||
// Gear.owned is a Mongo object so the _.each function iterates over hidden properties.
|
||||
// The content.gear.flat[k] check should prevent this causing an error
|
||||
_.each(gear.owned, function resetOwnedGear (v, k) {
|
||||
each(gear.owned, function resetOwnedGear (v, k) {
|
||||
if (gear.owned[k] && content.gear.flat[k] && content.gear.flat[k].value) {
|
||||
gear.owned[k] = false;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import content from '../content/index';
|
||||
import _ from 'lodash';
|
||||
import lodashFind from 'lodash/find';
|
||||
import reduce from 'lodash/reduce';
|
||||
import includes from 'lodash/includes';
|
||||
|
||||
module.exports = function ultimateGear (user) {
|
||||
let owned = typeof window !== 'undefined' ? user.items.gear.owned : user.items.gear.owned.toObject();
|
||||
|
||||
content.classes.forEach((klass) => {
|
||||
if (user.achievements.ultimateGearSets[klass] !== true) {
|
||||
user.achievements.ultimateGearSets[klass] = _.reduce(['armor', 'shield', 'head', 'weapon'], (soFarGood, type) => {
|
||||
let found = _.find(content.gear.tree[type][klass], {
|
||||
user.achievements.ultimateGearSets[klass] = reduce(['armor', 'shield', 'head', 'weapon'], (soFarGood, type) => {
|
||||
let found = lodashFind(content.gear.tree[type][klass], {
|
||||
last: true,
|
||||
});
|
||||
return soFarGood && (!found || owned[found.key] === true);
|
||||
@@ -26,7 +28,7 @@ module.exports = function ultimateGear (user) {
|
||||
ultimateGearSetValues = Object.values(user.achievements.ultimateGearSets);
|
||||
}
|
||||
|
||||
let hasFullSet = _.includes(ultimateGearSetValues, true);
|
||||
let hasFullSet = includes(ultimateGearSetValues, true);
|
||||
|
||||
if (hasFullSet && user.flags.armoireEnabled !== true) {
|
||||
user.flags.armoireEnabled = true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import _ from 'lodash';
|
||||
import each from 'lodash/each';
|
||||
import {
|
||||
MAX_HEALTH,
|
||||
MAX_STAT_POINTS,
|
||||
@@ -67,7 +67,7 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
|
||||
user.items.eggs.Wolf = 1;
|
||||
}
|
||||
}
|
||||
_.each({
|
||||
each({
|
||||
vice1: 30,
|
||||
atom1: 15,
|
||||
moonstone1: 60,
|
||||
|
||||
Reference in New Issue
Block a user