From c2b8a6274901c4189dca5d50b67e4f7404d08537 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 21 Nov 2013 09:53:50 -0800 Subject: [PATCH 01/24] [#1879] separate task schema types into habitschema, dailyschema, etc to reduce server load and to ensure the proper default `type` (some people are getting habits in the wrong columns) --- src/models/challenge.js | 10 +++--- src/models/task.js | 75 +++++++++++++++++++++++++++++++---------- src/models/user.js | 10 +++--- 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/src/models/challenge.js b/src/models/challenge.js index d00e533631..40f2ddd0c9 100644 --- a/src/models/challenge.js +++ b/src/models/challenge.js @@ -2,7 +2,7 @@ var mongoose = require("mongoose"); var Schema = mongoose.Schema; var helpers = require('habitrpg-shared/script/helpers'); var _ = require('lodash'); -var TaskSchema = require('./task').schema; +var TaskSchemas = require('./task'); var Group = require('./group').model; var ChallengeSchema = new Schema({ @@ -10,10 +10,10 @@ var ChallengeSchema = new Schema({ name: String, shortName: String, description: String, - habits: [TaskSchema], - dailys: [TaskSchema], - todos: [TaskSchema], - rewards: [TaskSchema], + habits: [TaskSchemas.HabitSchema], + dailys: [TaskSchemas.DailySchema], + todos: [TaskSchemas.TodoSchema], + rewards: [TaskSchemas.RewardSchema], leader: {type: String, ref: 'User'}, group: {type: String, ref: 'Group'}, timestamp: {type: Date, 'default': Date.now}, diff --git a/src/models/task.js b/src/models/task.js index 5a4f28953a..67d32929e9 100644 --- a/src/models/task.js +++ b/src/models/task.js @@ -12,37 +12,78 @@ var _ = require('lodash'); // Task Schema // ----------- -var TaskSchema = new Schema({ +var TaskSchema = { //_id:{type: String,'default': helpers.uuid}, id: {type: String,'default': helpers.uuid}, - history: Array, // [{date:Date, value:Number}], // this causes major performance problems text: String, - date: String, // due date for todos // FIXME we're getting parse errors, people have stored as "today" and "3/13". Need to run a migration & put this back to type: Date notes: {type: String, 'default': ''}, tags: {type: Schema.Types.Mixed, 'default': {}}, //{ "4ddf03d9-54bd-41a3-b011-ca1f1d2e9371" : true }, - type: {type:String, 'default': 'habit'}, // habit, daily - up: {type: Boolean, 'default': true}, - down: {type: Boolean, 'default': true}, - value: {type: Number, 'default': 0}, - completed: {type: Boolean, 'default': false}, + value: {type: Number, 'default': 0}, // redness priority: {type: String, 'default': '!'}, //'!!' // FIXME this should be a number or something - repeat: {type: Schema.Types.Mixed, 'default': {m:1, t:1, w:1, th:1, f:1, s:1, su:1} }, - streak: {type: Number, 'default': 0}, challenge: { id: {type: 'String', ref:'Challenge'}, broken: String, // CHALLENGE_DELETED, TASK_DELETED, UNSUBSCRIBED, CHALLENGE_CLOSED winner: String // user.profile.name // group: {type: 'Strign', ref: 'Group'} // if we restore this, rename `id` above to `challenge` } -},{ - _id: false -}); +}; + +var HabitSchema = new Schema( + _.defaults({ + type: {type:String, 'default': 'habit'}, + history: Array, // [{date:Date, value:Number}], // this causes major performance problems + up: {type: Boolean, 'default': true}, + down: {type: Boolean, 'default': true} + }, TaskSchema) + , { _id: false } +); + +var DailySchema = new Schema( + _.defaults({ + type: {type:String, 'default': 'daily'}, + history: Array, + completed: {type: Boolean, 'default': false}, + repeat: { + m: {type: Boolean, 'default': true}, + t: {type: Boolean, 'default': true}, + w: {type: Boolean, 'default': true}, + th: {type: Boolean, 'default': true}, + f: {type: Boolean, 'default': true}, + s: {type: Boolean, 'default': true}, + su: {type: Boolean, 'default': true} + }, + streak: {type: Number, 'default': 0} + }, TaskSchema) + , { _id: false } +) + +var TodoSchema = new Schema( + _.defaults({ + type: {type:String, 'default': 'todo'}, + completed: {type: Boolean, 'default': false}, + date: String // due date for todos // FIXME we're getting parse errors, people have stored as "today" and "3/13". Need to run a migration & put this back to type: Date + }, TaskSchema) + , { _id: false } +); + +var RewardSchema = new Schema( + _.defaults({ + type: {type:String, 'default': 'reward'} + }, TaskSchema) + , { _id: false } +); /** * Workaround for bug when _id & id were out of sync, we can remove this after challenges has been running for a while */ -TaskSchema.post('init', function(doc){ - if (!doc.id && doc._id) doc.id = doc._id; -}) +//_.each([HabitSchema, DailySchema, TodoSchema, RewardSchema], function(schema){ +// schema.post('init', function(doc){ +// if (!doc.id && doc._id) doc.id = doc._id; +// }) +//}) -module.exports.schema = TaskSchema; \ No newline at end of file +module.exports.TaskSchema = TaskSchema; +module.exports.HabitSchema = HabitSchema; +module.exports.DailySchema = DailySchema; +module.exports.TodoSchema = TodoSchema; +module.exports.RewardSchema = RewardSchema; diff --git a/src/models/user.js b/src/models/user.js index f1ac9ea5e5..94dd5cb9f9 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -9,7 +9,7 @@ var Schema = mongoose.Schema; var helpers = require('habitrpg-shared/script/helpers'); var items = require('habitrpg-shared/script/items'); var _ = require('lodash'); -var TaskSchema = require('./task').schema; +var TaskSchemas = require('./task'); var Challenge = require('./challenge').model; // User Schema @@ -216,10 +216,10 @@ var UserSchema = new Schema({ challenges: [{type: 'String', ref:'Challenge'}], - habits: [TaskSchema], - dailys: [TaskSchema], - todos: [TaskSchema], - rewards: [TaskSchema], + habits: [TaskSchemas.HabitSchema], + dailys: [TaskSchemas.DailySchema], + todos: [TaskSchemas.TodoSchema], + rewards: [TaskSchemas.RewardSchema], }, { strict: true, From 83e3a6aff293cdc3efb2b18982a5b0fd0e303646 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sat, 16 Nov 2013 02:22:12 -0800 Subject: [PATCH 02/24] classes WIP --- public/css/header.styl | 2 + public/css/index.styl | 11 +++- public/css/tasks.styl | 2 +- public/js/controllers/rootCtrl.js | 49 ++++++++++++++++- public/js/controllers/tasksCtrl.js | 7 +++ public/js/controllers/userCtrl.js | 21 +++++++ src/controllers/user.js | 61 +++++++++++++++++++++ src/models/user.js | 30 +++++++++- src/routes/api.js | 1 + views/index.jade | 5 +- views/options/profile.jade | 88 +++++++++++++++++++++++++----- views/shared/header/avatar.jade | 28 ++++++---- views/shared/header/header.jade | 9 ++- views/shared/modals/classes.jade | 45 +++++++++++++++ views/shared/modals/index.jade | 3 +- views/shared/tasks/lists.jade | 18 +++++- views/shared/tasks/task.jade | 10 +++- 17 files changed, 351 insertions(+), 39 deletions(-) create mode 100644 views/shared/modals/classes.jade diff --git a/public/css/header.styl b/public/css/header.styl index a12f1b1408..f5013ec182 100644 --- a/public/css/header.styl +++ b/public/css/header.styl @@ -150,6 +150,8 @@ background: darken($worse, 38%) .experience .bar background: darken($neutral, 30%) + .mana .bar + background: darken($best, 30%) .meter-text position: absolute diff --git a/public/css/index.styl b/public/css/index.styl index 62c4b06f1a..c8af436a16 100644 --- a/public/css/index.styl +++ b/public/css/index.styl @@ -173,4 +173,13 @@ a .modal-indented-list margin-left: 10px; - padding-left: 10px; \ No newline at end of file + padding-left: 10px; + +// Spells + +html.applying-action, html.applying-action * + cursor: copy !important +.cast-target:hover + border: 5px solid green !important +.selected-class + background-color: green \ No newline at end of file diff --git a/public/css/tasks.styl b/public/css/tasks.styl index 680fd1ce65..1cd7709df9 100644 --- a/public/css/tasks.styl +++ b/public/css/tasks.styl @@ -402,4 +402,4 @@ form color: #333 &:hover border-top: 0 - margin-top: 2px + margin-top: 2px \ No newline at end of file diff --git a/public/js/controllers/rootCtrl.js b/public/js/controllers/rootCtrl.js index 607bd333e7..bbf43d1a84 100644 --- a/public/js/controllers/rootCtrl.js +++ b/public/js/controllers/rootCtrl.js @@ -3,8 +3,8 @@ /* Make user and settings available for everyone through root scope. */ -habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', - function($scope, $rootScope, $location, User, $http, $state, $stateParams) { +habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', + function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification) { $rootScope.modals = {}; $rootScope.modals.achievements = {}; $rootScope.User = User; @@ -121,5 +121,50 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ chart = new google.visualization.LineChart($("." + id + "-chart")[0]); chart.draw(data, options); }; + + + + /* + ------------------------ + Spells + ------------------------ + */ + $scope.castStart = function(spell) { + if (User.user.stats.mp < spell.mana) return Notification.text("Not enough mana."); + $rootScope.applyingAction = true; + $scope.spell = spell; + if (spell.target == 'self') { + debugger + var tasks = User.user.habits.concat(User.user.dailys).concat(User.user.todos); + User.user.tasks = _.object(_.pluck(tasks,'id'), tasks); + $scope.castEnd(null, 'self'); + } else if (spell.target == 'party') { + //TODO $scope.castEnd() + } + } + + $scope.castEnd = function(target, type, $event){ + if ($scope.spell.target != type) return Notification.text("Invalid target"); + $scope.spell.cast(User.user, target); + $http.post('/api/v1/user/cast/' + $scope.spell.name, {target:target, type:type}).success(function(){ + var msg = "You cast " + $scope.spell.text; + switch (type) { + case 'task': msg += ' on ' + target.text;break; + case 'user': msg += ' on ' + target.profile.name;break; + case 'party': msg += ' on the Party';break; + } + Notification.text(msg); + $rootScope.applyingAction = false; + $scope.spell = null; + //User.sync(); // FIXME push a lot of the server code to also in client, so we can run updates in browser without requiring sync + }) + $event && $event.stopPropagation(); + } + +// $rootScope.castCancel = function(){ +// debugger +// $rootScope.applyingAction = false; +// $scope.spell = null; +// } } ]); diff --git a/public/js/controllers/tasksCtrl.js b/public/js/controllers/tasksCtrl.js index 5b599e9473..323f944f28 100644 --- a/public/js/controllers/tasksCtrl.js +++ b/public/js/controllers/tasksCtrl.js @@ -132,6 +132,13 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', ' User.log({op: 'clear-completed'}); } + + /* + ------------------------ + Ads + ------------------------ + */ + /** * See conversation on http://productforums.google.com/forum/#!topic/adsense/WYkC_VzKwbA, * Adsense is very sensitive. It must be called once-and-only-once for every , else things break. diff --git a/public/js/controllers/userCtrl.js b/public/js/controllers/userCtrl.js index 793f54c9f7..ab5f3bea1c 100644 --- a/public/js/controllers/userCtrl.js +++ b/public/js/controllers/userCtrl.js @@ -14,6 +14,27 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$ if(value === true) $scope.editingProfile = angular.copy(User.user.profile); }); + $scope.allocate = function(stat){ + var setObj = {} + setObj['stats.' + stat] = User.user.stats[stat] + 1; + setObj['stats.points'] = User.user.stats.points - 1; + User.setMultiple(setObj); + } + + $scope.rerollClass = function(){ + if (!confirm("Are you sure you want to re-roll? This will reset your character's class and allocated points (you'll get them all back to re-allocate)")) + return; + User.setMultiple({ + 'stats.class': '', + //'stats.points': this is handled on the server + 'stats.str': 0, + 'stats.def': 0, + 'stats.per': 0, + 'stats.int': 0 + }) + + } + $scope.save = function(){ var values = {}; _.each($scope.editingProfile, function(value, key){ diff --git a/src/controllers/user.js b/src/controllers/user.js index 560b5a7776..915ed348ae 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -482,6 +482,67 @@ api.deleteTag = function(req, res){ } } +/* + ------------------------------------------------------------------------ + Spells + ------------------------------------------------------------------------ + */ +api.cast = function(req, res) { + var user = res.locals.user; + var type = req.body.type, target = req.body.target; + var spell = items.items.spells[user.stats.class][req.params.spell]; + + var done = function(){ + var err = arguments[0]; + var saved = _.size(arguments == 3) ? arguments[2] : arguments[1]; + if (err) return res.json(500, {err:err}); + res.json(saved); + } + + switch (type) { + case 'task': + spell.cast(user, user.tasks[target.id]); + user.save(done); + break; + + case 'self': + spell.cast(user); + user.save(done); + break; + + case 'party': + async.waterfall([ + function(cb){ + Group.findOne({type: 'party', members: {'$in': [user._id]}}).populate('members').exec(cb); + }, + function(group, cb) { + spell.cast(user, group.members); + var series = _.reduce(group.members, function(m,v){ + m.push(function(cb2){v.save(cb2);}) + return m; + }, []); + async.series(series, cb); + } + ], done); + break; + + case 'user': + async.waterfall([ + function(cb) { + User.findById(target._id, cb); + }, + function(member, cb) { + spell.cast(user, member); + member.save(cb); // not parallel because target could be user, which causes race condition when saving + }, + function(saved, num, cb) { + user.save(cb); + } + ], done); + break; + } +} + /* ------------------------------------------------------------------------ Batch Update diff --git a/src/models/user.js b/src/models/user.js index 94dd5cb9f9..80a11b878d 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -188,12 +188,17 @@ var UserSchema = new Schema({ armorSet: String, dayStart: {type:Number, 'default': 0}, gender: {type:String, 'default': 'm'}, - hair: {type:String, 'default':'blond'}, + hair: { + color: {type: String, 'default': 'blonde'}, + base: {type: Number, 'default': 0}, + bangs: {type: Number, 'default': 0} + }, hideHeader: {type:Boolean, 'default':false}, showHelm: {type:Boolean, 'default':true}, skin: {type:String, 'default':'white'}, timezoneOffset: Number, - language: String + language: String, + automaticAllocation: Boolean }, profile: { blurb: String, @@ -202,9 +207,24 @@ var UserSchema = new Schema({ }, stats: { hp: Number, + mp: Number, exp: Number, gp: Number, - lvl: Number + lvl: Number, + + // Class System + 'class': String, + points: {type: Number, 'default': 0}, + str: {type: Number, 'default': 0}, + def: {type: Number, 'default': 0}, + int: {type: Number, 'default': 0}, + per: {type: Number, 'default': 0}, + buffs: { + str: Number, + def: Number, + per: Number, + stealth: Number + } }, tags: [ { @@ -264,6 +284,10 @@ UserSchema.pre('save', function(next) { 'Anonymous'; } + // FIXME handle this on level-up instead, and come up with how we're going to handle retroactively + // Actually, can this be used as an attr default? (schema {type: ..., 'default': function(){}}) + this.stats.points = this.stats.lvl - (this.stats.def + this.stats.str + this.stats.per + this.stats.int); + var petCount = _.reduce(this.items.pets,function(m,v){return m+(v ? 1 : 0);},0); this.achievements.beastMaster = petCount >= 90; diff --git a/src/routes/api.js b/src/routes/api.js index cdee266826..34c3c3327d 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -60,6 +60,7 @@ 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.post('/user/cast/:spell', auth.auth, user.cast); router['delete']('/user', auth.auth, user['delete']); /* Tags */ diff --git a/views/index.jade b/views/index.jade index 733bdca2ae..b28e87b716 100644 --- a/views/index.jade +++ b/views/index.jade @@ -1,5 +1,6 @@ doctype 5 -html +//html(ng-app="habitrpg", ng-controller="RootCtrl", ng-class='{"applying-action":applyingAction}', ui-keypress="{27:'castCancel()'}") +html(ng-app="habitrpg", ng-controller="RootCtrl", ng-class='{"applying-action":applyingAction}', ui-keypress="{27:'castCancel()'}") head title HabitRPG | Your Life The Role Playing Game @@ -21,7 +22,7 @@ html meta(name='viewport', content='width=device-width') meta(name='apple-mobile-web-app-capable', content='yes') - body(ng-app="habitrpg", ng-controller="RootCtrl", ng-cloak) + body(ng-cloak) div(ng-controller='GroupsCtrl') include ./shared/modals/index include ./shared/header/header diff --git a/views/options/profile.jade b/views/options/profile.jade index 27c5baa885..470cf8758d 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -12,21 +12,44 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') input(type='checkbox', ng-model='user.preferences.showHelm', ng-change='toggleHelm(user.preferences.showHelm)') | Show Helm - menu(ng-show='user.preferences.gender=="f"', type='list') - li.customize-menu - menu(label='Clothing') - button.f_armor_0_v1.customize-option(type='button', ng-click='set("preferences.armorSet","v1")') - button.f_armor_0_v2.customize-option(type='button', ng-click='set("preferences.armorSet","v2")') + menu(ng-show='user.preferences.gender=="f"', type='list') + li.customize-menu + menu(label='Clothing') + button.f_armor_0_v1.customize-option(type='button', ng-click='set("preferences.armorSet","v1")') + button.f_armor_0_v2.customize-option(type='button', ng-click='set("preferences.armorSet","v2")') .span4 - // hair - li.customize-menu - menu(label='Hair') - button(class='{{user.preferences.gender}}_hair_blond customize-option', type='button', ng-click='set("preferences.hair","blond")') - 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")') - button(class='{{user.preferences.gender}}_hair_red customize-option', type='button', ng-click='set("preferences.hair","red")') + h3 Hair + menu(type='list') + // Color + li.customize-menu + menu(label='Color') + button(type='button', class='customize-option', style='width: 40px; height: 40px; background-color:#c8c8c8;', ng-click='set("preferences.hair.color", "white")') + button(type='button', class='customize-option', style='width: 40px; height: 40px; background-color:#903a00;', ng-click='set("preferences.hair.color", "brown")') + button(type='button', class='customize-option', style='width: 40px; height: 40px; background-color:#cfb853;', ng-click='set("preferences.hair.color", "blond")') + button(type='button', class='customize-option', style='width: 40px; height: 40px; background-color:#ec720f;', ng-click='set("preferences.hair.color", "red")') + button(type='button', class='customize-option', style='width: 40px; height: 40px; background-color:#2e2e2e;', ng-click='set("preferences.hair.color", "black")') + + // Bangs + li.customize-menu + menu(label='Bangs') + button(class='{{user.preferences.gender}}_hair_bangs_0_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') + button(class='{{user.preferences.gender}}_hair_bangs_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",1)') + button(class='{{user.preferences.gender}}_hair_bangs_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",2)') + button(class='{{user.preferences.gender}}_hair_bangs_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",3)') + + // Base + li.customize-menu + menu(label='Base') + button(class='{{user.preferences.gender}}_hair_base_0_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",0)') + button(class='{{user.preferences.gender}}_hair_base_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",1)') + button(class='{{user.preferences.gender}}_hair_base_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",2)') + button(class='{{user.preferences.gender}}_hair_base_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",3)') + button(class='{{user.preferences.gender}}_hair_base_4_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",4)') + button(class='{{user.preferences.gender}}_hair_base_5_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",5)') + button(class='{{user.preferences.gender}}_hair_base_6_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",6)') + button(class='{{user.preferences.gender}}_hair_base_7_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",7)') + button(class='{{user.preferences.gender}}_hair_base_8_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",8)') .span4 // skin @@ -70,9 +93,44 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') script(id='partials/options.profile.stats.html', type='text/ng-template') .row-fluid - .span6.border-right + .border-right(ng-class='user.stats.lvl < 5 ? "span6" : "span4"') include ../shared/profiles/stats - .span6.border-right + .span4.border-right(ng-show='user.stats.lvl >= 5') + h4 + | {{user.stats.class}}  + a.btn.btn-danger.btn-mini(ng-click='rerollClass()') Re-roll + h6 Points: {{user.stats.points}} + fieldset + label.checkbox + input(type='checkbox', ng-model='user.preferences.automaticAllocation', ng-change='set("preferences.automaticAllocation", user.preferences.automaticAllocation?true: false)') + | Automatic Allocation + i.icon-question-sign(popover-trigger='mouseenter', popover-placement='bottom', popover="When 'automatic' is checked, your points will be allocated to the stat representing your task focus (see Task > Edit). When unchecked, you'll have one point to allocate each level. The system makes a suggestion, but you can ignore the suggestion.") + table.table.table-striped + tr + td + i.icon-question-sign(popover-title='Strength', popover='Strength increases damage you inflict to tasks, reducing their redness', popover-trigger='mouseenter') + |  STR: {{user.stats.str}} + td + a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("str")') + + tr + td + i.icon-question-sign(popover-title='Defense', popover='Defense decreases damage inflicted by tasks, and increases the effectiveness of healing and buff spells', popover-trigger='mouseenter') + |  DEF: {{user.stats.def}} + td + a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("def")') + + tr + td + i.icon-question-sign(popover-title='Perception', popover='Perception increases the likelihood of drops, Gold bonuses, and critical hit chances', popover-trigger='mouseenter') + |  PER: {{user.stats.per}} + td + a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("per")') + + tr + td + i.icon-question-sign(popover-title='Intelligence', popover='Intelligence increases your overall mana, allowing you to cast more spells', popover-trigger='mouseenter') + |  INT: {{user.stats.int}} + td + a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("int")') + + .border-right(ng-class='user.stats.lvl < 5 ? "span6" : "span4"') include ../shared/profiles/achievements script(id='partials/options.profile.profile.html', type='text/ng-template') diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 3154f5f92d..7e0ac9b371 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -3,27 +3,35 @@ Removing it will remove the user's name, but will allow more room for mounts & helms. IMO this is the lesser of two evils, revisit //-figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: profile.id==user.id, hasPet: profile.items.currentPet}', data-level='{{profile.stats.lvl}}', data-uid='{{profile.id}}', rel='popover', data-placement='bottom', data-trigger='hover', data-html='true', data-content="
Level: {{profile.stats.lvl}}
GP: {{profile.stats.gp | number:0}}
{{count(profile.items.pets)}} / 90 Pets Found
") -figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: user._id==profile._id && !(user.items.currentMount && user.items.currentPet), hasPet: profile.items.currentPet && profile.items.currentMount}') +figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: user._id==profile._id && !(user.items.currentMount && user.items.currentPet), hasPet: profile.items.currentPet && profile.items.currentMount, "cast-target": applyingAction}') .character-sprites // Mount Body span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}') // Avatar - span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') - span(class='{{profile.preferences.gender}}_hair_{{profile.preferences.hair}}') - span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}') - span(class='{{profile.preferences.gender}}_head_0', ng-hide='profile.preferences.showHelm') - span(class='{{equipped("head", profile.items.head, profile.preferences, profile.backer, profile.contributor)}}', ng-show='profile.preferences.showHelm') - span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}') - span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}') + //span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') + //span(class='{{profile.preferences.gender}}_head_0') + //span(class='{{profile.preferences.gender}}_hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') + //span(class='{{profile.preferences.gender}}_hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') + //span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') + //span(class='{{equipped("head", profile.items.head, profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}', ng-show='profile.preferences.showHelm') + //span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') + //span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') + + span(class='m_skin_{{profile.preferences.skin}}') + span(class='m_head_0') + span(class='m_hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') + span(class='m_hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') + span(class='m_armor_{{profile.items.armor}}-{{profile.stats.class}}') + span(class='m_head_{{profile.items.head}}-{{profile.stats.class}}', ng-show='profile.preferences.showHelm') + span(class='m_shield_{{profile.items.shield}}-{{profile.stats.class}}') + span(class='m_weapon_{{profile.items.weapon}}-{{profile.stats.class}}') // Mount Head span(ng-if='profile.items.currentMount', class='Mount_Head_{{profile.items.currentMount}}') // Resting span(ng-class='{zzz:profile.flags.rest}') - - // Pet // FIXME handle @minimal, this might have to be a directive span.current-pet(class='Pet-{{profile.items.currentPet}}', ng-show='profile.items.currentPet && !minimal') .avatar-level Lvl {{profile.stats.lvl}} diff --git a/views/shared/header/header.jade b/views/shared/header/header.jade index 626d295786..b37f2be6eb 100644 --- a/views/shared/header/header.jade +++ b/views/shared/header/header.jade @@ -1,5 +1,4 @@ -//.header-wrap(ng-controller='HeaderCtrl', data-spy="affix", data-offset-top="148") -.header-wrap(ng-controller='HeaderCtrl') +.header-wrap(ng-controller='HeaderCtrl', data-spy="affix", data-offset-top="148") a.label.undo-button(x-bind='click:undo', ng-show='_undo') Undo div(ng-if='!user.preferences.hideHeader') include menu @@ -25,6 +24,12 @@ span(ng-show='user.history.exp') a(ng-click='toggleChart("exp")', tooltip='Progress') i.icon-signal + .meter.mana(title='Mana', ng-if='user.stats.class') + .bar(style='width: {{percent(user.stats.mp, user.stats.int+10)}}%;') + span.meter-text + i.icon-fire + | {{user.stats.mp || 0 | number:0}} / {{user.stats.int+10}} + // party span(ng-controller='PartyCtrl') .herobox-wrap(ng-repeat='profile in partyMinusSelf') diff --git a/views/shared/modals/classes.jade b/views/shared/modals/classes.jade new file mode 100644 index 0000000000..985352462b --- /dev/null +++ b/views/shared/modals/classes.jade @@ -0,0 +1,45 @@ +.modal(ng-if='user.stats.lvl >= 10 && !user.stats.class', data-backdrop=true) + .modal-header + h3 Class System Unlocked! + .modal-body + .well Select your class. Upon level-up, you will now be able to allocate points to various stats. Alternatively, you can choose which stat your tasks represent (physical, mental, social, or "other") and drive your class automatically. + .well(ng-show='selectedClass=="warrior"') Warriors deal moderate damage to tasks and have moderate defense against tasks. + .well(ng-show='selectedClass=="wizard"') Wizards deal high damage to task, and can cast debuff spells on multiple tasks. + .well(ng-show='selectedClass=="rogue"') Rogues finds more drops, Gold, and have a high chance of dealing "critical hits," which grant large GP & Exp bonuses. Rogues can also "go stealth" to avoid and entire day of dailies. + .well(ng-show='selectedClass=="healer"') Healers have high defense against damage, and can heal themselves and other players in the party, as well as buff players. + .row-fluid + .span3(ng-click='selectedClass = "warrior"') + h5 Warrior + figure.herobox(ng-class='{"selected-class": selectedClass=="warrior"}') + .character-sprites + span(class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}') + span(class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}') + span(class='{{user.preferences.gender}}_armor_5-warrior') + span(class='{{user.preferences.gender}}_head_5-warrior') + .span3(ng-click='selectedClass = "wizard"') + h5 Wizard + figure.herobox(ng-class='{"selected-class": selectedClass=="wizard"}') + .character-sprites + span(class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}') + span(class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}') + span(class='{{user.preferences.gender}}_armor_5-wizard') + span(class='{{user.preferences.gender}}_head_5-wizard') + .span3(ng-click='selectedClass = "rogue"') + h5 Rogue + figure.herobox(ng-class='{"selected-class": selectedClass=="rogue"}') + .character-sprites + span(class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}') + span(class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}') + span(class='{{user.preferences.gender}}_armor_5-rogue') + span(class='{{user.preferences.gender}}_head_5-rogue') + .span3(ng-click='selectedClass = "healer"') + h5 Healer + figure.herobox(ng-class='{"selected-class": selectedClass=="healer"}') + .character-sprites + span(class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}') + span(class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}') + span(class='{{user.preferences.gender}}_armor_5-healer') + span(class='{{user.preferences.gender}}_head_5-healer') + + .modal-footer + button.btn.btn-default.cancel(ng-click='set("stats.class", selectedClass)') Select \ No newline at end of file diff --git a/views/shared/modals/index.jade b/views/shared/modals/index.jade index 6d15f517b7..339424984e 100644 --- a/views/shared/modals/index.jade +++ b/views/shared/modals/index.jade @@ -6,4 +6,5 @@ include ./new-stuff include ./buy-gems include ./members include ./settings -include ./pets \ No newline at end of file +include ./pets +include ./classes \ No newline at end of file diff --git a/views/shared/tasks/lists.jade b/views/shared/tasks/lists.jade index df20e2d6ee..7d1f8fca55 100644 --- a/views/shared/tasks/lists.jade +++ b/views/shared/tasks/lists.jade @@ -45,7 +45,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") include ./task // Static Rewards - ul.items(ng-show='main && list.type=="reward" && user.flags.itemsEnabled') + ul.items.rewards(ng-if='main && list.type=="reward" && user.flags.itemsEnabled') li.task.reward-item(ng-hide='item.hide', ng-repeat='item in itemStore') // right-hand side control buttons .task-meta-controls @@ -62,6 +62,22 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") span(ng-class='{"shop_{{item.classes}} shop-sprite item-img": true}') p.task-text {{item.text}} + // Spells + ul.items(ng-if='main && list.type=="reward" && user.stats.class') + li.task.reward-item(ng-repeat='(k,spell) in Items.spells[user.stats.class]') + .task-meta-controls + span.task-notes(popover-trigger='mouseenter', popover-placement='left', popover='{{spell.notes}}', popover-title='{{spell.text}}') + i.icon-comment + //left-hand size commands + .task-controls + a.money.btn-buy.item-btn(ng-click='castStart(spell)') + span.reward-cost + strong {{spell.mana}} + |  MP + // main content + span(ng-class='{"shop_{{spell.classes}} shop-sprite item-img": true}') + p.task-text {{spell.text}} + br // Ads diff --git a/views/shared/tasks/task.jade b/views/shared/tasks/task.jade index c20f601c58..cdd677a504 100644 --- a/views/shared/tasks/task.jade +++ b/views/shared/tasks/task.jade @@ -1,4 +1,4 @@ -li(ng-repeat='task in obj[list.type+"s"]', class='task {{taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', data-id='{{task.id}}') +li(ng-repeat='task in obj[list.type+"s"]', class='task {{taskClasses(task, user.filters, user.preferences.dayStart, user.lastCron, list.showCompleted, main)}}', ng-click='spell && castEnd(task, "task", $event)', ng-class='{"cast-target":spell}') // right-hand side control buttons .task-meta-controls @@ -159,6 +159,14 @@ li(ng-repeat='task in obj[list.type+"s"]', class='task {{taskClasses(task, user. span(ng-if='task.type=="daily" && !task.challenge.id') legend.option-title Restore Streak input.option-content(type='number', ng-model='task.streak') + + legend.option-title Attributes + .task-controls.tile-group + button.task-action-btn.tile(type='button') Physical + button.task-action-btn.tile(type='button') Mental + button.task-action-btn.tile(type='button') Social + button.task-action-btn.tile(type='button') Other + button.task-action-btn.tile.spacious(type='submit') Save & Close div(class='{{obj._id}}{{task.id}}-chart', ng-show='charts[obj._id+task.id]') From 91c141140d795ff44d7981093a3a57336190e260 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sat, 30 Nov 2013 14:55:39 -0700 Subject: [PATCH 03/24] classes: armory WIP --- public/js/controllers/settingsCtrl.js | 12 ++++++------ public/js/controllers/tasksCtrl.js | 9 +++------ src/controllers/user.js | 11 +++++------ src/models/user.js | 21 +++++++++++++++----- src/routes/api.js | 2 +- views/options/inventory/inventory.jade | 5 +++++ views/shared/header/avatar.jade | 26 ++++++++++++------------- views/shared/modals/settings.jade | 27 +++++++++++++------------- views/shared/tasks/lists.jade | 4 ++-- 9 files changed, 65 insertions(+), 52 deletions(-) diff --git a/public/js/controllers/settingsCtrl.js b/public/js/controllers/settingsCtrl.js index e0747ba473..2d4574d493 100644 --- a/public/js/controllers/settingsCtrl.js +++ b/public/js/controllers/settingsCtrl.js @@ -73,24 +73,24 @@ habitrpg.controller('SettingsCtrl', $rootScope.$watch('modals.restore', function(value){ if(value === true){ $scope.restoreValues.stats = angular.copy(User.user.stats); - $scope.restoreValues.items = angular.copy(User.user.items); +// $scope.restoreValues.items = angular.copy(User.user.items); $scope.restoreValues.achievements = {streak: User.user.achievements.streak || 0}; } }) $scope.restore = function(){ var stats = $scope.restoreValues.stats, - items = $scope.restoreValues.items, +// items = $scope.restoreValues.items, achievements = $scope.restoreValues.achievements; User.setMultiple({ "stats.hp": stats.hp, "stats.exp": stats.exp, "stats.gp": stats.gp, "stats.lvl": stats.lvl, - "items.weapon": items.weapon, - "items.armor": items.armor, - "items.head": items.head, - "items.shield": items.shield, +// "items.weapon": items.weapon, +// "items.armor": items.armor, +// "items.head": items.head, +// "items.shield": items.shield, "achievements.streak": achievements.streak }); $rootScope.modals.restore = false; diff --git a/public/js/controllers/tasksCtrl.js b/public/js/controllers/tasksCtrl.js index 323f944f28..fb6c35b89c 100644 --- a/public/js/controllers/tasksCtrl.js +++ b/public/js/controllers/tasksCtrl.js @@ -105,12 +105,9 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', ' */ var updateStore = function(){ - var sorted, updated; - updated = window.habitrpgShared.items.updateStore(User.user); - /* Figure out whether we wanna put this in habitrpg-shared - */ - - sorted = [updated.weapon, updated.armor, updated.head, updated.shield, updated.potion, updated.reroll]; + var updated = window.habitrpgShared.items.updateStore(User.user); + // Figure out whether we wanna put this in habitrpg-shared + var sorted = [updated.weapon, updated.armor, updated.head, updated.shield, updated.potion, updated.reroll]; $scope.itemStore = sorted; } diff --git a/src/controllers/user.js b/src/controllers/user.js index 915ed348ae..8c875dc1dc 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -203,13 +203,12 @@ api.clearCompleted = function(req, res, next) { ------------------------------------------------------------------------ */ api.buy = function(req, res, next) { - var hasEnough, type, user; - user = res.locals.user; - type = req.params.type; - if (type !== 'weapon' && type !== 'armor' && type !== 'head' && type !== 'shield' && type !== 'potion') { - return res.json(400, {err: ":type must be in one of: 'weapon', 'armor', 'head', 'shield', 'potion'"}); + var user = res.locals.user; + var item = req.params.item; + if (item !== 'potion' && !items.items.gear.flat[item]) { + return res.json(400, {err: ":item must be a supported key, see https://github.com/HabitRPG/habitrpg-shared/blob/master/script/items.coffee"}); } - hasEnough = items.buyItem(user, type); + var hasEnough = items.buyItem(user, type); if (hasEnough) { return user.save(function(err, saved) { if (err) return res.json(500, {err: err}); diff --git a/src/models/user.js b/src/models/user.js index 80a11b878d..d13dd60360 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -105,10 +105,20 @@ var UserSchema = new Schema({ party: Schema.Types.Mixed }, items: { - armor: Number, - weapon: Number, - head: Number, - shield: Number, + gear: { + owned: _.transform(items.items.gear.flat, function(m,v,k){ + m[v.key] = {type: Boolean}; + if (v.key.match(/[weapon|armor|head|shield]_warrior_0/)) + m[v.key]['default'] = true; + }), + + current: { + weapon: {type: String, 'default': 'weapon_warrior_0'}, + armor: {type: String, 'default': 'armor_warrior_0'}, + head: {type: String, 'default': 'head_warrior_0'}, + shield: {type: String, 'default': 'shield_warrior_0'} + } + }, // -------------- Animals ------------------- @@ -213,7 +223,8 @@ var UserSchema = new Schema({ lvl: Number, // Class System - 'class': String, +// 'class': {type: String, enum: ['warrior','rogue','wizard','rogue'], 'default': 'warrior'}, + 'class': {type: String, 'default': 'warrior'}, points: {type: Number, 'default': 0}, str: {type: Number, 'default': 0}, def: {type: Number, 'default': 0}, diff --git a/src/routes/api.js b/src/routes/api.js index 34c3c3327d..209a183313 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -48,7 +48,7 @@ if (nconf.get('NODE_ENV') == 'development') { } /* Items*/ -router.post('/user/buy/:type', auth.auth, cron, user.buy); +router.post('/user/buy/:item', auth.auth, cron, user.buy); /* User*/ router.get('/user', auth.auth, cron, user.getUser); diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index f74df36c94..5513af5b37 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -5,6 +5,11 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') p.well Click an egg to see usable potions highlighted in green and then click one of the highlighted potions to hatch your pet. If no potions are highlighted, click that egg again to deselect it, and instead click a potion first to have the usable eggs highlighted. You can also sell unwanted drops to Alexander the Merchant. menu.inventory-list(type='list') + li.customize-menu + menu.pets-menu(label='Gear') + div(ng-repeat='(k,v) in user.items.gear.owned') + button.customize-option(popover='{{Items.gear.flat[k].notes}}', popover-title='{{Items.gear.flat[k].text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(v)', class='shop_{{v.key}}') + li.customize-menu menu.pets-menu(label='Eggs ({{eggCount}})') p(ng-show='eggCount < 1') You don't have any eggs yet. diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 7e0ac9b371..e608026e84 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -8,24 +8,24 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( // Mount Body span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}') - // Avatar - //span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') - //span(class='{{profile.preferences.gender}}_head_0') - //span(class='{{profile.preferences.gender}}_hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') - //span(class='{{profile.preferences.gender}}_hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') - //span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') - //span(class='{{equipped("head", profile.items.head, profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}', ng-show='profile.preferences.showHelm') - //span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') - //span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') + //- Avatar + //-span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') + //-span(class='{{profile.preferences.gender}}_head_0') + //-span(class='{{profile.preferences.gender}}_hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') + //-span(class='{{profile.preferences.gender}}_hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') + //-span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') + //-span(class='{{equipped("head", profile.items.head, profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}', ng-show='profile.preferences.showHelm') + //-span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') + //-span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') span(class='m_skin_{{profile.preferences.skin}}') span(class='m_head_0') span(class='m_hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') span(class='m_hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') - span(class='m_armor_{{profile.items.armor}}-{{profile.stats.class}}') - span(class='m_head_{{profile.items.head}}-{{profile.stats.class}}', ng-show='profile.preferences.showHelm') - span(class='m_shield_{{profile.items.shield}}-{{profile.stats.class}}') - span(class='m_weapon_{{profile.items.weapon}}-{{profile.stats.class}}') + span(class='m_{{profile.items.gear.current.armor}}') + span(class='m_{{profile.items.gear.current.head}}', ng-show='profile.preferences.showHelm') + span(class='m_{{profile.items.gear.current.shield}}') + span(class='m_{{profile.items.gear.current.weapon}}') // Mount Head span(ng-if='profile.items.currentMount', class='Mount_Head_{{profile.items.currentMount}}') diff --git a/views/shared/modals/settings.jade b/views/shared/modals/settings.jade index 6aafed4060..3f9f5b2f4d 100644 --- a/views/shared/modals/settings.jade +++ b/views/shared/modals/settings.jade @@ -29,19 +29,20 @@ div(ng-controller='SettingsCtrl') .option-group.option-medium input.option-content(type='number', data-for='stats.lvl', ng-model='restoreValues.stats.lvl') span.input-suffix Level - h3 Items - .option-group.option-medium - input.option-content(type='number', data-for='items.weapon', ng-model='restoreValues.items.weapon') - span.input-suffix Weapon - .option-group.option-medium - input.option-content(type='number', data-for='items.armor', ng-model='restoreValues.items.armor') - span.input-suffix Armor - .option-group.option-medium - input.option-content(type='number', data-for='items.head', ng-model='restoreValues.items.head') - span.input-suffix Helm - .option-group.option-medium - input.option-content(type='number', data-for='items.shield', ng-model='restoreValues.items.shield') - span.input-suffix Shield + //- + h3 Items + .option-group.option-medium + input.option-content(type='number', data-for='items.weapon', ng-model='restoreValues.items.weapon') + span.input-suffix Weapon + .option-group.option-medium + input.option-content(type='number', data-for='items.armor', ng-model='restoreValues.items.armor') + span.input-suffix Armor + .option-group.option-medium + input.option-content(type='number', data-for='items.head', ng-model='restoreValues.items.head') + span.input-suffix Helm + .option-group.option-medium + input.option-content(type='number', data-for='items.shield', ng-model='restoreValues.items.shield') + span.input-suffix Shield h3 Streak Achievements .option-group.option-medium input.option-content(type='number', data-for='achievements.streak', ng-model='restoreValues.achievements.streak') diff --git a/views/shared/tasks/lists.jade b/views/shared/tasks/lists.jade index 7d1f8fca55..5d87f68a6b 100644 --- a/views/shared/tasks/lists.jade +++ b/views/shared/tasks/lists.jade @@ -59,7 +59,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") span.reward-cost {{item.value}} span.shop_gold // main content - span(ng-class='{"shop_{{item.classes}} shop-sprite item-img": true}') + span(ng-class='{"shop_{{item.key}} shop-sprite item-img": true}') p.task-text {{item.text}} // Spells @@ -75,7 +75,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") strong {{spell.mana}} |  MP // main content - span(ng-class='{"shop_{{spell.classes}} shop-sprite item-img": true}') + span(ng-class='{"shop_{{spell.key}} shop-sprite item-img": true}') p.task-text {{spell.text}} br From 350e3681d76cb603da93c1ea7c2879e31ae7c14e Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Tue, 3 Dec 2013 17:39:43 -0700 Subject: [PATCH 04/24] classes: grunt-spritesmith fixes --- views/shared/header/avatar.jade | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 8d766628e8..8a7cdc9886 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -18,14 +18,14 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( //-span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') //-span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') - span(class='m_skin_{{profile.preferences.skin}}') - span(class='m_head_0') - span(class='m_hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') - span(class='m_hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') - span(class='m_{{profile.items.gear.current.armor}}', ng-show='profile.preferences.showArmor') - span(class='m_{{profile.items.gear.current.head}}', ng-show='profile.preferences.showHelm') - span(class='m_{{profile.items.gear.current.shield}}', ng-show='profile.preferences.showShield') - span(class='m_{{profile.items.gear.current.weapon}}', ng-show='profile.preferences.showWeapon') + span(class='skin_{{profile.preferences.skin}}') + span(class='head_0') + span(class='hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') + span(class='hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') + span(class='{{profile.items.gear.current.armor}}', ng-show='profile.preferences.showArmor') + span(class='{{profile.items.gear.current.head}}', ng-show='profile.preferences.showHelm') + span(class='{{profile.items.gear.current.shield}}', ng-show='profile.preferences.showShield') + span(class='{{profile.items.gear.current.weapon}}', ng-show='profile.preferences.showWeapon') // Mount Head span(ng-if='profile.items.currentMount', class='Mount_Head_{{profile.items.currentMount}}') From 55d0a0a94df92f9eab74d4d35faa3766dca57ebd Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 4 Dec 2013 15:09:56 -0700 Subject: [PATCH 05/24] classes: fix customizations based on habitrpg-shared#9821a88 --- src/models/user.js | 4 +- views/options/profile.jade | 76 ++++++++++++++++----------------- views/shared/header/avatar.jade | 4 +- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/models/user.js b/src/models/user.js index 7c07306478..d46db203b0 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -195,9 +195,9 @@ var UserSchema = new Schema({ preferences: { armorSet: String, dayStart: {type:Number, 'default': 0}, - gender: {type:String, 'default': 'm'}, + size: {type:String, enum: ['broad','slim'], 'default': 'broad'}, hair: { - color: {type: String, 'default': 'blonde'}, + color: {type: String, 'default': 'blond'}, base: {type: Number, 'default': 0}, bangs: {type: Number, 'default': 0} }, diff --git a/views/options/profile.jade b/views/options/profile.jade index 7bb502e321..1dea74ff85 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -6,13 +6,13 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') 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")') + button.broad_armor_warrior_0.customize-option(type='button', ng-click='set("preferences.size","broad")') + button.slim_armor_warrior_0.customize-option(type='button', ng-click='set("preferences.size","slim")') label.checkbox input(type='checkbox', ng-model='user.preferences.showHelm', ng-change='set("preferences.showHelm", user.preferences.showHelm?true: false)') | Show Helm menu(type='list') - li.customize-menu + //-li.customize-menu menu(label='Clothing') button.f_armor_0_v1.customize-option(ng-show='user.preferences.gender=="f"', type='button', ng-click='set("preferences.armorSet","v1")') button.f_armor_0_v2.customize-option(ng-show='user.preferences.gender=="f"', type='button', ng-click='set("preferences.armorSet","v2")') @@ -45,50 +45,50 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Bangs li.customize-menu menu(label='Bangs') - button(class='{{user.preferences.gender}}_hair_bangs_0_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') - button(class='{{user.preferences.gender}}_hair_bangs_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",1)') - button(class='{{user.preferences.gender}}_hair_bangs_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",2)') - button(class='{{user.preferences.gender}}_hair_bangs_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",3)') + button(class='hair_bangs_0_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') + button(class='hair_bangs_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",1)') + button(class='hair_bangs_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",2)') + button(class='hair_bangs_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",3)') // Base li.customize-menu menu(label='Base') - button(class='{{user.preferences.gender}}_hair_base_0_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",0)') - button(class='{{user.preferences.gender}}_hair_base_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",1)') - button(class='{{user.preferences.gender}}_hair_base_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",2)') - button(class='{{user.preferences.gender}}_hair_base_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",3)') - button(class='{{user.preferences.gender}}_hair_base_4_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",4)') - button(class='{{user.preferences.gender}}_hair_base_5_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",5)') - button(class='{{user.preferences.gender}}_hair_base_6_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",6)') - button(class='{{user.preferences.gender}}_hair_base_7_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",7)') - button(class='{{user.preferences.gender}}_hair_base_8_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",8)') + button(class='hair_base_0_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",0)') + button(class='hair_base_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",1)') + button(class='hair_base_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",2)') + button(class='hair_base_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",3)') + button(class='hair_base_4_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",4)') + button(class='hair_base_5_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",5)') + button(class='hair_base_6_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",6)') + button(class='hair_base_7_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",7)') + button(class='hair_base_8_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",8)') .span4 // skin li.customize-menu 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")') - 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")') + button.customize-option(type='button', class='skin_asian', ng-click='set("preferences.skin","asian")') + button.customize-option(type='button', class='skin_white', ng-click='set("preferences.skin","white")') + button.customize-option(type='button', class='skin_ea8349', ng-click='set("preferences.skin","ea8349")') + button.customize-option(type='button', class='skin_c06534', ng-click='set("preferences.skin","c06534")') + button.customize-option(type='button', class='skin_98461a', ng-click='set("preferences.skin","98461a")') + button.customize-option(type='button', class='skin_black', ng-click='set("preferences.skin","black")') + button.customize-option(type='button', class='skin_dead', ng-click='set("preferences.skin","dead")') + button.customize-option(type='button', class='skin_orc', ng-click='set("preferences.skin","orc")') // Rainbow 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")') - 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.customize-option(type='button', class='skin_eb052b', ng-class='{locked: !user.purchased.skin.eb052b}', ng-click='unlock("skin.eb052b")') + button.customize-option(type='button', class='skin_f69922', ng-class='{locked: !user.purchased.skin.f69922}', ng-click='unlock("skin.f69922")') + button.customize-option(type='button', class='skin_f5d70f', ng-class='{locked: !user.purchased.skin.f5d70f}', ng-click='unlock("skin.f5d70f")') + button.customize-option(type='button', class='skin_0ff591', ng-class='{locked: !user.purchased.skin.0ff591}', ng-click='unlock("skin.0ff591")') + button.customize-option(type='button', class='skin_2b43f6', ng-class='{locked: !user.purchased.skin.2b43f6}', ng-click='unlock("skin.2b43f6")') + button.customize-option(type='button', class='skin_d7a9f7', ng-class='{locked: !user.purchased.skin.d7a9f7}', ng-click='unlock("skin.d7a9f7")') + button.customize-option(type='button', class='skin_800ed0', ng-class='{locked: !user.purchased.skin.800ed0}', ng-click='unlock("skin.800ed0")') + button.customize-option(type='button', class='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 // Special Events @@ -96,12 +96,12 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') div(ng-if='user.purchased.skin.monster || user.purchased.skin.pumpkin || user.purchased.skin.skeleton || user.purchased.skin.zombie || user.purchased.skin.ghost || user.purchased.skin.shadow') h5 Spooky Skins menu - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_monster', ng-if='user.purchased.skin.monster', ng-click='unlock("skin.monster")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_pumpkin', ng-if='user.purchased.skin.pumpkin', ng-click='unlock("skin.pumpkin")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_skeleton', ng-if='user.purchased.skin.skeleton', ng-click='unlock("skin.skeleton")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_zombie', ng-if='user.purchased.skin.zombie', ng-click='unlock("skin.zombie")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_ghost', ng-if='user.purchased.skin.ghost', ng-click='unlock("skin.ghost")') - button.customize-option(type='button', class='{{user.preferences.gender}}_skin_shadow', ng-if='user.purchased.skin.shadow', ng-click='unlock("skin.shadow")') + button.customize-option(type='button', class='skin_monster', ng-if='user.purchased.skin.monster', ng-click='unlock("skin.monster")') + button.customize-option(type='button', class='skin_pumpkin', ng-if='user.purchased.skin.pumpkin', ng-click='unlock("skin.pumpkin")') + button.customize-option(type='button', class='skin_skeleton', ng-if='user.purchased.skin.skeleton', ng-click='unlock("skin.skeleton")') + button.customize-option(type='button', class='skin_zombie', ng-if='user.purchased.skin.zombie', ng-click='unlock("skin.zombie")') + button.customize-option(type='button', class='skin_ghost', ng-if='user.purchased.skin.ghost', ng-click='unlock("skin.ghost")') + button.customize-option(type='button', class='skin_shadow', ng-if='user.purchased.skin.shadow', ng-click='unlock("skin.shadow")') script(id='partials/options.profile.stats.html', type='text/ng-template') .row-fluid diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 8a7cdc9886..e050431114 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -19,10 +19,10 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( //-span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') span(class='skin_{{profile.preferences.skin}}') - span(class='head_0') + span(class='{{profile.preferences.size}}_{{profile.items.gear.current.armor}}', ng-show='profile.preferences.showArmor') + span(class='head_warrior_0') span(class='hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') span(class='hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') - span(class='{{profile.items.gear.current.armor}}', ng-show='profile.preferences.showArmor') span(class='{{profile.items.gear.current.head}}', ng-show='profile.preferences.showHelm') span(class='{{profile.items.gear.current.shield}}', ng-show='profile.preferences.showShield') span(class='{{profile.items.gear.current.weapon}}', ng-show='profile.preferences.showWeapon') From 8803df46c03f9d04f1ef3dd577eeba27a3b196c0 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 4 Dec 2013 16:02:08 -0700 Subject: [PATCH 06/24] classes & grunt-spritesmith: death, paws, gems-cleanup --- views/options/inventory/stable.jade | 6 +++--- views/options/profile.jade | 4 ++-- views/options/social/group.jade | 2 +- views/shared/gems.jade | 2 +- views/shared/header/avatar.jade | 10 ---------- views/shared/modals/death.jade | 2 +- 6 files changed, 8 insertions(+), 18 deletions(-) diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 82f719e6d5..4df4017525 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -30,7 +30,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.mounts.htm button(class="pet-button Mount_Head_{{mount}}", ng-show='user.items.mounts[mount]', ng-class='{active: user.items.currentMount == mount}', ng-click='chooseMount(egg.name, potion.name)') //div(class='Mount_Head_{{mount}}') button(class="pet-button pet-not-owned", ng-hide='user.items.mounts[mount]') - img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') + .PixelPaw h4 Rare Mounts menu @@ -60,7 +60,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' //-.progress(ng-class='{"progress-success": user.items.pets[pet]<50}') .bar(style="width: {{user.items.pets[pet]/.5}}%;") button(class="pet-button pet-not-owned", ng-if='!user.items.pets[pet]') - img(src='/bower_components/habitrpg-shared/img/PixelPaw.png') + .PixelPaw h4 Rare Pets menu @@ -71,7 +71,7 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' button(ng-if='user.items.pets["Turkey-Base"]', class="pet-button Pet-Turkey-Base", ng-class='{active: user.items.currentPet == "Turkey-Base"}', ng-click='choosePet("Turkey", "Base")', popover='Turkey', popover-trigger='mouseenter', popover-placement='bottom') a(target='_blank', href='http://habitrpg.wikia.com/wiki/Contributing_to_HabitRPG') button(ng-if='!user.items.pets["Dragon-Hydra"]', class="pet-button pet-not-owned", popover-trigger='mouseenter', popover-placement='right', popover="Click the gold paw to learn more about how you can obtain this rare pet through contributing to HabitRPG!", popover-title='How to Get this Pet!') - img(src='/bower_components/habitrpg-shared/img/PixelPaw-Gold.png') + .PixelPaw-Gold //-.well.food-tray p(ng-show='foodCount < 1') You don't have any food yet. diff --git a/views/options/profile.jade b/views/options/profile.jade index 1dea74ff85..b9c8749c37 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -45,7 +45,7 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Bangs li.customize-menu menu(label='Bangs') - button(class='hair_bangs_0_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') + button(class='head_warrior_0 customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') button(class='hair_bangs_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",1)') button(class='hair_bangs_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",2)') button(class='hair_bangs_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",3)') @@ -53,7 +53,7 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Base li.customize-menu menu(label='Base') - button(class='hair_base_0_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",0)') + button(class='head_warrior_0 customize-option', type='button', ng-click='set("preferences.hair.base",0)') button(class='hair_base_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",1)') button(class='hair_base_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",2)') button(class='hair_base_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",3)') diff --git a/views/options/social/group.jade b/views/options/social/group.jade index 9371e3567d..17ef4cbde3 100644 --- a/views/options/social/group.jade +++ b/views/options/social/group.jade @@ -1,7 +1,7 @@ a.pull-right.gem-wallet(popover-trigger='mouseenter', popover-title='Guild Bank', popover='Gems which your guild leader can use for challenge prizes.', popover-placement='left', popover-html='true') // + span.task-action-btn.tile.flush.neutral - .Gems + .Pet_Currency_Gem2x.Gems | {{group.balance * 4 | number:0 }} Guild Gems .row-fluid .span4 diff --git a/views/shared/gems.jade b/views/shared/gems.jade index 09c9c50dbf..7dc26b0463 100644 --- a/views/shared/gems.jade +++ b/views/shared/gems.jade @@ -1,5 +1,5 @@ a.pull-right.gem-wallet(ng-click='modals.buyGems = true', popover-trigger='mouseenter', popover-title='Gems', popover="Used for buying special items (reroll, eggs, hatching potions, etc). You'll need to unlock those features before being able to use Gems.", popover-placement='bottom') span.task-action-btn.tile.flush.bright.add-gems-btn + span.task-action-btn.tile.flush.neutral - .Gems + .Pet_Currency_Gem2x.Gems | {{user.balance * 4 | number:0}} Gems \ No newline at end of file diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index e050431114..e7cc90271b 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -8,16 +8,6 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( // Mount Body span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}') - //- Avatar - //-span(class='{{profile.preferences.gender}}_skin_{{profile.preferences.skin}}') - //-span(class='{{profile.preferences.gender}}_head_0') - //-span(class='{{profile.preferences.gender}}_hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') - //-span(class='{{profile.preferences.gender}}_hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') - //-span(class='{{equipped("armor", profile.items.armor, profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') - //-span(class='{{equipped("head", profile.items.head, profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}', ng-show='profile.preferences.showHelm') - //-span(class='{{equipped("shield",profile.items.shield,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') - //-span(class='{{equipped("weapon",profile.items.weapon,profile.preferences, profile.backer, profile.contributor)}}-{{profile.stats.class}}') - span(class='skin_{{profile.preferences.skin}}') span(class='{{profile.preferences.size}}_{{profile.items.gear.current.armor}}', ng-show='profile.preferences.showArmor') span(class='head_warrior_0') diff --git a/views/shared/modals/death.jade b/views/shared/modals/death.jade index 3384ccbfe9..7069de2135 100644 --- a/views/shared/modals/death.jade +++ b/views/shared/modals/death.jade @@ -3,7 +3,7 @@ div(modal='user.stats.hp <= 0', options='{backdrop:true, keyboard:false, backdro .row-fluid .span4 figure.notification-character - img(src='/bower_components/habitrpg-shared/img/sprites/dead.png') + .GrimReaper .span8 h2 You Died! .row-fluid From 88c64a6f80000aa76d5146a61b08cb9d34fcaa3a Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 4 Dec 2013 16:52:06 -0700 Subject: [PATCH 07/24] classes & grunt-spritesmith: NPCs habitrpg-shared#85164c9 --- public/css/npcs.styl | 47 +++++++++++--------------- public/js/services/guideServices.js | 4 +-- views/options/inventory/inventory.jade | 4 +-- views/options/inventory/stable.jade | 42 +++++++++++++---------- views/options/social/tavern.jade | 2 +- views/shared/header/header.jade | 2 +- views/shared/modals/achievements.jade | 2 +- views/shared/modals/buy-gems.jade | 2 +- views/shared/modals/new-stuff.jade | 2 +- 9 files changed, 52 insertions(+), 55 deletions(-) diff --git a/public/css/npcs.styl b/public/css/npcs.styl index 2c2370808c..f7127f5f72 100644 --- a/public/css/npcs.styl +++ b/public/css/npcs.styl @@ -1,36 +1,27 @@ -.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_container + margin-bottom: 20px -.NPC-Alex {background-position: 0 0; width: 162px; height: 138px;} -.NPC-Alex-container{margin-bottom: 20px;} -.NPC-Daniel {background-position: -222px 0; width: 135px; height: 123px} -.NPC-Justin {background-position: -357px 0; width: 84px; height: 119px} -.NPC-Justin-Head {background-position: -396px 0; width: 36px; height: 96px} -.NPC-Matt {background-position: -441px 0; width: 100%; padding-left: 208px; padding-bottom: 20px;} +.npc_matt + margin-bottom: 20px -// Bailey -.NPC-Bailey - background-position: -162px -42px - width: 60px - height: 72px - float:left -.NPC-Bailey-Head - background-position: -162px -42px - width: 60px - height: 30px - position: absolute - top: 117px // 147 (header-height) - 30 (bailey height) - right: 50px - cursor: pointer - - -.static-popover - z-index 0 - display block - position:relative +.npc_bailey + float:left +.npc_bailey_head + height: 30px !important + position: absolute + top: 117px // 147 (header-height) - 30 (bailey height) + right: 50px + cursor: pointer // Tour (Justin) -.NPC-Justin.float-left +.npc_justin.float-left float: left margin-right: 5px margin-bottom: 5px + +.static-popover + z-index 0 + display block + position:relative + .popover-navigation {clear:both;} \ No newline at end of file diff --git a/public/js/services/guideServices.js b/public/js/services/guideServices.js index ebb9cadb36..e51dd44d06 100644 --- a/public/js/services/guideServices.js +++ b/public/js/services/guideServices.js @@ -52,7 +52,7 @@ angular.module('guideServices', []). } ]; _.each(tourSteps, function(step){ - step.content = "
" + step.content + "
"; // add Justin NPC img + step.content = "
" + step.content + "
"; // add Justin NPC img }); $('.main-herobox').popover('destroy'); var tour = new Tour({ @@ -75,7 +75,7 @@ angular.module('guideServices', []). if (!placement) placement = 'bottom'; $(selector).popover('destroy'); var button = ""; - html = "
" + html + '
' + button + '
'; + html = "
" + html + '
' + button + '
'; $(selector).popover({ title: title, placement: placement, diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index 90a57f379c..8547ddfdef 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -38,10 +38,10 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') .span6 h2 Market .row-fluid - table.NPC-Alex-container + table.npc_alex_container tr td - .NPC-Alex.pull-left + .npc_alex.pull-left td .popover.static-popover.fade.right.in .arrow diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 4df4017525..939c86cad4 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -14,15 +14,18 @@ script(type='text/ng-template', id='partials/options.inventory.stable.html') script(type='text/ng-template', id='partials/options.inventory.stable.mounts.html') .stable - .NPC-Matt - .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') - .arrow - h3.popover-title - a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch - .popover-content - p. - Shall I bring you your steed, {{user.profile.name}}? Click a mount to saddle up. - h4 {{mountCount}} / {{totalPets}} Mounts Tamed + table(style='width:100%') + tr + td.npc_matt + td + .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') + .arrow + h3.popover-title + a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch + .popover-content + p. + Shall I bring you your steed, {{user.profile.name}}? Click a mount to saddle up. + h4 {{mountCount}} / {{totalPets}} Mounts Tamed menu.pets(type='list') li.customize-menu(ng-repeat='egg in Items.eggs') menu @@ -42,15 +45,18 @@ script(type='text/ng-template', id='partials/options.inventory.stable.mounts.htm script(type='text/ng-template', id='partials/options.inventory.stable.pets.html') .stable - .NPC-Matt - .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') - .arrow - h3.popover-title - a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch - .popover-content - p. - Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to venture at your side. Have a look-see at all the pets you can collect. - h4 {{petCount}} / {{totalPets}} Pets Found + table(style='width:100%') + tr + td.npc_matt + td + .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') + .arrow + h3.popover-title + a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch + .popover-content + p. + Welcome to the Stable! I'm Matt, the beast master. Choose a pet here to venture at your side. Have a look-see at all the pets you can collect. + h4 {{petCount}} / {{totalPets}} Pets Found menu.pets(type='list') li.customize-menu(ng-repeat='egg in Items.eggs') diff --git a/views/options/social/tavern.jade b/views/options/social/tavern.jade index 46a773f8f4..b3bc2657d9 100644 --- a/views/options/social/tavern.jade +++ b/views/options/social/tavern.jade @@ -4,7 +4,7 @@ table tr td - .NPC-Daniel + .npc_daniel td .popover.static-popover.fade.right.in .arrow diff --git a/views/shared/header/header.jade b/views/shared/header/header.jade index 4ff786fa96..051c71d8db 100644 --- a/views/shared/header/header.jade +++ b/views/shared/header/header.jade @@ -35,5 +35,5 @@ .herobox-wrap(ng-repeat='profile in partyMinusSelf') include avatar - .NPC-Bailey-Head(ng-show='user.flags.newStuff', tooltip='Psst', tooltip-placement='top', ng-click='modals.newStuff=true') + .npc_bailey.npc_bailey_head(ng-show='user.flags.newStuff', tooltip='Psst', tooltip-placement='top', ng-click='modals.newStuff=true') diff --git a/views/shared/modals/achievements.jade b/views/shared/modals/achievements.jade index fd05296c54..c599d910e1 100644 --- a/views/shared/modals/achievements.jade +++ b/views/shared/modals/achievements.jade @@ -35,7 +35,7 @@ div(modal='user.flags.contributor') .modal-header h3 Contributor Achievement! .modal-body - .NPC-Justin.float-left + .npc_justin.float-left p. {{user.profile.name}}, you awesome person! You're now a level {{user.contributor.level}} contributor for helping HabitRPG. See what prizes you've earned for your contribution! diff --git a/views/shared/modals/buy-gems.jade b/views/shared/modals/buy-gems.jade index e041f2d0ae..61688ef33c 100644 --- a/views/shared/modals/buy-gems.jade +++ b/views/shared/modals/buy-gems.jade @@ -7,7 +7,7 @@ div(modal='modals.buyGems') table tr td - .NPC-Justin + .npc_justin td .popover.static-popover.fade.right.in.wide-popover .arrow diff --git a/views/shared/modals/new-stuff.jade b/views/shared/modals/new-stuff.jade index a24c8049c8..e7bd9bde38 100644 --- a/views/shared/modals/new-stuff.jade +++ b/views/shared/modals/new-stuff.jade @@ -5,7 +5,7 @@ div(modal='modals.newStuff') table tr td - .NPC-Bailey + .npc_bailey td .popover.static-popover.fade.right.in.wide-popover .arrow From decaa2867becc7a365c8118d6897b9dbe87aab6f Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 4 Dec 2013 17:08:55 -0700 Subject: [PATCH 08/24] classes: misc fixes. start a running migration file (add to, or add notes as we go along) --- migrations/20131204_classes.js | 22 +++++++++++++++ views/shared/modals/classes.jade | 48 +++++++++++++++++++++----------- 2 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 migrations/20131204_classes.js diff --git a/migrations/20131204_classes.js b/migrations/20131204_classes.js new file mode 100644 index 0000000000..4527b4b562 --- /dev/null +++ b/migrations/20131204_classes.js @@ -0,0 +1,22 @@ +/** + * Probably the biggest migration of all! This adds the following features: + * - Customization Redo: https://trello.com/c/YKXmHNjY/306-customization-redo + * - Armory: https://trello.com/c/83M5RqQB/299-armory + * - Classes + */ + +db.users.find().forEach(function(user){ + + // grant backer/contrib gear, rather than using js logic + + // migrate current owned items + + // gender => size + user.preferences.size = (user.preferences.gender == 'f') ? 'slim' : 'broad'; + delete user.preferences.gender; + + // Delete armorSet + delete user.preferences.armorSet; + + db.users.update({_id:user._id}, user); +}); \ No newline at end of file diff --git a/views/shared/modals/classes.jade b/views/shared/modals/classes.jade index 985352462b..737c8f1d74 100644 --- a/views/shared/modals/classes.jade +++ b/views/shared/modals/classes.jade @@ -12,34 +12,50 @@ h5 Warrior figure.herobox(ng-class='{"selected-class": selectedClass=="warrior"}') .character-sprites - span(class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}') - span(class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}') - span(class='{{user.preferences.gender}}_armor_5-warrior') - span(class='{{user.preferences.gender}}_head_5-warrior') + span(class='skin_{{user.preferences.skin}}') + span(class='{{user.preferences.size}}_armor_warrior_5') + span(class='head_warrior_0') + span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') + span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') + span(class='head_warrior_5') + span(class='shield_warrior_5') + span(class='weapon_warrior_6') .span3(ng-click='selectedClass = "wizard"') h5 Wizard figure.herobox(ng-class='{"selected-class": selectedClass=="wizard"}') .character-sprites - span(class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}') - span(class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}') - span(class='{{user.preferences.gender}}_armor_5-wizard') - span(class='{{user.preferences.gender}}_head_5-wizard') + span(class='skin_{{user.preferences.skin}}') + span(class='{{user.preferences.size}}_armor_wizard_5') + span(class='head_warrior_0') + span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') + span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') + span(class='head_wizard_5') + span(class='shield_wizard_5') + span(class='weapon_wizard_6') .span3(ng-click='selectedClass = "rogue"') h5 Rogue figure.herobox(ng-class='{"selected-class": selectedClass=="rogue"}') .character-sprites - span(class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}') - span(class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}') - span(class='{{user.preferences.gender}}_armor_5-rogue') - span(class='{{user.preferences.gender}}_head_5-rogue') + span(class='skin_{{user.preferences.skin}}') + span(class='{{user.preferences.size}}_armor_rogue_5') + span(class='head_warrior_0') + span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') + span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') + span(class='head_rogue_5') + span(class='shield_rogue_5') + span(class='weapon_rogue_6') .span3(ng-click='selectedClass = "healer"') h5 Healer figure.herobox(ng-class='{"selected-class": selectedClass=="healer"}') .character-sprites - span(class='{{user.preferences.gender}}_skin_{{user.preferences.skin}}') - span(class='{{user.preferences.gender}}_hair_{{user.preferences.hair}}') - span(class='{{user.preferences.gender}}_armor_5-healer') - span(class='{{user.preferences.gender}}_head_5-healer') + span(class='skin_{{user.preferences.skin}}') + span(class='{{user.preferences.size}}_armor_healer_5') + span(class='head_warrior_0') + span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') + span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') + span(class='head_healer_5') + span(class='shield_healer_5') + span(class='weapon_healer_6') .modal-footer button.btn.btn-default.cancel(ng-click='set("stats.class", selectedClass)') Select \ No newline at end of file From 5fea978e6b6b74a80ae37f29bce13b4a5a67f7bc Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 4 Dec 2013 22:50:20 -0700 Subject: [PATCH 09/24] costumes: add costume support in inventory --- public/js/controllers/inventoryCtrl.js | 5 +++++ src/models/user.js | 13 ++++++++++--- views/options/inventory/inventory.jade | 12 ++++++++++-- views/shared/header/avatar.jade | 19 +++++++++++++++---- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index 28deb61463..99fc90164a 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -162,5 +162,10 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', User.set('items.currentMount', (user.items.currentMount == mount) ? '' : mount); } + $scope.equip = function(user, item, costume) { + var equipTo = costume ? 'costume' : 'equipped'; + User.set('items.gear.' + equipTo + '.' + item.type, item.key); + } + } ]); \ No newline at end of file diff --git a/src/models/user.js b/src/models/user.js index d46db203b0..5da8e612d9 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -114,12 +114,18 @@ var UserSchema = new Schema({ m[v.key]['default'] = true; }), - current: { + equipped: { weapon: {type: String, 'default': 'weapon_warrior_0'}, armor: {type: String, 'default': 'armor_warrior_0'}, head: {type: String, 'default': 'head_warrior_0'}, shield: {type: String, 'default': 'shield_warrior_0'} - } + }, + costume: { + weapon: {type: String, 'default': 'weapon_warrior_0'}, + armor: {type: String, 'default': 'armor_warrior_0'}, + head: {type: String, 'default': 'head_warrior_0'}, + shield: {type: String, 'default': 'shield_warrior_0'} + }, }, // -------------- Animals ------------------- @@ -209,7 +215,8 @@ var UserSchema = new Schema({ skin: {type:String, 'default':'white'}, timezoneOffset: Number, language: String, - automaticAllocation: Boolean + automaticAllocation: Boolean, + useCostume: Boolean }, profile: { blurb: String, diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index 8547ddfdef..52989257fb 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -7,8 +7,16 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') li.customize-menu menu.pets-menu(label='Gear') - div(ng-repeat='(k,v) in user.items.gear.owned') - button.customize-option(popover='{{Items.gear.flat[k].notes}}', popover-title='{{Items.gear.flat[k].text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(v)', class='shop_{{v.key}}') + div(ng-repeat='(k,v) in user.items.gear.owned', ng-init='item = Items.gear.flat[k]') + button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(user,item)', class='shop_{{item.key}}') + label.checkbox.inline + input(type="checkbox", ng-model="user.preferences.costume") + | Use Custume  + i.icon-question-sign(popover="Show something different on your avatar than the gear you have equipped for battle", popover-trigger='mouseenter', popover-placement='right') + li.customize-menu(ng-if='user.preferences.costume') + menu.pets-menu(label='Gear') + div(ng-repeat='(k,v) in user.items.gear.owned', ng-init='item = Items.gear.flat[k]') + button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(user,item,true)', class='shop_{{item.key}}') li.customize-menu menu.pets-menu(label='Eggs ({{eggCount}})') diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index e7cc90271b..204dd82ed1 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -8,14 +8,25 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( // Mount Body span(ng-if='profile.items.currentMount', class='Mount_Body_{{profile.items.currentMount}}') + // Avatar span(class='skin_{{profile.preferences.skin}}') - span(class='{{profile.preferences.size}}_{{profile.items.gear.current.armor}}', ng-show='profile.preferences.showArmor') + + span(class='{{profile.preferences.size}}_{{profile.items.gear.equipped.armor}}', ng-if='!profile.preferences.costume') + span(class='{{profile.preferences.size}}_{{profile.items.gear.costume.armor}}', ng-if='profile.preferences.costume') + span(class='head_warrior_0') span(class='hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') span(class='hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') - span(class='{{profile.items.gear.current.head}}', ng-show='profile.preferences.showHelm') - span(class='{{profile.items.gear.current.shield}}', ng-show='profile.preferences.showShield') - span(class='{{profile.items.gear.current.weapon}}', ng-show='profile.preferences.showWeapon') + + span(class='{{profile.items.gear.equipped.head}}', ng-if='!profile.preferences.costume') + span(class='{{profile.items.gear.costume.head}}', ng-if='profile.preferences.costume') + + span(class='{{profile.items.gear.equipped.shield}}', ng-if='!profile.preferences.costume') + span(class='{{profile.items.gear.costume.shield}}', ng-if='profile.preferences.costume') + + span(class='{{profile.items.gear.equipped.weapon}}', ng-if='!profile.preferences.costume') + span(class='{{profile.items.gear.costume.weapon}}', ng-if='profile.preferences.costume') + // Mount Head span(ng-if='profile.items.currentMount', class='Mount_Head_{{profile.items.currentMount}}') From 62d50a1f4da47ef143e026454df96f444b404eb8 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 4 Dec 2013 23:10:14 -0700 Subject: [PATCH 10/24] classes: fixes to buying items --- public/js/controllers/tasksCtrl.js | 2 +- src/controllers/user.js | 4 ++-- src/routes/api.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/public/js/controllers/tasksCtrl.js b/public/js/controllers/tasksCtrl.js index 399899d911..cd8a10e1cf 100644 --- a/public/js/controllers/tasksCtrl.js +++ b/public/js/controllers/tasksCtrl.js @@ -116,7 +116,7 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', ' $scope.buy = function(type) { var hasEnough = window.habitrpgShared.items.buyItem(User.user, type); if (hasEnough) { - User.log({op: "buy",type: type}); + User.log({op: "buy", type: type}); Notification.text("Item purchased."); updateStore(); } else { diff --git a/src/controllers/user.js b/src/controllers/user.js index b453d2c914..aefa137942 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -204,8 +204,8 @@ api.clearCompleted = function(req, res, next) { */ api.buy = function(req, res, next) { var user = res.locals.user; - var item = req.params.item; - if (item !== 'potion' && !items.items.gear.flat[item]) { + var type = req.params.type; + if (!type.match(/potion|weapon|armor|head|shield/)) { // if (item !== 'potion' && !items.items.gear.flat[item]) return res.json(400, {err: ":item must be a supported key, see https://github.com/HabitRPG/habitrpg-shared/blob/master/script/items.coffee"}); } var hasEnough = items.buyItem(user, type); diff --git a/src/routes/api.js b/src/routes/api.js index 209a183313..34c3c3327d 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -48,7 +48,7 @@ if (nconf.get('NODE_ENV') == 'development') { } /* Items*/ -router.post('/user/buy/:item', auth.auth, cron, user.buy); +router.post('/user/buy/:type', auth.auth, cron, user.buy); /* User*/ router.get('/user', auth.auth, cron, user.getUser); From dde0655900dd2493fd6b194160fb73122d9340ad Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Wed, 4 Dec 2013 23:53:55 -0700 Subject: [PATCH 11/24] classes: fixes to class-selection & reroll, remove show/hide gear since we're using costumes --- public/js/controllers/userCtrl.js | 3 +-- src/models/user.js | 14 ++++++-------- views/options/profile.jade | 21 --------------------- views/shared/modals/classes.jade | 4 ++-- views/shared/tasks/lists.jade | 4 ++-- 5 files changed, 11 insertions(+), 35 deletions(-) diff --git a/public/js/controllers/userCtrl.js b/public/js/controllers/userCtrl.js index c9336e8525..20d946dde8 100644 --- a/public/js/controllers/userCtrl.js +++ b/public/js/controllers/userCtrl.js @@ -22,14 +22,13 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$ if (!confirm("Are you sure you want to re-roll? This will reset your character's class and allocated points (you'll get them all back to re-allocate)")) return; User.setMultiple({ - 'stats.class': '', + 'flags.classSelected': false, //'stats.points': this is handled on the server 'stats.str': 0, 'stats.def': 0, 'stats.per': 0, 'stats.int': 0 }) - } $scope.save = function(){ diff --git a/src/models/user.js b/src/models/user.js index 5da8e612d9..3d56176fbf 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -94,7 +94,8 @@ var UserSchema = new Schema({ rewrite: {type: Boolean, 'default': true}, partyEnabled: Boolean, // FIXME do we need this? rest: {type: Boolean, 'default': false}, // fixme - change to preferences.resting once we're off derby - contributor: Boolean + contributor: Boolean, + classSelected: {type: Boolean, 'default': false} }, history: { exp: Array, // [{date: Date, value: Number}], // big peformance issues if these are defined @@ -205,13 +206,11 @@ var UserSchema = new Schema({ hair: { color: {type: String, 'default': 'blond'}, base: {type: Number, 'default': 0}, - bangs: {type: Number, 'default': 0} + bangs: {type: Number, 'default': 0}, + beard: {type: Number, 'default': 0}, + mustach: {type: Number, 'default': 0}, }, hideHeader: {type:Boolean, 'default':false}, - showHelm: {type:Boolean, 'default':true}, - showWeapon: {type:Boolean, 'default':true}, - showShield: {type:Boolean, 'default':true}, - showArmor: {type:Boolean, 'default':true}, skin: {type:String, 'default':'white'}, timezoneOffset: Number, language: String, @@ -231,8 +230,7 @@ var UserSchema = new Schema({ lvl: Number, // Class System -// 'class': {type: String, enum: ['warrior','rogue','wizard','rogue'], 'default': 'warrior'}, - 'class': {type: String, 'default': 'warrior'}, + 'class': {type: String, enum: ['warrior','rogue','wizard','rogue'], 'default': 'warrior'}, points: {type: Number, 'default': 0}, str: {type: Number, 'default': 0}, def: {type: Number, 'default': 0}, diff --git a/views/options/profile.jade b/views/options/profile.jade index b9c8749c37..0e05f1690f 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -8,27 +8,6 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') menu button.broad_armor_warrior_0.customize-option(type='button', ng-click='set("preferences.size","broad")') button.slim_armor_warrior_0.customize-option(type='button', ng-click='set("preferences.size","slim")') - label.checkbox - input(type='checkbox', ng-model='user.preferences.showHelm', ng-change='set("preferences.showHelm", user.preferences.showHelm?true: false)') - | Show Helm - menu(type='list') - //-li.customize-menu - menu(label='Clothing') - button.f_armor_0_v1.customize-option(ng-show='user.preferences.gender=="f"', type='button', ng-click='set("preferences.armorSet","v1")') - button.f_armor_0_v2.customize-option(ng-show='user.preferences.gender=="f"', type='button', ng-click='set("preferences.armorSet","v2")') - label.checkbox - input(type='checkbox', ng-model='user.preferences.showArmor', ng-change='set("preferences.showArmor", user.preferences.showArmor?true: false)') - | Show Armor - menu(type='list') - li.customize-menu - menu(label='Other') - label.checkbox - input(type='checkbox', ng-model='user.preferences.showWeapon', ng-change='set("preferences.showWeapon", user.preferences.showWeapon?true: false)') - | Show Weapon - label.checkbox - input(type='checkbox', ng-model='user.preferences.showShield', ng-change='set("preferences.showShield", user.preferences.showShield?true: false)') - | Show Shield - .span4 h3 Hair diff --git a/views/shared/modals/classes.jade b/views/shared/modals/classes.jade index 737c8f1d74..9073172be8 100644 --- a/views/shared/modals/classes.jade +++ b/views/shared/modals/classes.jade @@ -1,4 +1,4 @@ -.modal(ng-if='user.stats.lvl >= 10 && !user.stats.class', data-backdrop=true) +.modal(ng-if='!user.flags.classSelected && user.stats.lvl >= 5', data-backdrop=true) .modal-header h3 Class System Unlocked! .modal-body @@ -58,4 +58,4 @@ span(class='weapon_healer_6') .modal-footer - button.btn.btn-default.cancel(ng-click='set("stats.class", selectedClass)') Select \ No newline at end of file + button.btn.btn-default.cancel(ng-click='User.setMultiple({"stats.class":selectedClass,"flags.classSelected":true});') Select \ No newline at end of file diff --git a/views/shared/tasks/lists.jade b/views/shared/tasks/lists.jade index 4fb533d22f..796df6579f 100644 --- a/views/shared/tasks/lists.jade +++ b/views/shared/tasks/lists.jade @@ -46,7 +46,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") // Static Rewards ul.items.rewards(bo-if='main && list.type=="reward" && user.flags.itemsEnabled') - li.task.reward-item(ng-hide='item.hide', ng-repeat='item in itemStore') + li.task.reward-item(ng-if='!item.hide', ng-repeat='item in itemStore') // right-hand side control buttons .task-meta-controls span.task-notes(popover-trigger='mouseenter', popover-placement='left', popover='{{item.notes}}', popover-title='{{item.text}}') @@ -64,7 +64,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") // Spells ul.items(ng-if='main && list.type=="reward" && user.stats.class') - li.task.reward-item(ng-repeat='(k,spell) in Items.spells[user.stats.class]') + li.task.reward-item(ng-repeat='(k,spell) in Items.spells[user.stats.class]', ng-show='user.stats.lvl >= spell.lvl') .task-meta-controls span.task-notes(popover-trigger='mouseenter', popover-placement='left', popover='{{spell.notes}}', popover-title='{{spell.text}}') i.icon-comment From 2563ec576303c4e205284d2b667c9300c63552de Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 5 Dec 2013 03:31:02 -0700 Subject: [PATCH 12/24] classes: beards & mustaches! --- views/options/inventory/inventory.jade | 2 +- views/options/profile.jade | 15 +++++++++++++++ views/shared/header/avatar.jade | 4 ++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index 52989257fb..a8446e551a 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -11,7 +11,7 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(user,item)', class='shop_{{item.key}}') label.checkbox.inline input(type="checkbox", ng-model="user.preferences.costume") - | Use Custume  + | Use Costume  i.icon-question-sign(popover="Show something different on your avatar than the gear you have equipped for battle", popover-trigger='mouseenter', popover-placement='right') li.customize-menu(ng-if='user.preferences.costume') menu.pets-menu(label='Gear') diff --git a/views/options/profile.jade b/views/options/profile.jade index 0e05f1690f..69812fcb77 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -29,6 +29,21 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') button(class='hair_bangs_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",2)') button(class='hair_bangs_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",3)') + // Beard + li.customize-menu + menu(label='Beard') + button(class='head_warrior_0 customize-option', type='button', ng-click='set("preferences.hair.beard",0)') + button(class='hair_beard_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",1)') + button(class='hair_beard_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",2)') + button(class='hair_beard_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",3)') + + // Mustache + li.customize-menu + menu(label='Mustache') + button(class='head_warrior_0 customize-option', type='button', ng-click='set("preferences.hair.mustache",0)') + button(class='hair_mustache_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.mustache",1)') + button(class='hair_mustache_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.mustache",2)') + // Base li.customize-menu menu(label='Base') diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 204dd82ed1..77495879da 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -18,9 +18,13 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( span(class='hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') span(class='hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') + span(class='{{profile.items.gear.equipped.head}}', ng-if='!profile.preferences.costume') span(class='{{profile.items.gear.costume.head}}', ng-if='profile.preferences.costume') + span(class='hair_beard_{{profile.preferences.hair.beard}}_{{profile.preferences.hair.color}}') + span(class='hair_mustache_{{profile.preferences.hair.mustache}}_{{profile.preferences.hair.color}}') + span(class='{{profile.items.gear.equipped.shield}}', ng-if='!profile.preferences.costume') span(class='{{profile.items.gear.costume.shield}}', ng-if='profile.preferences.costume') From 80e97a71ed18e525ba79f39aadca053a8f5d9469 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 5 Dec 2013 09:52:41 -0700 Subject: [PATCH 13/24] classes: misc fixes --- views/shared/header/avatar.jade | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 77495879da..51d26eb294 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -18,12 +18,12 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( span(class='hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') span(class='hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') + span(class='hair_beard_{{profile.preferences.hair.beard}}_{{profile.preferences.hair.color}}') + span(class='hair_mustache_{{profile.preferences.hair.mustache}}_{{profile.preferences.hair.color}}') span(class='{{profile.items.gear.equipped.head}}', ng-if='!profile.preferences.costume') span(class='{{profile.items.gear.costume.head}}', ng-if='profile.preferences.costume') - span(class='hair_beard_{{profile.preferences.hair.beard}}_{{profile.preferences.hair.color}}') - span(class='hair_mustache_{{profile.preferences.hair.mustache}}_{{profile.preferences.hair.color}}') span(class='{{profile.items.gear.equipped.shield}}', ng-if='!profile.preferences.costume') span(class='{{profile.items.gear.costume.shield}}', ng-if='profile.preferences.costume') From 5fd378ebedf6e67446a9b7c7d9e9112893fcd46f Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 5 Dec 2013 11:05:36 -0700 Subject: [PATCH 14/24] classes: fixes to beard / chin overlap --- views/options/profile.jade | 8 ++++---- views/shared/header/avatar.jade | 2 +- views/shared/modals/classes.jade | 16 ++++++++++++---- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/views/options/profile.jade b/views/options/profile.jade index 69812fcb77..6a5ad5b896 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -24,7 +24,7 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Bangs li.customize-menu menu(label='Bangs') - button(class='head_warrior_0 customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') + button(class='head_0 customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') button(class='hair_bangs_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",1)') button(class='hair_bangs_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",2)') button(class='hair_bangs_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",3)') @@ -32,7 +32,7 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Beard li.customize-menu menu(label='Beard') - button(class='head_warrior_0 customize-option', type='button', ng-click='set("preferences.hair.beard",0)') + button(class='head_0 customize-option', type='button', ng-click='set("preferences.hair.beard",0)') button(class='hair_beard_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",1)') button(class='hair_beard_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",2)') button(class='hair_beard_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",3)') @@ -40,14 +40,14 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Mustache li.customize-menu menu(label='Mustache') - button(class='head_warrior_0 customize-option', type='button', ng-click='set("preferences.hair.mustache",0)') + button(class='head_0 customize-option', type='button', ng-click='set("preferences.hair.mustache",0)') button(class='hair_mustache_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.mustache",1)') button(class='hair_mustache_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.mustache",2)') // Base li.customize-menu menu(label='Base') - button(class='head_warrior_0 customize-option', type='button', ng-click='set("preferences.hair.base",0)') + button(class='head_0 customize-option', type='button', ng-click='set("preferences.hair.base",0)') button(class='hair_base_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",1)') button(class='hair_base_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",2)') button(class='hair_base_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",3)') diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 51d26eb294..6b26a5b5b6 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -14,7 +14,7 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( span(class='{{profile.preferences.size}}_{{profile.items.gear.equipped.armor}}', ng-if='!profile.preferences.costume') span(class='{{profile.preferences.size}}_{{profile.items.gear.costume.armor}}', ng-if='profile.preferences.costume') - span(class='head_warrior_0') + span(class='head_0') span(class='hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') span(class='hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') diff --git a/views/shared/modals/classes.jade b/views/shared/modals/classes.jade index 9073172be8..6c789ce576 100644 --- a/views/shared/modals/classes.jade +++ b/views/shared/modals/classes.jade @@ -14,9 +14,11 @@ .character-sprites span(class='skin_{{user.preferences.skin}}') span(class='{{user.preferences.size}}_armor_warrior_5') - span(class='head_warrior_0') + span(class='head_0') span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') + span(class='hair_beard_{{user.preferences.hair.beard}}_{{user.preferences.hair.color}}') + span(class='hair_mustache_{{user.preferences.hair.mustache}}_{{user.preferences.hair.color}}') span(class='head_warrior_5') span(class='shield_warrior_5') span(class='weapon_warrior_6') @@ -26,9 +28,11 @@ .character-sprites span(class='skin_{{user.preferences.skin}}') span(class='{{user.preferences.size}}_armor_wizard_5') - span(class='head_warrior_0') + span(class='head_0') span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') + span(class='hair_beard_{{user.preferences.hair.beard}}_{{user.preferences.hair.color}}') + span(class='hair_mustache_{{user.preferences.hair.mustache}}_{{user.preferences.hair.color}}') span(class='head_wizard_5') span(class='shield_wizard_5') span(class='weapon_wizard_6') @@ -38,9 +42,11 @@ .character-sprites span(class='skin_{{user.preferences.skin}}') span(class='{{user.preferences.size}}_armor_rogue_5') - span(class='head_warrior_0') + span(class='head_0') span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') + span(class='hair_beard_{{user.preferences.hair.beard}}_{{user.preferences.hair.color}}') + span(class='hair_mustache_{{user.preferences.hair.mustache}}_{{user.preferences.hair.color}}') span(class='head_rogue_5') span(class='shield_rogue_5') span(class='weapon_rogue_6') @@ -50,9 +56,11 @@ .character-sprites span(class='skin_{{user.preferences.skin}}') span(class='{{user.preferences.size}}_armor_healer_5') - span(class='head_warrior_0') + span(class='head_0') span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') + span(class='hair_beard_{{user.preferences.hair.beard}}_{{user.preferences.hair.color}}') + span(class='hair_mustache_{{user.preferences.hair.mustache}}_{{user.preferences.hair.color}}') span(class='head_healer_5') span(class='shield_healer_5') span(class='weapon_healer_6') From ad0c953d0a5af13d39a967f30a143f68f15e6e24 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 5 Dec 2013 11:05:47 -0700 Subject: [PATCH 15/24] classes: misc spell-casting fixes, support party spells --- public/js/controllers/rootCtrl.js | 9 +++++---- src/controllers/user.js | 11 +++++++---- src/models/user.js | 10 +++++----- views/shared/header/header.jade | 2 +- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/public/js/controllers/rootCtrl.js b/public/js/controllers/rootCtrl.js index fdbacd9ceb..17525266ab 100644 --- a/public/js/controllers/rootCtrl.js +++ b/public/js/controllers/rootCtrl.js @@ -3,8 +3,8 @@ /* Make user and settings available for everyone through root scope. */ -habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', - function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification) { +habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', 'Groups', + function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification, Groups) { $rootScope.modals = {}; $rootScope.modals.achievements = {}; $rootScope.User = User; @@ -150,12 +150,13 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ $rootScope.applyingAction = true; $scope.spell = spell; if (spell.target == 'self') { - debugger var tasks = User.user.habits.concat(User.user.dailys).concat(User.user.todos); User.user.tasks = _.object(_.pluck(tasks,'id'), tasks); $scope.castEnd(null, 'self'); } else if (spell.target == 'party') { - //TODO $scope.castEnd() + var party = Groups.party(); + party = (_.isArray(party) ? party : []).concat(User.user); + $scope.castEnd(party, 'party'); } } diff --git a/src/controllers/user.js b/src/controllers/user.js index aefa137942..2cad317dfa 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -517,12 +517,15 @@ api.cast = function(req, res) { Group.findOne({type: 'party', members: {'$in': [user._id]}}).populate('members').exec(cb); }, function(group, cb) { + if (!group) group = {members:[user]}; spell.cast(user, group.members); - var series = _.reduce(group.members, function(m,v){ - m.push(function(cb2){v.save(cb2);}) - return m; - }, []); + var series = _.transform(group.members, function(m,v,k){ + m[k] = function(cb2){v.save(cb2);} + }); async.series(series, cb); + }, + function(whatever, cb){ + user.save(cb); } ], done); break; diff --git a/src/models/user.js b/src/models/user.js index 3d56176fbf..2fd4d1ad42 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -223,11 +223,11 @@ var UserSchema = new Schema({ name: String, }, stats: { - hp: Number, - mp: Number, - exp: Number, - gp: Number, - lvl: Number, + hp: {type: Number, 'default': 50}, + mp: {type: Number, 'default': 10}, + exp: {type: Number, 'default': 0}, + gp: {type: Number, 'default': 0}, + lvl: {type: Number, 'default': 1}, // Class System 'class': {type: String, enum: ['warrior','rogue','wizard','rogue'], 'default': 'warrior'}, diff --git a/views/shared/header/header.jade b/views/shared/header/header.jade index 051c71d8db..ee8fde65d9 100644 --- a/views/shared/header/header.jade +++ b/views/shared/header/header.jade @@ -24,7 +24,7 @@ span(ng-show='user.history.exp') a(ng-click='toggleChart("exp")', tooltip='Progress') i.icon-signal - .meter.mana(title='Mana', ng-if='user.stats.class') + .meter.mana(title='Mana', ng-if='user.flags.classSelected') .bar(style='width: {{percent(user.stats.mp, user.stats.int+10)}}%;') span.meter-text i.icon-fire From e5c34af7fdff921b3e4ebbe15d05fe22918d32fd Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 5 Dec 2013 15:47:08 -0700 Subject: [PATCH 16/24] grunt-spritesmith contrib gear habitrpg-shared#69d248f --- views/options/social/tavern.jade | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/views/options/social/tavern.jade b/views/options/social/tavern.jade index b3bc2657d9..d208852244 100644 --- a/views/options/social/tavern.jade +++ b/views/options/social/tavern.jade @@ -62,23 +62,23 @@ When your first submission is deployed, you will receive the HabitRPG Contributor's badge. Your name in Tavern chat will proudly display that you are a contributor. As a bounty for your work, you will also receive 2 Gems. hr p. - When your second submission is deployed, the Crystal Armor will be available for purchase in the Rewards shop after the Golden Armor. As a bounty for your continued work, you will also receive 2 Gems. + When your second submission is deployed, the Crystal Armor will be available for purchase in the Rewards shop after the Golden Armor. As a bounty for your continued work, you will also receive 2 Gems. tr td a.label.label-contributor-3(ng-click='toggleUserTier($event)') Elite (3-4) div(style='display:none;') p. - When your third submission is deployed, the Crystal Helmet will be available for purchase in the Rewards shop after the Golden Helmet. As a bounty for your great work, you will also receive 2 Gems. + When your third submission is deployed, the Crystal Helmet will be available for purchase in the Rewards shop after the Golden Helmet. As a bounty for your great work, you will also receive 2 Gems. hr p. - When your fourth submission is deployed, the Crystal Sword will be available for purchase in the Rewards shop after the Golden Sword. You will once again receive a bounty of 2 Gems. + When your fourth submission is deployed, the Crystal Sword will be available for purchase in the Rewards shop after the Golden Sword. You will once again receive a bounty of 2 Gems. tr td a.label.label-contributor-5(ng-click='toggleUserTier($event)') Champion (5-6) div(style='display:none;') p. - When your fifth submission is deployed, the Crystal Shield will be available for purchase in the Reward shop after the Golden Shield. You will also receive 2 Gems. + When your fifth submission is deployed, the Crystal Shield will be available for purchase in the Reward shop after the Golden Shield. You will also receive 2 Gems. hr p.
When your sixth submission is deployed, you will receive a Hydra Pet. You will also receive 2 Gems. From b9845aec4a1288bfc997d86d9f2c7949b702d233 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 5 Dec 2013 15:48:50 -0700 Subject: [PATCH 17/24] classes: fixes to buying special-gear & regular gear habitrpg-shared#ee4777d --- migrations/20131204_classes.js | 2 ++ public/js/controllers/tasksCtrl.js | 23 ++++++++++++++++++----- src/controllers/user.js | 7 ++++--- src/routes/api.js | 2 +- views/shared/tasks/lists.jade | 2 +- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/migrations/20131204_classes.js b/migrations/20131204_classes.js index 4527b4b562..bf03f92740 100644 --- a/migrations/20131204_classes.js +++ b/migrations/20131204_classes.js @@ -7,6 +7,8 @@ db.users.find().forEach(function(user){ + user.stats.class = 'warrior'; + // grant backer/contrib gear, rather than using js logic // migrate current owned items diff --git a/public/js/controllers/tasksCtrl.js b/public/js/controllers/tasksCtrl.js index cd8a10e1cf..6544e1bb0d 100644 --- a/public/js/controllers/tasksCtrl.js +++ b/public/js/controllers/tasksCtrl.js @@ -106,17 +106,30 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', ' var updateStore = function(){ var updated = window.habitrpgShared.items.updateStore(User.user); - // Figure out whether we wanna put this in habitrpg-shared - var sorted = [updated.weapon, updated.armor, updated.head, updated.shield, updated.potion, updated.reroll]; + // Do we wanna put this in habitrpg-shared? + var sorted = _.chain(updated) + .toArray() + .sortBy(function(item){ + switch (item.type) { + case 'weapon': return 1; + case 'armor': return 2; + case 'head': return 3; + case 'shield': return 4; + case 'potion': return 5; + case 'reroll': return 6; + default: return 7; + } + }) + .value(); $scope.itemStore = sorted; } updateStore(); - $scope.buy = function(type) { - var hasEnough = window.habitrpgShared.items.buyItem(User.user, type); + $scope.buy = function(item) { + var hasEnough = window.habitrpgShared.items.buyItem(User.user, item); if (hasEnough) { - User.log({op: "buy", type: type}); + User.log({op: "buy", key: item.key}); Notification.text("Item purchased."); updateStore(); } else { diff --git a/src/controllers/user.js b/src/controllers/user.js index 2cad317dfa..fcae5a6596 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -204,11 +204,11 @@ api.clearCompleted = function(req, res, next) { */ api.buy = function(req, res, next) { var user = res.locals.user; - var type = req.params.type; - if (!type.match(/potion|weapon|armor|head|shield/)) { // if (item !== 'potion' && !items.items.gear.flat[item]) + var key = req.params.key; + if (key !== 'potion' && !items.items.gear.flat[key]) { return res.json(400, {err: ":item must be a supported key, see https://github.com/HabitRPG/habitrpg-shared/blob/master/script/items.coffee"}); } - var hasEnough = items.buyItem(user, type); + var hasEnough = items.buyItem(user, items.items.gear.flat[key]); if (hasEnough) { return user.save(function(err, saved) { if (err) return res.json(500, {err: err}); @@ -565,6 +565,7 @@ api.batchUpdate = function(req, res, next) { req.params.id = action.data && action.data.id; req.params.direction = action.dir; req.params.type = action.type; + req.params.key = action.key; req.body = action.data; res.send = res.json = function(code, data) { if (_.isNumber(code) && code >= 400) { diff --git a/src/routes/api.js b/src/routes/api.js index 34c3c3327d..8329c4a511 100644 --- a/src/routes/api.js +++ b/src/routes/api.js @@ -48,7 +48,7 @@ if (nconf.get('NODE_ENV') == 'development') { } /* Items*/ -router.post('/user/buy/:type', auth.auth, cron, user.buy); +router.post('/user/buy/:key', auth.auth, cron, user.buy); /* User*/ router.get('/user', auth.auth, cron, user.getUser); diff --git a/views/shared/tasks/lists.jade b/views/shared/tasks/lists.jade index 796df6579f..05ad059d15 100644 --- a/views/shared/tasks/lists.jade +++ b/views/shared/tasks/lists.jade @@ -55,7 +55,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") .task-controls a.task-action-btn.btn-reroll(bo-if='item.type=="reroll"', ng-click='modals.reroll = true') i.icon-repeat - a.money.btn-buy.item-btn(bo-if='item.type!="reroll"', ng-click='buy(item.type)') + a.money.btn-buy.item-btn(bo-if='item.type!="reroll"', ng-click='buy(item)') span.reward-cost {{item.value}} span.shop_gold // main content From 7f1892b34a66d7413d1689db7ec6acdb009de003 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Thu, 5 Dec 2013 18:20:09 -0700 Subject: [PATCH 18/24] classes: move item-store sorting from web to shard (so we can share with mobile) habitrpg-shared#6651665 --- migrations/20131204_classes.js | 2 +- public/js/controllers/tasksCtrl.js | 24 ++---------------------- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/migrations/20131204_classes.js b/migrations/20131204_classes.js index bf03f92740..c760da4c4b 100644 --- a/migrations/20131204_classes.js +++ b/migrations/20131204_classes.js @@ -9,7 +9,7 @@ db.users.find().forEach(function(user){ user.stats.class = 'warrior'; - // grant backer/contrib gear, rather than using js logic + // grant backer/contrib gear, 300, rather than using js logic // migrate current owned items diff --git a/public/js/controllers/tasksCtrl.js b/public/js/controllers/tasksCtrl.js index 6544e1bb0d..72fb1dcb59 100644 --- a/public/js/controllers/tasksCtrl.js +++ b/public/js/controllers/tasksCtrl.js @@ -104,34 +104,14 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', ' ------------------------ */ - var updateStore = function(){ - var updated = window.habitrpgShared.items.updateStore(User.user); - // Do we wanna put this in habitrpg-shared? - var sorted = _.chain(updated) - .toArray() - .sortBy(function(item){ - switch (item.type) { - case 'weapon': return 1; - case 'armor': return 2; - case 'head': return 3; - case 'shield': return 4; - case 'potion': return 5; - case 'reroll': return 6; - default: return 7; - } - }) - .value(); - $scope.itemStore = sorted; - } - - updateStore(); + $scope.itemStore = window.habitrpgShared.items.updateStore(User.user); $scope.buy = function(item) { var hasEnough = window.habitrpgShared.items.buyItem(User.user, item); if (hasEnough) { User.log({op: "buy", key: item.key}); Notification.text("Item purchased."); - updateStore(); + $scope.itemStore = window.habitrpgShared.items.updateStore(User.user); } else { Notification.text("Not enough Gold!"); } From 3e5c2136942031600c68bf15231a0417758b3776 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Fri, 6 Dec 2013 09:26:02 -0700 Subject: [PATCH 19/24] classes armory: separate gear listings by class type, show selected gear --- public/js/controllers/inventoryCtrl.js | 22 ++++++++++++++++++++-- views/options/inventory/inventory.jade | 13 +++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index 99fc90164a..20720745ea 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -2,6 +2,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', function($rootScope, $scope, User, API_URL, $http, Notification) { var user = User.user; + var Items = window.habitrpgShared.items; // convenience vars since these are accessed frequently @@ -17,11 +18,28 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', $scope.$watch('user.items.hatchingPotions', function(pots){ $scope.potCount = countStacks(pots); }, true); $scope.$watch('user.items.food', function(food){ $scope.foodCount = countStacks(food); }, true); + $scope.$watch('user.items.gear', function(gear){ + $scope.gear = { + base: [ + Items.items.gear.flat['head_warrior_0'], + Items.items.gear.flat['armor_warrior_0'], + //Items.items.gear.flat['weapon_warrior_0'], + Items.items.gear.flat['shield_warrior_0'] + ] + }; + _.each(gear.owned, function(bool,key){ + var item = Items.items.gear.flat[key]; + debugger; + if (!$scope.gear[item.klass]) $scope.gear[item.klass] = []; + $scope.gear[item.klass].push(item); + }) + }, true) + $scope.chooseEgg = function(egg){ if ($scope.selectedEgg && $scope.selectedEgg.name == egg) { return $scope.selectedEgg = null; // clicked same egg, unselect } - var eggData = _.findWhere(window.habitrpgShared.items.items.eggs, {name:egg}); + var eggData = _.findWhere(Items.items.eggs, {name:egg}); if (!$scope.selectedPotion) { $scope.selectedEgg = eggData; } else { @@ -34,7 +52,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', return $scope.selectedPotion = null; // clicked same egg, unselect } // we really didn't think through the way these things are stored and getting passed around... - var potionData = _.findWhere(window.habitrpgShared.items.items.hatchingPotions, {name:potion}); + var potionData = _.findWhere(Items.items.hatchingPotions, {name:potion}); if (!$scope.selectedEgg) { $scope.selectedPotion = potionData; } else { diff --git a/views/options/inventory/inventory.jade b/views/options/inventory/inventory.jade index a8446e551a..28b1e1e6d2 100644 --- a/views/options/inventory/inventory.jade +++ b/views/options/inventory/inventory.jade @@ -5,18 +5,19 @@ script(type='text/ng-template', id='partials/options.inventory.inventory.html') p.well Click an egg to see usable potions highlighted in green and then click one of the highlighted potions to hatch your pet. If no potions are highlighted, click that egg again to deselect it, and instead click a potion first to have the usable eggs highlighted. You can also sell unwanted drops to Alexander the Merchant. menu.inventory-list(type='list') + h4 Gear li.customize-menu - menu.pets-menu(label='Gear') - div(ng-repeat='(k,v) in user.items.gear.owned', ng-init='item = Items.gear.flat[k]') - button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(user,item)', class='shop_{{item.key}}') + menu.pets-menu(label='{{label}}', ng-repeat='(klass,label) in {base:"Base", warrior:"Warrior", wizard:"Wizard", rogue:"Rogue", special:"Special"}', ng-show='gear[klass]') + div(ng-repeat='item in gear[klass]') + button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(user,item)', class='shop_{{item.key}}', ng-class='{selectableInventory: user.items.gear.equipped[item.type] == item.key}') label.checkbox.inline input(type="checkbox", ng-model="user.preferences.costume") | Use Costume  i.icon-question-sign(popover="Show something different on your avatar than the gear you have equipped for battle", popover-trigger='mouseenter', popover-placement='right') li.customize-menu(ng-if='user.preferences.costume') - menu.pets-menu(label='Gear') - div(ng-repeat='(k,v) in user.items.gear.owned', ng-init='item = Items.gear.flat[k]') - button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(user,item,true)', class='shop_{{item.key}}') + menu.pets-menu(label='{{label}}', ng-repeat='(klass,label) in {base:"Base", warrior:"Warrior", wizard:"Wizard", rogue:"Rogue", special:"Special"}', ng-show='gear[klass]') + div(ng-repeat='item in gear[klass]') + button.customize-option(popover='{{item.notes}}', popover-title='{{item.text}}', popover-trigger='mouseenter', popover-placement='right', ng-click='equip(user,item, true)', class='shop_{{item.key}}', ng-class='{selectableInventory: user.items.gear.costume[item.type] == item.key}') li.customize-menu menu.pets-menu(label='Eggs ({{eggCount}})') From 82168285142e1d75c166973bbb54eb639af66859 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Fri, 6 Dec 2013 10:51:15 -0700 Subject: [PATCH 20/24] classes #943 reroll sets you on your new class's item track. Handling of two-handed staves --- public/js/controllers/inventoryCtrl.js | 8 +++++++- public/js/controllers/userCtrl.js | 17 +++++++++++++++++ views/shared/modals/classes.jade | 4 ++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index 20720745ea..ac9171e100 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -182,7 +182,13 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', $scope.equip = function(user, item, costume) { var equipTo = costume ? 'costume' : 'equipped'; - User.set('items.gear.' + equipTo + '.' + item.type, item.key); + if (~user.items.gear[equipTo].weapon.indexOf('wizard') && item.type == 'shield') + return Notification.text('Staves are two-handed'); + var setVars = {}; + setVars['items.gear.' + equipTo + '.' + item.type] = item.key; + if (item.klass == 'wizard') + setVars['items.gear.' + equipTo + '.shield'] = 'warrior_shield_0'; + User.setMultiple(setVars); } } diff --git a/public/js/controllers/userCtrl.js b/public/js/controllers/userCtrl.js index 20d946dde8..24436261e8 100644 --- a/public/js/controllers/userCtrl.js +++ b/public/js/controllers/userCtrl.js @@ -30,6 +30,23 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$ 'stats.int': 0 }) } + $scope.rerollSubmit = function(){ + var setVars = { + "stats.class": $scope.selectedClass, + "flags.classSelected": true + }; + _.each(['weapon','armor','shield','head'], function(type){ + setVars['items.gear.owned.' + type + '_' + $scope.selectedClass + '_0'] = true; + setVars['items.gear.equipped.' + type] = $scope.selectedClass + '_0'; + }); + if ($scope.selectedClass == 'wizard') { + delete setVars['items.gear.owned.shield_wizard_0']; + setVars['items.gear.equipped.shield'] = 'warrior_shield_0'; + } + + User.setMultiple(setVars); + $scope.selectedClass = undefined; + } $scope.save = function(){ var values = {}; diff --git a/views/shared/modals/classes.jade b/views/shared/modals/classes.jade index 6c789ce576..ba38bf3375 100644 --- a/views/shared/modals/classes.jade +++ b/views/shared/modals/classes.jade @@ -1,4 +1,4 @@ -.modal(ng-if='!user.flags.classSelected && user.stats.lvl >= 5', data-backdrop=true) +.modal(ng-if='!user.flags.classSelected && user.stats.lvl >= 5', data-backdrop=true, ng-controller='UserCtrl') .modal-header h3 Class System Unlocked! .modal-body @@ -66,4 +66,4 @@ span(class='weapon_healer_6') .modal-footer - button.btn.btn-default.cancel(ng-click='User.setMultiple({"stats.class":selectedClass,"flags.classSelected":true});') Select \ No newline at end of file + button.btn.btn-default.cancel(ng-click='rerollSubmit()') Select \ No newline at end of file From b852d9a9f2cf34624e426988072db6a8b0a9d418 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Fri, 6 Dec 2013 11:46:07 -0700 Subject: [PATCH 21/24] classes #943 more general solution to two-handed weapons habitrpg-shared#41da82f --- public/js/controllers/inventoryCtrl.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index ac9171e100..84e0ebff56 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -182,11 +182,13 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', $scope.equip = function(user, item, costume) { var equipTo = costume ? 'costume' : 'equipped'; - if (~user.items.gear[equipTo].weapon.indexOf('wizard') && item.type == 'shield') - return Notification.text('Staves are two-handed'); + if (item.type == 'shield') { + var weapon = Items.items.gear.flat[user.items.gear[equipTo].weapon]; + if (weapon && weapon.twoHanded) return Notification.text(weapon.text + ' is two-handed'); + } var setVars = {}; setVars['items.gear.' + equipTo + '.' + item.type] = item.key; - if (item.klass == 'wizard') + if (item.twoHanded) setVars['items.gear.' + equipTo + '.shield'] = 'warrior_shield_0'; User.setMultiple(setVars); } From c51cdd0849428a5d8644b9d434c55c234fd92197 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Fri, 6 Dec 2013 15:41:58 -0700 Subject: [PATCH 22/24] classes: proper handling of items on class-switch, un-equipping items, etc. Paves way for item-loss on death. See habitrpg-shared#acae9c3 --- public/js/controllers/inventoryCtrl.js | 8 +------ public/js/controllers/userCtrl.js | 32 +++++++++++++++++++------- src/models/user.js | 14 +++++------ views/options/profile.jade | 12 +++++----- views/shared/header/avatar.jade | 2 +- views/shared/modals/classes.jade | 8 +++---- views/shared/tasks/lists.jade | 2 +- 7 files changed, 44 insertions(+), 34 deletions(-) diff --git a/public/js/controllers/inventoryCtrl.js b/public/js/controllers/inventoryCtrl.js index 84e0ebff56..8874a531cb 100644 --- a/public/js/controllers/inventoryCtrl.js +++ b/public/js/controllers/inventoryCtrl.js @@ -20,16 +20,10 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL', $scope.$watch('user.items.gear', function(gear){ $scope.gear = { - base: [ - Items.items.gear.flat['head_warrior_0'], - Items.items.gear.flat['armor_warrior_0'], - //Items.items.gear.flat['weapon_warrior_0'], - Items.items.gear.flat['shield_warrior_0'] - ] + base: _.where(Items.items.gear.flat, {klass: 'base'}) }; _.each(gear.owned, function(bool,key){ var item = Items.items.gear.flat[key]; - debugger; if (!$scope.gear[item.klass]) $scope.gear[item.klass] = []; $scope.gear[item.klass].push(item); }) diff --git a/public/js/controllers/userCtrl.js b/public/js/controllers/userCtrl.js index 24436261e8..e0c52fdba2 100644 --- a/public/js/controllers/userCtrl.js +++ b/public/js/controllers/userCtrl.js @@ -31,21 +31,37 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$ }) } $scope.rerollSubmit = function(){ + var klass = $scope.selectedClass; var setVars = { - "stats.class": $scope.selectedClass, + "stats.class": klass, "flags.classSelected": true }; - _.each(['weapon','armor','shield','head'], function(type){ - setVars['items.gear.owned.' + type + '_' + $scope.selectedClass + '_0'] = true; - setVars['items.gear.equipped.' + type] = $scope.selectedClass + '_0'; + + // Clear their gear and equip their new class's gear (can still equip old gear from inventory) + // If they've rolled this class before, restore their progress + _.each(['weapon', 'armor','shield','head'], function(type){ + var foundKey = false; + _.findLast(User.user.items.gear.owned, function(v,k){ + if (~k.indexOf(type + '_' + klass)) { + foundKey = k; + return true; + } + }); + setVars['items.gear.equipped.' + type] = + foundKey ? foundKey : // restore progress from when they last rolled this class + (type == 'weapon') ? 'weapon_' + klass + '_0' : // weapon_0 is significant, don't reset to base_0 + (type == 'shield' && klass == 'rogue') ? 'shield_rogue_0' : // rogues start with an off-hand weapon + type + '_base_0'; // naked for the rest! + + // Grant them their new class's gear + if (type == 'weapon' || (type == 'shield' && klass == 'rogue')) + setVars['items.gear.owned.' + type + '_' + klass + '_0'] = true; }); - if ($scope.selectedClass == 'wizard') { - delete setVars['items.gear.owned.shield_wizard_0']; - setVars['items.gear.equipped.shield'] = 'warrior_shield_0'; - } User.setMultiple(setVars); $scope.selectedClass = undefined; + + //FIXME run updateStore (we need to access a different scope) } $scope.save = function(){ diff --git a/src/models/user.js b/src/models/user.js index 2fd4d1ad42..c1e723d1ae 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -117,15 +117,15 @@ var UserSchema = new Schema({ equipped: { weapon: {type: String, 'default': 'weapon_warrior_0'}, - armor: {type: String, 'default': 'armor_warrior_0'}, - head: {type: String, 'default': 'head_warrior_0'}, - shield: {type: String, 'default': 'shield_warrior_0'} + armor: {type: String, 'default': 'armor_base_0'}, + head: {type: String, 'default': 'head_base_0'}, + shield: {type: String, 'default': 'shield_base_0'} }, costume: { - weapon: {type: String, 'default': 'weapon_warrior_0'}, - armor: {type: String, 'default': 'armor_warrior_0'}, - head: {type: String, 'default': 'head_warrior_0'}, - shield: {type: String, 'default': 'shield_warrior_0'} + weapon: {type: String, 'default': 'weapon_base_0'}, + armor: {type: String, 'default': 'armor_base_0'}, + head: {type: String, 'default': 'head_base_0'}, + shield: {type: String, 'default': 'shield_base_0'} }, }, diff --git a/views/options/profile.jade b/views/options/profile.jade index 6a5ad5b896..e457457cfb 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -6,8 +6,8 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') li.customize-menu menu(label='Head') menu - button.broad_armor_warrior_0.customize-option(type='button', ng-click='set("preferences.size","broad")') - button.slim_armor_warrior_0.customize-option(type='button', ng-click='set("preferences.size","slim")') + button.broad_armor_base_0.customize-option(type='button', ng-click='set("preferences.size","broad")') + button.slim_armor_base_0.customize-option(type='button', ng-click='set("preferences.size","slim")') .span4 h3 Hair @@ -24,7 +24,7 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Bangs li.customize-menu menu(label='Bangs') - button(class='head_0 customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') + button(class='head_base_0 customize-option', type='button', ng-click='set("preferences.hair.bangs",0)') button(class='hair_bangs_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",1)') button(class='hair_bangs_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",2)') button(class='hair_bangs_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.bangs",3)') @@ -32,7 +32,7 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Beard li.customize-menu menu(label='Beard') - button(class='head_0 customize-option', type='button', ng-click='set("preferences.hair.beard",0)') + button(class='head_base_0 customize-option', type='button', ng-click='set("preferences.hair.beard",0)') button(class='hair_beard_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",1)') button(class='hair_beard_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",2)') button(class='hair_beard_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.beard",3)') @@ -40,14 +40,14 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template') // Mustache li.customize-menu menu(label='Mustache') - button(class='head_0 customize-option', type='button', ng-click='set("preferences.hair.mustache",0)') + button(class='head_base_0 customize-option', type='button', ng-click='set("preferences.hair.mustache",0)') button(class='hair_mustache_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.mustache",1)') button(class='hair_mustache_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.mustache",2)') // Base li.customize-menu menu(label='Base') - button(class='head_0 customize-option', type='button', ng-click='set("preferences.hair.base",0)') + button(class='head_base_0 customize-option', type='button', ng-click='set("preferences.hair.base",0)') button(class='hair_base_1_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",1)') button(class='hair_base_2_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",2)') button(class='hair_base_3_{{user.preferences.hair.color}} customize-option', type='button', ng-click='set("preferences.hair.base",3)') diff --git a/views/shared/header/avatar.jade b/views/shared/header/avatar.jade index 6b26a5b5b6..dce75fa564 100644 --- a/views/shared/header/avatar.jade +++ b/views/shared/header/avatar.jade @@ -14,7 +14,7 @@ figure.herobox(ng-click='spell ? castEnd(profile, "user", $event) : clickMember( span(class='{{profile.preferences.size}}_{{profile.items.gear.equipped.armor}}', ng-if='!profile.preferences.costume') span(class='{{profile.preferences.size}}_{{profile.items.gear.costume.armor}}', ng-if='profile.preferences.costume') - span(class='head_0') + span(class='head_base_0') span(class='hair_base_{{profile.preferences.hair.base}}_{{profile.preferences.hair.color}}') span(class='hair_bangs_{{profile.preferences.hair.bangs}}_{{profile.preferences.hair.color}}') diff --git a/views/shared/modals/classes.jade b/views/shared/modals/classes.jade index ba38bf3375..ae5c5c06a3 100644 --- a/views/shared/modals/classes.jade +++ b/views/shared/modals/classes.jade @@ -14,7 +14,7 @@ .character-sprites span(class='skin_{{user.preferences.skin}}') span(class='{{user.preferences.size}}_armor_warrior_5') - span(class='head_0') + span(class='head_base_0') span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') span(class='hair_beard_{{user.preferences.hair.beard}}_{{user.preferences.hair.color}}') @@ -28,7 +28,7 @@ .character-sprites span(class='skin_{{user.preferences.skin}}') span(class='{{user.preferences.size}}_armor_wizard_5') - span(class='head_0') + span(class='head_base_0') span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') span(class='hair_beard_{{user.preferences.hair.beard}}_{{user.preferences.hair.color}}') @@ -42,7 +42,7 @@ .character-sprites span(class='skin_{{user.preferences.skin}}') span(class='{{user.preferences.size}}_armor_rogue_5') - span(class='head_0') + span(class='head_base_0') span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') span(class='hair_beard_{{user.preferences.hair.beard}}_{{user.preferences.hair.color}}') @@ -56,7 +56,7 @@ .character-sprites span(class='skin_{{user.preferences.skin}}') span(class='{{user.preferences.size}}_armor_healer_5') - span(class='head_0') + span(class='head_base_0') span(class='hair_base_{{user.preferences.hair.base}}_{{user.preferences.hair.color}}') span(class='hair_bangs_{{user.preferences.hair.bangs}}_{{user.preferences.hair.color}}') span(class='hair_beard_{{user.preferences.hair.beard}}_{{user.preferences.hair.color}}') diff --git a/views/shared/tasks/lists.jade b/views/shared/tasks/lists.jade index 05ad059d15..4598d278df 100644 --- a/views/shared/tasks/lists.jade +++ b/views/shared/tasks/lists.jade @@ -46,7 +46,7 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") // Static Rewards ul.items.rewards(bo-if='main && list.type=="reward" && user.flags.itemsEnabled') - li.task.reward-item(ng-if='!item.hide', ng-repeat='item in itemStore') + li.task.reward-item(ng-repeat='item in itemStore') // right-hand side control buttons .task-meta-controls span.task-notes(popover-trigger='mouseenter', popover-placement='left', popover='{{item.notes}}', popover-title='{{item.text}}') From 59f8727cbfe752af9aa882728f9f8f4d50ca0ef2 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sat, 7 Dec 2013 11:31:11 -0700 Subject: [PATCH 23/24] classes: small tweaks --- migrations/20131204_classes.js | 2 ++ public/js/services/userServices.js | 1 + src/models/user.js | 4 ++-- views/options/profile.jade | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/migrations/20131204_classes.js b/migrations/20131204_classes.js index c760da4c4b..8dddd0a826 100644 --- a/migrations/20131204_classes.js +++ b/migrations/20131204_classes.js @@ -11,6 +11,8 @@ db.users.find().forEach(function(user){ // grant backer/contrib gear, 300, rather than using js logic + // customizations redo: https://trello.com/c/YKXmHNjY/306-customization-redo + // migrate current owned items // gender => size diff --git a/public/js/services/userServices.js b/public/js/services/userServices.js index bf9b605a87..9db94b7828 100644 --- a/public/js/services/userServices.js +++ b/public/js/services/userServices.js @@ -23,6 +23,7 @@ angular.module('userServices', []). //first we populate user with schema _.extend(user, $window.habitrpgShared.helpers.newUser()); user.apiToken = user._id = ''; // we use id / apitoken to determine if registered + $window.habitrpgShared.algos.defineComputed(user); //than we try to load localStorage if (localStorage.getItem(STORAGE_USER_ID)) { diff --git a/src/models/user.js b/src/models/user.js index c1e723d1ae..2fbd5e6e4d 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -233,7 +233,7 @@ var UserSchema = new Schema({ 'class': {type: String, enum: ['warrior','rogue','wizard','rogue'], 'default': 'warrior'}, points: {type: Number, 'default': 0}, str: {type: Number, 'default': 0}, - def: {type: Number, 'default': 0}, + con: {type: Number, 'default': 0}, int: {type: Number, 'default': 0}, per: {type: Number, 'default': 0}, buffs: { @@ -306,7 +306,7 @@ UserSchema.pre('save', function(next) { // FIXME handle this on level-up instead, and come up with how we're going to handle retroactively // Actually, can this be used as an attr default? (schema {type: ..., 'default': function(){}}) - this.stats.points = this.stats.lvl - (this.stats.def + this.stats.str + this.stats.per + this.stats.int); + this.stats.points = this.stats.lvl - (this.stats.con + this.stats.str + this.stats.per + this.stats.int); var petCount = helpers.countPets(_.reduce(this.items.pets,function(m,v){ //HOTFIX - Remove when solution is found, the first argument passed to reduce is a function diff --git a/views/options/profile.jade b/views/options/profile.jade index e457457cfb..b0d32c24a0 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -123,7 +123,7 @@ script(id='partials/options.profile.stats.html', type='text/ng-template') i.icon-question-sign(popover-title='Defense', popover='Defense decreases damage inflicted by tasks, and increases the effectiveness of healing and buff spells', popover-trigger='mouseenter') |  DEF: {{user.stats.def}} td - a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("def")') + + a.btn.btn-primary(ng-show='user.stats.points', ng-click='allocate("con")') + tr td i.icon-question-sign(popover-title='Perception', popover='Perception increases the likelihood of drops, Gold bonuses, and critical hit chances', popover-trigger='mouseenter') From 714dad6e917b168a3b9d7a4fb94508d20051c904 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sat, 7 Dec 2013 20:41:48 -0700 Subject: [PATCH 24/24] classes: small bug fixes --- src/models/user.js | 2 +- views/options/inventory/stable.jade | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/models/user.js b/src/models/user.js index 2fbd5e6e4d..10e548d11e 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -230,7 +230,7 @@ var UserSchema = new Schema({ lvl: {type: Number, 'default': 1}, // Class System - 'class': {type: String, enum: ['warrior','rogue','wizard','rogue'], 'default': 'warrior'}, + 'class': {type: String, enum: ['warrior','rogue','wizard','healer'], 'default': 'warrior'}, points: {type: Number, 'default': 0}, str: {type: Number, 'default': 0}, con: {type: Number, 'default': 0}, diff --git a/views/options/inventory/stable.jade b/views/options/inventory/stable.jade index 4dd103f20c..c5656b844c 100644 --- a/views/options/inventory/stable.jade +++ b/views/options/inventory/stable.jade @@ -14,16 +14,17 @@ script(type='text/ng-template', id='partials/options.inventory.stable.mounts.htm .stable table(style='width:100%') tr - td.npc_matt + td(style='width:144px') + .npc_matt td - .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') - .arrow - h3.popover-title - a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch - .popover-content - p. - Shall I bring you your steed, {{user.profile.name}}? Click a mount to saddle up. - h4 {{mountCount}} / {{totalPets}} Mounts Tamed + .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') + .arrow + h3.popover-title + a(target='_blank', href='http://www.kickstarter.com/profile/mattboch') Matt Boch + .popover-content + p. + Shall I bring you your steed, {{user.profile.name}}? Click a mount to saddle up. + h4 {{mountCount}} / {{totalPets}} Mounts Tamed menu.pets(type='list') li.customize-menu(ng-repeat='egg in Items.eggs') menu @@ -45,7 +46,8 @@ script(type='text/ng-template', id='partials/options.inventory.stable.pets.html' .stable table(style='width:100%') tr - td.npc_matt + td(style='width:144px') + .npc_matt td .popover.static-popover.fade.right.in(style='max-width: 550px; margin-left: 10px;') .arrow