mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
feat(pets): Full purchase behavior
This commit is contained in:
@@ -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": "Invalid egg+potion combination. Try hatching 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",
|
||||||
|
|||||||
@@ -822,7 +822,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 type is 'hatchingPotions' and not item.canBuy
|
||||||
|
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
|
||||||
@@ -1070,10 +1071,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]--
|
||||||
|
|||||||
139
test/common/user.ops.hatch.js
Normal file
139
test/common/user.ops.hatch.js
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
.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}}',
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
|
|
||||||
li.customize-menu
|
li.customize-menu
|
||||||
menu.pets-menu(label=env.t('magicHatchingPotions'))
|
menu.pets-menu(label=env.t('magicHatchingPotions'))
|
||||||
div(ng-repeat='pot in Content.hatchingPotions', ng-if='pot.premium')
|
div(ng-repeat='pot in Content.hatchingPotions', ng-if='pot.premium && pot.canBuy')
|
||||||
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()}}"}),
|
||||||
|
|||||||
Reference in New Issue
Block a user