Merge branch 'develop' of https://github.com/lefnire/habitrpg into develop

This commit is contained in:
Matteo Pagliazzi
2013-10-23 16:38:37 +02:00
16 changed files with 222 additions and 182 deletions

View File

@@ -0,0 +1,5 @@
db.users.find().forEach(function(user){
if (!user.purchased) user.purchased = {hair: {}, skin: {}};
user.purchased.ads = user.flags && !!user.flags.ads;
db.users.update({_id:user._id}, {$set:{'purchased': user.purchased, 'flags.newStuff': true}, $unset: {'flags.ads':1}});
});

View File

@@ -0,0 +1,12 @@
// node .migrations/20131022_restore_ads.js
var mongo = require('mongoskin');
var _ = require('lodash');
var dbBackup = mongo.db('localhost:27017/habitrpg?auto_reconnect');
var dbLive = mongo.db('localhost:27017/habitrpg2?auto_reconnect');
var count = 89474;
dbBackup.collection('users').findEach({$or: [{'flags.ads':'show'}, {'flags.ads': null}]}, {batchSize:10}, function(err, item) {
if (err) return console.error({err:err});
if (!item || !item._id) return console.error('blank user');
dbLive.collection('users').update({_id:item._id}, {$set:{'purchased.ads':false}, $unset: {'flags.ads': 1}});
if (--count <= 0) console.log("DONE!");
});

View File

@@ -1 +1 @@
db.users.update({},{$set:{'flags.newStuff':'show'}},{multi:true}) db.users.update({},{$set:{'flags.newStuff':true}},{multi:true})

View File

@@ -52,83 +52,6 @@ menu
} }
} }
// narrower spriting for customize modal .well.limited-edition
.customize-menu padding: 5px
.m_hair_blond,.m_hair_black,.m_hair_brown,.m_hair_white, margin: 0px
.f_hair_blond,.f_hair_black,.f_hair_brown,.f_hair_white,
.m_skin_dead,.m_skin_orc,.m_skin_asian,.m_skin_black,.m_skin_white,.m_skin_ea8349,.m_skin_c06534,.m_skin_98461a,
.f_skin_dead,.f_skin_orc,.f_skin_asian,.f_skin_black,.f_skin_white,.f_skin_ea8349,.f_skin_c06534,.f_skin_98461a,
.m_head_0,.f_head_0,
.f_armor_0_v1,.f_armor_0_v2
width: 60px
height: 60px
// head
.m_head_0
background-position: -1557px -9px;
// hair
.m_hair_blond
background-position: -1647px -4px;
.m_hair_black
background-position: -1737px -4px;
.m_hair_brown
background-position: -1827px -4px;
.m_hair_white
background-position: -1917px -4px;
// skin
.m_skin_dead
background-position: -2547px -20px;
.m_skin_orc
background-position: -2637px -20px;
.m_skin_asian
background-position: -2727px -20px;
.m_skin_black
background-position: -2817px -20px;
.m_skin_white
background-position: -2907px -20px;
.m_skin_ea8349
background-position: -2997px -20px;
.m_skin_c06534
background-position: -3087px -20px;
.m_skin_98461a
background-position: -3177px -20px;
// head
.f_head_0
background-position: -1917px -9px;
// hair
.f_hair_white
background-position: -2009px -8px;
.f_hair_brown
background-position: -2099px -8px;
.f_hair_black
background-position: -2189px -8px;
.f_hair_blond
background-position: -2279px -8px;
// skin
.f_skin_dead
background-position: -2997px -20px;
.f_skin_orc
background-position: -3087px -20px;
.f_skin_asian
background-position: -3177px -20px;
.f_skin_black
background-position: -3267px -20px;
.f_skin_white
background-position: -3357px -20px;
.f_skin_ea8349
background-position: -3447px -20px;
.f_skin_c06534
background-position: -3537px -20px;
.f_skin_98461a
background-position: -3627px -20px;
// starting armor
.f_armor_0_v2
background-position: -2819px -38px;
.f_armor_0_v1
background-position: -2909px -38px;

View File

@@ -170,6 +170,6 @@ a
.btn .btn
margin-right: 5px margin-right: 5px
.buy-gems-list .modal-indented-list
margin-left: 10px; margin-left: 10px;
padding-left: 10px; padding-left: 10px;

View File

@@ -1,4 +1,4 @@
.NPC-Alex, .NPC-Bailey, .NPC-Bailey-Head, .NPC-Daniel, .NPC-Justin, .NPC-Justin-Head, .NPC-Matt {background: url("/bower_components/habitrpg-shared/img/npcs/NPC-SpriteSheet.png") no-repeat} .NPC-Alex, .NPC-Bailey, .NPC-Bailey-Head, .NPC-Daniel, .NPC-Justin, .NPC-Justin-Head, .NPC-Matt {background: url("/bower_components/habitrpg-shared/img/npcs/halloween/NPC-SpriteSheet.png") no-repeat}
.NPC-Alex {background-position: 0 0; width: 162px; height: 138px;} .NPC-Alex {background-position: 0 0; width: 162px; height: 138px;}
.NPC-Alex-container{margin-bottom: 20px;} .NPC-Alex-container{margin-bottom: 20px;}

View File

@@ -14,7 +14,7 @@ habitrpg.controller("FooterCtrl", ['$scope', '$rootScope', 'User', '$http',
$.getScript('//checkout.stripe.com/v2/checkout.js'); $.getScript('//checkout.stripe.com/v2/checkout.js');
// Amazon Affiliate // Amazon Affiliate
// if ($rootScope.authenticated() && User.user.flags.ads !== 'hide') { // if ($rootScope.authenticated() && !User.user.purchased.ads) {
// $.getScript('//wms.assoc-amazon.com/20070822/US/js/link-enhancer-common.js?tag=ha0d2-20').fail(function() { // $.getScript('//wms.assoc-amazon.com/20070822/US/js/link-enhancer-common.js?tag=ha0d2-20').fail(function() {
// $('body').append('<img src="//wms.assoc-amazon.com/20070822/US/img/noscript.gif?tag=ha0d2-20" alt="" />'); // $('body').append('<img src="//wms.assoc-amazon.com/20070822/US/img/noscript.gif?tag=ha0d2-20" alt="" />');
// }); // });

View File

@@ -1,7 +1,7 @@
"use strict"; "use strict";
habitrpg.controller("UserCtrl", ['$scope', '$location', 'User', habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$http',
function($scope, $location, User) { function($rootScope, $scope, $location, User, $http) {
$scope.profile = User.user; $scope.profile = User.user;
$scope.hideUserAvatar = function() { $scope.hideUserAvatar = function() {
$(".userAvatar").hide(); $(".userAvatar").hide();
@@ -32,4 +32,8 @@ habitrpg.controller("UserCtrl", ['$scope', '$location', 'User',
$scope.removeWebsite = function($index){ $scope.removeWebsite = function($index){
$scope.editingProfile.websites.splice($index,1); $scope.editingProfile.websites.splice($index,1);
} }
}]);
$scope.unlock = User.unlock;
}
]);

View File

@@ -164,6 +164,38 @@ angular.module('userServices', []).
userServices.log(log); userServices.log(log);
}, },
/**
* For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase
* @param path: User.preferences <-> User.purchased maps like User.preferences.skin=abc <-> User.purchased.skin.abc.
* Pass in this paramater as "skin.abc". Alternatively, pass as an array ["skin.abc", "skin.xyz"] to unlock sets
*/
unlock: function(path){
var self = userServices; //this; // why isn't this working?
if (_.isArray(path)) {
if (confirm("Purchase for 5 Gems?") !== true) return;
if (user.balance < 1.25) return $rootScope.modals.buyGems = true;
path = path.join(',');
} else {
if (window.habitrpgShared.helpers.dotGet('purchased.' + path, user)) {
var pref = path.split('.')[0],
val = path.split('.')[1];
return self.set('preferences.' + pref, val);
} else {
if (confirm("Purchase for 2 Gems?") !== true) return;
if (user.balance < 0.5) return $rootScope.modals.buyGems = true;
}
}
$http.post(API_URL + '/api/v1/user/unlock?path=' + path)
.success(function(data, status, headers, config){
self.log({}); // sync new unlocked & preferences
}).error(function(data, status, headers, config){
alert(status + ': ' + data);
//FIXME use method used elsewhere for handling this error, this is temp while developing
})
},
save: save, save: save,
settings: settings settings: settings

View File

@@ -564,6 +564,49 @@ api['delete'] = function(req, res) {
}) })
} }
/*
------------------------------------------------------------------------
Unlock Preferences
------------------------------------------------------------------------
*/
api.unlock = function(req, res) {
var user = res.locals.user;
var path = req.query.path;
var fullSet = ~path.indexOf(',');
// 5G per set, 2G per individual
cost = fullSet ? 1.25 : 0.5;
if (user.balance < cost)
return res.json(401, {err: 'Not enough gems'});
if (fullSet) {
var paths = path.split(',');
_.each(paths, function(p){
helpers.dotSet('purchased.' + p, true, user);
});
} else {
if (helpers.dotGet('purchased.' + path, user) === true)
return res.json(401, {err: 'User already purchased that'});
helpers.dotSet('purchased.' + path, true, user);
}
user.balance -= cost;
user.__v++;
user.markModified('purchased');
user.save(function(err, saved){
if (err) res.json(500, {err:err});
res.send(200);
})
}
/*
------------------------------------------------------------------------
Buy Gems
------------------------------------------------------------------------
*/
/* /*
Setup Stripe response when posting payment Setup Stripe response when posting payment
@@ -584,7 +627,7 @@ api.buyGems = function(req, res) {
}, },
function(response, cb) { function(response, cb) {
res.locals.user.balance += 5; res.locals.user.balance += 5;
res.locals.user.flags.ads = 'hide'; res.locals.user.purchased.ads = true;
res.locals.user.save(cb); res.locals.user.save(cb);
} }
], function(err, saved){ ], function(err, saved){
@@ -609,7 +652,7 @@ api.buyGemsPaypalIPN = function(req, res) {
if (err) throw err; if (err) throw err;
if (_.isEmpty(user)) throw "user not found with uuid " + uuid + " when completing paypal transaction" if (_.isEmpty(user)) throw "user not found with uuid " + uuid + " when completing paypal transaction"
user.balance += 5; user.balance += 5;
user.flags.ads = 'hide'; user.purchased.ads = true;
user.save(); user.save();
console.log('PayPal transaction completed and user updated'); console.log('PayPal transaction completed and user updated');
}); });

View File

@@ -69,13 +69,18 @@ var UserSchema = new Schema({
rewardIds: Array, rewardIds: Array,
filters: {type: Schema.Types.Mixed, 'default': {}}, filters: {type: Schema.Types.Mixed, 'default': {}},
purchased: {
ads: {type: Boolean, 'default': false},
skin: {type: Schema.Types.Mixed, 'default': {}}, // eg, {skeleton: true, pumpkin: true, eb052b: true}
hair: {type: Schema.Types.Mixed, 'default': {}}
},
flags: { flags: {
customizationsNotification: {type: Boolean, 'default': false}, customizationsNotification: {type: Boolean, 'default': false},
showTour: {type: Boolean, 'default': true}, showTour: {type: Boolean, 'default': true},
ads: {type: String, 'default': 'show'}, // FIXME make this a boolean, run migration
dropsEnabled: {type: Boolean, 'default': false}, dropsEnabled: {type: Boolean, 'default': false},
itemsEnabled: {type: Boolean, 'default': false}, itemsEnabled: {type: Boolean, 'default': false},
newStuff: {type: String, 'default': 'hide'}, //FIXME to boolean (currently show/hide) 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}, petsEnabled: {type: Boolean, 'default': false},

View File

@@ -48,6 +48,7 @@ router.post('/user/batch-update', auth.auth, cron, user.batchUpdate);
router.post('/user/reroll', auth.auth, cron, user.reroll); router.post('/user/reroll', auth.auth, cron, user.reroll);
router.post('/user/buy-gems', auth.auth, user.buyGems); router.post('/user/buy-gems', auth.auth, user.buyGems);
router.post('/user/buy-gems/paypal-ipn', user.buyGemsPaypalIPN); router.post('/user/buy-gems/paypal-ipn', user.buyGemsPaypalIPN);
router.post('/user/unlock', auth.auth, cron, user.unlock);
router.post('/user/reset', auth.auth, user.reset); router.post('/user/reset', auth.auth, user.reset);
router['delete']('/user', auth.auth, user['delete']); router['delete']('/user', auth.auth, user['delete']);

View File

@@ -6,11 +6,14 @@
// gender // gender
li.customize-menu li.customize-menu
menu(label='Head') menu(label='Head')
menu
button.m_head_0.customize-option(type='button', ng-click='set("preferences.gender","m")') button.m_head_0.customize-option(type='button', ng-click='set("preferences.gender","m")')
button.f_head_0.customize-option(type='button', ng-click='set("preferences.gender","f")') button.f_head_0.customize-option(type='button', ng-click='set("preferences.gender","f")')
label.checkbox label.checkbox
input(type='checkbox', ng-model='user.preferences.showHelm', ng-change='toggleHelm(user.preferences.showHelm)') input(type='checkbox', ng-model='user.preferences.showHelm', ng-change='toggleHelm(user.preferences.showHelm)')
| Show Helm | Show Helm
hr
// hair // hair
li.customize-menu li.customize-menu
menu(label='Hair') menu(label='Hair')
@@ -18,17 +21,53 @@
button(class='{{user.preferences.gender}}_hair_black customize-option', type='button', ng-click='set("preferences.hair","black")') button(class='{{user.preferences.gender}}_hair_black customize-option', type='button', ng-click='set("preferences.hair","black")')
button(class='{{user.preferences.gender}}_hair_brown customize-option', type='button', ng-click='set("preferences.hair","brown")') button(class='{{user.preferences.gender}}_hair_brown customize-option', type='button', ng-click='set("preferences.hair","brown")')
button(class='{{user.preferences.gender}}_hair_white customize-option', type='button', ng-click='set("preferences.hair","white")') button(class='{{user.preferences.gender}}_hair_white customize-option', type='button', ng-click='set("preferences.hair","white")')
hr
// skin // skin
li.customize-menu li.customize-menu
menu(label='Skin') menu(label='Basic Skins')
button.customize-option(class='{{user.preferences.gender}}_skin_asian', type='button', ng-click='set("preferences.skin","asian")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_asian', ng-click='set("preferences.skin","asian")')
button.customize-option(class='{{user.preferences.gender}}_skin_white', type='button', ng-click='set("preferences.skin","white")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_white', ng-click='set("preferences.skin","white")')
button.customize-option(class='{{user.preferences.gender}}_skin_ea8349', type='button', ng-click='set("preferences.skin","ea8349")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_ea8349', ng-click='set("preferences.skin","ea8349")')
button.customize-option(class='{{user.preferences.gender}}_skin_c06534', type='button', ng-click='set("preferences.skin","c06534")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_c06534', ng-click='set("preferences.skin","c06534")')
button.customize-option(class='{{user.preferences.gender}}_skin_98461a', type='button', ng-click='set("preferences.skin","98461a")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_98461a', ng-click='set("preferences.skin","98461a")')
button.customize-option(class='{{user.preferences.gender}}_skin_black', type='button', ng-click='set("preferences.skin","black")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_black', ng-click='set("preferences.skin","black")')
button.customize-option(class='{{user.preferences.gender}}_skin_dead', type='button', ng-click='set("preferences.skin","dead")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_dead', ng-click='set("preferences.skin","dead")')
button.customize-option(class='{{user.preferences.gender}}_skin_orc', type='button', ng-click='set("preferences.skin","orc")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-click='set("preferences.skin","orc")')
// Rainbow Skin
h5.
Rainbow Skins - 2<span class="Pet_Currency_Gem1x inline-gems"/>/skin
//menu(label='Rainbow Skins (2G / skin)')
menu
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_eb052b', ng-class='{locked: !user.purchased.skin.eb052b}', ng-click='unlock("skin.eb052b")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_f69922', ng-class='{locked: !user.purchased.skin.f69922}', ng-click='unlock("skin.f69922")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_f5d70f', ng-class='{locked: !user.purchased.skin.f5d70f}', ng-click='unlock("skin.f5d70f")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_0ff591', ng-class='{locked: !user.purchased.skin.0ff591}', ng-click='unlock("skin.0ff591")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_2b43f6', ng-class='{locked: !user.purchased.skin.2b43f6}', ng-click='unlock("skin.2b43f6")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_d7a9f7', ng-class='{locked: !user.purchased.skin.d7a9f7}', ng-click='unlock("skin.d7a9f7")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_800ed0', ng-class='{locked: !user.purchased.skin.800ed0}', ng-click='unlock("skin.800ed0")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_rainbow', ng-class='{locked: !user.purchased.skin.rainbow}', ng-click='unlock("skin.rainbow")')
button.btn.btn-small.btn-primary(ng-hide='user.purchased.skin.eb052b && user.purchased.skin.f69922 && user.purchased.skin.f5d70f && user.purchased.skin.0ff591 && user.purchased.skin.2b43f6 && user.purchased.skin.d7a9f7 && user.purchased.skin.800ed0 && user.purchased.skin.rainbow', ng-click='unlock(["skin.eb052b", "skin.f69922", "skin.f5d70f", "skin.0ff591", "skin.2b43f6", "skin.d7a9f7", "skin.800ed0", "skin.rainbow"])') Unlock Set - 5<span class="Pet_Currency_Gem1x inline-gems"/>
// Special Events
div.well.limited-edition
.label.label-info.pull-right(popover='Available for purchase until November 10th (but permanently in your options if purchased).', popover-title='Limited Edition', popover-placement='right', popover-trigger='mouseenter')
| Limited Edition&nbsp;
i.icon.icon-question-sign
h5.
Spooky Skins - 2<span class="Pet_Currency_Gem1x inline-gems"/>/skin
//menu(label='Spooky Skins (2 Gems / skin)')
menu
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_monster', ng-class='{locked: !user.purchased.skin.monster}', ng-click='unlock("skin.monster")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_pumpkin', ng-class='{locked: !user.purchased.skin.pumpkin}', ng-click='unlock("skin.pumpkin")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_skeleton', ng-class='{locked: !user.purchased.skin.skeleton}', ng-click='unlock("skin.skeleton")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_zombie', ng-class='{locked: !user.purchased.skin.zombie}', ng-click='unlock("skin.zombie")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_ghost', ng-class='{locked: !user.purchased.skin.ghost}', ng-click='unlock("skin.ghost")')
button.customize-option(type='button', class='{{user.preferences.gender}}_skin_shadow', ng-class='{locked: !user.purchased.skin.shadow}', ng-click='unlock("skin.shadow")')
button.btn.btn-small.btn-primary(ng-hide='user.purchased.skin.monster && user.purchased.skin.pumpkin && user.purchased.skin.skeleton && user.purchased.skin.zombie && user.purchased.skin.ghost && user.purchased.skin.shadow', ng-click='unlock(["skin.monster", "skin.pumpkin", "skin.skeleton", "skin.zombie", "skin.ghost", "skin.shadow"])') Unlock Set - 5<span class="Pet_Currency_Gem1x inline-gems"/>
menu(ng-show='user.preferences.gender=="f"', type='list') menu(ng-show='user.preferences.gender=="f"', type='list')
li.customize-menu li.customize-menu
menu(label='Clothing') menu(label='Clothing')

View File

@@ -15,10 +15,10 @@ div(modal='modals.buyGems')
a(target='_blank', href='https://twitter.com/bowenNstuff') Justin a(target='_blank', href='https://twitter.com/bowenNstuff') Justin
.popover-content .popover-content
p <span class='label label-info'>$5 USD</span> will: p <span class='label label-info'>$5 USD</span> will:
ul.buy-gems-list ul.modal-indented-list
li Add 20 gems to your account, which are used to buy special items. li Add 20 gems to your account, which are used to buy special items.
li Disable ads. li Disable ads.
li Donate to the developers (as an open source project, we can us all the help we can get). li Donate to the developers (as an open source project, we can use all the help we can get).
br br
.row-fluid .row-fluid
.span6.well .span6.well

View File

@@ -1,49 +1,3 @@
div(modal='user.flags.rewrite !== false')
.modal-header
h3 Mega Ultra Update!
.modal-body
table
tr
td
.NPC-Bailey
td
.popover.static-popover.fade.right.in.wide-popover
.arrow
h3.popover-title
a(target='_blank', href='https://twitter.com/Mihakuu') Bailey
.popover-content
p.
Hello my Habiteers! I have some amazing news to share with you, it's huge!
Has Habit ever crashed for you? (Joke). Well we <u><a target='_blank' href="http://habitrpg.tumblr.com/post/59104876969/website-issues-what-were-doing">re-wrote the website</a></u> from the ground up
to conquor those critical bugs once and for all (more from Tyler in a bit). If you haven't seen me for a while (due to a bug in the old site), be sure to catch up with me on the right side of the screen for any missed news. Importantly:
.alert.alert-success(style='margin-bottom:5px').
<a target='_blank' href='https://play.google.com/store/apps/details?id=com.ocdevel.habitrpg'>Android</a> & <a target='_blank' href='https://itunes.apple.com/us/app/habitrpg/id689569235?mt=8'>iOS</a> Apps are out!</u>
p.
They're open source, so help us make them awesome. As for the rewrite: not all features are yet ported, but don't worry - you're still getting drops and streak-bonuses in the background, even if you can't see them yet.
We'll be working hard to bring in all the missing features. And if you're not already, be sure to follow our updates on <a href="http://habitrpg.tumblr.com/" target="_blank">Tumblr</a> (there are some fun member highlights recently). One more thing: if you are a Veteran of the old site, I have granted you a Veteran Wolf! Check your inventory :)
table(style='clear:both;')
tr
td
.popover.static-popover.fade.left.in
.arrow
h3.popover-title
a(target='_blank', href='https://twitter.com/lefnire') Tyler
.popover-content
p.
JavaScript developers! To me! We must finish vanquishing the old site, as not all features have been ported.
We rewrote Habit on <a target='_blank' href='http://angularjs.org/'>AngularJS</a> + <a target='_blank' href='http://expressjs.com/'>Express</a>.
We desparately need your help porting <a href='http://goo.gl/jYWTwl' target='_blank'>the rest of the features</a>, and polishing off the bugs. <a target='_blank' href='https://github.com/lefnire/habitrpg/wiki/Contributing#website'>Read this guide</a> to getting started.
Thanks everyone for all your support and patience!
td
img.pull-right(src='/bower_components/habitrpg-shared/img/unprocessed/efbd21c4-82a1-11e2-8190-fbc609b5c58b.png', style='height:72px')
.modal-footer
button.btn.btn-default.cancel(ng-click='user.flags.rewrite = false') Read Later
button.btn.btn-warning.cancel(ng-click='set("flags.rewrite", false)') Dismiss
div(modal='modals.newStuff') div(modal='modals.newStuff')
.modal-header .modal-header
h3 New Stuff! h3 New Stuff!
@@ -58,24 +12,46 @@ div(modal='modals.newStuff')
h3.popover-title h3.popover-title
a(target='_blank', href='https://twitter.com/Mihakuu') Bailey a(target='_blank', href='https://twitter.com/Mihakuu') Bailey
.popover-content .popover-content
strong 10/19/2013 strong 10/22/2013
p p
ul.modal-indented-list
li TRICK OR TREAT! It's Habit Halloween! Some of the NPCs have decorated for the occasion. Can you spot us?
li Two gem-purchasable skin tones are now available! The Rainbow Skin Set is here to stay, but in honor of Halloween, we also have the LIMITED EDITION SPOOKY SKIN SET. You will only be able to purchase the Spooky Skin Set until November 10th, so if you want a monstrous avatar, now's the time to act!
li Do note, skins won't work on mobile until the app is updated. We'll update Android ASAP, iPhone usually takes ~1wk to approve.
hr
h3 Archive
p
h4 10/19/2013
ul ul
li. li.
New custom skin colors are now available! Go check them out in the Profile section. Also, the new mobile update, 0.0.10, is now available to download! It includes the new skin tones and the ability to hide or show your helm, among other things. New custom skin colors are now available! Go check them out in the Profile section. Also, the new mobile update, 0.0.10, is now available to download! It includes the new skin tones and the ability to hide or show your helm, among other things.
li. li.
You can now sell un-wanted drops to Alex the Merchant. Trade those troves of eggs for gold! You can now sell un-wanted drops to Alex the Merchant. Trade those troves of eggs for gold!
hr
h3 Archive
p
h4 09/01/2013 h4 09/01/2013
ul ul
li. li.
We <a target='_blank' href="http://habitrpg.tumblr.com/post/59104876969/website-issues-what-were-doing">re-wrote the website from the ground up</a> We <a target='_blank' href="http://habitrpg.tumblr.com/post/59104876969/website-issues-what-were-doing">re-wrote the website from the ground up</a>
And in case you missed it, <a target='_blank' href='https://play.google.com/store/apps/details?id=com.ocdevel.habitrpg'>Android</a> & <a target='_blank' href='https://itunes.apple.com/us/app/habitrpg/id689569235?mt=8'>iOS</a> Apps are out! And in case you missed it, <a target='_blank' href='https://play.google.com/store/apps/details?id=com.ocdevel.habitrpg'>Android</a> & <a target='_blank' href='https://itunes.apple.com/us/app/habitrpg/id689569235?mt=8'>iOS</a> Apps are out!
Both apps and the website are open source, and we desparately need your help porting the rest of the features, and polishing off the bugs. <a target='_blank' href='https://github.com/lefnire/habitrpg/wiki/Contributing#website'>Read this guide</a> to getting started. Both apps and the website are open source, and we desparately need your help porting the rest of the features, and polishing off the bugs. <a target='_blank' href='https://github.com/lefnire/habitrpg/wiki/Contributing#website'>Read this guide</a> to getting started.
Each of your pull requests shall grant you a special <a href='https://github.com/lefnire/habitrpg/issues/946#issuecomment-18654292' target='_blank'>Contributor Gear piece</a>. We're working on a system of Contributor Gear to reward the awesome people who help out, so stay tuned!
h4 The Rewrite! (Mid August)
ul
li.
Hello my Habiteers! I have some amazing news to share with you, it's huge!
Has Habit ever crashed for you? (Joke). Well we <u><a target='_blank' href="http://habitrpg.tumblr.com/post/59104876969/website-issues-what-were-doing">re-wrote the website</a></u> from the ground up
to conquor those critical bugs once and for all (more from Tyler in a bit). If you haven't seen me for a while (due to a bug in the old site), be sure to catch up with me on the right side of the screen for any missed news. Importantly:
.alert.alert-success(style='margin-bottom:5px').
<a target='_blank' href='https://play.google.com/store/apps/details?id=com.ocdevel.habitrpg'>Android</a> & <a target='_blank' href='https://itunes.apple.com/us/app/habitrpg/id689569235?mt=8'>iOS</a> Apps are out!</u>
li.
They're open source, so help us make them awesome. As for the rewrite: not all features are yet ported, but don't worry - you're still getting drops and streak-bonuses in the background, even if you can't see them yet.
We'll be working hard to bring in all the missing features. And if you're not already, be sure to follow our updates on <a href="http://habitrpg.tumblr.com/" target="_blank">Tumblr</a> (there are some fun member highlights recently). One more thing: if you are a Veteran of the old site, I have granted you a Veteran Wolf! Check your inventory :)
li.
JavaScript developers! To me! We must finish vanquishing the old site, as not all features have been ported.
We rewrote Habit on <a target='_blank' href='http://angularjs.org/'>AngularJS</a> + <a target='_blank' href='http://expressjs.com/'>Express</a>.
We desparately need your help porting <a href='http://goo.gl/jYWTwl' target='_blank'>the rest of the features</a>, and polishing off the bugs. <a target='_blank' href='https://github.com/lefnire/habitrpg/wiki/Contributing#website'>Read this guide</a> to getting started.
Thanks everyone for all your support and patience!
h4 8/20/2013 h4 8/20/2013
ul ul

View File

@@ -1,4 +1,4 @@
div(ng-if='authenticated() && user.flags.ads!="hide"') div(ng-if='authenticated() && !user.purchased.ads')
span.pull-right(ng-if='list.type!="reward"') span.pull-right(ng-if='list.type!="reward"')
a(ng-click='modals.buyGems=true', tooltip='Remove Ads') a(ng-click='modals.buyGems=true', tooltip='Remove Ads')
i.icon-remove i.icon-remove