diff --git a/test/common/fns/randomDrop.test.js b/test/common/fns/randomDrop.test.js index b53faffe9e..9ef30ca267 100644 --- a/test/common/fns/randomDrop.test.js +++ b/test/common/fns/randomDrop.test.js @@ -29,8 +29,10 @@ describe('common.fns.randomDrop', () => { }; randomDrop(user, { task, predictableRandom }); expect(user.party.quest.progress.collectedItems).to.eql(1); + expect(user._tmp.quest.collection).to.eql(1); randomDrop(user, { task, predictableRandom }); expect(user.party.quest.progress.collectedItems).to.eql(2); + expect(user._tmp.quest.collection).to.eql(1); }); context('drops enabled', () => { @@ -42,7 +44,7 @@ describe('common.fns.randomDrop', () => { it('does nothing if user.items.lastDrop.count is exceeded', () => { user.items.lastDrop.count = 100; randomDrop(user, { task, predictableRandom }); - expect(user._tmp).to.eql({}); + expect(user._tmp.drop).to.be.undefined; }); it('drops something when the task is a todo', () => { diff --git a/test/common/ops/scoreTask.test.js b/test/common/ops/scoreTask.test.js index fe6bb0037b..572c261d96 100644 --- a/test/common/ops/scoreTask.test.js +++ b/test/common/ops/scoreTask.test.js @@ -142,6 +142,21 @@ describe('shared.ops.scoreTask', () => { expect(ref.beforeUser._id).to.eql(ref.afterUser._id); }); + it('and increments quest progress', () => { + expect(ref.afterUser.party.quest.progress.up).to.eql(0); + ref.afterUser.party.quest.key = 'gryphon'; + + scoreTask({ user: ref.afterUser, task: habit, direction: 'up', cron: false }); + let firstTaskDelta = ref.afterUser.party.quest.progress.up; + expect(firstTaskDelta).to.be.greaterThan(0); + expect(ref.afterUser._tmp.quest.progressDelta).to.eql(firstTaskDelta); + + scoreTask({ user: ref.afterUser, task: habit, direction: 'up', cron: false }); + let secondTaskDelta = ref.afterUser.party.quest.progress.up - firstTaskDelta; + expect(secondTaskDelta).to.be.greaterThan(0); + expect(ref.afterUser._tmp.quest.progressDelta).to.eql(secondTaskDelta); + }); + context('habits', () => { it('up', () => { options = { user: ref.afterUser, task: habit, direction: 'up', times: 5, cron: false }; diff --git a/website/client-old/js/controllers/rootCtrl.js b/website/client-old/js/controllers/rootCtrl.js index 422c730369..3645a2c0e4 100644 --- a/website/client-old/js/controllers/rootCtrl.js +++ b/website/client-old/js/controllers/rootCtrl.js @@ -326,6 +326,24 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ } } + function _questProgress() { + var user = $scope.user; + if (user.party.quest) { + var userQuest = Content.quests[user.party.quest.key]; + + if (!userQuest) { + return 0; + } + if (userQuest.boss && user.party.quest.progress.up > 0) { + return user.party.quest.progress.up; + } + if (userQuest.collect && user.party.quest.progress.collectedItems > 0) { + return user.party.quest.progress.collectedItems; + } + } + return 0; + } + /* ------------------------ Spells @@ -365,6 +383,8 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ } $scope.castEnd = function(target, type, $event){ + var beforeQuestProgress = _questProgress(); + if (!$rootScope.applyingAction) return 'No applying action'; $event && ($event.stopPropagation(),$event.preventDefault()); @@ -383,12 +403,22 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ $http.post(spellUrl) .success(function(){ // TODO response will always include the modified data, no need to sync! var msg = window.env.t('youCast', {spell: spell.text()}); + switch (type) { case 'task': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.text});break; case 'user': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.profile.name});break; case 'party': msg = window.env.t('youCastParty', {spell: spell.text()});break; } Notification.markdown(msg); + var questProgress = _questProgress() - beforeQuestProgress; + if (questProgress > 0) { + var userQuest = Content.quests[user.party.quest.key]; + if (userQuest.boss) { + Notification.quest('questDamage', questProgress.toFixed(1)); + } else if (quest.collection && userQuest.collect) { + Notification.quest('questCollection', questProgress); + } + } User.sync(); }); } diff --git a/website/client-old/js/services/notificationServices.js b/website/client-old/js/services/notificationServices.js index 3730910cef..a4864a1da8 100644 --- a/website/client-old/js/services/notificationServices.js +++ b/website/client-old/js/services/notificationServices.js @@ -56,6 +56,10 @@ angular.module("habitrpg").factory("Notification", _notify(val, 'drop', dropClass); } + function quest(type, val) { + _notify(window.env.t(type, { val: val }), 'success'); + } + function exp(val) { if (val < -50) return; // don't show when they level up (resetting their exp) _notify(_sign(val) + " " + _round(val) + " " + window.env.t('experience'), 'xp', 'glyphicon glyphicon-star'); @@ -147,6 +151,7 @@ angular.module("habitrpg").factory("Notification", markdown: markdown, mp: mp, streak: streak, - text: text + text: text, + quest: quest }; }]); diff --git a/website/client-old/js/services/userServices.js b/website/client-old/js/services/userServices.js index 1e36196bef..e306e0f3b9 100644 --- a/website/client-old/js/services/userServices.js +++ b/website/client-old/js/services/userServices.js @@ -247,11 +247,22 @@ angular.module('habitrpg') var tmp = res.data.data._tmp || {}; // used to notify drops, critical hits and other bonuses var crit = tmp.crit; var drop = tmp.drop; + var quest = tmp.quest; if (crit) { var critBonus = crit * 100 - 100; Notification.crit(critBonus); } + + if (quest && user.party.quest) { + var userQuest = Content.quests[user.party.quest.key]; + if (quest.progressDelta && userQuest.boss) { + Notification.quest('questDamage', quest.progressDelta.toFixed(1)); + } else if (quest.collection && userQuest.collect) { + Notification.quest('questCollection', quest.collection); + } + } + if (drop) { var text, notes, type; $rootScope.playSound('Item_Drop'); diff --git a/website/common/locales/en/quests.json b/website/common/locales/en/quests.json index ea8751c887..a0b41bf2cb 100644 --- a/website/common/locales/en/quests.json +++ b/website/common/locales/en/quests.json @@ -26,6 +26,8 @@ "pending": "Pending", "questStart": "Once all members have either accepted or rejected, the quest begins. Only those that clicked \"accept\" will be able to participate in the quest and receive the drops. If members are pending too long (inactive?), the quest owner can start the quest without them by clicking \"Begin\". The quest owner can also cancel the quest and regain the quest scroll by clicking \"Cancel\".", "questStartBroken": "Once all members have either accepted or rejected, the quest begins... Only those that clicked \"accept\" will be able to participate in the quest and receive the drops... If members are pending too long (inactive?), the quest owner can start the quest without them by clicking \"Begin\"... The quest owner can also cancel the quest and regain the quest scroll by clicking \"Cancel\"...", + "questCollection": "+<%= val %> quest item(s) found", + "questDamage": "+<%= val %> damage to boss", "begin": "Begin", "bossHP": "Boss Health", "bossStrength": "Boss Strength", diff --git a/website/common/script/fns/randomDrop.js b/website/common/script/fns/randomDrop.js index 658fceef4e..83bb585668 100644 --- a/website/common/script/fns/randomDrop.js +++ b/website/common/script/fns/randomDrop.js @@ -39,6 +39,8 @@ module.exports = function randomDrop (user, options, req = {}) { if (predictableRandom(user, user.stats.gp) < chance) { if (!user.party.quest.progress.collectedItems) user.party.quest.progress.collectedItems = 0; user.party.quest.progress.collectedItems++; + if (!user._tmp.quest) user._tmp.quest = {}; + user._tmp.quest.collection = 1; user.markModified('party.quest.progress'); } diff --git a/website/common/script/ops/scoreTask.js b/website/common/script/ops/scoreTask.js index 42751d7c84..b0a973314c 100644 --- a/website/common/script/ops/scoreTask.js +++ b/website/common/script/ops/scoreTask.js @@ -150,14 +150,17 @@ function _changeTaskValue (user, task, direction, times, cron) { if (direction === 'up') { // Make progress on quest based on STR user.party.quest.progress.up = user.party.quest.progress.up || 0; + let prevProgress = user.party.quest.progress.up; if (task.type === 'todo' || task.type === 'daily') { user.party.quest.progress.up += nextDelta * (1 + user._statsComputed.str / 200); } else if (task.type === 'habit') { user.party.quest.progress.up += nextDelta * (0.5 + user._statsComputed.str / 400); } - } + if (!user._tmp.quest) user._tmp.quest = {}; + user._tmp.quest.progressDelta = user.party.quest.progress.up - prevProgress; + } task.value += nextDelta; }