Tasks scoring and misc fixes (#8925)
* wip: add task scoring and persist checklist items * remove unused files, fix checklist scoring and start adding support for groups tasks * amke group and challenge tasks not scoreable
@@ -1,3 +1,20 @@
|
||||
.daily-todo-control {
|
||||
|
||||
&:hover {
|
||||
.svg-icon.check {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.svg-icon.check {
|
||||
display: none;
|
||||
|
||||
&.display-check-icon {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.task {
|
||||
// for editing rewards or when a task is created
|
||||
&-purple {
|
||||
@@ -20,6 +37,7 @@
|
||||
|
||||
&-control-daily-todo {
|
||||
background: $maroon-500;
|
||||
background: $maroon-100;
|
||||
}
|
||||
|
||||
&-modal-input {
|
||||
@@ -35,6 +53,7 @@
|
||||
|
||||
&-control-daily-todo {
|
||||
background: $red-500;
|
||||
color: $red-100;
|
||||
}
|
||||
|
||||
&-modal-input {
|
||||
@@ -50,6 +69,7 @@
|
||||
|
||||
&-control-daily-todo {
|
||||
background: $orange-500;
|
||||
color: $orange-100;
|
||||
}
|
||||
|
||||
&-modal-input {
|
||||
@@ -58,13 +78,14 @@
|
||||
}
|
||||
|
||||
&-neutral {
|
||||
background: $yellow-50;
|
||||
background: $yellow-100;
|
||||
&-control-habit {
|
||||
background: darken($yellow-50, 12%);
|
||||
background: darken($yellow-100, 12%);
|
||||
}
|
||||
|
||||
&-control-daily-todo {
|
||||
background: $yellow-500;
|
||||
color: $yellow-100;
|
||||
}
|
||||
|
||||
&-modal-input {
|
||||
@@ -80,6 +101,7 @@
|
||||
|
||||
&-control-daily-todo {
|
||||
background: $green-500;
|
||||
color: $green-10;
|
||||
}
|
||||
|
||||
&-modal-input {
|
||||
@@ -95,6 +117,7 @@
|
||||
|
||||
&-control-daily-todo {
|
||||
background: $blue-500;
|
||||
color: $blue-50;
|
||||
}
|
||||
|
||||
&-modal-input {
|
||||
@@ -110,6 +133,7 @@
|
||||
|
||||
&-control-daily-todo {
|
||||
background: $teal-500;
|
||||
color: $teal-50;
|
||||
}
|
||||
|
||||
&-modal-input {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template lang="pug">
|
||||
.tasks-column(:class='type')
|
||||
b-modal(ref="editTaskModal")
|
||||
span Hello From My Modal!
|
||||
.d-flex
|
||||
h2.tasks-column-title(v-once) {{ $t(types[type].label) }}
|
||||
.filters.d-flex.justify-content-end
|
||||
@@ -15,6 +14,7 @@
|
||||
v-for="task in taskList",
|
||||
:key="task.id", :task="task",
|
||||
v-if="filterTask(task)",
|
||||
:isUser="isUser",
|
||||
@editTask="editTask",
|
||||
)
|
||||
.bottom-gradient
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template lang="pug">
|
||||
.task.d-flex
|
||||
.task.d-flex(:class="{'task-not-scoreable': isUser !== true}")
|
||||
// Habits left side control
|
||||
.left-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="controlClass.up")
|
||||
.task-control.habit-control(:class="controlClass.up + '-control-habit'")
|
||||
.task-control.habit-control(:class="controlClass.up + '-control-habit'", @click="isUser ? score('up') : null")
|
||||
.svg-icon.positive(v-html="icons.positive")
|
||||
// Dailies and todos left side control
|
||||
.left-control.d-flex.justify-content-center(v-if="task.type === 'daily' || task.type === 'todo'", :class="controlClass")
|
||||
.task-control.daily-todo-control(:class="controlClass + '-control-daily-todo'")
|
||||
.svg-icon.check(v-html="icons.check", v-if="task.completed")
|
||||
.task-control.daily-todo-control(:class="controlClass + '-control-daily-todo'", @click="isUser ? score(task.completed ? 'down' : 'up') : null")
|
||||
.svg-icon.check(v-html="icons.check", :class="{'display-check-icon': task.completed}")
|
||||
// Task title, description and icons
|
||||
.task-content(:class="contentClass")
|
||||
.task-clickable-area(@click="edit($event, task)")
|
||||
@@ -17,7 +17,7 @@
|
||||
label.custom-control.custom-checkbox.checklist-item(
|
||||
v-for="item in task.checklist", :class="{'checklist-item-done': item.completed}",
|
||||
)
|
||||
input.custom-control-input(type="checkbox", :checked="item.completed")
|
||||
input.custom-control-input(type="checkbox", :checked="item.completed", @change="toggleChecklistItem(item)")
|
||||
span.custom-control-indicator
|
||||
span.custom-control-description {{ item.text }}
|
||||
.icons.small-text.d-flex.align-items-center
|
||||
@@ -47,10 +47,10 @@
|
||||
|
||||
// Habits right side control
|
||||
.right-control.d-flex.align-items-center.justify-content-center(v-if="task.type === 'habit'", :class="controlClass.down")
|
||||
.task-control.habit-control(:class="controlClass.down + '-control-habit'")
|
||||
.task-control.habit-control(:class="controlClass.down + '-control-habit'", @click="isUser ? score('down') : null")
|
||||
.svg-icon.negative(v-html="icons.negative")
|
||||
// Rewards right side control
|
||||
.right-control.d-flex.align-items-center.justify-content-center.reward-control(v-if="task.type === 'reward'", :class="controlClass")
|
||||
.right-control.d-flex.align-items-center.justify-content-center.reward-control(v-if="task.type === 'reward'", :class="controlClass", @click="isUser ? score('down') : null")
|
||||
.svg-icon(v-html="icons.gold")
|
||||
.small-text {{task.value}}
|
||||
</template>
|
||||
@@ -190,6 +190,20 @@
|
||||
min-height: 56px;
|
||||
}
|
||||
|
||||
.task-control, .reward-control {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.task-not-scoreable {
|
||||
.task-control, .reward-control {
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
.svg-icon.check {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.daily-todo-control {
|
||||
margin-top: 16px;
|
||||
border-radius: 2px;
|
||||
@@ -239,8 +253,11 @@
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import { mapState, mapGetters } from 'client/libs/store';
|
||||
import { mapState, mapGetters, mapActions } from 'client/libs/store';
|
||||
import moment from 'moment';
|
||||
import axios from 'axios';
|
||||
import scoreTask from 'common/script/ops/scoreTask';
|
||||
import Vue from 'vue';
|
||||
|
||||
import positiveIcon from 'assets/svg/positive.svg';
|
||||
import negativeIcon from 'assets/svg/negative.svg';
|
||||
@@ -252,15 +269,17 @@ import tagsIcon from 'assets/svg/tags.svg';
|
||||
import checkIcon from 'assets/svg/check.svg';
|
||||
import bPopover from 'bootstrap-vue/lib/components/popover';
|
||||
import markdownDirective from 'client/directives/markdown';
|
||||
import notifications from 'client/mixins/notifications';
|
||||
|
||||
export default {
|
||||
mixins: [notifications],
|
||||
components: {
|
||||
bPopover,
|
||||
},
|
||||
directives: {
|
||||
markdown: markdownDirective,
|
||||
},
|
||||
props: ['task'],
|
||||
props: ['task', 'isUser'],
|
||||
data () {
|
||||
return {
|
||||
icons: Object.freeze({
|
||||
@@ -312,6 +331,11 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
...mapActions({scoreChecklistItem: 'tasks:scoreChecklistItem'}),
|
||||
toggleChecklistItem (item) {
|
||||
item.completed = !item.completed;
|
||||
this.scoreChecklistItem({taskId: this.task._id, itemId: item.id});
|
||||
},
|
||||
edit (e, task) {
|
||||
// Prevent clicking on a link from opening the edit modal
|
||||
const target = e.target || e.srcElement;
|
||||
@@ -322,6 +346,87 @@ export default {
|
||||
this.$emit('editTask', task);
|
||||
}
|
||||
},
|
||||
async score (direction) {
|
||||
// TODO move to an action
|
||||
const Content = this.$store.state.content;
|
||||
const user = this.user;
|
||||
const task = this.task;
|
||||
|
||||
try {
|
||||
scoreTask({task, user, direction});
|
||||
} catch (err) {
|
||||
this.text(err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (task.group.approval.required) task.group.approval.requested = true;
|
||||
|
||||
const response = await axios.post(`/api/v3/tasks/${task._id}/score/${direction}`);
|
||||
const tmp = response.data.data._tmp || {}; // used to notify drops, critical hits and other bonuses
|
||||
const crit = tmp.crit;
|
||||
const drop = tmp.drop;
|
||||
const quest = tmp.quest;
|
||||
|
||||
if (crit) {
|
||||
const critBonus = crit * 100 - 100;
|
||||
this.crit(critBonus);
|
||||
}
|
||||
|
||||
if (quest && user.party.quest && user.party.quest.key) {
|
||||
const userQuest = Content.quests[user.party.quest.key];
|
||||
if (quest.progressDelta && userQuest.boss) {
|
||||
this.quest('questDamage', quest.progressDelta.toFixed(1));
|
||||
} else if (quest.collection && userQuest.collect) {
|
||||
user.party.quest.progress.collectedItems++;
|
||||
this.quest('questCollection', quest.collection);
|
||||
}
|
||||
}
|
||||
|
||||
if (drop) {
|
||||
let text;
|
||||
let notes;
|
||||
let type;
|
||||
// TODO $rootScope.playSound('Item_Drop');
|
||||
|
||||
// Note: For Mystery Item gear, drop.type will be 'head', 'armor', etc
|
||||
// so we use drop.notificationType below.
|
||||
|
||||
if (drop.type !== 'gear' && drop.type !== 'Quest' && drop.notificationType !== 'Mystery') {
|
||||
if (drop.type === 'Food') {
|
||||
type = 'food';
|
||||
} else if (drop.type === 'HatchingPotion') {
|
||||
type = 'hatchingPotions';
|
||||
} else {
|
||||
type = `${drop.type.toLowerCase()}s`;
|
||||
}
|
||||
|
||||
if (!user.items[type][drop.key]) {
|
||||
Vue.set(user, `items.${type}.${drop.key}`, 0);
|
||||
}
|
||||
user.items[type][drop.key]++;
|
||||
}
|
||||
|
||||
if (drop.type === 'HatchingPotion') {
|
||||
text = Content.hatchingPotions[drop.key].text();
|
||||
notes = Content.hatchingPotions[drop.key].notes();
|
||||
this.drop(this.$t('messageDropPotion', {dropText: text, dropNotes: notes}), drop);
|
||||
} else if (drop.type === 'Egg') {
|
||||
text = Content.eggs[drop.key].text();
|
||||
notes = Content.eggs[drop.key].notes();
|
||||
this.drop(this.$t('messageDropEgg', {dropText: text, dropNotes: notes}), drop);
|
||||
} else if (drop.type === 'Food') {
|
||||
text = Content.food[drop.key].text();
|
||||
notes = Content.food[drop.key].notes();
|
||||
this.drop(this.$t('messageDropFood', {dropArticle: drop.article, dropText: text, dropNotes: notes}), drop);
|
||||
} else if (drop.type === 'Quest') {
|
||||
// TODO $rootScope.selectedQuest = Content.quests[drop.key];
|
||||
// $rootScope.openModal('questDrop', {controller:'PartyCtrl', size:'sm'});
|
||||
} else {
|
||||
// Keep support for another type of drops that might be added
|
||||
this.drop(drop.dialog);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 306 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
@@ -1,63 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="206.8 158.6 1132.2 280" style="enable-background:new 206.8 158.6 1132.2 280;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#30ABE9;}
|
||||
</style>
|
||||
<path class="st0" d="M500.9,182.9c-0.3-0.1-0.6-0.2-0.8-0.2H500c-1.3-0.3-2.5-0.6-3.7-0.9l0,0h-0.1l0,0l-0.3-0.1l-0.6-0.1l0,0l0,0
|
||||
l0,0h-0.1l0,0l0,0l0,0h-0.1l0,0l0,0l-0.5-0.1l0,0c-10.4-2.4-21.1-4.4-31.8-5.7c-11.1-1.4-22.5-2.3-33.8-2.5c-2.2,0-4.5-0.1-6.7-0.1
|
||||
c-7.1,0-14.2,0.2-21.2,0.7h-0.5l0.1,0.5c1.1,9.2-1.8,18.4-8,25.3c-5.4,6-13.1,9.8-21.1,10.4c-0.8,0.1-1.6,0.1-2.5,0.1
|
||||
c-8,0-15.7-3-21.6-8.4c-4.8-4.4-8.3-10.4-9.7-16.7l-0.1-0.5l-0.4,0.1c-10.6,3-21.2,6.5-31.5,10.6c-10,4-19.9,8.5-29.4,13.5
|
||||
c-4.8,2.5-9.5,5.1-14.1,7.8c-2.4,1.4-4.9,2.9-7.3,4.4c-0.1,0-0.2,0.1-0.4,0.2c-0.5,0.3-1.2,0.8-1.9,1.2c-1.3,0.8-1.5,0.9-1.3,1.3
|
||||
l27.3,60l0.2,0.4l0.4-0.2c9.8-5.7,20-10.9,30.3-15.5c0.7-0.3,1.3-0.6,2-0.9l21.4,89.2l0.1,0.6l0.5-0.3c5.7-3.1,10.4-5.4,15-7.3
|
||||
c5.7-2.3,11-4.2,16.1-5.6c9.5-2.7,19.2-4,29.1-4c1.5,0,3.1,0,4.6,0.1c4.7,0.2,10.7,0.7,16.3,2.9c2.6,1,4.6,2.2,6.1,3.7
|
||||
c1.7,1.7,2.6,4,2.5,6.5c0,5.2-4.1,9.4-7.4,12.1c-2.2,1.7-4.6,3.1-6.4,4.1c-2.3,1.3-4.8,2.4-7.3,3.4c-4.9,2-10.1,3.5-16,4.7
|
||||
c-5.8,1.2-11.5,1.9-16.9,2.1c-0.5,0-1,0-1.6,0c-0.7,0-1.3,0-2,0h-0.5c-1.4,0-2.8-0.1-4.2-0.3c-1.5-0.2-2.7-0.3-4-0.7h-0.1
|
||||
c-1.3-0.3-1.7-0.6-1.9-0.7c0.6-0.9,1.6-1.6,2.5-2.2c1-0.6,2.1-1.3,3.4-1.9c2.2-1.1,4.7-2.1,7.7-3c5.1-1.6,10.6-2.7,16.5-3.2
|
||||
c2.8-0.3,5.6-0.4,8.4-0.4c0.3,0,0.7,0,1,0c0.9,0,2.1,0,3.2,0.1c0.2,0,0.5,0,0.7,0.1c0.4,0,0.8,0.1,1.2,0.1h0.1h0.1
|
||||
c3-1,13.1-4.9,15.9-11.4l0.2-0.4l-0.4-0.2c-0.1-0.1-0.3-0.1-0.5-0.2c-0.1,0-0.1,0-0.2-0.1c-1.1-0.3-2.5-0.8-4-1.1
|
||||
c-2.6-0.6-5.4-1.1-8.4-1.5c-3.1-0.4-6.3-0.5-9.5-0.5c-2.6,0-5.2,0.1-7.8,0.4c-6.3,0.6-11.8,1.5-16.7,2.8c-6,1.5-11.1,3.4-15.5,5.8
|
||||
c-5.5,2.9-9.3,6.4-11.5,10.4c-2.4,4.4-2.5,9.6-0.3,13.7c2.1,4,6.3,6.8,12.3,8.4c4,1,8.5,1.6,13.7,1.6c0.9,0,1.9,0,2.9,0
|
||||
c5.4-0.2,11.1-0.8,16.9-1.9c5.6-1.1,11.1-2.5,16.3-4.3c5.7-2,10.7-4.2,15.1-6.7c0.7-0.4,1.2-0.7,1.7-1l1.3-0.8c0,0.2,0,0.4,0,0.6
|
||||
c0,0.6,0,1.1-0.2,1.8c-0.4,2.3-1.3,4.5-2.9,6.6c-2.5,3.4-6.3,6.3-11.6,9c-4.4,2.2-9.4,4.1-15.2,5.8c-5.3,1.5-10.9,2.7-16.4,3.5
|
||||
c-1.2,0.2-2.4,0.3-3.5,0.5l-0.7,0.1c-0.3,0-0.7,0.1-1,0.1c-0.3,0-0.8,0.1-0.8,0.1h-0.4v0.4l0.8,14.4v0.5h0.5l2.3-0.2
|
||||
c2.7-0.3,5.6-0.7,8.5-1.2c12.6-2.2,23-5.4,31.8-9.7c11.4-5.7,18.9-13,22.2-21.7c2-5.4,2.5-11.4,1.3-16.7c-0.3-1.3-0.7-2.6-1.2-3.8
|
||||
c-0.1-0.2-0.2-0.4-0.3-0.7c-0.2-0.3-0.4-0.7-0.4-1c-0.1-0.2,0.2-0.7,0.5-1c0.1-0.1,0.2-0.3,0.3-0.4c1.4-2.3,2.5-4.8,3.2-7.5
|
||||
c1.3-5.2,1-10.8-0.8-15.6c-1.8-4.7-5.2-8.8-9.9-11.8c-4.2-2.7-9.2-4.7-15.4-6c-5.2-1.1-10.7-1.6-16.9-1.6c-11.7,0-23.2,1.5-34,4.6
|
||||
c-5.6,1.6-11.4,3.6-18.4,6.4l-20.9-86.8l-0.1-0.5l-0.5,0.2c-10.6,4-21.1,8.5-31.3,13.6c-1.5,0.7-2.9,1.5-4.4,2.2l-16.3-35.7
|
||||
c0.3-0.2,0.7-0.4,1.4-0.8c0.1-0.1,0.2-0.1,0.2-0.1c4.7-2.7,9.5-5.3,14.3-7.8c9.6-4.9,19.5-9.3,29.6-13.2c4.9-1.9,9.9-3.6,14.9-5.3
|
||||
c2.1,3.6,4.7,6.8,7.7,9.7c6.3,6,14.1,10.1,22.6,11.9c3,0.6,6,0.9,9.1,0.9c5.6,0,11-1,16.1-2.9c7.5-2.8,14.2-7.6,19.3-13.8
|
||||
c2.6-3.1,4.7-6.5,6.4-10.1c0.8-1.8,1.6-3.7,2.2-5.7c0.3-1,0.6-2,0.8-3c0.1-0.5,0.2-1,0.3-1.4l0,0h0.2c0.4,0,0.8,0,1.2,0
|
||||
c2.3-0.1,4.6-0.1,6.9-0.1c9.1,0,18.3,0.4,27.3,1.2c11.3,1,22.6,2.7,33.7,4.9h0.2c1,0.2,1.6,0.3,1.9,0.4l-7.9,38.7
|
||||
c-0.9-0.1-3.2-0.4-4.9-0.7c-1.2-0.2-2.1-0.3-2.4-0.3c-2.8-0.4-5.7-0.7-8.6-0.9c-5.7-0.6-11.5-1-17.3-1.2c-2.9-0.1-5.8-0.2-8.7-0.2
|
||||
c-0.1,0-0.7,0-0.7,0h-0.4v0.4l-3.6,85.5c0,0.2,0.1,0.5,0.5,0.6c0,0,0,0,0.1,0c1.2,0.6,2.4,1.2,3.6,1.8c2.5,1.4,4.7,3,6.5,4.7
|
||||
c0.5,0.4,0.9,0.9,1.3,1.3c0.2,0.2,0.4,0.5,0.6,0.7c0.1,0.1,0.2,0.3,0.3,0.4l0.7,1.4l0.1-1.6l3.8-80.9c11.2,0.6,22.2,1.9,33.6,3.8
|
||||
c1.4,0.2,2.8,0.5,4.3,0.8l0.5,0.1c1.4,0.3,1.4,0.3,1.4,0.3h0.4l0.1-0.4l13.1-64.5C501.9,183.1,501.5,183,500.9,182.9z"/>
|
||||
<g>
|
||||
<path class="st0" d="M522.4,339.3v-53h-15.2V269h15.2v-25.1h20V269H561v17.3h-18.6v48.1c0,6.3,3,11,8.7,11c3.8,0,7.2-1.7,8.7-3.4
|
||||
l4.8,15.2c-3.6,3.2-9.5,5.9-18.6,5.9C530.4,363.1,522.4,354.7,522.4,339.3z"/>
|
||||
<path class="st0" d="M573.3,314.8c0-26.6,19.4-48.1,46.6-48.1c27.5,0,45,20.9,45,49.8v4.9h-70.7c1.5,13.7,11.8,25.3,29.1,25.3
|
||||
c9.1,0,19.6-3.6,26.2-10.3l9.1,13.1c-9.3,8.7-22.8,13.5-37.2,13.5C593.6,363.1,573.3,343.9,573.3,314.8z M619.7,283.1
|
||||
c-16.9,0-24.9,13.1-25.7,24.1h51.7C645.1,296.4,637.7,283.1,619.7,283.1z"/>
|
||||
<path class="st0" d="M679.1,314.8c0-26.6,19.4-48.1,46.6-48.1c27.5,0,45,20.9,45,49.8v4.9H700c1.5,13.7,11.8,25.3,29.1,25.3
|
||||
c9.1,0,19.6-3.6,26.2-10.3l9.1,13.1c-9.3,8.7-22.8,13.5-37.2,13.5C699.5,363.1,679.1,343.9,679.1,314.8z M725.5,283.1
|
||||
c-16.9,0-24.9,13.1-25.7,24.1h51.7C751,296.4,743.5,283.1,725.5,283.1z"/>
|
||||
<path class="st0" d="M782.7,348.6l9.1-14.2c6.5,6.6,19.2,12.7,31,12.7c12,0,18.2-4.9,18.2-12.2c0-18.1-55.5-5.1-55.5-40.5
|
||||
c0-15,12.9-27.7,36.1-27.7c15.6,0,27.4,5.5,35.5,12.7l-8.4,14.1c-5.5-6.1-15.6-11-27.2-11c-10.4,0-16.9,4.9-16.9,11.4
|
||||
c0,16.2,55.5,4,55.5,40.5c0,16.3-13.5,28.7-38.2,28.7C806.2,363.1,792.2,357.9,782.7,348.6z"/>
|
||||
<path class="st0" d="M900.1,348.1v47.7h-20V269h20v12.5c6.8-9.1,17.5-14.8,29.5-14.8c23.8,0,40.7,17.9,40.7,48.1
|
||||
s-16.9,48.3-40.7,48.3C918,363.1,907.7,357.8,900.1,348.1z M949.7,314.8c0-17.9-10.3-30.4-26-30.4c-9.3,0-19,5.3-23.6,12.2v36.3
|
||||
c4.4,6.8,14.3,12.5,23.6,12.5C939.4,345.4,949.7,332.7,949.7,314.8z"/>
|
||||
<path class="st0" d="M990.2,360.8V269h20v13.3c7-8.7,18.1-15.6,29.8-15.6v19.8c-1.7-0.4-3.6-0.6-6.1-0.6c-8.6,0-19.8,5.7-23.8,12.4
|
||||
v62.5H990.2z"/>
|
||||
<path class="st0" d="M1053.8,245.5c0-6.8,5.5-12.4,12.3-12.4c6.8,0,12.4,5.5,12.4,12.4c0,6.8-5.5,12.4-12.4,12.4
|
||||
S1053.8,252.3,1053.8,245.5z M1056.1,360.8V269h20v91.8H1056.1z"/>
|
||||
<path class="st0" d="M1164,360.8v-57.4c0-14.4-7.4-19-18.6-19c-10.1,0-18.8,6.1-23.6,12.2v64.2h-20V269h20v12.4
|
||||
c6.1-7.2,18.1-14.6,32.5-14.6c19.8,0,29.6,10.6,29.6,29.5v64.6L1164,360.8L1164,360.8z"/>
|
||||
<path class="st0" d="M1208.7,384.4l9.3-14.4c7.6,8.6,17.1,11.8,29.3,11.8c13.1,0,27.2-6.1,27.2-25.7v-10.5
|
||||
c-7,9.3-17.5,15.4-29.5,15.4c-23.4,0-40.7-16.9-40.7-47.1c0-29.8,16.9-47.1,40.7-47.1c11.6,0,22,5.1,29.5,15v-12.7h20v87
|
||||
c0,33.1-24.7,42-47.1,42C1231.6,398,1220.1,394.6,1208.7,384.4z M1274.4,331v-34.4c-4.6-6.7-14.2-12.2-23.6-12.2
|
||||
c-16,0-26,11.8-26,29.5c0,17.7,10.1,29.3,26,29.3C1260.1,343.1,1269.8,337.6,1274.4,331z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 394 KiB |
@@ -115,10 +115,14 @@ export async function save (store, editedTask) {
|
||||
if (originalTask) Object.assign(originalTask, editedTask);
|
||||
|
||||
const taskDataToSend = omit(editedTask, ['history']);
|
||||
const response = await axios.put(`/api/v3/tasks/${editedTask._id}`, taskDataToSend);
|
||||
const response = await axios.put(`/api/v3/tasks/${taskId}`, taskDataToSend);
|
||||
if (originalTask) Object.assign(originalTask, response.data.data);
|
||||
}
|
||||
|
||||
export async function scoreChecklistItem (store, {taskId, itemId}) {
|
||||
await axios.post(`/api/v3/tasks/${taskId}/checklist/${itemId}/score`);
|
||||
}
|
||||
|
||||
export async function destroy (store, task) {
|
||||
const list = store.state.tasks.data[`${task.type}s`];
|
||||
const taskIndex = list.findIndex(t => t._id === task._id);
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = function getLoginIncentives (api) {
|
||||
user.purchased.background.purple = true;
|
||||
user.purchased.background.red = true;
|
||||
user.purchased.background.yellow = true;
|
||||
user.markModified('purchased.background');
|
||||
if (user.markModified) user.markModified('purchased.background');
|
||||
},
|
||||
},
|
||||
3: {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import t from './translation';
|
||||
import each from 'lodash/each';
|
||||
import { NotAuthorized } from '../libs/errors';
|
||||
import statsComputed from '../libs/statsComputed';
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------
|
||||
Spells
|
||||
@@ -41,11 +43,11 @@ spells.wizard = {
|
||||
target: 'task',
|
||||
notes: t('spellWizardFireballNotes'),
|
||||
cast (user, target, req) {
|
||||
let bonus = user._statsComputed.int * user.fns.crit('per');
|
||||
let bonus = statsComputed(user).int * user.fns.crit('per');
|
||||
bonus *= Math.ceil((target.value < 0 ? 1 : target.value + 1) * 0.075);
|
||||
user.stats.exp += diminishingReturns(bonus, 75);
|
||||
if (!user.party.quest.progress.up) user.party.quest.progress.up = 0;
|
||||
user.party.quest.progress.up += Math.ceil(user._statsComputed.int * 0.1);
|
||||
user.party.quest.progress.up += Math.ceil(statsComputed(user).int * 0.1);
|
||||
user.fns.updateStats(user.stats, req);
|
||||
},
|
||||
},
|
||||
@@ -57,7 +59,7 @@ spells.wizard = {
|
||||
notes: t('spellWizardMPHealNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.int;
|
||||
let bonus = statsComputed(user).int;
|
||||
if (user._id !== member._id) {
|
||||
member.stats.mp += Math.ceil(diminishingReturns(bonus, 25, 125));
|
||||
}
|
||||
@@ -72,7 +74,7 @@ spells.wizard = {
|
||||
notes: t('spellWizardEarthNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.int - user.stats.buffs.int;
|
||||
let bonus = statsComputed(user).int - user.stats.buffs.int;
|
||||
if (!member.stats.buffs.int) member.stats.buffs.int = 0;
|
||||
member.stats.buffs.int += Math.ceil(diminishingReturns(bonus, 30, 200));
|
||||
});
|
||||
@@ -98,7 +100,7 @@ spells.warrior = {
|
||||
target: 'task',
|
||||
notes: t('spellWarriorSmashNotes'),
|
||||
cast (user, target) {
|
||||
let bonus = user._statsComputed.str * user.fns.crit('con');
|
||||
let bonus = statsComputed(user).str * user.fns.crit('con');
|
||||
target.value += diminishingReturns(bonus, 2.5, 35);
|
||||
if (!user.party.quest.progress.up) user.party.quest.progress.up = 0;
|
||||
user.party.quest.progress.up += diminishingReturns(bonus, 55, 70);
|
||||
@@ -111,7 +113,7 @@ spells.warrior = {
|
||||
target: 'self',
|
||||
notes: t('spellWarriorDefensiveStanceNotes'),
|
||||
cast (user) {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
let bonus = statsComputed(user).con - user.stats.buffs.con;
|
||||
if (!user.stats.buffs.con) user.stats.buffs.con = 0;
|
||||
user.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 40, 200));
|
||||
},
|
||||
@@ -124,7 +126,7 @@ spells.warrior = {
|
||||
notes: t('spellWarriorValorousPresenceNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.str - user.stats.buffs.str;
|
||||
let bonus = statsComputed(user).str - user.stats.buffs.str;
|
||||
if (!member.stats.buffs.str) member.stats.buffs.str = 0;
|
||||
member.stats.buffs.str += Math.ceil(diminishingReturns(bonus, 20, 200));
|
||||
});
|
||||
@@ -138,7 +140,7 @@ spells.warrior = {
|
||||
notes: t('spellWarriorIntimidateNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
let bonus = statsComputed(user).con - user.stats.buffs.con;
|
||||
if (!member.stats.buffs.con) member.stats.buffs.con = 0;
|
||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 24, 200));
|
||||
});
|
||||
@@ -154,7 +156,7 @@ spells.rogue = {
|
||||
target: 'task',
|
||||
notes: t('spellRoguePickPocketNotes'),
|
||||
cast (user, target) {
|
||||
let bonus = calculateBonus(target.value, user._statsComputed.per);
|
||||
let bonus = calculateBonus(target.value, statsComputed(user).per);
|
||||
user.stats.gp += diminishingReturns(bonus, 25, 75);
|
||||
},
|
||||
},
|
||||
@@ -166,7 +168,7 @@ spells.rogue = {
|
||||
notes: t('spellRogueBackStabNotes'),
|
||||
cast (user, target, req) {
|
||||
let _crit = user.fns.crit('str', 0.3);
|
||||
let bonus = calculateBonus(target.value, user._statsComputed.str, _crit);
|
||||
let bonus = calculateBonus(target.value, statsComputed(user).str, _crit);
|
||||
user.stats.exp += diminishingReturns(bonus, 75, 50);
|
||||
user.stats.gp += diminishingReturns(bonus, 18, 75);
|
||||
user.fns.updateStats(user.stats, req);
|
||||
@@ -180,7 +182,7 @@ spells.rogue = {
|
||||
notes: t('spellRogueToolsOfTradeNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.per - user.stats.buffs.per;
|
||||
let bonus = statsComputed(user).per - user.stats.buffs.per;
|
||||
if (!member.stats.buffs.per) member.stats.buffs.per = 0;
|
||||
member.stats.buffs.per += Math.ceil(diminishingReturns(bonus, 100, 50));
|
||||
});
|
||||
@@ -194,7 +196,7 @@ spells.rogue = {
|
||||
notes: t('spellRogueStealthNotes'),
|
||||
cast (user) {
|
||||
if (!user.stats.buffs.stealth) user.stats.buffs.stealth = 0;
|
||||
user.stats.buffs.stealth += Math.ceil(diminishingReturns(user._statsComputed.per, user.tasksOrder.dailys.length * 0.64, 55));
|
||||
user.stats.buffs.stealth += Math.ceil(diminishingReturns(statsComputed(user).per, user.tasksOrder.dailys.length * 0.64, 55));
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -207,7 +209,7 @@ spells.healer = {
|
||||
target: 'self',
|
||||
notes: t('spellHealerHealNotes'),
|
||||
cast (user) {
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * 0.075;
|
||||
user.stats.hp += (statsComputed(user).con + statsComputed(user).int + 5) * 0.075;
|
||||
if (user.stats.hp > 50) user.stats.hp = 50;
|
||||
},
|
||||
},
|
||||
@@ -220,7 +222,7 @@ spells.healer = {
|
||||
cast (user, tasks) {
|
||||
each(tasks, (task) => {
|
||||
if (task.type !== 'reward') {
|
||||
task.value += 4 * (user._statsComputed.int / (user._statsComputed.int + 40));
|
||||
task.value += 4 * (statsComputed(user).int / (statsComputed(user).int + 40));
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -233,7 +235,7 @@ spells.healer = {
|
||||
notes: t('spellHealerProtectAuraNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
let bonus = statsComputed(user).con - user.stats.buffs.con;
|
||||
if (!member.stats.buffs.con) member.stats.buffs.con = 0;
|
||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 200, 200));
|
||||
});
|
||||
@@ -247,7 +249,7 @@ spells.healer = {
|
||||
notes: t('spellHealerHealAllNotes'),
|
||||
cast (user, target) {
|
||||
each(target, (member) => {
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * 0.04;
|
||||
member.stats.hp += (statsComputed(user).con + statsComputed(user).int + 5) * 0.04;
|
||||
if (member.stats.hp > 50) member.stats.hp = 50;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import predictableRandom from './predictableRandom';
|
||||
import statsComputed from '../libs/statsComputed';
|
||||
|
||||
function crit (user, stat = 'str', chance = 0.03) {
|
||||
let s = user._statsComputed[stat];
|
||||
let s = statsComputed(user)[stat];
|
||||
if (predictableRandom(user) <= chance * (1 + s / 100)) {
|
||||
return 1.5 + 4 * s / (s + 200);
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,7 @@ import i18n from '../i18n';
|
||||
import { daysSince } from '../cron';
|
||||
import { diminishingReturns } from '../statHelpers';
|
||||
import randomVal from '../libs/randomVal';
|
||||
import statsComputed from '../libs/statsComputed';
|
||||
|
||||
// TODO This is only used on the server
|
||||
// move to user model as an instance method?
|
||||
@@ -36,7 +37,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
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 + statsComputed(user).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
|
||||
@@ -50,7 +51,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
user.party.quest.progress.collectedItems++;
|
||||
user._tmp.quest = user._tmp.quest || {};
|
||||
user._tmp.quest.collection = 1;
|
||||
user.markModified('party.quest.progress');
|
||||
if (user.markModified) user.markModified('party.quest.progress');
|
||||
}
|
||||
|
||||
if (user.purchased && user.purchased.plan && user.purchased.plan.customerId) {
|
||||
@@ -60,7 +61,7 @@ module.exports = function randomDrop (user, options, req = {}) {
|
||||
}
|
||||
|
||||
if (daysSince(user.items.lastDrop.date, user.preferences) === 0 &&
|
||||
user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level || 0))) {
|
||||
user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(statsComputed(user).per / 25) + (user.contributor.level || 0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ module.exports = function ultimateGear (user) {
|
||||
}, true);
|
||||
|
||||
if (user.achievements.ultimateGearSets[klass] === true) {
|
||||
user.addNotification('ULTIMATE_GEAR_ACHIEVEMENT');
|
||||
if (user.addNotification) user.addNotification('ULTIMATE_GEAR_ACHIEVEMENT');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -59,7 +59,7 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
|
||||
}
|
||||
if (!user.flags.dropsEnabled && user.stats.lvl >= 3) {
|
||||
user.flags.dropsEnabled = true;
|
||||
user.addNotification('DROPS_ENABLED');
|
||||
if (user.addNotification) user.addNotification('DROPS_ENABLED');
|
||||
|
||||
if (user.items.eggs.Wolf > 0) {
|
||||
user.items.eggs.Wolf++;
|
||||
@@ -78,7 +78,7 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
|
||||
if (!user.items.quests[k])
|
||||
user.items.quests[k] = 0;
|
||||
user.items.quests[k]++;
|
||||
user.markModified('flags.levelDrops');
|
||||
if (user.markModified) user.markModified('flags.levelDrops');
|
||||
if (analytics) {
|
||||
analytics.track('acquire item', {
|
||||
uuid: user._id,
|
||||
@@ -95,7 +95,7 @@ module.exports = function updateStats (user, stats, req = {}, analytics) {
|
||||
}
|
||||
});
|
||||
if (!user.flags.rebirthEnabled && user.stats.lvl >= 50) {
|
||||
user.addNotification('REBIRTH_ENABLED');
|
||||
if (user.addNotification) user.addNotification('REBIRTH_ENABLED');
|
||||
user.flags.rebirthEnabled = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ module.exports = function blockUser (user, req = {}) {
|
||||
user.inbox.blocks.splice(i, 1);
|
||||
}
|
||||
|
||||
user.markModified('inbox.blocks');
|
||||
if (user.markModified) user.markModified('inbox.blocks');
|
||||
return [
|
||||
user.inbox.blocks,
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module.exports = function clearPMs (user) {
|
||||
user.inbox.messages = {};
|
||||
user.markModified('inbox.messages');
|
||||
if (user.markModified) user.markModified('inbox.messages');
|
||||
return [
|
||||
user.inbox.messages,
|
||||
];
|
||||
|
||||
@@ -2,7 +2,7 @@ import get from 'lodash/get';
|
||||
|
||||
module.exports = function deletePM (user, req = {}) {
|
||||
delete user.inbox.messages[get(req, 'params.id')];
|
||||
user.markModified(`inbox.messages.${req.params.id}`);
|
||||
if (user.markModified) user.markModified(`inbox.messages.${req.params.id}`);
|
||||
return [
|
||||
user.inbox.messages,
|
||||
];
|
||||
|
||||
@@ -27,7 +27,7 @@ module.exports = function deleteTag (user, req = {}) {
|
||||
});
|
||||
|
||||
each(['habits', 'dailys', 'todos', 'rewards'], (type) => {
|
||||
user.markModified(type);
|
||||
if (user.markModified) user.markModified(type);
|
||||
});
|
||||
|
||||
return user.tags;
|
||||
|
||||
@@ -15,7 +15,7 @@ module.exports = function openMysteryItem (user, req = {}, analytics) {
|
||||
item = cloneDeep(content.gear.flat[item]);
|
||||
user.items.gear.owned[item.key] = true;
|
||||
|
||||
user.markModified('purchased.plan.mysteryItems');
|
||||
if (user.markModified) user.markModified('purchased.plan.mysteryItems');
|
||||
|
||||
if (analytics) {
|
||||
analytics.track('open mystery item', {
|
||||
|
||||
@@ -93,7 +93,7 @@ module.exports = function rebirth (user, tasks = [], req = {}, analytics) {
|
||||
user.achievements.rebirthLevel = lvl;
|
||||
}
|
||||
|
||||
user.addNotification('REBIRTH_ACHIEVEMENT');
|
||||
if (user.addNotification) user.addNotification('REBIRTH_ACHIEVEMENT');
|
||||
|
||||
user.stats.buffs = {};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
import i18n from '../i18n';
|
||||
import updateStats from '../fns/updateStats';
|
||||
import crit from '../fns/crit';
|
||||
import statsComputed from '../libs/statsComputed';
|
||||
|
||||
const MAX_TASK_VALUE = 21.27;
|
||||
const MIN_TASK_VALUE = -47.27;
|
||||
@@ -86,7 +87,7 @@ function _gainMP (user, val) {
|
||||
val *= user._tmp.crit || 1;
|
||||
user.stats.mp += val;
|
||||
|
||||
if (user.stats.mp >= user._statsComputed.maxMP) user.stats.mp = user._statsComputed.maxMP;
|
||||
if (user.stats.mp >= statsComputed(user).maxMP) user.stats.mp = statsComputed(user).maxMP;
|
||||
if (user.stats.mp < 0) {
|
||||
user.stats.mp = 0;
|
||||
}
|
||||
@@ -96,7 +97,7 @@ function _gainMP (user, val) {
|
||||
// ===== CONSTITUTION =====
|
||||
// TODO Decreases HP loss from bad habits / missed dailies by 0.5% per point.
|
||||
function _subtractPoints (user, task, stats, delta) {
|
||||
let conBonus = 1 - user._statsComputed.con / 250;
|
||||
let conBonus = 1 - statsComputed(user).con / 250;
|
||||
if (conBonus < 0.1) conBonus = 0.1;
|
||||
|
||||
let hpMod = delta * conBonus * task.priority * 2; // constant 2 multiplier for better results
|
||||
@@ -110,13 +111,13 @@ function _addPoints (user, task, stats, direction, delta) {
|
||||
// Exp Modifier
|
||||
// ===== Intelligence =====
|
||||
// TODO Increases Experience gain by .2% per point.
|
||||
let intBonus = 1 + user._statsComputed.int * 0.025;
|
||||
let intBonus = 1 + statsComputed(user).int * 0.025;
|
||||
stats.exp += Math.round(delta * intBonus * task.priority * _crit * 6);
|
||||
|
||||
// GP modifier
|
||||
// ===== PERCEPTION =====
|
||||
// TODO Increases Gold gained from tasks by .3% per point.
|
||||
let perBonus = 1 + user._statsComputed.per * 0.02;
|
||||
let perBonus = 1 + statsComputed(user).per * 0.02;
|
||||
let gpMod = delta * task.priority * _crit * perBonus;
|
||||
|
||||
if (task.streak) {
|
||||
@@ -157,9 +158,9 @@ function _changeTaskValue (user, task, direction, times, cron) {
|
||||
let prevProgress = user.party.quest.progress.up;
|
||||
|
||||
if (task.type === 'todo' || task.type === 'daily') {
|
||||
user.party.quest.progress.up += nextDelta * _crit * (1 + user._statsComputed.str / 200);
|
||||
user.party.quest.progress.up += nextDelta * _crit * (1 + statsComputed(user).str / 200);
|
||||
} else if (task.type === 'habit') {
|
||||
user.party.quest.progress.up += nextDelta * _crit * (0.5 + user._statsComputed.str / 400);
|
||||
user.party.quest.progress.up += nextDelta * _crit * (0.5 + statsComputed(user).str / 400);
|
||||
}
|
||||
|
||||
if (!user._tmp.quest) user._tmp.quest = {};
|
||||
@@ -209,7 +210,7 @@ module.exports = function scoreTask (options = {}, req = {}) {
|
||||
} else {
|
||||
_subtractPoints(user, task, stats, delta);
|
||||
}
|
||||
_gainMP(user, max([0.25, 0.0025 * user._statsComputed.maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
_gainMP(user, max([0.25, 0.0025 * statsComputed(user).maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
|
||||
task.history = task.history || [];
|
||||
|
||||
@@ -232,14 +233,14 @@ module.exports = function scoreTask (options = {}, req = {}) {
|
||||
delta += _changeTaskValue(user, task, direction, times, cron);
|
||||
if (direction === 'down') delta = _calculateDelta(task, direction, cron); // recalculate delta for unchecking so the gp and exp come out correctly
|
||||
_addPoints(user, task, stats, direction, delta); // obviously for delta>0, but also a trick to undo accidental checkboxes
|
||||
_gainMP(user, max([1, 0.01 * user._statsComputed.maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
_gainMP(user, max([1, 0.01 * statsComputed(user).maxMP]) * (direction === 'down' ? -1 : 1));
|
||||
|
||||
if (direction === 'up') {
|
||||
task.streak += 1;
|
||||
// Give a streak achievement when the streak is a multiple of 21
|
||||
if (task.streak % 21 === 0) {
|
||||
user.achievements.streak = user.achievements.streak ? user.achievements.streak + 1 : 1;
|
||||
user.addNotification('STREAK_ACHIEVEMENT');
|
||||
if (user.addNotification) user.addNotification('STREAK_ACHIEVEMENT');
|
||||
}
|
||||
task.completed = true;
|
||||
} else if (direction === 'down') {
|
||||
@@ -267,7 +268,7 @@ module.exports = function scoreTask (options = {}, req = {}) {
|
||||
|
||||
// MP++ per checklist item in ToDo, bonus per CLI
|
||||
let multiplier = max([reduce(task.checklist, (m, i) => m + (i.completed ? 1 : 0), 1), 1]);
|
||||
_gainMP(user, max([multiplier, 0.01 * user._statsComputed.maxMP * multiplier]) * (direction === 'down' ? -1 : 1));
|
||||
_gainMP(user, max([multiplier, 0.01 * statsComputed(user).maxMP * multiplier]) * (direction === 'down' ? -1 : 1));
|
||||
}
|
||||
} else if (task.type === 'reward') {
|
||||
// Don't adjust values for rewards
|
||||
|
||||
@@ -93,7 +93,7 @@ module.exports = function unlock (user, req = {}, analytics) {
|
||||
|
||||
if (!alreadyOwns) {
|
||||
if (path.indexOf('gear.') === -1) {
|
||||
user.markModified('purchased');
|
||||
if (user.markModified) user.markModified('purchased');
|
||||
}
|
||||
|
||||
user.balance -= cost;
|
||||
|
||||