From 60421a85cccd0250609be42ef8a21eb436df635d Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sat, 9 Nov 2013 20:14:35 -0800 Subject: [PATCH 01/15] mounts: revamp UserSchema.items to store all animal-related items as objects rather than arrays. Preparation for the mount system --- migrations/20131109_refactor_pets.js | 1 + src/models/user.js | 81 ++++++++++++++-------------- 2 files changed, 43 insertions(+), 39 deletions(-) create mode 100644 migrations/20131109_refactor_pets.js diff --git a/migrations/20131109_refactor_pets.js b/migrations/20131109_refactor_pets.js new file mode 100644 index 0000000000..ea641885d8 --- /dev/null +++ b/migrations/20131109_refactor_pets.js @@ -0,0 +1 @@ +//TODO \ No newline at end of file diff --git a/src/models/user.js b/src/models/user.js index 383b53271d..5a8b1206a2 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -7,6 +7,7 @@ var mongoose = require("mongoose"); var Schema = mongoose.Schema; var helpers = require('habitrpg-shared/script/helpers'); +var items = require('habitrpg-shared/script/items'); var _ = require('lodash'); var TaskSchema = require('./task').schema; var Challenge = require('./challenge').model; @@ -83,7 +84,6 @@ var UserSchema = new Schema({ newStuff: {type: Boolean, 'default': false}, rewrite: {type: Boolean, 'default': true}, partyEnabled: Boolean, // FIXME do we need this? - petsEnabled: {type: Boolean, 'default': false}, rest: {type: Boolean, 'default': false}, // fixme - change to preferences.resting once we're off derby contributor: Boolean }, @@ -92,7 +92,7 @@ var UserSchema = new Schema({ todos: Array //[{data: Date, value: Number}] // big peformance issues if these are defined }, - /* FIXME remove?*/ + // FIXME remove? invitations: { guilds: {type: Array, 'default': []}, party: Schema.Types.Mixed @@ -103,52 +103,55 @@ var UserSchema = new Schema({ head: Number, shield: Number, - /*FIXME - tidy this up, not the best way to store current pet*/ + // -------------- Animals ------------------- - currentPet: { - /*Cactus*/ + // Complex bit here. The result looks like: + // pets: { + // 'Wolf-Desert': 0, // 0 means does not own + // 'PandaCub-Red': 10, // Number represents "Growth Points" + // etc... + // } + pets: _.transform(items.items.eggs, function(m, egg){ + _.defaults(m, _.transform(items.items.hatchingPotions, function(m2, pot){ + m2[egg.name + '-' + pot.name] = Number; + })); + }), + currentPet: String, // Cactus-Desert - text: String, - /*Cactus*/ + // eggs: { + // 'PandaCub': 0, // 0 indicates "doesn't own" + // 'Wolf': 5 // Number indicates "stacking" + // } + eggs: _.transform(items.items.eggs, function(m,v,k){ m[k] = Number; }), - name: String, - /*3*/ + // hatchingPotions: { + // 'Desert': 0, // 0 indicates "doesn't own" + // 'CottonCandyBlue': 5 // Number indicates "stacking" + // } + hatchingPotions: _.transform(items.items.hatchingPotions, function(m,v,k){ m[k] = Number; }), - value: Number, - /*"Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet.",*/ + // Food: { + // 'Watermelon': 0, // 0 indicates "doesn't own" + // 'RottenMeat': 5 // Number indicates "stacking" + // } + food: _.transform(items.items.food, function(m,v,k){ m[k] = Number; }), - notes: String, - /*Skeleton*/ + // mounts: { + // 'Wolf-Desert': true, + // 'PandaCub-Red': false, + // etc... + // } + mounts: _.transform(items.items.eggs, function(m, egg){ + _.defaults(m, _.transform(items.items.hatchingPotions, function(m2, pot){ + m2[egg.name + '-' + pot.name] = Boolean; + })); + }), + currentMount: String, - modifier: String, - /*Cactus-Skeleton*/ - - str: String - }, - - eggs: [ - { - // example: You've found a Wolf Egg! Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet - dialog: String, - // example: Wolf - name: String, - // example: Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet. - notes: String, - // example: Wolf - text: String, - /* type: String, //Egg // this is forcing mongoose to return object as "[object Object]", but I don't think this is needed anyway? */ - // example: 3 - value: Number - } - ], - hatchingPotions: Array, // ["Base", "Skeleton",...] lastDrop: { date: {type: Date, 'default': Date.now}, count: {type: Number, 'default': 0} - }, - // ["BearCub-Base", "Cactus-Base", ...] - - pets: Array + } }, lastCron: { From 085919c000d87ef48165b5461d94e21e14b35bf6 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sat, 9 Nov 2013 20:15:55 -0800 Subject: [PATCH 02/15] mounts: update all html & javascript to support UserSchema overhaul (60421a8). Also add very basic feeding & saddling mounts functionality. use progress bars to indicate pet feeding progress --- package.json | 2 +- public/css/inventory.styl | 23 +++- public/js/app.js | 3 +- public/js/controllers/inventoryCtrl.js | 150 ++++++++++++++++------ public/js/controllers/marketCtrl.js | 37 ------ public/js/controllers/notificationCtrl.js | 4 +- public/js/controllers/petsCtrl.js | 32 ----- public/js/controllers/rootCtrl.js | 1 + public/js/filters/filters.js | 5 +- public/js/services/guideServices.js | 13 +- public/manifest.json | 2 - src/controllers/groups.js | 4 +- src/controllers/user.js | 43 ++----- views/options/inventory/inventory.jade | 53 +++++--- views/options/inventory/stable.jade | 52 +++++--- views/shared/header/avatar.jade | 17 ++- views/shared/modals/pets.jade | 6 +- 17 files changed, 248 insertions(+), 199 deletions(-) delete mode 100644 public/js/controllers/marketCtrl.js delete mode 100644 public/js/controllers/petsCtrl.js diff --git a/package.json b/package.json index 8d7d1f36d8..9d1794abd6 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.0-152", "main": "./src/server.js", "dependencies": { - "habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared#master", + "habitrpg-shared": "git://github.com/HabitRPG/habitrpg-shared#mounts", "derby-auth": "git://github.com/lefnire/derby-auth#master", "connect-mongo": "*", "passport-facebook": "~1.0.0", diff --git a/public/css/inventory.styl b/public/css/inventory.styl index fe5f84fd22..3ba84b2bb6 100644 --- a/public/css/inventory.styl +++ b/public/css/inventory.styl @@ -65,10 +65,18 @@ menu.pets div .Pet_Currency_Gem2x {background-position: -55px -513px; width: 34px; height: 30px} .Pet_Currency_Gem1x {background-position: -63px -542px; width: 19px; height: 17px} -.inventory-list p +.inventory-list + p //display: none -.inventory-list li + li clear:both + button.customize-option + position:relative + .stack-count + position:absolute + bottom:-6px + right:-9px + .pets-menu > div display:inline-block vertical-align:top @@ -90,6 +98,17 @@ menu.pets div width:6em margin-top:-.5em +// This adds feeding progress bars to pets. If we have any issues with `menu.pets > button`, revisit +menu.pets .customize-menu + button + position: relative + .progress + width: 60% + position: absolute + bottom: -25px + left: 20% + height: 5px + .pet-button border: none background: none white diff --git a/public/js/app.js b/public/js/app.js index cdb890c820..599d5255f1 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -128,7 +128,8 @@ window.habitrpg = angular.module('habitrpg', // Options > Inventory .state('options.inventory', { url: '/inventory', - templateUrl: "partials/options.inventory.html" + templateUrl: "partials/options.inventory.html", + controller: 'InventoryCtrl' }) .state('options.inventory.inventory', { url: '/inventory', diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index 6dc8d16955..1b7a443ce5 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -1,18 +1,27 @@ -habitrpg.controller("InventoryCtrl", ['$scope', 'User', - function($scope, User) { +habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', '$http', 'Notification', + function($rootScope, $scope, User, API_URL, $http, Notification) { + + var user = User.user; // convenience vars since these are accessed frequently - $scope.userEggs = User.user.items.eggs; - $scope.userHatchingPotions = User.user.items.hatchingPotions; $scope.selectedEgg = null; // {index: 1, name: "Tiger", value: 5} $scope.selectedPotion = null; // {index: 5, name: "Red", value: 3} + $scope.petCount = _.size(User.user.items.pets); + $scope.totalPets = _.size($scope.Items.eggs) * _.size($scope.Items.hatchingPotions); - $scope.chooseEgg = function(egg, $index){ - if ($scope.selectedEgg && $scope.selectedEgg.index == $index) { + var countItems = function(items) { + return _.reduce(items,function(m,v){return m+v;},0); + } + $scope.$watch('user.items.pets', function(pets){ $scope.petCount = countItems(pets); }); + $scope.$watch('user.items.eggs', function(eggs){ $scope.eggCount = countItems(eggs); }); + $scope.$watch('user.items.hatchingPotions', function(pots){ $scope.potCount = countItems(pots); }); + + $scope.chooseEgg = function(egg){ + if ($scope.selectedEgg && $scope.selectedEgg.name == egg) { return $scope.selectedEgg = null; // clicked same egg, unselect } - var eggData = _.defaults({index:$index}, egg); + var eggData = _.findWhere(window.habitrpgShared.items.items.eggs, {name:egg}); if (!$scope.selectedPotion) { $scope.selectedEgg = eggData; } else { @@ -20,13 +29,12 @@ habitrpg.controller("InventoryCtrl", ['$scope', 'User', } } - $scope.choosePotion = function(potion, $index){ - if ($scope.selectedPotion && $scope.selectedPotion.index == $index) { + $scope.choosePotion = function(potion){ + if ($scope.selectedPotion && $scope.selectedPotion.name == potion) { return $scope.selectedPotion = null; // clicked same egg, unselect } // we really didn't think through the way these things are stored and getting passed around... var potionData = _.findWhere(window.habitrpgShared.items.items.hatchingPotions, {name:potion}); - potionData = _.defaults({index:$index}, potionData); if (!$scope.selectedEgg) { $scope.selectedPotion = potionData; } else { @@ -34,54 +42,52 @@ habitrpg.controller("InventoryCtrl", ['$scope', 'User', } } + $scope.chooseFood = function(food){ + $scope.selectedFood = $scope.Items.food[food]; + } + $scope.sellInventory = function() { + // TODO DRY this if ($scope.selectedEgg) { - $scope.userEggs.splice($scope.selectedEgg.index, 1); + user.items.eggs[$scope.selectedEgg.name]--; User.setMultiple({ - 'items.eggs': $scope.userEggs, + 'items.eggs': user.items.eggs, 'stats.gp': User.user.stats.gp + $scope.selectedEgg.value }); $scope.selectedEgg = null; } else if ($scope.selectedPotion) { - $scope.userHatchingPotions.splice($scope.selectedPotion.index, 1); + user.items.hatchingPotions[$scope.selectedPotion.name]--; User.setMultiple({ - 'items.hatchingPotions': $scope.userHatchingPotions, + 'items.hatchingPotions': user.items.hatchingPotions, 'stats.gp': User.user.stats.gp + $scope.selectedPotion.value }); $scope.selectedPotion = null; + } else if ($scope.selectedFood) { + user.items.food[$scope.selectedFood.name]--; + User.setMultiple({ + 'items.food': user.items.food, + 'stats.gp': User.user.stats.gp + $scope.selectedFood.value + }); + $scope.selectedFood = null; } + } - $scope.ownsPet = function(egg, potion){ - if (!egg || !potion) return; - var pet = egg.name + '-' + potion; - return User.user.items.pets && ~User.user.items.pets.indexOf(pet) - } - - $scope.selectableInventory = function(egg, potion, $index) { - if (!egg || !potion) return; - // FIXME this isn't updating the view for some reason - //if ($scope.selectedEgg && $scope.selectedEgg.index == $index) return 'selectableInventory'; - //if ($scope.selectedPotion && $scope.selectedPotion.index == $index) return 'selectableInventory'; - if (!$scope.ownsPet(egg, potion)) return 'selectableInventory'; + $scope.ownedItems = function(inventory){ + return _.pick(inventory, function(v,k){return v>0;}); } $scope.hatch = function(egg, potion){ - if ($scope.ownsPet(egg, potion.name)){ - return alert("You already have that pet, hatch a different combo.") - } - var pet = egg.name + '-' + potion.name; - $scope.userEggs.splice(egg.index, 1); - $scope.userHatchingPotions.splice(potion.index, 1); + var pet = egg.name+"-"+potion.name; + if (user.items.pets[pet]) + return alert("You already have that pet, hatch a different combo."); - if(!User.user.items.pets) User.user.items.pets = []; - User.user.items.pets.push(pet); + var setObj = {}; + setObj['items.pets.' + pet] = 5; + setObj['items.eggs.' + egg.name] = user.items.eggs[egg.name] - 1; + setObj['items.hatchingPotions.' + potion.name] = user.items.hatchingPotions[potion.name] - 1; - User.log([ - { op: 'set', data: {'items.pets': User.user.items.pets} }, - { op: 'set', data: {'items.eggs': $scope.userEggs} }, - { op: 'set', data: {'items.hatchingPotions': $scope.userHatchingPotions} } - ]); + User.setMultiple(setObj); alert("Your egg hatched! Visit your stable to equip your pet."); @@ -89,4 +95,68 @@ habitrpg.controller("InventoryCtrl", ['$scope', 'User', $scope.selectedPotion = null; } - }]); \ No newline at end of file + $scope.buy = function(type, item){ + var gems = User.user.balance * 4; + if(gems < item.value) return $rootScope.modals.buyGems = true; + var string = (type == 'hatchingPotion') ? 'hatching potion' : type; // give hatchingPotion a space + var message = "Buy this " + string + " with " + item.value + " of your " + gems + " Gems?" + if(confirm(message)){ + $http.post(API_URL + '/api/v1/market/buy?type=' + type, item) + .success(function(data){ + User.user.items = data.items; + }); + } + } + + $scope.choosePet = function(egg, potion){ + var pet = egg + '-' + potion; + + // Feeding Pet + if ($scope.selectedFood) { + var setObj = {}; + var userPets = user.items.pets; + + // Saddling a pet + if ($scope.selectedFood.name == 'Saddle') { + if (userPets[pet] < 150) + return Notification.text(egg+" is not strong enough yet to saddle."); + if (!confirm('Saddle ' + pet + '?')) return; + userPets[pet] = 0; + setObj['items.mounts.' + pet] = true; + Notification.text('You have tamed '+egg+", let's go for a ride!"); + } else { + if (userPets[pet] >= 150) + return Notification.text(egg+" has become very strong and wild, try using a saddle and something might happen."); + if (!confirm('Feed ' + pet + ' a ' + $scope.selectedFood.name + '?')) return; + if ($scope.selectedFood.target == potion) { + userPets[pet] += 50; // FIXME change this to 5 before we're live + Notification.text(egg+' really likes the '+$scope.selectedFood.name+'!'); + } else { + userPets[pet] += 2; + Notification.text(egg+' eats the '+$scope.selectedFood.name+" but doesn't seem to enjoy it."); + } + } + setObj['items.pets.' + pet] = userPets[pet]; + setObj['items.food.' + $scope.selectedFood.name] = user.items.food[$scope.selectedFood.name] - 1; + User.setMultiple(setObj); + $scope.selectedFood = null; + + // Selecting Pet + } else { + var userCurrentPet = User.user.items.currentPet; + if(userCurrentPet && userCurrentPet == pet){ + User.user.items.currentPet = null; + }else{ + User.user.items.currentPet = pet; + } + User.set('items.currentPet', User.user.items.currentPet); + } + } + + $scope.chooseMount = function(egg, potion) { + var mount = egg + '-' + potion; + User.set('items.currentMount', (user.items.currentMount == mount) ? null : mount); + } + + } +]); \ No newline at end of file diff --git a/public/js/controllers/marketCtrl.js b/public/js/controllers/marketCtrl.js deleted file mode 100644 index c0cf429539..0000000000 --- a/public/js/controllers/marketCtrl.js +++ /dev/null @@ -1,37 +0,0 @@ -habitrpg.controller("MarketCtrl", ['$rootScope', '$scope', 'User', 'API_URL', '$http', - function($rootScope, $scope, User, API_URL, $http) { - - $scope.eggs = window.habitrpgShared.items.items.pets; - $scope.hatchingPotions = window.habitrpgShared.items.items.hatchingPotions; - $scope.userEggs = User.user.items.eggs; - $scope.userHatchingPotions = User.user.items.hatchingPotions; - - $scope.buy = function(type, item){ - var gems = User.user.balance * 4, - store = type === 'egg' ? $scope.userEggs : $scope.userHatchingPotions, - storePath = type === 'egg' ? 'items.eggs' : 'items.hatchingPotions' - - if(gems < item.value){ - return $rootScope.modals.buyGems = true; - } - - var message = "Buy this " + (type == 'egg' ? 'egg' : 'hatching potion') + " with " + item.value + " of your " + gems + " Gems?" - - if(confirm(message)){ - $http.post(API_URL + '/api/v1/market/buy?type=' + type, item) - .success(function(data){ - // don't know what's going on, but trying to work with the returned data (a) isn't updating the ui, (b) isnt' - // stickign between refreshes until a force-refresh is called (user._v--). - User.user._v--; - User.log({}); - //User.user.balance = data.balance; - store.push(type === 'egg' ? item : item.name); - //$scope.items = data.items.eggs; // FIXME this isn't updating the UI - }).error(function(data){ - alert(data); - console.error(data); - }); - } - } - - }]); \ No newline at end of file diff --git a/public/js/controllers/notificationCtrl.js b/public/js/controllers/notificationCtrl.js index 618964f70f..4eb64caa9b 100644 --- a/public/js/controllers/notificationCtrl.js +++ b/public/js/controllers/notificationCtrl.js @@ -43,8 +43,8 @@ habitrpg.controller('NotificationCtrl', $rootScope.modals.achievements.ultimateGear = true; }); - $rootScope.$watch('user.items.pets.length', function(after, before){ - if(after === before || after < 90) return; + $rootScope.$watch('user.items.pets', function(after, before){ + if(_.size(after) === _.size(before) || _.size(after) < 90) return; User.user.achievements.beastMaster = true; $rootScope.modals.achievements.beastMaster = true; }) diff --git a/public/js/controllers/petsCtrl.js b/public/js/controllers/petsCtrl.js deleted file mode 100644 index 7d4e6ba5ed..0000000000 --- a/public/js/controllers/petsCtrl.js +++ /dev/null @@ -1,32 +0,0 @@ -habitrpg.controller("PetsCtrl", ['$scope', 'User', - function($scope, User) { - - $scope.userPets = User.user.items.pets; - $scope.userCurrentPet = User.user.items.currentPet; - $scope.pets = window.habitrpgShared.items.items.pets; - $scope.hatchingPotions = window.habitrpgShared.items.items.hatchingPotions; - $scope.totalPets = $scope.pets.length * $scope.hatchingPotions.length; - - $scope.hasPet = function(name, potion){ - if (!$scope.userPets) return false; - return _.contains($scope.userPets, name + '-' + potion) ? true : false; - } - - $scope.isCurrentPet = function(name, potion){ - if (!$scope.userCurrentPet || !$scope.userPets) return false; - return $scope.userCurrentPet.str === (name + '-' + potion); - } - - $scope.choosePet = function(name, potion){ - if($scope.userCurrentPet && $scope.userCurrentPet.str === (name + '-' + potion)){ - $scope.userCurrentPet = null; - }else{ - var pet = _.find($scope.pets, {name: name}); - pet.modifier = potion; - pet.str = name + '-' + potion; - $scope.userCurrentPet = pet; - } - User.set('items.currentPet', $scope.userCurrentPet); - } - - }]); \ No newline at end of file diff --git a/public/js/controllers/rootCtrl.js b/public/js/controllers/rootCtrl.js index eab96974a5..98b09b2401 100644 --- a/public/js/controllers/rootCtrl.js +++ b/public/js/controllers/rootCtrl.js @@ -10,6 +10,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ $rootScope.User = User; $rootScope.user = User.user; $rootScope.settings = User.settings; + $rootScope.Items = window.habitrpgShared.items.items; // Angular UI Router $rootScope.$state = $state; diff --git a/public/js/filters/filters.js b/public/js/filters/filters.js index 65223c5957..9d2255d9e2 100644 --- a/public/js/filters/filters.js +++ b/public/js/filters/filters.js @@ -3,8 +3,9 @@ angular.module('habitrpg') return function (gp) { return Math.floor(gp); } - }).filter('silver', function () { + }) + .filter('silver', function () { return function (gp) { return Math.floor((gp - Math.floor(gp))*100); } - }); + }) \ No newline at end of file diff --git a/public/js/services/guideServices.js b/public/js/services/guideServices.js index 3e709ce4c5..964ccdffc9 100644 --- a/public/js/services/guideServices.js +++ b/public/js/services/guideServices.js @@ -96,13 +96,6 @@ angular.module('guideServices', []). showPopover('div.rewards', 'Item Store Unlocked', html, 'left'); }); - $rootScope.$watch('user.flags.petsEnabled', function(after, before) { - //TODO is this ever used? I think dropsEnabled is the one that's used - if (alreadyShown(before, after)) return; - var html = "You have unlocked Pets! You can now buy pets with Gems (note, you replenish Gems with real-life money - so chose your pets wisely!)"; - showPopover('#rewardsTabs', 'Pets Unlocked', html, 'left'); - }); - $rootScope.$watch('user.flags.partyEnabled', function(after, before) { if (alreadyShown(before, after)) return; var html = "Be social, join a party and play Habit with your friends! You'll be better at your habits with accountability partners. Click User -> Options -> Party, and follow the instructions. LFG anyone?"; @@ -111,10 +104,8 @@ angular.module('guideServices', []). $rootScope.$watch('user.flags.dropsEnabled', function(after, before) { if (alreadyShown(before, after)) return; - var drop = Helpers.randomVal(Items.items.pets); - var eggs = User.user.items.eggs || []; - eggs.push(drop); // FIXME put this on server instead - User.set('items.eggs', eggs); + var eggs = User.user.items.eggs || {}; + eggs['Wolf-Base'] = 5; // This is also set on the server $rootScope.modals.dropsEnabled = true; }); diff --git a/public/manifest.json b/public/manifest.json index ee6d559b95..83dd7176bd 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -48,9 +48,7 @@ "js/controllers/filtersCtrl.js", "js/controllers/userCtrl.js", "js/controllers/groupsCtrl.js", - "js/controllers/petsCtrl.js", "js/controllers/inventoryCtrl.js", - "js/controllers/marketCtrl.js", "js/controllers/footerCtrl.js", "js/controllers/challengesCtrl.js", "js/controllers/adminCtrl.js" diff --git a/src/controllers/groups.js b/src/controllers/groups.js index 4aefd73e08..41ac5ab55f 100644 --- a/src/controllers/groups.js +++ b/src/controllers/groups.js @@ -60,9 +60,7 @@ api.updateMember = function(req, res) { member.balance += (req.body.contributor.level - (member.contributor.level || 0))*.5 // +2 gems per tier } _.merge(member, _.pick(req.body, 'contributor')); - if (!member.items.pets) member.items.pets = []; - var i = member.items.pets.indexOf('Dragon-Hydra'); - if (!~i && member.contributor.level >= 6) member.items.pets.push('Dragon-Hydra'); + if (member.contributor.level >= 6 && !member.items.pets['Dragon-Hydra']) member.items.pets['Dragon-Hydra'] = 5; member.save(cb); } ], function(err, saved){ diff --git a/src/controllers/user.js b/src/controllers/user.js index b67c61fe42..560b5a7776 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -22,17 +22,11 @@ api.marketBuy = function(req, res, next){ type = req.query.type, item = req.body; - if (!_.contains(['hatchingPotion', 'egg'], req.query.type)) - return res.json(400, {err: "Type must be in 'hatchingPotion' or 'egg'"}); - var item; - if (type == 'egg'){ - if (!user.items && !user.items.eggs) user.items.eggs = []; - user.items.eggs.push(item); - } else { - if (!user.items && !user.items.hatchingPotions) user.items.hatchingPotions = []; - user.items.hatchingPotions.push(item.name); - } - user.markModified('items'); // I still don't get when this is necessary and when not.. + if (!_.contains(['hatchingPotion', 'egg', 'food'], type)) + return res.json(400, {err: "Type must be 'hatchingPotion', 'egg', or 'food'"}); + type = (type == 'food' ? type : type + 's'); // I'm stupid, we're passing up 'hatchingPotion' but we need 'hatchingPotions' + if (!user.items[type][item.name]) user.items[type][item.name] = 0; + user.items[type][item.name]++; user.balance -= (item.value/4); user.save(function(err, saved){ if (err) return res.json(500, {err:err}); @@ -270,30 +264,21 @@ api.updateUser = function(req, res, next) { acceptableAttrs = 'tasks. achievements. filters. flags. invitations. items. lastCron party. preferences. profile. stats. tags custom.'.split(' '); _.each(req.body, function(v, k) { - if ((_.find(acceptableAttrs, function(attr) { - return k.indexOf(attr) === 0; - })) != null) { - if (_.isObject(v)) { - errors.push("Value for " + k + " was an object. Be careful here, you could clobber stuff."); - } + var found = _.find(acceptableAttrs, function(attr) { return k.indexOf(attr) == 0; }) + if (found) { +// if (_.isObject(v)) { +// errors.push("Value for " + k + " was an object. Be careful here, you could clobber stuff."); +// } helpers.dotSet(k, v, user); } else { errors.push("path `" + k + "` was not saved, as it's a protected path. Make sure to send `PUT /api/v1/user` request bodies as `{'set.this.path':value}` instead of `{set:{this:{path:value}}}`"); } return true; }); - return user.save(function(err) { - if (!_.isEmpty(errors)) { - return res.json(500, { - err: errors - }); - } - if (err) { - return res.json(500, { - err: err - }); - } - return res.json(200, user); + user.save(function(err) { + if (!_.isEmpty(errors)) return res.json(500, {err: errors}); + if (err) {return res.json(500, {err: err})} + res.json(200, user); }); }; diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index 37be78f7b2..95b5ff2be0 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -1,25 +1,38 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') - .row-fluid(ng-controller='InventoryCtrl') + .row-fluid .span6.border-right h2 Inventory p.well Click an egg to see usable potions highlighted in green and then click one of the highlighted potions to hatch your pet. If no potions are highlighted, click that egg again to deselect it, and instead click a potion first to have the usable eggs highlighted. You can also sell unwanted drops to Alexander the Merchant. menu.inventory-list(type='list') + li.customize-menu - menu.pets-menu(label='Eggs ({{userEggs.length}})') - p(ng-show='userEggs.length < 1') You don't have any eggs yet. - div(ng-repeat='egg in userEggs track by $index') - button.customize-option(tooltip='{{egg.text}}', ng-click='chooseEgg(egg, $index)', class='Pet_Egg_{{egg.name}}', ng-class='selectableInventory(egg, selectedPotion.name, $index)') - p {{egg.text}} + menu.pets-menu(label='Eggs ({{eggCount}})') + p(ng-show='user.items.eggs.length < 1') You don't have any eggs yet. + div(ng-repeat='(egg,points) in ownedItems(user.items.eggs)') + //TODO move positioning this styling to css + button.customize-option(tooltip='{{Items.eggs[egg].text}}', ng-click='chooseEgg(egg)', class='Pet_Egg_{{egg}}', ng-class='{selectableInventory: selectedPotion && !user.items.pets[egg+"-"+selectedPotion.name]}') + .badge.badge-info.stack-count {{points}} + p {{Items.eggs[egg].text}} + li.customize-menu - menu.hatchingPotion-menu(label='Hatching Potions ({{userHatchingPotions.length}})') - p(ng-show='userHatchingPotions.length < 1') You don't have any hatching potions yet. - div(ng-repeat='hatchingPotion in userHatchingPotions track by $index') - button.customize-option(tooltip='{{hatchingPotion}}', ng-click='choosePotion(hatchingPotion, $index)', class='Pet_HatchingPotion_{{hatchingPotion}}', ng-class='selectableInventory(selectedEgg, hatchingPotion, $index)') - p {{hatchingPotion}} + menu.hatchingPotion-menu(label='Hatching Potions ({{potCount}})') + p(ng-show='potCount < 1') You don't have any hatching potions yet. + div(ng-repeat='(pot,points) in ownedItems(user.items.hatchingPotions)') + button.customize-option(tooltip='{{pot}}', ng-click='choosePotion(pot)', class='Pet_HatchingPotion_{{pot}}', ng-class='{selectableInventory: selectedEgg && !user.items.pets[selectedEgg.name+"-"+pot]}') + .badge.badge-info.stack-count {{points}} + p {{pot}} + + li.customize-menu + menu.food-menu(label='Food ({{foodCount}})') + p(ng-show='foodCount < 1') You don't have any food yet. + div(ng-repeat='(food,points) in ownedItems(user.items.food)') + button.customize-option(tooltip='{{food}}', ng-click='chooseFood(food)', class='Pet_Food_{{food}}') + .badge.badge-info.stack-count {{points}} + p {{food}} .span6 h2 Market - .row-fluid(ng-controller='MarketCtrl') + .row-fluid table.NPC-Alex-container tr td @@ -37,19 +50,27 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') | Sell {{selectedEgg.name}} for {{selectedEgg.value}} GP button.btn.btn-primary(ng-show='selectedPotion', ng-click='sellInventory()') | Sell {{selectedPotion.name}} for {{selectedPotion.value}} GP + button.btn.btn-primary(ng-show='selectedFood', ng-click='sellInventory()') + | Sell {{selectedFood.name}} for {{selectedFood.value}} GP menu.inventory-list(type='list') li.customize-menu menu.pets-menu(label='Eggs') - div(ng-repeat='egg in eggs track by $index') + div(ng-repeat='egg in Items.eggs') button.customize-option(tooltip='{{egg.text}} - {{egg.value}} Gem(s)', ng-click='buy("egg", egg)', class='Pet_Egg_{{egg.name}}') p {{egg.text}} li.customize-menu menu.pets-menu(label='Hatching Potions') - div(ng-repeat='hatchingPotion in hatchingPotions track by $index') - button.customize-option(tooltip='{{hatchingPotion.text}} - {{hatchingPotion.value}} Gem(s)', ng-click='buy("hatchingPotion", hatchingPotion)', class='Pet_HatchingPotion_{{hatchingPotion.name}}') - p {{hatchingPotion.text}} + div(ng-repeat='pot in Items.hatchingPotions') + button.customize-option(tooltip='{{pot.text}} - {{pot.value}} Gem(s)', ng-click='buy("hatchingPotion", pot)', class='Pet_HatchingPotion_{{pot.name}}') + p {{pot.text}} + + li.customize-menu + menu.pets-menu(label='Food') + div(ng-repeat='food in Items.food') + button.customize-option(tooltip='{{food.text}} - {{food.value}} Gem(s)', ng-click='buy("food", food)', class='Pet_Food_{{food.name}}') + p {{food.text}} diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 042970aed9..f95c00bd25 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -1,33 +1,51 @@ script(type='text/ng-template', id='partials/options.inventory.stable.html') - .stable(ng-controller='PetsCtrl') + .stable .NPC-Matt .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') .arrow h3.popover-title a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch .popover-content - p - | Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to venture at your side. They aren't much help yet, but I forsee a time when they're able to - a(href='https://trello.com/card/mounts/50e5d3684fe3a7266b0036d6/221') grow into powerful steeds - | ! Until that day, - a(target='_blank', href='https://f.cloud.github.com/assets/2374703/164631/3ed5fa6c-78cd-11e2-8743-f65ac477b55e.png') have a look-see - | at all the pets you can collect. - h4 {{userPets.length}} / {{totalPets}} Pets Found + p. + Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to venture at your side. They aren't much help yet, but I forsee a time when they're able to grow into powerful steeds! Until that day, have a look-see at all the pets you can collect. + h4 {{petCount}} / {{totalPets}} Pets Found menu.pets(type='list') - li.customize-menu(ng-repeat='pet in pets') + li.customize-menu(ng-repeat='egg in Items.eggs') menu - div(ng-repeat='potion in hatchingPotions', tooltip='{{potion.name}} {{pet.name}}') - button(class="pet-button Pet-{{pet.name}}-{{potion.name}}", ng-show='hasPet(pet.name, potion.name)', ng-class="{active: isCurrentPet(pet.name, potion.name)}", ng-click='choosePet(pet.name, potion.name)') - button(class="pet-button pet-not-owned", ng-hide='hasPet(pet.name, potion.name)') + div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='pet = egg.name+"-"+potion.name') + button(class="pet-button Pet-{{pet}}", ng-if='user.items.pets[pet]>0', ng-class='{active: user.items.currentPet == pet}', ng-click='choosePet(egg.name, potion.name)') + .progress(ng-class='{"progress-success": user.items.pets[pet]<150}') + .bar(style="width: {{user.items.pets[pet]/1.5}}%;") + button(class="pet-button pet-not-owned", ng-if='!user.items.pets[pet]') img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') h4 Rare Pets menu div - button(ng-if='hasPet("Wolf", "Veteran")', class="pet-button Pet-Wolf-Veteran", ng-class='{active: isCurrentPet("Wolf", "Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf') - button(ng-if='hasPet("Wolf", "Cerberus")', class="pet-button Pet-Wolf-Cerberus", ng-class='{active: isCurrentPet("Wolf", "Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') - button(ng-if='hasPet("Dragon", "Hydra")', class="pet-button Pet-Dragon-Hydra", ng-class='{active: isCurrentPet("Dragon", "Hydra")}', ng-click='choosePet("Dragon", "Hydra")', tooltip='Hydra Pet') + button(ng-if='user.items.pets["Wolf-Veteran"]', class="pet-button Pet-Wolf-Veteran", ng-class='{active: user.items.currentPet == "Wolf-Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf') + button(ng-if='user.items.pets["Wolf-Cerberus"]', class="pet-button Pet-Wolf-Cerberus", ng-class='{active: user.items.currentPet == "Wolf-Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') + button(ng-if='user.items.pets["Dragon-Hydra"]', class="pet-button Pet-Dragon-Hydra", ng-class='{active: user.items.currentPet == "Dragon-Hydra")}', ng-click='choosePet("Dragon", "Hydra")', tooltip='Hydra Pet') a(target='_blank', href='https://github.com/HabitRPG/habitrpg/wiki/Contributing') - button(ng-if='!hasPet("Dragon", "Hydra")', class="pet-button pet-not-owned", popover-trigger='mouseenter', popover-placement='right', popover="Click the gold paw to learn more about how you can obtain this rare pet through contributing to HabitRPG!", popover-title='How to Get this Pet!') - img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png') \ No newline at end of file + button(ng-if='!user.items.pets["Dragon-Hydra"]', class="pet-button pet-not-owned", popover-trigger='mouseenter', popover-placement='right', popover="Click the gold paw to learn more about how you can obtain this rare pet through contributing to HabitRPG!", popover-title='How to Get this Pet!') + img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png') + + hr + h4 Mounts + menu.pets(type='list') + li.customize-menu(ng-repeat='egg in Items.eggs') + menu + div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='mount = egg.name+"-"+potion.name') + button(class="pet-button Pet-{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.name, potion.name)') + button(class="pet-button pet-not-owned", ng-hide='user.items.mounts[mount]') + img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') + + .well(style='position:fixed;right:0px;top:50%;width:200px') + menu.inventory-list(type='list') + li.customize-menu + menu.food-menu(label='Food') + p(ng-show='foodCount < 1') You don't have any food yet. + div(ng-repeat='(food,points) in ownedItems(user.items.food)') + button.customize-option(tooltip='{{food}}', ng-click='chooseFood(food)', class='Pet_Food_{{food}}') + .badge.badge-info.stack-count {{points}} + p {{food}} \ No newline at end of file diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 0fcb8096a4..9ee9527b33 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -1,6 +1,9 @@ -figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: profile.id==user.id, hasPet: profile.items.pet}', data-level='{{profile.stats.lvl}}', data-uid='{{profile.id}}', rel='popover', data-placement='bottom', data-trigger='hover', data-html='true', data-content="
Level: {{profile.stats.lvl}}
GP: {{profile.stats.gp | number:0}}
{{count(profile.items.pets)}} / 90 Pets Found
") +figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: profile.id==user.id, hasPet: profile.items.currentPet}', data-level='{{profile.stats.lvl}}', data-uid='{{profile.id}}', rel='popover', data-placement='bottom', data-trigger='hover', data-html='true', data-content="
Level: {{profile.stats.lvl}}
GP: {{profile.stats.gp | number:0}}
{{count(profile.items.pets)}} / 90 Pets Found
") .character-sprites - span(ng-class='{zzz:profile.flags.rest}') + // Mount Body + span(class='Mount_Body_{{profile.items.currentMount}}') + + // Avatar span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') span(class='{{profile.preferences.gender}}_hair_{{profile.preferences.hair}}') span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}') @@ -8,6 +11,14 @@ figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile span(class='{{equipped("head", profile.items.head, profile.preferences, profile.backer, profile.contributor)}}', ng-show='profile.preferences.showHelm') span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}') span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}') + + // Mount Head + span(class='Mount_Head_{{profile.items.currentMount}}') + + // Resting + span(ng-class='{zzz:profile.flags.rest}') + + // Pet // FIXME handle @minimal, this might have to be a directive - span.current-pet(class='Pet-{{profile.items.currentPet.name}}-{{profile.items.currentPet.modifier}}', ng-show='profile.items.currentPet && !minimal') + span.current-pet(class='Pet-{{profile.items.currentPet}}', ng-show='profile.items.currentPet && !minimal') .avatar-level Lvl {{profile.stats.lvl}} diff --git a/views/shared/modals/pets.jade b/views/shared/modals/pets.jade index aa60e7610b..0a2f152d08 100644 --- a/views/shared/modals/pets.jade +++ b/views/shared/modals/pets.jade @@ -2,11 +2,15 @@ div(modal='modals.dropsEnabled') .modal-header h3 Drops Enabled! .modal-body - p + //-p // TODO how to handle random first drop? span.item-drop-icon(class='Pet_Egg_{{user.items.eggs.0.name}}', style='margin-left: 0px') | You've unlocked the Drop System! Now when you complete tasks, you have a small chance of finding an item. You just found a strong {{user.items.eggs.0.text}} Egg | ! {{user.items.eggs.0.notes}}. + p + span.item-drop-icon(class='Pet_Egg_Wolf', style='margin-left: 0px') + span. + You've unlocked the Drop System! Now when you complete tasks, you have a small chance of finding an item. You just found a {{Items.eggs.Wolf.text}} Egg! {{Items.eggs.Wolf.notes}} br p. If you've got your eye on a pet, but can't wait any longer for it to drop, use Gems in Options > Inventory to buy one! From 284114c0563f938fc7c23577707087074902f28b Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 11:47:33 -0800 Subject: [PATCH 03/15] mounts: counting bug fixes, put pets & mounts in tabs --- public/js/app.js | 9 ++++++ public/js/controllers/inventoryCtrl.js | 16 ++++++---- views/options/inventory/stable.jade | 43 +++++++++++++++++++------- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/public/js/app.js b/public/js/app.js index 599d5255f1..8cf9e716b2 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -24,6 +24,7 @@ window.habitrpg = angular.module('habitrpg', .when('/options/groups', '/options/groups/tavern') .when('/options/groups/guilds', '/options/groups/guilds/public') .when('/options/inventory', '/options/inventory/inventory') + .when('/options/inventory/stable', '/options/inventory/stable/pets') // redirect states that don't match .otherwise("/tasks"); @@ -139,6 +140,14 @@ window.habitrpg = angular.module('habitrpg', url: '/stable', templateUrl: "partials/options.inventory.stable.html" }) + .state('options.inventory.stable.pets', { + url: '/pets', + templateUrl: "partials/options.inventory.stable.pets.html" + }) + .state('options.inventory.stable.mounts', { + url: '/mounts', + templateUrl: "partials/options.inventory.stable.mounts.html" + }) // Options > Settings .state('options.settings', { diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index 1b7a443ce5..ea39a88b3b 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -10,12 +10,16 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', $scope.petCount = _.size(User.user.items.pets); $scope.totalPets = _.size($scope.Items.eggs) * _.size($scope.Items.hatchingPotions); - var countItems = function(items) { - return _.reduce(items,function(m,v){return m+v;},0); - } - $scope.$watch('user.items.pets', function(pets){ $scope.petCount = countItems(pets); }); - $scope.$watch('user.items.eggs', function(eggs){ $scope.eggCount = countItems(eggs); }); - $scope.$watch('user.items.hatchingPotions', function(pots){ $scope.potCount = countItems(pots); }); + // count egg, food, hatchingPotion stack totals + var countStacks = function(items) { return _.reduce(items,function(m,v){return m+v;},0);} + // count pets, mounts collected totals + var countExists = function(items) { return _.reduce(items,function(m,v){return m+(v ? 1 : 0);},0);} + + $scope.$watch('user.items.pets', function(pets){ $scope.petCount = countExists(pets); }); + $scope.$watch('user.items.mounts', function(mounts){ $scope.mountCount = countExists(mounts); }); + $scope.$watch('user.items.eggs', function(eggs){ $scope.eggCount = countStacks(eggs); }); + $scope.$watch('user.items.hatchingPotions', function(pots){ $scope.potCount = countStacks(pots); }); + $scope.$watch('user.items.food', function(food){ $scope.foodCount = countStacks(food); }); $scope.chooseEgg = function(egg){ if ($scope.selectedEgg && $scope.selectedEgg.name == egg) { diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index f95c00bd25..591566b689 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -1,4 +1,16 @@ script(type='text/ng-template', id='partials/options.inventory.stable.html') + ul.nav.nav-tabs + li(ng-class="{ active: $state.includes('options.inventory.stable.pets') }") + a(ui-sref='options.inventory.stable.pets') + | Pets + li(ng-class="{ active: $state.includes('options.inventory.stable.mounts') }") + a(ui-sref='options.inventory.stable.mounts') + | Mounts + .tab-content + .tab-pane.active + div(ui-view) + +script(type='text/ng-template', id='partials/options.inventory.stable.mounts.html') .stable .NPC-Matt .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') @@ -7,7 +19,26 @@ script(type='text/ng-template', id='partials/options.inventory.stable.html') a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch .popover-content p. - Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to venture at your side. They aren't much help yet, but I forsee a time when they're able to grow into powerful steeds! Until that day, have a look-see at all the pets you can collect. + Shall I bring you your steed, {{user.profile.name}}? Click a mount to saddle up. + h4 {{mountCount}} / {{totalPets}} Mounts Tamed + menu.pets(type='list') + li.customize-menu(ng-repeat='egg in Items.eggs') + menu + div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='mount = egg.name+"-"+potion.name') + button(class="pet-button Pet-{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.name, potion.name)') + button(class="pet-button pet-not-owned", ng-hide='user.items.mounts[mount]') + img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') + +script(type='text/ng-template', id='partials/options.inventory.stable.pets.html') + .stable + .NPC-Matt + .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') + .arrow + h3.popover-title + a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch + .popover-content + p. + Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to venture at your side. Feed them and they'll grow into powerful steeds. Have a look-see at all the pets you can collect. h4 {{petCount}} / {{totalPets}} Pets Found menu.pets(type='list') @@ -30,16 +61,6 @@ script(type='text/ng-template', id='partials/options.inventory.stable.html') button(ng-if='!user.items.pets["Dragon-Hydra"]', class="pet-button pet-not-owned", popover-trigger='mouseenter', popover-placement='right', popover="Click the gold paw to learn more about how you can obtain this rare pet through contributing to HabitRPG!", popover-title='How to Get this Pet!') img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png') - hr - h4 Mounts - menu.pets(type='list') - li.customize-menu(ng-repeat='egg in Items.eggs') - menu - div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='mount = egg.name+"-"+potion.name') - button(class="pet-button Pet-{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.name, potion.name)') - button(class="pet-button pet-not-owned", ng-hide='user.items.mounts[mount]') - img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') - .well(style='position:fixed;right:0px;top:50%;width:200px') menu.inventory-list(type='list') li.customize-menu From cd796491001fe50588f1ea0f015360924ca5eafe Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 12:28:47 -0800 Subject: [PATCH 04/15] mounts: fix isUser class bringing user too far down. Fix initial drop bug. Remove items.currentPet if turned into mount --- public/js/controllers/inventoryCtrl.js | 6 ++++-- public/js/services/guideServices.js | 2 +- views/shared/header/avatar.jade | 7 ++++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index ea39a88b3b..a206f86bf7 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -127,6 +127,8 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', if (!confirm('Saddle ' + pet + '?')) return; userPets[pet] = 0; setObj['items.mounts.' + pet] = true; + if (pet == user.items.currentPet) + setObj['items.currentPet'] = ''; Notification.text('You have tamed '+egg+", let's go for a ride!"); } else { if (userPets[pet] >= 150) @@ -149,7 +151,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', } else { var userCurrentPet = User.user.items.currentPet; if(userCurrentPet && userCurrentPet == pet){ - User.user.items.currentPet = null; + User.user.items.currentPet = ''; }else{ User.user.items.currentPet = pet; } @@ -159,7 +161,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', $scope.chooseMount = function(egg, potion) { var mount = egg + '-' + potion; - User.set('items.currentMount', (user.items.currentMount == mount) ? null : mount); + User.set('items.currentMount', (user.items.currentMount == mount) ? '' : mount); } } diff --git a/public/js/services/guideServices.js b/public/js/services/guideServices.js index 964ccdffc9..ebb9cadb36 100644 --- a/public/js/services/guideServices.js +++ b/public/js/services/guideServices.js @@ -105,7 +105,7 @@ angular.module('guideServices', []). $rootScope.$watch('user.flags.dropsEnabled', function(after, before) { if (alreadyShown(before, after)) return; var eggs = User.user.items.eggs || {}; - eggs['Wolf-Base'] = 5; // This is also set on the server + eggs['Wolf'] = 1; // This is also set on the server $rootScope.modals.dropsEnabled = true; }); diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 9ee9527b33..5df250fa8f 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -1,4 +1,9 @@ -figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: profile.id==user.id, hasPet: profile.items.currentPet}', data-level='{{profile.stats.lvl}}', data-uid='{{profile.id}}', rel='popover', data-placement='bottom', data-trigger='hover', data-html='true', data-content="
Level: {{profile.stats.lvl}}
GP: {{profile.stats.gp | number:0}}
{{count(profile.items.pets)}} / 90 Pets Found
") +//- FIXME the commented-out figure.herobox used to have a functioning popover, but angular-ui-bootstrap doesn't support + html in popovers. Figure out what to do here. Also, {isUser:..} class seems to bring the user too far down with mounts. + Removing it will remove the user's name, but will allow more room for mounts & helms. IMO this is the lesser of two evils, revisit +//-figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: profile.id==user.id, hasPet: profile.items.currentPet}', data-level='{{profile.stats.lvl}}', data-uid='{{profile.id}}', rel='popover', data-placement='bottom', data-trigger='hover', data-html='true', data-content="
Level: {{profile.stats.lvl}}
GP: {{profile.stats.gp | number:0}}
{{count(profile.items.pets)}} / 90 Pets Found
") + +figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: user._id==profile._id && !(user.items.currentMount && user.items.currentPet), hasPet: profile.items.currentPet && profile.items.currentMount}') .character-sprites // Mount Body span(class='Mount_Body_{{profile.items.currentMount}}') From 244fe63bdda35a528b8b2a72ba67c0e37d3ddccc Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 14:36:40 -0800 Subject: [PATCH 05/15] mounts: add support for rare mounts --- src/controllers/groups.js | 2 +- src/models/user.js | 36 +++++++++++++++++++++-------- views/options/inventory/stable.jade | 11 ++++++++- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/controllers/groups.js b/src/controllers/groups.js index 41ac5ab55f..c53a7e265e 100644 --- a/src/controllers/groups.js +++ b/src/controllers/groups.js @@ -60,7 +60,7 @@ api.updateMember = function(req, res) { member.balance += (req.body.contributor.level - (member.contributor.level || 0))*.5 // +2 gems per tier } _.merge(member, _.pick(req.body, 'contributor')); - if (member.contributor.level >= 6 && !member.items.pets['Dragon-Hydra']) member.items.pets['Dragon-Hydra'] = 5; + if (member.contributor.level >= 6) member.items.pets['Dragon-Hydra'] = 5; member.save(cb); } ], function(err, saved){ diff --git a/src/models/user.js b/src/models/user.js index 5a8b1206a2..0e12f5d3bd 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -15,6 +15,12 @@ var Challenge = require('./challenge').model; // User Schema // ----------- +var eggPotionMapping = _.transform(items.items.eggs, function(m, egg){ + _.defaults(m, _.transform(items.items.hatchingPotions, function(m2, pot){ + m2[egg.name + '-' + pot.name] = true; + })); +}) + var UserSchema = new Schema({ // ### UUID and API Token _id: { @@ -111,11 +117,17 @@ var UserSchema = new Schema({ // 'PandaCub-Red': 10, // Number represents "Growth Points" // etc... // } - pets: _.transform(items.items.eggs, function(m, egg){ - _.defaults(m, _.transform(items.items.hatchingPotions, function(m2, pot){ - m2[egg.name + '-' + pot.name] = Number; - })); - }), + pets: + _.defaults( + // First transform to a 1D eggs/potions mapping + _.transform(eggPotionMapping, function(m,v,k){ m[k] = Number; }), + // Then add additional pets (backer, contributor) + { + 'Wolf-Veteran': Number, + 'Wolf-Cerberus': Number, + 'Dragon-Hydra': Number + } + ), currentPet: String, // Cactus-Desert // eggs: { @@ -141,11 +153,15 @@ var UserSchema = new Schema({ // 'PandaCub-Red': false, // etc... // } - mounts: _.transform(items.items.eggs, function(m, egg){ - _.defaults(m, _.transform(items.items.hatchingPotions, function(m2, pot){ - m2[egg.name + '-' + pot.name] = Boolean; - })); - }), + mounts: _.defaults( + // First transform to a 1D eggs/potions mapping + _.transform(eggPotionMapping, function(m,v,k){ m[k] = Boolean; }), + // Then add additional pets (backer, contributor) + { + 'LionCub-Ethereal': Boolean, + 'BearCub-Polar': Boolean + } + ), currentMount: String, lastDrop: { diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 591566b689..71a5ad638c 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -25,10 +25,19 @@ script(type='text/ng-template', id='partials/options.inventory.stable.mounts.htm li.customize-menu(ng-repeat='egg in Items.eggs') menu div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='mount = egg.name+"-"+potion.name') - button(class="pet-button Pet-{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.name, potion.name)') + button(class="pet-button Mount_Body_{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.name, potion.name)') + div(class='Mount_Head_{{mount}}') button(class="pet-button pet-not-owned", ng-hide='user.items.mounts[mount]') img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') + h4 Rare Mounts + menu + div + button(ng-if='user.items.mounts["BearCub-Polar"]', class="pet-button Mount_Body_BearCub-Polar", ng-class='{active: user.items.currentMount == "BearCub-Polar")}', ng-click='chooseMount("BearCub", "Polar")', tooltip='Polar Bear') + .Mount_Head_BearCub-Polar + button(ng-if='user.items.mounts["LionCub-Ethereal"]', class="pet-button Mount_Body_LionCub-Ethereal", ng-class='{active: user.items.currentMount == "LionCub-Ethereal")}', ng-click='chooseMount("LionCub", "Ethereal")', tooltip='Ethereal Lion') + .Mount_Head_LionCub-Ethereal + script(type='text/ng-template', id='partials/options.inventory.stable.pets.html') .stable .NPC-Matt From 4c15905cd998e314dd2a825005a3c00ed95c2585 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 15:13:50 -0800 Subject: [PATCH 06/15] mounts: block creating mount if they already have it --- public/js/controllers/inventoryCtrl.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index a206f86bf7..3c2857dc45 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -122,8 +122,8 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', // Saddling a pet if ($scope.selectedFood.name == 'Saddle') { - if (userPets[pet] < 150) - return Notification.text(egg+" is not strong enough yet to saddle."); + if (userPets[pet] < 150) return Notification.text(egg+" is not strong enough yet to saddle."); + if (user.items.mounts[pet]) return Notification.text("You already have that mount"); if (!confirm('Saddle ' + pet + '?')) return; userPets[pet] = 0; setObj['items.mounts.' + pet] = true; From bd4385632feb2ed51e58567f8feaead776df919b Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 15:30:25 -0800 Subject: [PATCH 07/15] mounts: add migration --- migrations/20131109_refactor_pets.js | 35 +++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/migrations/20131109_refactor_pets.js b/migrations/20131109_refactor_pets.js index ea641885d8..1e85ff8fb2 100644 --- a/migrations/20131109_refactor_pets.js +++ b/migrations/20131109_refactor_pets.js @@ -1 +1,34 @@ -//TODO \ No newline at end of file +db.users.find({},{backer: 1, items:1}).forEach(function(user){ + user.items = { + armor: +user.items.armor || 0, + weapon: +user.items.weapon || 0, + head: +user.items.head || 0, + shield: +user.items.shield || 0, + + pets: _.reduce(user.items.pets, function(m,v){ m[v] = 5; return m;}, {}), + currentPet: user.items.currentPet ? user.items.currentPet.str : '', + eggs: _.reduce(user.items.eggs, function(m,v){ + if (!m[v.name]) m[v.name] = 0; + m[v.name]++; + return m; + }, {}), + + hatchingPotions: _.reduce(user.items.hatchingPotions, function(m,v){ + if (!m[v]) m[v] = 0; + m[v]++; + return m; + }, {}), + + food: {}, + + mounts: {}, + currentMount: '', + + lastDrop: user.items.lastDrop || {date: new Date(), count: 0} + }; + if (user.backer && user.backer.tier && user.backer.tier >= 90) { + user.items.mounts['LionCub-Ethereal'] = true; + } + + db.users.update({_id:user._id}, {$set:{items:user.items}}); +}); From 4f2a4b1f020c9295e786e069182067883dfb128d Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 17:17:24 -0800 Subject: [PATCH 08/15] mounts: rare mounts html fix --- views/options/inventory/stable.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 71a5ad638c..2d551a30cb 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -33,9 +33,9 @@ script(type='text/ng-template', id='partials/options.inventory.stable.mounts.htm h4 Rare Mounts menu div - button(ng-if='user.items.mounts["BearCub-Polar"]', class="pet-button Mount_Body_BearCub-Polar", ng-class='{active: user.items.currentMount == "BearCub-Polar")}', ng-click='chooseMount("BearCub", "Polar")', tooltip='Polar Bear') + button(ng-if='user.items.mounts["BearCub-Polar"]', class="pet-button Mount_Body_BearCub-Polar", ng-class='{active: user.items.currentMount == "BearCub-Polar"}', ng-click='chooseMount("BearCub", "Polar")', tooltip='Polar Bear') .Mount_Head_BearCub-Polar - button(ng-if='user.items.mounts["LionCub-Ethereal"]', class="pet-button Mount_Body_LionCub-Ethereal", ng-class='{active: user.items.currentMount == "LionCub-Ethereal")}', ng-click='chooseMount("LionCub", "Ethereal")', tooltip='Ethereal Lion') + button(ng-if='user.items.mounts["LionCub-Ethereal"]', class="pet-button Mount_Body_LionCub-Ethereal", ng-class='{active: user.items.currentMount == "LionCub-Ethereal"}', ng-click='chooseMount("LionCub", "Ethereal")', tooltip='Ethereal Lion') .Mount_Head_LionCub-Ethereal script(type='text/ng-template', id='partials/options.inventory.stable.pets.html') From 05c3e71a922ecd7b7321e92169fa1b2e43aedc71 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 19:18:06 -0800 Subject: [PATCH 09/15] mounts: fixes to starter food css --- public/css/inventory.styl | 17 +++++++++++++---- views/options/inventory/inventory.jade | 2 +- views/options/inventory/stable.jade | 8 ++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/public/css/inventory.styl b/public/css/inventory.styl index 3ba84b2bb6..77820be8ba 100644 --- a/public/css/inventory.styl +++ b/public/css/inventory.styl @@ -52,15 +52,24 @@ menu.pets div padding-right:20px padding-bottom:20px -.Pet_Food_Base, .Pet_Food_Zombie, .Pet_Food_White, .Pet_Food_Veteran, .Pet_Food_Skeleton, .Pet_Food_Shade, .Pet_Food_Red, .Pet_Food_Golden, .Pet_Food_Desert, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Zombie, .Pet_Food_White, .Pet_Food_Skeleton, .Pet_Food_Shade, .Pet_Food_Red, .Pet_Food_Golden, .Pet_Food_Desert, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Base, .Pet_Food_Base, .Pet_Food_Zombie, .Pet_Food_White, .Pet_Food_Skeleton, .Pet_Food_Shade, .Pet_Food_Red, .Pet_Food_Golden, .Pet_Food_Desert, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Base, .Pet_Food_Zombie, .Pet_Food_White, .Pet_Food_Skeleton, .Pet_Food_Shade, .Pet_Food_Red, .Pet_Food_Golden, .Pet_Food_Desert, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Base, .Pet_Food_Zombie, .Pet_Food_White, .Pet_Food_Skeleton, .Pet_Food_Shade, .Pet_Food_Red, .Pet_Food_Golden, .Pet_Food_Desert, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Base, .Pet_Food_Zombie, .Pet_Food_White, .Pet_Food_Skeleton, .Pet_Food_Shade, .Pet_Food_Red, .Pet_Food_Golden, .Pet_Food_Desert, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Base, .Pet_Food_Zombie, .Pet_Food_White, .Pet_Food_Skeleton, .Pet_Food_Shade, .Pet_Food_Red, .Pet_Food_Golden, .Pet_Food_Desert, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Base, .Pet_Food_SugarCube, .Pet_Food_Strawberry, .Pet_Food_Rotten, .Pet_Food_Licorice, .Pet_Food_Golden, .Pet_Food_Cream, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Chocolate, .Pet_Food_Base, .Pet_Food_Zombie, .Pet_Food_White, .Pet_Food_Skeleton, .Pet_Food_Shade, .Pet_Food_Red, .Pet_Food_Golden, .Pet_Food_Desert, .Pet_Food_CottonCandyPink, .Pet_Food_CottonCandyBlue, .Pet_Food_Base - background: url("/bower_components/habitrpg-shared/img/hatching_powder.png") no-repeat - width:34px - height:34px +// we'll remove this and place it into habitrpg-shared when we have art to work with +menu button[class*="Pet_Food_"] + width:48px + height:53px + margin-left: 1.25em .Pet_Currency_Gem, .Pet_Currency_Gem2x, .Pet_Currency_Gem1x background: url("/bower_components/habitrpg-shared/img/sprites/Egg_Sprite_Sheet.png") no-repeat display:block +.food-tray + position:fixed + right:0px + bottom:0px + width:30% + height: 50% + overflow-y: scroll + .Pet_Currency_Gem {background-position: 0px -510px; width: 51px; height: 45px} /* Not an egg or potion so has a different size */ .Pet_Currency_Gem2x {background-position: -55px -513px; width: 34px; height: 30px} .Pet_Currency_Gem1x {background-position: -63px -542px; width: 19px; height: 17px} diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index 95b5ff2be0..405ab408d9 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -23,7 +23,7 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') p {{pot}} li.customize-menu - menu.food-menu(label='Food ({{foodCount}})') + menu.pets-menu(label='Food ({{foodCount}})') p(ng-show='foodCount < 1') You don't have any food yet. div(ng-repeat='(food,points) in ownedItems(user.items.food)') button.customize-option(tooltip='{{food}}', ng-click='chooseFood(food)', class='Pet_Food_{{food}}') diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 2d551a30cb..13c1435483 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -70,11 +70,11 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' button(ng-if='!user.items.pets["Dragon-Hydra"]', class="pet-button pet-not-owned", popover-trigger='mouseenter', popover-placement='right', popover="Click the gold paw to learn more about how you can obtain this rare pet through contributing to HabitRPG!", popover-title='How to Get this Pet!') img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png') - .well(style='position:fixed;right:0px;top:50%;width:200px') - menu.inventory-list(type='list') + .well.food-tray + p(ng-show='foodCount < 1') You don't have any food yet. + menu.inventory-list(type='list', ng-if='foodCount > 0') li.customize-menu - menu.food-menu(label='Food') - p(ng-show='foodCount < 1') You don't have any food yet. + menu.pets-menu(label='Food') div(ng-repeat='(food,points) in ownedItems(user.items.food)') button.customize-option(tooltip='{{food}}', ng-click='chooseFood(food)', class='Pet_Food_{{food}}') .badge.badge-info.stack-count {{points}} From 543635dd371ff6452634ba3f09da21ca0190ddcc Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 19:20:34 -0800 Subject: [PATCH 10/15] mounts: change growth-points requirement to 50 (@lemoness) --- public/js/controllers/inventoryCtrl.js | 6 +++--- views/options/inventory/stable.jade | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index 3c2857dc45..abf9e1cf86 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -122,7 +122,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', // Saddling a pet if ($scope.selectedFood.name == 'Saddle') { - if (userPets[pet] < 150) return Notification.text(egg+" is not strong enough yet to saddle."); + if (userPets[pet] < 50) return Notification.text(egg+" is not strong enough yet to saddle."); if (user.items.mounts[pet]) return Notification.text("You already have that mount"); if (!confirm('Saddle ' + pet + '?')) return; userPets[pet] = 0; @@ -131,11 +131,11 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', setObj['items.currentPet'] = ''; Notification.text('You have tamed '+egg+", let's go for a ride!"); } else { - if (userPets[pet] >= 150) + if (userPets[pet] >= 50) return Notification.text(egg+" has become very strong and wild, try using a saddle and something might happen."); if (!confirm('Feed ' + pet + ' a ' + $scope.selectedFood.name + '?')) return; if ($scope.selectedFood.target == potion) { - userPets[pet] += 50; // FIXME change this to 5 before we're live + userPets[pet] += 5; Notification.text(egg+' really likes the '+$scope.selectedFood.name+'!'); } else { userPets[pet] += 2; diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 13c1435483..dfcc97816c 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -55,8 +55,8 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' menu div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='pet = egg.name+"-"+potion.name') button(class="pet-button Pet-{{pet}}", ng-if='user.items.pets[pet]>0', ng-class='{active: user.items.currentPet == pet}', ng-click='choosePet(egg.name, potion.name)') - .progress(ng-class='{"progress-success": user.items.pets[pet]<150}') - .bar(style="width: {{user.items.pets[pet]/1.5}}%;") + .progress(ng-class='{"progress-success": user.items.pets[pet]<50}') + .bar(style="width: {{user.items.pets[pet]/.5}}%;") button(class="pet-button pet-not-owned", ng-if='!user.items.pets[pet]') img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') From e6f524fce2eb7f4cb78901cf463da82f1bdb68e1 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 20:03:54 -0800 Subject: [PATCH 11/15] mounts: much cleaner inventory interface. Replace text (underneath) with gem cost. Use popover instead of tooltip, show item.text & item.notes for more details than before (especially useful for saddle). Screenshot: http://goo.gl/0AfLfG --- views/options/inventory/inventory.jade | 30 +++++++++++++++----------- views/options/inventory/stable.jade | 5 +++-- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index 405ab408d9..a88bbffd88 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -10,25 +10,25 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') p(ng-show='user.items.eggs.length < 1') You don't have any eggs yet. div(ng-repeat='(egg,points) in ownedItems(user.items.eggs)') //TODO move positioning this styling to css - button.customize-option(tooltip='{{Items.eggs[egg].text}}', ng-click='chooseEgg(egg)', class='Pet_Egg_{{egg}}', ng-class='{selectableInventory: selectedPotion && !user.items.pets[egg+"-"+selectedPotion.name]}') + button.customize-option(popover='{{Items.eggs[egg].notes}}', popover-title='{{Items.eggs[egg].text}} Egg', popover-trigger='mouseenter', popover-placement='right', ng-click='chooseEgg(egg)', class='Pet_Egg_{{egg}}', ng-class='{selectableInventory: selectedPotion && !user.items.pets[egg+"-"+selectedPotion.name]}') .badge.badge-info.stack-count {{points}} - p {{Items.eggs[egg].text}} + //-p {{Items.eggs[egg].text}} li.customize-menu menu.hatchingPotion-menu(label='Hatching Potions ({{potCount}})') p(ng-show='potCount < 1') You don't have any hatching potions yet. div(ng-repeat='(pot,points) in ownedItems(user.items.hatchingPotions)') - button.customize-option(tooltip='{{pot}}', ng-click='choosePotion(pot)', class='Pet_HatchingPotion_{{pot}}', ng-class='{selectableInventory: selectedEgg && !user.items.pets[selectedEgg.name+"-"+pot]}') + button.customize-option(popover='{{Items.hatchingPotions[pot].notes}}', popover-title='{{Items.hatchingPotions[pot].text}} Potion', popover-trigger='mouseenter', popover-placement='right', ng-click='choosePotion(pot)', class='Pet_HatchingPotion_{{pot}}', ng-class='{selectableInventory: selectedEgg && !user.items.pets[selectedEgg.name+"-"+pot]}') .badge.badge-info.stack-count {{points}} - p {{pot}} + //-p {{pot}} li.customize-menu menu.pets-menu(label='Food ({{foodCount}})') p(ng-show='foodCount < 1') You don't have any food yet. div(ng-repeat='(food,points) in ownedItems(user.items.food)') - button.customize-option(tooltip='{{food}}', ng-click='chooseFood(food)', class='Pet_Food_{{food}}') + button.customize-option(popover='{{Items.food[food].notes}}', popover-title='{{Items.food[food].text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='chooseFood(food)', class='Pet_Food_{{food}}') .badge.badge-info.stack-count {{points}} - p {{food}} + //-p {{food}} .span6 h2 Market @@ -57,20 +57,26 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') li.customize-menu menu.pets-menu(label='Eggs') div(ng-repeat='egg in Items.eggs') - button.customize-option(tooltip='{{egg.text}} - {{egg.value}} Gem(s)', ng-click='buy("egg", egg)', class='Pet_Egg_{{egg.name}}') - p {{egg.text}} + button.customize-option(popover='{{egg.notes}}', popover-title='{{egg.text}} Egg', popover-trigger='mouseenter', popover-placement='left', ng-click='buy("egg", egg)', class='Pet_Egg_{{egg.name}}') + p + | {{egg.value}} + span.Pet_Currency_Gem1x.inline-gems li.customize-menu menu.pets-menu(label='Hatching Potions') div(ng-repeat='pot in Items.hatchingPotions') - button.customize-option(tooltip='{{pot.text}} - {{pot.value}} Gem(s)', ng-click='buy("hatchingPotion", pot)', class='Pet_HatchingPotion_{{pot.name}}') - p {{pot.text}} + button.customize-option(popover='{{pot.notes}}', popover-title='{{pot.text}} Potion', popover-trigger='mouseenter', popover-placement='left', ng-click='buy("hatchingPotion", pot)', class='Pet_HatchingPotion_{{pot.name}}') + p + | {{pot.value}} + span.Pet_Currency_Gem1x.inline-gems li.customize-menu menu.pets-menu(label='Food') div(ng-repeat='food in Items.food') - button.customize-option(tooltip='{{food.text}} - {{food.value}} Gem(s)', ng-click='buy("food", food)', class='Pet_Food_{{food.name}}') - p {{food.text}} + button.customize-option(popover='{{food.notes}}', popover-title='{{food.text}}', popover-trigger='mouseenter', popover-placement='left', ng-click='buy("food", food)', class='Pet_Food_{{food.name}}') + p + | {{food.value}} + span.Pet_Currency_Gem1x.inline-gems diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index dfcc97816c..f8b03bf388 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -76,6 +76,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' li.customize-menu menu.pets-menu(label='Food') div(ng-repeat='(food,points) in ownedItems(user.items.food)') - button.customize-option(tooltip='{{food}}', ng-click='chooseFood(food)', class='Pet_Food_{{food}}') + button.customize-option(popover-append-to-body='true', popover='{{Items.food[food].notes}}', popover-title='{{Items.food[food].text}}', popover-trigger='mouseenter', popover-placement='left', ng-click='chooseFood(food)', class='Pet_Food_{{food}}') .badge.badge-info.stack-count {{points}} - p {{food}} \ No newline at end of file + // Remove this once we have images in + p {{Items.food[food].text}} \ No newline at end of file From e990850b015d481a15d1061d8f96eceb8fd91dd8 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 20:23:14 -0800 Subject: [PATCH 12/15] mounts: new saddle logic. saddles don't drop, can only purchase for 5G. Saddle instantly raises pet=>mount (full 50pts). Saddles no longer required as "finisher" item. (@lemoness) --- public/js/controllers/inventoryCtrl.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index abf9e1cf86..351d9d6f7b 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -119,20 +119,20 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', if ($scope.selectedFood) { var setObj = {}; var userPets = user.items.pets; + if (user.items.mounts[pet] && (userPets[pet] >= 50 || $scope.selectedFood.name == 'Saddle')) + return Notification.text("You already have that mount"); - // Saddling a pet - if ($scope.selectedFood.name == 'Saddle') { - if (userPets[pet] < 50) return Notification.text(egg+" is not strong enough yet to saddle."); - if (user.items.mounts[pet]) return Notification.text("You already have that mount"); - if (!confirm('Saddle ' + pet + '?')) return; + var evolve = function(){ userPets[pet] = 0; setObj['items.mounts.' + pet] = true; - if (pet == user.items.currentPet) - setObj['items.currentPet'] = ''; + if (pet == user.items.currentPet) setObj['items.currentPet'] = ''; Notification.text('You have tamed '+egg+", let's go for a ride!"); + } + // Saddling a pet + if ($scope.selectedFood.name == 'Saddle') { + if (!confirm('Saddle ' + pet + '?')) return; + evolve(); } else { - if (userPets[pet] >= 50) - return Notification.text(egg+" has become very strong and wild, try using a saddle and something might happen."); if (!confirm('Feed ' + pet + ' a ' + $scope.selectedFood.name + '?')) return; if ($scope.selectedFood.target == potion) { userPets[pet] += 5; @@ -141,6 +141,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', userPets[pet] += 2; Notification.text(egg+' eats the '+$scope.selectedFood.name+" but doesn't seem to enjoy it."); } + if (userPets[pet] >= 50 && !user.items.mounts[pet]) evolve(); } setObj['items.pets.' + pet] = userPets[pet]; setObj['items.food.' + $scope.selectedFood.name] = user.items.food[$scope.selectedFood.name] - 1; From bfbc907fa1fb066488d29da353207c09e0db3f73 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sun, 10 Nov 2013 22:53:20 -0800 Subject: [PATCH 13/15] mounts: show when selectedFood by green-circle highlighting pets --- public/css/inventory.styl | 1 + public/js/controllers/inventoryCtrl.js | 1 + views/options/inventory/stable.jade | 8 ++++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/public/css/inventory.styl b/public/css/inventory.styl index 77820be8ba..f9ed52f076 100644 --- a/public/css/inventory.styl +++ b/public/css/inventory.styl @@ -134,6 +134,7 @@ menu.pets .customize-menu .selectableInventory background-color: lightgreen !important + border-radius: 50% .sell-inventory width: 162px diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index 351d9d6f7b..ce090d18ec 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -47,6 +47,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', } $scope.chooseFood = function(food){ + if ($scope.selectedFood && $scope.selectedFood.name == food) return $scope.selectedFood = null; $scope.selectedFood = $scope.Items.food[food]; } diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index f8b03bf388..151a60beff 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -54,7 +54,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' li.customize-menu(ng-repeat='egg in Items.eggs') menu div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='pet = egg.name+"-"+potion.name') - button(class="pet-button Pet-{{pet}}", ng-if='user.items.pets[pet]>0', ng-class='{active: user.items.currentPet == pet}', ng-click='choosePet(egg.name, potion.name)') + button(class="pet-button Pet-{{pet}}", ng-if='user.items.pets[pet]>0', ng-class='{active: user.items.currentPet == pet, selectableInventory: selectedFood}', ng-click='choosePet(egg.name, potion.name)') .progress(ng-class='{"progress-success": user.items.pets[pet]<50}') .bar(style="width: {{user.items.pets[pet]/.5}}%;") button(class="pet-button pet-not-owned", ng-if='!user.items.pets[pet]') @@ -63,9 +63,9 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' h4 Rare Pets menu div - button(ng-if='user.items.pets["Wolf-Veteran"]', class="pet-button Pet-Wolf-Veteran", ng-class='{active: user.items.currentPet == "Wolf-Veteran")}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf') - button(ng-if='user.items.pets["Wolf-Cerberus"]', class="pet-button Pet-Wolf-Cerberus", ng-class='{active: user.items.currentPet == "Wolf-Cerberus")}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') - button(ng-if='user.items.pets["Dragon-Hydra"]', class="pet-button Pet-Dragon-Hydra", ng-class='{active: user.items.currentPet == "Dragon-Hydra")}', ng-click='choosePet("Dragon", "Hydra")', tooltip='Hydra Pet') + button(ng-if='user.items.pets["Wolf-Veteran"]', class="pet-button Pet-Wolf-Veteran", ng-class='{active: user.items.currentPet == "Wolf-Veteran"}', ng-click='choosePet("Wolf", "Veteran")', tooltip='Veteran Wolf') + button(ng-if='user.items.pets["Wolf-Cerberus"]', class="pet-button Pet-Wolf-Cerberus", ng-class='{active: user.items.currentPet == "Wolf-Cerberus"}', ng-click='choosePet("Wolf", "Cerberus")', tooltip='Cerberus Pup') + button(ng-if='user.items.pets["Dragon-Hydra"]', class="pet-button Pet-Dragon-Hydra", ng-class='{active: user.items.currentPet == "Dragon-Hydra"}', ng-click='choosePet("Dragon", "Hydra")', tooltip='Hydra Pet') a(target='_blank', href='https://github.com/HabitRPG/habitrpg/wiki/Contributing') button(ng-if='!user.items.pets["Dragon-Hydra"]', class="pet-button pet-not-owned", popover-trigger='mouseenter', popover-placement='right', popover="Click the gold paw to learn more about how you can obtain this rare pet through contributing to HabitRPG!", popover-title='How to Get this Pet!') img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png') From dda3670d036fa3a78d7ad5ab1091bf50e9cac75e Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Mon, 11 Nov 2013 13:50:11 -0800 Subject: [PATCH 14/15] mounts: only show mount head in stable (fix later), use egg.mountText for grown mount popovers. replace pet/mount tooltips with popovers --- views/options/inventory/stable.jade | 16 ++++++++-------- views/shared/header/avatar.jade | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 151a60beff..b45d7ed36d 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -24,19 +24,19 @@ script(type='text/ng-template', id='partials/options.inventory.stable.mounts.htm menu.pets(type='list') li.customize-menu(ng-repeat='egg in Items.eggs') menu - div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='mount = egg.name+"-"+potion.name') - button(class="pet-button Mount_Body_{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.name, potion.name)') - div(class='Mount_Head_{{mount}}') + div(ng-repeat='potion in Items.hatchingPotions', popover-trigger='mouseenter', popover='{{potion.text}} {{egg.mountText}}', ng-init='mount = egg.name+"-"+potion.name') + button(class="pet-button Mount_Head_{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.name, potion.name)') + //div(class='Mount_Head_{{mount}}') button(class="pet-button pet-not-owned", ng-hide='user.items.mounts[mount]') img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') h4 Rare Mounts menu div - button(ng-if='user.items.mounts["BearCub-Polar"]', class="pet-button Mount_Body_BearCub-Polar", ng-class='{active: user.items.currentMount == "BearCub-Polar"}', ng-click='chooseMount("BearCub", "Polar")', tooltip='Polar Bear') - .Mount_Head_BearCub-Polar - button(ng-if='user.items.mounts["LionCub-Ethereal"]', class="pet-button Mount_Body_LionCub-Ethereal", ng-class='{active: user.items.currentMount == "LionCub-Ethereal"}', ng-click='chooseMount("LionCub", "Ethereal")', tooltip='Ethereal Lion') - .Mount_Head_LionCub-Ethereal + button(ng-if='user.items.mounts["BearCub-Polar"]', class="pet-button Mount_Head_BearCub-Polar", ng-class='{active: user.items.currentMount == "BearCub-Polar"}', ng-click='chooseMount("BearCub", "Polar")', tooltip='Polar Bear') + //.Mount_Head_BearCub-Polar + button(ng-if='user.items.mounts["LionCub-Ethereal"]', class="pet-button Mount_Head_LionCub-Ethereal", ng-class='{active: user.items.currentMount == "LionCub-Ethereal"}', ng-click='chooseMount("LionCub", "Ethereal")', tooltip='Ethereal Lion') + //.Mount_Head_LionCub-Ethereal script(type='text/ng-template', id='partials/options.inventory.stable.pets.html') .stable @@ -53,7 +53,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' menu.pets(type='list') li.customize-menu(ng-repeat='egg in Items.eggs') menu - div(ng-repeat='potion in Items.hatchingPotions', tooltip='{{potion.name}} {{egg.name}}', ng-init='pet = egg.name+"-"+potion.name') + div(ng-repeat='potion in Items.hatchingPotions', popover-trigger='mouseenter', popover='{{potion.text}} {{egg.text}}', ng-init='pet = egg.name+"-"+potion.name') button(class="pet-button Pet-{{pet}}", ng-if='user.items.pets[pet]>0', ng-class='{active: user.items.currentPet == pet, selectableInventory: selectedFood}', ng-click='choosePet(egg.name, potion.name)') .progress(ng-class='{"progress-success": user.items.pets[pet]<50}') .bar(style="width: {{user.items.pets[pet]/.5}}%;") diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 5df250fa8f..3154f5f92d 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -6,7 +6,7 @@ figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: user._id==profile._id && !(user.items.currentMount && user.items.currentPet), hasPet: profile.items.currentPet && profile.items.currentMount}') .character-sprites // Mount Body - span(class='Mount_Body_{{profile.items.currentMount}}') + span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}') // Avatar span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') @@ -18,7 +18,7 @@ figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}') // Mount Head - span(class='Mount_Head_{{profile.items.currentMount}}') + span(ng-if='profile.items.currentMount', class='Mount_Head_{{profile.items.currentMount}}') // Resting span(ng-class='{zzz:profile.flags.rest}') From d245c87f295e347f79162aa9a125e9539eb6b69f Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 14 Nov 2013 12:59:00 -0800 Subject: [PATCH 15/15] mounts: temporarily remove mounts code from views. merging to master so we can run schema migration and start with item translations. This commit will be reverted when mounts is fully merged --- views/options/inventory/inventory.jade | 4 ++-- views/options/inventory/stable.jade | 28 ++++++++++++++------------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index a88bbffd88..febf372a48 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -22,7 +22,7 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') .badge.badge-info.stack-count {{points}} //-p {{pot}} - li.customize-menu + //-li.customize-menu menu.pets-menu(label='Food ({{foodCount}})') p(ng-show='foodCount < 1') You don't have any food yet. div(ng-repeat='(food,points) in ownedItems(user.items.food)') @@ -70,7 +70,7 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') | {{pot.value}} span.Pet_Currency_Gem1x.inline-gems - li.customize-menu + //-li.customize-menu menu.pets-menu(label='Food') div(ng-repeat='food in Items.food') button.customize-option(popover='{{food.notes}}', popover-title='{{food.text}}', popover-trigger='mouseenter', popover-placement='left', ng-click='buy("food", food)', class='Pet_Food_{{food.name}}') diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index b45d7ed36d..15af5a5f28 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -1,14 +1,16 @@ script(type='text/ng-template', id='partials/options.inventory.stable.html') - ul.nav.nav-tabs - li(ng-class="{ active: $state.includes('options.inventory.stable.pets') }") - a(ui-sref='options.inventory.stable.pets') - | Pets - li(ng-class="{ active: $state.includes('options.inventory.stable.mounts') }") - a(ui-sref='options.inventory.stable.mounts') - | Mounts - .tab-content - .tab-pane.active - div(ui-view) + div(ui-view) + //- + ul.nav.nav-tabs + li(ng-class="{ active: $state.includes('options.inventory.stable.pets') }") + a(ui-sref='options.inventory.stable.pets') + | Pets + li(ng-class="{ active: $state.includes('options.inventory.stable.mounts') }") + a(ui-sref='options.inventory.stable.mounts') + | Mounts + .tab-content + .tab-pane.active + div(ui-view) script(type='text/ng-template', id='partials/options.inventory.stable.mounts.html') .stable @@ -47,7 +49,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch .popover-content p. - Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to venture at your side. Feed them and they'll grow into powerful steeds. Have a look-see at all the pets you can collect. + Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to venture at your side. Have a look-see at all the pets you can collect. h4 {{petCount}} / {{totalPets}} Pets Found menu.pets(type='list') @@ -55,7 +57,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' menu div(ng-repeat='potion in Items.hatchingPotions', popover-trigger='mouseenter', popover='{{potion.text}} {{egg.text}}', ng-init='pet = egg.name+"-"+potion.name') button(class="pet-button Pet-{{pet}}", ng-if='user.items.pets[pet]>0', ng-class='{active: user.items.currentPet == pet, selectableInventory: selectedFood}', ng-click='choosePet(egg.name, potion.name)') - .progress(ng-class='{"progress-success": user.items.pets[pet]<50}') + //-.progress(ng-class='{"progress-success": user.items.pets[pet]<50}') .bar(style="width: {{user.items.pets[pet]/.5}}%;") button(class="pet-button pet-not-owned", ng-if='!user.items.pets[pet]') img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') @@ -70,7 +72,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' button(ng-if='!user.items.pets["Dragon-Hydra"]', class="pet-button pet-not-owned", popover-trigger='mouseenter', popover-placement='right', popover="Click the gold paw to learn more about how you can obtain this rare pet through contributing to HabitRPG!", popover-title='How to Get this Pet!') img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png') - .well.food-tray + //-.well.food-tray p(ng-show='foodCount < 1') You don't have any food yet. menu.inventory-list(type='list', ng-if='foodCount > 0') li.customize-menu