diff --git a/common/locales/en/death.json b/common/locales/en/death.json
index b7032d7a73..dc131e74f2 100644
--- a/common/locales/en/death.json
+++ b/common/locales/en/death.json
@@ -3,5 +3,15 @@
"dontDespair": "Don't despair!",
"deathPenaltyDetails": "You lost a Level, your Gold, and a piece of Equipment, but you can get them all back with hard work! Good luck--you'll do great.",
"refillHealthTryAgain": "Refill Health & Try Again",
- "dyingOftenTips": "Is this happening often? Here are some tips!"
-}
\ No newline at end of file
+ "dyingOftenTips": "Is this happening often? Here are some tips!",
+ "losingHealthWarning": "Careful - You're Losing Health!",
+ "losingHealthWarning2": "Don't let your Health drop to zero! If you do, you'll lose a level, your Gold, and a piece of equipment.",
+ "toRegainHealth": "To regain Health:",
+ "lowHealthTips1": "Level up to fully heal!",
+ "lowHealthTips2": "Buy a Health Potion from the Rewards column to restore 15 Health Points.",
+ "losingHealthQuickly": "Losing Health quickly?",
+ "lowHealthTips3": "Incomplete Dailies hurt you overnight, so be careful not to add too many at first!",
+ "lowHealthTips4": "If a Daily isn't due on a certain day, you can disable it by clicking the pencil icon.",
+ "goodLuck": "Good luck!"
+}
+
diff --git a/website/public/css/shared.styl b/website/public/css/shared.styl
index 41a04df2ce..9a48dd28df 100644
--- a/website/public/css/shared.styl
+++ b/website/public/css/shared.styl
@@ -45,6 +45,9 @@ a.hint:hover
ul
list-style-position: inside;
+li.spaced
+ margin: auto auto .5em 3em
+
.group-leave-join
.glyphicon-ban-circle
color: white;
diff --git a/website/public/js/controllers/notificationCtrl.js b/website/public/js/controllers/notificationCtrl.js
index 77f66b497f..06c8dc74be 100644
--- a/website/public/js/controllers/notificationCtrl.js
+++ b/website/public/js/controllers/notificationCtrl.js
@@ -8,6 +8,8 @@ habitrpg.controller('NotificationCtrl',
if (after <= 0){
$rootScope.playSound('Death');
$rootScope.openModal('death', {keyboard:false, backdrop:'static'});
+ } else if (after <= 30 && !User.user.flags.warnedLowHealth) {
+ $rootScope.openModal('lowHealth', {keyboard:false, backdrop:'static', controller:'UserCtrl', track:'Health Warning'});
}
if (after == before) return;
if (User.user.stats.lvl == 0) return;
diff --git a/website/public/js/controllers/userCtrl.js b/website/public/js/controllers/userCtrl.js
index db8559d728..f2a53ed2b5 100644
--- a/website/public/js/controllers/userCtrl.js
+++ b/website/public/js/controllers/userCtrl.js
@@ -43,6 +43,10 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$
$scope._editing.profile = false;
}
+ $scope.acknowledgeHealthWarning = function(){
+ User.user.ops.update && User.set({'flags.warnedLowHealth':false});
+ }
+
/**
* For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase
* @param path: User.preferences <-> User.purchased maps like User.preferences.skin=abc <-> User.purchased.skin.abc.
diff --git a/website/src/models/user.js b/website/src/models/user.js
index fc52a48f3b..a8638dcc45 100644
--- a/website/src/models/user.js
+++ b/website/src/models/user.js
@@ -163,7 +163,8 @@ var UserSchema = new Schema({
armoireEnabled: {type: Boolean, 'default': false},
armoireOpened: {type: Boolean, 'default': false},
armoireEmpty: {type: Boolean, 'default': false},
- cardReceived: {type: Boolean, 'default': false}
+ cardReceived: {type: Boolean, 'default': false},
+ warnedLowHealth: {type: Boolean, 'default': false}
},
history: {
exp: Array, // [{date: Date, value: Number}], // big peformance issues if these are defined
diff --git a/website/views/shared/avatar/appearance.jade b/website/views/shared/avatar/appearance.jade
index 75d74e2a45..7b28273996 100644
--- a/website/views/shared/avatar/appearance.jade
+++ b/website/views/shared/avatar/appearance.jade
@@ -1,3 +1,5 @@
+include generated_avatar
+
mixin avatar(opts)
.character-sprites
.addthis_native_toolbox(ng-if='::profile._id==user._id',
@@ -16,7 +18,7 @@ mixin avatar(opts)
// Show avatar only if not currently affected by visual buff
- var buffs = '!profile.stats.buffs'
span(ng-if='#{buffs}.snowball && #{buffs}.spookDust && #{buffs}.shinySeed && #{buffs}.seafoam')
- include generated_avatar
+ +generatedAvatar
// Mount Head
if !opts.minimal
diff --git a/website/views/shared/avatar/generated_avatar.jade b/website/views/shared/avatar/generated_avatar.jade
index 7f7ef4479b..e6423c8f16 100644
--- a/website/views/shared/avatar/generated_avatar.jade
+++ b/website/views/shared/avatar/generated_avatar.jade
@@ -4,39 +4,24 @@ mixin costumeSetting(type, options)
- var equipped = (options.prefix || '') + 'profile.items.gear.equipped.' + type + (options.suffix || '')
span(ng-class="profile.preferences.costume ? #{costume} : #{equipped}")
-// Back accessory
-+costumeSetting('back')
-
-span(ng-class="profile.preferences.sleep ? 'skin_' + profile.preferences.skin + '_sleep' : 'skin_' + profile.preferences.skin")
-
-// Shirt
-span(class='{{profile.preferences.size}}_shirt_{{profile.preferences.shirt}}')
-
-// Armor
-+costumeSetting('armor', {prefix: "profile.preferences.size + '_' + "})
-
-// Cape collar
-+costumeSetting('back', {suffix: " + '_collar'"})
-
-// Body
-+costumeSetting('body')
-
-// Empty outline of head
-span(class='head_0')
-
-// Hair
-- var hairTypes = ['base', 'bangs', 'mustache', 'beard']
-each type in hairTypes
- span(class='hair_#{type}_{{profile.preferences.hair.#{type}}}_{{profile.preferences.hair.color}}')
-
-// Head
-+costumeSetting('eyewear')
-+costumeSetting('head')
-+costumeSetting('headAccessory')
-
-// Flower
-span(class='hair_flower_{{profile.preferences.hair.flower}}')
-
-// Items held in hands
-+costumeSetting('shield')
-+costumeSetting('weapon')
+mixin generatedAvatar(options)
+ - options = options || {}
+ +costumeSetting('back')
+ if options.sleep
+ span(ng-class="'skin_' + profile.preferences.skin + '_sleep'")
+ else
+ span(ng-class="profile.preferences.sleep ? 'skin_' + profile.preferences.skin + '_sleep' : 'skin_' + profile.preferences.skin")
+ span(class='{{profile.preferences.size}}_shirt_{{profile.preferences.shirt}}')
+ +costumeSetting('armor', {prefix: "profile.preferences.size + '_' + "})
+ +costumeSetting('back', {suffix: " + '_collar'"})
+ +costumeSetting('body')
+ span(class='head_0')
+ - var hairTypes = ['base', 'bangs', 'mustache', 'beard']
+ each type in hairTypes
+ span(class='hair_#{type}_{{profile.preferences.hair.#{type}}}_{{profile.preferences.hair.color}}')
+ +costumeSetting('eyewear')
+ +costumeSetting('head')
+ +costumeSetting('headAccessory')
+ span(class='hair_flower_{{profile.preferences.hair.flower}}')
+ +costumeSetting('shield')
+ +costumeSetting('weapon')
diff --git a/website/views/shared/modals/death.jade b/website/views/shared/modals/death.jade
index 2c7166fb62..cfdbced16e 100644
--- a/website/views/shared/modals/death.jade
+++ b/website/views/shared/modals/death.jade
@@ -15,22 +15,7 @@ script(type='text/ng-template', id='modals/death.html')
| {{Math.ceil(user.stats.hp)}} / {{::Shared.maxHealth}}
figure.herobox.text-center
.character-sprites
- +costumeSetting('back')
- span(ng-class="'skin_' + profile.preferences.skin + '_sleep'")
- span(class='{{profile.preferences.size}}_shirt_{{profile.preferences.shirt}}')
- +costumeSetting('armor', {prefix: "profile.preferences.size + '_' + "})
- +costumeSetting('back', {suffix: " + '_collar'"})
- +costumeSetting('body')
- span(class='head_0')
- - var hairTypes = ['base', 'bangs', 'mustache', 'beard']
- each type in hairTypes
- span(class='hair_#{type}_{{profile.preferences.hair.#{type}}}_{{profile.preferences.hair.color}}')
- +costumeSetting('eyewear')
- +costumeSetting('head')
- +costumeSetting('headAccessory')
- span(class='hair_flower_{{profile.preferences.hair.flower}}')
- +costumeSetting('shield')
- +costumeSetting('weapon')
+ +generatedAvatar({sleep:true})
span(class='knockout')
.col-md-6
h4(style='margin-top:1.5em')=env.t('dontDespair')
diff --git a/website/views/shared/modals/index.jade b/website/views/shared/modals/index.jade
index 519f20e2d6..8146882046 100644
--- a/website/views/shared/modals/index.jade
+++ b/website/views/shared/modals/index.jade
@@ -13,3 +13,4 @@ include ./rebirth
include ./limited
include ./invite-friends
include ./welcome.jade
+include ./low-health.jade
diff --git a/website/views/shared/modals/low-health.jade b/website/views/shared/modals/low-health.jade
new file mode 100644
index 0000000000..4cc26e8384
--- /dev/null
+++ b/website/views/shared/modals/low-health.jade
@@ -0,0 +1,29 @@
+include ../avatar/generated_avatar
+
+script(type='text/ng-template', id='modals/lowHealth.html')
+ .modal-header
+ h3.text-center=env.t('losingHealthWarning')
+ .modal-body
+ .hero-stats(style='position:absolute; margin-left:9em; width:50%')
+ .meter-label(tooltip=env.t('health'))
+ span.glyphicon.glyphicon-heart
+ .meter.health(tooltip='{{Math.round(user.stats.hp * 100) / 100}}')
+ .bar(ng-style='{"width": Shared.percent(user.stats.hp, Shared.maxHealth)+"%"}')
+ span.meter-text.value
+ | {{Math.ceil(user.stats.hp)}} / {{::Shared.maxHealth}}
+ .herobox.inline-block(style='padding-top:0em; margin-left:16em')
+ .character-sprites(style='display:inline-flex; margin:3em auto')
+ +generatedAvatar
+ p=env.t('losingHealthWarning2')
+ h4=env.t('toRegainHealth')
+ ul
+ li.spaced=env.t('lowHealthTips1')
+ li.spaced=env.t('lowHealthTips2')
+ h4=env.t('losingHealthQuickly')
+ ul
+ li.spaced=env.t('lowHealthTips3')
+ li.spaced=env.t('lowHealthTips4')
+ h4=env.t('goodLuck')
+ .modal-footer(style='margin-top: 0em')
+ a.btn.btn-primary(ng-click='acknowledgeHealthWarning(); $close()')=env.t('ok')
+