Merge pull request #5962 from HabitRPG/sabrecat/magic-potions

Magic Potions!
This commit is contained in:
Sabe Jones 2015-10-01 14:04:14 -05:00
commit 233211adc9
44 changed files with 406 additions and 185 deletions

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

@ -8,101 +8,101 @@
"armoireNotesEmpty": "The Armoire will have new Equipment in the first week of every month. Until then, keep clicking for Experience and Food!",
"dropEggWolfText": "Wolf",
"dropEggWolfAdjective": "loyal",
"dropEggWolfAdjective": "a loyal",
"dropEggTigerCubText": "Tiger Cub",
"dropEggTigerCubMountText": "Tiger",
"dropEggTigerCubAdjective": "fierce",
"dropEggTigerCubAdjective": "a fierce",
"dropEggPandaCubText": "Panda Cub",
"dropEggPandaCubMountText": "Panda",
"dropEggPandaCubAdjective": "gentle",
"dropEggPandaCubAdjective": "a gentle",
"dropEggLionCubText": "Lion Cub",
"dropEggLionCubMountText": "Lion",
"dropEggLionCubAdjective": "regal",
"dropEggLionCubAdjective": "a regal",
"dropEggFoxText": "Fox",
"dropEggFoxAdjective": "wily",
"dropEggFoxAdjective": "a wily",
"dropEggFlyingPigText": "Flying Pig",
"dropEggFlyingPigAdjective": "whimsical",
"dropEggFlyingPigAdjective": "a whimsical",
"dropEggDragonText": "Dragon",
"dropEggDragonAdjective": "mighty",
"dropEggDragonAdjective": "a mighty",
"dropEggCactusText": "Cactus",
"dropEggCactusAdjective": "prickly",
"dropEggCactusAdjective": "a prickly",
"dropEggBearCubText": "Bear Cub",
"dropEggBearCubMountText": "Bear",
"dropEggBearCubAdjective": "cuddly",
"dropEggBearCubAdjective": "a cuddly",
"questEggGryphonText": "Gryphon",
"questEggGryphonAdjective": "proud",
"questEggGryphonAdjective": "a proud",
"questEggHedgehogText": "Hedgehog",
"questEggHedgehogAdjective": "spiky",
"questEggHedgehogAdjective": "a spiky",
"questEggDeerText": "Deer",
"questEggDeerAdjective": "elegant",
"questEggDeerAdjective": "an elegant",
"questEggEggText": "Egg",
"questEggEggMountText": "Egg Basket",
"questEggEggAdjective": "colorful",
"questEggEggAdjective": "a colorful",
"questEggRatText": "Rat",
"questEggRatAdjective": "dirty",
"questEggRatAdjective": "a dirty",
"questEggOctopusText": "Octopus",
"questEggOctopusAdjective": "slippery",
"questEggOctopusAdjective": "a slippery",
"questEggSeahorseText": "Seahorse",
"questEggSeahorseAdjective": "prize",
"questEggSeahorseAdjective": "a prize",
"questEggParrotText": "Parrot",
"questEggParrotAdjective": "vibrant",
"questEggParrotAdjective": "a vibrant",
"questEggRoosterText": "Rooster",
"questEggRoosterAdjective": "strutting",
"questEggRoosterAdjective": "a strutting",
"questEggSpiderText": "Spider",
"questEggSpiderAdjective": "creepy",
"questEggSpiderAdjective": "a creepy",
"questEggOwlText": "Owl",
"questEggOwlAdjective": "wise",
"questEggOwlAdjective": "a wise",
"questEggPenguinText": "Penguin",
"questEggPenguinAdjective": "perspicacious",
"questEggPenguinAdjective": "a perspicacious",
"questEggTRexText": "Tyrannosaur",
"questEggTRexAdjective": "tiny-armed",
"questEggTRexAdjective": "a tiny-armed",
"questEggRockText": "Rock",
"questEggRockAdjective": "lively",
"questEggRockAdjective": "a lively",
"questEggBunnyText": "Bunny",
"questEggBunnyAdjective": "snuggly",
"questEggBunnyAdjective": "a snuggly",
"questEggSlimeText": "Marshmallow Slime",
"questEggSlimeAdjective": "sweet",
"questEggSlimeAdjective": "a sweet",
"questEggSheepText": "Sheep",
"questEggSheepAdjective": "woolly",
"questEggSheepAdjective": "a woolly",
"questEggCuttlefishText": "Cuttlefish",
"questEggCuttlefishAdjective": "cuddly",
"questEggCuttlefishAdjective": "a cuddly",
"questEggWhaleText": "Whale",
"questEggWhaleAdjective": "splashy",
"questEggWhaleAdjective": "a splashy",
"questEggCheetahText": "Cheetah",
"questEggCheetahAdjective": "honest",
"questEggCheetahAdjective": "an honest",
"questEggHorseText": "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",
"hatchingPotionWhite": "White",
@ -114,8 +114,10 @@
"hatchingPotionCottonCandyPink": "Cotton Candy Pink",
"hatchingPotionCottonCandyBlue": "Cotton Candy Blue",
"hatchingPotionGolden": "Golden",
"hatchingPotionSpooky": "Spooky",
"hatchingPotionNotes": "Pour this on an egg, and it will hatch as a <%= potText(locale) %> pet.",
"premiumPotionAddlNotes": "Not usable on quest pet eggs.",
"foodMeat": "Meat",
"foodMilk": "Milk",

View file

@ -59,5 +59,6 @@
"monsterOfScienceSet": "Monster of Science (Warrior)",
"witchyWizardSet": "Witchy Wizard (Mage)",
"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.",
"messagePetNotFound": ":pet not found in user.items.pets",
"messageFoodNotFound": ":food not found in user.items.food",
"messageNotAvailable": "This item is not currently available for purchase.",
"messageCannotFeedPet": "Can't feed this pet.",
"messageAlreadyMount": "You already have that mount. Try feeding another pet.",
"messageEvolve": "You have tamed <%= egg %>, let's go for a ride!",
@ -14,6 +15,7 @@
"messageEquipped": " <%= itemText %> equipped.",
"messageUnEquipped": "<%= itemText %> un-equipped.",
"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!",
"messageHatched": "Your egg hatched! Visit your stable to equip your pet.",
"messageNotEnoughGold": "Not Enough Gold",

View file

@ -1,11 +1,13 @@
{
"pets": "Pets",
"petsFound": "Pets Found",
"magicPets": "Magic Potion Pets",
"rarePets": "Rare Pets",
"questPets": "Quest Pets",
"mounts": "Mounts",
"mountsTamed": "Mounts Tamed",
"questMounts": "Quest Mounts",
"magicMounts": "Magic Potion Mounts",
"rareMounts": "Rare Mounts",
"etherealLion": "Ethereal Lion",
"veteranWolf": "Veteran Wolf",
@ -24,13 +26,15 @@
"eggSingular": "egg",
"noEggs": "You don't have any eggs.",
"hatchingPotions": "Hatching Potions",
"magicHatchingPotions": "<strong>Magic Hatching Potions</strong>",
"hatchingPotion": "hatching potion",
"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.",
"foodText": "food",
"food": "Food and 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",
"stableBeastMasterProgress": "Beast Master Progress: <%= number %> Pets Found",
"beastAchievement": "You have earned the \"Beast Master\" Achievement for collecting all the pets!",

View file

@ -131,10 +131,10 @@ gear =
summerMage: event: events.summer, specialClass: 'wizard', twoHanded:true, text: t('weaponSpecialSummerMageText'), notes: t('weaponSpecialSummerMageNotes', {int: 15, per: 7}), value: 160, int:15, per:7
summerHealer: event: events.summer, specialClass: 'healer', text: t('weaponSpecialSummerHealerText'), notes: t('weaponSpecialSummerHealerNotes', {int: 9}), value: 90, int: 9
# Fall Festival
fallRogue: event: events.fall, specialClass: 'rogue', text: t('weaponSpecialFallRogueText'), notes: t('weaponSpecialFallRogueNotes', {str: 8}), value: 80, str: 8
fallWarrior: event: events.fall, specialClass: 'warrior', text: t('weaponSpecialFallWarriorText'), notes: t('weaponSpecialFallWarriorNotes', {str: 15}), value: 90, str: 15
fallMage: event: events.fall, specialClass: 'wizard', twoHanded:true, text: t('weaponSpecialFallMageText'), notes: t('weaponSpecialFallMageNotes', {int: 15, per: 7}), value: 160, int:15, per:7
fallHealer: event: events.fall, specialClass: 'healer', text: t('weaponSpecialFallHealerText'), notes: t('weaponSpecialFallHealerNotes', {int: 9}), value: 90, int: 9
fallRogue: event: events.fall, specialClass: 'rogue', text: t('weaponSpecialFallRogueText'), notes: t('weaponSpecialFallRogueNotes', {str: 8}), value: 80, str: 8, canBuy: (()->true)
fallWarrior: event: events.fall, specialClass: 'warrior', text: t('weaponSpecialFallWarriorText'), notes: t('weaponSpecialFallWarriorNotes', {str: 15}), value: 90, str: 15, canBuy: (()->true)
fallMage: event: events.fall, specialClass: 'wizard', twoHanded:true, text: t('weaponSpecialFallMageText'), notes: t('weaponSpecialFallMageNotes', {int: 15, per: 7}), value: 160, int:15, per:7, canBuy: (()->true)
fallHealer: event: events.fall, specialClass: 'healer', text: t('weaponSpecialFallHealerText'), notes: t('weaponSpecialFallHealerNotes', {int: 9}), value: 90, int: 9, canBuy: (()->true)
# Winter 2015
winter2015Rogue: event: events.winter2015, specialClass: 'rogue', text: t('weaponSpecialWinter2015RogueText'), notes: t('weaponSpecialWinter2015RogueNotes', {str: 8}), value: 80, str: 8
winter2015Warrior: event: events.winter2015, specialClass: 'warrior', text: t('weaponSpecialWinter2015WarriorText'), notes: t('weaponSpecialWinter2015WarriorNotes', {str: 15}), value: 90, str: 15
@ -218,10 +218,10 @@ gear =
summerMage: event: events.summer, specialClass: 'wizard', text: t('armorSpecialSummerMageText'), notes: t('armorSpecialSummerMageNotes', {int: 9}), value: 90, int: 9
summerHealer: event: events.summer, specialClass: 'healer', text: t('armorSpecialSummerHealerText'), notes: t('armorSpecialSummerHealerNotes', {con: 15}), value: 90, con: 15
# Fall Festival
fallRogue: event: events.fall, specialClass: 'rogue', text: t('armorSpecialFallRogueText'), notes: t('armorSpecialFallRogueNotes', {per: 15}), value: 90, per: 15
fallWarrior: event: events.fall, specialClass: 'warrior', text: t('armorSpecialFallWarriorText'), notes: t('armorSpecialFallWarriorNotes', {con: 9}), value: 90, con: 9
fallMage: event: events.fall, specialClass: 'wizard', text: t('armorSpecialFallMageText'), notes: t('armorSpecialFallMageNotes', {int: 9}), value: 90, int: 9
fallHealer: event: events.fall, specialClass: 'healer', text: t('armorSpecialFallHealerText'), notes: t('armorSpecialFallHealerNotes', {con: 15}), value: 90, con: 15
fallRogue: event: events.fall, specialClass: 'rogue', text: t('armorSpecialFallRogueText'), notes: t('armorSpecialFallRogueNotes', {per: 15}), value: 90, per: 15, canBuy: (()->true)
fallWarrior: event: events.fall, specialClass: 'warrior', text: t('armorSpecialFallWarriorText'), notes: t('armorSpecialFallWarriorNotes', {con: 9}), value: 90, con: 9, canBuy: (()->true)
fallMage: event: events.fall, specialClass: 'wizard', text: t('armorSpecialFallMageText'), notes: t('armorSpecialFallMageNotes', {int: 9}), value: 90, int: 9, canBuy: (()->true)
fallHealer: event: events.fall, specialClass: 'healer', text: t('armorSpecialFallHealerText'), notes: t('armorSpecialFallHealerNotes', {con: 15}), value: 90, con: 15, canBuy: (()->true)
# Winter 2015
winter2015Rogue: event: events.winter2015, specialClass: 'rogue', text: t('armorSpecialWinter2015RogueText'), notes: t('armorSpecialWinter2015RogueNotes', {per: 15}), value: 90, per: 15
winter2015Warrior: event: events.winter2015, specialClass: 'warrior', text: t('armorSpecialWinter2015WarriorText'), notes: t('armorSpecialWinter2015WarriorNotes', {con: 9}), value: 90, con: 9
@ -320,10 +320,10 @@ gear =
summerMage: event: events.summer, specialClass: 'wizard', text: t('headSpecialSummerMageText'), notes: t('headSpecialSummerMageNotes', {per: 7}),value: 60,per: 7
summerHealer: event: events.summer, specialClass: 'healer', text: t('headSpecialSummerHealerText'), notes: t('headSpecialSummerHealerNotes', {int: 7}), value: 60, int: 7
# Fall Festival
fallRogue: event: events.fall, specialClass: 'rogue', text: t('headSpecialFallRogueText'), notes: t('headSpecialFallRogueNotes', {per: 9}),value: 60,per: 9
fallWarrior: event: events.fall, specialClass: 'warrior', text: t('headSpecialFallWarriorText'), notes: t('headSpecialFallWarriorNotes', {str: 9}),value: 60,str: 9
fallMage: event: events.fall, specialClass: 'wizard', text: t('headSpecialFallMageText'), notes: t('headSpecialFallMageNotes', {per: 7}),value: 60,per: 7
fallHealer: event: events.fall, specialClass: 'healer', text: t('headSpecialFallHealerText'), notes: t('headSpecialFallHealerNotes', {int: 7}), value: 60, int: 7
fallRogue: event: events.fall, specialClass: 'rogue', text: t('headSpecialFallRogueText'), notes: t('headSpecialFallRogueNotes', {per: 9}),value: 60,per: 9, canBuy: (()->true)
fallWarrior: event: events.fall, specialClass: 'warrior', text: t('headSpecialFallWarriorText'), notes: t('headSpecialFallWarriorNotes', {str: 9}),value: 60,str: 9, canBuy: (()->true)
fallMage: event: events.fall, specialClass: 'wizard', text: t('headSpecialFallMageText'), notes: t('headSpecialFallMageNotes', {per: 7}),value: 60,per: 7, canBuy: (()->true)
fallHealer: event: events.fall, specialClass: 'healer', text: t('headSpecialFallHealerText'), notes: t('headSpecialFallHealerNotes', {int: 7}), value: 60, int: 7, canBuy: (()->true)
# Winter 2015
winter2015Rogue: event: events.winter2015, specialClass: 'rogue', text: t('headSpecialWinter2015RogueText'), notes: t('headSpecialWinter2015RogueNotes', {per: 9}),value: 60,per: 9
winter2015Warrior: event: events.winter2015, specialClass: 'warrior', text: t('headSpecialWinter2015WarriorText'), notes: t('headSpecialWinter2015WarriorNotes', {str: 9}),value: 60,str: 9
@ -422,9 +422,9 @@ gear =
summerWarrior: event: events.summer, specialClass: 'warrior', text: t('shieldSpecialSummerWarriorText'), notes: t('shieldSpecialSummerWarriorNotes', {con: 7}), value: 70, con: 7
summerHealer: event: events.summer, specialClass: 'healer', text: t('shieldSpecialSummerHealerText'), notes: t('shieldSpecialSummerHealerNotes', {con: 9}), value: 70, con: 9
# Fall Festival
fallRogue: event: events.fall, specialClass: 'rogue', text: t('shieldSpecialFallRogueText'), notes: t('shieldSpecialFallRogueNotes', {str: 8}), value: 80, str: 8
fallWarrior: event: events.fall, specialClass: 'warrior', text: t('shieldSpecialFallWarriorText'), notes: t('shieldSpecialFallWarriorNotes', {con: 7}), value: 70, con: 7
fallHealer: event: events.fall, specialClass: 'healer', text: t('shieldSpecialFallHealerText'), notes: t('shieldSpecialFallHealerNotes', {con: 9}), value: 70, con: 9
fallRogue: event: events.fall, specialClass: 'rogue', text: t('shieldSpecialFallRogueText'), notes: t('shieldSpecialFallRogueNotes', {str: 8}), value: 80, str: 8, canBuy: (()->true)
fallWarrior: event: events.fall, specialClass: 'warrior', text: t('shieldSpecialFallWarriorText'), notes: t('shieldSpecialFallWarriorNotes', {con: 7}), value: 70, con: 7, canBuy: (()->true)
fallHealer: event: events.fall, specialClass: 'healer', text: t('shieldSpecialFallHealerText'), notes: t('shieldSpecialFallHealerNotes', {con: 9}), value: 70, con: 9, canBuy: (()->true)
# Winter 2015
winter2015Rogue: event: events.winter2015, specialClass: 'rogue', text: t('shieldSpecialWinter2015RogueText'), notes: t('shieldSpecialWinter2015RogueNotes', {str: 8}), value: 80, str: 8
winter2015Warrior: event: events.winter2015, specialClass: 'warrior', text: t('shieldSpecialWinter2015WarriorText'), notes: t('shieldSpecialWinter2015WarriorNotes', {con: 7}), value: 70, con: 7
@ -490,14 +490,14 @@ gear =
spring2015Mage: event: events.spring2015, specialClass: 'wizard', text: t('headAccessorySpecialSpring2015MageText'), notes: t('headAccessorySpecialSpring2015MageNotes'), value: 20
spring2015Healer: event: events.spring2015, specialClass: 'healer', text: t('headAccessorySpecialSpring2015HealerText'), notes: t('headAccessorySpecialSpring2015HealerNotes'), value: 20
# Animal ears
bearEars: gearSet: 'animal', text: t('headAccessoryBearEarsText'), notes: t('headAccessoryBearEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_bearEars?)
cactusEars: gearSet: 'animal', text: t('headAccessoryCactusEarsText'), notes: t('headAccessoryCactusEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_cactusEars?)
foxEars: gearSet: 'animal', text: t('headAccessoryFoxEarsText'), notes: t('headAccessoryFoxEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_foxEars?)
lionEars: gearSet: 'animal', text: t('headAccessoryLionEarsText'), notes: t('headAccessoryLionEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_lionEars?)
pandaEars: gearSet: 'animal', text: t('headAccessoryPandaEarsText'), notes: t('headAccessoryPandaEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_pandaEars?)
pigEars: gearSet: 'animal', text: t('headAccessoryPigEarsText'), notes: t('headAccessoryPigEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_pigEars?)
tigerEars: gearSet: 'animal', text: t('headAccessoryTigerEarsText'), notes: t('headAccessoryTigerEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_tigerEars?)
wolfEars: gearSet: 'animal', text: t('headAccessoryWolfEarsText'), notes: t('headAccessoryWolfEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_wolfEars?)
bearEars: gearSet: 'animal', text: t('headAccessoryBearEarsText'), notes: t('headAccessoryBearEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_bearEars?), canBuy: (()->true)
cactusEars: gearSet: 'animal', text: t('headAccessoryCactusEarsText'), notes: t('headAccessoryCactusEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_cactusEars?), canBuy: (()->true)
foxEars: gearSet: 'animal', text: t('headAccessoryFoxEarsText'), notes: t('headAccessoryFoxEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_foxEars?), canBuy: (()->true)
lionEars: gearSet: 'animal', text: t('headAccessoryLionEarsText'), notes: t('headAccessoryLionEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_lionEars?), canBuy: (()->true)
pandaEars: gearSet: 'animal', text: t('headAccessoryPandaEarsText'), notes: t('headAccessoryPandaEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_pandaEars?), canBuy: (()->true)
pigEars: gearSet: 'animal', text: t('headAccessoryPigEarsText'), notes: t('headAccessoryPigEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_pigEars?), canBuy: (()->true)
tigerEars: gearSet: 'animal', text: t('headAccessoryTigerEarsText'), notes: t('headAccessoryTigerEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_tigerEars?), canBuy: (()->true)
wolfEars: gearSet: 'animal', text: t('headAccessoryWolfEarsText'), notes: t('headAccessoryWolfEarsNotes'), value: 20, canOwn: ((u)-> u.items.gear.owned.headAccessory_special_wolfEars?), canBuy: (()->true)
mystery:
201403: text: t('headAccessoryMystery201403Text'), notes: t('headAccessoryMystery201403Notes'), mystery:'201403', value: 0
201404: text: t('headAccessoryMystery201404Text'), notes: t('headAccessoryMystery201404Notes'), mystery:'201404', value: 0
@ -536,7 +536,7 @@ _.each gearTypes, (type) ->
# add "type" to each item, so we can reference that as "weapon" or "armor" in the html
_.each gear[type][klass], (item, i) ->
key = "#{type}_#{klass}_#{i}"
_.defaults item, {type, key, klass, index: i, str:0, int:0, per:0, con:0}
_.defaults item, {type, key, klass, index: i, str:0, int:0, per:0, con:0, canBuy:(()->false)}
if item.event
#? indicates null/undefined. true means they own currently, false means they once owned - and false is what we're
@ -1088,7 +1088,7 @@ api.dropEggs =
_.each api.dropEggs, (egg,key) ->
_.defaults egg,
canBuy:true
canBuy: (()->true)
value: 3
key: key
notes: t('eggNotes', {eggText: egg.text, eggAdjective: egg.adjective})
@ -1096,31 +1096,31 @@ _.each api.dropEggs, (egg,key) ->
api.questEggs =
# value & other defaults set below
Gryphon: text: t('questEggGryphonText'), adjective: t('questEggGryphonAdjective'), canBuy: false
Hedgehog: text: t('questEggHedgehogText'), adjective: t('questEggHedgehogAdjective'), canBuy: false
Deer: text: t('questEggDeerText'), adjective: t('questEggDeerAdjective'), canBuy: false
Egg: text: t('questEggEggText'), adjective: t('questEggEggAdjective'), canBuy: false, mountText: t('questEggEggMountText')
Rat: text: t('questEggRatText'), adjective: t('questEggRatAdjective'), canBuy: false
Octopus: text: t('questEggOctopusText'), adjective: t('questEggOctopusAdjective'), canBuy: false
Seahorse: text: t('questEggSeahorseText'), adjective: t('questEggSeahorseAdjective'), canBuy: false
Parrot: text: t('questEggParrotText'), adjective: t('questEggParrotAdjective'), canBuy: false
Rooster: text: t('questEggRoosterText'), adjective: t('questEggRoosterAdjective'), canBuy: false
Spider: text: t('questEggSpiderText'), adjective: t('questEggSpiderAdjective'), canBuy: false
Owl: text: t('questEggOwlText'), adjective: t('questEggOwlAdjective'), canBuy: false
Penguin: text: t('questEggPenguinText'), adjective: t('questEggPenguinAdjective'), canBuy: false
TRex: text: t('questEggTRexText'), adjective: t('questEggTRexAdjective'), canBuy: false
Rock: text: t('questEggRockText'), adjective: t('questEggRockAdjective'), canBuy: false
Bunny: text: t('questEggBunnyText'), adjective: t('questEggBunnyAdjective'), canBuy: false
Slime: text: t('questEggSlimeText'), adjective: t('questEggSlimeAdjective'), canBuy: false
Sheep: text: t('questEggSheepText'), adjective: t('questEggSheepAdjective'), canBuy: false
Cuttlefish: text: t('questEggCuttlefishText'), adjective: t('questEggCuttlefishAdjective'), canBuy: false
Whale: text: t('questEggWhaleText'), adjective: t('questEggWhaleAdjective'), canBuy: false
Cheetah: text: t('questEggCheetahText'), adjective: t('questEggCheetahAdjective'), canBuy: false
Horse: text: t('questEggHorseText'), adjective: t('questEggHorseAdjective'), canBuy: false
Gryphon: text: t('questEggGryphonText'), adjective: t('questEggGryphonAdjective'), canBuy: ((u)-> u.achievements.quests.gryphon? > 0)
Hedgehog: text: t('questEggHedgehogText'), adjective: t('questEggHedgehogAdjective'), canBuy: ((u)-> u.achievements.quests.hedgehog? > 0)
Deer: text: t('questEggDeerText'), adjective: t('questEggDeerAdjective'), canBuy: ((u)-> u.achievements.quests.ghost_stag? > 0)
Egg: text: t('questEggEggText'), adjective: t('questEggEggAdjective'), mountText: t('questEggEggMountText')
Rat: text: t('questEggRatText'), adjective: t('questEggRatAdjective'), canBuy: ((u)-> u.achievements.quests.rat? > 0)
Octopus: text: t('questEggOctopusText'), adjective: t('questEggOctopusAdjective'), canBuy: ((u)-> u.achievements.quests.octopus? > 0)
Seahorse: text: t('questEggSeahorseText'), adjective: t('questEggSeahorseAdjective'), canBuy: ((u)-> u.achievements.quests.dilatory_derby? > 0)
Parrot: text: t('questEggParrotText'), adjective: t('questEggParrotAdjective'), canBuy: ((u)-> u.achievements.quests.harpy? > 0)
Rooster: text: t('questEggRoosterText'), adjective: t('questEggRoosterAdjective'), canBuy: ((u)-> u.achievements.quests.rooster? > 0)
Spider: text: t('questEggSpiderText'), adjective: t('questEggSpiderAdjective'), canBuy: ((u)-> u.achievements.quests.spider? > 0)
Owl: text: t('questEggOwlText'), adjective: t('questEggOwlAdjective'), canBuy: ((u)-> u.achievements.quests.owl? > 0)
Penguin: text: t('questEggPenguinText'), adjective: t('questEggPenguinAdjective'), canBuy: ((u)-> u.achievements.quests.penguin? > 0)
TRex: text: t('questEggTRexText'), adjective: t('questEggTRexAdjective'), canBuy: ((u)-> (u.achievements.quests.trex? > 0 or u.achievements.quests.trex_undead? > 0))
Rock: text: t('questEggRockText'), adjective: t('questEggRockAdjective'), canBuy: ((u)-> u.achievements.quests.rock? > 0)
Bunny: text: t('questEggBunnyText'), adjective: t('questEggBunnyAdjective'), canBuy: ((u)-> u.achievements.quests.bunny? > 0)
Slime: text: t('questEggSlimeText'), adjective: t('questEggSlimeAdjective'), canBuy: ((u)-> u.achievements.quests.slime? > 0)
Sheep: text: t('questEggSheepText'), adjective: t('questEggSheepAdjective'), canBuy: ((u)-> u.achievements.quests.sheep? > 0)
Cuttlefish: text: t('questEggCuttlefishText'), adjective: t('questEggCuttlefishAdjective'), canBuy: ((u)-> u.achievements.quests.kraken? > 0)
Whale: text: t('questEggWhaleText'), adjective: t('questEggWhaleAdjective'), canBuy: ((u)-> u.achievements.quests.whale? > 0)
Cheetah: text: t('questEggCheetahText'), adjective: t('questEggCheetahAdjective'), canBuy: ((u)-> u.achievements.quests.cheetah? > 0)
Horse: text: t('questEggHorseText'), adjective: t('questEggHorseAdjective'), canBuy: ((u)-> u.achievements.quests.horse? > 0)
_.each api.questEggs, (egg,key) ->
_.defaults egg,
canBuy:false
canBuy: (()->false)
value: 3
key: key
notes: t('eggNotes', {eggText: egg.text, eggAdjective: egg.adjective})
@ -1157,7 +1157,7 @@ api.timeTravelStable =
'Mammoth-Base': t('mammoth')
'MantisShrimp-Base': t('mantisShrimp')
api.hatchingPotions =
api.dropHatchingPotions =
Base: value: 2, text: t('hatchingPotionBase')
White: value: 2, text: t('hatchingPotionWhite')
Desert: value: 2, text: t('hatchingPotionDesert')
@ -1168,67 +1168,85 @@ api.hatchingPotions =
CottonCandyPink: value: 4, text: t('hatchingPotionCottonCandyPink')
CottonCandyBlue: value: 4, text: t('hatchingPotionCottonCandyBlue')
Golden: value: 5, text: t('hatchingPotionGolden')
_.each api.hatchingPotions, (pot,key) ->
_.defaults pot, {key, value: 2, notes: t('hatchingPotionNotes', {potText: pot.text})}
api.premiumHatchingPotions =
Spooky: value: 2, text: t('hatchingPotionSpooky'), addlNotes: t('premiumPotionAddlNotes'), premium: true, limited: true
_.each api.dropHatchingPotions, (pot,key) ->
_.defaults pot, {key, value: 2, notes: t('hatchingPotionNotes', {potText: pot.text}), premium: false, limited: false, canBuy: (()->true)}
_.each api.premiumHatchingPotions, (pot,key) ->
_.defaults pot, {key, value: 2, notes: t('hatchingPotionNotes', {potText: pot.text}), premium: true, limited: false, canBuy: (()->true)}
api.hatchingPotions = _.merge(api.dropHatchingPotions, api.premiumHatchingPotions)
api.pets = _.transform api.dropEggs, (m, egg) ->
_.defaults m, _.transform api.hatchingPotions, (m2, pot) ->
m2[egg.key + "-" + pot.key] = true
if not pot.premium
m2[egg.key + "-" + pot.key] = true
api.premiumPets = _.transform api.dropEggs, (m, egg) ->
_.defaults m, _.transform api.hatchingPotions, (m2, pot) ->
if pot.premium
m2[egg.key + "-" + pot.key] = true
api.questPets = _.transform api.questEggs, (m, egg) ->
_.defaults m, _.transform api.hatchingPotions, (m2, pot) ->
m2[egg.key + "-" + pot.key] = true
if not pot.premium
m2[egg.key + "-" + pot.key] = true
## added for mountmaster -- yes, the transforms are correct, since the same strings are used for both pets and mounts
api.mounts = _.transform api.dropEggs, (m, egg) ->
_.defaults m, _.transform api.hatchingPotions, (m2, pot) ->
m2[egg.key + "-" + pot.key] = true
if not pot.premium
m2[egg.key + "-" + pot.key] = true
api.questMounts = _.transform api.questEggs, (m, egg) ->
_.defaults m, _.transform api.hatchingPotions, (m2, pot) ->
m2[egg.key + "-" + pot.key] = true
if not pot.premium
m2[egg.key + "-" + pot.key] = true
api.food =
# Base
Meat: canBuy:false, canDrop:false, text: t('foodMeat'), target: 'Base', article: ''
Milk: canBuy:false, canDrop:false, text: t('foodMilk'), target: 'White', article: ''
Potatoe: canBuy:false, canDrop:false, text: t('foodPotatoe'), target: 'Desert', article: 'a '
Strawberry: canBuy:false, canDrop:false, text: t('foodStrawberry'), target: 'Red', article: 'a '
Chocolate: canBuy:false, canDrop:false, text: t('foodChocolate'), target: 'Shade', article: ''
Fish: canBuy:false, canDrop:false, text: t('foodFish'), target: 'Skeleton', article: 'a '
RottenMeat: canBuy:false, canDrop:false, text: t('foodRottenMeat'), target: 'Zombie', article: ''
CottonCandyPink: canBuy:false, canDrop:false, text: t('foodCottonCandyPink'), target: 'CottonCandyPink', article: ''
CottonCandyBlue: canBuy:false, canDrop:false, text: t('foodCottonCandyBlue'), target: 'CottonCandyBlue', article: ''
Honey: canBuy:false, canDrop:false, text: t('foodHoney'), target: 'Golden', article: ''
Meat: text: t('foodMeat'), target: 'Base', article: ''
Milk: text: t('foodMilk'), target: 'White', article: ''
Potatoe: text: t('foodPotatoe'), target: 'Desert', article: 'a '
Strawberry: text: t('foodStrawberry'), target: 'Red', article: 'a '
Chocolate: text: t('foodChocolate'), target: 'Shade', article: ''
Fish: text: t('foodFish'), target: 'Skeleton', article: 'a '
RottenMeat: text: t('foodRottenMeat'), target: 'Zombie', article: ''
CottonCandyPink: text: t('foodCottonCandyPink'), target: 'CottonCandyPink', article: ''
CottonCandyBlue: text: t('foodCottonCandyBlue'), target: 'CottonCandyBlue', article: ''
Honey: text: t('foodHoney'), target: 'Golden', article: ''
Saddle: canBuy:true, canDrop:false, text: t('foodSaddleText'), value: 5, notes: t('foodSaddleNotes')
Saddle: canBuy:(()->true), text: t('foodSaddleText'), value: 5, notes: t('foodSaddleNotes')
# Cake
Cake_Skeleton: canBuy:false, canDrop:false, text: t('foodCakeSkeleton'), target: 'Skeleton', article: ''
Cake_Base: canBuy:false, canDrop:false, text: t('foodCakeBase'), target: 'Base', article: ''
Cake_CottonCandyBlue: canBuy:false, canDrop:false, text: t('foodCakeCottonCandyBlue'), target: 'CottonCandyBlue', article: ''
Cake_CottonCandyPink: canBuy:false, canDrop:false, text: t('foodCakeCottonCandyPink'), target: 'CottonCandyPink', article: ''
Cake_Shade: canBuy:false, canDrop:false, text: t('foodCakeShade'), target: 'Shade', article: ''
Cake_White: canBuy:false, canDrop:false, text: t('foodCakeWhite'), target: 'White', article: ''
Cake_Golden: canBuy:false, canDrop:false, text: t('foodCakeGolden'), target: 'Golden', article: ''
Cake_Zombie: canBuy:false, canDrop:false, text: t('foodCakeZombie'), target: 'Zombie', article: ''
Cake_Desert: canBuy:false, canDrop:false, text: t('foodCakeDesert'), target: 'Desert', article: ''
Cake_Red: canBuy:false, canDrop:false, text: t('foodCakeRed'), target: 'Red', article: ''
Cake_Skeleton: text: t('foodCakeSkeleton'), target: 'Skeleton', article: ''
Cake_Base: text: t('foodCakeBase'), target: 'Base', article: ''
Cake_CottonCandyBlue: text: t('foodCakeCottonCandyBlue'), target: 'CottonCandyBlue', article: ''
Cake_CottonCandyPink: text: t('foodCakeCottonCandyPink'), target: 'CottonCandyPink', article: ''
Cake_Shade: text: t('foodCakeShade'), target: 'Shade', article: ''
Cake_White: text: t('foodCakeWhite'), target: 'White', article: ''
Cake_Golden: text: t('foodCakeGolden'), target: 'Golden', article: ''
Cake_Zombie: text: t('foodCakeZombie'), target: 'Zombie', article: ''
Cake_Desert: text: t('foodCakeDesert'), target: 'Desert', article: ''
Cake_Red: text: t('foodCakeRed'), target: 'Red', article: ''
# Fall
Candy_Skeleton: canBuy:true, canDrop:true, text: t('foodCandySkeleton'), target: 'Skeleton', article: ''
Candy_Base: canBuy:true, canDrop:true, text: t('foodCandyBase'), target: 'Base', article: ''
Candy_CottonCandyBlue: canBuy:true, canDrop:true, text: t('foodCandyCottonCandyBlue'), target: 'CottonCandyBlue', article: ''
Candy_CottonCandyPink: canBuy:true, canDrop:true, text: t('foodCandyCottonCandyPink'), target: 'CottonCandyPink', article: ''
Candy_Shade: canBuy:true, canDrop:true, text: t('foodCandyShade'), target: 'Shade', article: ''
Candy_White: canBuy:true, canDrop:true, text: t('foodCandyWhite'), target: 'White', article: ''
Candy_Golden: canBuy:true, canDrop:true, text: t('foodCandyGolden'), target: 'Golden', article: ''
Candy_Zombie: canBuy:true, canDrop:true, text: t('foodCandyZombie'), target: 'Zombie', article: ''
Candy_Desert: canBuy:true, canDrop:true, text: t('foodCandyDesert'), target: 'Desert', article: ''
Candy_Red: canBuy:true, canDrop:true, text: t('foodCandyRed'), target: 'Red', article: ''
Candy_Skeleton: canBuy:(()->true), canDrop:true, text: t('foodCandySkeleton'), target: 'Skeleton', article: ''
Candy_Base: canBuy:(()->true), canDrop:true, text: t('foodCandyBase'), target: 'Base', article: ''
Candy_CottonCandyBlue: canBuy:(()->true), canDrop:true, text: t('foodCandyCottonCandyBlue'), target: 'CottonCandyBlue', article: ''
Candy_CottonCandyPink: canBuy:(()->true), canDrop:true, text: t('foodCandyCottonCandyPink'), target: 'CottonCandyPink', article: ''
Candy_Shade: canBuy:(()->true), canDrop:true, text: t('foodCandyShade'), target: 'Shade', article: ''
Candy_White: canBuy:(()->true), canDrop:true, text: t('foodCandyWhite'), target: 'White', article: ''
Candy_Golden: canBuy:(()->true), canDrop:true, text: t('foodCandyGolden'), target: 'Golden', article: ''
Candy_Zombie: canBuy:(()->true), canDrop:true, text: t('foodCandyZombie'), target: 'Zombie', article: ''
Candy_Desert: canBuy:(()->true), canDrop:true, text: t('foodCandyDesert'), target: 'Desert', article: ''
Candy_Red: canBuy:(()->true), canDrop:true, text: t('foodCandyRed'), target: 'Red', article: ''
_.each api.food, (food,key) ->
_.defaults food, {value: 1, key, notes: t('foodNotes')}
_.defaults food, {value: 1, key, notes: t('foodNotes'), canBuy:(()->false), canDrop:false}
api.userCanOwnQuestCategories = [
'unlockable'
@ -1243,7 +1261,7 @@ api.quests =
notes: t("questDilatoryNotes")
completion: t("questDilatoryCompletion")
value: 0
canBuy: false
canBuy: (()->false)
category: 'world'
boss:
name: t("questDilatoryBoss")
@ -1286,7 +1304,7 @@ api.quests =
completion: t("questStressbeastCompletion")
completionChat: t("questStressbeastCompletionChat")
value: 0
canBuy: false
canBuy: (()->false)
category: 'world'
boss:
name: t("questStressbeastBoss")
@ -1326,7 +1344,7 @@ api.quests =
exp: 0
evilsanta:
canBuy:false
canBuy: (()->false)
text: t('questEvilSantaText') # title of the quest (eg, Deep into Vice's Layer)
notes: t('questEvilSantaNotes')
completion: t('questEvilSantaCompletion')
@ -1344,7 +1362,7 @@ api.quests =
exp: 100 # Exp bonus from defeating the boss
evilsanta2:
canBuy:false
canBuy: (()->false)
text: t('questEvilSanta2Text')
notes: t('questEvilSanta2Notes')
completion: t('questEvilSanta2Completion')
@ -1482,7 +1500,7 @@ api.quests =
notes: t('questEggHuntNotes')
completion: t('questEggHuntCompletion')
value: 1
canBuy: false
canBuy: (()->false)
category: 'pet'
collect:
plainEgg: text: t('questEggHuntCollectPlainEgg'), count: 100
@ -2115,7 +2133,7 @@ api.quests =
unlock: t('questHorseUnlockText')
_.each api.quests, (v,key) ->
_.defaults v, {key,canBuy:true}
_.defaults v, {key,canBuy:(()->true)}
b = v.boss
if b
_.defaults b, {str:1,def:1}

View file

@ -766,7 +766,7 @@ api.wrap = (user, main=true) ->
if food.key is 'Saddle'
evolve()
else
if food.target is potion
if food.target is potion or content.hatchingPotions[potion].premium
userPets[pet] += 5
message = i18n.t('messageLikesFood', {egg: petDisplayName, foodText: food.text(req.language)}, req.language)
else
@ -822,7 +822,8 @@ api.wrap = (user, main=true) ->
item = content[type][key]
price = item.value / 4
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
if type is 'gear' then user.items.gear.owned[key] = true
else
@ -1070,10 +1071,11 @@ api.wrap = (user, main=true) ->
hatch: (req, cb) ->
{egg, hatchingPotion} = req.params
return cb?({code:404,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:400,message:"Please specify query.egg & query.hatchingPotion"}) unless egg and hatchingPotion
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}"
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.eggs[egg]--
user.items.hatchingPotions[hatchingPotion]--
@ -1529,7 +1531,7 @@ api.wrap = (user, main=true) ->
# Eggs: 30% chance
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]++
drop.type = 'Egg'

View file

@ -544,7 +544,7 @@ describe 'User', ->
expect(quest.notes()).to.be.an('string')
expect(quest.completion()).to.be.an('string') if quest.completion
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.exp).to.not.be.lessThan 0
expect(quest.category).to.match(/pet|unlockable|gold|world/)

View file

@ -26,6 +26,16 @@ describe('count', function() {
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() {
var pets = {
"Wolf-Base": 2,
@ -65,6 +75,15 @@ describe('count', function() {
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() {
var mounts = { "Dragon-Red": true, "Gryphon-Base": true };
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-Red" : 5,
"Egg-Desert" : 5,
"MantisShrimp-Base" : 5
"MantisShrimp-Base" : 5,
"Wolf-Spooky": 5
}
var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets);
@ -38,9 +39,10 @@ describe('Stats Service', function() {
"BearCub-CottonCandyBlue" : -1,
"Cactus-Zombie" : 5,
"Deer-Golden" : 5,
"Deer-Red" : 5,
"Deer-Red" : -1,
"Egg-Desert" : 5,
"MantisShrimp-Base" : 5
"MantisShrimp-Base" : 5,
"Wolf-Spooky": -1
}
var beastMasterDisplay = statCalc.beastMasterProgress(user.items.pets);
@ -221,7 +223,8 @@ describe('Stats Service', function() {
"Wolf-Golden" : true,
"Owl-CottonCandyBlue" : true,
"Mammoth-Base" : true,
"Bunny-Skeleton" : true
"Bunny-Skeleton" : true,
"Tiger-Spooky": true
}
var mountMasterDisplay = statCalc.mountMasterProgress(user.items.mounts);
@ -237,7 +240,8 @@ describe('Stats Service', function() {
"Wolf-Golden" : false,
"Owl-CottonCandyBlue" : true,
"Mammoth-Base" : true,
"Bunny-Skeleton" : true
"Bunny-Skeleton" : true,
"Tiger-Spooky": true
}
var mountMasterDisplay = statCalc.mountMasterProgress(user.items.mounts);

View file

@ -232,10 +232,10 @@ var UserSchema = new Schema({
_.defaults(
// First transform to a 1D eggs/potions mapping
_.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; }),
// 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
@ -265,9 +265,10 @@ var UserSchema = new Schema({
mounts: _.defaults(
// First transform to a 1D eggs/potions mapping
_.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; }),
// 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; })
),
currentMount: String,

View file

@ -10,7 +10,7 @@
p.muted(ng-show='eggCount < 1')=env.t('noEggs')
div(ng-repeat='(egg,points) in ownedItems(user.items.eggs)')
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-title!=env.t("egg", {eggType: "{{::Content.eggs[egg].text()}}"}),
popover-trigger='mouseenter', popover-placement='right',
@ -18,12 +18,12 @@
.badge.badge-info.stack-count {{points}}
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')
div(ng-repeat='(pot,points) in ownedItems(user.items.hatchingPotions)')
button.customize-option(class='Pet_HatchingPotion_{{::pot}}',
ng-class='{selectableInventory: selectedEgg && !(user.items.pets[selectedEgg.key+"-"+pot]>0)}',
popover='{{::Content.hatchingPotions[pot].notes()}}',
ng-class='{selectableInventory: selectedEgg && !(user.items.pets[selectedEgg.key+"-"+pot]>0) && (Content.dropEggs[selectedEgg.key] || !Content.hatchingPotions[pot].premium)}',
popover='{{::Content.hatchingPotions[pot].notes()}} {{::Content.hatchingPotions[pot].addlNotes()}}',
popover-title!=env.t("potion", {potionType: "{{::Content.hatchingPotions[pot].text()}}"}),
popover-trigger='mouseenter', popover-placement='right',
popover-append-to-body='true',
@ -102,7 +102,7 @@
menu.pets-menu(label=env.t('eggs'))
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}}',
popover='{{::egg.notes()}}', popover-append-to-body='true',
popover-title!=env.t("egg", {eggType: "{{::egg.text()}}"}),
@ -110,31 +110,11 @@
ng-click='purchase("eggs", egg)')
p {{::egg.value}}&nbsp;
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
menu.pets-menu(label=env.t('hatchingPotions'))
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}}',
popover='{{::pot.notes()}}', popover-append-to-body='true',
popover-title!=env.t("potion", {potionType: "{{::pot.text()}}"}),
@ -144,10 +124,23 @@
| {{::pot.value}}&nbsp;
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
menu.pets-menu(label=env.t('food'))
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}}',
popover='{{::food.notes()}}', popover-title='{{::food.text()}}',
popover-trigger='mouseenter', popover-placement='top',

View file

@ -1,15 +1,14 @@
mixin mountList(source)
mixin mountList(eggSource, potionSource)
menu.pets(type='list')
each egg in source
each egg in eggSource
-if(!egg.noMount) {
li.customize-menu
menu
each potion in env.Content.hatchingPotions
each potion in potionSource
- 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}")')
//div(class='Mount_Head_{{mount}}')
button(class="pet-button mount-not-owned", ng-hide='user.items.mounts["#{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}"])')
.PixelPaw
-}
@ -24,10 +23,23 @@ mixin mountList(source)
p=env.t('mattShall', {name: "{{user.profile.name}}"})
h4 {{:: env.t('stableMountMasterProgress', { number: mountMasterProgress }) }}
.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
h4=env.t('questMounts')
+mountList(env.Content.questEggs)
+mountList(env.Content.questEggs,env.Content.dropHatchingPotions)
.row: .col-md-12
h4=env.t('rareMounts')
menu

View file

@ -1,15 +1,15 @@
mixin petList(source)
mixin petList(eggSource, potionSource)
menu.pets(type='list')
each egg in source
each egg in eggSource
li.customize-menu
menu
each potion in env.Content.hatchingPotions
each potion in potionSource
- 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}"]')
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')
@ -24,10 +24,25 @@ mixin petList(source)
p=env.t('mattBochText1')
h4 {{:: env.t('stableBeastMasterProgress', { number: beastMasterProgress }) }}
.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
h4=env.t('questPets')
+petList(env.Content.questEggs)
+petList(env.Content.questEggs,env.Content.dropHatchingPotions)
.row: .col-md-12
h4=env.t('rarePets')

View file

@ -19,7 +19,7 @@ include ../../shared/mixins
h3.equipment-title=env.t('questsForSale')
div(ng-repeat='type in Content.userCanOwnQuestCategories')
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}}"',
data-popover-html="{{::lockQuest(quest,true) ? env.t('scrollsPre') : questPopover(quest) | markdown}}",
popover-title='{{::quest.text()}}', popover-append-to-body="true",

View file

@ -33,7 +33,7 @@
span.Pet_Currency_Gem1x.inline-gems
menu.pets-menu(label=env.t('seasonalItems'))
div
button.customize-option(class='shop_spookDust',
button.customize-option(class='inventory_special_spookDust',
popover='{{::Content.spells.special.spookDust.notes()}}',
popover-title='{{::Content.spells.special.spookDust.text()}}',
popover-trigger='mouseenter', popover-placement='right',
@ -41,6 +41,15 @@
ng-click='purchase("special", Content.spells.special.spookDust)')
p {{::Content.spells.special.spookDust.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()}}"}),
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
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')