import Vue from 'vue'; import scoreTask from '@/../../common/script/ops/scoreTask'; import notifications from './notifications'; import { mapState } from '@/libs/store'; import * as Analytics from '@/libs/analytics'; import { CONSTANTS, getLocalSetting, setLocalSetting } from '@/libs/userlocalManager'; export default { mixins: [notifications], computed: { ...mapState({ castingSpell: 'spellOptions.castingSpell', user: 'user.data', }), }, methods: { async beforeTaskScore () { return (!this.castingSpell); }, playTaskScoreSound (task, direction) { switch (task.type) { // eslint-disable-line default-case case 'habit': this.$root.$emit('playSound', direction === 'up' ? 'Plus_Habit' : 'Minus_Habit'); break; case 'todo': this.$root.$emit('playSound', 'Todo'); break; case 'daily': this.$root.$emit('playSound', 'Daily'); break; case 'reward': this.$root.$emit('playSound', 'Reward'); break; } }, async taskScore (task, direction) { const { user } = this; const canScoreTask = await this.beforeTaskScore(task); if (!canScoreTask) return; try { scoreTask({ task, user, direction }); } catch (err) { this.text(err.message); return; } this.playTaskScoreSound(task, direction); const response = await this.$store.dispatch('tasks:score', { taskId: task._id, direction, }); this.handleTaskScoreNotifications(response.data.data._tmp || {}); const tasksScoredCount = getLocalSetting(CONSTANTS.keyConstants.TASKS_SCORED_COUNT); if (!tasksScoredCount || tasksScoredCount < 2) { Analytics.track({ eventName: 'task scored', eventAction: 'task scored', eventCategory: 'behavior', hitType: 'event', uuid: user._id, taskType: task.type, direction, }, { trackOnClient: true }); if (!tasksScoredCount) { setLocalSetting(CONSTANTS.keyConstants.TASKS_SCORED_COUNT, 1); } else { setLocalSetting(CONSTANTS.keyConstants.TASKS_SCORED_COUNT, Number(tasksScoredCount) + 1); } } }, async handleTaskScoreNotifications (tmpObject = {}) { const { user } = this; const Content = this.$store.state.content; // _tmp is used to notify drops, critical hits and other bonuses const { crit, drop, firstDrops, quest, } = tmpObject; 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.damage(quest.progressDelta.toFixed(1)); } else if (quest.collection && userQuest.collect) { user.party.quest.progress.collectedItems += 1; this.quest('questCollection', quest.collection); } } if (firstDrops) { if (!user.items.eggs[firstDrops.egg]) Vue.set(user.items.eggs, firstDrops.egg, 0); if (!user.items.hatchingPotions[firstDrops.hatchingPotion]) { Vue.set(user.items.hatchingPotions, firstDrops.hatchingPotion, 0); } user.items.eggs[firstDrops.egg] += 1; user.items.hatchingPotions[firstDrops.hatchingPotion] += 1; } if (drop) { let dropText; let dropNotes; let type; this.$root.$emit('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] += 1; } if (drop.type === 'HatchingPotion') { dropText = Content.hatchingPotions[drop.key].text(); dropNotes = Content.hatchingPotions[drop.key].notes(); this.drop(this.$t('messageDropPotion', { dropText, dropNotes }), drop); } else if (drop.type === 'Egg') { dropText = Content.eggs[drop.key].text(); dropNotes = Content.eggs[drop.key].notes(); this.drop(this.$t('messageDropEgg', { dropText, dropNotes }), drop); } else if (drop.type === 'Food') { dropText = Content.food[drop.key].textA(); dropNotes = Content.food[drop.key].notes(); this.drop(this.$t('messageDropFood', { dropText, dropNotes }), drop); } else if (drop.type === 'Quest') { // TODO $rootScope.selectedQuest = Content.quests[drop.key]; // $rootScope.openModal('questDrop', {controller:'PartyCtrl', size:'sm'}); // NOTE if a modal is shown again for quest drops // this code will likely need changes, see the NOTE // https://github.com/HabitRPG/habitica/blob/develop/website/client/src/components/notifications.vue#L640-L646 } else { // Keep support for another type of drops that might be added this.drop(drop.dialog); } } }, }, };