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