From d184237c797532daaf0561df49bc68b5722d08a6 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 12:19:43 -0700 Subject: [PATCH 01/17] halloween: begin adding mechanic for the special skins --- public/css/customizer.styl | 3 ++ public/js/controllers/userCtrl.js | 75 ++++++++++++++++++------------ public/js/services/userServices.js | 11 +++++ src/controllers/user.js | 33 +++++++++++++ src/models/user.js | 6 +++ src/routes/api.js | 1 + views/options/profile.jade | 44 ++++++++++++++---- 7 files changed, 135 insertions(+), 38 deletions(-) diff --git a/public/css/customizer.styl b/public/css/customizer.styl index 95e35a6540..0bbfe88db7 100644 --- a/public/css/customizer.styl +++ b/public/css/customizer.styl @@ -132,3 +132,6 @@ menu background-position: -2819px -38px; .f_armor_0_v1 background-position: -2909px -38px; + + .locked + background-color: #727272 \ No newline at end of file diff --git a/public/js/controllers/userCtrl.js b/public/js/controllers/userCtrl.js index 80a0d1413c..d441a23dbf 100644 --- a/public/js/controllers/userCtrl.js +++ b/public/js/controllers/userCtrl.js @@ -1,35 +1,52 @@ "use strict"; -habitrpg.controller("UserCtrl", ['$scope', '$location', 'User', - function($scope, $location, User) { - $scope.profile = User.user; - $scope.hideUserAvatar = function() { - $(".userAvatar").hide(); - }; - $scope.toggleHelm = function(val){ - User.log({op:'set', data:{'preferences.showHelm':val}}); - } +habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$http', + function($rootScope, $scope, $location, User, $http) { + $scope.profile = User.user; + $scope.hideUserAvatar = function() { + $(".userAvatar").hide(); + }; + $scope.toggleHelm = function(val){ + User.log({op:'set', data:{'preferences.showHelm':val}}); + } - $scope.$watch('_editing.profile', function(value){ - if(value === true) $scope.editingProfile = angular.copy(User.user.profile); - }); - - $scope.save = function(){ - var values = {}; - _.each($scope.editingProfile, function(value, key){ - // Using toString because we need to compare two arrays (websites) - if($scope.editingProfile[key].toString() !== $scope.profile.profile[key].toString()) values['profile.' + key] = value; + $scope.$watch('_editing.profile', function(value){ + if(value === true) $scope.editingProfile = angular.copy(User.user.profile); }); - User.setMultiple(values); - $scope._editing.profile = false; - } - $scope.addWebsite = function(){ - if (!$scope.editingProfile.websites) $scope.editingProfile.websites = []; - $scope.editingProfile.websites.push($scope._newWebsite); - $scope._newWebsite = ''; + $scope.save = function(){ + var values = {}; + _.each($scope.editingProfile, function(value, key){ + // Using toString because we need to compare two arrays (websites) + if($scope.editingProfile[key].toString() !== $scope.profile.profile[key].toString()) values['profile.' + key] = value; + }); + User.setMultiple(values); + $scope._editing.profile = false; + } + + $scope.addWebsite = function(){ + if (!$scope.editingProfile.websites) $scope.editingProfile.websites = []; + $scope.editingProfile.websites.push($scope._newWebsite); + $scope._newWebsite = ''; + } + $scope.removeWebsite = function($index){ + $scope.editingProfile.websites.splice($index,1); + } + + /** + * 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" + */ + $scope.unlock = function(path){ + if (window.habitrpgShared.helpers.dotGet('purchased.' + path, User.user)) { + var pref = path.split('.')[0], + val = path.split('.')[1]; + window.habitrpgShared.helpers.dotSet('preferences.' + pref, val, User.user); + } else { + if (confirm("Purchase for 2 Gems?") !== true) return; + if (User.user.balance < 0.5) return $rootScope.modals.moreGems = true; + User.unlock(path); + } + } } - $scope.removeWebsite = function($index){ - $scope.editingProfile.websites.splice($index,1); - } -}]); +]); diff --git a/public/js/services/userServices.js b/public/js/services/userServices.js index 3ed760ace5..4b6a27bd50 100644 --- a/public/js/services/userServices.js +++ b/public/js/services/userServices.js @@ -164,6 +164,17 @@ angular.module('userServices', []). userServices.log(log); }, + unlock: function(path){ + var self = this; + $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, settings: settings diff --git a/src/controllers/user.js b/src/controllers/user.js index 8fd0891d0d..8c76ac6001 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -564,6 +564,39 @@ api['delete'] = function(req, res) { }) } +/* + ------------------------------------------------------------------------ + Unlock Preferences + ------------------------------------------------------------------------ + */ + +api.unlock = function(req, res) { + var user = res.locals.user; + if (user.balance < 0.5) + return res.json(401, {err: 'Not enough gems'}); + + // Provide deafult values if !user.purchased + _.defaults(user, {purchased:{}}); + _.defaults(user.purchased, {skin:{}, hair:{}, ads: false}); + + var path = req.query.path; + if (helpers.dotGet('purchased.' + path, user) === true) + return res.json(401, {err: 'User already purchased that'}); + user.balance -= 2; + helpers.dotSet('purchased.' + path, true, user); + user.__v++; + user.save(function(err, saved){ + if (err) res.json(500, {err:err}); + res.send(200); + }) +} + +/* + ------------------------------------------------------------------------ + Buy Gems + ------------------------------------------------------------------------ + */ + /* Setup Stripe response when posting payment diff --git a/src/models/user.js b/src/models/user.js index 52aae66993..c98da6f64f 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -69,6 +69,12 @@ var UserSchema = new Schema({ rewardIds: Array, filters: {type: Schema.Types.Mixed, 'default': {}}, + purchased: { + ads: {type: Boolean, 'default': false}, + skin: Schema.Types.Mixed, // eg, {skeleton: true, pumpkin: true, eb052b: true} + hair: Schema.Types.Mixed + }, + flags: { customizationsNotification: {type: Boolean, 'default': false}, showTour: {type: Boolean, 'default': true}, diff --git a/src/routes/api.js b/src/routes/api.js index 86f995239c..1eb4ade222 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -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/buy-gems', auth.auth, user.buyGems); 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['delete']('/user', auth.auth, user['delete']); diff --git a/views/options/profile.jade b/views/options/profile.jade index 0f50d9df16..6dc664c3b1 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -6,11 +6,14 @@ // gender li.customize-menu menu(label='Head') + menu 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")') label.checkbox input(type='checkbox', ng-model='user.preferences.showHelm', ng-change='toggleHelm(user.preferences.showHelm)') | Show Helm + hr + // hair li.customize-menu menu(label='Hair') @@ -18,17 +21,40 @@ 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_white customize-option', type='button', ng-click='set("preferences.hair","white")') + hr + // skin li.customize-menu - menu(label='Skin') - button.customize-option(class='{{user.preferences.gender}}_skin_asian', type='button', 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(class='{{user.preferences.gender}}_skin_ea8349', type='button', 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(class='{{user.preferences.gender}}_skin_98461a', type='button', 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(class='{{user.preferences.gender}}_skin_dead', type='button', ng-click='set("preferences.skin","dead")') - button.customize-option(class='{{user.preferences.gender}}_skin_orc', type='button', ng-click='set("preferences.skin","orc")') + menu(label='Basic Skin') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_asian', ng-click='set("preferences.skin","asian")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_white', ng-click='set("preferences.skin","white")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_ea8349', ng-click='set("preferences.skin","ea8349")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_c06534', ng-click='set("preferences.skin","c06534")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_98461a', ng-click='set("preferences.skin","98461a")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_black', ng-click='set("preferences.skin","black")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_dead', ng-click='set("preferences.skin","dead")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-click='set("preferences.skin","orc")') + + // Special Events + menu(label='Crazy Skin') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.eb052b}', ng-click='unlock("skin.eb052b")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.f69922}', ng-click='unlock("skin.f69922")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.f5d70f}', ng-click='unlock("skin.f5d70f")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.0ff591}', ng-click='unlock("skin.0ff591")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.2b43f6}', ng-click='unlock("skin.2b43f6")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.d7a9f7}', ng-click='unlock("skin.d7a9f7")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.800ed0}', ng-click='unlock("skin.800ed0")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.rainbow}', ng-click='unlock("skin.rainbow")') + + // Special Events + menu(label='Monster Skin (Happy Halloween!)') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.monster}', ng-click='unlock("skin.monster")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.pumpkin}', ng-click='unlock("skin.pumpkin")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.skeleton}', ng-click='unlock("skin.skeleton")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.zombie}', ng-click='unlock("skin.zombie")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.ghost}', ng-click='unlock("skin.ghost")') + button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.shadow}', ng-click='unlock("skin.shadow")') + menu(ng-show='user.preferences.gender=="f"', type='list') li.customize-menu menu(label='Clothing') From 619c00fb5c0ff587e0cb6614bf69cc615bf59afd Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 13:37:55 -0700 Subject: [PATCH 02/17] halloween: some unlocking bug fixes (appears a markModified was required) --- public/js/controllers/userCtrl.js | 2 +- src/controllers/user.js | 5 +---- src/models/user.js | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/public/js/controllers/userCtrl.js b/public/js/controllers/userCtrl.js index d441a23dbf..48d674897c 100644 --- a/public/js/controllers/userCtrl.js +++ b/public/js/controllers/userCtrl.js @@ -44,7 +44,7 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$ window.habitrpgShared.helpers.dotSet('preferences.' + pref, val, User.user); } else { if (confirm("Purchase for 2 Gems?") !== true) return; - if (User.user.balance < 0.5) return $rootScope.modals.moreGems = true; + if (User.user.balance < 0.5) return $rootScope.modals.buyGems = true; User.unlock(path); } } diff --git a/src/controllers/user.js b/src/controllers/user.js index 8c76ac6001..b362408244 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -575,16 +575,13 @@ api.unlock = function(req, res) { if (user.balance < 0.5) return res.json(401, {err: 'Not enough gems'}); - // Provide deafult values if !user.purchased - _.defaults(user, {purchased:{}}); - _.defaults(user.purchased, {skin:{}, hair:{}, ads: false}); - var path = req.query.path; if (helpers.dotGet('purchased.' + path, user) === true) return res.json(401, {err: 'User already purchased that'}); user.balance -= 2; helpers.dotSet('purchased.' + path, true, user); user.__v++; + user.markModified('purchased'); user.save(function(err, saved){ if (err) res.json(500, {err:err}); res.send(200); diff --git a/src/models/user.js b/src/models/user.js index c98da6f64f..d5f4725170 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -71,8 +71,8 @@ var UserSchema = new Schema({ purchased: { ads: {type: Boolean, 'default': false}, - skin: Schema.Types.Mixed, // eg, {skeleton: true, pumpkin: true, eb052b: true} - hair: Schema.Types.Mixed + skin: {type: Schema.Types.Mixed, 'default': {}}, // eg, {skeleton: true, pumpkin: true, eb052b: true} + hair: {type: Schema.Types.Mixed, 'default': {}} }, flags: { From 6f32ac2a247071f739bc41a85604516f3baf6e82 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 13:59:30 -0700 Subject: [PATCH 03/17] halloween: purchase full set --- public/js/controllers/userCtrl.js | 17 ++--------------- public/js/services/userServices.js | 23 ++++++++++++++++++++++- src/controllers/user.js | 25 +++++++++++++++++++------ views/options/profile.jade | 6 ++++-- 4 files changed, 47 insertions(+), 24 deletions(-) diff --git a/public/js/controllers/userCtrl.js b/public/js/controllers/userCtrl.js index 48d674897c..511183e808 100644 --- a/public/js/controllers/userCtrl.js +++ b/public/js/controllers/userCtrl.js @@ -33,20 +33,7 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$ $scope.editingProfile.websites.splice($index,1); } - /** - * 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" - */ - $scope.unlock = function(path){ - if (window.habitrpgShared.helpers.dotGet('purchased.' + path, User.user)) { - var pref = path.split('.')[0], - val = path.split('.')[1]; - window.habitrpgShared.helpers.dotSet('preferences.' + pref, val, User.user); - } else { - if (confirm("Purchase for 2 Gems?") !== true) return; - if (User.user.balance < 0.5) return $rootScope.modals.buyGems = true; - User.unlock(path); - } - } + $scope.unlock = User.unlock; + } ]); diff --git a/public/js/services/userServices.js b/public/js/services/userServices.js index 4b6a27bd50..88fbffaaba 100644 --- a/public/js/services/userServices.js +++ b/public/js/services/userServices.js @@ -164,8 +164,29 @@ angular.module('userServices', []). 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 = this; + 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]; + window.habitrpgShared.helpers.dotSet('preferences.' + pref, val, user); + } 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 diff --git a/src/controllers/user.js b/src/controllers/user.js index b362408244..b11cb96338 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -572,14 +572,27 @@ api['delete'] = function(req, res) { api.unlock = function(req, res) { var user = res.locals.user; - if (user.balance < 0.5) + 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'}); - var path = req.query.path; - if (helpers.dotGet('purchased.' + path, user) === true) - return res.json(401, {err: 'User already purchased that'}); - user.balance -= 2; - helpers.dotSet('purchased.' + path, true, user); + 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){ diff --git a/views/options/profile.jade b/views/options/profile.jade index 6dc664c3b1..5df43c03f3 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -36,7 +36,7 @@ button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-click='set("preferences.skin","orc")') // Special Events - menu(label='Crazy Skin') + menu(label='Crazy Skin (2G / skin)') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.eb052b}', ng-click='unlock("skin.eb052b")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.f69922}', ng-click='unlock("skin.f69922")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.f5d70f}', ng-click='unlock("skin.f5d70f")') @@ -45,15 +45,17 @@ button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.d7a9f7}', ng-click='unlock("skin.d7a9f7")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.800ed0}', ng-click='unlock("skin.800ed0")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', 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 (5G) // Special Events - menu(label='Monster Skin (Happy Halloween!)') + menu(label='Monster Skin (2G / skin)') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.monster}', ng-click='unlock("skin.monster")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.pumpkin}', ng-click='unlock("skin.pumpkin")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.skeleton}', ng-click='unlock("skin.skeleton")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.zombie}', ng-click='unlock("skin.zombie")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.ghost}', ng-click='unlock("skin.ghost")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', 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 (5G) menu(ng-show='user.preferences.gender=="f"', type='list') li.customize-menu From 2c1d8e1688718acdff608cc01ca037ed57bf0d46 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 14:32:51 -0700 Subject: [PATCH 04/17] halloween: functional new skins for female sprites (requires habitrpg-shared@d7482fe) --- views/options/profile.jade | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/views/options/profile.jade b/views/options/profile.jade index 5df43c03f3..c7a22351f1 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -37,24 +37,24 @@ // Special Events menu(label='Crazy Skin (2G / skin)') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.eb052b}', ng-click='unlock("skin.eb052b")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.f69922}', ng-click='unlock("skin.f69922")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.f5d70f}', ng-click='unlock("skin.f5d70f")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.0ff591}', ng-click='unlock("skin.0ff591")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.2b43f6}', ng-click='unlock("skin.2b43f6")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.d7a9f7}', ng-click='unlock("skin.d7a9f7")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.800ed0}', ng-click='unlock("skin.800ed0")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.rainbow}', ng-click='unlock("skin.rainbow")') + 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 (5G) // Special Events menu(label='Monster Skin (2G / skin)') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.monster}', ng-click='unlock("skin.monster")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.pumpkin}', ng-click='unlock("skin.pumpkin")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.skeleton}', ng-click='unlock("skin.skeleton")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.zombie}', ng-click='unlock("skin.zombie")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.ghost}', ng-click='unlock("skin.ghost")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-class='{locked: !user.purchased.skin.shadow}', ng-click='unlock("skin.shadow")') + 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 (5G) menu(ng-show='user.preferences.gender=="f"', type='list') From ec50c7d0ec739a3b7ed9e800cfeaa932afa572c0 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 14:46:58 -0700 Subject: [PATCH 05/17] halloween fix to 401 error --- public/js/services/userServices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/services/userServices.js b/public/js/services/userServices.js index 88fbffaaba..dae616f6f0 100644 --- a/public/js/services/userServices.js +++ b/public/js/services/userServices.js @@ -180,7 +180,7 @@ angular.module('userServices', []). if (window.habitrpgShared.helpers.dotGet('purchased.' + path, user)) { var pref = path.split('.')[0], val = path.split('.')[1]; - window.habitrpgShared.helpers.dotSet('preferences.' + pref, val, user); + return window.habitrpgShared.helpers.dotSet('preferences.' + pref, val, user); } else { if (confirm("Purchase for 2 Gems?") !== true) return; if (user.balance < 0.5) return $rootScope.modals.buyGems = true; From 534a761875f0defc5b2700c6088333f3ce2be163 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 16:19:54 -0700 Subject: [PATCH 06/17] remove customizer css, moved to habitrg-shared@06e489d --- public/css/customizer.styl | 86 +------------------------------------- 1 file changed, 1 insertion(+), 85 deletions(-) diff --git a/public/css/customizer.styl b/public/css/customizer.styl index 0bbfe88db7..7cbbdf3360 100644 --- a/public/css/customizer.styl +++ b/public/css/customizer.styl @@ -50,88 +50,4 @@ menu .customize-menu { width: 100%; } -} - -// narrower spriting for customize modal -.customize-menu - .m_hair_blond,.m_hair_black,.m_hair_brown,.m_hair_white, - .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; - - .locked - background-color: #727272 \ No newline at end of file +} \ No newline at end of file From a1959a9beb957e9f7fc9174257cc1ec5ae7bd704 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 16:20:37 -0700 Subject: [PATCH 07/17] halloween: use halloween npcs habitrpg-shared@0ffd265 --- public/css/npcs.styl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/css/npcs.styl b/public/css/npcs.styl index 084a5c19d4..5fc3bfc879 100644 --- a/public/css/npcs.styl +++ b/public/css/npcs.styl @@ -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-container{margin-bottom: 20px;} From b3853800a38b4729156f38bcd8693ae7a2b09f06 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 16:28:13 -0700 Subject: [PATCH 08/17] remove Ultra Mega Update (since we've been live for a long time). Add bailey notif for halloween, update contrib gear wording as per @lemoness recommendation --- views/shared/modals/new-stuff.jade | 79 ++++++++++-------------------- 1 file changed, 27 insertions(+), 52 deletions(-) diff --git a/views/shared/modals/new-stuff.jade b/views/shared/modals/new-stuff.jade index efcd9bfc47..10cd973803 100644 --- a/views/shared/modals/new-stuff.jade +++ b/views/shared/modals/new-stuff.jade @@ -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 re-wrote the website 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'). - Android & iOS Apps are out! - 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 Tumblr (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 AngularJS + Express. - We desparately need your help porting the rest of the features, and polishing off the bugs. Read this guide 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') .modal-header h3 New Stuff! @@ -58,24 +12,45 @@ div(modal='modals.newStuff') h3.popover-title a(target='_blank', href='https://twitter.com/Mihakuu') Bailey .popover-content - strong 10/19/2013 + strong 10/22/2013 p ul - 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. - li. - You can now sell un-wanted drops to Alex the Merchant. Trade those troves of eggs for gold! + 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 tone sets 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! hr h3 Archive p + h4 10/19/2013 + ul + 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. + li. + You can now sell un-wanted drops to Alex the Merchant. Trade those troves of eggs for gold! h4 09/01/2013 ul li. We re-wrote the website from the ground up And in case you missed it, Android & iOS 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. Read this guide to getting started. - Each of your pull requests shall grant you a special Contributor Gear piece. + 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 re-wrote the website 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'). + Android & iOS Apps are out! + 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 Tumblr (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 AngularJS + Express. + We desparately need your help porting the rest of the features, and polishing off the bugs. Read this guide to getting started. + Thanks everyone for all your support and patience! h4 8/20/2013 ul From 2c7fc724194c3301089b9c85cc85d6fe8ad06957 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 16:33:06 -0700 Subject: [PATCH 09/17] better modal indenting --- public/css/index.styl | 2 +- views/shared/modals/buy-gems.jade | 2 +- views/shared/modals/new-stuff.jade | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/css/index.styl b/public/css/index.styl index 729328f19d..444f3e49f4 100644 --- a/public/css/index.styl +++ b/public/css/index.styl @@ -170,6 +170,6 @@ a .btn margin-right: 5px -.buy-gems-list +.modal-indented-list margin-left: 10px; padding-left: 10px; \ No newline at end of file diff --git a/views/shared/modals/buy-gems.jade b/views/shared/modals/buy-gems.jade index 77d44d26ab..bcb6908943 100644 --- a/views/shared/modals/buy-gems.jade +++ b/views/shared/modals/buy-gems.jade @@ -15,7 +15,7 @@ div(modal='modals.buyGems') a(target='_blank', href='https://twitter.com/bowenNstuff') Justin .popover-content p $5 USD will: - ul.buy-gems-list + ul.modal-indented-list li Add 20 gems to your account, which are used to buy special items. li Disable ads. li Donate to the developers (as an open source project, we can us all the help we can get). diff --git a/views/shared/modals/new-stuff.jade b/views/shared/modals/new-stuff.jade index 10cd973803..64a5682543 100644 --- a/views/shared/modals/new-stuff.jade +++ b/views/shared/modals/new-stuff.jade @@ -14,7 +14,7 @@ div(modal='modals.newStuff') .popover-content strong 10/22/2013 p - ul + 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 tone sets 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! From b90aadf7ab7bed5ec0d7ee9e22004a73ec5a3753 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 16:52:54 -0700 Subject: [PATCH 10/17] update bailey notif --- views/shared/modals/new-stuff.jade | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/views/shared/modals/new-stuff.jade b/views/shared/modals/new-stuff.jade index 64a5682543..ecbf986797 100644 --- a/views/shared/modals/new-stuff.jade +++ b/views/shared/modals/new-stuff.jade @@ -16,7 +16,8 @@ div(modal='modals.newStuff') 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 tone sets 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 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 From e7886e00b4c5f8118caa330302d58e658104f19a Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 17:54:17 -0700 Subject: [PATCH 11/17] halloween: highlght limited skins, add description about limited, rename to "rainbow" and "spooky" @lemoness --- public/css/customizer.styl | 6 +++++- views/options/profile.jade | 27 ++++++++++++++++----------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/public/css/customizer.styl b/public/css/customizer.styl index 7cbbdf3360..e61402f24b 100644 --- a/public/css/customizer.styl +++ b/public/css/customizer.styl @@ -50,4 +50,8 @@ menu .customize-menu { width: 100%; } -} \ No newline at end of file +} + +.well.limited-edition + padding: 5px + margin: 0px \ No newline at end of file diff --git a/views/options/profile.jade b/views/options/profile.jade index c7a22351f1..03a9f623c6 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -25,7 +25,7 @@ // skin li.customize-menu - menu(label='Basic Skin') + menu(label='Basic Skins') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_asian', ng-click='set("preferences.skin","asian")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_white', ng-click='set("preferences.skin","white")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_ea8349', ng-click='set("preferences.skin","ea8349")') @@ -35,8 +35,8 @@ button.customize-option(type='button', class='{{user.preferences.gender}}_skin_dead', ng-click='set("preferences.skin","dead")') button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-click='set("preferences.skin","orc")') - // Special Events - menu(label='Crazy Skin (2G / skin)') + // Rainbow Skin + menu(label='Rainbow Skins (2G / skin)') 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")') @@ -48,14 +48,19 @@ 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 (5G) // Special Events - menu(label='Monster Skin (2G / skin)') - 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 (5G) + 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  + i.icon.icon-question-sign + menu(label='Spooky Skins (2G / skin)') + 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 (5G) + menu(ng-show='user.preferences.gender=="f"', type='list') li.customize-menu From c40697761b53ed265af9cdcbd230dba1e064b403 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 18:16:23 -0700 Subject: [PATCH 12/17] halloween: fix to transient skin set --- public/js/services/userServices.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/services/userServices.js b/public/js/services/userServices.js index dae616f6f0..e25cc89a5c 100644 --- a/public/js/services/userServices.js +++ b/public/js/services/userServices.js @@ -180,7 +180,7 @@ angular.module('userServices', []). if (window.habitrpgShared.helpers.dotGet('purchased.' + path, user)) { var pref = path.split('.')[0], val = path.split('.')[1]; - return window.habitrpgShared.helpers.dotSet('preferences.' + pref, val, user); + 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; From 44cb797063dba66d28281ef5bd3f38993070e595 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 18:50:50 -0700 Subject: [PATCH 13/17] migrate: flags.ads -> purchased.ads (boolean); flags.newStuff to boolean --- migrations/20131022_purchased_and_newStuff.js | 5 +++++ migrations/new_stuff.js | 2 +- public/js/controllers/footerCtrl.js | 2 +- src/controllers/user.js | 4 ++-- src/models/user.js | 3 +-- views/tasks/ads.jade | 2 +- 6 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 migrations/20131022_purchased_and_newStuff.js diff --git a/migrations/20131022_purchased_and_newStuff.js b/migrations/20131022_purchased_and_newStuff.js new file mode 100644 index 0000000000..862d9e107f --- /dev/null +++ b/migrations/20131022_purchased_and_newStuff.js @@ -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}}); +}); \ No newline at end of file diff --git a/migrations/new_stuff.js b/migrations/new_stuff.js index fa517671a6..df2d59e795 100644 --- a/migrations/new_stuff.js +++ b/migrations/new_stuff.js @@ -1 +1 @@ -db.users.update({},{$set:{'flags.newStuff':'show'}},{multi:true}) \ No newline at end of file +db.users.update({},{$set:{'flags.newStuff':true}},{multi:true}) \ No newline at end of file diff --git a/public/js/controllers/footerCtrl.js b/public/js/controllers/footerCtrl.js index 7a31b9532c..3757f3cffb 100644 --- a/public/js/controllers/footerCtrl.js +++ b/public/js/controllers/footerCtrl.js @@ -14,7 +14,7 @@ habitrpg.controller("FooterCtrl", ['$scope', '$rootScope', 'User', '$http', $.getScript('//checkout.stripe.com/v2/checkout.js'); // 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() { // $('body').append(''); // }); diff --git a/src/controllers/user.js b/src/controllers/user.js index c98fdd845d..ecd75a3d28 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -627,7 +627,7 @@ api.buyGems = function(req, res) { }, function(response, cb) { res.locals.user.balance += 5; - res.locals.user.flags.ads = 'hide'; + res.locals.user.purchased.ads = true; res.locals.user.save(cb); } ], function(err, saved){ @@ -652,7 +652,7 @@ api.buyGemsPaypalIPN = function(req, res) { if (err) throw err; if (_.isEmpty(user)) throw "user not found with uuid " + uuid + " when completing paypal transaction" user.balance += 5; - user.flags.ads = 'hide'; + user.purchased.ads = true; user.save(); console.log('PayPal transaction completed and user updated'); }); diff --git a/src/models/user.js b/src/models/user.js index d5f4725170..587bcf22d1 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -78,10 +78,9 @@ var UserSchema = new Schema({ flags: { customizationsNotification: {type: Boolean, 'default': false}, showTour: {type: Boolean, 'default': true}, - ads: {type: String, 'default': 'show'}, // FIXME make this a boolean, run migration dropsEnabled: {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}, partyEnabled: Boolean, // FIXME do we need this? petsEnabled: {type: Boolean, 'default': false}, diff --git a/views/tasks/ads.jade b/views/tasks/ads.jade index f86d0bb5f6..1622a3cb74 100644 --- a/views/tasks/ads.jade +++ b/views/tasks/ads.jade @@ -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"') a(ng-click='modals.buyGems=true', tooltip='Remove Ads') i.icon-remove From 077850b1728216a818f367f22eebd0753a35f72a Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 19:22:32 -0700 Subject: [PATCH 14/17] halloween: explicit gems instead of 'G' --- views/options/profile.jade | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/views/options/profile.jade b/views/options/profile.jade index 03a9f623c6..3b6d723641 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -36,7 +36,10 @@ button.customize-option(type='button', class='{{user.preferences.gender}}_skin_orc', ng-click='set("preferences.skin","orc")') // Rainbow Skin - menu(label='Rainbow Skins (2G / skin)') + h5. + Rainbow Skins (2/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")') @@ -52,7 +55,10 @@ .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  i.icon.icon-question-sign - menu(label='Spooky Skins (2G / skin)') + h5. + Spooky Skins (2/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")') From 619a15b3163e2d6d4c055735f991ccb6d07de467 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 19:33:55 -0700 Subject: [PATCH 15/17] gem icon for unlock-set as well --- views/options/profile.jade | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/views/options/profile.jade b/views/options/profile.jade index 3b6d723641..41a485fc42 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -37,7 +37,7 @@ // Rainbow Skin h5. - Rainbow Skins (2/skin) + Rainbow Skins - 2/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")') @@ -48,7 +48,7 @@ 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 (5G) + 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 // Special Events div.well.limited-edition @@ -56,7 +56,7 @@ | Limited Edition  i.icon.icon-question-sign h5. - Spooky Skins (2/skin) + Spooky Skins - 2/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")') @@ -65,7 +65,7 @@ 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 (5G) + 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 menu(ng-show='user.preferences.gender=="f"', type='list') From 5c4c4ae2527a243a969267bc8bb54ec83fb648cf Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 20:55:55 -0700 Subject: [PATCH 16/17] typo in donate page --- views/shared/modals/buy-gems.jade | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/shared/modals/buy-gems.jade b/views/shared/modals/buy-gems.jade index bcb6908943..e041f2d0ae 100644 --- a/views/shared/modals/buy-gems.jade +++ b/views/shared/modals/buy-gems.jade @@ -18,7 +18,7 @@ div(modal='modals.buyGems') ul.modal-indented-list li Add 20 gems to your account, which are used to buy special items. 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 .row-fluid .span6.well From 9397c1396055a55167da0576c1af023de2639350 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 22 Oct 2013 20:56:13 -0700 Subject: [PATCH 17/17] add an "oh-shit" backtrack migration --- migrations/20131022_restore_ads.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 migrations/20131022_restore_ads.js diff --git a/migrations/20131022_restore_ads.js b/migrations/20131022_restore_ads.js new file mode 100644 index 0000000000..6261990664 --- /dev/null +++ b/migrations/20131022_restore_ads.js @@ -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!"); +}); \ No newline at end of file