mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
Merge branch 'mounts' into develop
Conflicts: views/options/inventory/stable.jade
This commit is contained in:
34
migrations/20131109_refactor_pets.js
Normal file
34
migrations/20131109_refactor_pets.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
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}});
|
||||||
|
});
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"version": "0.0.0-152",
|
"version": "0.0.0-152",
|
||||||
"main": "./src/server.js",
|
"main": "./src/server.js",
|
||||||
"dependencies": {
|
"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",
|
"derby-auth": "git://github.com/lefnire/derby-auth#master",
|
||||||
"connect-mongo": "*",
|
"connect-mongo": "*",
|
||||||
"passport-facebook": "~1.0.0",
|
"passport-facebook": "~1.0.0",
|
||||||
|
|||||||
@@ -52,23 +52,40 @@ menu.pets div
|
|||||||
padding-right:20px
|
padding-right:20px
|
||||||
padding-bottom: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
|
// we'll remove this and place it into habitrpg-shared when we have art to work with
|
||||||
background: url("/bower_components/habitrpg-shared/img/hatching_powder.png") no-repeat
|
menu button[class*="Pet_Food_"]
|
||||||
width:34px
|
width:48px
|
||||||
height:34px
|
height:53px
|
||||||
|
margin-left: 1.25em
|
||||||
|
|
||||||
.Pet_Currency_Gem, .Pet_Currency_Gem2x, .Pet_Currency_Gem1x
|
.Pet_Currency_Gem, .Pet_Currency_Gem2x, .Pet_Currency_Gem1x
|
||||||
background: url("/bower_components/habitrpg-shared/img/sprites/Egg_Sprite_Sheet.png") no-repeat
|
background: url("/bower_components/habitrpg-shared/img/sprites/Egg_Sprite_Sheet.png") no-repeat
|
||||||
display:block
|
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_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_Gem2x {background-position: -55px -513px; width: 34px; height: 30px}
|
||||||
.Pet_Currency_Gem1x {background-position: -63px -542px; width: 19px; height: 17px}
|
.Pet_Currency_Gem1x {background-position: -63px -542px; width: 19px; height: 17px}
|
||||||
|
|
||||||
.inventory-list p
|
.inventory-list
|
||||||
|
p
|
||||||
//display: none
|
//display: none
|
||||||
.inventory-list li
|
li
|
||||||
clear:both
|
clear:both
|
||||||
|
button.customize-option
|
||||||
|
position:relative
|
||||||
|
.stack-count
|
||||||
|
position:absolute
|
||||||
|
bottom:-6px
|
||||||
|
right:-9px
|
||||||
|
|
||||||
.pets-menu > div
|
.pets-menu > div
|
||||||
display:inline-block
|
display:inline-block
|
||||||
vertical-align:top
|
vertical-align:top
|
||||||
@@ -90,6 +107,17 @@ menu.pets div
|
|||||||
width:6em
|
width:6em
|
||||||
margin-top:-.5em
|
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
|
.pet-button
|
||||||
border: none
|
border: none
|
||||||
background: none white
|
background: none white
|
||||||
@@ -106,6 +134,7 @@ menu.pets div
|
|||||||
|
|
||||||
.selectableInventory
|
.selectableInventory
|
||||||
background-color: lightgreen !important
|
background-color: lightgreen !important
|
||||||
|
border-radius: 50%
|
||||||
|
|
||||||
.sell-inventory
|
.sell-inventory
|
||||||
width: 162px
|
width: 162px
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ window.habitrpg = angular.module('habitrpg',
|
|||||||
.when('/options/groups', '/options/groups/tavern')
|
.when('/options/groups', '/options/groups/tavern')
|
||||||
.when('/options/groups/guilds', '/options/groups/guilds/public')
|
.when('/options/groups/guilds', '/options/groups/guilds/public')
|
||||||
.when('/options/inventory', '/options/inventory/inventory')
|
.when('/options/inventory', '/options/inventory/inventory')
|
||||||
|
.when('/options/inventory/stable', '/options/inventory/stable/pets')
|
||||||
|
|
||||||
// redirect states that don't match
|
// redirect states that don't match
|
||||||
.otherwise("/tasks");
|
.otherwise("/tasks");
|
||||||
@@ -134,7 +135,8 @@ window.habitrpg = angular.module('habitrpg',
|
|||||||
// Options > Inventory
|
// Options > Inventory
|
||||||
.state('options.inventory', {
|
.state('options.inventory', {
|
||||||
url: '/inventory',
|
url: '/inventory',
|
||||||
templateUrl: "partials/options.inventory.html"
|
templateUrl: "partials/options.inventory.html",
|
||||||
|
controller: 'InventoryCtrl'
|
||||||
})
|
})
|
||||||
.state('options.inventory.inventory', {
|
.state('options.inventory.inventory', {
|
||||||
url: '/inventory',
|
url: '/inventory',
|
||||||
@@ -144,6 +146,14 @@ window.habitrpg = angular.module('habitrpg',
|
|||||||
url: '/stable',
|
url: '/stable',
|
||||||
templateUrl: "partials/options.inventory.stable.html"
|
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
|
// Options > Settings
|
||||||
.state('options.settings', {
|
.state('options.settings', {
|
||||||
|
|||||||
@@ -1,18 +1,31 @@
|
|||||||
habitrpg.controller("InventoryCtrl", ['$scope', 'User',
|
habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', '$http', 'Notification',
|
||||||
function($scope, User) {
|
function($rootScope, $scope, User, API_URL, $http, Notification) {
|
||||||
|
|
||||||
|
var user = User.user;
|
||||||
|
|
||||||
// convenience vars since these are accessed frequently
|
// 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.selectedEgg = null; // {index: 1, name: "Tiger", value: 5}
|
||||||
$scope.selectedPotion = null; // {index: 5, name: "Red", value: 3}
|
$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){
|
// count egg, food, hatchingPotion stack totals
|
||||||
if ($scope.selectedEgg && $scope.selectedEgg.index == $index) {
|
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) {
|
||||||
return $scope.selectedEgg = null; // clicked same egg, unselect
|
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) {
|
if (!$scope.selectedPotion) {
|
||||||
$scope.selectedEgg = eggData;
|
$scope.selectedEgg = eggData;
|
||||||
} else {
|
} else {
|
||||||
@@ -20,13 +33,12 @@ habitrpg.controller("InventoryCtrl", ['$scope', 'User',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.choosePotion = function(potion, $index){
|
$scope.choosePotion = function(potion){
|
||||||
if ($scope.selectedPotion && $scope.selectedPotion.index == $index) {
|
if ($scope.selectedPotion && $scope.selectedPotion.name == potion) {
|
||||||
return $scope.selectedPotion = null; // clicked same egg, unselect
|
return $scope.selectedPotion = null; // clicked same egg, unselect
|
||||||
}
|
}
|
||||||
// we really didn't think through the way these things are stored and getting passed around...
|
// 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});
|
var potionData = _.findWhere(window.habitrpgShared.items.items.hatchingPotions, {name:potion});
|
||||||
potionData = _.defaults({index:$index}, potionData);
|
|
||||||
if (!$scope.selectedEgg) {
|
if (!$scope.selectedEgg) {
|
||||||
$scope.selectedPotion = potionData;
|
$scope.selectedPotion = potionData;
|
||||||
} else {
|
} else {
|
||||||
@@ -34,54 +46,53 @@ habitrpg.controller("InventoryCtrl", ['$scope', 'User',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$scope.chooseFood = function(food){
|
||||||
|
if ($scope.selectedFood && $scope.selectedFood.name == food) return $scope.selectedFood = null;
|
||||||
|
$scope.selectedFood = $scope.Items.food[food];
|
||||||
|
}
|
||||||
|
|
||||||
$scope.sellInventory = function() {
|
$scope.sellInventory = function() {
|
||||||
|
// TODO DRY this
|
||||||
if ($scope.selectedEgg) {
|
if ($scope.selectedEgg) {
|
||||||
$scope.userEggs.splice($scope.selectedEgg.index, 1);
|
user.items.eggs[$scope.selectedEgg.name]--;
|
||||||
User.setMultiple({
|
User.setMultiple({
|
||||||
'items.eggs': $scope.userEggs,
|
'items.eggs': user.items.eggs,
|
||||||
'stats.gp': User.user.stats.gp + $scope.selectedEgg.value
|
'stats.gp': User.user.stats.gp + $scope.selectedEgg.value
|
||||||
});
|
});
|
||||||
$scope.selectedEgg = null;
|
$scope.selectedEgg = null;
|
||||||
} else if ($scope.selectedPotion) {
|
} else if ($scope.selectedPotion) {
|
||||||
$scope.userHatchingPotions.splice($scope.selectedPotion.index, 1);
|
user.items.hatchingPotions[$scope.selectedPotion.name]--;
|
||||||
User.setMultiple({
|
User.setMultiple({
|
||||||
'items.hatchingPotions': $scope.userHatchingPotions,
|
'items.hatchingPotions': user.items.hatchingPotions,
|
||||||
'stats.gp': User.user.stats.gp + $scope.selectedPotion.value
|
'stats.gp': User.user.stats.gp + $scope.selectedPotion.value
|
||||||
});
|
});
|
||||||
$scope.selectedPotion = null;
|
$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){
|
$scope.ownedItems = function(inventory){
|
||||||
if (!egg || !potion) return;
|
return _.pick(inventory, function(v,k){return v>0;});
|
||||||
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.hatch = function(egg, potion){
|
$scope.hatch = function(egg, potion){
|
||||||
if ($scope.ownsPet(egg, potion.name)){
|
var pet = egg.name+"-"+potion.name;
|
||||||
return alert("You already have that pet, hatch a different combo.")
|
if (user.items.pets[pet])
|
||||||
}
|
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);
|
|
||||||
|
|
||||||
if(!User.user.items.pets) User.user.items.pets = [];
|
var setObj = {};
|
||||||
User.user.items.pets.push(pet);
|
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([
|
User.setMultiple(setObj);
|
||||||
{ op: 'set', data: {'items.pets': User.user.items.pets} },
|
|
||||||
{ op: 'set', data: {'items.eggs': $scope.userEggs} },
|
|
||||||
{ op: 'set', data: {'items.hatchingPotions': $scope.userHatchingPotions} }
|
|
||||||
]);
|
|
||||||
|
|
||||||
alert("Your egg hatched! Visit your stable to equip your pet.");
|
alert("Your egg hatched! Visit your stable to equip your pet.");
|
||||||
|
|
||||||
@@ -89,4 +100,71 @@ habitrpg.controller("InventoryCtrl", ['$scope', 'User',
|
|||||||
$scope.selectedPotion = null;
|
$scope.selectedPotion = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}]);
|
$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;
|
||||||
|
if (user.items.mounts[pet] && (userPets[pet] >= 50 || $scope.selectedFood.name == 'Saddle'))
|
||||||
|
return Notification.text("You already have that mount");
|
||||||
|
|
||||||
|
var evolve = function(){
|
||||||
|
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!");
|
||||||
|
}
|
||||||
|
// Saddling a pet
|
||||||
|
if ($scope.selectedFood.name == 'Saddle') {
|
||||||
|
if (!confirm('Saddle ' + pet + '?')) return;
|
||||||
|
evolve();
|
||||||
|
} else {
|
||||||
|
if (!confirm('Feed ' + pet + ' a ' + $scope.selectedFood.name + '?')) return;
|
||||||
|
if ($scope.selectedFood.target == potion) {
|
||||||
|
userPets[pet] += 5;
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
User.setMultiple(setObj);
|
||||||
|
$scope.selectedFood = null;
|
||||||
|
|
||||||
|
// Selecting Pet
|
||||||
|
} else {
|
||||||
|
var userCurrentPet = User.user.items.currentPet;
|
||||||
|
if(userCurrentPet && userCurrentPet == pet){
|
||||||
|
User.user.items.currentPet = '';
|
||||||
|
}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) ? '' : mount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
]);
|
||||||
@@ -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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}]);
|
|
||||||
@@ -43,8 +43,8 @@ habitrpg.controller('NotificationCtrl',
|
|||||||
$rootScope.modals.achievements.ultimateGear = true;
|
$rootScope.modals.achievements.ultimateGear = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
$rootScope.$watch('user.items.pets.length', function(after, before){
|
$rootScope.$watch('user.items.pets', function(after, before){
|
||||||
if(after === before || after < 90) return;
|
if(_.size(after) === _.size(before) || _.size(after) < 90) return;
|
||||||
User.user.achievements.beastMaster = true;
|
User.user.achievements.beastMaster = true;
|
||||||
$rootScope.modals.achievements.beastMaster = true;
|
$rootScope.modals.achievements.beastMaster = true;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}]);
|
|
||||||
@@ -10,6 +10,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
|
|||||||
$rootScope.User = User;
|
$rootScope.User = User;
|
||||||
$rootScope.user = User.user;
|
$rootScope.user = User.user;
|
||||||
$rootScope.settings = User.settings;
|
$rootScope.settings = User.settings;
|
||||||
|
$rootScope.Items = window.habitrpgShared.items.items;
|
||||||
|
|
||||||
// Angular UI Router
|
// Angular UI Router
|
||||||
$rootScope.$state = $state;
|
$rootScope.$state = $state;
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ angular.module('habitrpg')
|
|||||||
return function (gp) {
|
return function (gp) {
|
||||||
return Math.floor(gp);
|
return Math.floor(gp);
|
||||||
}
|
}
|
||||||
}).filter('silver', function () {
|
})
|
||||||
|
.filter('silver', function () {
|
||||||
return function (gp) {
|
return function (gp) {
|
||||||
return Math.floor((gp - Math.floor(gp))*100);
|
return Math.floor((gp - Math.floor(gp))*100);
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
@@ -96,13 +96,6 @@ angular.module('guideServices', []).
|
|||||||
showPopover('div.rewards', 'Item Store Unlocked', html, 'left');
|
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) {
|
$rootScope.$watch('user.flags.partyEnabled', function(after, before) {
|
||||||
if (alreadyShown(before, after)) return;
|
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?";
|
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) {
|
$rootScope.$watch('user.flags.dropsEnabled', function(after, before) {
|
||||||
if (alreadyShown(before, after)) return;
|
if (alreadyShown(before, after)) return;
|
||||||
var drop = Helpers.randomVal(Items.items.pets);
|
var eggs = User.user.items.eggs || {};
|
||||||
var eggs = User.user.items.eggs || [];
|
eggs['Wolf'] = 1; // This is also set on the server
|
||||||
eggs.push(drop); // FIXME put this on server instead
|
|
||||||
User.set('items.eggs', eggs);
|
|
||||||
$rootScope.modals.dropsEnabled = true;
|
$rootScope.modals.dropsEnabled = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -50,9 +50,7 @@
|
|||||||
"js/controllers/filtersCtrl.js",
|
"js/controllers/filtersCtrl.js",
|
||||||
"js/controllers/userCtrl.js",
|
"js/controllers/userCtrl.js",
|
||||||
"js/controllers/groupsCtrl.js",
|
"js/controllers/groupsCtrl.js",
|
||||||
"js/controllers/petsCtrl.js",
|
|
||||||
"js/controllers/inventoryCtrl.js",
|
"js/controllers/inventoryCtrl.js",
|
||||||
"js/controllers/marketCtrl.js",
|
|
||||||
"js/controllers/footerCtrl.js",
|
"js/controllers/footerCtrl.js",
|
||||||
"js/controllers/challengesCtrl.js",
|
"js/controllers/challengesCtrl.js",
|
||||||
"js/controllers/adminCtrl.js"
|
"js/controllers/adminCtrl.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
|
member.balance += (req.body.contributor.level - (member.contributor.level || 0))*.5 // +2 gems per tier
|
||||||
}
|
}
|
||||||
_.merge(member, _.pick(req.body, 'contributor'));
|
_.merge(member, _.pick(req.body, 'contributor'));
|
||||||
if (!member.items.pets) member.items.pets = [];
|
if (member.contributor.level >= 6) member.items.pets['Dragon-Hydra'] = 5;
|
||||||
var i = member.items.pets.indexOf('Dragon-Hydra');
|
|
||||||
if (!~i && member.contributor.level >= 6) member.items.pets.push('Dragon-Hydra');
|
|
||||||
member.save(cb);
|
member.save(cb);
|
||||||
}
|
}
|
||||||
], function(err, saved){
|
], function(err, saved){
|
||||||
|
|||||||
@@ -22,17 +22,11 @@ api.marketBuy = function(req, res, next){
|
|||||||
type = req.query.type,
|
type = req.query.type,
|
||||||
item = req.body;
|
item = req.body;
|
||||||
|
|
||||||
if (!_.contains(['hatchingPotion', 'egg'], req.query.type))
|
if (!_.contains(['hatchingPotion', 'egg', 'food'], type))
|
||||||
return res.json(400, {err: "Type must be in 'hatchingPotion' or 'egg'"});
|
return res.json(400, {err: "Type must be 'hatchingPotion', 'egg', or 'food'"});
|
||||||
var item;
|
type = (type == 'food' ? type : type + 's'); // I'm stupid, we're passing up 'hatchingPotion' but we need 'hatchingPotions'
|
||||||
if (type == 'egg'){
|
if (!user.items[type][item.name]) user.items[type][item.name] = 0;
|
||||||
if (!user.items && !user.items.eggs) user.items.eggs = [];
|
user.items[type][item.name]++;
|
||||||
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..
|
|
||||||
user.balance -= (item.value/4);
|
user.balance -= (item.value/4);
|
||||||
user.save(function(err, saved){
|
user.save(function(err, saved){
|
||||||
if (err) return res.json(500, {err:err});
|
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(' ');
|
acceptableAttrs = 'tasks. achievements. filters. flags. invitations. items. lastCron party. preferences. profile. stats. tags custom.'.split(' ');
|
||||||
_.each(req.body, function(v, k) {
|
_.each(req.body, function(v, k) {
|
||||||
if ((_.find(acceptableAttrs, function(attr) {
|
var found = _.find(acceptableAttrs, function(attr) { return k.indexOf(attr) == 0; })
|
||||||
return k.indexOf(attr) === 0;
|
if (found) {
|
||||||
})) != null) {
|
// if (_.isObject(v)) {
|
||||||
if (_.isObject(v)) {
|
// errors.push("Value for " + k + " was an object. Be careful here, you could clobber stuff.");
|
||||||
errors.push("Value for " + k + " was an object. Be careful here, you could clobber stuff.");
|
// }
|
||||||
}
|
|
||||||
helpers.dotSet(k, v, user);
|
helpers.dotSet(k, v, user);
|
||||||
} else {
|
} 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}}}`");
|
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 true;
|
||||||
});
|
});
|
||||||
return user.save(function(err) {
|
user.save(function(err) {
|
||||||
if (!_.isEmpty(errors)) {
|
if (!_.isEmpty(errors)) return res.json(500, {err: errors});
|
||||||
return res.json(500, {
|
if (err) {return res.json(500, {err: err})}
|
||||||
err: errors
|
res.json(200, user);
|
||||||
});
|
|
||||||
}
|
|
||||||
if (err) {
|
|
||||||
return res.json(500, {
|
|
||||||
err: err
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return res.json(200, user);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
var mongoose = require("mongoose");
|
var mongoose = require("mongoose");
|
||||||
var Schema = mongoose.Schema;
|
var Schema = mongoose.Schema;
|
||||||
var helpers = require('habitrpg-shared/script/helpers');
|
var helpers = require('habitrpg-shared/script/helpers');
|
||||||
|
var items = require('habitrpg-shared/script/items');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var TaskSchema = require('./task').schema;
|
var TaskSchema = require('./task').schema;
|
||||||
var Challenge = require('./challenge').model;
|
var Challenge = require('./challenge').model;
|
||||||
@@ -14,6 +15,12 @@ var Challenge = require('./challenge').model;
|
|||||||
// User Schema
|
// 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({
|
var UserSchema = new Schema({
|
||||||
// ### UUID and API Token
|
// ### UUID and API Token
|
||||||
_id: {
|
_id: {
|
||||||
@@ -83,7 +90,6 @@ var UserSchema = new Schema({
|
|||||||
newStuff: {type: Boolean, 'default': false},
|
newStuff: {type: Boolean, 'default': false},
|
||||||
rewrite: {type: Boolean, 'default': true},
|
rewrite: {type: Boolean, 'default': true},
|
||||||
partyEnabled: Boolean, // FIXME do we need this?
|
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
|
rest: {type: Boolean, 'default': false}, // fixme - change to preferences.resting once we're off derby
|
||||||
contributor: Boolean
|
contributor: Boolean
|
||||||
},
|
},
|
||||||
@@ -92,7 +98,7 @@ var UserSchema = new Schema({
|
|||||||
todos: Array //[{data: Date, value: Number}] // big peformance issues if these are defined
|
todos: Array //[{data: Date, value: Number}] // big peformance issues if these are defined
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FIXME remove?*/
|
// FIXME remove?
|
||||||
invitations: {
|
invitations: {
|
||||||
guilds: {type: Array, 'default': []},
|
guilds: {type: Array, 'default': []},
|
||||||
party: Schema.Types.Mixed
|
party: Schema.Types.Mixed
|
||||||
@@ -103,52 +109,65 @@ var UserSchema = new Schema({
|
|||||||
head: Number,
|
head: Number,
|
||||||
shield: Number,
|
shield: Number,
|
||||||
|
|
||||||
/*FIXME - tidy this up, not the best way to store current pet*/
|
// -------------- Animals -------------------
|
||||||
|
|
||||||
currentPet: {
|
// Complex bit here. The result looks like:
|
||||||
/*Cactus*/
|
// pets: {
|
||||||
|
// 'Wolf-Desert': 0, // 0 means does not own
|
||||||
text: String,
|
// 'PandaCub-Red': 10, // Number represents "Growth Points"
|
||||||
/*Cactus*/
|
// etc...
|
||||||
|
// }
|
||||||
name: String,
|
pets:
|
||||||
/*3*/
|
_.defaults(
|
||||||
|
// First transform to a 1D eggs/potions mapping
|
||||||
value: Number,
|
_.transform(eggPotionMapping, function(m,v,k){ m[k] = Number; }),
|
||||||
/*"Find a hatching potion to pour on this egg, and one day it will hatch into a loyal pet.",*/
|
// Then add additional pets (backer, contributor)
|
||||||
|
|
||||||
notes: String,
|
|
||||||
/*Skeleton*/
|
|
||||||
|
|
||||||
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
|
'Wolf-Veteran': Number,
|
||||||
dialog: String,
|
'Wolf-Cerberus': Number,
|
||||||
// example: Wolf
|
'Dragon-Hydra': Number
|
||||||
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",...]
|
currentPet: String, // Cactus-Desert
|
||||||
|
|
||||||
|
// 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; }),
|
||||||
|
|
||||||
|
// 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; }),
|
||||||
|
|
||||||
|
// 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; }),
|
||||||
|
|
||||||
|
// mounts: {
|
||||||
|
// 'Wolf-Desert': true,
|
||||||
|
// 'PandaCub-Red': false,
|
||||||
|
// etc...
|
||||||
|
// }
|
||||||
|
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: {
|
lastDrop: {
|
||||||
date: {type: Date, 'default': Date.now},
|
date: {type: Date, 'default': Date.now},
|
||||||
count: {type: Number, 'default': 0}
|
count: {type: Number, 'default': 0}
|
||||||
},
|
}
|
||||||
// ["BearCub-Base", "Cactus-Base", ...]
|
|
||||||
|
|
||||||
pets: Array
|
|
||||||
},
|
},
|
||||||
|
|
||||||
lastCron: {
|
lastCron: {
|
||||||
|
|||||||
@@ -1,25 +1,38 @@
|
|||||||
script(type='text/ng-template', id='partials/options.inventory.inventory.html')
|
script(type='text/ng-template', id='partials/options.inventory.inventory.html')
|
||||||
.row-fluid(ng-controller='InventoryCtrl')
|
.row-fluid
|
||||||
.span6.border-right
|
.span6.border-right
|
||||||
h2 Inventory
|
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.
|
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')
|
menu.inventory-list(type='list')
|
||||||
|
|
||||||
li.customize-menu
|
li.customize-menu
|
||||||
menu.pets-menu(label='Eggs ({{userEggs.length}})')
|
menu.pets-menu(label='Eggs ({{eggCount}})')
|
||||||
p(ng-show='userEggs.length < 1') You don't have any eggs yet.
|
p(ng-show='user.items.eggs.length < 1') You don't have any eggs yet.
|
||||||
div(ng-repeat='egg in userEggs track by $index')
|
div(ng-repeat='(egg,points) in ownedItems(user.items.eggs)')
|
||||||
button.customize-option(tooltip='{{egg.text}}', ng-click='chooseEgg(egg, $index)', class='Pet_Egg_{{egg.name}}', ng-class='selectableInventory(egg, selectedPotion.name, $index)')
|
//TODO move positioning this styling to css
|
||||||
p {{egg.text}}
|
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}}
|
||||||
|
|
||||||
li.customize-menu
|
li.customize-menu
|
||||||
menu.hatchingPotion-menu(label='Hatching Potions ({{userHatchingPotions.length}})')
|
menu.hatchingPotion-menu(label='Hatching Potions ({{potCount}})')
|
||||||
p(ng-show='userHatchingPotions.length < 1') You don't have any hatching potions yet.
|
p(ng-show='potCount < 1') You don't have any hatching potions yet.
|
||||||
div(ng-repeat='hatchingPotion in userHatchingPotions track by $index')
|
div(ng-repeat='(pot,points) in ownedItems(user.items.hatchingPotions)')
|
||||||
button.customize-option(tooltip='{{hatchingPotion}}', ng-click='choosePotion(hatchingPotion, $index)', class='Pet_HatchingPotion_{{hatchingPotion}}', ng-class='selectableInventory(selectedEgg, hatchingPotion, $index)')
|
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]}')
|
||||||
p {{hatchingPotion}}
|
.badge.badge-info.stack-count {{points}}
|
||||||
|
//-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(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}}
|
||||||
|
|
||||||
.span6
|
.span6
|
||||||
h2 Market
|
h2 Market
|
||||||
.row-fluid(ng-controller='MarketCtrl')
|
.row-fluid
|
||||||
table.NPC-Alex-container
|
table.NPC-Alex-container
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
@@ -37,19 +50,33 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html')
|
|||||||
| Sell {{selectedEgg.name}} for {{selectedEgg.value}} GP
|
| Sell {{selectedEgg.name}} for {{selectedEgg.value}} GP
|
||||||
button.btn.btn-primary(ng-show='selectedPotion', ng-click='sellInventory()')
|
button.btn.btn-primary(ng-show='selectedPotion', ng-click='sellInventory()')
|
||||||
| Sell {{selectedPotion.name}} for {{selectedPotion.value}} GP
|
| 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')
|
menu.inventory-list(type='list')
|
||||||
li.customize-menu
|
li.customize-menu
|
||||||
menu.pets-menu(label='Eggs')
|
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}}')
|
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.text}}
|
p
|
||||||
|
| {{egg.value}}
|
||||||
|
span.Pet_Currency_Gem1x.inline-gems
|
||||||
|
|
||||||
li.customize-menu
|
li.customize-menu
|
||||||
menu.pets-menu(label='Hatching Potions')
|
menu.pets-menu(label='Hatching Potions')
|
||||||
div(ng-repeat='hatchingPotion in hatchingPotions track by $index')
|
div(ng-repeat='pot in Items.hatchingPotions')
|
||||||
button.customize-option(tooltip='{{hatchingPotion.text}} - {{hatchingPotion.value}} Gem(s)', ng-click='buy("hatchingPotion", hatchingPotion)', class='Pet_HatchingPotion_{{hatchingPotion.name}}')
|
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 {{hatchingPotion.text}}
|
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(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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,33 +1,84 @@
|
|||||||
script(type='text/ng-template', id='partials/options.inventory.stable.html')
|
script(type='text/ng-template', id='partials/options.inventory.stable.html')
|
||||||
.stable(ng-controller='PetsCtrl')
|
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
|
||||||
.NPC-Matt
|
.NPC-Matt
|
||||||
.popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;')
|
.popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;')
|
||||||
.arrow
|
.arrow
|
||||||
h3.popover-title
|
h3.popover-title
|
||||||
a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch
|
a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch
|
||||||
.popover-content
|
.popover-content
|
||||||
p
|
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
|
Shall I bring you your steed, {{user.profile.name}}? Click a mount to saddle up.
|
||||||
a(href='https://trello.com/card/mounts/50e5d3684fe3a7266b0036d6/221') grow into powerful steeds
|
h4 {{mountCount}} / {{totalPets}} Mounts Tamed
|
||||||
| ! Until that day,
|
menu.pets(type='list')
|
||||||
a(target='_blank', href='https://f.cloud.github.com/assets/2374703/164631/3ed5fa6c-78cd-11e2-8743-f65ac477b55e.png') have a look-see
|
li.customize-menu(ng-repeat='egg in Items.eggs')
|
||||||
| at all the pets you can collect.
|
menu
|
||||||
h4 {{userPets.length}} / {{totalPets}} Pets Found
|
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_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
|
||||||
|
.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. <a target='_blank' href='https://f.cloud.github.com/assets/2374703/164631/3ed5fa6c-78cd-11e2-8743-f65ac477b55e.png'>Have a look-see</a> at all the pets you can collect.
|
||||||
|
h4 {{petCount}} / {{totalPets}} Pets Found
|
||||||
|
|
||||||
menu.pets(type='list')
|
menu.pets(type='list')
|
||||||
li.customize-menu(ng-repeat='pet in pets')
|
li.customize-menu(ng-repeat='egg in Items.eggs')
|
||||||
menu
|
menu
|
||||||
div(ng-repeat='potion in hatchingPotions', tooltip='{{potion.name}} {{pet.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.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-{{pet}}", ng-if='user.items.pets[pet]>0', ng-class='{active: user.items.currentPet == pet, selectableInventory: selectedFood}', ng-click='choosePet(egg.name, potion.name)')
|
||||||
button(class="pet-button pet-not-owned", ng-hide='hasPet(pet.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]')
|
||||||
img(src='/bower_components/habitrpg-shared/img/PixelPaw.png')
|
img(src='/bower_components/habitrpg-shared/img/PixelPaw.png')
|
||||||
|
|
||||||
h4 Rare Pets
|
h4 Rare Pets
|
||||||
menu
|
menu
|
||||||
div
|
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='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='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='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='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["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='http://habitrpg.wikia.com/wiki/Contributing_to_HabitRPG')
|
a(target='_blank', href='http://habitrpg.wikia.com/wiki/Contributing_to_HabitRPG')
|
||||||
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!')
|
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')
|
img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png')
|
||||||
|
|
||||||
|
//-.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.pets-menu(label='Food')
|
||||||
|
div(ng-repeat='(food,points) in ownedItems(user.items.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}}
|
||||||
|
// Remove this once we have images in
|
||||||
|
p {{Items.food[food].text}}
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
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="<div ng-hide='profile.id == user.id'> <div class='progress progress-danger' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.hp, 50)}}%;'></div> </div> <div class='progress progress-warning' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.exp, tnl(profile.stats.lvl))}}%;'></div> </div> <div>Level: {{profile.stats.lvl}}</div> <div>GP: {{profile.stats.gp | number:0}}</div> <div>{{count(profile.items.pets)}} / 90 Pets Found</div> </div>")
|
//- 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="<div ng-hide='profile.id == user.id'> <div class='progress progress-danger' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.hp, 50)}}%;'></div> </div> <div class='progress progress-warning' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.exp, tnl(profile.stats.lvl))}}%;'></div> </div> <div>Level: {{profile.stats.lvl}}</div> <div>GP: {{profile.stats.gp | number:0}}</div> <div>{{count(profile.items.pets)}} / 90 Pets Found</div> </div>")
|
||||||
|
|
||||||
|
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
|
.character-sprites
|
||||||
span(ng-class='{zzz:profile.flags.rest}')
|
// Mount Body
|
||||||
|
span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}')
|
||||||
|
|
||||||
|
// Avatar
|
||||||
span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}')
|
span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}')
|
||||||
span(class='{{profile.preferences.gender}}_hair_{{profile.preferences.hair}}')
|
span(class='{{profile.preferences.gender}}_hair_{{profile.preferences.hair}}')
|
||||||
span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}')
|
span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}')
|
||||||
@@ -8,6 +16,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("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("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}')
|
||||||
span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}')
|
span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}')
|
||||||
|
|
||||||
|
// Mount Head
|
||||||
|
span(ng-if='profile.items.currentMount', 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
|
// 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}}
|
.avatar-level Lvl {{profile.stats.lvl}}
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ div(modal='modals.dropsEnabled')
|
|||||||
.modal-header
|
.modal-header
|
||||||
h3 Drops Enabled!
|
h3 Drops Enabled!
|
||||||
.modal-body
|
.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')
|
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
|
| 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
|
strong {{user.items.eggs.0.text}} Egg
|
||||||
| ! {{user.items.eggs.0.notes}}.
|
| ! {{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 <strong>{{Items.eggs.Wolf.text}}</strong> Egg! {{Items.eggs.Wolf.notes}}
|
||||||
br
|
br
|
||||||
p.
|
p.
|
||||||
<span class='Pet_Currency_Gem item-drop-icon'></span> If you've got your eye on a pet, but can't wait any longer for it to drop, use Gems in <strong>Options > Inventory</strong> to buy one!
|
<span class='Pet_Currency_Gem item-drop-icon'></span> If you've got your eye on a pet, but can't wait any longer for it to drop, use Gems in <strong>Options > Inventory</strong> to buy one!
|
||||||
|
|||||||
Reference in New Issue
Block a user