Merge branch 'develop' into TheHollidayInn-challenges-clone

Take specHelper off of global scope
This commit is contained in:
Blade Barringer
2015-06-21 18:59:11 -05:00
98 changed files with 8670 additions and 8152 deletions

View File

@@ -2,12 +2,12 @@
margin-left: 1.25em; margin-left: 1.25em;
}*/ }*/
/* Comment out for holiday events */ /* Comment out for holiday events
.npc_ian { .npc_ian {
background: url("/common/img/sprites/npc_ian.gif") no-repeat; background: url("/common/img/sprites/npc_ian.gif") no-repeat;
width: 78px; width: 78px;
height: 135px; height: 135px;
} } */
.Gems { .Gems {
display:inline-block; display:inline-block;

File diff suppressed because one or more lines are too long

View File

@@ -1,216 +1,216 @@
.achievement-alien { .achievement-alien {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -479px; background-position: -1949px -1116px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-alpha { .achievement-alpha {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -182px; background-position: -1924px -819px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-armor { .achievement-armor {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -479px; background-position: -1924px -1116px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-boot { .achievement-boot {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -479px; background-position: -1899px -1116px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-bow { .achievement-bow {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -452px; background-position: -1949px -1089px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-cactus { .achievement-cactus {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -452px; background-position: -1924px -1089px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-cake { .achievement-cake {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -452px; background-position: -1899px -1089px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-cave { .achievement-cave {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -425px; background-position: -1949px -1062px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-coffin { .achievement-coffin {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -425px; background-position: -1924px -1062px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-comment { .achievement-comment {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -425px; background-position: -1899px -1062px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-costumeContest { .achievement-costumeContest {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -398px; background-position: -1949px -1035px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-dilatory { .achievement-dilatory {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -398px; background-position: -1924px -1035px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-firefox { .achievement-firefox {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -398px; background-position: -1899px -1035px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-habitBirthday { .achievement-habitBirthday {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -371px; background-position: -1949px -1008px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-heart { .achievement-heart {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -371px; background-position: -1924px -1008px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-karaoke { .achievement-karaoke {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -371px; background-position: -1899px -1008px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-ninja { .achievement-ninja {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -344px; background-position: -1949px -981px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-nye { .achievement-nye {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -344px; background-position: -1924px -981px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-perfect { .achievement-perfect {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -182px; background-position: -1899px -819px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-rat { .achievement-rat {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -317px; background-position: -1949px -954px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-shield { .achievement-shield {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -317px; background-position: -1924px -954px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-shinySeed { .achievement-shinySeed {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -317px; background-position: -1899px -954px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-snowball { .achievement-snowball {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -290px; background-position: -1949px -927px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-spookDust { .achievement-spookDust {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -290px; background-position: -1924px -927px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-stoikalm { .achievement-stoikalm {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -290px; background-position: -1899px -927px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-sun { .achievement-sun {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -263px; background-position: -1949px -900px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-sword { .achievement-sword {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -263px; background-position: -1924px -900px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-thermometer { .achievement-thermometer {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -263px; background-position: -1899px -900px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-tree { .achievement-tree {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -236px; background-position: -1949px -873px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-triadbingo { .achievement-triadbingo {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -236px; background-position: -1924px -873px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-ultimate-healer { .achievement-ultimate-healer {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -236px; background-position: -1899px -873px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-ultimate-mage { .achievement-ultimate-mage {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -209px; background-position: -1949px -846px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-ultimate-rogue { .achievement-ultimate-rogue {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1924px -209px; background-position: -1924px -846px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-ultimate-warrior { .achievement-ultimate-warrior {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -209px; background-position: -1899px -846px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-valentine { .achievement-valentine {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1949px -182px; background-position: -1949px -819px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
.achievement-wolf { .achievement-wolf {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1899px -344px; background-position: -1899px -981px;
width: 24px; width: 24px;
height: 26px; height: 26px;
} }
@@ -1890,13 +1890,13 @@
} }
.hair_mustache_1_ppurple { .hair_mustache_1_ppurple {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -708px -592px; background-position: -182px -1434px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_mustache_1_ppurple { .customize-option.hair_mustache_1_ppurple {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -733px -607px; background-position: -207px -1449px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
@@ -1938,13 +1938,13 @@
} }
.hair_mustache_1_rainbow { .hair_mustache_1_rainbow {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -546px -1434px; background-position: -708px -592px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_mustache_1_rainbow { .customize-option.hair_mustache_1_rainbow {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -571px -1449px; background-position: -733px -607px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
@@ -3810,431 +3810,515 @@
} }
.hair_bangs_3_rainbow { .hair_bangs_3_rainbow {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -182px -1434px; background-position: -1899px -182px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_bangs_3_rainbow { .customize-option.hair_bangs_3_rainbow {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -207px -1449px; background-position: -1924px -197px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_bangs_3_red { .hair_bangs_3_red {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -637px -979px; background-position: -1899px -273px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_bangs_3_red { .customize-option.hair_bangs_3_red {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -662px -994px; background-position: -1924px -288px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_bangs_3_snowy { .hair_bangs_3_snowy {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -546px -979px; background-position: -1899px -364px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_bangs_3_snowy { .customize-option.hair_bangs_3_snowy {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -571px -994px; background-position: -1924px -379px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_bangs_3_white { .hair_bangs_3_white {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -455px -979px; background-position: -1899px -455px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_bangs_3_white { .customize-option.hair_bangs_3_white {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -480px -994px; background-position: -1924px -470px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_bangs_3_winternight { .hair_bangs_3_winternight {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -364px -979px; background-position: -1899px -546px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_bangs_3_winternight { .customize-option.hair_bangs_3_winternight {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -389px -994px; background-position: -1924px -561px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_bangs_3_winterstar { .hair_bangs_3_winterstar {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -273px -979px; background-position: -1899px -637px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_bangs_3_winterstar { .customize-option.hair_bangs_3_winterstar {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -298px -994px; background-position: -1924px -652px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_bangs_3_yellow { .hair_bangs_3_yellow {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -182px -979px; background-position: -1899px -728px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_bangs_3_yellow { .customize-option.hair_bangs_3_yellow {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -207px -994px; background-position: -1924px -743px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_bangs_3_zombie { .hair_bangs_3_zombie {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -91px -979px; background-position: -546px -1434px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_bangs_3_zombie { .customize-option.hair_bangs_3_zombie {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -116px -994px; background-position: -571px -1449px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_TRUred { .hair_base_10_TRUred {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: 0px -979px; background-position: -637px -979px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_TRUred { .customize-option.hair_base_10_TRUred {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -25px -994px; background-position: -662px -994px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_aurora { .hair_base_10_aurora {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -819px; background-position: -546px -979px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_aurora { .customize-option.hair_base_10_aurora {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -834px; background-position: -571px -994px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_black { .hair_base_10_black {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -728px; background-position: -455px -979px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_black { .customize-option.hair_base_10_black {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -743px; background-position: -480px -994px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_blond { .hair_base_10_blond {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -637px; background-position: -364px -979px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_blond { .customize-option.hair_base_10_blond {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -652px; background-position: -389px -994px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_blue { .hair_base_10_blue {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -546px; background-position: -273px -979px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_blue { .customize-option.hair_base_10_blue {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -561px; background-position: -298px -994px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_brown { .hair_base_10_brown {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -455px; background-position: -182px -979px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_brown { .customize-option.hair_base_10_brown {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -470px; background-position: -207px -994px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_candycane { .hair_base_10_candycane {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -364px; background-position: -91px -979px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_candycane { .customize-option.hair_base_10_candycane {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -379px; background-position: -116px -994px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_candycorn { .hair_base_10_candycorn {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -273px; background-position: 0px -979px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_candycorn { .customize-option.hair_base_10_candycorn {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -288px; background-position: -25px -994px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_festive { .hair_base_10_festive {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -182px; background-position: -989px -819px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_festive { .customize-option.hair_base_10_festive {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -197px; background-position: -1014px -834px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_frost { .hair_base_10_frost {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px -91px; background-position: -989px -728px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_frost { .customize-option.hair_base_10_frost {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -106px; background-position: -1014px -743px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_ghostwhite { .hair_base_10_ghostwhite {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -989px 0px; background-position: -989px -637px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_ghostwhite { .customize-option.hair_base_10_ghostwhite {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1014px -15px; background-position: -1014px -652px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_green { .hair_base_10_green {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -819px -888px; background-position: -989px -546px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_green { .customize-option.hair_base_10_green {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -844px -903px; background-position: -1014px -561px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_halloween { .hair_base_10_halloween {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -728px -888px; background-position: -989px -455px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_halloween { .customize-option.hair_base_10_halloween {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -753px -903px; background-position: -1014px -470px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_holly { .hair_base_10_holly {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -637px -888px; background-position: -989px -364px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_holly { .customize-option.hair_base_10_holly {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -662px -903px; background-position: -1014px -379px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_hollygreen { .hair_base_10_hollygreen {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -546px -888px; background-position: -989px -273px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_hollygreen { .customize-option.hair_base_10_hollygreen {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -571px -903px; background-position: -1014px -288px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_midnight { .hair_base_10_midnight {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -455px -888px; background-position: -989px -182px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_midnight { .customize-option.hair_base_10_midnight {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -480px -903px; background-position: -1014px -197px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_pblue { .hair_base_10_pblue {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -364px -888px; background-position: -989px -91px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_pblue { .customize-option.hair_base_10_pblue {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -389px -903px; background-position: -1014px -106px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_pblue2 { .hair_base_10_pblue2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -273px -888px; background-position: -989px 0px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_pblue2 { .customize-option.hair_base_10_pblue2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -298px -903px; background-position: -1014px -15px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_peppermint { .hair_base_10_peppermint {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -182px -888px; background-position: -819px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_peppermint { .customize-option.hair_base_10_peppermint {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -207px -903px; background-position: -844px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_pgreen { .hair_base_10_pgreen {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -91px -888px; background-position: -728px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_pgreen { .customize-option.hair_base_10_pgreen {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -116px -903px; background-position: -753px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_pgreen2 { .hair_base_10_pgreen2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: 0px -888px; background-position: -637px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_pgreen2 { .customize-option.hair_base_10_pgreen2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -25px -903px; background-position: -662px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_porange { .hair_base_10_porange {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -889px -740px; background-position: -546px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_porange { .customize-option.hair_base_10_porange {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -914px -755px; background-position: -571px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_porange2 { .hair_base_10_porange2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -798px -740px; background-position: -455px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_porange2 { .customize-option.hair_base_10_porange2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -823px -755px; background-position: -480px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_ppink { .hair_base_10_ppink {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -707px -740px; background-position: -364px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_ppink { .customize-option.hair_base_10_ppink {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -732px -755px; background-position: -389px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_ppink2 { .hair_base_10_ppink2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1080px 0px; background-position: -273px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_ppink2 { .customize-option.hair_base_10_ppink2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -1105px -15px; background-position: -298px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_ppurple { .hair_base_10_ppurple {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -910px -979px; background-position: -182px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_ppurple { .customize-option.hair_base_10_ppurple {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -935px -994px; background-position: -207px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_ppurple2 { .hair_base_10_ppurple2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -819px -979px; background-position: -91px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_ppurple2 { .customize-option.hair_base_10_ppurple2 {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -844px -994px; background-position: -116px -903px;
width: 60px; width: 60px;
height: 60px; height: 60px;
} }
.hair_base_10_pumpkin { .hair_base_10_pumpkin {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -728px -979px; background-position: 0px -888px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
.customize-option.hair_base_10_pumpkin { .customize-option.hair_base_10_pumpkin {
background-image: url(spritesmith0.png);
background-position: -25px -903px;
width: 60px;
height: 60px;
}
.hair_base_10_purple {
background-image: url(spritesmith0.png);
background-position: -889px -740px;
width: 90px;
height: 90px;
}
.customize-option.hair_base_10_purple {
background-image: url(spritesmith0.png);
background-position: -914px -755px;
width: 60px;
height: 60px;
}
.hair_base_10_pyellow {
background-image: url(spritesmith0.png);
background-position: -798px -740px;
width: 90px;
height: 90px;
}
.customize-option.hair_base_10_pyellow {
background-image: url(spritesmith0.png);
background-position: -823px -755px;
width: 60px;
height: 60px;
}
.hair_base_10_pyellow2 {
background-image: url(spritesmith0.png);
background-position: -707px -740px;
width: 90px;
height: 90px;
}
.customize-option.hair_base_10_pyellow2 {
background-image: url(spritesmith0.png);
background-position: -732px -755px;
width: 60px;
height: 60px;
}
.hair_base_10_rainbow {
background-image: url(spritesmith0.png);
background-position: -1080px 0px;
width: 90px;
height: 90px;
}
.customize-option.hair_base_10_rainbow {
background-image: url(spritesmith0.png);
background-position: -1105px -15px;
width: 60px;
height: 60px;
}
.hair_base_10_red {
background-image: url(spritesmith0.png);
background-position: -910px -979px;
width: 90px;
height: 90px;
}
.customize-option.hair_base_10_red {
background-image: url(spritesmith0.png);
background-position: -935px -994px;
width: 60px;
height: 60px;
}
.hair_base_10_snowy {
background-image: url(spritesmith0.png);
background-position: -819px -979px;
width: 90px;
height: 90px;
}
.customize-option.hair_base_10_snowy {
background-image: url(spritesmith0.png);
background-position: -844px -994px;
width: 60px;
height: 60px;
}
.hair_base_10_white {
background-image: url(spritesmith0.png);
background-position: -728px -979px;
width: 90px;
height: 90px;
}
.customize-option.hair_base_10_white {
background-image: url(spritesmith0.png); background-image: url(spritesmith0.png);
background-position: -753px -994px; background-position: -753px -994px;
width: 60px; width: 60px;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 306 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 152 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 156 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 KiB

After

Width:  |  Height:  |  Size: 733 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 KiB

After

Width:  |  Height:  |  Size: 366 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -128,6 +128,15 @@
"weaponSpecialSpring2015MageNotes": "Conjure yourself up a carrot with this fancy wand. Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Spring Gear.", "weaponSpecialSpring2015MageNotes": "Conjure yourself up a carrot with this fancy wand. Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Spring Gear.",
"weaponSpecialSpring2015HealerText": "Cat Rattle", "weaponSpecialSpring2015HealerText": "Cat Rattle",
"weaponSpecialSpring2015HealerNotes": "When you wave it, it makes a fascinating clickety noise that would keep ANYONE entertained for hours. Increases Intelligence by <%= int %>. Limited Edition 2015 Spring Gear.", "weaponSpecialSpring2015HealerNotes": "When you wave it, it makes a fascinating clickety noise that would keep ANYONE entertained for hours. Increases Intelligence by <%= int %>. Limited Edition 2015 Spring Gear.",
"weaponSpecialSummer2015RogueText": "Firing Coral",
"weaponSpecialSummer2015RogueNotes": "This relative of fire coral has the ability to propel its venom through the water. Increases Strength by <%= str %>. Limited Edition 2015 Summer Gear.",
"weaponSpecialSummer2015WarriorText": "Sun Swordfish",
"weaponSpecialSummer2015WarriorNotes": "The Sun Swordfish is a fearsome weapon, provided that it can be induced to stop wriggling. Increases Strength by <%= str %>. Limited Edition 2015 Summer Gear.",
"weaponSpecialSummer2015MageText": "Soothsayer Staff",
"weaponSpecialSummer2015MageNotes": "Hidden power glimmers in the jewels of this staff. Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Summer Gear.",
"weaponSpecialSummer2015HealerText": "Wand of the Waves",
"weaponSpecialSummer2015HealerNotes": "Cures seasickness and sea sickness! Increases Intelligence by <%= int %>. Limited Edition 2015 Summer Gear.",
"weaponMystery201411Text": "Pitchfork of Feasting", "weaponMystery201411Text": "Pitchfork of Feasting",
"weaponMystery201411Notes": "Stab your enemies or dig in to your favorite foods - this versatile pitchfork does it all! Confers no benefit. November 2014 Subscriber Item.", "weaponMystery201411Notes": "Stab your enemies or dig in to your favorite foods - this versatile pitchfork does it all! Confers no benefit. November 2014 Subscriber Item.",
@@ -259,6 +268,15 @@
"armorSpecialSpring2015MageNotes": "Your coattails match your cottontail! Increases Intelligence by <%= int %>. Limited Edition 2015 Spring Gear.", "armorSpecialSpring2015MageNotes": "Your coattails match your cottontail! Increases Intelligence by <%= int %>. Limited Edition 2015 Spring Gear.",
"armorSpecialSpring2015HealerText": "Comforting Catsuit", "armorSpecialSpring2015HealerText": "Comforting Catsuit",
"armorSpecialSpring2015HealerNotes": "This soft catsuit is comfortable, and as comforting as mint tea. Increases Constitution by <%= con %>. Limited Edition 2015 Spring Gear.", "armorSpecialSpring2015HealerNotes": "This soft catsuit is comfortable, and as comforting as mint tea. Increases Constitution by <%= con %>. Limited Edition 2015 Spring Gear.",
"armorSpecialSummer2015RogueText": "Ruby Tail",
"armorSpecialSummer2015RogueNotes": "This garment of shimmering scales transforms its wearer into a real Reef Renegade! Increases Perception by <%= per %>. Limited Edition 2015 Summer Gear.",
"armorSpecialSummer2015WarriorText": "Golden Tail",
"armorSpecialSummer2015WarriorNotes": "This garment of shimmering scales transforms its wearer into a real Sunfish Warrior! Increases Constitution by <%= con %>. Limited Edition 2015 Summer Gear.",
"armorSpecialSummer2015MageText": "Soothsayer Robes",
"armorSpecialSummer2015MageNotes": "Hidden power resides in the puffs of these sleeves. Increases Intelligence by <%= int %>. Limited Edition 2015 Summer Gear.",
"armorSpecialSummer2015HealerText": "Sailor's Armor",
"armorSpecialSummer2015HealerNotes": "This armor lets everyone know that you are an honest merchant sailor who would never dream of behaving like a scalawag. Increases Constitution by <%= con %>. Limited Edition 2015 Summer Gear.",
"armorMystery201402Text": "Messenger Robes", "armorMystery201402Text": "Messenger Robes",
"armorMystery201402Notes": "Shimmering and strong, these robes have many pockets to carry letters. Confers no benefit. February 2014 Subscriber Item.", "armorMystery201402Notes": "Shimmering and strong, these robes have many pockets to carry letters. Confers no benefit. February 2014 Subscriber Item.",
@@ -406,6 +424,15 @@
"headSpecialSpring2015HealerText": "Comforting Crown", "headSpecialSpring2015HealerText": "Comforting Crown",
"headSpecialSpring2015HealerNotes": "The pearl at the center of this crown calms and comforts those around it. Increases Intelligence by <%= int %>. Limited Edition 2015 Spring Gear.", "headSpecialSpring2015HealerNotes": "The pearl at the center of this crown calms and comforts those around it. Increases Intelligence by <%= int %>. Limited Edition 2015 Spring Gear.",
"headSpecialSummer2015RogueText": "Renegade Hat",
"headSpecialSummer2015RogueNotes": "This pirate hat fell overboard and has been decorated with scraps of fire coral. Increases Perception by <%= per %>. Limited Edition 2015 Summer Gear.",
"headSpecialSummer2015WarriorText": "Jeweled Oceanic Helm",
"headSpecialSummer2015WarriorNotes": "Crafted of deep-ocean metal by the artisans of Dilatory, this helm is strong and handsome. Increases Strength by <%= str %>. Limited Edition 2015 Summer Gear.",
"headSpecialSummer2015MageText": "Soothsayer Scarf",
"headSpecialSummer2015MageNotes": "Hidden power shines in the threads of this scarf. Increases Perception by <%= per %>. Limited Edition 2015 Summer Gear.",
"headSpecialSummer2015HealerText": "Sailor's Cap",
"headSpecialSummer2015HealerNotes": "With your sailor's cap set firmly on your head, you can navigate even the stormiest seas! Increases Intelligence by <%= int %>. Limited Edition 2015 Summer Gear.",
"headSpecialGaymerxText": "Rainbow Warrior Helm", "headSpecialGaymerxText": "Rainbow Warrior Helm",
"headSpecialGaymerxNotes": "In celebration of pride season and GaymerX, this special helmet is decorated with a radiant, colorful rainbow pattern! GaymerX is a game convention celebrating LGBTQ and gaming and is open to everyone. It takes place at the InterContinental in downtown San Francisco on July 11-13! Confers no benefit.", "headSpecialGaymerxNotes": "In celebration of pride season and GaymerX, this special helmet is decorated with a radiant, colorful rainbow pattern! GaymerX is a game convention celebrating LGBTQ and gaming and is open to everyone. It takes place at the InterContinental in downtown San Francisco on July 11-13! Confers no benefit.",
@@ -517,6 +544,13 @@
"shieldSpecialSpring2015WarriorNotes": "Hurl it at your enemies.... or just hold it, because it will fill up with yummy kibble at dinnertime. Increases Constitution by <%= con %>. Limited Edition 2015 Spring Gear.", "shieldSpecialSpring2015WarriorNotes": "Hurl it at your enemies.... or just hold it, because it will fill up with yummy kibble at dinnertime. Increases Constitution by <%= con %>. Limited Edition 2015 Spring Gear.",
"shieldSpecialSpring2015HealerText": "Patterned Pillow", "shieldSpecialSpring2015HealerText": "Patterned Pillow",
"shieldSpecialSpring2015HealerNotes": "You can rest your head on this soft pillow, or you can wrestle it with your fearsome claws. Rawr! Increases Constitution by <%= con %>. Limited Edition 2015 Spring Gear.", "shieldSpecialSpring2015HealerNotes": "You can rest your head on this soft pillow, or you can wrestle it with your fearsome claws. Rawr! Increases Constitution by <%= con %>. Limited Edition 2015 Spring Gear.",
"shieldSpecialSummer2015RogueText": "Firing Coral",
"shieldSpecialSummer2015RogueNotes": "This relative of fire coral has the ability to propel its venom through the water. Increases Strength by <%= str %>. Limited Edition 2015 Summer Gear.",
"shieldSpecialSummer2015WarriorText": "Sunfish Shield",
"shieldSpecialSummer2015WarriorNotes": "Crafted of deep-ocean metal by the artisans of Dilatory, this shield shines like the sand and the sea. Increases Constitution by <%= con %>. Limited Edition 2015 Summer Gear.",
"shieldSpecialSummer2015HealerText": "Strapping Shield",
"shieldSpecialSummer2015HealerNotes": "Use this shield to bash away bilge rats. Increases Constitution by <%= con %>. Limited Edition 2015 Summer Gear.",
"shieldMystery301405Text": "Clock Shield", "shieldMystery301405Text": "Clock Shield",
"shieldMystery301405Notes": "Time is on your side with this towering clock shield! Confers no benefit. June 3015 Subscriber Item.", "shieldMystery301405Notes": "Time is on your side with this towering clock shield! Confers no benefit. June 3015 Subscriber Item.",
@@ -524,6 +558,7 @@
"shieldArmoireGladiatorShieldText": "Gladiator Shield", "shieldArmoireGladiatorShieldText": "Gladiator Shield",
"shieldArmoireGladiatorShieldNotes": "To be a gladiator you must.... eh, whatever, just bash them with your shield. Increases Constitution by <%= con %> and Strength by <%= str %>. Enchanted Armoire: Gladiator Set (Item 3 of 3).", "shieldArmoireGladiatorShieldNotes": "To be a gladiator you must.... eh, whatever, just bash them with your shield. Increases Constitution by <%= con %> and Strength by <%= str %>. Enchanted Armoire: Gladiator Set (Item 3 of 3).",
"back": "Back Accessory",
"backBase0Text": "No Back Accessory", "backBase0Text": "No Back Accessory",
"backBase0Notes": "No Back Accessory.", "backBase0Notes": "No Back Accessory.",
@@ -541,6 +576,7 @@
"backSpecialWonderconBlackText": "Sneaky Cape", "backSpecialWonderconBlackText": "Sneaky Cape",
"backSpecialWonderconBlackNotes": "Spun of shadows and whispers. Confers no benefit. Special Edition Convention Item.", "backSpecialWonderconBlackNotes": "Spun of shadows and whispers. Confers no benefit. Special Edition Convention Item.",
"body": "Body Accessory",
"bodyBase0Text": "No Body Accessory", "bodyBase0Text": "No Body Accessory",
"bodyBase0Notes": "No Body Accessory.", "bodyBase0Notes": "No Body Accessory.",
@@ -556,6 +592,15 @@
"bodySpecialSummerHealerText": "Coral Collar", "bodySpecialSummerHealerText": "Coral Collar",
"bodySpecialSummerHealerNotes": "A stylish collar of live coral! Confers no benefit. Limited Edition 2014 Summer Gear.", "bodySpecialSummerHealerNotes": "A stylish collar of live coral! Confers no benefit. Limited Edition 2014 Summer Gear.",
"bodySpecialSummer2015RogueText": "Renegade Sash",
"bodySpecialSummer2015RogueNotes": "You can't be a true Renegade without panache... and a sash. Confers no benefit. Limited Edition 2015 Summer Gear.",
"bodySpecialSummer2015WarriorText": "Oceanic Spikes",
"bodySpecialSummer2015WarriorNotes": "Each spike drips jellyfish venom, defending the wearer. Confers no benefit. Limited Edition 2015 Summer Gear.",
"bodySpecialSummer2015MageText": "Golden Buckle",
"bodySpecialSummer2015MageNotes": "This buckle adds no power at all, but it's shiny. Confers no benefit. Limited Edition 2015 Summer Gear.",
"bodySpecialSummer2015HealerText": "Sailor's Neckerchief",
"bodySpecialSummer2015HealerNotes": "Yo ho ho? No, no, no! Confers no benefit. Limited Edition 2015 Summer Gear.",
"headAccessory": "head accessory", "headAccessory": "head accessory",
"accessories": "Accessories", "accessories": "Accessories",
"animalEars": "Animal Ears", "animalEars": "Animal Ears",
@@ -609,6 +654,7 @@
"headAccessoryMystery301405Text": "Headwear Goggles", "headAccessoryMystery301405Text": "Headwear Goggles",
"headAccessoryMystery301405Notes": "\"Goggles are for your eyes,\" they said. \"Nobody wants goggles that you can only wear on your head,\" they said. Hah! You sure showed them! Confers no benefit. August 3015 Subscriber Item.", "headAccessoryMystery301405Notes": "\"Goggles are for your eyes,\" they said. \"Nobody wants goggles that you can only wear on your head,\" they said. Hah! You sure showed them! Confers no benefit. August 3015 Subscriber Item.",
"eyewear": "Eyewear",
"eyewearBase0Text": "No Eyewear", "eyewearBase0Text": "No Eyewear",
"eyewearBase0Notes": "No Eyewear.", "eyewearBase0Notes": "No Eyewear.",

View File

@@ -25,6 +25,7 @@
"seasonalShopTitle": "<%= linkStart %>Seasonal Sorceress<%= linkEnd %>", "seasonalShopTitle": "<%= linkStart %>Seasonal Sorceress<%= linkEnd %>",
"seasonalShopClosedText": "The Seasonal Shop is currently closed!! I don't know where the Seasonal Sorceress is now, but I bet she'll be back during the next <%= linkStart %>Grand Gala<%= linkEnd %>!", "seasonalShopClosedText": "The Seasonal Shop is currently closed!! I don't know where the Seasonal Sorceress is now, but I bet she'll be back during the next <%= linkStart %>Grand Gala<%= linkEnd %>!",
"seasonalShopText": "Welcome to the Seasonal Shop!! We're stocking springtime <a href='http://habitrpg.wikia.com/wiki/Item_Availability' target='_blank'>Seasonal Edition</a> goodies at the moment. Everything here will be available to purchase during the Spring Fling event each year, but we're only open until April 30th, so be sure to stock up now, or you'll have to wait a year to buy these items again!", "seasonalShopText": "Welcome to the Seasonal Shop!! We're stocking springtime <a href='http://habitrpg.wikia.com/wiki/Item_Availability' target='_blank'>Seasonal Edition</a> goodies at the moment. Everything here will be available to purchase during the Spring Fling event each year, but we're only open until April 30th, so be sure to stock up now, or you'll have to wait a year to buy these items again!",
"seasonalShopSummerText": "Welcome to the Seasonal Shop!! We're stocking summertime <a href='http://habitrpg.wikia.com/wiki/Item_Availability' target='_blank'>Seasonal Edition</a> goodies at the moment. Everything here will be available to purchase during the Summer Splash event each year, but we're only open until July 31st, so be sure to stock up now, or you'll have to wait a year to buy these items again!",
"seasonalShopRebirth": "If you've used the Orb of Rebirth, you can repurchase this equipment in the Rewards Column after you unlock the Item Shop. Initially, you'll only be able to purchase the items for your current class (Warrior by default), but fear not, the other class-specific items will become available if you switch to that class.", "seasonalShopRebirth": "If you've used the Orb of Rebirth, you can repurchase this equipment in the Rewards Column after you unlock the Item Shop. Initially, you'll only be able to purchase the items for your current class (Warrior by default), but fear not, the other class-specific items will become available if you switch to that class.",
"candycaneSet": "Candy Cane (Mage)", "candycaneSet": "Candy Cane (Mage)",
"skiSet": "Ski-sassin (Rogue)", "skiSet": "Ski-sassin (Rogue)",
@@ -44,5 +45,9 @@
"mightyBunnySet": "Mighty Bunny (Warrior)", "mightyBunnySet": "Mighty Bunny (Warrior)",
"magicMouseSet": "Magic Mouse (Mage)", "magicMouseSet": "Magic Mouse (Mage)",
"lovingPupSet": "Loving Pup (Healer)", "lovingPupSet": "Loving Pup (Healer)",
"stealthyKittySet": "Stealthy Kitty (Rogue)" "stealthyKittySet": "Stealthy Kitty (Rogue)",
"daringSwashbucklerSet": "Daring Swashbuckler (Warrior)",
"emeraldMermageSet": "Emerald Mermage (Mage)",
"reefSeahealerSet": "Reef Seahealer (Healer)",
"roguishPirateSet": "Roguish Pirate (Rogue)"
} }

View File

@@ -20,6 +20,9 @@ classes = ['warrior', 'rogue', 'healer', 'wizard']
gearTypes = [ 'weapon', 'armor', 'head', 'shield', 'body', 'back', 'headAccessory', 'eyewear'] gearTypes = [ 'weapon', 'armor', 'head', 'shield', 'body', 'back', 'headAccessory', 'eyewear']
events = events =
# IMPORTANT: The end date should be one to two days AFTER the actual end of
# the event, to allow people in different timezones to still buy the
# event gear up until at least the actual end of the event.
winter: {start:'2013-12-31',end:'2014-02-01'} winter: {start:'2013-12-31',end:'2014-02-01'}
birthday: {start:'2013-01-30',end:'2014-02-01'} birthday: {start:'2013-01-30',end:'2014-02-01'}
spring: {start:'2014-03-21',end:'2014-05-01'} spring: {start:'2014-03-21',end:'2014-05-01'}
@@ -28,9 +31,7 @@ events =
fall: {start:'2014-09-21',end:'2014-11-01'} fall: {start:'2014-09-21',end:'2014-11-01'}
winter2015: {start:'2014-12-21',end:'2015-02-02'} winter2015: {start:'2014-12-21',end:'2015-02-02'}
spring2015: {start:'2015-03-20',end:'2015-05-02'} spring2015: {start:'2015-03-20',end:'2015-05-02'}
# IMPORTANT: The end date should be one to two days AFTER the actual end of summer2015: {start:'2015-06-20',end:'2015-08-02'}
# the event, to allow people in different timezones to still buy the
# event gear up until at least the actual end of the event.
api.mystery = api.mystery =
201402: {start:'2014-02-22',end:'2014-02-28', text:'Winged Messenger Set'} 201402: {start:'2014-02-22',end:'2014-02-28', text:'Winged Messenger Set'}
@@ -135,6 +136,11 @@ gear =
spring2015Warrior: event: events.spring2015, specialClass: 'warrior', text: t('weaponSpecialSpring2015WarriorText'), notes: t('weaponSpecialSpring2015WarriorNotes', {str: 15}), value: 90, str: 15 spring2015Warrior: event: events.spring2015, specialClass: 'warrior', text: t('weaponSpecialSpring2015WarriorText'), notes: t('weaponSpecialSpring2015WarriorNotes', {str: 15}), value: 90, str: 15
spring2015Mage: event: events.spring2015, specialClass: 'wizard', twoHanded:true, text: t('weaponSpecialSpring2015MageText'), notes: t('weaponSpecialSpring2015MageNotes', {int: 15, per: 7}), value: 160, int:15, per:7 spring2015Mage: event: events.spring2015, specialClass: 'wizard', twoHanded:true, text: t('weaponSpecialSpring2015MageText'), notes: t('weaponSpecialSpring2015MageNotes', {int: 15, per: 7}), value: 160, int:15, per:7
spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('weaponSpecialSpring2015HealerText'), notes: t('weaponSpecialSpring2015HealerNotes', {int: 9}), value: 90, int: 9 spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('weaponSpecialSpring2015HealerText'), notes: t('weaponSpecialSpring2015HealerNotes', {int: 9}), value: 90, int: 9
# Summer 2015
summer2015Rogue: event: events.summer2015, specialClass: 'rogue', text: t('weaponSpecialSummer2015RogueText'), notes: t('weaponSpecialSummer2015RogueNotes', {str: 8}), value: 80, str: 8
summer2015Warrior: event: events.summer2015, specialClass: 'warrior', text: t('weaponSpecialSummer2015WarriorText'), notes: t('weaponSpecialSummer2015WarriorNotes', {str: 15}), value: 90, str: 15
summer2015Mage: event: events.summer2015, specialClass: 'wizard', twoHanded:true, text: t('weaponSpecialSummer2015MageText'), notes: t('weaponSpecialSummer2015MageNotes', {int: 15, per: 7}), value: 160, int:15, per:7
summer2015Healer: event: events.summer2015, specialClass: 'healer', text: t('weaponSpecialSummer2015HealerText'), notes: t('weaponSpecialSummer2015HealerNotes', {int: 9}), value: 90, int: 9
mystery: mystery:
201411: text: t('weaponMystery201411Text'), notes: t('weaponMystery201411Notes'), mystery:'201411', value: 0 201411: text: t('weaponMystery201411Text'), notes: t('weaponMystery201411Notes'), mystery:'201411', value: 0
201502: text: t('weaponMystery201502Text'), notes: t('weaponMystery201502Notes'), mystery:'201502', value: 0 201502: text: t('weaponMystery201502Text'), notes: t('weaponMystery201502Notes'), mystery:'201502', value: 0
@@ -211,6 +217,11 @@ gear =
spring2015Warrior: event: events.spring2015, specialClass: 'warrior', text: t('armorSpecialSpring2015WarriorText'), notes: t('armorSpecialSpring2015WarriorNotes', {con: 9}), value: 90, con: 9 spring2015Warrior: event: events.spring2015, specialClass: 'warrior', text: t('armorSpecialSpring2015WarriorText'), notes: t('armorSpecialSpring2015WarriorNotes', {con: 9}), value: 90, con: 9
spring2015Mage: event: events.spring2015, specialClass: 'wizard', text: t('armorSpecialSpring2015MageText'), notes: t('armorSpecialSpring2015MageNotes', {int: 9}), value: 90, int: 9 spring2015Mage: event: events.spring2015, specialClass: 'wizard', text: t('armorSpecialSpring2015MageText'), notes: t('armorSpecialSpring2015MageNotes', {int: 9}), value: 90, int: 9
spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('armorSpecialSpring2015HealerText'), notes: t('armorSpecialSpring2015HealerNotes', {con: 15}), value: 90, con: 15 spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('armorSpecialSpring2015HealerText'), notes: t('armorSpecialSpring2015HealerNotes', {con: 15}), value: 90, con: 15
# Summer 2015
summer2015Rogue: event: events.summer2015, specialClass: 'rogue', text: t('armorSpecialSummer2015RogueText'), notes: t('armorSpecialSummer2015RogueNotes', {per: 15}), value: 90, per: 15
summer2015Warrior: event: events.summer2015, specialClass: 'warrior', text: t('armorSpecialSummer2015WarriorText'), notes: t('armorSpecialSummer2015WarriorNotes', {con: 9}), value: 90, con: 9
summer2015Mage: event: events.summer2015, specialClass: 'wizard', text: t('armorSpecialSummer2015MageText'), notes: t('armorSpecialSummer2015MageNotes', {int: 9}), value: 90, int: 9
summer2015Healer: event: events.summer2015, specialClass: 'healer', text: t('armorSpecialSummer2015HealerText'), notes: t('armorSpecialSummer2015HealerNotes', {con: 15}), value: 90, con: 15
# Other # Other
gaymerx: event: events.gaymerx, text: t('armorSpecialGaymerxText'), notes: t('armorSpecialGaymerxNotes'), value: 0 gaymerx: event: events.gaymerx, text: t('armorSpecialGaymerxText'), notes: t('armorSpecialGaymerxNotes'), value: 0
mystery: mystery:
@@ -298,6 +309,11 @@ gear =
spring2015Warrior: event: events.spring2015, specialClass: 'warrior', text: t('headSpecialSpring2015WarriorText'), notes: t('headSpecialSpring2015WarriorNotes', {str: 9}),value: 60,str: 9 spring2015Warrior: event: events.spring2015, specialClass: 'warrior', text: t('headSpecialSpring2015WarriorText'), notes: t('headSpecialSpring2015WarriorNotes', {str: 9}),value: 60,str: 9
spring2015Mage: event: events.spring2015, specialClass: 'wizard', text: t('headSpecialSpring2015MageText'), notes: t('headSpecialSpring2015MageNotes', {per: 7}),value: 60,per: 7 spring2015Mage: event: events.spring2015, specialClass: 'wizard', text: t('headSpecialSpring2015MageText'), notes: t('headSpecialSpring2015MageNotes', {per: 7}),value: 60,per: 7
spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('headSpecialSpring2015HealerText'), notes: t('headSpecialSpring2015HealerNotes', {int: 7}), value: 60, int: 7 spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('headSpecialSpring2015HealerText'), notes: t('headSpecialSpring2015HealerNotes', {int: 7}), value: 60, int: 7
# Summer 2015
summer2015Rogue: event: events.summer2015, specialClass: 'rogue', text: t('headSpecialSummer2015RogueText'), notes: t('headSpecialSummer2015RogueNotes', {per: 9}),value: 60,per: 9
summer2015Warrior: event: events.summer2015, specialClass: 'warrior', text: t('headSpecialSummer2015WarriorText'), notes: t('headSpecialSummer2015WarriorNotes', {str: 9}),value: 60,str: 9
summer2015Mage: event: events.summer2015, specialClass: 'wizard', text: t('headSpecialSummer2015MageText'), notes: t('headSpecialSummer2015MageNotes', {per: 7}),value: 60,per: 7
summer2015Healer: event: events.summer2015, specialClass: 'healer', text: t('headSpecialSummer2015HealerText'), notes: t('headSpecialSummer2015HealerNotes', {int: 7}), value: 60, int: 7
# Other # Other
gaymerx: event: events.gaymerx, text: t('headSpecialGaymerxText'), notes: t('headSpecialGaymerxNotes'), value: 0 gaymerx: event: events.gaymerx, text: t('headSpecialGaymerxText'), notes: t('headSpecialGaymerxNotes'), value: 0
mystery: mystery:
@@ -375,6 +391,10 @@ gear =
spring2015Rogue: event: events.spring2015, specialClass: 'rogue', text: t('shieldSpecialSpring2015RogueText'), notes: t('shieldSpecialSpring2015RogueNotes', {str: 8}), value: 80, str: 8 spring2015Rogue: event: events.spring2015, specialClass: 'rogue', text: t('shieldSpecialSpring2015RogueText'), notes: t('shieldSpecialSpring2015RogueNotes', {str: 8}), value: 80, str: 8
spring2015Warrior: event: events.spring2015, specialClass: 'warrior', text: t('shieldSpecialSpring2015WarriorText'), notes: t('shieldSpecialSpring2015WarriorNotes', {con: 7}), value: 70, con: 7 spring2015Warrior: event: events.spring2015, specialClass: 'warrior', text: t('shieldSpecialSpring2015WarriorText'), notes: t('shieldSpecialSpring2015WarriorNotes', {con: 7}), value: 70, con: 7
spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('shieldSpecialSpring2015HealerText'), notes: t('shieldSpecialSpring2015HealerNotes', {con: 9}), value: 70, con: 9 spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('shieldSpecialSpring2015HealerText'), notes: t('shieldSpecialSpring2015HealerNotes', {con: 9}), value: 70, con: 9
# Summer 2015
summer2015Rogue: event: events.summer2015, specialClass: 'rogue', text: t('shieldSpecialSummer2015RogueText'), notes: t('shieldSpecialSummer2015RogueNotes', {str: 8}), value: 80, str: 8
summer2015Warrior: event: events.summer2015, specialClass: 'warrior', text: t('shieldSpecialSummer2015WarriorText'), notes: t('shieldSpecialSummer2015WarriorNotes', {con: 7}), value: 70, con: 7
summer2015Healer: event: events.summer2015, specialClass: 'healer', text: t('shieldSpecialSummer2015HealerText'), notes: t('shieldSpecialSummer2015HealerNotes', {con: 9}), value: 70, con: 9
mystery: mystery:
301405: text: t('shieldMystery301405Text'), notes: t('shieldMystery301405Notes'), mystery:'301405', value: 0 301405: text: t('shieldMystery301405Text'), notes: t('shieldMystery301405Notes'), mystery:'301405', value: 0
armoire: armoire:
@@ -402,6 +422,11 @@ gear =
# Summer # Summer
summerHealer: event: events.summer, specialClass: 'healer', text: t('bodySpecialSummerHealerText'), notes: t('bodySpecialSummerHealerNotes'), value: 20 summerHealer: event: events.summer, specialClass: 'healer', text: t('bodySpecialSummerHealerText'), notes: t('bodySpecialSummerHealerNotes'), value: 20
summerMage: event: events.summer, specialClass: 'wizard', text: t('bodySpecialSummerMageText'), notes: t('bodySpecialSummerMageNotes'), value: 20 summerMage: event: events.summer, specialClass: 'wizard', text: t('bodySpecialSummerMageText'), notes: t('bodySpecialSummerMageNotes'), value: 20
# Summer 2015
summer2015Healer: event: events.summer2015, specialClass: 'healer', text: t('bodySpecialSummer2015HealerText'), notes: t('bodySpecialSummer2015HealerNotes'), value: 20
summer2015Mage: event: events.summer2015, specialClass: 'wizard', text: t('bodySpecialSummer2015MageText'), notes: t('bodySpecialSummer2015MageNotes'), value: 20
summer2015Rogue: event: events.summer2015, specialClass: 'rogue', text: t('bodySpecialSummer2015RogueText'), notes: t('bodySpecialSummer2015RogueNotes'), value: 20
summer2015Warrior: event: events.summer2015, specialClass: 'warrior', text: t('bodySpecialSummer2015WarriorText'), notes: t('bodySpecialSummer2015WarriorNotes'), value: 20
headAccessory: headAccessory:
base: base:

View File

@@ -698,7 +698,7 @@ api.wrap = (user, main=true) ->
pd.push(item) unless i != -1 pd.push(item) unless i != -1
cb? null, user.pushDevices cb? null, user.pushDevices
# ------ # ------
# Inbox # Inbox
# ------ # ------
@@ -882,6 +882,7 @@ api.wrap = (user, main=true) ->
# the same seed would give one of the first five foods only. # the same seed would give one of the first five foods only.
eligibleEquipment = _.filter(content.gear.flat, ((i)->i.klass is 'armoire' and !user.items.gear.owned[i.key])) eligibleEquipment = _.filter(content.gear.flat, ((i)->i.klass is 'armoire' and !user.items.gear.owned[i.key]))
if !_.isEmpty(eligibleEquipment) and (armoireResult < .6 or !user.flags.armoireOpened) if !_.isEmpty(eligibleEquipment) and (armoireResult < .6 or !user.flags.armoireOpened)
eligibleEquipment.sort() # https://github.com/HabitRPG/habitrpg/issues/5376#issuecomment-111799217
drop = user.fns.randomVal(eligibleEquipment) drop = user.fns.randomVal(eligibleEquipment)
user.items.gear.owned[drop.key] = true user.items.gear.owned[drop.key] = true
user.flags.armoireOpened = true user.flags.armoireOpened = true
@@ -1579,7 +1580,7 @@ api.wrap = (user, main=true) ->
_.merge plan.consecutive, {count:0, offset:0, gemCapExtra:0} _.merge plan.consecutive, {count:0, offset:0, gemCapExtra:0}
user.markModified? 'purchased.plan' user.markModified? 'purchased.plan'
# User is resting at the inn. # User is resting at the inn.
# On cron, buffs are cleared and all dailies are reset without performing damage # On cron, buffs are cleared and all dailies are reset without performing damage
if user.preferences.sleep is true if user.preferences.sleep is true
user.stats.buffs = clearBuffs user.stats.buffs = clearBuffs
@@ -1715,7 +1716,7 @@ api.wrap = (user, main=true) ->
owned = if window? then user.items.gear.owned else user.items.gear.owned.toObject() owned = if window? then user.items.gear.owned else user.items.gear.owned.toObject()
user.achievements.ultimateGearSets ?= {healer: false, wizard: false, rogue: false, warrior: false} user.achievements.ultimateGearSets ?= {healer: false, wizard: false, rogue: false, warrior: false}
content.classes.forEach (klass) -> content.classes.forEach (klass) ->
if user.achievements.ultimateGearSets[klass] is not true if user.achievements.ultimateGearSets[klass] isnt true
user.achievements.ultimateGearSets[klass] = _.reduce ['armor', 'shield', 'head', 'weapon'], (soFarGood, type) -> user.achievements.ultimateGearSets[klass] = _.reduce ['armor', 'shield', 'head', 'weapon'], (soFarGood, type) ->
found = _.find content.gear.tree[type][klass], {last:true} found = _.find content.gear.tree[type][klass], {last:true}
soFarGood and (!found or owned[found.key]==true) #!found only true when weapon is two-handed (mages) soFarGood and (!found or owned[found.key]==true) #!found only true when weapon is two-handed (mages)

View File

@@ -1,13 +1,22 @@
/** // var migrationName = '20150604_ultimateGearSets';
* Created by Sabe on 6/3/2015. // var authorName = 'Sabe'; // in case script author needs to know when their ...
*/ // var authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done
var migrationName = '20150604_ultimateGearSets'; var migrationName = '20150620_ultimateGearSets';
var authorName = process.env.AUTHOR_NAME || 'Sabe'; // in case script author needs to know when their ... var authorName = 'Alys'; // in case script author needs to know when their ...
var authorUuid = process.env.AUTHOR_UUID || '7f14ed62-5408-4e1b-be83-ada62d504931'; //... own data is done var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done
/* /*
* grant the new ultimateGearSets achievement for existing users' collected equipment * grant the new ultimateGearSets achievement for existing users' collected equipment
*
*
* Changed by Alys on 20150620 to assign false values to
* 'achievements.ultimateGearSets' when true values are not appropriate,
* because of https://github.com/HabitRPG/habitrpg/issues/5427
*
* Minimal changes were made so the code isn't as efficient or clean
* as it could be, but it's (hopefully) one-use-only and minimal changes
* means minimal new testing.
*/ */
var dbserver = 'localhost:27017' // FOR TEST DATABASE var dbserver = 'localhost:27017' // FOR TEST DATABASE
@@ -24,25 +33,10 @@ var fields = {
'items.gear.owned':1 'items.gear.owned':1
}; };
// Changes 20150620: All users have to be processed now (non-achievers need
// false values).
var query = { var query = {
// 'auth.timestamps.loggedin':{$lte:new Date('2015-05-22')},
$or: [
{'items.gear.owned.weapon_wizard_6': {$exists: true}},
{'items.gear.owned.armor_wizard_5': {$exists: true}},
{'items.gear.owned.head_wizard_5': {$exists: true}},
{'items.gear.owned.weapon_warrior_6': {$exists: true}},
{'items.gear.owned.armor_warrior_5': {$exists: true}},
{'items.gear.owned.head_warrior_5': {$exists: true}},
{'items.gear.owned.shield_warrior_5': {$exists: true}},
{'items.gear.owned.weapon_healer_6': {$exists: true}},
{'items.gear.owned.armor_healer_5': {$exists: true}},
{'items.gear.owned.head_healer_5': {$exists: true}},
{'items.gear.owned.shield_healer_5': {$exists: true}},
{'items.gear.owned.weapon_rogue_6': {$exists: true}},
{'items.gear.owned.armor_rogue_5': {$exists: true}},
{'items.gear.owned.head_rogue_5': {$exists: true}},
{'items.gear.owned.shield_rogue_6': {$exists: true}}
]
}; };
console.warn('Updating users...'); console.warn('Updating users...');
@@ -58,6 +52,8 @@ dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
var achievements = {}; var achievements = {};
var changeUser = false; var changeUser = false;
// Changes 20150620: 'changeUser' now indicates that the user must have the
// Enchanted Armoire unlocked.
if ( (typeof user.items.gear.owned.weapon_wizard_6 !== 'undefined') if ( (typeof user.items.gear.owned.weapon_wizard_6 !== 'undefined')
&& (typeof user.items.gear.owned.armor_wizard_5 !== 'undefined') && (typeof user.items.gear.owned.armor_wizard_5 !== 'undefined')
&& (typeof user.items.gear.owned.head_wizard_5 !== 'undefined') && (typeof user.items.gear.owned.head_wizard_5 !== 'undefined')
@@ -65,6 +61,11 @@ dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
achievements['wizard'] = true; achievements['wizard'] = true;
changeUser = true; changeUser = true;
} }
else {
// Changes 20150620: false added for all classes (here and below)
achievements['wizard'] = false;
}
if ( (typeof user.items.gear.owned.weapon_warrior_6 !== 'undefined') if ( (typeof user.items.gear.owned.weapon_warrior_6 !== 'undefined')
&& (typeof user.items.gear.owned.armor_warrior_5 !== 'undefined') && (typeof user.items.gear.owned.armor_warrior_5 !== 'undefined')
&& (typeof user.items.gear.owned.head_warrior_5 !== 'undefined') && (typeof user.items.gear.owned.head_warrior_5 !== 'undefined')
@@ -73,6 +74,10 @@ dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
achievements['warrior'] = true; achievements['warrior'] = true;
changeUser = true; changeUser = true;
} }
else {
achievements['warrior'] = false;
}
if ( (typeof user.items.gear.owned.weapon_healer_6 !== 'undefined') if ( (typeof user.items.gear.owned.weapon_healer_6 !== 'undefined')
&& (typeof user.items.gear.owned.armor_healer_5 !== 'undefined') && (typeof user.items.gear.owned.armor_healer_5 !== 'undefined')
&& (typeof user.items.gear.owned.head_healer_5 !== 'undefined') && (typeof user.items.gear.owned.head_healer_5 !== 'undefined')
@@ -81,6 +86,10 @@ dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
achievements['healer'] = true; achievements['healer'] = true;
changeUser = true; changeUser = true;
} }
else {
achievements['healer'] = false;
}
if ( (typeof user.items.gear.owned.weapon_rogue_6 !== 'undefined') if ( (typeof user.items.gear.owned.weapon_rogue_6 !== 'undefined')
&& (typeof user.items.gear.owned.armor_rogue_5 !== 'undefined') && (typeof user.items.gear.owned.armor_rogue_5 !== 'undefined')
&& (typeof user.items.gear.owned.head_rogue_5 !== 'undefined') && (typeof user.items.gear.owned.head_rogue_5 !== 'undefined')
@@ -89,12 +98,17 @@ dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) {
achievements['rogue'] = true; achievements['rogue'] = true;
changeUser = true; changeUser = true;
} }
else {
if (changeUser) { achievements['rogue'] = false;
var set = {'migration':migrationName, 'achievements.ultimateGearSets':achievements, 'flags.armoireEnabled':true};
dbUsers.update({_id:user._id}, {$set:set});
} }
// Changes 20150620: $set is now run for all users.
var set = {'migration':migrationName, 'achievements.ultimateGearSets':achievements};
if (changeUser) { // user has at least one Ultimate Gear achievement
set['flags.armoireEnabled'] = true;
}
dbUsers.update({_id:user._id}, {$set:set});
if (count%progressCount == 0) console.warn(count + ' ' + user._id); if (count%progressCount == 0) console.warn(count + ' ' + user._id);
if (user._id == authorUuid) console.warn(authorName + ' processed'); if (user._id == authorUuid) console.warn(authorName + ' processed');
if (user._id == '9' ) console.warn('lefnire' + ' processed'); if (user._id == '9' ) console.warn('lefnire' + ' processed');

View File

@@ -75,7 +75,7 @@
"www.habitrpg.com" "www.habitrpg.com"
], ],
"engines": { "engines": {
"node": "0.10.x" "node": "0.12.4"
}, },
"scripts": { "scripts": {
"test": "./node_modules/.bin/gulp test", "test": "./node_modules/.bin/gulp test",

114
test/api/score.coffee Normal file
View File

@@ -0,0 +1,114 @@
'use strict'
require("../../website/src/server")
describe "Score", ->
before (done) ->
registerNewUser done, true
context "Todos that did not previously exist", ->
it "creates a completed a todo when using up url", (done) ->
request.post(baseURL + "/user/tasks/withUp/up").send(
type: "todo"
text: "withUp"
).end (res) ->
expectCode res, 200
request.get(baseURL + "/user/tasks/withUp").end (res) ->
upTodo = res.body
expect(upTodo.completed).to.equal true
done()
it "creates an uncompleted todo when using down url", (done) ->
request.post(baseURL + "/user/tasks/withDown/down").send(
type: "todo"
text: "withDown"
).end (res) ->
expectCode res, 200
request.get(baseURL + "/user/tasks/withDown").end (res) ->
downTodo = res.body
expect(downTodo.completed).to.equal false
done()
it "creates a completed a todo overriding the complete parameter when using up url", (done) ->
request.post(baseURL + "/user/tasks/withUpWithComplete/up").send(
type: "todo"
text: "withUpWithComplete"
completed: false
).end (res) ->
expectCode res, 200
request.get(baseURL + "/user/tasks/withUpWithComplete").end (res) ->
upTodo = res.body
expect(upTodo.completed).to.equal true
done()
it "Creates an uncompleted todo overriding the completed parameter when using down url", (done) ->
request.post(baseURL + "/user/tasks/withDownWithUncomplete/down").send(
type: "todo"
text: "withDownWithUncomplete"
completed: true
).end (res) ->
expectCode res, 200
request.get(baseURL + "/user/tasks/withDownWithUncomplete").end (res) ->
downTodo = res.body
expect(downTodo.completed).to.equal false
done()
context "Todo that already exists", ->
it "It completes a todo when using up url", (done) ->
request.post(baseURL + "/user/tasks").send(
type: "todo"
text: "Sample Todo"
).end (res) ->
expectCode res, 200
unCompletedTodo = res.body
expect(unCompletedTodo.completed).to.equal false
request.post(baseURL + "/user/tasks/"+unCompletedTodo._id+"/up").end (res) ->
expectCode res, 200
request.get(baseURL + "/user/tasks/"+unCompletedTodo._id).end (res) ->
unCompletedTodo = res.body
expect(unCompletedTodo.completed).to.equal true
done()
it "It uncompletes a todo when using down url", (done) ->
request.post(baseURL + "/user/tasks").send(
type: "todo"
text: "Sample Todo"
completed: true
).end (res) ->
expectCode res, 200
completedTodo = res.body
expect(completedTodo.completed).to.equal true
request.post(baseURL + "/user/tasks/"+completedTodo._id+"/down").end (res) ->
expectCode res, 200
request.get(baseURL + "/user/tasks/"+completedTodo._id).end (res) ->
completedTodo = res.body
expect(completedTodo.completed).to.equal false
done()
it "Creates and scores up a habit when using up url", (done) ->
upHabit = undefined
request.post(baseURL + "/user/tasks/habitWithUp/up").send(
type: "habit"
text: "testTitle"
completed: true
).end (res) ->
expectCode res, 200
request.get(baseURL + "/user/tasks/habitWithUp").end (res) ->
upHabit = res.body
expect(upHabit.value).to.be.at.least(1)
expect(upHabit.type).to.equal("habit")
done()
it "Creates and scores down a habit when using down url", (done) ->
downHabit = undefined
request.post(baseURL + "/user/tasks/habitWithDown/down").send(
type: "habit"
text: "testTitle"
completed: true
).end (res) ->
expectCode res, 200
request.get(baseURL + "/user/tasks/habitWithDown").end (res) ->
downHabit = res.body
expect(downHabit.value).to.have.at.most(-1)
expect(downHabit.type).to.equal("habit")
done()

View File

@@ -160,7 +160,7 @@ describe "Todos", ->
).end (res) -> ).end (res) ->
expectCode res, 200 expectCode res, 200
body = res.body body = res.body
expect(body).to.be.empty expect(body).to.be.empty
done() done()
it "Does not delete already deleted todo", (done) -> it "Does not delete already deleted todo", (done) ->
@@ -183,4 +183,3 @@ describe "Todos", ->
body = res.body body = res.body
expect(body.err).to.equal "Task not found." expect(body.err).to.equal "Task not found."
done() done()

30
test/common/user.fns.js Normal file
View File

@@ -0,0 +1,30 @@
'use strict';
var shared = require('../../common/script/index.coffee');
shared.i18n.translations = require('../../website/src/i18n.js').translations
require('./test_helper');
describe('User.fns', function() {
describe('.ultimateGear', function() {
it('sets armoirEnabled when partial achievement already achieved', function() {
var user = shared.wrap({
items: { gear: { owned: {
toObject: function() { return {
armor_warrior_5: true,
shield_warrior_5: true,
head_warrior_5: true,
weapon_warrior_6: true
}}
}}},
achievements: {
ultimateGearSets: {}
},
flags: {}
});
user.fns.ultimateGear();
expect(user.flags.armoireEnabled).to.equal(true);
});
});
});

View File

@@ -4,13 +4,8 @@ describe('AppJS', function() {
describe('Automatic page refresh', function(){ describe('Automatic page refresh', function(){
var clock; var clock;
beforeEach(function () { beforeEach(function () {
clock = sinon.useFakeTimers(); clock = sandbox.useFakeTimers();
sinon.stub(window, "refresher", function(){return true}); sandbox.stub(window, "refresher", function(){return true});
});
afterEach(function () {
clock.restore();
window.refresher.restore();
}); });
it('should not call refresher if idle time is less than 6 hours', function() { it('should not call refresher if idle time is less than 6 hours', function() {

View File

@@ -10,8 +10,8 @@ describe('Auth Controller', function() {
scope = $rootScope.$new(); scope = $rootScope.$new();
scope.loginUsername = 'user'; scope.loginUsername = 'user';
scope.loginPassword = 'pass'; scope.loginPassword = 'pass';
$window = { location: { href: ""}, alert: sinon.spy() }; $window = { location: { href: ""}, alert: sandbox.spy() };
user = { user: {}, authenticate: sinon.spy() }; user = { user: {}, authenticate: sandbox.spy() };
ctrl = $controller('AuthCtrl', {$scope: scope, $window: $window, User: user}); ctrl = $controller('AuthCtrl', {$scope: scope, $window: $window, User: user});
})); }));
@@ -20,16 +20,16 @@ describe('Auth Controller', function() {
$httpBackend.expectPOST('/api/v2/user/auth/local').respond({id: 'abc', token: 'abc'}); $httpBackend.expectPOST('/api/v2/user/auth/local').respond({id: 'abc', token: 'abc'});
scope.auth(); scope.auth();
$httpBackend.flush(); $httpBackend.flush();
sinon.assert.calledOnce(user.authenticate); expect(user.authenticate).to.be.calledOnce;
sinon.assert.notCalled($window.alert); expect($window.alert).to.not.be.called;
}); });
it('should not log in users with incorrect uname / pass', function() { it('should not log in users with incorrect uname / pass', function() {
$httpBackend.expectPOST('/api/v2/user/auth/local').respond(404, ''); $httpBackend.expectPOST('/api/v2/user/auth/local').respond(404, '');
scope.auth(); scope.auth();
$httpBackend.flush(); $httpBackend.flush();
sinon.assert.notCalled(user.authenticate); expect(user.authenticate).to.not.be.called;
sinon.assert.calledOnce($window.alert); expect($window.alert).to.be.calledOnce;
}); });
}); });

View File

@@ -188,10 +188,10 @@ describe('Challenges Controller', function() {
var challengeToClone = { var challengeToClone = {
name: 'copyChallenge', name: 'copyChallenge',
description: 'copyChallenge', description: 'copyChallenge',
habits: [newHabit()], habits: [specHelper.newHabit()],
dailys: [newDaily()], dailys: [specHelper.newDaily()],
todos: [newTodo()], todos: [specHelper.newTodo()],
rewards: [newReward()], rewards: [specHelper.newReward()],
leader: 'unique-user-id', leader: 'unique-user-id',
group: { _id: "copyGroup" }, group: { _id: "copyGroup" },
timestamp: new Date("October 13, 2014 11:13:00"), timestamp: new Date("October 13, 2014 11:13:00"),

View File

@@ -30,7 +30,7 @@ describe('Groups Controller', function() {
party.type = 'party'; party.type = 'party';
party.members = []; // Ensure we wouldn't pass automatically. party.members = []; // Ensure we wouldn't pass automatically.
var partyStub = sinon.stub(groups,"party", function() { var partyStub = sandbox.stub(groups,"party", function() {
return party; return party;
}); });
@@ -44,7 +44,7 @@ describe('Groups Controller', function() {
guild.type = 'guild'; guild.type = 'guild';
guild.members.push(user._id); guild.members.push(user._id);
var myGuilds = sinon.stub(groups,"myGuilds", function() { var myGuilds = sandbox.stub(groups,"myGuilds", function() {
return [guild]; return [guild];
}); });
@@ -58,7 +58,7 @@ describe('Groups Controller', function() {
guild._id = "unique-guild-id"; guild._id = "unique-guild-id";
guild.type = 'guild'; guild.type = 'guild';
var myGuilds = sinon.stub(groups,"myGuilds", function() { var myGuilds = sandbox.stub(groups,"myGuilds", function() {
return []; return [];
}); });
@@ -98,7 +98,7 @@ describe("Chat Controller", function() {
name: "Princess Bride" name: "Princess Bride"
}; };
var modalSpy = sinon.spy($rootScope, "openModal"); var modalSpy = sandbox.spy($rootScope, "openModal");
var message = { var message = {
uuid: 'the-dread-pirate-roberts', uuid: 'the-dread-pirate-roberts',
user: 'Wesley', user: 'Wesley',
@@ -120,7 +120,7 @@ describe("Chat Controller", function() {
name: "Princess Bride" name: "Princess Bride"
}; };
var modalSpy = sinon.spy($rootScope, "openModal"); var modalSpy = sandbox.spy($rootScope, "openModal");
var message = { var message = {
uuid: 'system', uuid: 'system',
text: 'Wesley attacked the ROUS in the Fire Swamp' text: 'Wesley attacked the ROUS in the Fire Swamp'
@@ -221,7 +221,7 @@ describe("Autocomplete controller", function() {
describe("performCompletion", function() { describe("performCompletion", function() {
it('triggers autoComplete', function() { it('triggers autoComplete', function() {
scope.autoComplete = sinon.spy(); scope.autoComplete = sandbox.spy();
var msg = {user: "boo"}; // scope.autoComplete only cares about user var msg = {user: "boo"}; // scope.autoComplete only cares about user
scope.query = {text: "b"}; scope.query = {text: "b"};
@@ -247,7 +247,7 @@ describe("Autocomplete controller", function() {
describe("chatChanged", function() { describe("chatChanged", function() {
it('if a new chat arrives, the new user name is extracted', function() { it('if a new chat arrives, the new user name is extracted', function() {
var chatChanged = sinon.spy(scope, 'chatChanged'); var chatChanged = sandbox.spy(scope, 'chatChanged');
scope.$watch('group.chat',scope.chatChanged); // reinstantiate watch so spy works scope.$watch('group.chat',scope.chatChanged); // reinstantiate watch so spy works
scope.$digest(); // trigger watch scope.$digest(); // trigger watch
@@ -269,11 +269,11 @@ describe("CopyMessageModal controller", function() {
user = specHelper.newUser(); user = specHelper.newUser();
user._id = "unique-user-id"; user._id = "unique-user-id";
user.ops = { user.ops = {
addTask: sinon.spy() addTask: sandbox.spy()
}; };
scope = $rootScope.$new(); scope = $rootScope.$new();
scope.$close = sinon.spy(); scope.$close = sandbox.spy();
$controller = _$controller_; $controller = _$controller_;
@@ -283,7 +283,7 @@ describe("CopyMessageModal controller", function() {
ctrl = $controller('CopyMessageModalCtrl', {$scope: scope, User: {user: user}}); ctrl = $controller('CopyMessageModalCtrl', {$scope: scope, User: {user: user}});
Notification = _Notification_; Notification = _Notification_;
Notification.text = sinon.spy(); Notification.text = sandbox.spy();
}); });
}); });

View File

@@ -22,15 +22,12 @@ describe('Hall of Heroes Controller', function() {
}); });
it('populates contributor input with selected hero id', function(){ it('populates contributor input with selected hero id', function(){
var loadHero = sinon.spy(scope, "loadHero"); var loadHero = sandbox.spy(scope, "loadHero");
var scrollTo = sinon.spy(window, "scrollTo"); var scrollTo = sandbox.spy(window, "scrollTo");
scope.populateContributorInput(user._id); scope.populateContributorInput(user._id);
expect(scope._heroID).to.eql(user._id); expect(scope._heroID).to.eql(user._id);
expect(loadHero.callCount).to.eql(1); expect(loadHero.callCount).to.eql(1);
expect(scrollTo.callCount).to.eql(1); expect(scrollTo.callCount).to.eql(1);
scope.loadHero.restore();
window.scrollTo.restore();
}); });
}); });

View File

@@ -26,13 +26,8 @@ describe('Header Controller', function() {
context('inviteOrStartParty', function(){ context('inviteOrStartParty', function(){
beforeEach(function(){ beforeEach(function(){
sinon.stub($location, 'path'); sandbox.stub($location, 'path');
sinon.stub($rootScope, 'openModal'); sandbox.stub($rootScope, 'openModal');
});
afterEach(function(){
$location.path.restore();
$rootScope.openModal.restore();
}); });
it('redirects to party page if user does not have a party', function(){ it('redirects to party page if user does not have a party', function(){

View File

@@ -24,13 +24,13 @@ describe('Root Controller', function() {
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
notification = Notification; notification = Notification;
sinon.stub(notification, 'text'); sandbox.stub(notification, 'text');
sinon.stub(notification, 'markdown'); sandbox.stub(notification, 'markdown');
user = specHelper.newUser(); user = specHelper.newUser();
User = {user: user}; User = {user: user};
User.save = sinon.spy(); User.save = sandbox.spy();
User.sync = sinon.spy(); User.sync = sandbox.spy();
$httpBackend.whenGET(/partials/).respond(); $httpBackend.whenGET(/partials/).respond();
@@ -38,13 +38,6 @@ describe('Root Controller', function() {
}); });
}); });
afterEach(function() {
notification.text.reset();
notification.markdown.reset();
User.save.reset();
User.sync.reset();
});
describe('contribText', function(){ describe('contribText', function(){
it('shows contributor level text', function(){ it('shows contributor level text', function(){
expect(scope.contribText()).to.eql(undefined); expect(scope.contribText()).to.eql(undefined);

View File

@@ -16,7 +16,7 @@ describe('focusMe Directive', function() {
it('focuses the element when appended to the DOM', function() { it('focuses the element when appended to the DOM', function() {
inject(function($timeout) { inject(function($timeout) {
var focusSpy = sinon.spy(); var focusSpy = sandbox.spy();
element.appendTo(document.body); element.appendTo(document.body);
element.on('focus', focusSpy); element.on('focus', focusSpy);

View File

@@ -11,7 +11,7 @@ describe('fromNow Directive', function() {
scope = $rootScope.$new(); scope = $rootScope.$new();
scope.message = {}; scope.message = {};
sinon.stub(window, 'moment').returns({ sandbox.stub(window, 'moment').returns({
fromNow: function() { return fromNow }, fromNow: function() { return fromNow },
diff: function() { return diff } diff: function() { return diff }
}); });

View File

@@ -1,10 +1,11 @@
'use strict'; 'use strict';
describe('Task Ordering Filters', function() { describe('Task Ordering Filters', function() {
var filter var filter, orderBySpy;
, orderBySpy = sinon.spy();
beforeEach(function() { beforeEach(function() {
orderBySpy = sandbox.spy();
module(function($provide) { module(function($provide) {
$provide.value('orderByFilter', orderBySpy); $provide.value('orderByFilter', orderBySpy);
}); });

View File

@@ -3,13 +3,11 @@
describe('notificationServices', function() { describe('notificationServices', function() {
var notification; var notification;
before(function(){ beforeEach(function() {
sinon.stub($, 'pnotify', function(){ sandbox.stub($, 'pnotify', function(){
return { click: function(){}} return { click: function(){}}
}); });
});
beforeEach(function() {
module(function($provide){ module(function($provide){
$provide.value('User', {}); $provide.value('User', {});
}); });
@@ -19,10 +17,6 @@ describe('notificationServices', function() {
}); });
}); });
afterEach(function() {
$.pnotify.reset();
});
it('notifies coins amount', function() { it('notifies coins amount', function() {
var SILVER_COIN = "<span class='notification-icon shop_silver'></span>"; var SILVER_COIN = "<span class='notification-icon shop_silver'></span>";
var GOLD_COIN = "<span class='notification-icon shop_gold'></span>"; var GOLD_COIN = "<span class='notification-icon shop_gold'></span>";

View File

@@ -22,7 +22,7 @@ describe('Tasks Service', function() {
var task; var task;
beforeEach(function(){ beforeEach(function(){
task = newTask(); task = specHelper.newTask();
}); });
it('toggles the _editing property', function() { it('toggles the _editing property', function() {
@@ -71,7 +71,7 @@ describe('Tasks Service', function() {
context('generic tasks', function() { context('generic tasks', function() {
it('clones the data from a task', function() { it('clones the data from a task', function() {
var task = newTask(); var task = specHelper.newTask();
var clonedTask = tasks.cloneTask(task); var clonedTask = tasks.cloneTask(task);
expect(clonedTask.text).to.eql(task.text); expect(clonedTask.text).to.eql(task.text);
@@ -83,7 +83,7 @@ describe('Tasks Service', function() {
}); });
it('does not clone original task\'s id or _id', function() { it('does not clone original task\'s id or _id', function() {
var task = newTask(); var task = specHelper.newTask();
var clonedTask = tasks.cloneTask(task); var clonedTask = tasks.cloneTask(task);
expect(clonedTask.id).to.exist; expect(clonedTask.id).to.exist;
@@ -93,7 +93,7 @@ describe('Tasks Service', function() {
}); });
it('does not clone original task\'s dateCreated attribute', function() { it('does not clone original task\'s dateCreated attribute', function() {
var task = newTask({ var task = specHelper.newTask({
dateCreated: new Date(2014, 5, 1, 1, 1, 1, 1), dateCreated: new Date(2014, 5, 1, 1, 1, 1, 1),
}); });
var clonedTask = tasks.cloneTask(task); var clonedTask = tasks.cloneTask(task);
@@ -103,7 +103,7 @@ describe('Tasks Service', function() {
}); });
it('does not clone original task\'s value', function() { it('does not clone original task\'s value', function() {
var task = newTask({ var task = specHelper.newTask({
value: 130 value: 130
}); });
var clonedTask = tasks.cloneTask(task); var clonedTask = tasks.cloneTask(task);
@@ -116,7 +116,7 @@ describe('Tasks Service', function() {
context('Habits', function() { context('Habits', function() {
it('clones a habit', function() { it('clones a habit', function() {
var habit = newHabit({ var habit = specHelper.newHabit({
up: true, up: true,
down: false down: false
}); });
@@ -131,7 +131,7 @@ describe('Tasks Service', function() {
context('Dailys', function() { context('Dailys', function() {
it('clones a daily', function() { it('clones a daily', function() {
var daily = newDaily({ var daily = specHelper.newDaily({
frequency: 'daily', frequency: 'daily',
everyX: 3, everyX: 3,
startDate: new Date(2014, 5, 1, 1, 1, 1, 1), startDate: new Date(2014, 5, 1, 1, 1, 1, 1),
@@ -146,7 +146,7 @@ describe('Tasks Service', function() {
}); });
it('does not clone streak', function() { it('does not clone streak', function() {
var daily = newDaily({ var daily = specHelper.newDaily({
streak: 11 streak: 11
}); });
@@ -159,14 +159,14 @@ describe('Tasks Service', function() {
context('Todos', function() { context('Todos', function() {
it('clones a todo', function() { it('clones a todo', function() {
var todo = newTodo(); var todo = specHelper.newTodo();
var clonedTodo = tasks.cloneTask(todo); var clonedTodo = tasks.cloneTask(todo);
expect(clonedTodo.type).to.eql('todo'); expect(clonedTodo.type).to.eql('todo');
}); });
it('does not clone due date', function() { it('does not clone due date', function() {
var todo = newTodo({ var todo = specHelper.newTodo({
date: '2015-06-20' date: '2015-06-20'
}); });
@@ -176,7 +176,7 @@ describe('Tasks Service', function() {
}); });
it('does not clone date completed', function() { it('does not clone date completed', function() {
var todo = newTodo({ var todo = specHelper.newTodo({
dateCompleted: new Date() dateCompleted: new Date()
}); });
@@ -189,14 +189,14 @@ describe('Tasks Service', function() {
context('Rewards', function() { context('Rewards', function() {
it('clones a reward', function() { it('clones a reward', function() {
var reward = newReward(); var reward = specHelper.newReward();
var clonedReward = tasks.cloneTask(reward); var clonedReward = tasks.cloneTask(reward);
expect(clonedReward.type).to.eql('reward'); expect(clonedReward.type).to.eql('reward');
}); });
it('does clone a reward\'s value', function() { it('does clone a reward\'s vaue', function() {
var reward = newReward({ var reward = specHelper.newReward({
value: 20 value: 20
}); });
var clonedReward = tasks.cloneTask(reward); var clonedReward = tasks.cloneTask(reward);
@@ -207,7 +207,7 @@ describe('Tasks Service', function() {
context('complete', function() { context('complete', function() {
it('does not clone completed status', function() { it('does not clone completed status', function() {
var todo = newTodo({ var todo = specHelper.newTodo({
completed: true completed: true
}); });
@@ -220,7 +220,7 @@ describe('Tasks Service', function() {
context('history', function() { context('history', function() {
it('does not clone history', function() { it('does not clone history', function() {
var habit = newHabit({ var habit = specHelper.newHabit({
history: [ history: [
{ date: Date.now, value: 3.1 }, { date: Date.now, value: 3.1 },
{ date: Date.now, value: 2.7 } { date: Date.now, value: 2.7 }
@@ -236,7 +236,7 @@ describe('Tasks Service', function() {
context('checklists', function() { context('checklists', function() {
it('clones checklist text', function() { it('clones checklist text', function() {
var todo = newTodo({ var todo = specHelper.newTodo({
checklist: [{ checklist: [{
completed: true, completed: true,
text: 'checklist 1', text: 'checklist 1',
@@ -255,7 +255,7 @@ describe('Tasks Service', function() {
}); });
it('does not clone complete or id attribute of checklist', function() { it('does not clone complete or id attribute of checklist', function() {
var todo = newTodo({ var todo = specHelper.newTodo({
checklist: [{ checklist: [{
completed: true, completed: true,
text: 'checklist 1', text: 'checklist 1',

View File

@@ -7,7 +7,7 @@ describe('userServices', function() {
beforeEach(function(){ beforeEach(function(){
module(function($provide){ module(function($provide){
$window = {href: '', alert: sinon.spy(), location: {search: '', pathname: ''}}; $window = {href: '', alert: sandbox.spy(), location: {search: '', pathname: ''}};
$provide.value('$window', $window); $provide.value('$window', $window);
}); });

View File

@@ -1,144 +1,156 @@
beforeEach(module('habitrpg')); beforeEach(module('habitrpg'));
function newUser() { var sandbox;
var buffs = {per:0, int:0, con:0, str:0, stealth: 0, streaks: false}; beforeEach(function() {
user = { sandbox = sinon.sandbox.create();
auth:{timestamps: {}}, });
stats: {str:1, con:1, per:1, int:1, mp: 32, class: 'warrior', buffs: buffs, gp: 0},
items:{
lastDrop:{count: 0},
hatchingPotions: {},
eggs: {},
food: {},
pets: {},
mounts: {},
gear: {equipped: {}, costume: {}, owned: {}},
},
party: {
quest: {
progress: {down: 0}
}
},
preferences: {},
dailys: [],
todos: [],
rewards: [],
flags: {},
filters: {},
achievements: {},
};
return user;
}
function newGroup(leader) { afterEach(function() {
var quest = { progress: { }, active: false }; sandbox.restore();
group = { });
"leader" : leader,
"quest" : quest,
"memberCount" : 1,
"chat" : [],
"privacy" : "public",
"invites" : [],
"members" : [
leader
]
};
return group;
}
function newTask(overrides) { var specHelper = {};
var task = {
id: 'task-id',
_id: 'task-id',
dateCreated: Date.now,
text: 'task text',
notes: 'task notes',
tags: { },
value: 0,
priority: 1,
attribute: 'str',
challenge: { }
};
for(var key in overrides) { (function(){
task[key] = overrides[key];
specHelper.newUser = newUser;
specHelper.newGroup = newGroup;
specHelper.newTask = newTask;
specHelper.newHabit = newHabit;
specHelper.newDaily = newDaily;
specHelper.newTodo = newTodo;
specHelper.newReward = newReward;
function newUser() {
var buffs = {per:0, int:0, con:0, str:0, stealth: 0, streaks: false};
user = {
auth:{timestamps: {}},
stats: {str:1, con:1, per:1, int:1, mp: 32, class: 'warrior', buffs: buffs, gp: 0},
items:{
lastDrop:{count: 0},
hatchingPotions: {},
eggs: {},
food: {},
pets: {},
mounts: {},
gear: {equipped: {}, costume: {}, owned: {}},
},
party: {
quest: {
progress: {down: 0}
}
},
preferences: {},
dailys: [],
todos: [],
rewards: [],
flags: {},
filters: {},
achievements: {},
};
return user;
} }
return task; function newGroup(leader) {
} var quest = { progress: { }, active: false };
group = {
function newHabit(overrides) { "leader" : leader,
var habit = newTask(); "quest" : quest,
habit.type = 'habit'; "memberCount" : 1,
habit.history = []; "chat" : [],
habit.up = true; "privacy" : "public",
habit.down = true; "invites" : [],
"members" : [
for(var key in overrides) { leader
habit[key] = overrides[key]; ]
};
return group;
} }
return habit; function newTask(overrides) {
} var task = {
id: 'task-id',
_id: 'task-id',
dateCreated: Date.now,
text: 'task text',
notes: 'task notes',
tags: { },
value: 0,
priority: 1,
attribute: 'str',
challenge: { }
};
function newDaily(overrides) { for(var key in overrides) {
var daily = newTask(); task[key] = overrides[key];
daily.type = 'daily'; }
daily.frequency = 'weekly';
daily.repeat = {
m: true,
t: true,
w: true,
th: true,
f: true,
s: true,
su: true
};
daily.startDate = Date.now;
daily.history = [];
daily.completed = false;
daily.collapseChecklist = false;
daily.checklist = [];
daily.streak = 0;
for(var key in overrides) { return task;
daily[key] = overrides[key];
} }
return daily; function newHabit(overrides) {
} var habit = newTask();
habit.type = 'habit';
habit.history = [];
habit.up = true;
habit.down = true;
function newTodo(overrides) { for(var key in overrides) {
var todo = newTask(); habit[key] = overrides[key];
todo.type = 'todo'; }
todo.completed = false;
todo.collapseChecklist = false;
todo.checklist = [];
for(var key in overrides) { return habit;
todo[key] = overrides[key];
} }
return todo; function newDaily(overrides) {
} var daily = newTask();
daily.type = 'daily';
daily.frequency = 'weekly';
daily.repeat = {
m: true,
t: true,
w: true,
th: true,
f: true,
s: true,
su: true
};
daily.startDate = Date.now;
daily.history = [];
daily.completed = false;
daily.collapseChecklist = false;
daily.checklist = [];
daily.streak = 0;
function newReward(overrides) { for(var key in overrides) {
var reward = newTask(); daily[key] = overrides[key];
reward.type = 'reward'; }
for(var key in overrides) { return daily;
reward[key] = overrides[key];
} }
return reward; function newTodo(overrides) {
} var todo = newTask();
todo.type = 'todo';
todo.completed = false;
todo.collapseChecklist = false;
todo.checklist = [];
specHelper = { for(var key in overrides) {
newUser: newUser, todo[key] = overrides[key];
newGroup: newGroup, }
newTask: newTask,
newHabit: newHabit, return todo;
newDaily: newDaily, }
newTodo: newTodo,
newRward: newReward function newReward(overrides) {
} var reward = newTask();
reward.type = 'reward';
for(var key in overrides) {
reward[key] = overrides[key];
}
return reward;
}
})();

View File

@@ -214,9 +214,10 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
var gems = User.user.balance * 4; var gems = User.user.balance * 4;
var string = (type == 'weapon') ? window.env.t('weapon') : (type == 'armor') ? window.env.t('armor') : (type == 'head') ? window.env.t('headgear') : (type == 'shield') ? window.env.t('offhand') : (type == 'headAccessory') ? window.env.t('headAccessory') : (type == 'hatchingPotions') ? window.env.t('hatchingPotion') : (type == 'eggs') ? window.env.t('eggSingular') : (type == 'quests') ? window.env.t('quest') : (item.key == 'Saddle') ? window.env.t('foodSaddleText').toLowerCase() : type; // FIXME this is ugly but temporary, once the purchase modal is done this will be removed var string = (type == 'weapon') ? window.env.t('weapon') : (type == 'armor') ? window.env.t('armor') : (type == 'head') ? window.env.t('headgear') : (type == 'shield') ? window.env.t('offhand') : (type == 'back') ? window.env.t('back') : (type == 'body') ? window.env.t('body') : (type == 'headAccessory') ? window.env.t('headAccessory') : (type == 'eyewear') ? window.env.t('eyewear') : (type == 'hatchingPotions') ? window.env.t('hatchingPotion') : (type == 'eggs') ? window.env.t('eggSingular') : (type == 'quests') ? window.env.t('quest') : (item.key == 'Saddle') ? window.env.t('foodSaddleText').toLowerCase() : type; // FIXME this is ugly but temporary, once the purchase modal is done this will be removed
var price = ((((item.specialClass == "wizard") && (item.type == "weapon")) || item.gearSet == "animal") + 1); var price = ((((item.specialClass == "wizard") && (item.type == "weapon")) || item.gearSet == "animal") + 1);
if (type == 'weapon' || type == 'armor' || type == 'head' || type == 'shield' || type == 'headAccessory') { if (type == 'weapon' || type == 'armor' || type == 'head' || type == 'shield' || type == 'headAccessory' || type == 'body' || type == 'back' || type == 'eyewear' ) {
if (User.user.items.gear.owned[item.key]) { if (User.user.items.gear.owned[item.key]) {
if (User.user.preferences.costume) return User.user.ops.equip({params:{type: 'costume', key: item.key}}); if (User.user.preferences.costume) return User.user.ops.equip({params:{type: 'costume', key: item.key}});
else { else {

View File

@@ -1,3 +1,4 @@
'use strict';
// @see ../routes for routing // @see ../routes for routing
function clone(a) { function clone(a) {
@@ -195,7 +196,7 @@ api.create = function(req, res, next) {
group = user = null; group = user = null;
}); });
}else{ } else{
async.waterfall([ async.waterfall([
function(cb){ function(cb){
Group.findOne({type:'party',members:{$in:[user._id]}},cb); Group.findOne({type:'party',members:{$in:[user._id]}},cb);
@@ -210,8 +211,8 @@ api.create = function(req, res, next) {
], function(err, populated){ ], function(err, populated){
if (err == 'Already in a party, try refreshing.') return res.json(400,{err:err}); if (err == 'Already in a party, try refreshing.') return res.json(400,{err:err});
if (err) return next(err); if (err) return next(err);
return res.json(populated);
group = user = null; group = user = null;
return res.json(populated);
}) })
} }
} }
@@ -285,7 +286,7 @@ api.postChat = function(req, res, next) {
group.save(function(err, saved){ group.save(function(err, saved){
if (err) return next(err); if (err) return next(err);
return chatUpdated ? res.json({chat: group.chat}) : res.json({message: saved.chat[0]}); chatUpdated ? res.json({chat: group.chat}) : res.json({message: saved.chat[0]});
group = chatUpdated = null; group = chatUpdated = null;
}); });
} }
@@ -549,8 +550,8 @@ api.leave = function(req, res, next) {
} }
],function(err){ ],function(err){
if (err) return next(err); if (err) return next(err);
return res.send(204);
user = group = keep = null; user = group = keep = null;
return res.send(204);
}) })
} }
@@ -786,8 +787,8 @@ api.removeMember = function(req, res, next){
}); });
}else{ }else{
return res.json(400, {err: "User not found among group's members!"});
group = uuid = null; group = uuid = null;
return res.json(400, {err: "User not found among group's members!"});
} }
} }
@@ -795,7 +796,7 @@ api.removeMember = function(req, res, next){
// Quests // Quests
// ------------------------------------ // ------------------------------------
questStart = function(req, res, next) { function questStart(req, res, next) {
var group = res.locals.group; var group = res.locals.group;
var force = req.query.force; var force = req.query.force;

View File

@@ -99,9 +99,11 @@ api.score = function(req, res, next) {
text: req.body && req.body.text, text: req.body && req.body.text,
notes: (req.body && req.body.notes) || "This task was created by a third-party service. Feel free to edit, it won't harm the connection to that service. Additionally, multiple services may piggy-back off this task." notes: (req.body && req.body.notes) || "This task was created by a third-party service. Feel free to edit, it won't harm the connection to that service. Additionally, multiple services may piggy-back off this task."
}; };
task = user.ops.addTask({body:task});
if (task.type === 'daily' || task.type === 'todo') if (task.type === 'daily' || task.type === 'todo')
task.completed = direction === 'up'; task.completed = direction === 'up';
task = user.ops.addTask({body:task});
} }
var delta = user.ops.score({params:{id:task.id, direction:direction}, language: req.language}); var delta = user.ops.score({params:{id:task.id, direction:direction}, language: req.language});

View File

@@ -296,7 +296,6 @@ var UserSchema = new Schema({
} }
}, },
preferences: { preferences: {
armorSet: String,
dayStart: {type:Number, 'default': 0, min: 0, max: 23}, dayStart: {type:Number, 'default': 0, min: 0, max: 23},
size: {type:String, enum: ['broad','slim'], 'default': 'slim'}, size: {type:String, enum: ['broad','slim'], 'default': 'slim'},
hair: { hair: {

View File

@@ -28,32 +28,28 @@ script(type='text/ng-template', id='partials/options.inventory.seasonalshop.html
.container-fluid .container-fluid
.stable.row .stable.row
.col-md-2 .col-md-2
.seasonalshop_closed .seasonalshop_summer2015
.col-md-10 .col-md-10
.popover.static-popover.fade.right.in .popover.static-popover.fade.right.in
.arrow .arrow
h3.popover-title!=env.t('seasonalShopClosedTitle', {linkStart:"<a href='http://blog.habitrpg.com/who' target='_blank'>", linkEnd: "</a>"}) h3.popover-title!=env.t('seasonalShopTitle', {linkStart:"<a href='http://blog.habitrpg.com/who' target='_blank'>", linkEnd: "</a>"})
.popover-content .popover-content
p!=env.t('seasonalShopClosedText', {linkStart:"<a href='http://habitrpg.wikia.com/wiki/Grand_Galas' target='_blank'>", linkEnd: "</a>"}) p!=env.t('seasonalShopSummerText')
// .well(ng-if='User.user.achievements.rebirths > 0')=env.t('seasonalShopRebirth') .well(ng-if='User.user.achievements.rebirths > 0')=env.t('seasonalShopRebirth')
// li.customize-menu.inventory-gear li.customize-menu.inventory-gear
menu.pets-menu(label='{{::label}}', ng-repeat='(set,label) in ::{springWarrior:env.t("mightyBunnySet"), springMage:env.t("magicMouseSet"), springHealer:env.t("lovingPupSet"), springRogue:env.t("stealthyKittySet")}') menu.pets-menu(label='{{::label}}', ng-repeat='(set,label) in ::{summerWarrior:env.t("daringSwashbucklerSet"), summerMage:env.t("emeraldMermageSet"), summerHealer:env.t("reefSeahealerSet"), summerRogue:env.t("roguishPirateSet")}')
// The `if true || false` conditional for applying the transparent class is necessary because
// when a user activates the orb of rebirth, the seasonal items are still in their inventory, but
// they have each have a value of false. The item can be purchased for gold in the rewards column,
// not the seasonal shop. This makes that more clear.
div(ng-repeat='item in ::getSeasonalShopArray(set)' ng-class="{transparent: user.items.gear.owned[item.key] === true ||user.items.gear.owned[item.key] === false}") div(ng-repeat='item in ::getSeasonalShopArray(set)' ng-class="{transparent: user.items.gear.owned[item.key] === true ||user.items.gear.owned[item.key] === false}")
button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='purchase(item.type,item)', class='shop_{{::item.key}}') button.customize-option(popover='{{::item.notes()}}', popover-title='{{::item.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='purchase(item.type,item)', class='shop_{{::item.key}}')
.text-left .text-left
| {{((item.specialClass == "wizard") && (item.type == "weapon")) + 1}}&nbsp; | {{((item.specialClass == "wizard") && (item.type == "weapon")) + 1}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems span.Pet_Currency_Gem1x.inline-gems
menu.pets-menu(label=env.t('quests')) // menu.pets-menu(label=env.t('quests'))
div(ng-repeat='quest in ::getSeasonalShopQuests()') div(ng-repeat='quest in ::getSeasonalShopQuests()')
button.customize-option(data-popover-html="{{::quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-append-to-body='true', popover-title='{{::quest.text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='buyQuest(quest.key)', ng-class='(quest.previous && !user.achievements.quests[quest.previous]) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"') button.customize-option(data-popover-html="{{::quest.previous && !user.achievements.quests[quest.previous] ? env.t('scrollsPre') : questPopover(quest) | markdown}}", popover-append-to-body='true', popover-title='{{::quest.text()}}', popover-trigger='mouseenter', popover-placement='right', ng-click='buyQuest(quest.key)', ng-class='(quest.previous && !user.achievements.quests[quest.previous]) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"')
p p
| {{::quest.value}}&nbsp; | {{::quest.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems span.Pet_Currency_Gem1x.inline-gems
menu.pets-menu(label=env.t('seasonalItems')) // menu.pets-menu(label=env.t('seasonalItems'))
div div
button.customize-option(popover='{{::Content.spells.special.shinySeed.notes()}}', popover-title='{{::Content.spells.special.shinySeed.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='purchase("special", Content.spells.special.shinySeed)', class='inventory_special_shinySeed') button.customize-option(popover='{{::Content.spells.special.shinySeed.notes()}}', popover-title='{{::Content.spells.special.shinySeed.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='purchase("special", Content.spells.special.shinySeed)', class='inventory_special_shinySeed')
p p

View File

@@ -1,23 +1,45 @@
h5 6/17/2015 - CUTTLEFISH PET QUEST AND QUEST DISPLAY IMPROVEMENTS h5 6/20/2015 - SUMMER SPLASH EVENT: LIMITED EDITION OUTFITS, SEASONAL SHOP OPENS, AND SUMMER NPCS!
hr hr
tr tr
td td
.quest_kraken.pull-right h5 Summer Splash Begins!
h5 Cuttlefish Pet Quest p The Summer Splash festival has arrived, and Habitica has moved to the undersea city of Dilatory for the summer! From today until July 31st, join us for fun in the sun.
p A new pet quest is available in the <a href='/#/options/inventory/drops' target='_blank'>Market</a>: The Kraken of Inkomplete! A pleasant day sailing is ruined when a Kraken attacks. Can you strike down the tasks and tentacles that keep cropping up? If so, you'll be awarded with some cuttlefish eggs!
p.small.muted art by Lemoness and Wolvenhalo
p.small.muted writing by Lemoness
tr tr
td td
h5 Quest Display Improvements .promo_summer_classes_2015.pull-right
p Now you can see the details of a pending quest on the Party Page by clicking the new "Quest Details" tab above the quest invitations. We hope this helps you decide whether or not you want to accept the quest! h5 Limited Edition Class Outfits
p.small.muted by hairlessbear p From now until July 31st, limited edition outfits are available in the Rewards column. Depending on your class, you can be a Reef Renegade, Sunfish Warrior, Strapping Sailor, or Ship Soothsayer! You'd better get productive to earn enough gold before they disappear. Good luck!
p.small.muted by Lemoness
tr
td
.promo_summer_classes_2014.pull-right
h5 Seasonal Shop Opens
p The <a href='/#/options/inventory/seasonalshop'>Seasonal Shop</a> has opened! It's stocking summertime Seasonal Edition goodies at the moment, including last year's summer outfits. Everything there will be available to purchase during the Summer Splash event each year, but it's only open until July 31st, so be sure to stock up now, or you'll have to wait a year to buy these items again.
p.small.muted by Lemoness
tr
td
.seasonalshop_summer2015.pull-right
h5 Summer NPCs
p Looks like the NPCs are really getting in to the summer spirit. Ian, Bailey, Matt, and the Seasonal Sorceress are having fun under the sea in the sunken city of Dilatory, and Alex and Daniel have moved down to the beach. Even the Time Travelers are getting into the fun, although... oh dear... they seem to have overshot the season...
p.small.muted by Lemoness
hr hr
a(href='/static/old-news', target='_blank') Read older news a(href='/static/old-news', target='_blank') Read older news
mixin oldNews mixin oldNews
h5 6/17/2015 - CUTTLEFISH PET QUEST AND QUEST DISPLAY IMPROVEMENTS
tr
td
.quest_kraken.pull-right
h5 Cuttlefish Pet Quest
p A new pet quest is available in the <a href='/#/options/inventory/drops' target='_blank'>Market</a>: The Kraken of Inkomplete! A pleasant day sailing is ruined when a Kraken attacks. Can you strike down the tasks and tentacles that keep cropping up? If so, you'll be awarded with some cuttlefish eggs!
p.small.muted art by Lemoness and Wolvenhalo
p.small.muted writing by Lemoness
tr
td
h5 Quest Display Improvements
p Now you can see the details of a pending quest on the Party Page by clicking the new "Quest Details" tab above the quest invitations. We hope this helps you decide whether or not you want to accept the quest!
p.small.muted by hairlessbear
h5 6/16/2015 - SEARCH BAR, CHALLENGES FILTER, INTERMITTENT REFRESH, AND VISUAL TWEAKS h5 6/16/2015 - SEARCH BAR, CHALLENGES FILTER, INTERMITTENT REFRESH, AND VISUAL TWEAKS
tr tr
td td

View File

@@ -75,8 +75,8 @@ html(ng-app='habitrpg', ng-controller='RootCtrl')
a(href='/static/contact')=env.t('contactUs') a(href='/static/contact')=env.t('contactUs')
li li
button#header-play-button.btn.btn-primary.navbar-btn.navbar-right(ng-click='playButtonClick()')= env.t('playButtonFull') button#header-play-button.btn.btn-primary.navbar-btn.navbar-right(ng-click='playButtonClick()')= env.t('playButtonFull')
#intro #intro(ng-cloak)
h1(ng-cloak) {{ variant==0 ? "#{env.t('motivate')}" : (variant==1 ? "#{env.t('motivate1')}" : "#{env.t('motivate2')}") }} h1 {{ variant==0 ? "#{env.t('motivate')}" : (variant==1 ? "#{env.t('motivate1')}" : "#{env.t('motivate2')}") }}
img.center-block.img-responsive(src='https://s3.amazonaws.com/habitrpg-assets/front/images/intro.png') img.center-block.img-responsive(src='https://s3.amazonaws.com/habitrpg-assets/front/images/intro.png')
// insert intro images // insert intro images
.introcall.bg-success .introcall.bg-success