Merge branch 'develop' into TheHollidayInn-leveling-ensure-user-gets-100-points

This commit is contained in:
Blade Barringer 2015-12-26 19:14:40 -06:00
commit ba31cda85d
103 changed files with 8185 additions and 7385 deletions

View file

@ -1,9 +1,9 @@
/* Comment out for holiday events */
.npc_ian {
/* .npc_ian {
background: url("/common/img/sprites/npc_ian.gif") no-repeat;
width: 78px;
height: 135px;
}
} */
.quest_burnout {
background: url("/common/img/sprites/quest_burnout.gif") no-repeat;

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
.2014_Fall_HealerPROMO2 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -943px -616px;
background-position: -943px -728px;
width: 90px;
height: 90px;
}
@ -12,13 +12,13 @@
}
.2014_Fall_RoguePROMO3 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -943px -343px;
background-position: -1300px -915px;
width: 105px;
height: 90px;
}
.2014_Fall_Warrior_PROMO {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -306px -402px;
background-position: 0px -1085px;
width: 90px;
height: 90px;
}
@ -30,7 +30,7 @@
}
.promo_backtoschool {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -251px;
background-position: -1119px -342px;
width: 150px;
height: 150px;
}
@ -54,37 +54,37 @@
}
.promo_dilatoryDistress {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -452px -417px;
background-position: -306px -402px;
width: 90px;
height: 90px;
}
.promo_enchanted_armoire {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -499px -525px;
background-position: 0px -835px;
width: 374px;
height: 76px;
}
.promo_enchanted_armoire_201507 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -550px;
background-position: -1119px -641px;
width: 217px;
height: 90px;
}
.promo_enchanted_armoire_201508 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -824px;
background-position: -1119px -915px;
width: 180px;
height: 90px;
}
.promo_enchanted_armoire_201509 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -543px -417px;
background-position: -306px -220px;
width: 90px;
height: 90px;
}
.promo_enchanted_armoire_201511 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1225px -991px;
background-position: -1260px -493px;
width: 122px;
height: 90px;
}
@ -102,97 +102,97 @@
}
.promo_haunted_hair {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1260px -402px;
background-position: -1276px -194px;
width: 100px;
height: 137px;
}
.customize-option.promo_haunted_hair {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1285px -417px;
background-position: -1301px -209px;
width: 60px;
height: 60px;
}
.promo_item_notif {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px 0px;
background-position: -1119px -91px;
width: 249px;
height: 102px;
}
.promo_mystery_201405 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -380px -1008px;
background-position: -364px -1085px;
width: 90px;
height: 90px;
}
.promo_mystery_201406 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1270px -251px;
background-position: -943px -449px;
width: 90px;
height: 96px;
}
.promo_mystery_201407 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1037px -525px;
background-position: -1034px -449px;
width: 42px;
height: 62px;
}
.promo_mystery_201408 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1300px -824px;
background-position: -1337px -732px;
width: 60px;
height: 71px;
}
.promo_mystery_201409 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -306px -311px;
background-position: -808px -621px;
width: 90px;
height: 90px;
}
.promo_mystery_201410 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1272px -915px;
background-position: -1318px -823px;
width: 72px;
height: 63px;
}
.promo_mystery_201411 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -808px -621px;
background-position: -182px -1085px;
width: 90px;
height: 90px;
}
.promo_mystery_201412 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1037px -434px;
background-position: -1034px -343px;
width: 42px;
height: 66px;
}
.promo_mystery_201501 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1318px -732px;
background-position: -1333px -1006px;
width: 48px;
height: 63px;
}
.promo_mystery_201502 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -943px -707px;
background-position: -452px -417px;
width: 90px;
height: 90px;
}
.promo_mystery_201503 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -562px -1008px;
background-position: -543px -417px;
width: 90px;
height: 90px;
}
.promo_mystery_201504 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1049px -343px;
background-position: -1272px -1006px;
width: 60px;
height: 69px;
}
.promo_mystery_201505 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -306px -220px;
background-position: -306px -311px;
width: 90px;
height: 90px;
}
@ -204,109 +204,115 @@
}
.promo_mystery_201507 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1276px -103px;
background-position: -943px -343px;
width: 90px;
height: 105px;
}
.promo_mystery_201508 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -943px -525px;
background-position: -943px -546px;
width: 93px;
height: 90px;
}
.promo_mystery_201509 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -289px -1008px;
background-position: -91px -1085px;
width: 90px;
height: 90px;
}
.promo_mystery_201510 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -943px -434px;
background-position: -943px -637px;
width: 93px;
height: 90px;
}
.promo_mystery_201511 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -471px -1008px;
background-position: -273px -1085px;
width: 90px;
height: 90px;
}
.promo_mystery_201512 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1337px -641px;
width: 60px;
height: 81px;
}
.promo_mystery_3014 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -641px;
background-position: -1119px -732px;
width: 217px;
height: 90px;
}
.promo_orca {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -991px;
background-position: -1270px -342px;
width: 105px;
height: 105px;
}
.promo_partyhats {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -662px -835px;
background-position: -1260px -584px;
width: 115px;
height: 47px;
}
.promo_pastel_skin {
background-image: url(spritesmith-largeSprites-0.png);
background-position: 0px -835px;
background-position: -331px -912px;
width: 330px;
height: 83px;
}
.customize-option.promo_pastel_skin {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -25px -850px;
background-position: -356px -927px;
width: 60px;
height: 60px;
}
.promo_pet_skins {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -402px;
background-position: -1119px -493px;
width: 140px;
height: 147px;
}
.customize-option.promo_pet_skins {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1144px -417px;
background-position: -1144px -508px;
width: 60px;
height: 60px;
}
.promo_shimmer_hair {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -331px -835px;
background-position: 0px -912px;
width: 330px;
height: 83px;
}
.customize-option.promo_shimmer_hair {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -356px -850px;
background-position: -25px -927px;
width: 60px;
height: 60px;
}
.promo_splashyskins {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -732px;
background-position: -1119px -823px;
width: 198px;
height: 91px;
}
.customize-option.promo_splashyskins {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1144px -747px;
background-position: -1144px -838px;
width: 60px;
height: 60px;
}
.promo_springclasses2014 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -648px -724px;
background-position: -1119px 0px;
width: 288px;
height: 90px;
}
.promo_springclasses2015 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: 0px -1008px;
background-position: -648px -724px;
width: 288px;
height: 90px;
}
@ -318,13 +324,13 @@
}
.promo_summer_classes_2015 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: 0px -919px;
background-position: 0px -996px;
width: 300px;
height: 88px;
}
.promo_updos {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -103px;
background-position: -1119px -194px;
width: 156px;
height: 147px;
}
@ -334,6 +340,12 @@
width: 146px;
height: 75px;
}
.promo_winter_classes_2016 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -499px -525px;
width: 360px;
height: 90px;
}
.promo_winterclasses2015 {
background-image: url(spritesmith-largeSprites-0.png);
background-position: 0px -724px;
@ -342,13 +354,13 @@
}
.promo_winteryhair {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1119px -915px;
background-position: -1119px -1006px;
width: 152px;
height: 75px;
}
.customize-option.promo_winteryhair {
background-image: url(spritesmith-largeSprites-0.png);
background-position: -1144px -930px;
background-position: -1144px -1021px;
width: 60px;
height: 60px;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 209 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 332 KiB

After

Width:  |  Height:  |  Size: 272 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 58 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 132 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 KiB

After

Width:  |  Height:  |  Size: 375 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 KiB

After

Width:  |  Height:  |  Size: 172 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 145 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 142 KiB

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 6.1 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.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.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 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: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 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.

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 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.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 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: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 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: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -18,6 +18,7 @@
"choreSample4": "Tidy One Room",
"choreSample5": "Wash and Dry a Load of Clothes",
"chores": "Chores",
"clearBrowserData": "Clear Browser Data",
"communityBug": "Submit Bug",
"communityExtensions": "Add-ons & Extensions",
"communityFacebook": "Facebook",
@ -164,6 +165,12 @@
"teams": "Teams",
"terms": "Terms and Conditions",
"testimonialHeading": "What people say...",
"localStorageTryFirst": "If you are experiencing problems with Habitica, click the button below to clear cookies and local storage for this website (other websites will not be affected). You will need to log in again after doing this, so first be sure that you know your log-in details, which can be found at Settings -> <%= linkStart %>Site<%= linkEnd %>.",
"localStorageTryNext": "If the problem persists, please <%= linkStart %>Report a Bug<%= linkEnd %> if you haven't already.",
"localStorageClearing": "Clearing Local Storage",
"localStorageClearingExplanation": "Your browser's local storage is being cleared. You will be logged out and redirected to the home page. Please wait.",
"localStorageClear": "Clear Local Storage",
"localStorageClearExplanation": "This button will clear local storage and log you out",
"tutorials": "Tutorials",
"unlockByline1": "Achieve your goals and level up.",
"unlockByline2": "Unlock new motivational tools, such as pet collecting, random rewards, spell-casting, and more!",

View file

@ -149,6 +149,15 @@
"weaponSpecialFall2015HealerText": "Swamp-Slime Potion",
"weaponSpecialFall2015HealerNotes": "Brewed to perfection! Now you just have to convince yourself to drink it. Increases Intelligence by <%= int %>. Limited Edition 2015 Autumn Gear.",
"weaponSpecialWinter2016RogueText": "Cocoa Mug",
"weaponSpecialWinter2016RogueNotes": "Warming drink, or boiling projectile? You decide... Increases Strength by <%= str %>. Limited Edition 2015-2016 Winter Gear.",
"weaponSpecialWinter2016WarriorText": "Sturdy Shovel",
"weaponSpecialWinter2016WarriorNotes": "Shovel overdue tasks out of the way! Increases Strength by <%= str %>. Limited Edition 2015-2016 Winter Gear.",
"weaponSpecialWinter2016MageText": "Sorcerous Snowboard",
"weaponSpecialWinter2016MageNotes": "Your moves are so sick, they must be magic! Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015-2016 Winter Gear.",
"weaponSpecialWinter2016HealerText": "Confetti Cannon",
"weaponSpecialWinter2016HealerNotes": "WHEEEEEEEEEE!!!!!!! HAPPY WINTER WONDERLAND!!!!!!!! Increases Intelligence by <%= int %>. Limited Edition 2015-2016 Winter Gear.",
"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.",
"weaponMystery201502Text": "Shimmery Winged Staff of Love and Also Truth",
@ -316,6 +325,15 @@
"armorSpecialFall2015HealerText": "Potioner Robes",
"armorSpecialFall2015HealerNotes": "What? Of course that was a potion of constitution. No, you are definitely not turning into a frog! Don't be ribbiticulous. Increases Constitution by <%= con %>. Limited Edition 2015 Autumn Gear.",
"armorSpecialWinter2016RogueText": "Cocoa Armor",
"armorSpecialWinter2016RogueNotes": "This leather armor keeps you nice and toasty. Is it actually made from cocoa? You'll never tell. Increases Perception by <%= per %>. Limited Edition 2015-2016 Winter Gear.",
"armorSpecialWinter2016WarriorText": "Snowman Suit",
"armorSpecialWinter2016WarriorNotes": "Brr! This padded armor is truly powerful... until it melts. Increases Constitution by <%= con %>. Limited Edition 2015-2016 Winter Gear.",
"armorSpecialWinter2016MageText": "Snowboarder Parka",
"armorSpecialWinter2016MageNotes": "The wisest wizard keeps well-bundled in the winter wind. Increases Intelligence by <%= int %>. Limited Edition 2015-2016 Winter Gear.",
"armorSpecialWinter2016HealerText": "Festive Fairy Cloak",
"armorSpecialWinter2016HealerNotes": "Festive Fairies wrap their body wings around themselves for protection as they use their head wings to catch headwinds and fly around Habitica at speeds of up to 100 mph, delivering gifts and spraying everyone with confetti. How droll. Increases Constitution by <%= con %>. Limited Edition 2015-2016 Winter Gear.",
"armorMystery201402Text": "Messenger Robes",
"armorMystery201402Notes": "Shimmering and strong, these robes have many pockets to carry letters. Confers no benefit. February 2014 Subscriber Item.",
"armorMystery201403Text": "Forest Walker Armor",
@ -348,6 +366,8 @@
"armorMystery201509Notes": "This IS a costume, right? Confers no benefit. September 2015 Subscriber Item.",
"armorMystery201511Text": "Wooden Armor",
"armorMystery201511Notes": "Considering this armor was carved directly from a magical log, it's surprisingly comfortable. Confers no benefit. November 2015 Subscriber Item.",
"armorMystery201512Text": "Cold Fire Armor",
"armorMystery201512Notes": "Summon the icy flames of winter! Confers no benefit. December 2015 Subscriber Item.",
"armorMystery301404Text": "Steampunk Suit",
"armorMystery301404Notes": "Dapper and dashing, wot! Confers no benefit. February 3015 Subscriber Item.",
@ -504,6 +524,15 @@
"headSpecialFall2015HealerText": "Hat of Frog",
"headSpecialFall2015HealerNotes": "This is an extremely serious hat that is worthy of only the most advanced potioners. Increases Intelligence by <%= int %>. Limited Edition 2015 Autumn Gear.",
"headSpecialWinter2016RogueText": "Cocoa Helm",
"headSpecialWinter2016RogueNotes": "The protective scarf on this cozy helm is only removed to sip warm winter beverages. Increases Perception by <%= per %>. Limited Edition 2015-2016 Winter Gear.",
"headSpecialWinter2016WarriorText": "Snowman Cap",
"headSpecialWinter2016WarriorNotes": "Brr! This mighty helm is truly powerful... until it melts. Increases Strength by <%= str %>. Limited Edition 2015-2016 Winter Gear.",
"headSpecialWinter2016MageText": "Snowboarder Hood",
"headSpecialWinter2016MageNotes": "Keeps the snow out of your eyes while you're casting spells. Increases Perception by <%= per %>. Limited Edition 2015-2016 Winter Gear.",
"headSpecialWinter2016HealerText": "Fairy Wing Helm",
"headSpecialWinter2016HealerNotes": "Thesewingsfluttersoquicklythattheyblur! Increases Intelligence by <%= int %>. Limited Edition 2015-2016 Winter Gear.",
"headSpecialGaymerxText": "Rainbow Warrior Helm",
"headSpecialGaymerxNotes": "In celebration of the GaymerX Conference, this special helmet is decorated with a radiant, colorful rainbow pattern! GaymerX is a game convention celebrating LGTBQ and gaming and is open to everyone.",
@ -531,6 +560,8 @@
"headMystery201509Notes": "This IS a mask, right? Confers no benefit. September 2015 Subscriber Item.",
"headMystery201511Text": "Log Crown",
"headMystery201511Notes": "Count the number of rings to learn how old this crown is. Confers no benefit. November 2015 Subscriber Item.",
"headMystery201512Text": "Winter Flame",
"headMystery201512Notes": "These flames burn cold with pure intellect. Confers no benefit. December 2015 Subscriber Item.",
"headMystery301404Text": "Fancy Top Hat",
"headMystery301404Notes": "A fancy top hat for the finest of gentlefolk! January 3015 Subscriber Item. Confers no benefit.",
"headMystery301405Text": "Basic Top Hat",
@ -662,6 +693,13 @@
"shieldSpecialFall2015HealerText": "Stirring Stick",
"shieldSpecialFall2015HealerNotes": "This stick can stir anything without melting, dissolving, or bursting into flame! It can also be used to fiercely poke enemy tasks. Increases Constitution by <%= con %>. Limited Edition 2015 Autumn Gear.",
"shieldSpecialWinter2016RogueText": "Cocoa Mug",
"shieldSpecialWinter2016RogueNotes": "Warming drink, or boiling projectile? You decide... Increases Strength by <%= str %>. Limited Edition 2015-2016 Winter Gear.",
"shieldSpecialWinter2016WarriorText": "Sled Shield",
"shieldSpecialWinter2016WarriorNotes": "Use this sled to block attacks, or ride it triumphantly into battle! Increases Constitution by <%= con %>. Limited Edition 2015-2016 Winter Gear.",
"shieldSpecialWinter2016HealerText": "Pixie Present",
"shieldSpecialWinter2016HealerNotes": "Open it open it open it open it open it open it!!!!!!!!! Increases Constitution by <%= con %>. Limited Edition 2015-2016 Winter Gear.",
"shieldMystery301405Text": "Clock Shield",
"shieldMystery301405Notes": "Time is on your side with this towering clock shield! Confers no benefit. June 3015 Subscriber Item.",

View file

@ -31,12 +31,17 @@
"seasonalShopText": "Welcome to the Seasonal Shop!! We're stocking springtime <a href='http://habitica.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://habitica.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!",
"seasonalShopFallText": "Welcome to the Seasonal Shop!! We're stocking autumn <a href='http://habitica.wikia.com/wiki/Item_Availability' target='_blank'>Seasonal Edition</a> goodies at the moment. Everything here will be available to purchase during the Fall Festival event each year, but we're only open until October 31, so be sure to stock up now, or you'll have to wait a year to buy these items again!",
"seasonalShopWinterText": "Welcome to the Seasonal Shop!! We're stocking winter <a href='http://habitica.wikia.com/wiki/Item_Availability' target='_blank'>Seasonal Edition</a> goodies at the moment. Everything here will be available to purchase during the Winter Wonderland event each year, but we're only open until January 31, so be sure to stock up now, or you'll have to wait a year to buy these items again!",
"seasonalShopFallTextBroken": "Oh.... Welcome to the Seasonal Shop... We're stocking autumn Seasonal Edition goodies, or something... Everything here will be available to purchase during the Fall Festival event each year, but we're only open until October 31... I guess you should to stock up now, or you'll have to wait... and wait... and wait... <strong>*sigh*</strong>",
"seasonalShopRebirth": "If you've used the Orb of Rebirth, you can repurchase this equipment in the Rewards Column. 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)",
"skiSet": "Ski-sassin (Rogue)",
"snowflakeSet": "Snowflake (Healer)",
"yetiSet": "Yeti Tamer (Warrior)",
"northMageSet": "Mage of the North (Mage)",
"icicleDrakeSet": "Icicle Drake (Rogue)",
"soothingSkaterSet": "Soothing Skater (Healer)",
"gingerbreadSet": "Gingerbread Warrior (Warrior)",
"toAndFromCard": "To: <%= toName %>, From: <%= fromName %>",
"nyeCard": "New Year's Card",
"nyeCardExplanation": "For celebrating the new year together, you both receive the \"Auld Acquaintance\" badge!",

View file

@ -1,6 +1,6 @@
{
"questEvilSantaText": "Trapper Santa",
"questEvilSantaNotes": "You hear bemoaned roars deep in the icefields. You follow the roars and growls - punctuated by another voice's cackling - to a clearing in the woods where you see a fully-grown polar bear. She's caged and shackled, roaring for life. Dancing atop the cage is a malicious little imp wearing castaway Christmas costumes. Vanquish Trapper Santa, and save the beast!",
"questEvilSantaNotes": "You hear moaning roars deep in the icefields. You follow the roars and growls - punctuated by another voice's cackling - to a clearing in the woods where you see a fully-grown polar bear. She's caged and shackled, roaring for life. Dancing atop the cage is a malicious little imp wearing castaway Christmas costumes. Vanquish Trapper Santa, and save the beast!",
"questEvilSantaCompletion": "Trapper Santa squeals in anger, and bounces off into the night. A grateful she-bear, through roars and growls, tries to tell you something. You take her back to the stables, where Matt Boch the whisperer listens to her tale with a gasp of horror. She has a cub! He ran off into the icefields when mama bear was captured. Help her find her baby!",
"questEvilSantaBoss": "Trapper Santa",
"questEvilSantaDropBearCubPolarMount": "Polar Bear (Mount)",

View file

@ -22,6 +22,7 @@ export const EVENTS = {
summer2015: { start: '2015-06-20', end: '2015-08-02' },
fall2015: { start: '2015-09-21', end: '2015-11-01' },
gaymerx: { start: '2015-12-01', end: '2015-12-14' },
winter2016: { start: '2015-12-18', end: '2016-02-02' },
};
export const GEAR_TYPES = [

View file

@ -97,6 +97,12 @@ let armor = {
mystery: '201511',
value: 0,
},
201512: {
text: t('armorMystery201512Text'),
notes: t('armorMystery201512Notes'),
mystery: '201512',
value: 0,
},
301404: {
text: t('armorMystery301404Text'),
notes: t('armorMystery301404Notes'),
@ -250,6 +256,12 @@ let head = {
mystery: '201511',
value: 0,
},
201512: {
text: t('headMystery201512Text'),
notes: t('headMystery201512Notes'),
mystery: '201512',
value: 0,
},
301404: {
text: t('headMystery301404Text'),
notes: t('headMystery301404Notes'),

View file

@ -25,6 +25,9 @@ let armor = {
notes: t('armorSpecialYetiNotes', { con: 9 }),
con: 9,
value: 90,
canBuy: () => {
return true;
},
},
ski: {
event: EVENTS.winter,
@ -33,6 +36,9 @@ let armor = {
notes: t('armorSpecialSkiNotes', { per: 15 }),
per: 15,
value: 90,
canBuy: () => {
return true;
},
},
candycane: {
event: EVENTS.winter,
@ -41,6 +47,9 @@ let armor = {
notes: t('armorSpecialCandycaneNotes', { int: 9 }),
int: 9,
value: 90,
canBuy: () => {
return true;
},
},
snowflake: {
event: EVENTS.winter,
@ -49,11 +58,15 @@ let armor = {
notes: t('armorSpecialSnowflakeNotes', { con: 15 }),
con: 15,
value: 90,
canBuy: () => {
return true;
},
},
birthday: {
event: EVENTS.birthday,
text: t('armorSpecialBirthdayText'),
notes: t('armorSpecialBirthdayNotes'), value: 0 },
notes: t('armorSpecialBirthdayNotes'), value: 0,
},
springRogue: {
event: EVENTS.spring,
specialClass: 'rogue',
@ -169,6 +182,9 @@ let armor = {
notes: t('armorSpecialWinter2015RogueNotes', { per: 15 }),
value: 90,
per: 15,
canBuy: () => {
return true;
},
},
winter2015Warrior: {
event: EVENTS.winter2015,
@ -177,6 +193,9 @@ let armor = {
notes: t('armorSpecialWinter2015WarriorNotes', { con: 9 }),
value: 90,
con: 9,
canBuy: () => {
return true;
},
},
winter2015Mage: {
event: EVENTS.winter2015,
@ -185,6 +204,9 @@ let armor = {
notes: t('armorSpecialWinter2015MageNotes', { int: 9 }),
value: 90,
int: 9,
canBuy: () => {
return true;
},
},
winter2015Healer: {
event: EVENTS.winter2015,
@ -193,6 +215,9 @@ let armor = {
notes: t('armorSpecialWinter2015HealerNotes', { con: 15 }),
value: 90,
con: 15,
canBuy: () => {
return true;
},
},
birthday2015: {
text: t('armorSpecialBirthday2015Text'),
@ -302,6 +327,38 @@ let armor = {
notes: t('armorSpecialGaymerxNotes'),
value: 0,
},
winter2016Rogue: {
event: EVENTS.winter2016,
specialClass: 'rogue',
text: t('armorSpecialWinter2016RogueText'),
notes: t('armorSpecialWinter2016RogueNotes', { per: 15 }),
value: 90,
per: 15,
},
winter2016Warrior: {
event: EVENTS.winter2016,
specialClass: 'warrior',
text: t('armorSpecialWinter2016WarriorText'),
notes: t('armorSpecialWinter2016WarriorNotes', { con: 9 }),
value: 90,
con: 9,
},
winter2016Mage: {
event: EVENTS.winter2016,
specialClass: 'wizard',
text: t('armorSpecialWinter2016MageText'),
notes: t('armorSpecialWinter2016MageNotes', { int: 9 }),
value: 90,
int: 9,
},
winter2016Healer: {
event: EVENTS.winter2016,
specialClass: 'healer',
text: t('armorSpecialWinter2016HealerText'),
notes: t('armorSpecialWinter2016HealerNotes', { con: 15 }),
value: 90,
con: 15,
},
};
let back = {
@ -400,6 +457,9 @@ let head = {
notes: t('headSpecialYetiNotes', { str: 9 }),
str: 9,
value: 60,
canBuy: () => {
return true;
},
},
ski: {
event: EVENTS.winter,
@ -408,6 +468,9 @@ let head = {
notes: t('headSpecialSkiNotes', { per: 9 }),
per: 9,
value: 60,
canBuy: () => {
return true;
},
},
candycane: {
event: EVENTS.winter,
@ -416,6 +479,9 @@ let head = {
notes: t('headSpecialCandycaneNotes', { per: 7 }),
per: 7,
value: 60,
canBuy: () => {
return true;
},
},
snowflake: {
event: EVENTS.winter,
@ -424,6 +490,9 @@ let head = {
notes: t('headSpecialSnowflakeNotes', { int: 7 }),
int: 7,
value: 60,
canBuy: () => {
return true;
},
},
springRogue: {
event: EVENTS.spring,
@ -540,6 +609,9 @@ let head = {
notes: t('headSpecialWinter2015RogueNotes', { per: 9 }),
value: 60,
per: 9,
canBuy: () => {
return true;
},
},
winter2015Warrior: {
event: EVENTS.winter2015,
@ -548,6 +620,9 @@ let head = {
notes: t('headSpecialWinter2015WarriorNotes', { str: 9 }),
value: 60,
str: 9,
canBuy: () => {
return true;
},
},
winter2015Mage: {
event: EVENTS.winter2015,
@ -556,6 +631,9 @@ let head = {
notes: t('headSpecialWinter2015MageNotes', { per: 7 }),
value: 60,
per: 7,
canBuy: () => {
return true;
},
},
winter2015Healer: {
event: EVENTS.winter2015,
@ -564,6 +642,9 @@ let head = {
notes: t('headSpecialWinter2015HealerNotes', { int: 7 }),
value: 60,
int: 7,
canBuy: () => {
return true;
},
},
nye2014: {
text: t('headSpecialNye2014Text'),
@ -673,6 +754,38 @@ let head = {
notes: t('headSpecialGaymerxNotes'),
value: 0,
},
winter2016Rogue: {
event: EVENTS.winter2016,
specialClass: 'rogue',
text: t('headSpecialWinter2016RogueText'),
notes: t('headSpecialWinter2016RogueNotes', { per: 9 }),
value: 60,
per: 9,
},
winter2016Warrior: {
event: EVENTS.winter2016,
specialClass: 'warrior',
text: t('headSpecialWinter2016WarriorText'),
notes: t('headSpecialWinter2016WarriorNotes', { str: 9 }),
value: 60,
str: 9,
},
winter2016Mage: {
event: EVENTS.winter2016,
specialClass: 'wizard',
text: t('headSpecialWinter2016MageText'),
notes: t('headSpecialWinter2016MageNotes', { per: 7 }),
value: 60,
per: 7,
},
winter2016Healer: {
event: EVENTS.winter2016,
specialClass: 'healer',
text: t('headSpecialWinter2016HealerText'),
notes: t('headSpecialWinter2016HealerNotes', { int: 7 }),
value: 60,
int: 7,
},
};
let headAccessory = {
@ -839,6 +952,9 @@ let shield = {
notes: t('shieldSpecialYetiNotes', { con: 7 }),
con: 7,
value: 70,
canBuy: () => {
return true;
},
},
ski: {
event: EVENTS.winter,
@ -847,6 +963,9 @@ let shield = {
notes: t('weaponSpecialSkiNotes', { str: 8 }),
str: 8,
value: 90,
canBuy: () => {
return true;
},
},
snowflake: {
event: EVENTS.winter,
@ -855,6 +974,9 @@ let shield = {
notes: t('shieldSpecialSnowflakeNotes', { con: 9 }),
con: 9,
value: 70,
canBuy: () => {
return true;
},
},
springRogue: {
event: EVENTS.spring,
@ -944,6 +1066,9 @@ let shield = {
notes: t('shieldSpecialWinter2015RogueNotes', { str: 8 }),
value: 80,
str: 8,
canBuy: () => {
return true;
},
},
winter2015Warrior: {
event: EVENTS.winter2015,
@ -952,6 +1077,9 @@ let shield = {
notes: t('shieldSpecialWinter2015WarriorNotes', { con: 7 }),
value: 70,
con: 7,
canBuy: () => {
return true;
},
},
winter2015Healer: {
event: EVENTS.winter2015,
@ -960,6 +1088,9 @@ let shield = {
notes: t('shieldSpecialWinter2015HealerNotes', { con: 9 }),
value: 70,
con: 9,
canBuy: () => {
return true;
},
},
spring2015Rogue: {
event: EVENTS.spring2015,
@ -1033,6 +1164,30 @@ let shield = {
value: 70,
con: 9,
},
winter2016Rogue: {
event: EVENTS.winter2016,
specialClass: 'rogue',
text: t('shieldSpecialWinter2016RogueText'),
notes: t('shieldSpecialWinter2016RogueNotes', { str: 8 }),
value: 80,
str: 8,
},
winter2016Warrior: {
event: EVENTS.winter2016,
specialClass: 'warrior',
text: t('shieldSpecialWinter2016WarriorText'),
notes: t('shieldSpecialWinter2016WarriorNotes', { con: 7 }),
value: 70,
con: 7,
},
winter2016Healer: {
event: EVENTS.winter2016,
specialClass: 'healer',
text: t('shieldSpecialWinter2016HealerText'),
notes: t('shieldSpecialWinter2016HealerNotes', { con: 9 }),
value: 70,
con: 9,
},
};
let weapon = {
@ -1055,6 +1210,9 @@ let weapon = {
notes: t('weaponSpecialYetiNotes', { str: 15 }),
str: 15,
value: 90,
canBuy: () => {
return true;
},
},
ski: {
event: EVENTS.winter,
@ -1063,6 +1221,9 @@ let weapon = {
notes: t('weaponSpecialSkiNotes', { str: 8 }),
str: 8,
value: 90,
canBuy: () => {
return true;
},
},
candycane: {
event: EVENTS.winter,
@ -1073,6 +1234,9 @@ let weapon = {
int: 15,
per: 7,
value: 160,
canBuy: () => {
return true;
},
},
snowflake: {
event: EVENTS.winter,
@ -1081,6 +1245,9 @@ let weapon = {
notes: t('weaponSpecialSnowflakeNotes', { int: 9 }),
int: 9,
value: 90,
canBuy: () => {
return true;
},
},
springRogue: {
event: EVENTS.spring,
@ -1203,6 +1370,9 @@ let weapon = {
notes: t('weaponSpecialWinter2015RogueNotes', { str: 8 }),
value: 80,
str: 8,
canBuy: () => {
return true;
},
},
winter2015Warrior: {
event: EVENTS.winter2015,
@ -1211,6 +1381,9 @@ let weapon = {
notes: t('weaponSpecialWinter2015WarriorNotes', { str: 15 }),
value: 90,
str: 15,
canBuy: () => {
return true;
},
},
winter2015Mage: {
event: EVENTS.winter2015,
@ -1221,6 +1394,9 @@ let weapon = {
value: 160,
int: 15,
per: 7,
canBuy: () => {
return true;
},
},
winter2015Healer: {
event: EVENTS.winter2015,
@ -1229,6 +1405,9 @@ let weapon = {
notes: t('weaponSpecialWinter2015HealerNotes', { int: 9 }),
value: 90,
int: 9,
canBuy: () => {
return true;
},
},
spring2015Rogue: {
event: EVENTS.spring2015,
@ -1332,6 +1511,40 @@ let weapon = {
value: 90,
int: 9,
},
winter2016Rogue: {
event: EVENTS.winter2016,
specialClass: 'rogue',
text: t('weaponSpecialWinter2016RogueText'),
notes: t('weaponSpecialWinter2016RogueNotes', { str: 8 }),
value: 80,
str: 8,
},
winter2016Warrior: {
event: EVENTS.winter2016,
specialClass: 'warrior',
text: t('weaponSpecialWinter2016WarriorText'),
notes: t('weaponSpecialWinter2016WarriorNotes', { str: 15 }),
value: 90,
str: 15,
},
winter2016Mage: {
event: EVENTS.winter2016,
specialClass: 'wizard',
twoHanded: true,
text: t('weaponSpecialWinter2016MageText'),
notes: t('weaponSpecialWinter2016MageNotes', { int: 15, per: 7 }),
value: 160,
int: 15,
per: 7,
},
winter2016Healer: {
event: EVENTS.winter2016,
specialClass: 'healer',
text: t('weaponSpecialWinter2016HealerText'),
notes: t('weaponSpecialWinter2016HealerNotes', { int: 9 }),
value: 90,
int: 9,
},
};
let specialSet = {

View file

@ -1590,7 +1590,7 @@ api.quests = {
},
evilsanta: {
canBuy: (function() {
return false;
return true;
}),
text: t('questEvilSantaText'),
notes: t('questEvilSantaNotes'),
@ -1616,7 +1616,7 @@ api.quests = {
},
evilsanta2: {
canBuy: (function() {
return false;
return true;
}),
text: t('questEvilSanta2Text'),
notes: t('questEvilSanta2Notes'),

View file

@ -90,6 +90,10 @@ let mysterySets = {
start: '2015-11-25',
end: '2015-12-02',
},
201512: {
start: '2015-12-23',
end: '2016-01-02',
},
301404: {
start: '3014-03-24',
end: '3014-04-02',

View file

@ -2,7 +2,7 @@ var _id = '';
var update = {
$addToSet: {
'purchased.plan.mysteryItems':{
$each:['head_mystery_201511','armor_mystery_201511']
$each:['head_mystery_201512','armor_mystery_201512']
}
}
};

View file

@ -103,6 +103,7 @@
"event-stream": "^3.2.2",
"expect.js": "~0.2.0",
"istanbul": "^0.3.14",
"phantomjs": "^1.9",
"karma": "~0.13.15",
"karma-chai-plugins": "~0.6.0",
"karma-coverage": "^0.5.3",

View file

@ -51,6 +51,7 @@ gulp.task('lint:common', () => {
gulp.task('lint:tests', () => {
let options = {
rules: {
'one-var': 0,
'max-nested-callbacks': 0,
'no-unused-expressions': 0,
'mocha/no-exclusive-tests': 2,

View file

@ -36,6 +36,22 @@ One caveat. If you have a severe syntax error in your files, the tests may fail
$ gulp test:api:safe
```
If you'd like to run the tests individually and inspect the output from the server, in one pane you can run:
```bash
$ export PORT=3003; export NODE_DB_URI="mongodb://localhost/habitrpgtest"
$ gulp nodemon
```
And run your tests in another pane:
```bash
$ mocha path/to/file.js
# Mark a test with the `.only` attribute
$ mocha
```
## Structure
Each top level route has it's own directory. So, all the routes that begin with `/groups/` live in `/test/api/groups/`.

View file

@ -0,0 +1,76 @@
import moment from 'moment';
import { generateTodo } from '../helpers/common.helper';
import { preenTodos } from '../../common/script/index.js';
describe('#preenTodos', () => {
let todos, uncompletedTodo, completedChallengeTodo, newlyCompletedTodo, completedTodoFromTwoDaysAgo, completedTodoFromThreeDaysAgo, completedTodoFromTenDaysAgo;
beforeEach(() => {
uncompletedTodo = generateTodo({ completed: false });
completedChallengeTodo = generateTodo({
completed: true,
challenge: { id: 'some-challenge' },
});
newlyCompletedTodo = generateTodo({
completed: true,
dateCompleted: moment(),
});
completedTodoFromTwoDaysAgo = generateTodo({
completed: true,
dateCompleted: moment().subtract({ days: 2 }),
});
completedTodoFromThreeDaysAgo = generateTodo({
completed: true,
dateCompleted: moment().subtract({ days: 3 }),
});
completedTodoFromTenDaysAgo = generateTodo({
completed: true,
dateCompleted: moment().subtract({ days: 10 }),
});
todos = [
uncompletedTodo,
completedChallengeTodo,
newlyCompletedTodo,
completedTodoFromTwoDaysAgo,
completedTodoFromThreeDaysAgo,
completedTodoFromTenDaysAgo,
];
});
it('includes uncompleted todos', () => {
let preenedTodos = preenTodos(todos);
expect(preenedTodos).to.include(uncompletedTodo);
});
it('includes completed challenge todos', () => {
let preenedTodos = preenTodos(todos);
expect(preenedTodos).to.include(completedChallengeTodo);
});
it('includes recently completed todos', () => {
let preenedTodos = preenTodos(todos);
expect(preenedTodos).to.include(newlyCompletedTodo);
});
it('includes todos completed two days ago', () => {
let preenedTodos = preenTodos(todos);
expect(preenedTodos).to.include(completedTodoFromTwoDaysAgo);
});
it('does not include todos completed three days ago', () => {
let preenedTodos = preenTodos(todos);
expect(preenedTodos).to.not.include(completedTodoFromThreeDaysAgo);
});
it('does not include todos completed more than three days ago', () => {
let preenedTodos = preenTodos(todos);
expect(preenedTodos).to.not.include(completedTodoFromTenDaysAgo);
});
});

View file

@ -1,45 +1,121 @@
'use strict';
describe('Auth Controller', function() {
var scope, ctrl, user, $httpBackend, $window, $modal;
describe('AuthCtrl', function(){
var scope, ctrl, user, $httpBackend, $window;
beforeEach(function(){
module(function($provide) {
$provide.value('Analytics', analyticsMock);
$provide.value('Chat', { seenMessage: function() {} });
});
inject(function(_$httpBackend_, $rootScope, $controller) {
$httpBackend = _$httpBackend_;
scope = $rootScope.$new();
scope.loginUsername = 'user';
scope.loginPassword = 'pass';
$window = { location: { href: ""}, alert: sandbox.spy() };
user = { user: {}, authenticate: sandbox.spy() };
ctrl = $controller('AuthCtrl', {$scope: scope, $window: $window, User: user});
})
beforeEach(function(){
module(function($provide) {
$provide.value('Analytics', analyticsMock);
$provide.value('Chat', { seenMessage: function() {} });
});
describe('logging in', function() {
inject(function(_$httpBackend_, $rootScope, $controller, _$modal_) {
$httpBackend = _$httpBackend_;
scope = $rootScope.$new();
scope.loginUsername = 'user';
scope.loginPassword = 'pass';
$window = { location: { href: ""}, alert: sandbox.spy() };
$modal = _$modal_;
user = { user: {}, authenticate: sandbox.spy() };
it('should log in users with correct uname / pass', function() {
$httpBackend.expectPOST('/api/v2/user/auth/local').respond({id: 'abc', token: 'abc'});
scope.auth();
$httpBackend.flush();
expect(user.authenticate).to.be.calledOnce;
expect($window.alert).to.not.be.called;
ctrl = $controller('AuthCtrl', {$scope: scope, $window: $window, User: user});
})
});
describe('logging in', function() {
it('should log in users with correct uname / pass', function() {
$httpBackend.expectPOST('/api/v2/user/auth/local').respond({id: 'abc', token: 'abc'});
scope.auth();
$httpBackend.flush();
expect(user.authenticate).to.be.calledOnce;
expect($window.alert).to.not.be.called;
});
it('should not log in users with incorrect uname / pass', function() {
$httpBackend.expectPOST('/api/v2/user/auth/local').respond(404, '');
scope.auth();
$httpBackend.flush();
expect(user.authenticate).to.not.be.called;
expect($window.alert).to.be.calledOnce;
});
});
describe('#clearLocalStorage', function () {
var timer;
beforeEach(function () {
timer = sandbox.useFakeTimers();
sandbox.stub($modal, 'open');
});
it('opens modal with message about clearing local storage and logging out', function () {
scope.clearLocalStorage();
expect($modal.open).to.be.calledOnce;
expect($modal.open).to.be.calledWith({
templateUrl: 'modals/message-modal.html',
scope: scope
});
it('should not log in users with incorrect uname / pass', function() {
$httpBackend.expectPOST('/api/v2/user/auth/local').respond(404, '');
scope.auth();
$httpBackend.flush();
expect(user.authenticate).to.not.be.called;
expect($window.alert).to.be.calledOnce;
});
expect(scope.messageModal.title).to.eql(window.env.t('localStorageClearing'));
expect(scope.messageModal.body).to.eql(window.env.t('localStorageClearingExplanation'));
});
it('does not call $scope.logout before 3 seconds', function () {
sandbox.stub(scope, 'logout');
scope.clearLocalStorage();
timer.tick(2999);
expect(scope.logout).to.not.be.called;
});
it('calls $scope.logout after 3 seconds', function () {
sandbox.stub(scope, 'logout');
scope.clearLocalStorage();
timer.tick(3000);
expect(scope.logout).to.be.calledOnce;
});
it('does not clear local storage before 3 seconds', function () {
sandbox.stub(localStorage, 'clear');
scope.clearLocalStorage();
timer.tick(2999);
expect(localStorage.clear).to.not.be.called;
});
it('clears local storage after 3 seconds', function () {
sandbox.stub(localStorage, 'clear');
scope.clearLocalStorage();
timer.tick(3000);
expect(localStorage.clear).to.be.calledOnce;
});
it('does not redirect to /logout route before 3 seconds', function () {
scope.clearLocalStorage();
timer.tick(2999);
expect($window.location.href).to.eql('');
});
it('redirects to /logout after 3 seconds', function () {
scope.clearLocalStorage();
timer.tick(3000);
expect($window.location.href).to.eql('/logout');
});
});
});

View file

@ -11,7 +11,7 @@ angular.module('habitrpg')
$scope.logout = function() {
localStorage.clear();
window.location.href = '/logout';
$window.location.href = '/logout';
};
var runAuth = function(id, token) {
@ -105,6 +105,23 @@ angular.module('habitrpg')
}, function( e ){
alert("Signin error: " + e.error.message );
});
}
};
$scope.clearLocalStorage = function () {
$scope.messageModal = {
title: window.env.t('localStorageClearing'),
body: window.env.t('localStorageClearingExplanation'),
noFooter: true,
};
$modal.open({
templateUrl: 'modals/message-modal.html',
scope: $scope
});
var threeSecondsForUsersToReadClearLocalStorageMessage = 3000;
setTimeout($scope.logout, threeSecondsForUsersToReadClearLocalStorageMessage);
};
}
]);

View file

@ -216,7 +216,7 @@ habitrpg.controller("InventoryCtrl",
var questArray = _.toArray(Content.quests);
var filteredArray = _.filter(questArray, function(q){
return q.key == "egg";
return q.key.indexOf('evilsanta') !== -1;
});
return filteredArray;

View file

@ -18,7 +18,7 @@ router.get('/', i18n.getUserLanguage, locals, function(req, res) {
// -------- Static Pages --------
var pages = ['front', 'privacy', 'terms', 'api', 'features', 'videos', 'contact', 'plans', 'new-stuff', 'community-guidelines', 'old-news', 'press-kit', 'faq', 'overview', 'apps'];
var pages = ['front', 'privacy', 'terms', 'api', 'features', 'videos', 'contact', 'plans', 'new-stuff', 'community-guidelines', 'old-news', 'press-kit', 'faq', 'overview', 'apps', 'clear-browser-data'];
_.each(pages, function(name){
router.get('/static/' + name, i18n.getUserLanguage, locals, function(req, res) {

View file

@ -1,17 +1,17 @@
.container-fluid
.stable.row: .col-xs-12
div(class="#{env.worldDmg.seasonalShop ? 'seasonalshop_broken' : 'seasonalshop_closed'}").pull-left-sm.col-centered
div(class="#{env.worldDmg.seasonalShop ? 'seasonalshop_broken' : 'seasonalshop_open'}").pull-left-sm.col-centered
.popover.static-popover.fade.right.in.pull-left-sm.col-centered
.arrow.hidden-xs
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
p(ng-if='!env.worldDmg.seasonalShop')!=env.t('seasonalShopClosedText')
p(ng-if='!env.worldDmg.seasonalShop')!=env.t('seasonalShopWinterText')
p(ng-if='env.worldDmg.seasonalShop')!=env.t('seasonalShopFallTextBroken')
// .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
menu.pets-menu(label='{{::label}}', ng-repeat='(set,label) in ::{fallWarrior:env.t("monsterOfScienceSet"), fallMage:env.t("witchyWizardSet"), fallHealer:env.t("mummyMedicSet"), fallRogue:env.t("vampireSmiterSet")}')
li.customize-menu.inventory-gear
menu.pets-menu(label='{{::label}}', ng-repeat='(set,label) in ::{yeti:env.t("yetiSet"), candycane:env.t("candycaneSet"), snowflake:env.t("snowflakeSet"), ski:env.t("skiSet"), winter2015Warrior:env.t("gingerbreadSet"), winter2015Mage:env.t("northMageSet"), winter2015Healer:env.t("soothingSkaterSet"), winter2015Rogue:env.t("icicleDrakeSet")}')
div(ng-repeat='item in ::getSeasonalShopArray(set)',
ng-class="{transparent: user.items.gear.owned[item.key] !== undefined}")
button.customize-option(class='shop_{{::item.key}}',
@ -30,26 +30,26 @@
popover-append-to-body='true', popover-title='{{::quest.text()}}',
popover-trigger='mouseenter', popover-placement='right',
ng-click='buyQuest(quest.key)')
p {{::quest.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems
p {{::quest.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems
menu.pets-menu(label=env.t('seasonalItems'))
div
button.customize-option(class='inventory_special_spookDust',
popover='{{::Content.spells.special.spookDust.notes()}}',
popover-title='{{::Content.spells.special.spookDust.text()}}',
button.customize-option(class='inventory_special_snowball',
popover='{{::Content.spells.special.snowball.notes()}}',
popover-title='{{::Content.spells.special.snowball.text()}}',
popover-trigger='mouseenter', popover-placement='right',
popover-append-to-body='true',
ng-click='purchase("special", Content.spells.special.spookDust)')
p {{::Content.spells.special.spookDust.value}}
ng-click='purchase("special", Content.spells.special.snowball)')
p {{::Content.spells.special.snowball.value}}
span(class='shop_gold')
div
button.customize-option(class='Pet_HatchingPotion_Spooky',
popover='{{::Content.hatchingPotions.Spooky.notes()}}',
popover-title!=env.t("potion", {potionType: "{{::Content.hatchingPotions.Spooky.text()}}"}),
button.customize-option(class='Pet_HatchingPotion_Peppermint',
popover='{{::Content.hatchingPotions.Peppermint.notes()}}',
popover-title!=env.t("potion", {potionType: "{{::Content.hatchingPotions.Peppermint.text()}}"}),
popover-trigger='mouseenter', popover-placement='right',
popover-append-to-body='true',
ng-click='purchase("hatchingPotions", Content.hatchingPotions.Spooky)')
p {{::Content.hatchingPotions.Spooky.value}}&nbsp;
ng-click='purchase("hatchingPotions", Content.hatchingPotions.Peppermint)')
p {{::Content.hatchingPotions.Peppermint.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems
// div

View file

@ -42,7 +42,7 @@ footer.footer(ng-controller='FooterCtrl')
li
a(target='_blank', href='/static/community-guidelines')=env.t('communityGuidelines')
li
a(target='_blank', href='https://github.com/HabitRPG/habitrpg/issues/2760')=env.t('communityBug')
a(target='_blank', href='/static/clear-browser-data')=env.t('communityBug')
li
a(target='_blank', href='https://trello.com/c/odmhIqyW/440-read-first-table-of-contents')=env.t('communityFeature')
li

View file

@ -1,3 +1,4 @@
include ./message-modal
include ./achievements
include ./reroll
include ./death

View file

@ -0,0 +1,9 @@
script(type='text/ng-template', id='modals/message-modal.html')
.modal-header
h3.text-center {{::messageModal.title}}
.modal-body
p {{::messageModal.body}}
p {{:: env.t('some') }}
.modal-footer(ng-if='::!messageModal.noFooter')
a.btn.btn-primary(ng-click='$close()')
=env.t('close')

Some files were not shown because too many files have changed in this diff Show more