mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
classes WIP
This commit is contained in:
@@ -150,6 +150,8 @@
|
||||
background: darken($worse, 38%)
|
||||
.experience .bar
|
||||
background: darken($neutral, 30%)
|
||||
.mana .bar
|
||||
background: darken($best, 30%)
|
||||
|
||||
.meter-text
|
||||
position: absolute
|
||||
|
||||
@@ -174,3 +174,12 @@ a
|
||||
.modal-indented-list
|
||||
margin-left: 10px;
|
||||
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
|
||||
@@ -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;
|
||||
// }
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -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 <ins>, else things break.
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,14 +19,37 @@ script(id='partials/options.profile.avatar.html', type='text/ng-template')
|
||||
button.f_armor_0_v2.customize-option(type='button', ng-click='set("preferences.armorSet","v2")')
|
||||
|
||||
.span4
|
||||
// hair
|
||||
h3 Hair
|
||||
menu(type='list')
|
||||
// Color
|
||||
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")')
|
||||
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')
|
||||
|
||||
@@ -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="<div ng-hide='profile.id == user.id'> <div class='progress progress-danger' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.hp, 50)}}%;'></div> </div> <div class='progress progress-warning' style='height:5px;'> <div class='bar' style='height: 5px; width: {{percent(profile.stats.exp, tnl(profile.stats.lvl))}}%;'></div> </div> <div>Level: {{profile.stats.lvl}}</div> <div>GP: {{profile.stats.gp | number:0}}</div> <div>{{count(profile.items.pets)}} / 90 Pets Found</div> </div>")
|
||||
|
||||
figure.herobox(ng-click='clickMember(profile._id)', data-name='{{profile.profile.name}}', ng-class='{isUser: user._id==profile._id && !(user.items.currentMount && user.items.currentPet), hasPet: profile.items.currentPet && profile.items.currentMount}')
|
||||
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}}
|
||||
|
||||
@@ -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')
|
||||
|
||||
45
views/shared/modals/classes.jade
Normal file
45
views/shared/modals/classes.jade
Normal file
@@ -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
|
||||
@@ -7,3 +7,4 @@ include ./buy-gems
|
||||
include ./members
|
||||
include ./settings
|
||||
include ./pets
|
||||
include ./classes
|
||||
@@ -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
|
||||
|
||||
@@ -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]')
|
||||
|
||||
Reference in New Issue
Block a user