From 78d49895441d3e88bcf12e76095a81d96f671bd6 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Wed, 8 Jul 2015 16:13:23 -0500 Subject: [PATCH 1/2] WIP(event): Summer Splash cont'd Splits Quests out to a new page. Refactors inventory Jade files and controllers to more manageable structures. --- common/locales/en/npc.json | 1 + common/locales/en/quests.json | 9 +- common/script/content.coffee | 58 +++++++-- test/common/algos.mocha.coffee | 1 + website/public/css/inventory.styl | 2 +- website/public/js/app.js | 4 + website/public/js/controllers/headerCtrl.js | 20 +-- .../public/js/controllers/inventoryCtrl.js | 61 ++------- website/public/js/services/groupServices.js | 18 ++- website/public/js/services/questServices.js | 95 ++++++++++++++ website/public/manifest.json | 1 + .../views/options/inventory/equipment.jade | 30 +++++ website/views/options/inventory/index.jade | 7 ++ .../views/options/inventory/inventory.jade | 116 ------------------ website/views/options/inventory/quests.jade | 38 ++++++ .../options/inventory/seasonal-shop.jade | 36 ++++++ .../options/inventory/time-travelers.jade | 29 +++++ website/views/shared/header/menu.jade | 4 + 18 files changed, 333 insertions(+), 197 deletions(-) create mode 100644 website/public/js/services/questServices.js create mode 100644 website/views/options/inventory/equipment.jade create mode 100644 website/views/options/inventory/quests.jade create mode 100644 website/views/options/inventory/seasonal-shop.jade create mode 100644 website/views/options/inventory/time-travelers.jade diff --git a/common/locales/en/npc.json b/common/locales/en/npc.json index e1daafb192..c387207ea1 100644 --- a/common/locales/en/npc.json +++ b/common/locales/en/npc.json @@ -14,6 +14,7 @@ "sellPotionForGold": "Sell <%= itemType %> Potion for <%= gold %> Gold", "buyGems": "Buy Gems", "justin": "Justin", + "ian": "Ian", "USD": "USD", "newStuff": "New Stuff", "cool": "Tell Me Later", diff --git a/common/locales/en/quests.json b/common/locales/en/quests.json index 256ff78642..a5cdfaf5eb 100644 --- a/common/locales/en/quests.json +++ b/common/locales/en/quests.json @@ -1,6 +1,11 @@ { "quests": "Quests", "quest": "quest", + "yourQuests": "Your Quests", + "questsForSale": "Quests for Sale", + "petQuests": "Pet and Mount Quests", + "unlockableQuests": "Unlockable Quests", + "goldQuests": "Gold-Purchasable Quests", "questDetails": "Quest Details", "invitations": "Invitations", "completed": "Completed!", @@ -37,11 +42,13 @@ "noScrolls": "You don't have any quest scrolls.", "scrollsText1": "Quests require parties. If you want to quest solo,", "scrollsText2": "create an empty party", - "scrollsPre": "You need to complete the previous quest to start this one!", + "scrollsPre": "You haven't unlocked this quest yet!", "completedQuests": "Completed the following quests", "mustComplete": "You must first complete <%= quest %>.", "mustLevel": "You must be level <%= level %>.", "mustLvlQuest": "You must be level <%= level %> to buy this quest!", + "mustInviteFriend": "To earn this Quest, invite a friend to your Party. Invite someone now?", + "unlockByQuesting": "To earn this Quest, complete <%= title %>.", "sureCancel": "Are you sure you want to cancel this quest? All invitation acceptances will be lost. The quest owner will retain possession of the quest scroll.", "sureAbort": "Are you sure you want to abort this mission? It will abort it for everyone in your party and all progress will be lost. The quest scroll will be returned to the quest owner.", "doubleSureAbort": "Are you double sure? Make sure they won't hate you forever!", diff --git a/common/script/content.coffee b/common/script/content.coffee index b7a3a6c38c..315b3f0136 100644 --- a/common/script/content.coffee +++ b/common/script/content.coffee @@ -1094,6 +1094,7 @@ api.quests = completion: t("questDilatoryCompletion") value: 0 canBuy: false + category: 'world' boss: name: t("questDilatoryBoss") # We ran an average of progress{up,down} on users over 5 days: {up:805025,down:1324423}. /5*30 (we want the @@ -1136,6 +1137,7 @@ api.quests = completionChat: t("questStressbeastCompletionChat") value: 0 canBuy: false + category: 'world' boss: name: t("questStressbeastBoss") hp: 2750000 @@ -1179,7 +1181,7 @@ api.quests = notes: t('questEvilSantaNotes') completion: t('questEvilSantaCompletion') value: 4 # Gem cost to buy, GP sell-back - #mechanic: enum['perfectDailies', ...] + category: 'pet' boss: name: t('questEvilSantaBoss') # name of the boss himself (eg, Vice) hp: 300 @@ -1198,6 +1200,7 @@ api.quests = completion: t('questEvilSanta2Completion') value: 4 previous: 'evilsanta' + category: 'pet' collect: tracks: text: t('questEvilSanta2CollectTracks'), count: 20 branches: text: t('questEvilSanta2CollectBranches'), count: 10 @@ -1213,6 +1216,7 @@ api.quests = notes: t('questGryphonNotes') completion: t('questGryphonCompletion') value: 4 # Gem cost to buy, GP sell-back + category: 'pet' boss: name: t('questGryphonBoss') # name of the boss himself (eg, Vice) hp: 300 @@ -1232,6 +1236,7 @@ api.quests = notes: t('questHedgehogNotes') completion: t('questHedgehogCompletion') value: 4 # Gem cost to buy, GP sell-back + category: 'pet' boss: name: t('questHedgehogBoss') # name of the boss himself (eg, Vice) hp: 400 @@ -1251,6 +1256,7 @@ api.quests = notes: t('questGhostStagNotes') completion: t('questGhostStagCompletion') value: 4 + category: 'pet' boss: name: t('questGhostStagBoss') hp: 1200 @@ -1270,6 +1276,7 @@ api.quests = notes: t('questVice1Notes') value: 4 lvl: 30 + category: 'unlockable' boss: name: t('questVice1Boss') hp: 750 @@ -1285,7 +1292,8 @@ api.quests = text: t('questVice2Text') notes: t('questVice2Notes') value: 4 - lvl: 35 + lvl: 30 + category: 'unlockable' previous: 'vice1' collect: lightCrystal: text: t('questVice2CollectLightCrystal'), count: 45 @@ -1302,7 +1310,8 @@ api.quests = completion: t('questVice3Completion') previous: 'vice2' value: 4 - lvl: 40 + lvl: 30 + category: 'unlockable' boss: name: t('questVice3Boss') hp: 1500 @@ -1324,6 +1333,7 @@ api.quests = completion: t('questEggHuntCompletion') value: 1 canBuy: false + category: 'pet' collect: plainEgg: text: t('questEggHuntCollectPlainEgg'), count: 100 drop: @@ -1347,6 +1357,7 @@ api.quests = notes: t('questRatNotes') completion: t('questRatCompletion') value: 4 + category: 'pet' boss: name: t('questRatBoss') hp: 1200 @@ -1366,6 +1377,7 @@ api.quests = notes: t('questOctopusNotes') completion: t('questOctopusCompletion') value: 4 + category: 'pet' boss: name: t('questOctopusBoss') hp: 1200 @@ -1385,6 +1397,7 @@ api.quests = notes: t('questSeahorseNotes') completion: t('questSeahorseCompletion') value: 4 + category: 'pet' boss: name: t('questSeahorseBoss') hp: 300 @@ -1404,6 +1417,7 @@ api.quests = notes: t('questAtom1Notes') value: 4 lvl: 15 + category: 'unlockable' collect: soapBars: text: t('questAtom1CollectSoapBars'), count: 20 drop: @@ -1418,6 +1432,7 @@ api.quests = previous: 'atom1' value: 4 lvl: 15 + category: 'unlockable' boss: name: t('questAtom2Boss') hp: 300 @@ -1435,6 +1450,7 @@ api.quests = completion: t('questAtom3Completion') value: 4 lvl: 15 + category: 'unlockable' boss: name: t('questAtom3Boss') hp: 800 @@ -1453,6 +1469,7 @@ api.quests = notes: t('questHarpyNotes') completion: t('questHarpyCompletion') value: 4 + category: 'pet' boss: name: t('questHarpyBoss') hp: 600 @@ -1472,6 +1489,7 @@ api.quests = notes: t('questRoosterNotes') completion: t('questRoosterCompletion') value: 4 + category: 'pet' boss: name: t('questRoosterBoss') hp: 300 @@ -1491,6 +1509,7 @@ api.quests = notes: t('questSpiderNotes') completion: t('questSpiderCompletion') value: 4 + category: 'pet' boss: name: t('questSpiderBoss') hp: 400 @@ -1510,6 +1529,7 @@ api.quests = notes: t('questMoonstone1Notes') value: 4 lvl: 60 + category: 'unlockable' collect: moonstone: text: t('questMoonstone1CollectMoonstone'), count: 500 drop: @@ -1522,8 +1542,9 @@ api.quests = text: t('questMoonstone2Text') notes: t('questMoonstone2Notes') value: 4 - lvl: 65 + lvl: 60 previous: 'moonstone1' + category: 'unlockable' boss: name: t('questMoonstone2Boss') hp: 1500 @@ -1540,7 +1561,8 @@ api.quests = completion: t('questMoonstone3Completion') previous: 'moonstone2' value: 4 - lvl: 70 + lvl: 60 + category: 'unlockable' boss: name: t('questMoonstone3Boss') hp: 2000 @@ -1565,6 +1587,7 @@ api.quests = notes: t('questGoldenknight1Notes') value: 4 lvl: 40 + category: 'unlockable' collect: testimony: text: t('questGoldenknight1CollectTestimony'), count: 300 drop: @@ -1578,7 +1601,8 @@ api.quests = notes: t('questGoldenknight2Notes') value: 4 previous: 'goldenknight1' - lvl: 45 + lvl: 40 + category: 'unlockable' boss: name: t('questGoldenknight2Boss') hp: 1000 @@ -1595,7 +1619,8 @@ api.quests = completion: t('questGoldenknight3Completion') previous: 'goldenknight2' value: 4 - lvl: 50 + lvl: 40 + category: 'unlockable' boss: name: t('questGoldenknight3Boss') hp: 1700 @@ -1616,8 +1641,10 @@ api.quests = text: t('questBasilistText') notes: t('questBasilistNotes') completion: t('questBasilistCompletion') - canBuy: false - value: 4 + category: 'unlockable' + unlockCondition: + condition: 'party invite' + text: t('inviteFriends') boss: name: t('questBasilistBoss') hp: 100 @@ -1631,6 +1658,7 @@ api.quests = notes: t('questOwlNotes') completion: t('questOwlCompletion') value: 4 + category: 'pet' boss: name: t('questOwlBoss') hp: 500 @@ -1650,6 +1678,7 @@ api.quests = notes: t('questPenguinNotes') completion: t('questPenguinCompletion') value: 4 + category: 'pet' boss: name: t('questPenguinBoss') hp: 400 @@ -1669,6 +1698,7 @@ api.quests = notes: t('questTRexNotes') completion: t('questTRexCompletion') value: 4 + category: 'pet' boss: name: t('questTRexBoss') hp: 800 @@ -1688,6 +1718,7 @@ api.quests = notes: t('questTRexUndeadNotes') completion: t('questTRexUndeadCompletion') value: 4 + category: 'pet' boss: name: t('questTRexUndeadBoss') hp: 500 @@ -1713,6 +1744,7 @@ api.quests = notes: t('questRockNotes') completion: t('questRockCompletion') value: 4 + category: 'pet' boss: name: t('questRockBoss') hp: 400 @@ -1732,6 +1764,7 @@ api.quests = notes: t('questBunnyNotes') completion: t('questBunnyCompletion') value: 4 + category: 'pet' boss: name: t('questBunnyBoss') hp: 300 @@ -1751,6 +1784,7 @@ api.quests = notes: t('questSlimeNotes') completion: t('questSlimeCompletion') value: 4 + category: 'pet' boss: name: t('questSlimeBoss') hp: 400 @@ -1770,6 +1804,7 @@ api.quests = notes: t('questSheepNotes') completion: t('questSheepCompletion') value: 4 + category: 'pet' boss: name: t('questSheepBoss') hp: 300 @@ -1789,6 +1824,7 @@ api.quests = notes: t('questKrakenNotes') completion: t('questKrakenCompletion') value: 4 + category: 'pet' boss: name: t('questKrakenBoss') hp: 800 @@ -1811,6 +1847,10 @@ _.each api.quests, (v,key) -> if b.rage _.defaults b.rage, {title:t('bossRageTitle'),description:t('bossRageDescription')} +api.questsByLevel = + _.sortBy api.quests, (quest) -> + quest.lvl || 0 + api.backgrounds = backgrounds062014: beach: diff --git a/test/common/algos.mocha.coffee b/test/common/algos.mocha.coffee index 64bda3ccf4..49205fe84a 100644 --- a/test/common/algos.mocha.coffee +++ b/test/common/algos.mocha.coffee @@ -574,6 +574,7 @@ describe 'User', -> expect(quest.value).to.be.greaterThan 0 if quest.canBuy expect(quest.drop.gp).to.not.be.lessThan 0 expect(quest.drop.exp).to.not.be.lessThan 0 + expect(quest.category).to.match('pet|unlockable|gold|world') if quest.drop.items expect(quest.drop.items).to.be.an(Array) if quest.boss diff --git a/website/public/css/inventory.styl b/website/public/css/inventory.styl index bcd297268d..8e86e70f5b 100644 --- a/website/public/css/inventory.styl +++ b/website/public/css/inventory.styl @@ -74,8 +74,8 @@ menu.pets div padding:.3em width:6em margin-top:1em + text-align:center p - text-align:center //width:6em margin-top:-.3em .hatchingPotion-menu > div diff --git a/website/public/js/app.js b/website/public/js/app.js index 36e25702d7..d0caf41c2b 100644 --- a/website/public/js/app.js +++ b/website/public/js/app.js @@ -193,6 +193,10 @@ window.habitrpg = angular.module('habitrpg', url: '/drops', templateUrl: "partials/options.inventory.drops.html" }) + .state('options.inventory.quests', { + url: '/quests', + templateUrl: "partials/options.inventory.quests.html" + }) .state('options.inventory.pets', { url: '/pets', templateUrl: "partials/options.inventory.pets.html" diff --git a/website/public/js/controllers/headerCtrl.js b/website/public/js/controllers/headerCtrl.js index 474e5446f5..68000da3b9 100644 --- a/website/public/js/controllers/headerCtrl.js +++ b/website/public/js/controllers/headerCtrl.js @@ -1,11 +1,13 @@ "use strict"; -habitrpg.controller("HeaderCtrl", ['$scope', 'Groups', 'User', '$location', '$rootScope', 'Analytics', - function($scope, Groups, User, $location, $rootScope, Analytics) { +habitrpg.controller("HeaderCtrl", ['$scope', 'Groups', 'User', + function($scope, Groups, User) { $scope.Math = window.Math; $scope.user = User.user; + $scope.inviteOrStartParty = Groups.inviteOrStartParty; + $scope.party = Groups.party(function(){ var triggerResort = function() { $scope.partyMinusSelf = resortParty(); @@ -16,20 +18,6 @@ habitrpg.controller("HeaderCtrl", ['$scope', 'Groups', 'User', '$location', '$ro $scope.$watch('user.party.orderAscending', triggerResort); }); - $scope.inviteOrStartParty = function(group) { - if (group.type === "party") { - $rootScope.openModal('invite-friends', { - controller:'InviteToGroupCtrl', - resolve: { - injectedGroup: function(){ return group; } - } - }); - } else { - Analytics.track({'hitType':'event','eventCategory':'button','eventAction':'click','eventLabel':'Invite Friends'}); - $location.path("/options/groups/party"); - } - } - function resortParty() { var result = _.sortBy( _.filter($scope.party.members, function(member){ diff --git a/website/public/js/controllers/inventoryCtrl.js b/website/public/js/controllers/inventoryCtrl.js index afd85b625b..4bc97cbc42 100644 --- a/website/public/js/controllers/inventoryCtrl.js +++ b/website/public/js/controllers/inventoryCtrl.js @@ -1,6 +1,6 @@ habitrpg.controller("InventoryCtrl", - ['$rootScope', '$scope', 'Shared', '$window', 'User', 'Content', 'Analytics', - function($rootScope, $scope, Shared, $window, User, Content, Analytics) { + ['$rootScope', '$scope', 'Shared', '$window', 'User', 'Content', 'Analytics', 'Quests', + function($rootScope, $scope, Shared, $window, User, Content, Analytics, Quests) { var user = User.user; @@ -11,6 +11,13 @@ habitrpg.controller("InventoryCtrl", $scope.totalPets = _.size(Content.dropEggs) * _.size(Content.hatchingPotions); $scope.totalMounts = _.size(Content.dropEggs) * _.size(Content.hatchingPotions); + // Functions from Quests service + $scope.lockQuest = Quests.lockQuest; + $scope.buyQuest = Quests.buyQuest; + $scope.questPopover = Quests.questPopover; + $scope.showQuest = Quests.showQuest; + $scope.closeQuest = Quests.closeQuest; + // count egg, food, hatchingPotion stack totals var countStacks = function(items) { return _.reduce(items,function(m,v){return m+v;},0);} @@ -139,46 +146,6 @@ habitrpg.controller("InventoryCtrl", User.user.ops.equip({params:{type: 'mount', key: egg + '-' + potion}}); } - $scope.questPopover = function(quest) { - // The popover gets parsed as markdown (hence the double \n for line breaks - var text = ''; - if(quest.boss) { - text += '**' + window.env.t('bossHP') + ':** ' + quest.boss.hp + '\n\n'; - text += '**' + window.env.t('bossStrength') + ':** ' + quest.boss.str + '\n\n'; - } else if(quest.collect) { - var count = 0; - for (var key in quest.collect) { - text += '**' + window.env.t('collect') + ':** ' + quest.collect[key].count + ' ' + quest.collect[key].text() + '\n\n'; - } - } - text += '---\n\n'; - text += '**' + window.env.t('rewards') + ':**\n\n'; - if(quest.drop.items) { - for (var item in quest.drop.items) { - text += quest.drop.items[item].text() + '\n\n'; - } - } - if(quest.drop.exp) - text += quest.drop.exp + ' ' + window.env.t('experience') + '\n\n'; - if(quest.drop.gp) - text += quest.drop.gp + ' ' + window.env.t('gold') + '\n\n'; - - return text; - } - - $scope.showQuest = function(quest) { - var item = Content.quests[quest]; - var completedPrevious = !item.previous || (User.user.achievements.quests && User.user.achievements.quests[item.previous]); - if (!completedPrevious) - return alert(window.env.t('mustComplete', {quest: $rootScope.Content.quests[item.previous].text()})); - if (item.lvl && item.lvl > user.stats.lvl) - return alert(window.env.t('mustLevel', {level: item.lvl})); - $rootScope.selectedQuest = item; - $rootScope.openModal('showQuest', {controller:'InventoryCtrl'}); - } - $scope.closeQuest = function(){ - $rootScope.selectedQuest = undefined; - } $scope.questInit = function(){ Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'quest','owner':true,'response':'accept','questName':$scope.selectedQuest.key}); $rootScope.party.$questAccept({key:$scope.selectedQuest.key}, function(){ @@ -186,16 +153,6 @@ habitrpg.controller("InventoryCtrl", }); $scope.closeQuest(); } - $scope.buyQuest = function(quest) { - var item = Content.quests[quest]; - if (item.lvl && item.lvl > user.stats.lvl) - return alert(window.env.t('mustLvlQuest', {level: item.lvl})); - var completedPrevious = !item.previous || (User.user.achievements.quests && User.user.achievements.quests[item.previous]); - if (!completedPrevious) - return $scope.purchase("quests", item); - $rootScope.selectedQuest = item; - $rootScope.openModal('buyQuest', {controller:'InventoryCtrl'}); - } $scope.getSeasonalShopArray = function(set){ var flatGearArray = _.toArray(Content.gear.flat); diff --git a/website/public/js/services/groupServices.js b/website/public/js/services/groupServices.js index 368c675123..6235cb9f5a 100644 --- a/website/public/js/services/groupServices.js +++ b/website/public/js/services/groupServices.js @@ -5,8 +5,8 @@ */ angular.module('habitrpg').factory('Groups', -['ApiUrl', '$resource', '$q', '$http', 'User', 'Challenges', -function(ApiUrl, $resource, $q, $http, User, Challenges) { +['$rootScope','ApiUrl', '$resource', '$q', '$http', 'User', 'Challenges', 'Analytics', '$location', +function($rootScope, ApiUrl, $resource, $q, $http, User, Challenges, Analytics, $location) { var Group = $resource(ApiUrl.get() + '/api/v2/groups/:gid', {gid:'@_id', messageId: '@_messageId'}, { @@ -83,6 +83,20 @@ function(ApiUrl, $resource, $q, $http, User, Challenges) { .then(syncUser, logError); }, + inviteOrStartParty: function(group) { + if (group.type === "party") { + $rootScope.openModal('invite-friends', { + controller:'InviteToGroupCtrl', + resolve: { + injectedGroup: function(){ return group; } + } + }); + } else { + Analytics.track({'hitType':'event','eventCategory':'button','eventAction':'click','eventLabel':'Invite Friends'}); + $location.path("/options/groups/party"); + } + }, + // Pass reference to party, myGuilds, publicGuilds, tavern; inside data in order to // be able to modify them directly (otherwise will be stick with cached version) data: data, diff --git a/website/public/js/services/questServices.js b/website/public/js/services/questServices.js new file mode 100644 index 0000000000..1ca6995c38 --- /dev/null +++ b/website/public/js/services/questServices.js @@ -0,0 +1,95 @@ +/** + * Created by Sabe on 7/7/2015. + */ +(function(){ + angular + .module('habitrpg') + .factory('Quests', questsFactory); + + questsFactory.$inject = [ + '$rootScope', + 'Content', + 'Groups', + 'User' + ]; + + function questsFactory($rootScope,Content,Groups,User) { + + var user = User.user; + + function lockQuest(quest,ignoreLevel) { + if (!ignoreLevel){ + if (quest.lvl && user.stats.lvl < quest.lvl) return true; + } + if (user.achievements.quests) return (quest.previous && !user.achievements.quests[quest.previous]); + return (quest.previous); + } + + function buyQuest(quest) { + var item = Content.quests[quest]; + + if (item.unlockCondition && item.unlockCondition.condition === 'party invite') { + if (!confirm(window.env.t('mustInviteFriend'))) return; + return Groups.inviteOrStartParty(Groups.party()); + } + if (item.previous && (!User.user.achievements.quests || (User.user.achievements.quests && !User.user.achievements.quests[item.previous]))){ + return alert(window.env.t('unlockByQuesting', {title: Content.quests[item.previous].text()})); + } + if (item.lvl && item.lvl > user.stats.lvl) { + return alert(window.env.t('mustLvlQuest', {level: item.lvl})); + } + $rootScope.selectedQuest = item; + $rootScope.openModal('buyQuest', {controller:'InventoryCtrl'}); + } + + function questPopover(quest) { + // The popover gets parsed as markdown (hence the double \n for line breaks + var text = ''; + if(quest.boss) { + text += '**' + window.env.t('bossHP') + ':** ' + quest.boss.hp + '\n\n'; + text += '**' + window.env.t('bossStrength') + ':** ' + quest.boss.str + '\n\n'; + } else if(quest.collect) { + var count = 0; + for (var key in quest.collect) { + text += '**' + window.env.t('collect') + ':** ' + quest.collect[key].count + ' ' + quest.collect[key].text() + '\n\n'; + } + } + text += '---\n\n'; + text += '**' + window.env.t('rewards') + ':**\n\n'; + if(quest.drop.items) { + for (var item in quest.drop.items) { + text += quest.drop.items[item].text() + '\n\n'; + } + } + if(quest.drop.exp) + text += quest.drop.exp + ' ' + window.env.t('experience') + '\n\n'; + if(quest.drop.gp) + text += quest.drop.gp + ' ' + window.env.t('gold') + '\n\n'; + + return text; + } + + function showQuest(quest) { + var item = Content.quests[quest]; + var completedPrevious = !item.previous || (User.user.achievements.quests && User.user.achievements.quests[item.previous]); + if (!completedPrevious) + return alert(window.env.t('mustComplete', {quest: $rootScope.Content.quests[item.previous].text()})); + if (item.lvl && item.lvl > user.stats.lvl) + return alert(window.env.t('mustLevel', {level: item.lvl})); + $rootScope.selectedQuest = item; + $rootScope.openModal('showQuest', {controller:'InventoryCtrl'}); + } + + function closeQuest(){ + $rootScope.selectedQuest = undefined; + } + + return { + lockQuest: lockQuest, + buyQuest: buyQuest, + questPopover: questPopover, + showQuest: showQuest, + closeQuest: closeQuest + } + } +}()); diff --git a/website/public/manifest.json b/website/public/manifest.json index da32d2cfa4..029b618a94 100644 --- a/website/public/manifest.json +++ b/website/public/manifest.json @@ -51,6 +51,7 @@ "js/services/taskServices.js", "js/services/challengeServices.js", "js/services/paymentServices.js", + "js/services/questServices.js", "js/filters/money.js", "js/filters/roundLargeNumbers.js", diff --git a/website/views/options/inventory/equipment.jade b/website/views/options/inventory/equipment.jade new file mode 100644 index 0000000000..7d696462c4 --- /dev/null +++ b/website/views/options/inventory/equipment.jade @@ -0,0 +1,30 @@ +script(type='text/ng-template', id='partials/options.inventory.equipment.html') + .container-fluid + .row + .col-md-6.border-right + h3.equipment-title.hint(popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', popover=env.t('battleGearText'))=env.t('battleGear') + div + button.btn.btn-default(type="button", ng-click='dequip("battleGear");') {{env.t("unequipBattleGear")}} + li.customize-menu.inventory-gear + menu.pets-menu(label='{{::label}}', ng-repeat='(klass,label) in {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer"), special:env.t("special"), mystery:env.t("mystery"), armoire:env.t("armoireText")}', ng-show='gear[klass]') + div(ng-repeat='item in gear[klass]') + button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='user.ops.equip({params:{key:item.key}})', class='shop_{{::item.key}}', ng-class='{selectableInventory: user.items.gear.equipped[item.type] == item.key}') + .col-md-6 + h3.equipment-title.hint(popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', popover=env.t('costumeText'))=env.t('costume') + .checkbox.equipment-title + label + input(type="checkbox", ng-model="user.preferences.costume", ng-change='set({"preferences.costume":user.preferences.costume ? true : false})') + |  + =env.t('useCostume') + div + button.btn.btn-default(type="button", ng-click='dequip("costume");') {{env.t("unequipCostume")}} + button.btn.btn-default(type="button", ng-click='dequip("petMountBackground");') {{env.t("unequipPetMountBackground")}} + li.customize-menu(ng-if='!user.preferences.costume') + .well.use-costume-info + p=env.t('useCostumeInfo1') + p(ng-if='showUseCostumeInfo')!=env.t('useCostumeInfo2') + p: a(ng-click='showUseCostumeInfo = !showUseCostumeInfo') {{!showUseCostumeInfo ? env.t('showMoreMore') : env.t('showMoreLess')}} + li.customize-menu(ng-if='user.preferences.costume') + menu.pets-menu(label='{{::label}}', ng-repeat='(klass,label) in {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer"), special:env.t("special"), mystery:env.t("mystery"), armoire:env.t("armoireText")}', ng-show='gear[klass]') + div(ng-repeat='item in gear[klass]') + button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='user.ops.equip({params:{type:"costume", key:item.key}})', class='shop_{{::item.key}}', ng-class='{selectableInventory: user.items.gear.costume[item.type] == item.key}') \ No newline at end of file diff --git a/website/views/options/inventory/index.jade b/website/views/options/inventory/index.jade index 63959b1708..95e601f3d2 100644 --- a/website/views/options/inventory/index.jade +++ b/website/views/options/inventory/index.jade @@ -1,11 +1,18 @@ +include ./equipment include ./inventory +include ./quests +include ./seasonal-shop include ./stable +include ./time-travelers script(type='text/ng-template', id='partials/options.inventory.html') ul.options-menu li(ng-class="{ active: $state.includes('options.inventory.drops') }") a(ui-sref='options.inventory.drops') =env.t('market') + li(ng-class="{ active: $state.includes('options.inventory.quests') }") + a(ui-sref='options.inventory.quests') + =env.t('quests') li(ng-class="{ active: $state.includes('options.inventory.pets') }") a(ui-sref='options.inventory.pets') =env.t('pets') diff --git a/website/views/options/inventory/inventory.jade b/website/views/options/inventory/inventory.jade index bd841970d2..a69f0cb5b5 100644 --- a/website/views/options/inventory/inventory.jade +++ b/website/views/options/inventory/inventory.jade @@ -1,101 +1,3 @@ -script(type='text/ng-template', id='partials/options.inventory.equipment.html') - .container-fluid - .row - .col-md-6.border-right - h3.equipment-title.hint(popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', popover=env.t('battleGearText'))=env.t('battleGear') - div - button.btn.btn-default(type="button", ng-click='dequip("battleGear");') {{env.t("unequipBattleGear")}} - li.customize-menu.inventory-gear - menu.pets-menu(label='{{::label}}', ng-repeat='(klass,label) in {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer"), special:env.t("special"), mystery:env.t("mystery"), armoire:env.t("armoireText")}', ng-show='gear[klass]') - div(ng-repeat='item in gear[klass]') - button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='user.ops.equip({params:{key:item.key}})', class='shop_{{::item.key}}', ng-class='{selectableInventory: user.items.gear.equipped[item.type] == item.key}') - .col-md-6 - h3.equipment-title.hint(popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', popover=env.t('costumeText'))=env.t('costume') - .checkbox.equipment-title - label - input(type="checkbox", ng-model="user.preferences.costume", ng-change='set({"preferences.costume":user.preferences.costume ? true : false})') - |  - =env.t('useCostume') - div - button.btn.btn-default(type="button", ng-click='dequip("costume");') {{env.t("unequipCostume")}} - button.btn.btn-default(type="button", ng-click='dequip("petMountBackground");') {{env.t("unequipPetMountBackground")}} - li.customize-menu(ng-if='!user.preferences.costume') - .well.use-costume-info - p=env.t('useCostumeInfo1') - p(ng-if='showUseCostumeInfo')!=env.t('useCostumeInfo2') - p: a(ng-click='showUseCostumeInfo = !showUseCostumeInfo') {{!showUseCostumeInfo ? env.t('showMoreMore') : env.t('showMoreLess')}} - li.customize-menu(ng-if='user.preferences.costume') - menu.pets-menu(label='{{::label}}', ng-repeat='(klass,label) in {warrior:env.t("warrior"), wizard:env.t("mage"), rogue:env.t("rogue"), healer:env.t("healer"), special:env.t("special"), mystery:env.t("mystery"), armoire:env.t("armoireText")}', ng-show='gear[klass]') - div(ng-repeat='item in gear[klass]') - button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='user.ops.equip({params:{type:"costume", key:item.key}})', class='shop_{{::item.key}}', ng-class='{selectableInventory: user.items.gear.costume[item.type] == item.key}') - -script(type='text/ng-template', id='partials/options.inventory.seasonalshop.html') - .container-fluid - .stable.row - .col-md-2 - .seasonalshop_summer2015 - .col-md-10 - .popover.static-popover.fade.right.in - .arrow - h3.popover-title!=env.t('seasonalShopTitle', {linkStart:"", linkEnd: ""}) - .popover-content - p!=env.t('seasonalShopSummerText') - .well(ng-if='User.user.achievements.rebirths > 0')=env.t('seasonalShopRebirth') - li.customize-menu.inventory-gear - menu.pets-menu(label='{{::label}}', ng-repeat='(set,label) in ::{summerWarrior:env.t("daringSwashbucklerSet"), summerMage:env.t("emeraldMermageSet"), summerHealer:env.t("reefSeahealerSet"), summerRogue:env.t("roguishPirateSet")}') - div(ng-repeat='item in ::getSeasonalShopArray(set)' ng-class="{transparent: user.items.gear.owned[item.key] === true ||user.items.gear.owned[item.key] === false}") - button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='purchase(item.type,item)', class='shop_{{::item.key}}') - .text-left - | {{((item.specialClass == "wizard") && (item.type == "weapon")) + 1}}  - span.Pet_Currency_Gem1x.inline-gems - // menu.pets-menu(label=env.t('quests')) - div(ng-repeat='quest in ::getSeasonalShopQuests()') - button.customize-option(data-popover-html="{{::quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-append-to-body='true', popover-title='{{::quest.text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='buyQuest(quest.key)', ng-class='(quest.previous && !user.achievements.quests[quest.previous]) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"') - p - | {{::quest.value}}  - span.Pet_Currency_Gem1x.inline-gems - menu.pets-menu(label=env.t('seasonalItems')) - div - button.customize-option(popover='{{::Content.spells.special.seafoam.notes()}}', popover-title='{{::Content.spells.special.seafoam.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='purchase("special", Content.spells.special.seafoam)', class='shop_seafoam') - p - | {{::Content.spells.special.seafoam.value}} - span(class='shop_gold') - // div - button.customize-option(popover='{{::Content.spells.special.nye.notes()}}', popover-title='{{::Content.spells.special.nye.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='castStart(Content.spells.special.nye)', class='inventory_special_nye') - p - | {{Content.spells.special.nye.value}} - span(class='shop_gold') - -script(type='text/ng-template', id='partials/options.inventory.timetravelers.html') - .container-fluid - .stable.row(ng-if='user.purchased.plan.consecutive.trinkets <= 0') - .col-md-2 - .npc_timetravelers - .col-md-10 - .popover.static-popover.fade.right.in - .arrow - h3.popover-title!=env.t('timeTravelersTitleNoSub', {linkStartTyler: "", linkStartVicky: "", linkEnd: ""}) - .popover-content - p!=env.t('timeTravelersPopoverNoSub', {linkStart: "", linkEnd: ""}) - .row.stable(ng-if='user.purchased.plan.consecutive.trinkets > 0') - .col-md-2 - .npc_timetravelers_active - .col-md-10 - .popover.static-popover.fade.right.in - .arrow - h3.popover-title=env.t('timeTravelersTitle') - .popover-content - .pull-right - span.inventory_special_trinket.inline-gems - b x{{user.purchased.plan.consecutive.trinkets}} - p!=env.t('timeTravelersPopover', {linkStart: "", linkEnd: ""}) - - .col-md-12 - li.customize-menu.inventory-gear - menu.pets-menu(label='{{::set.text}}', ng-repeat='set in Content.timeTravelerStore(user.items.gear.owned)') - div(ng-repeat='item in set.items') - button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='user.ops.buyMysterySet({params:{key:set.key}})', class='shop_{{::item.key}}') - script(type='text/ng-template', id='partials/options.inventory.drops.html') .container-fluid .row @@ -120,14 +22,6 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html') button.customize-option(popover='{{::Content.hatchingPotions[pot].notes()}}', popover-title!=env.t("potion", {potionType: "{{::Content.hatchingPotions[pot].text()}}"}), popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='choosePotion(pot)', class='Pet_HatchingPotion_{{::pot}}', ng-class='{selectableInventory: selectedEgg && !(user.items.pets[selectedEgg.key+"-"+pot]>0)}') .badge.badge-info.stack-count {{points}} - li.customize-menu - menu.pets-menu(label=(env.t('quests') + ' ({{questCount}})')) - p.muted(ng-show='questCount < 1')=env.t('noScrolls') - p.muted!=env.t('scrollsText1') + ' ' + env.t('scrollsText2') + '' - div(ng-repeat='(quest_key,points) in ownedItems(user.items.quests)', ng-init='quest = Content.quests[quest_key]') - button.customize-option(data-popover-html="{{:: quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-title='{{::quest.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='showQuest(quest_key)', ng-class='(quest.previous && !user.achievements.quests[quest.previous]) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"') - .badge.badge-info.stack-count {{points}} - li.customize-menu menu.pets-menu(label=env.t('food') + ' ({{foodCount}})') p.muted(ng-show='foodCount < 1')=env.t('noFood') @@ -135,7 +29,6 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html') button.customize-option(popover='{{::Content.food[food].notes()}}', popover-title='{{::Content.food[food].text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='chooseFood(food)', class='Pet_Food_{{::food}}') .badge.badge-info.stack-count {{points}} - li.customize-menu menu.pets-menu(label=env.t('special')) mixin specialItem(k) @@ -221,15 +114,6 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html') | {{::food.value}}  span.Pet_Currency_Gem1x.inline-gems - li.customize-menu - menu.pets-menu(label=env.t('quests')) - p.muted!=env.t('scrollsText1') + ' ' + env.t('scrollsText2') + '' - div(ng-repeat='quest in Content.quests', ng-if='quest.canBuy') - button.customize-option(data-popover-html="{{::quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-title='{{::quest.text()}}', popover-append-to-body="true", popover-trigger='mouseenter', ng-click='buyQuest(quest.key)', ng-class='(quest.previous && !user.achievements.quests[quest.previous]) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"') - p - | {{::quest.value}}  - span.Pet_Currency_Gem1x.inline-gems - li.customize-menu menu.pets-menu(label=env.t('special')) div diff --git a/website/views/options/inventory/quests.jade b/website/views/options/inventory/quests.jade new file mode 100644 index 0000000000..40e73b796d --- /dev/null +++ b/website/views/options/inventory/quests.jade @@ -0,0 +1,38 @@ +// Created by Sabe on 7/6/2015. +script(type='text/ng-template', id='partials/options.inventory.quests.html') + .container-fluid + .row + .col-md-2 + .npc_ian + .col-md-10 + .popover.static-popover.fade.right.in + .arrow + h3.popover-title=env.t('ian') + .popover-content + p.muted!=env.t('scrollsText1') + ' ' + env.t('scrollsText2') + '.' + .row + - var questCategories = {'unlockable':'unlockableQuests','pet':'petQuests','gold':'goldQuests'} + .col-md-6 + h3.equipment-title=env.t('yourQuests') + menu.inventory-list + li.customize-menu + p.muted(ng-show='questCount < 1')=env.t('noScrolls') + each caption,type in questCategories + menu.pets-menu(label=env.t(caption)) + div(ng-repeat='(quest_key,points) in ownedItems(user.items.quests)', ng-init='quest = Content.quests[quest_key]', ng-if='Content.quests[quest_key].category === "#{type}"') + button.customize-option(data-popover-html="{{::lockQuest(quest) ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-title='{{::quest.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='showQuest(quest_key)', ng-class='lockQuest(quest) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"') + .badge.badge-info.stack-count {{points}} + .col-md-6.border-left + li.customize-menu + h3.equipment-title=env.t('questsForSale') + each caption,type in questCategories + menu.pets-menu(label=env.t(caption)) + div(ng-repeat='quest in Content.questsByLevel', ng-if='quest.canBuy && quest.category === "#{type}"') + button.customize-option(data-popover-html="{{::lockQuest(quest,true) ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-title='{{::quest.text()}}', popover-append-to-body="true", popover-trigger='mouseenter', ng-click='buyQuest(quest.key)', ng-class='lockQuest(quest) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"') + p(ng-if='quest.unlockCondition') + | {{::quest.unlockCondition.text()}} + p(ng-if='quest.value && !lockQuest(quest)') + | {{::quest.value}}  + span.Pet_Currency_Gem1x.inline-gems + p(ng-if='quest.lvl && lockQuest(quest)')=env.t('level') + | {{::quest.lvl}} \ No newline at end of file diff --git a/website/views/options/inventory/seasonal-shop.jade b/website/views/options/inventory/seasonal-shop.jade new file mode 100644 index 0000000000..9bbfd02cff --- /dev/null +++ b/website/views/options/inventory/seasonal-shop.jade @@ -0,0 +1,36 @@ +script(type='text/ng-template', id='partials/options.inventory.seasonalshop.html') + .container-fluid + .stable.row + .col-md-2 + .seasonalshop_summer2015 + .col-md-10 + .popover.static-popover.fade.right.in + .arrow + h3.popover-title!=env.t('seasonalShopTitle', {linkStart:"", linkEnd: ""}) + .popover-content + p!=env.t('seasonalShopSummerText') + .well(ng-if='User.user.achievements.rebirths > 0')=env.t('seasonalShopRebirth') + li.customize-menu.inventory-gear + menu.pets-menu(label='{{::label}}', ng-repeat='(set,label) in ::{summerWarrior:env.t("daringSwashbucklerSet"), summerMage:env.t("emeraldMermageSet"), summerHealer:env.t("reefSeahealerSet"), summerRogue:env.t("roguishPirateSet")}') + div(ng-repeat='item in ::getSeasonalShopArray(set)' ng-class="{transparent: user.items.gear.owned[item.key] === true ||user.items.gear.owned[item.key] === false}") + button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='purchase(item.type,item)', class='shop_{{::item.key}}') + .text-left + | {{((item.specialClass == "wizard") && (item.type == "weapon")) + 1}}  + span.Pet_Currency_Gem1x.inline-gems + // menu.pets-menu(label=env.t('quests')) + div(ng-repeat='quest in ::getSeasonalShopQuests()') + button.customize-option(data-popover-html="{{::quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-append-to-body='true', popover-title='{{::quest.text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='buyQuest(quest.key)', ng-class='(quest.previous && !user.achievements.quests[quest.previous]) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"') + p + | {{::quest.value}}  + span.Pet_Currency_Gem1x.inline-gems + menu.pets-menu(label=env.t('seasonalItems')) + div + button.customize-option(popover='{{::Content.spells.special.seafoam.notes()}}', popover-title='{{::Content.spells.special.seafoam.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='purchase("special", Content.spells.special.seafoam)', class='shop_seafoam') + p + | {{::Content.spells.special.seafoam.value}} + span(class='shop_gold') + // div + button.customize-option(popover='{{::Content.spells.special.nye.notes()}}', popover-title='{{::Content.spells.special.nye.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='castStart(Content.spells.special.nye)', class='inventory_special_nye') + p + | {{Content.spells.special.nye.value}} + span(class='shop_gold') \ No newline at end of file diff --git a/website/views/options/inventory/time-travelers.jade b/website/views/options/inventory/time-travelers.jade new file mode 100644 index 0000000000..f9d419a13b --- /dev/null +++ b/website/views/options/inventory/time-travelers.jade @@ -0,0 +1,29 @@ +script(type='text/ng-template', id='partials/options.inventory.timetravelers.html') + .container-fluid + .stable.row(ng-if='user.purchased.plan.consecutive.trinkets <= 0') + .col-md-2 + .npc_timetravelers + .col-md-10 + .popover.static-popover.fade.right.in + .arrow + h3.popover-title!=env.t('timeTravelersTitleNoSub', {linkStartTyler: "", linkStartVicky: "", linkEnd: ""}) + .popover-content + p!=env.t('timeTravelersPopoverNoSub', {linkStart: "", linkEnd: ""}) + .row.stable(ng-if='user.purchased.plan.consecutive.trinkets > 0') + .col-md-2 + .npc_timetravelers_active + .col-md-10 + .popover.static-popover.fade.right.in + .arrow + h3.popover-title=env.t('timeTravelersTitle') + .popover-content + .pull-right + span.inventory_special_trinket.inline-gems + b x{{user.purchased.plan.consecutive.trinkets}} + p!=env.t('timeTravelersPopover', {linkStart: "", linkEnd: ""}) + + .col-md-12 + li.customize-menu.inventory-gear + menu.pets-menu(label='{{::set.text}}', ng-repeat='set in Content.timeTravelerStore(user.items.gear.owned)') + div(ng-repeat='item in set.items') + button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='user.ops.buyMysterySet({params:{key:set.key}})', class='shop_{{::item.key}}') \ No newline at end of file diff --git a/website/views/shared/header/menu.jade b/website/views/shared/header/menu.jade index 02d2d0a758..9b853a63a6 100644 --- a/website/views/shared/header/menu.jade +++ b/website/views/shared/header/menu.jade @@ -41,6 +41,8 @@ nav.toolbar(ng-controller='MenuCtrl', ng-class='{active: isToolbarHidden}') ul.toolbar-submenu li a(ui-sref='options.inventory.drops')=env.t('market') + li + a(ui-sref='options.inventory.quests')=env.t('quests') li a(ui-sref='options.inventory.pets')=env.t('pets') li @@ -125,6 +127,8 @@ nav.toolbar(ng-controller='MenuCtrl', ng-class='{active: isToolbarHidden}') ul.toolbar-submenu(ng-click='expandMenu(null)') li a(ui-sref='options.inventory.drops')=env.t('market') + li + a(ui-sref='options.inventory.quests')=env.t('quests') li a(ui-sref='options.inventory.pets')=env.t('pets') li From c0d35dc472705dab77bf1b4da7104660d7304274 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Wed, 8 Jul 2015 17:43:08 -0500 Subject: [PATCH 2/2] WIP(quests): Quests page cont'd Test fixes and addition of function for buying Quests with Gold --- common/script/index.coffee | 13 ++++++++++++- karma.conf.js | 1 + test/common/algos.mocha.coffee | 2 +- website/public/js/controllers/tasksCtrl.js | 1 - website/public/js/services/questServices.js | 3 +++ website/views/options/inventory/quests.jade | 5 ++++- 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/common/script/index.coffee b/common/script/index.coffee index c78a0552bb..a71f7903f3 100644 --- a/common/script/index.coffee +++ b/common/script/index.coffee @@ -875,7 +875,7 @@ api.wrap = (user, main=true) -> item = if key is 'potion' then content.potion else if key is 'armoire' then content.armoire else content.gear.flat[key] - return cb?({code:404, message:"Item '#{key} not found (see https://github.com/HabitRPG/habitrpg-shared/blob/develop/script/content.coffee)"}) unless item + return cb?({code:404, message:"Item '#{key} not found (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content.coffee)"}) unless item return cb?({code:401, message: i18n.t('messageNotEnoughGold', req.language)}) if user.stats.gp < item.value return cb?({code:401, message: "You can't buy this item"}) if item.canOwn? and !item.canOwn(user) if item.key is 'potion' @@ -913,6 +913,17 @@ api.wrap = (user, main=true) -> mixpanel?.track("Acquire Item",{'itemName':key,'acquireMethod':'Gold','goldCost':item.value}) cb? {code:200, message}, _.pick(user,$w 'items achievements stats flags') + buyQuest: (req, cb) -> + {key} = req.params + item = content.quests[key] + return cb?({code:404, message:"Quest '#{key} not found (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content.coffee)"}) unless item + return cb?({code:401, message: i18n.t('messageNotEnoughGold', req.language)}) if user.stats.gp < item.value + message = i18n.t('messageBought', {itemText: item.text(req.language)}, req.language) + user.items.quests[item.key] ?= 0 + user.items.quests[item.key] += 1 + user.stats.gp -= item.value + cb? {code:200, message}, user.items.quests + buyMysterySet: (req, cb)-> return cb?({code:401, message:"You don't have enough Mystic Hourglasses"}) unless user.purchased.plan.consecutive.trinkets>0 mysterySet = content.timeTravelerStore(user.items.gear.owned)?[req.params.key] diff --git a/karma.conf.js b/karma.conf.js index 42e63f35db..d1d576e53b 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -54,6 +54,7 @@ module.exports = function(config) { "website/public/js/services/challengeServices.js", "website/public/js/services/taskServices.js", "website/public/js/services/paymentServices.js", + "website/public/js/services/questServices.js", "website/public/js/filters/money.js", "website/public/js/filters/roundLargeNumbers.js", diff --git a/test/common/algos.mocha.coffee b/test/common/algos.mocha.coffee index 49205fe84a..423c182d84 100644 --- a/test/common/algos.mocha.coffee +++ b/test/common/algos.mocha.coffee @@ -574,7 +574,7 @@ describe 'User', -> expect(quest.value).to.be.greaterThan 0 if quest.canBuy expect(quest.drop.gp).to.not.be.lessThan 0 expect(quest.drop.exp).to.not.be.lessThan 0 - expect(quest.category).to.match('pet|unlockable|gold|world') + expect(quest.category).to.match(/pet|unlockable|gold|world/) if quest.drop.items expect(quest.drop.items).to.be.an(Array) if quest.boss diff --git a/website/public/js/controllers/tasksCtrl.js b/website/public/js/controllers/tasksCtrl.js index 58a992c56d..74d4c2d642 100644 --- a/website/public/js/controllers/tasksCtrl.js +++ b/website/public/js/controllers/tasksCtrl.js @@ -219,7 +219,6 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','N $scope.buy = function(item) { User.user.ops.buy({params:{key:item.key}}); $rootScope.playSound('Reward'); - Guide.goto('intro', 4); }; diff --git a/website/public/js/services/questServices.js b/website/public/js/services/questServices.js index 1ca6995c38..b634e0ace4 100644 --- a/website/public/js/services/questServices.js +++ b/website/public/js/services/questServices.js @@ -38,6 +38,9 @@ if (item.lvl && item.lvl > user.stats.lvl) { return alert(window.env.t('mustLvlQuest', {level: item.lvl})); } + if (item.category === 'gold') { + return User.user.ops.buyQuest({params:{key:item.key}}); + } $rootScope.selectedQuest = item; $rootScope.openModal('buyQuest', {controller:'InventoryCtrl'}); } diff --git a/website/views/options/inventory/quests.jade b/website/views/options/inventory/quests.jade index 40e73b796d..7ac417c0f6 100644 --- a/website/views/options/inventory/quests.jade +++ b/website/views/options/inventory/quests.jade @@ -31,8 +31,11 @@ script(type='text/ng-template', id='partials/options.inventory.quests.html') button.customize-option(data-popover-html="{{::lockQuest(quest,true) ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-title='{{::quest.text()}}', popover-append-to-body="true", popover-trigger='mouseenter', ng-click='buyQuest(quest.key)', ng-class='lockQuest(quest) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"') p(ng-if='quest.unlockCondition') | {{::quest.unlockCondition.text()}} - p(ng-if='quest.value && !lockQuest(quest)') + p(ng-if='quest.value && quest.category !== "gold" && !lockQuest(quest)') | {{::quest.value}}  span.Pet_Currency_Gem1x.inline-gems + p(ng-if='quest.value && quest.category === "gold" && !lockQuest(quest)') + | {{::quest.value}}  + span.shop_gold p(ng-if='quest.lvl && lockQuest(quest)')=env.t('level') | {{::quest.lvl}} \ No newline at end of file