Merge branch 'develop' into refactor-content

This commit is contained in:
Blade Barringer
2015-10-01 21:08:00 -05:00
86 changed files with 5065 additions and 4461 deletions

File diff suppressed because one or more lines are too long

View File

@@ -42,7 +42,7 @@
} }
.promo_dilatoryDistress { .promo_dilatoryDistress {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -837px -843px; background-position: -291px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -66,7 +66,7 @@
} }
.promo_enchanted_armoire_201509 { .promo_enchanted_armoire_201509 {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -291px -843px; background-position: -837px -843px;
width: 90px; width: 90px;
height: 90px; height: 90px;
} }
@@ -216,7 +216,7 @@
} }
.promo_pastel_skin { .promo_pastel_skin {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: 0px -668px; background-position: -331px -668px;
width: 330px; width: 330px;
height: 83px; height: 83px;
} }
@@ -240,7 +240,7 @@
} }
.promo_shimmer_hair { .promo_shimmer_hair {
background-image: url(spritesmith-largeSprites-0.png); background-image: url(spritesmith-largeSprites-0.png);
background-position: -331px -668px; background-position: 0px -668px;
width: 330px; width: 330px;
height: 83px; height: 83px;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 146 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 239 KiB

After

Width:  |  Height:  |  Size: 240 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

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

After

Width:  |  Height:  |  Size: 131 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 KiB

After

Width:  |  Height:  |  Size: 328 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 153 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 KiB

After

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

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 74 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: 18 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: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 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.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 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.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 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.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -9,125 +9,133 @@
"dropEggWolfText": "Wolf", "dropEggWolfText": "Wolf",
"dropEggWolfMountText": "Wolf", "dropEggWolfMountText": "Wolf",
"dropEggWolfAdjective": "loyal", "dropEggWolfAdjective": "a loyal",
"dropEggTigerCubText": "Tiger Cub", "dropEggTigerCubText": "Tiger Cub",
"dropEggTigerCubMountText": "Tiger", "dropEggTigerCubMountText": "Tiger",
"dropEggTigerCubAdjective": "fierce", "dropEggTigerCubAdjective": "a fierce",
"dropEggPandaCubText": "Panda Cub", "dropEggPandaCubText": "Panda Cub",
"dropEggPandaCubMountText": "Panda", "dropEggPandaCubMountText": "Panda",
"dropEggPandaCubAdjective": "gentle", "dropEggPandaCubAdjective": "a gentle",
"dropEggLionCubText": "Lion Cub", "dropEggLionCubText": "Lion Cub",
"dropEggLionCubMountText": "Lion", "dropEggLionCubMountText": "Lion",
"dropEggLionCubAdjective": "regal", "dropEggLionCubAdjective": "a regal",
"dropEggFoxText": "Fox", "dropEggFoxText": "Fox",
"dropEggFoxMountText": "Fox", "dropEggFoxMountText": "Fox",
"dropEggFoxAdjective": "wily", "dropEggFoxAdjective": "a wily",
"dropEggFlyingPigText": "Flying Pig", "dropEggFlyingPigText": "Flying Pig",
"dropEggFlyingPigMountText": "Flying Pig", "dropEggFlyingPigMountText": "Flying Pig",
"dropEggFlyingPigAdjective": "whimsical", "dropEggFlyingPigAdjective": "a whimsical",
"dropEggDragonText": "Dragon", "dropEggDragonText": "Dragon",
"dropEggDragonMountText": "Dragon", "dropEggDragonMountText": "Dragon",
"dropEggDragonAdjective": "mighty", "dropEggDragonAdjective": "a mighty",
"dropEggCactusText": "Cactus", "dropEggCactusText": "Cactus",
"dropEggCactusMountText": "Cactus", "dropEggCactusMountText": "Cactus",
"dropEggCactusAdjective": "prickly", "dropEggCactusAdjective": "a prickly",
"dropEggFlyingPigText": "Flying Pig",
"dropEggFlyingPigAdjective": "a whimsical",
"dropEggDragonText": "Dragon",
"dropEggDragonAdjective": "a mighty",
"dropEggCactusText": "Cactus",
"dropEggBearCubText": "Bear Cub", "dropEggBearCubText": "Bear Cub",
"dropEggBearCubMountText": "Bear", "dropEggBearCubMountText": "Bear",
"dropEggBearCubAdjective": "cuddly", "dropEggBearCubAdjective": "a cuddly",
"questEggGryphonText": "Gryphon", "questEggGryphonText": "Gryphon",
"questEggGryphonMountText": "Gryphon", "questEggGryphonMountText": "Gryphon",
"questEggGryphonAdjective": "proud", "questEggGryphonAdjective": "a proud",
"questEggHedgehogText": "Hedgehog", "questEggHedgehogText": "Hedgehog",
"questEggHedgehogMountText": "Hedgehog", "questEggHedgehogMountText": "Hedgehog",
"questEggHedgehogAdjective": "spiky", "questEggHedgehogAdjective": "a spiky",
"questEggDeerText": "Deer", "questEggDeerText": "Deer",
"questEggDeerMountText": "Deer", "questEggDeerMountText": "Deer",
"questEggDeerAdjective": "elegant", "questEggDeerAdjective": "an elegant",
"questEggEggText": "Egg", "questEggEggText": "Egg",
"questEggEggMountText": "Egg Basket", "questEggEggMountText": "Egg Basket",
"questEggEggAdjective": "colorful", "questEggEggAdjective": "a colorful",
"questEggRatText": "Rat", "questEggRatText": "Rat",
"questEggRatMountText": "Rat", "questEggRatMountText": "Rat",
"questEggRatAdjective": "dirty", "questEggRatAdjective": "a dirty",
"questEggOctopusText": "Octopus", "questEggOctopusText": "Octopus",
"questEggOctopusMountText": "Octopus", "questEggOctopusMountText": "Octopus",
"questEggOctopusAdjective": "slippery", "questEggOctopusAdjective": "a slippery",
"questEggSeahorseText": "Seahorse", "questEggSeahorseText": "Seahorse",
"questEggSeahorseMountText": "Seahorse", "questEggSeahorseMountText": "Seahorse",
"questEggSeahorseAdjective": "prize", "questEggSeahorseAdjective": "a prize",
"questEggParrotText": "Parrot", "questEggParrotText": "Parrot",
"questEggParrotMountText": "Parrot", "questEggParrotMountText": "Parrot",
"questEggParrotAdjective": "vibrant", "questEggParrotAdjective": "a vibrant",
"questEggRoosterText": "Rooster", "questEggRoosterText": "Rooster",
"questEggRoosterMountText": "Rooster", "questEggRoosterMountText": "Rooster",
"questEggRoosterAdjective": "strutting", "questEggRoosterAdjective": "a strutting",
"questEggSpiderText": "Spider", "questEggSpiderText": "Spider",
"questEggSpiderMountText": "Spider", "questEggSpiderMountText": "Spider",
"questEggSpiderAdjective": "creepy", "questEggSpiderAdjective": "a creepy",
"questEggOwlText": "Owl", "questEggOwlText": "Owl",
"questEggOwlMountText": "Owl", "questEggOwlMountText": "Owl",
"questEggOwlAdjective": "wise", "questEggOwlAdjective": "a wise",
"questEggPenguinText": "Penguin", "questEggPenguinText": "Penguin",
"questEggPenguinMountText": "Penguin", "questEggPenguinMountText": "Penguin",
"questEggPenguinAdjective": "perspicacious", "questEggPenguinAdjective": "a perspicacious",
"questEggTRexText": "Tyrannosaur", "questEggTRexText": "Tyrannosaur",
"questEggTRexMountText": "Tyrannosaur", "questEggTRexMountText": "Tyrannosaur",
"questEggTRexAdjective": "tiny-armed", "questEggTRexAdjective": "a tiny-armed",
"questEggRockText": "Rock", "questEggRockText": "Rock",
"questEggRockMountText": "Rock", "questEggRockMountText": "Rock",
"questEggRockAdjective": "lively", "questEggRockAdjective": "a lively",
"questEggBunnyText": "Bunny", "questEggBunnyText": "Bunny",
"questEggBunnyMountText": "Bunny", "questEggBunnyMountText": "Bunny",
"questEggBunnyAdjective": "snuggly", "questEggBunnyAdjective": "a snuggly",
"questEggSlimeText": "Marshmallow Slime", "questEggSlimeText": "Marshmallow Slime",
"questEggSlimeMountText": "Marshmallow Slime", "questEggSlimeMountText": "Marshmallow Slime",
"questEggSlimeAdjective": "sweet", "questEggSlimeAdjective": "a sweet",
"questEggSheepText": "Sheep", "questEggSheepText": "Sheep",
"questEggSheepMountText": "Sheep", "questEggSheepMountText": "Sheep",
"questEggSheepAdjective": "woolly", "questEggSheepAdjective": "a woolly",
"questEggCuttlefishText": "Cuttlefish", "questEggCuttlefishText": "Cuttlefish",
"questEggCuttlefishMountText": "Cuttlefish", "questEggCuttlefishMountText": "Cuttlefish",
"questEggCuttlefishAdjective": "cuddly", "questEggCuttlefishAdjective": "a cuddly",
"questEggWhaleText": "Whale", "questEggWhaleText": "Whale",
"questEggWhaleMountText": "Whale", "questEggWhaleMountText": "Whale",
"questEggWhaleAdjective": "splashy", "questEggWhaleAdjective": "a splashy",
"questEggCheetahText": "Cheetah", "questEggCheetahText": "Cheetah",
"questEggCheetahMountText": "Cheetah", "questEggCheetahMountText": "Cheetah",
"questEggCheetahAdjective": "honest", "questEggCheetahAdjective": "an honest",
"questEggHorseText": "Horse", "questEggHorseText": "Horse",
"questEggHorseMountText": "Horse", "questEggHorseMountText": "Horse",
"questEggHorseAdjective": "galloping", "questEggHorseAdjective": "a galloping",
"eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into a <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.",
"hatchingPotionBase": "Base", "hatchingPotionBase": "Base",
"hatchingPotionWhite": "White", "hatchingPotionWhite": "White",
@@ -139,8 +147,10 @@
"hatchingPotionCottonCandyPink": "Cotton Candy Pink", "hatchingPotionCottonCandyPink": "Cotton Candy Pink",
"hatchingPotionCottonCandyBlue": "Cotton Candy Blue", "hatchingPotionCottonCandyBlue": "Cotton Candy Blue",
"hatchingPotionGolden": "Golden", "hatchingPotionGolden": "Golden",
"hatchingPotionSpooky": "Spooky",
"hatchingPotionNotes": "Pour this on an egg, and it will hatch as a <%= potText(locale) %> pet.", "hatchingPotionNotes": "Pour this on an egg, and it will hatch as a <%= potText(locale) %> pet.",
"premiumPotionAddlNotes": "Not usable on quest pet eggs.",
"foodMeat": "Meat", "foodMeat": "Meat",
"foodMilk": "Milk", "foodMilk": "Milk",

View File

@@ -170,6 +170,8 @@
"weaponArmoireIronCrookNotes": "Fiercely hammered from iron, this iron crook is good at herding sheep. Increases Perception and Strength by <%= attrs %> each. Enchanted Armoire: Horned Iron Set (Item 3 of 3)", "weaponArmoireIronCrookNotes": "Fiercely hammered from iron, this iron crook is good at herding sheep. Increases Perception and Strength by <%= attrs %> each. Enchanted Armoire: Horned Iron Set (Item 3 of 3)",
"weaponArmoireGoldWingStaffText": "Gold Wing Staff", "weaponArmoireGoldWingStaffText": "Gold Wing Staff",
"weaponArmoireGoldWingStaffNotes": "The wings on this staff constantly flutter and twist. Increases all attributes by <%= attrs %> each. Enchanted Armoire: Independent Item.", "weaponArmoireGoldWingStaffNotes": "The wings on this staff constantly flutter and twist. Increases all attributes by <%= attrs %> each. Enchanted Armoire: Independent Item.",
"weaponArmoireBatWandText": "Bat Wand",
"weaponArmoireBatWandNotes": "This wand can turn any task into a bat! Wave it about and watch them fly away. Increases Intelligence by <%= int %> and Perception by <%= per %>. Enchanted Armoire: Independent Item.",
"armor": "armor", "armor": "armor",
@@ -542,6 +544,10 @@
"headArmoireRedFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a radiant red color. Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.", "headArmoireRedFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a radiant red color. Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.",
"headArmoirePlagueDoctorHatText": "Plague Doctor Hat", "headArmoirePlagueDoctorHatText": "Plague Doctor Hat",
"headArmoirePlagueDoctorHatNotes": "An authentic hat worn by the doctors who battle the Plague of Procrastination! Increases Strength by <%= str %>, Intelligence by <%= int %>, and Constitution by <%= con %>. Enchanted Armoire: Plague Doctor Set (Item 1 of 3).", "headArmoirePlagueDoctorHatNotes": "An authentic hat worn by the doctors who battle the Plague of Procrastination! Increases Strength by <%= str %>, Intelligence by <%= int %>, and Constitution by <%= con %>. Enchanted Armoire: Plague Doctor Set (Item 1 of 3).",
"headArmoireBlackCatText": "Black Cat Hat",
"headArmoireBlackCatNotes": "This black hat is... purring. And twitching its tail. And breathing? Yeah, you just have a sleeping cat on your head. Increases Intelligence and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.",
"headArmoireOrangeCatText": "Orange Cat Hat",
"headArmoireOrangeCatNotes": "This orange hat is... purring. And twitching its tail. And breathing? Yeah, you just have a sleeping cat on your head. Increases Strength and Constitution by <%= attrs %> each. Enchanted Armoire: Independent Item.",
"offhand": "shield-hand item", "offhand": "shield-hand item",
@@ -639,6 +645,8 @@
"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).",
"shieldArmoireMidnightShieldText": "Midnight Shield",
"shieldArmoireMidnightShieldNotes": "This shield is most powerful at the stroke of midnight! Increases Constitution by <%= con %> and Strength by <%= str %>. Enchanted Armoire: Independent Item.",
"back": "Back Accessory", "back": "Back Accessory",
"backBase0Text": "No Back Accessory", "backBase0Text": "No Back Accessory",

View File

@@ -59,5 +59,6 @@
"monsterOfScienceSet": "Monster of Science (Warrior)", "monsterOfScienceSet": "Monster of Science (Warrior)",
"witchyWizardSet": "Witchy Wizard (Mage)", "witchyWizardSet": "Witchy Wizard (Mage)",
"mummyMedicSet": "Mummy Medic (Healer)", "mummyMedicSet": "Mummy Medic (Healer)",
"vampireSmiterSet": "Vampire Smiter (Rogue)" "vampireSmiterSet": "Vampire Smiter (Rogue)",
"fallEventAvailability": "Available until October 31"
} }

View File

@@ -5,6 +5,7 @@
"messageTagNotFound": "Tag not found.", "messageTagNotFound": "Tag not found.",
"messagePetNotFound": ":pet not found in user.items.pets", "messagePetNotFound": ":pet not found in user.items.pets",
"messageFoodNotFound": ":food not found in user.items.food", "messageFoodNotFound": ":food not found in user.items.food",
"messageNotAvailable": "This item is not currently available for purchase.",
"messageCannotFeedPet": "Can't feed this pet.", "messageCannotFeedPet": "Can't feed this pet.",
"messageAlreadyMount": "You already have that mount. Try feeding another pet.", "messageAlreadyMount": "You already have that mount. Try feeding another pet.",
"messageEvolve": "You have tamed <%= egg %>, let's go for a ride!", "messageEvolve": "You have tamed <%= egg %>, let's go for a ride!",
@@ -14,6 +15,7 @@
"messageEquipped": " <%= itemText %> equipped.", "messageEquipped": " <%= itemText %> equipped.",
"messageUnEquipped": "<%= itemText %> un-equipped.", "messageUnEquipped": "<%= itemText %> un-equipped.",
"messageMissingEggPotion": "You're missing either that egg or that potion", "messageMissingEggPotion": "You're missing either that egg or that potion",
"messageInvalidEggPotionCombo": "You can't hatch Quest Pet Eggs with Magic Hatching Potions! Try a different egg.",
"messageAlreadyPet": "You already have that pet. Try hatching a different combination!", "messageAlreadyPet": "You already have that pet. Try hatching a different combination!",
"messageHatched": "Your egg hatched! Visit your stable to equip your pet.", "messageHatched": "Your egg hatched! Visit your stable to equip your pet.",
"messageNotEnoughGold": "Not Enough Gold", "messageNotEnoughGold": "Not Enough Gold",

View File

@@ -1,11 +1,13 @@
{ {
"pets": "Pets", "pets": "Pets",
"petsFound": "Pets Found", "petsFound": "Pets Found",
"magicPets": "Magic Potion Pets",
"rarePets": "Rare Pets", "rarePets": "Rare Pets",
"questPets": "Quest Pets", "questPets": "Quest Pets",
"mounts": "Mounts", "mounts": "Mounts",
"mountsTamed": "Mounts Tamed", "mountsTamed": "Mounts Tamed",
"questMounts": "Quest Mounts", "questMounts": "Quest Mounts",
"magicMounts": "Magic Potion Mounts",
"rareMounts": "Rare Mounts", "rareMounts": "Rare Mounts",
"etherealLion": "Ethereal Lion", "etherealLion": "Ethereal Lion",
"veteranWolf": "Veteran Wolf", "veteranWolf": "Veteran Wolf",
@@ -24,13 +26,15 @@
"eggSingular": "egg", "eggSingular": "egg",
"noEggs": "You don't have any eggs.", "noEggs": "You don't have any eggs.",
"hatchingPotions": "Hatching Potions", "hatchingPotions": "Hatching Potions",
"magicHatchingPotions": "<strong>Magic Hatching Potions</strong>",
"hatchingPotion": "hatching potion", "hatchingPotion": "hatching potion",
"noHatchingPotions": "You don't have any hatching potions.", "noHatchingPotions": "You don't have any hatching potions.",
"inventoryText": "Click an egg to see usable potions highlighted in green and then click one of the highlighted potions to hatch your pet. If no potions are highlighted, click that egg again to deselect it, and instead click a potion first to have the usable eggs highlighted. You can also sell unwanted drops to Alexander the Merchant.", "inventoryText": "Click an egg to see usable potions highlighted in green and then click one of the highlighted potions to hatch your pet. If no potions are highlighted, click that egg again to deselect it, and instead click a potion first to have the usable eggs highlighted. You can also sell unwanted drops to Alexander the Merchant.",
"foodText": "food", "foodText": "food",
"food": "Food and Saddles", "food": "Food and Saddles",
"noFood": "You don't have any food or saddles.", "noFood": "You don't have any food or saddles.",
"dropsExplanation": "Get these items faster with gems if you don't want to wait for them to drop when completing a task. <a href=\"http://habitica.wikia.com/wiki/Drops\">Learn more about the drop system.</a>", "dropsExplanation": "Get these items faster with Gems if you don't want to wait for them to drop when completing a task. <a href=\"http://habitica.wikia.com/wiki/Drops\">Learn more about the drop system.</a>",
"premiumPotionNoDropExplanation": "Magic Hatching Potions cannot be used on eggs received from Quests. The only way to get Magic Hatching Potions is by buying them below, not from random drops.",
"beastMasterProgress": "Beast Master Progress", "beastMasterProgress": "Beast Master Progress",
"stableBeastMasterProgress": "Beast Master Progress: <%= number %> Pets Found", "stableBeastMasterProgress": "Beast Master Progress: <%= number %> Pets Found",
"beastAchievement": "You have earned the \"Beast Master\" Achievement for collecting all the pets!", "beastAchievement": "You have earned the \"Beast Master\" Achievement for collecting all the pets!",

View File

@@ -767,7 +767,7 @@ api.wrap = (user, main=true) ->
if food.key is 'Saddle' if food.key is 'Saddle'
evolve() evolve()
else else
if food.target is potion if food.target is potion or content.hatchingPotions[potion].premium
userPets[pet] += 5 userPets[pet] += 5
message = i18n.t('messageLikesFood', {egg: petDisplayName, foodText: food.text(req.language)}, req.language) message = i18n.t('messageLikesFood', {egg: petDisplayName, foodText: food.text(req.language)}, req.language)
else else
@@ -823,7 +823,8 @@ api.wrap = (user, main=true) ->
item = content[type][key] item = content[type][key]
price = item.value / 4 price = item.value / 4
return cb?({code:404,message:":key not found for Content.#{type}"},req) unless item return cb?({code:404,message:":key not found for Content.#{type}"},req) unless item
return cb?({code:401, message: i18n.t('notEnoughGems', req.language)}) if (user.balance < price) or !user.balance return cb?({code:403, message: i18n.t('messageNotAvailable', req.language)}) if not item.canBuy(user)
return cb?({code:403, message: i18n.t('notEnoughGems', req.language)}) if (user.balance < price) or !user.balance
user.balance -= price user.balance -= price
if type is 'gear' then user.items.gear.owned[key] = true if type is 'gear' then user.items.gear.owned[key] = true
else else
@@ -1071,10 +1072,11 @@ api.wrap = (user, main=true) ->
hatch: (req, cb) -> hatch: (req, cb) ->
{egg, hatchingPotion} = req.params {egg, hatchingPotion} = req.params
return cb?({code:404,message:"Please specify query.egg & query.hatchingPotion"}) unless egg and hatchingPotion return cb?({code:400,message:"Please specify query.egg & query.hatchingPotion"}) unless egg and hatchingPotion
return cb?({code:401,message:i18n.t('messageMissingEggPotion', req.language)}) unless user.items.eggs[egg] > 0 and user.items.hatchingPotions[hatchingPotion] > 0 return cb?({code:403,message:i18n.t('messageMissingEggPotion', req.language)}) unless user.items.eggs[egg] > 0 and user.items.hatchingPotions[hatchingPotion] > 0
return cb?({code:403,message:i18n.t('messageInvalidEggPotionCombo', req.language)}) if content.hatchingPotions[hatchingPotion].premium and not content.dropEggs[egg]
pet = "#{egg}-#{hatchingPotion}" pet = "#{egg}-#{hatchingPotion}"
return cb?({code:401, message:i18n.t('messageAlreadyPet', req.language)}) if user.items.pets[pet] and user.items.pets[pet] > 0 return cb?({code:403, message:i18n.t('messageAlreadyPet', req.language)}) if user.items.pets[pet] and user.items.pets[pet] > 0
user.items.pets[pet] = 5 user.items.pets[pet] = 5
user.items.eggs[egg]-- user.items.eggs[egg]--
user.items.hatchingPotions[hatchingPotion]-- user.items.hatchingPotions[hatchingPotion]--
@@ -1530,7 +1532,7 @@ api.wrap = (user, main=true) ->
# Eggs: 30% chance # Eggs: 30% chance
else if rarity > .3 else if rarity > .3
drop = user.fns.randomVal _.where(content.eggs,{canBuy:true}) drop = user.fns.randomVal content.dropEggs
user.items.eggs[drop.key] ?= 0 user.items.eggs[drop.key] ?= 0
user.items.eggs[drop.key]++ user.items.eggs[drop.key]++
drop.type = 'Egg' drop.type = 'Egg'

View File

@@ -12,6 +12,15 @@ const DROP_EGGS = [
'BearCub', 'BearCub',
]; ];
let eggs = generateEggs(DROP_EGGS, {type: 'drop', canBuy: true}); let eggDefaults = {
type: 'drop',
canBuy: () => {
return () => {
return true;
};
},
};
let eggs = generateEggs(DROP_EGGS, eggDefaults);
export default eggs; export default eggs;

View File

@@ -24,6 +24,41 @@ const QUEST_EGGS = [
'Horse', 'Horse',
]; ];
let eggs = generateEggs(QUEST_EGGS, {type: 'quest', canBuy: false}); let eggDefaults = {
type: 'quest',
canBuy: (key) => {
return _generateQuestAchievementRequirement(key);
},
};
let eggs = generateEggs(QUEST_EGGS, eggDefaults);
// Exceptions to normal defaults
eggs.TRex.canBuy = (user) => {
let achievements = user.achievements.quests;
if (achievements) {
return achievements.trex > 0 ||
achievements.trex_undead > 0;
}
}
eggs.Deer.canBuy = _generateQuestAchievementRequirement('ghost_stag');
eggs.Seahorse.canBuy = _generateQuestAchievementRequirement('dilatory_derby');
eggs.Parrot.canBuy = _generateQuestAchievementRequirement('harpy');
eggs.Cuttlefish.canBuy = _generateQuestAchievementRequirement('kraken');
eggs.Egg.canBuy = () => { return false; }
function _generateQuestAchievementRequirement(name) {
return (user) => {
let achievements = user.achievements.quests;
let questKey = name.toLowerCase();
if (achievements) {
return achievements[questKey] > 0;
}
};
}
export default eggs; export default eggs;

View File

@@ -194,7 +194,29 @@ let head = {
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.head_armoire_plagueDoctorHat != null; return u.items.gear.owned.head_armoire_plagueDoctorHat != null;
}) })
} },
blackCat: {
notes: t('headArmoireBlackCatNotes', {
attrs: 9
}),
value: 100,
int: 9,
per: 9,
canOwn: (function(u) {
return u.items.gear.owned.head_armoire_blackCat != null;
})
},
orangeCat: {
notes: t('headArmoireOrangeCatNotes', {
attrs: 9
}),
value: 100,
con: 9,
str: 9,
canOwn: (function(u) {
return u.items.gear.owned.head_armoire_orangeCat != null;
})
},
}; };
let shield = { let shield = {
@@ -279,6 +301,14 @@ let weapon = {
canOwn: (function(u) { canOwn: (function(u) {
return u.items.gear.owned.weapon_armoire_goldWingStaff != null; return u.items.gear.owned.weapon_armoire_goldWingStaff != null;
}) })
},
batWand: {
value: 100,
int: 10,
per: 2,
canOwn: (function(u) {
return u.items.gear.owned.weapon_armoire_batWand != null;
})
} }
}; };

View File

@@ -126,24 +126,28 @@ let armor = {
event: events.fall, event: events.fall,
specialClass: 'rogue', specialClass: 'rogue',
value: 90, value: 90,
canBuy: () => { return true; },
per: 15 per: 15
}, },
fallWarrior: { fallWarrior: {
event: events.fall, event: events.fall,
specialClass: 'warrior', specialClass: 'warrior',
value: 90, value: 90,
canBuy: () => { return true; },
con: 9 con: 9
}, },
fallMage: { fallMage: {
event: events.fall, event: events.fall,
specialClass: 'wizard', specialClass: 'wizard',
value: 90, value: 90,
canBuy: () => { return true; },
int: 9 int: 9
}, },
fallHealer: { fallHealer: {
event: events.fall, event: events.fall,
specialClass: 'healer', specialClass: 'healer',
value: 90, value: 90,
canBuy: () => { return true; },
con: 15 con: 15
}, },
winter2015Rogue: { winter2015Rogue: {
@@ -453,24 +457,28 @@ let head = {
event: events.fall, event: events.fall,
specialClass: 'rogue', specialClass: 'rogue',
value: 60, value: 60,
canBuy: () => { return true; },
per: 9 per: 9
}, },
fallWarrior: { fallWarrior: {
event: events.fall, event: events.fall,
specialClass: 'warrior', specialClass: 'warrior',
value: 60, value: 60,
canBuy: () => { return true; },
str: 9 str: 9
}, },
fallMage: { fallMage: {
event: events.fall, event: events.fall,
specialClass: 'wizard', specialClass: 'wizard',
value: 60, value: 60,
canBuy: () => { return true; },
per: 7 per: 7
}, },
fallHealer: { fallHealer: {
event: events.fall, event: events.fall,
specialClass: 'healer', specialClass: 'healer',
value: 60, value: 60,
canBuy: () => { return true; },
int: 7 int: 7
}, },
winter2015Rogue: { winter2015Rogue: {
@@ -627,6 +635,7 @@ let headAccessory = {
text: t('headAccessoryBearEarsText'), text: t('headAccessoryBearEarsText'),
notes: t('headAccessoryBearEarsNotes'), notes: t('headAccessoryBearEarsNotes'),
value: 20, value: 20,
canBuy: () => { return true; },
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.headAccessory_special_bearEars != null; return u.items.gear.owned.headAccessory_special_bearEars != null;
}) })
@@ -636,6 +645,7 @@ let headAccessory = {
text: t('headAccessoryCactusEarsText'), text: t('headAccessoryCactusEarsText'),
notes: t('headAccessoryCactusEarsNotes'), notes: t('headAccessoryCactusEarsNotes'),
value: 20, value: 20,
canBuy: () => { return true; },
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.headAccessory_special_cactusEars != null; return u.items.gear.owned.headAccessory_special_cactusEars != null;
}) })
@@ -645,6 +655,7 @@ let headAccessory = {
text: t('headAccessoryFoxEarsText'), text: t('headAccessoryFoxEarsText'),
notes: t('headAccessoryFoxEarsNotes'), notes: t('headAccessoryFoxEarsNotes'),
value: 20, value: 20,
canBuy: () => { return true; },
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.headAccessory_special_foxEars != null; return u.items.gear.owned.headAccessory_special_foxEars != null;
}) })
@@ -654,6 +665,7 @@ let headAccessory = {
text: t('headAccessoryLionEarsText'), text: t('headAccessoryLionEarsText'),
notes: t('headAccessoryLionEarsNotes'), notes: t('headAccessoryLionEarsNotes'),
value: 20, value: 20,
canBuy: () => { return true; },
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.headAccessory_special_lionEars != null; return u.items.gear.owned.headAccessory_special_lionEars != null;
}) })
@@ -663,6 +675,7 @@ let headAccessory = {
text: t('headAccessoryPandaEarsText'), text: t('headAccessoryPandaEarsText'),
notes: t('headAccessoryPandaEarsNotes'), notes: t('headAccessoryPandaEarsNotes'),
value: 20, value: 20,
canBuy: () => { return true; },
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.headAccessory_special_pandaEars != null; return u.items.gear.owned.headAccessory_special_pandaEars != null;
}) })
@@ -672,6 +685,7 @@ let headAccessory = {
text: t('headAccessoryPigEarsText'), text: t('headAccessoryPigEarsText'),
notes: t('headAccessoryPigEarsNotes'), notes: t('headAccessoryPigEarsNotes'),
value: 20, value: 20,
canBuy: () => { return true; },
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.headAccessory_special_pigEars != null; return u.items.gear.owned.headAccessory_special_pigEars != null;
}) })
@@ -681,6 +695,7 @@ let headAccessory = {
text: t('headAccessoryTigerEarsText'), text: t('headAccessoryTigerEarsText'),
notes: t('headAccessoryTigerEarsNotes'), notes: t('headAccessoryTigerEarsNotes'),
value: 20, value: 20,
canBuy: () => { return true; },
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.headAccessory_special_tigerEars != null; return u.items.gear.owned.headAccessory_special_tigerEars != null;
}) })
@@ -690,6 +705,7 @@ let headAccessory = {
text: t('headAccessoryWolfEarsText'), text: t('headAccessoryWolfEarsText'),
notes: t('headAccessoryWolfEarsNotes'), notes: t('headAccessoryWolfEarsNotes'),
value: 20, value: 20,
canBuy: () => { return true; },
canOwn: ((u) => { canOwn: ((u) => {
return u.items.gear.owned.headAccessory_special_wolfEars != null; return u.items.gear.owned.headAccessory_special_wolfEars != null;
}) })
@@ -799,18 +815,21 @@ let shield = {
event: events.fall, event: events.fall,
specialClass: 'rogue', specialClass: 'rogue',
value: 80, value: 80,
canBuy: () => { return true; },
str: 8 str: 8
}, },
fallWarrior: { fallWarrior: {
event: events.fall, event: events.fall,
specialClass: 'warrior', specialClass: 'warrior',
value: 70, value: 70,
canBuy: () => { return true; },
con: 7 con: 7
}, },
fallHealer: { fallHealer: {
event: events.fall, event: events.fall,
specialClass: 'healer', specialClass: 'healer',
value: 70, value: 70,
canBuy: () => { return true; },
con: 9 con: 9
}, },
winter2015Rogue: { winter2015Rogue: {
@@ -1036,12 +1055,14 @@ let weapon = {
event: events.fall, event: events.fall,
specialClass: 'rogue', specialClass: 'rogue',
value: 80, value: 80,
canBuy: () => { return true; },
str: 8 str: 8
}, },
fallWarrior: { fallWarrior: {
event: events.fall, event: events.fall,
specialClass: 'warrior', specialClass: 'warrior',
value: 90, value: 90,
canBuy: () => { return true; },
str: 15 str: 15
}, },
fallMage: { fallMage: {
@@ -1049,6 +1070,7 @@ let weapon = {
specialClass: 'wizard', specialClass: 'wizard',
twoHanded: true, twoHanded: true,
value: 160, value: 160,
canBuy: () => { return true; },
int: 15, int: 15,
per: 7 per: 7
}, },
@@ -1056,6 +1078,7 @@ let weapon = {
event: events.fall, event: events.fall,
specialClass: 'healer', specialClass: 'healer',
value: 90, value: 90,
canBuy: () => { return true; },
int: 9 int: 9
}, },
winter2015Rogue: { winter2015Rogue: {

View File

@@ -1,6 +1,10 @@
import {setHatchingPotionDefaults} from './helpers'; import {
merge,
translator as t,
setHatchingPotionDefaults
} from './helpers';
let hatchingPotions = { let dropPotions = {
Base: { Base: {
value: 2, value: 2,
}, },
@@ -30,9 +34,25 @@ let hatchingPotions = {
}, },
Golden: { Golden: {
value: 5, value: 5,
} },
}; };
setHatchingPotionDefaults(hatchingPotions); let premiumPotions = {
Spooky: {
value: 2,
addlNotes: t('premiumPotionAddlNotes'),
premium: true,
limited: true,
},
};
export default hatchingPotions; setHatchingPotionDefaults(dropPotions);
setHatchingPotionDefaults(premiumPotions);
let allPotions = merge([dropPotions, premiumPotions]);
export default {
all: allPotions,
drop: dropPotions,
premium: premiumPotions,
};

View File

@@ -59,13 +59,14 @@ export function setSpellDefaults (className, spells) {
export function setFoodDefaults(food, options={}) { export function setFoodDefaults(food, options={}) {
each(food, (item, name) => { each(food, (item, name) => {
let formattedName = formatForTranslator(name); let formattedName = formatForTranslator(name);
let canBuy = () => { return options.canBuy; };
defaults(item, { defaults(item, {
key: name, key: name,
text: translator(`food${formattedName}`), text: translator(`food${formattedName}`),
notes: translator('foodNotes'), notes: translator('foodNotes'),
value: 1, value: 1,
canBuy: options.canBuy || false, canBuy: canBuy,
canDrop: options.canDrop || false, canDrop: options.canDrop || false,
}); });
}); });
@@ -78,6 +79,7 @@ export function setHatchingPotionDefaults(hatchingPotions) {
key: key, key: key,
value: 2, value: 2,
text: text, text: text,
canBuy: () => { return true },
notes: translator('hatchingPotionNotes', { notes: translator('hatchingPotionNotes', {
potText: text potText: text
}), }),
@@ -93,7 +95,7 @@ export function setQuestDefaults(quests) {
key: key, key: key,
text: translator(`quest${formattedName}Text`), text: translator(`quest${formattedName}Text`),
notes: translator(`quest${formattedName}Notes`), notes: translator(`quest${formattedName}Notes`),
canBuy: true, canBuy: () => { return true; },
value: 4, value: 4,
}; };
@@ -149,6 +151,7 @@ export function setGearSetDefaults(gearSet, options={}) {
let gearDefaults = { let gearDefaults = {
text: translator(text), text: translator(text),
notes: translator(notes, attributes), notes: translator(notes, attributes),
canBuy: () => { return false; },
} }
defaults(item, gearDefaults); defaults(item, gearDefaults);
@@ -183,11 +186,11 @@ export function generateBackgrounds(sets) {
export function generateEggs(set, options={}) { export function generateEggs(set, options={}) {
let eggs = {}; let eggs = {};
let type = options.type; let type = options.type;
let canBuy = options.canBuy;
each(set, (pet) => { each(set, (pet) => {
let text = translator(`${type}Egg${pet}Text`); let text = translator(`${type}Egg${pet}Text`);
let adj = translator(`${type}Egg${pet}Adjective`); let adj = translator(`${type}Egg${pet}Adjective`);
let canBuy = options.canBuy(pet);
eggs[pet] = { eggs[pet] = {
text: text, text: text,

View File

@@ -26,7 +26,11 @@ import {
specialMounts, specialMounts,
} from './pets-mounts/index'; } from './pets-mounts/index';
import timeTravelStable from './time-traveler-stable'; import timeTravelStable from './time-traveler-stable';
import hatchingPotions from './hatching-potions'; import {
all as allHatchingPotions,
drop as dropHatchingPotions,
premium as premiumHatchingPotions,
} from './hatching-potions';
import food from './food/index'; import food from './food/index';
import { import {
all as allQuests, all as allQuests,
@@ -66,7 +70,9 @@ export default {
special: special, special: special,
// Item Drops // Item Drops
hatchingPotions: hatchingPotions, dropHatchingPotions: dropHatchingPotions,
premiumHatchingPotions: premiumHatchingPotions,
hatchingPotions: allHatchingPotions,
food: food, food: food,
// Eggs // Eggs

View File

@@ -16,21 +16,26 @@ import {transform, defaults} from 'lodash';
// <fake_potion> - if a unique animal, potion is Base, if it's a special version of an existing animal, the fake potion is a different from a normal hatching potion // <fake_potion> - if a unique animal, potion is Base, if it's a special version of an existing animal, the fake potion is a different from a normal hatching potion
//-------------------------------------------------- //--------------------------------------------------
import hatchingPotions from '../hatching-potions'; import {
drop as dropHatchingPotions,
premium as premiumHatchingPotions,
} from '../hatching-potions';
import dropEggs from '../eggs/drops'; import dropEggs from '../eggs/drops';
import questEggs from '../eggs/quest'; import questEggs from '../eggs/quest';
import specialPets from './special-pets'; import specialPets from './special-pets';
import specialMounts from './special-mounts'; import specialMounts from './special-mounts';
let dropPets = generateAnimalSet(dropEggs); let dropPets = generateAnimalSet(dropEggs, dropHatchingPotions);
let questPets = generateAnimalSet(questEggs); let premiumPets = generateAnimalSet(dropEggs, premiumHatchingPotions);
let dropMounts = generateAnimalSet(dropEggs); let questPets = generateAnimalSet(questEggs, dropHatchingPotions);
let questMounts = generateAnimalSet(questEggs); let dropMounts = generateAnimalSet(dropEggs, dropHatchingPotions);
let premiumMounts = generateAnimalSet(dropEggs, premiumHatchingPotions);
let questMounts = generateAnimalSet(questEggs, dropHatchingPotions);
function generateAnimalSet(set) { function generateAnimalSet(eggSet, potionSet) {
return transform(set, (m, egg) => { return transform(eggSet, (m, egg) => {
defaults(m, transform(hatchingPotions, (m2, pot) => { defaults(m, transform(potionSet, (m2, pot) => {
return m2[egg.key + "-" + pot.key] = true; return m2[egg.key + "-" + pot.key] = true;
})); }));
}); });
@@ -39,6 +44,8 @@ function generateAnimalSet(set) {
export default { export default {
dropPets: dropPets, dropPets: dropPets,
dropMounts: dropMounts, dropMounts: dropMounts,
premiumPets: premiumPets,
premiumMounts: premiumMounts,
questPets: questPets, questPets: questPets,
questMounts: questMounts, questMounts: questMounts,
specialPets: specialPets, specialPets: specialPets,

View File

@@ -117,7 +117,7 @@ let holidayQuests = {
let questDefaults = (name) => { let questDefaults = (name) => {
return { return {
completion: t(`quest${name}Completion`), completion: t(`quest${name}Completion`),
canBuy: false, canBuy: () => { return false; },
category: 'pet', category: 'pet',
} }
}; };

View File

@@ -160,7 +160,7 @@ let questDefaults = (name) => {
return { return {
completion: t(`quest${name}Completion`), completion: t(`quest${name}Completion`),
value: 0, value: 0,
canBuy: false, canBuy: () => { return false; },
category: 'world', category: 'world',
} }
}; };

View File

@@ -544,7 +544,7 @@ describe 'User', ->
expect(quest.notes()).to.be.an('string') expect(quest.notes()).to.be.an('string')
expect(quest.completion()).to.be.an('string') if quest.completion expect(quest.completion()).to.be.an('string') if quest.completion
expect(quest.previous).to.be.an('string') if quest.previous expect(quest.previous).to.be.an('string') if quest.previous
expect(quest.value).to.be.greaterThan 0 if quest.canBuy expect(quest.value).to.be.greaterThan 0 if quest.canBuy()
expect(quest.drop.gp).to.not.be.lessThan 0 expect(quest.drop.gp).to.not.be.lessThan 0
expect(quest.drop.exp).to.not.be.lessThan 0 expect(quest.drop.exp).to.not.be.lessThan 0
expect(quest.category).to.match(/pet|unlockable|gold|world/) expect(quest.category).to.match(/pet|unlockable|gold|world/)

View File

@@ -26,6 +26,16 @@ describe('count', function() {
expect(beastMasterTotal).to.eql(1); expect(beastMasterTotal).to.eql(1);
}); });
it('does not count pets hatched with premium potions', function() {
var pets = {
"Wolf-Spooky": 5,
"Dragon-Spooky": 5,
"FlyingPig-Base": 5
}
var beastMasterTotal = count.beastMasterProgress(pets);
expect(beastMasterTotal).to.eql(1);
});
it('does not count special pets', function() { it('does not count special pets', function() {
var pets = { var pets = {
"Wolf-Base": 2, "Wolf-Base": 2,
@@ -65,6 +75,15 @@ describe('count', function() {
expect(mountMasterTotal).to.eql(2); expect(mountMasterTotal).to.eql(2);
}); });
it('does not count premium mounts', function() {
var mounts = {
"Dragon-Red": true,
"FlyingPig-Spooky": true
}
var mountMasterTotal = count.mountMasterProgress(mounts);
expect(mountMasterTotal).to.eql(1);
});
it('does not count quest mounts', function() { it('does not count quest mounts', function() {
var mounts = { "Dragon-Red": true, "Gryphon-Base": true }; var mounts = { "Dragon-Red": true, "Gryphon-Base": true };
var mountMasterTotal = count.mountMasterProgress(mounts); var mountMasterTotal = count.mountMasterProgress(mounts);

View File

@@ -0,0 +1,139 @@
var sinon = require('sinon');
var chai = require('chai');
chai.use(require('sinon-chai'))
var expect = chai.expect
require('coffee-script');
var shared = require('../../common/script/index.coffee');
var content = require('../../common/script/content/index.coffee');
describe('user.ops.hatch', function() {
var user;
beforeEach(function() {
user = {
items: {
eggs: {},
hatchingPotions: {},
pets: {}
}
};
shared.wrap(user);
});
context('Pet Hatching', function() {
context('failure conditions', function() {
it('does not allow hatching without specifying egg and potion', function(done) {
user.ops.hatch({params:{}},function(response) {
expect(response.message).to.eql('Please specify query.egg & query.hatchingPotion');
expect(user.items.pets).to.be.empty;
done();
});
});
it('does not allow hatching if user lacks specified egg', function(done) {
user.items.eggs = {'Wolf':1};
user.items.hatchingPotions = {'Base':1};
user.ops.hatch({params:{egg:'Dragon',hatchingPotion:'Base'}}, function(response) {
expect(response.message).to.eql(shared.i18n.t('messageMissingEggPotion'));
expect(user.items.pets).to.be.empty;
expect(user.items.eggs).to.eql({'Wolf':1});
expect(user.items.hatchingPotions).to.eql({'Base':1});
done();
});
});
it('does not allow hatching if user lacks specified hatching potion', function(done) {
user.items.eggs = {'Wolf':1};
user.items.hatchingPotions = {'Base':1};
user.ops.hatch({params:{egg:'Wolf',hatchingPotion:'Golden'}}, function(response) {
expect(response.message).to.eql(shared.i18n.t('messageMissingEggPotion'));
expect(user.items.pets).to.be.empty;
expect(user.items.eggs).to.eql({'Wolf':1});
expect(user.items.hatchingPotions).to.eql({'Base':1});
done();
});
});
it('does not allow hatching if user already owns target pet', function(done) {
user.items.eggs = {'Wolf':1};
user.items.hatchingPotions = {'Base':1};
user.items.pets = {'Wolf-Base':10};
user.ops.hatch({params:{egg:'Wolf',hatchingPotion:'Base'}}, function(response) {
expect(response.message).to.eql(shared.i18n.t('messageAlreadyPet'));
expect(user.items.pets).to.eql({'Wolf-Base':10});
expect(user.items.eggs).to.eql({'Wolf':1});
expect(user.items.hatchingPotions).to.eql({'Base':1});
done();
});
});
it('does not allow hatching quest pet egg using premium potion', function(done) {
user.items.eggs = {'Cheetah':1};
user.items.hatchingPotions = {'Spooky':1};
user.ops.hatch({params:{egg:'Cheetah',hatchingPotion:'Spooky'}}, function(response) {
expect(response.message).to.eql(shared.i18n.t('messageInvalidEggPotionCombo'));
expect(user.items.pets).to.be.empty;
expect(user.items.eggs).to.eql({'Cheetah':1});
expect(user.items.hatchingPotions).to.eql({'Spooky':1});
done();
});
});
});
context('successful hatching', function() {
it('hatches a basic pet', function(done) {
user.items.eggs = {'Wolf':1};
user.items.hatchingPotions = {'Base':1};
user.ops.hatch({params:{egg:'Wolf',hatchingPotion:'Base'}}, function(response) {
expect(response.message).to.eql(shared.i18n.t('messageHatched'));
expect(user.items.pets).to.eql({'Wolf-Base':5});
expect(user.items.eggs).to.eql({'Wolf':0});
expect(user.items.hatchingPotions).to.eql({'Base':0});
done();
});
});
it('hatches a quest pet', function(done) {
user.items.eggs = {'Cheetah':1};
user.items.hatchingPotions = {'Base':1};
user.ops.hatch({params:{egg:'Cheetah',hatchingPotion:'Base'}}, function(response) {
expect(response.message).to.eql(shared.i18n.t('messageHatched'));
expect(user.items.pets).to.eql({'Cheetah-Base':5});
expect(user.items.eggs).to.eql({'Cheetah':0});
expect(user.items.hatchingPotions).to.eql({'Base':0});
done();
});
});
it('hatches a premium pet', function(done) {
user.items.eggs = {'Wolf':1};
user.items.hatchingPotions = {'Spooky':1};
user.ops.hatch({params:{egg:'Wolf',hatchingPotion:'Spooky'}}, function(response) {
expect(response.message).to.eql(shared.i18n.t('messageHatched'));
expect(user.items.pets).to.eql({'Wolf-Spooky':5});
expect(user.items.eggs).to.eql({'Wolf':0});
expect(user.items.hatchingPotions).to.eql({'Spooky':0});
done();
});
});
it('hatches a pet previously raised to a mount', function(done) {
user.items.eggs = {'Wolf':1};
user.items.hatchingPotions = {'Base':1};
user.items.pets = {'Wolf-Base':-1};
user.ops.hatch({params:{egg:'Wolf',hatchingPotion:'Base'}}, function(response) {
expect(response.message).to.eql(shared.i18n.t('messageHatched'));
expect(user.items.pets).to.eql({'Wolf-Base':5});
expect(user.items.eggs).to.eql({'Wolf':0});
expect(user.items.hatchingPotions).to.eql({'Base':0});
done();
});
});
});
});
});

View File

@@ -24,7 +24,8 @@ describe('Stats Service', function() {
"Deer-Golden" : 5, "Deer-Golden" : 5,
"Deer-Red" : 5, "Deer-Red" : 5,
"Egg-Desert" : 5, "Egg-Desert" : 5,
"MantisShrimp-Base" : 5 "MantisShrimp-Base" : 5,
"Wolf-Spooky": 5
} }
var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets); var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets);
@@ -38,9 +39,10 @@ describe('Stats Service', function() {
"BearCub-CottonCandyBlue" : -1, "BearCub-CottonCandyBlue" : -1,
"Cactus-Zombie" : 5, "Cactus-Zombie" : 5,
"Deer-Golden" : 5, "Deer-Golden" : 5,
"Deer-Red" : 5, "Deer-Red" : -1,
"Egg-Desert" : 5, "Egg-Desert" : 5,
"MantisShrimp-Base" : 5 "MantisShrimp-Base" : 5,
"Wolf-Spooky": -1
} }
var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets); var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets);
@@ -221,7 +223,8 @@ describe('Stats Service', function() {
"Wolf-Golden" : true, "Wolf-Golden" : true,
"Owl-CottonCandyBlue" : true, "Owl-CottonCandyBlue" : true,
"Mammoth-Base" : true, "Mammoth-Base" : true,
"Bunny-Skeleton" : true "Bunny-Skeleton" : true,
"Tiger-Spooky": true
} }
var mountMasterDisplay = statCalc.mountMasterProgress(user.items.mounts); var mountMasterDisplay = statCalc.mountMasterProgress(user.items.mounts);
@@ -237,7 +240,8 @@ describe('Stats Service', function() {
"Wolf-Golden" : false, "Wolf-Golden" : false,
"Owl-CottonCandyBlue" : true, "Owl-CottonCandyBlue" : true,
"Mammoth-Base" : true, "Mammoth-Base" : true,
"Bunny-Skeleton" : true "Bunny-Skeleton" : true,
"Tiger-Spooky": true
} }
var mountMasterDisplay = statCalc.mountMasterProgress(user.items.mounts); var mountMasterDisplay = statCalc.mountMasterProgress(user.items.mounts);

View File

@@ -232,10 +232,10 @@ var UserSchema = new Schema({
_.defaults( _.defaults(
// First transform to a 1D eggs/potions mapping // First transform to a 1D eggs/potions mapping
_.transform(shared.content.pets, function(m,v,k){ m[k] = Number; }), _.transform(shared.content.pets, function(m,v,k){ m[k] = Number; }),
// Then add quest pets // Then add additional pets (quest, backer, contributor, premium)
_.transform(shared.content.questPets, function(m,v,k){ m[k] = Number; }), _.transform(shared.content.questPets, function(m,v,k){ m[k] = Number; }),
// Then add additional pets (backer, contributor) _.transform(shared.content.specialPets, function(m,v,k){ m[k] = Number; }),
_.transform(shared.content.specialPets, function(m,v,k){ m[k] = Number; }) _.transform(shared.content.premiumPets, function(m,v,k){ m[k] = Number; })
), ),
currentPet: String, // Cactus-Desert currentPet: String, // Cactus-Desert
@@ -265,9 +265,10 @@ var UserSchema = new Schema({
mounts: _.defaults( mounts: _.defaults(
// First transform to a 1D eggs/potions mapping // First transform to a 1D eggs/potions mapping
_.transform(shared.content.pets, function(m,v,k){ m[k] = Boolean; }), _.transform(shared.content.pets, function(m,v,k){ m[k] = Boolean; }),
// Then add quest pets // Then add quest and premium pets
_.transform(shared.content.questPets, function(m,v,k){ m[k] = Boolean; }), _.transform(shared.content.questPets, function(m,v,k){ m[k] = Boolean; }),
// Then add additional pets (backer, contributor) _.transform(shared.content.premiumPets, function(m,v,k){ m[k] = Boolean; }),
// Then add additional mounts (backer, contributor)
_.transform(shared.content.specialMounts, function(m,v,k){ m[k] = Boolean; }) _.transform(shared.content.specialMounts, function(m,v,k){ m[k] = Boolean; })
), ),
currentMount: String, currentMount: String,

View File

@@ -10,7 +10,7 @@
p.muted(ng-show='eggCount < 1')=env.t('noEggs') p.muted(ng-show='eggCount < 1')=env.t('noEggs')
div(ng-repeat='(egg,points) in ownedItems(user.items.eggs)') div(ng-repeat='(egg,points) in ownedItems(user.items.eggs)')
button.customize-option(class='Pet_Egg_{{::egg}}', button.customize-option(class='Pet_Egg_{{::egg}}',
ng-class='{selectableInventory: selectedPotion && !(user.items.pets[egg+"-"+selectedPotion.key]>0)}', ng-class='{selectableInventory: selectedPotion && !(user.items.pets[egg+"-"+selectedPotion.key]>0) && (Content.dropEggs[egg] || !selectedPotion.premium)}',
popover='{{::Content.eggs[egg].notes()}}', popover-append-to-body='true', popover='{{::Content.eggs[egg].notes()}}', popover-append-to-body='true',
popover-title!=env.t("egg", {eggType: "{{::Content.eggs[egg].text()}}"}), popover-title!=env.t("egg", {eggType: "{{::Content.eggs[egg].text()}}"}),
popover-trigger='mouseenter', popover-placement='right', popover-trigger='mouseenter', popover-placement='right',
@@ -18,12 +18,12 @@
.badge.badge-info.stack-count {{points}} .badge.badge-info.stack-count {{points}}
li.customize-menu li.customize-menu
menu.hatchingPotion-menu(label=(env.t('hatchingPotions') + ' ({{potCount}})')) menu.pets-menu(label=(env.t('hatchingPotions') + ' ({{potCount}})'))
p.muted(ng-show='potCount < 1')=env.t('noHatchingPotions') p.muted(ng-show='potCount < 1')=env.t('noHatchingPotions')
div(ng-repeat='(pot,points) in ownedItems(user.items.hatchingPotions)') div(ng-repeat='(pot,points) in ownedItems(user.items.hatchingPotions)')
button.customize-option(class='Pet_HatchingPotion_{{::pot}}', button.customize-option(class='Pet_HatchingPotion_{{::pot}}',
ng-class='{selectableInventory: selectedEgg && !(user.items.pets[selectedEgg.key+"-"+pot]>0)}', ng-class='{selectableInventory: selectedEgg && !(user.items.pets[selectedEgg.key+"-"+pot]>0) && (Content.dropEggs[selectedEgg.key] || !Content.hatchingPotions[pot].premium)}',
popover='{{::Content.hatchingPotions[pot].notes()}}', popover='{{::Content.hatchingPotions[pot].notes()}} {{::Content.hatchingPotions[pot].addlNotes()}}',
popover-title!=env.t("potion", {potionType: "{{::Content.hatchingPotions[pot].text()}}"}), popover-title!=env.t("potion", {potionType: "{{::Content.hatchingPotions[pot].text()}}"}),
popover-trigger='mouseenter', popover-placement='right', popover-trigger='mouseenter', popover-placement='right',
popover-append-to-body='true', popover-append-to-body='true',
@@ -102,7 +102,7 @@
menu.pets-menu(label=env.t('eggs')) menu.pets-menu(label=env.t('eggs'))
p.muted!=env.t('dropsExplanation') p.muted!=env.t('dropsExplanation')
div(ng-repeat='egg in Content.eggs', ng-if='egg.canBuy') div(ng-repeat='egg in Content.eggs', ng-if='egg.canBuy(user)')
button.customize-option(class='Pet_Egg_{{::egg.key}}', button.customize-option(class='Pet_Egg_{{::egg.key}}',
popover='{{::egg.notes()}}', popover-append-to-body='true', popover='{{::egg.notes()}}', popover-append-to-body='true',
popover-title!=env.t("egg", {eggType: "{{::egg.text()}}"}), popover-title!=env.t("egg", {eggType: "{{::egg.text()}}"}),
@@ -110,31 +110,11 @@
ng-click='purchase("eggs", egg)') ng-click='purchase("eggs", egg)')
p {{::egg.value}}&nbsp; p {{::egg.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems span.Pet_Currency_Gem1x.inline-gems
//- buyable quest eggs. TODO: Get this from a collection so we don't have to maintain this ridiculous comma-delimited list
//- The hard part will be the trex stuff, since it is allowed to exist with two quests
each egg,quest in {gryphon:'Gryphon',hedgehog:'Hedgehog',ghost_stag:'Deer',rat:'Rat',octopus:'Octopus',dilatory_derby:'Seahorse',harpy:'Parrot',rooster:'Rooster',spider:'Spider',owl:'Owl',penguin:'Penguin',rock:'Rock',bunny:'Bunny',slime:'Slime',sheep:'Sheep',kraken:'Cuttlefish',whale:'Whale',cheetah:'Cheetah',horse:'Horse'}
div(ng-show='user.achievements.quests.#{quest} > 0')
button.customize-option(class='Pet_Egg_#{egg}',
popover='{{::Content.eggs.#{egg}.notes()}}', popover-append-to-body='true',
popover-title!=env.t("egg", {eggType: "{{::Content.eggs.#{egg}.text()}}"}),
popover-trigger='mouseenter', popover-placement='top',
ng-click='purchase("eggs", Content.eggs.#{egg})')
p {{::Content.eggs.#{egg}.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems
div(ng-show='(user.achievements.quests.trex + user.achievements.quests.trex_undead) > 0')
button.customize-option(class='Pet_Egg_TRex',
popover='{{::Content.eggs.TRex.notes()}}', popover-append-to-body='true',
popover-title!=env.t("egg", {eggType: "{{Content.eggs.TRex.text()}}"}),
popover-trigger='mouseenter', popover-placement='top',
ng-click='purchase("eggs", Content.eggs.TRex)')
p {{::Content.eggs.TRex.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems
li.customize-menu li.customize-menu
menu.pets-menu(label=env.t('hatchingPotions')) menu.pets-menu(label=env.t('hatchingPotions'))
p.muted!=env.t('dropsExplanation') p.muted!=env.t('dropsExplanation')
div(ng-repeat='pot in Content.hatchingPotions') div(ng-repeat='pot in Content.hatchingPotions', ng-if='!pot.premium')
button.customize-option(class='Pet_HatchingPotion_{{::pot.key}}', button.customize-option(class='Pet_HatchingPotion_{{::pot.key}}',
popover='{{::pot.notes()}}', popover-append-to-body='true', popover='{{::pot.notes()}}', popover-append-to-body='true',
popover-title!=env.t("potion", {potionType: "{{::pot.text()}}"}), popover-title!=env.t("potion", {potionType: "{{::pot.text()}}"}),
@@ -144,10 +124,23 @@
| {{::pot.value}}&nbsp; | {{::pot.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems span.Pet_Currency_Gem1x.inline-gems
li.customize-menu
menu.pets-menu!=env.t('magicHatchingPotions') + " - " + env.t('fallEventAvailability')
p.muted=env.t('premiumPotionNoDropExplanation')
div(ng-repeat='pot in Content.hatchingPotions', ng-if='pot.premium && pot.canBuy(user)')
button.customize-option(class='Pet_HatchingPotion_{{::pot.key}}',
popover='{{::pot.notes()}} {{::pot.addlNotes()}}', popover-append-to-body='true',
popover-title!=env.t("potion", {potionType: "{{::pot.text()}}"}),
popover-trigger='mouseenter', popover-placement='top',
ng-click='purchase("hatchingPotions", pot)')
p
| {{::pot.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems
li.customize-menu li.customize-menu
menu.pets-menu(label=env.t('food')) menu.pets-menu(label=env.t('food'))
p.muted!=env.t('dropsExplanation') p.muted!=env.t('dropsExplanation')
div(ng-repeat='food in Content.food', ng-if='food.canBuy') div(ng-repeat='food in Content.food', ng-if='food.canBuy(user)')
button.customize-option(class='Pet_Food_{{::food.key}}', button.customize-option(class='Pet_Food_{{::food.key}}',
popover='{{::food.notes()}}', popover-title='{{::food.text()}}', popover='{{::food.notes()}}', popover-title='{{::food.text()}}',
popover-trigger='mouseenter', popover-placement='top', popover-trigger='mouseenter', popover-placement='top',

View File

@@ -1,15 +1,14 @@
mixin mountList(source) mixin mountList(eggSource, potionSource)
menu.pets(type='list') menu.pets(type='list')
each egg in source each egg in eggSource
-if(!egg.noMount) { -if(!egg.noMount) {
li.customize-menu li.customize-menu
menu menu
each potion in env.Content.hatchingPotions each potion in potionSource
- mount = egg.key+"-"+potion.key - mount = egg.key+"-"+potion.key
div(popover-trigger='mouseenter', popover=env.t('mountName', {potion: potion.text(env.language.code), mount: egg.mountText(env.language.code)}), popover-placement='bottom') div(popover-trigger='mouseenter', popover=env.t('mountName', {potion: potion.text(env.language.code), mount: egg.mountText(env.language.code)}), popover-placement='bottom')
button(class="pet-button Mount_Head_#{mount}", ng-show='user.items.mounts["#{mount}"]', ng-class='{active: user.items.currentMount == "#{mount}"}', ng-click='chooseMount("#{egg.key}", "#{potion.key}")') button(class="pet-button Mount_Head_#{mount}", ng-show='user.items.mounts["#{mount}"]', ng-class='{active: user.items.currentMount == "#{mount}"}', ng-click='chooseMount("#{egg.key}", "#{potion.key}")')
//div(class='Mount_Head_{{mount}}') button(class="pet-button mount-not-owned", ng-if='!user.items.mounts["#{mount}"] && (#{potion.canBuy()} || user.items.hatchingPotions["#{potion.key}"] || user.items.pets["#{mount}"])')
button(class="pet-button mount-not-owned", ng-hide='user.items.mounts["#{mount}"]')
.PixelPaw .PixelPaw
-} -}
@@ -24,10 +23,23 @@ mixin mountList(source)
p=env.t('mattShall', {name: "{{user.profile.name}}"}) p=env.t('mattShall', {name: "{{user.profile.name}}"})
h4 {{:: env.t('stableMountMasterProgress', { number: mountMasterProgress }) }} h4 {{:: env.t('stableMountMasterProgress', { number: mountMasterProgress }) }}
.row: .col-md-12 .row: .col-md-12
+mountList(env.Content.dropEggs) +mountList(env.Content.dropEggs,env.Content.dropHatchingPotions)
.row: .col-md-12
h4=env.t('magicMounts')
menu.pets(type='list')
each potion in env.Content.premiumHatchingPotions
li.customize-menu
menu
each egg in env.Content.dropEggs
- mount = egg.key+"-"+potion.key
div(popover-trigger='mouseenter', popover=env.t('mountName', {potion: potion.text(env.language.code), mount: egg.mountText(env.language.code)}), popover-placement='bottom')
button(class="pet-button Mount_Head_#{mount}", ng-show='user.items.mounts["#{mount}"]', ng-class='{active: user.items.currentMount == "#{mount}"}', ng-click='chooseMount("#{egg.key}", "#{potion.key}")')
button(class="pet-button mount-not-owned", ng-if='!user.items.mounts["#{mount}"] && (#{potion.canBuy()} || user.items.hatchingPotions["#{potion.key}"] || user.items.pets["#{mount}"])')
.PixelPaw
.row: .col-md-12 .row: .col-md-12
h4=env.t('questMounts') h4=env.t('questMounts')
+mountList(env.Content.questEggs) +mountList(env.Content.questEggs,env.Content.dropHatchingPotions)
.row: .col-md-12 .row: .col-md-12
h4=env.t('rareMounts') h4=env.t('rareMounts')
menu menu

View File

@@ -1,15 +1,15 @@
mixin petList(source) mixin petList(eggSource, potionSource)
menu.pets(type='list') menu.pets(type='list')
each egg in source each egg in eggSource
li.customize-menu li.customize-menu
menu menu
each potion in env.Content.hatchingPotions each potion in potionSource
- pet = egg.key+"-"+potion.key - pet = egg.key+"-"+potion.key
div(popover-trigger='mouseenter', popover=env.t('petName', {potion: potion.text(env.language.code), egg: egg.text(env.language.code)}), popover-placement='bottom') div(popover-trigger='mouseenter', popover=env.t('petName', {potion: potion.text(env.language.code), egg: egg.text(env.language.code)}), popover-placement='bottom')
button(class="pet-button Pet-#{pet}", ng-if='user.items.pets["#{pet}"]>0', ng-class='{active: user.items.currentPet == "#{pet}", selectableInventory: #{!egg.noMount} && selectedFood && !user.items.mounts["#{pet}"]}', ng-click='choosePet("#{egg.key}", "#{potion.key}")') button(class="pet-button Pet-#{pet}", ng-if='user.items.pets["#{pet}"]>0', ng-class='{active: user.items.currentPet == "#{pet}", selectableInventory: #{!egg.noMount} && selectedFood && !user.items.mounts["#{pet}"]}', ng-click='choosePet("#{egg.key}", "#{potion.key}")')
.progress(ng-show='!user.items.mounts["#{pet}"]') .progress(ng-show='!user.items.mounts["#{pet}"]')
.progress-bar.progress-bar-success(ng-style='{width: user.items.pets["#{pet}"]/.5 + "%"}') .progress-bar.progress-bar-success(ng-style='{width: user.items.pets["#{pet}"]/.5 + "%"}')
button(class="pet-button pet-not-owned", ng-if='!user.items.pets["#{pet}"]') button(class="pet-button pet-not-owned", ng-if='!user.items.pets["#{pet}"] && (#{potion.canBuy()} || user.items.hatchingPotions["#{potion.key}"])')
.PixelPaw .PixelPaw
button(class="pet-evolved pet-button Pet-#{pet}", ng-if='user.items.pets["#{pet}"]<0') button(class="pet-evolved pet-button Pet-#{pet}", ng-if='user.items.pets["#{pet}"]<0')
@@ -24,10 +24,25 @@ mixin petList(source)
p=env.t('mattBochText1') p=env.t('mattBochText1')
h4 {{:: env.t('stableBeastMasterProgress', { number: beastMasterProgress }) }} h4 {{:: env.t('stableBeastMasterProgress', { number: beastMasterProgress }) }}
.row: .col-md-12 .row: .col-md-12
+petList(env.Content.dropEggs) +petList(env.Content.dropEggs,env.Content.dropHatchingPotions)
.row: .col-md-12
h4=env.t('magicPets')
menu.pets(type='list')
each potion in env.Content.premiumHatchingPotions
li.customize-menu
menu
each egg in env.Content.dropEggs
- pet = egg.key+"-"+potion.key
div(popover-trigger='mouseenter', popover=env.t('petName', {potion: potion.text(env.language.code), egg: egg.text(env.language.code)}), popover-placement='bottom')
button(class="pet-button Pet-#{pet}", ng-if='user.items.pets["#{pet}"]>0', ng-class='{active: user.items.currentPet == "#{pet}", selectableInventory: #{!egg.noMount} && selectedFood && !user.items.mounts["#{pet}"]}', ng-click='choosePet("#{egg.key}", "#{potion.key}")')
.progress(ng-show='!user.items.mounts["#{pet}"]')
.progress-bar.progress-bar-success(ng-style='{width: user.items.pets["#{pet}"]/.5 + "%"}')
button(class="pet-button pet-not-owned", ng-if='!user.items.pets["#{pet}"] && (#{potion.canBuy()} || user.items.hatchingPotions["#{potion.key}"])')
.PixelPaw
button(class="pet-evolved pet-button Pet-#{pet}", ng-if='user.items.pets["#{pet}"]<0')
.row: .col-md-12 .row: .col-md-12
h4=env.t('questPets') h4=env.t('questPets')
+petList(env.Content.questEggs) +petList(env.Content.questEggs,env.Content.dropHatchingPotions)
.row: .col-md-12 .row: .col-md-12
h4=env.t('rarePets') h4=env.t('rarePets')

View File

@@ -19,7 +19,7 @@ include ../../shared/mixins
h3.equipment-title=env.t('questsForSale') h3.equipment-title=env.t('questsForSale')
div(ng-repeat='type in Content.userCanOwnQuestCategories') div(ng-repeat='type in Content.userCanOwnQuestCategories')
menu.pets-menu(label='{{env.t(type + "Quests")}}') menu.pets-menu(label='{{env.t(type + "Quests")}}')
div(ng-repeat='quest in Content.questsByLevel', ng-if='quest.canBuy && quest.category === type') div(ng-repeat='quest in Content.questsByLevel', ng-if='quest.canBuy(user) && quest.category === type')
button.customize-option(ng-class='lockQuest(quest) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"', button.customize-option(ng-class='lockQuest(quest) ? "inventory_quest_scroll_locked inventory_quest_scroll_{{::quest.key}}_locked locked" : "inventory_quest_scroll inventory_quest_scroll_{{::quest.key}}"',
data-popover-html="{{::lockQuest(quest,true) ? env.t('scrollsPre') : questPopover(quest) | markdown}}", data-popover-html="{{::lockQuest(quest,true) ? env.t('scrollsPre') : questPopover(quest) | markdown}}",
popover-title='{{::quest.text()}}', popover-append-to-body="true", popover-title='{{::quest.text()}}', popover-append-to-body="true",

View File

@@ -33,7 +33,7 @@
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(class='shop_spookDust', button.customize-option(class='inventory_special_spookDust',
popover='{{::Content.spells.special.spookDust.notes()}}', popover='{{::Content.spells.special.spookDust.notes()}}',
popover-title='{{::Content.spells.special.spookDust.text()}}', popover-title='{{::Content.spells.special.spookDust.text()}}',
popover-trigger='mouseenter', popover-placement='right', popover-trigger='mouseenter', popover-placement='right',
@@ -41,6 +41,15 @@
ng-click='purchase("special", Content.spells.special.spookDust)') ng-click='purchase("special", Content.spells.special.spookDust)')
p {{::Content.spells.special.spookDust.value}} p {{::Content.spells.special.spookDust.value}}
span(class='shop_gold') 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()}}"}),
popover-trigger='mouseenter', popover-placement='right',
popover-append-to-body='true',
ng-click='purchase("hatchingPotions", Content.hatchingPotions.Spooky)')
p {{::Content.hatchingPotions.Spooky.value}}&nbsp;
span.Pet_Currency_Gem1x.inline-gems
// div // div
button.customize-option(popover='{{::Content.spells.special.nye.notes()}}', popover-title='{{::Content.spells.special.nye.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='castStart(Content.spells.special.nye)', class='inventory_special_nye') button.customize-option(popover='{{::Content.spells.special.nye.notes()}}', popover-title='{{::Content.spells.special.nye.text()}}', popover-trigger='mouseenter', popover-placement='right', popover-append-to-body='true', ng-click='castStart(Content.spells.special.nye)', class='inventory_special_nye')

View File

@@ -1,5 +1,46 @@
h2 9/24/2015 - HAUNTED HAIR COLORS, SUPERNATURAL SKIN SET, AND WEREWOLF SUBSCRIBER ITEM! PLUS, THE FALL PLOT-LINE CONTINUES... h2 10/1/2015 - SPOOKY HATCHING POTION; NEW ITEMS IN THE ENCHANTED ARMOIRE
hr hr
tr
td
.Pet-Wolf-Spooky.pull-right
h3 Spooky Hatching Potions
p We've released a new feature: Magic Hatching Potions!
br
p Between now and October 31st, you can buy Spooky Hatching Potions from <a href='/#/options/inventory/drops'>the Market</a> and use them to hatch any standard pet egg. (Magic Hatching Potions do not work on Quest Pet eggs.) You'll find it very easy to care for your new Spooky Pets: they're from the Flourishing Fields, so they love to eat every kind of food!
br
p Spooky Hatching Potions are a Seasonal Edition item, so they will only be available during the Fall Festival each year! Be sure to get them while you can.
p.small.muted by Lemoness and SabreCat
tr
td
.head_armoire_orangeCat.pull-right
h3 New Items in the Enchanted Armoire
p There is new equipment in Enchanted Armoire, a 100 GP Reward in the Rewards Column which unlocks after you've attained Ultimate Gear!
br
p Click on the Enchanted Armoire for a random chance at special Equipment, including the Black Cat Hat, Orange Cat Hat, Midnight Shield, and Bat Wing Wand! It may also give you random XP or food items. We'll be adding new equipment to it during the first week of each month, but even when you've exhausted the current supply, you can keep clicking for a chance at food and XP.
br
p Now go spend all that accumulated Gold! May the Random Number Generator smile upon you...
p.small.muted by Lemoness and SabreCat
p.small.muted art by Kiwibot and UncommonCriminal
if menuItem !== 'oldNews'
hr
a(href='/static/old-news', target='_blank') Read older news
mixin oldNews
h2 9/30/2015 - LAST CHANCE FOR WEREWOLF ARMOR SET; BACK-TO-SCHOOL CHALLENGE WINNERS ANNOUNCED
tr
td
h3 Last Chance for Werewolf Armor Set
.promo_mystery_201509.pull-right
p Reminder: this is the final day to <a href='/#/options/settings/subscription'>subscribe</a> and receive the Werewolf Armor Set! If you want the Werewolf Costume or the Werewolf Mask, now's the time! Thanks so much for your support.
tr
td
h3 Back-to-School Challenge Winners!
p The winners of the Back-to-School Challenge have been selected! Congratulations to: Randy, Jenn, AnnDeLune, Sh1n1 DeFier, Velinde, Nadine, citrusella, Thiago Coascci, Alicia Puck Vickery, and goblin.
br
p Thank you to everyone who shared your tips!
h2 9/24/2015 - HAUNTED HAIR COLORS, SUPERNATURAL SKIN SET, AND WEREWOLF SUBSCRIBER ITEM! PLUS, THE FALL PLOT-LINE CONTINUES...
tr tr
td td
h3 Haunted Hair Colors and Supernatural Skin Set h3 Haunted Hair Colors and Supernatural Skin Set
@@ -25,11 +66,6 @@ h2 9/24/2015 - HAUNTED HAIR COLORS, SUPERNATURAL SKIN SET, AND WEREWOLF SUBSCRIB
br br
p Some blame the unseasonal heat wave that has begun in the past few days. Others point to the difficulty of the tasks, and their ever-increasing quantity. And a few people -- just a few -- murmur that some of the hardest-working citizens have been disappearing, one by one, leaving their obligations abandoned. But surely that is nothing more than rumor? p Some blame the unseasonal heat wave that has begun in the past few days. Others point to the difficulty of the tasks, and their ever-increasing quantity. And a few people -- just a few -- murmur that some of the hardest-working citizens have been disappearing, one by one, leaving their obligations abandoned. But surely that is nothing more than rumor?
if menuItem !== 'oldNews'
hr
a(href='/static/old-news', target='_blank') Read older news
mixin oldNews
h2 9/21/2015 - FALL FESTIVAL! LIMITED-EDITION OUTFITS, SEASONAL SHOP, CANDY FOOD DROPS, AND NPC DRESS-UP h2 9/21/2015 - FALL FESTIVAL! LIMITED-EDITION OUTFITS, SEASONAL SHOP, CANDY FOOD DROPS, AND NPC DRESS-UP
tr tr
td td