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')