mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-14 21:27:23 +01:00
* Added image * Added new achievement to user schema * Added new achievement to content * Added new achievement to libs * Added achievement text to locale * Added achievement to notification model and controller * Grant achievement on joining or creating first challenge * Added achievement to modal template * Compiled new sprites * Added integration tests * Fix linting error
This commit is contained in:
@@ -304,5 +304,15 @@ describe('POST /challenges', () => {
|
||||
|
||||
await expect(groupLeader.sync()).to.eventually.have.property('challenges').to.include(challenge._id);
|
||||
});
|
||||
|
||||
it('awards achievement if this is creator\'s first challenge', async () => {
|
||||
await groupLeader.post('/challenges', {
|
||||
group: group._id,
|
||||
name: 'Test Challenge',
|
||||
shortName: 'TC Label',
|
||||
});
|
||||
groupLeader = await groupLeader.sync();
|
||||
expect(groupLeader.achievements.joinedChallenge).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -123,5 +123,12 @@ describe('POST /challenges/:challengeId/join', () => {
|
||||
|
||||
await expect(authorizedUser.get('/tags')).to.eventually.have.length(userTagsLength + 1);
|
||||
});
|
||||
|
||||
it('awards achievement if this is user\'s first challenge', async () => {
|
||||
await authorizedUser.post(`/challenges/${challenge._id}/join`);
|
||||
|
||||
await authorizedUser.sync();
|
||||
expect(authorizedUser.achievements.joinedChallenge).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,8 +100,8 @@ describe('POST /challenges/:challengeId/winner/:winnerId', () => {
|
||||
await sleep(0.5);
|
||||
|
||||
await expect(winningUser.sync()).to.eventually.have.deep.property('achievements.challenges').to.include(challenge.name);
|
||||
expect(winningUser.notifications.length).to.equal(1);
|
||||
expect(winningUser.notifications[0].type).to.equal('WON_CHALLENGE');
|
||||
expect(winningUser.notifications.length).to.equal(2); // 2 because winningUser just joined the challenge, which now awards an achievement
|
||||
expect(winningUser.notifications[1].type).to.equal('WON_CHALLENGE');
|
||||
});
|
||||
|
||||
it('gives winner gems as reward', async () => {
|
||||
|
||||
452
website/assets/sprites/dist/spritesmith-main-0.css
vendored
452
website/assets/sprites/dist/spritesmith-main-0.css
vendored
File diff suppressed because it is too large
Load Diff
BIN
website/assets/sprites/dist/spritesmith-main-0.png
vendored
BIN
website/assets/sprites/dist/spritesmith-main-0.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 506 KiB After Width: | Height: | Size: 506 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
@@ -147,6 +147,10 @@ habitrpg.controller('NotificationCtrl',
|
||||
$rootScope.playSound('Achievement_Unlocked');
|
||||
Achievement.displayAchievement('joinedGuild', {size: 'md'});
|
||||
break;
|
||||
case 'CHALLENGE_JOINED_ACHIEVEMENT':
|
||||
$rootScope.playSound('Achievement_Unlocked');
|
||||
Achievement.displayAchievement('joinedChallenge', {size: 'md'});
|
||||
break;
|
||||
case 'NEW_CONTRIBUTOR_LEVEL':
|
||||
$rootScope.playSound('Achievement_Unlocked');
|
||||
Achievement.displayAchievement('contributor', {size: 'md'});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -79,5 +79,7 @@
|
||||
"onlyChalLeaderEditTasks": "Tasks belonging to a challenge can only be edited by the leader.",
|
||||
"userAlreadyInChallenge": "User is already participating in this challenge.",
|
||||
"cantOnlyUnlinkChalTask": "Only broken challenges tasks can be unlinked.",
|
||||
"shortNameTooShort": "Tag Name must have at least 3 characters."
|
||||
"shortNameTooShort": "Tag Name must have at least 3 characters.",
|
||||
"joinedChallenge": "Joined a Challenge",
|
||||
"joinedChallengeText": "This user put themselves to the test by joining a Challenge!"
|
||||
}
|
||||
|
||||
@@ -107,6 +107,11 @@ let basicAchievs = {
|
||||
titleKey: 'joinedGuild',
|
||||
textKey: 'joinedGuildText',
|
||||
},
|
||||
joinedChallenge: {
|
||||
icon: 'achievement-challenge',
|
||||
titleKey: 'joinedChallenge',
|
||||
textKey: 'joinedChallengeText',
|
||||
},
|
||||
};
|
||||
Object.assign(achievementsData, basicAchievs);
|
||||
|
||||
|
||||
@@ -181,6 +181,7 @@ function _getBasicAchievements (user, language) {
|
||||
_addSimple(result, user, {path: 'partyOn', language});
|
||||
_addSimple(result, user, {path: 'joinedGuild', language});
|
||||
_addSimple(result, user, {path: 'royallyLoyal', language});
|
||||
_addSimple(result, user, {path: 'joinedChallenge', language});
|
||||
|
||||
_addSimpleWithMasterCount(result, user, {path: 'beastMaster', language});
|
||||
_addSimpleWithMasterCount(result, user, {path: 'mountMaster', language});
|
||||
|
||||
@@ -228,6 +228,12 @@ api.createChallenge = {
|
||||
let challengeValidationErrors = challenge.validateSync();
|
||||
if (challengeValidationErrors) throw challengeValidationErrors;
|
||||
|
||||
// Add achievement if user's first challenge
|
||||
if (!user.achievements.joinedChallenge) {
|
||||
user.achievements.joinedChallenge = true;
|
||||
user.addNotification('CHALLENGE_JOINED_ACHIEVEMENT');
|
||||
}
|
||||
|
||||
let results = await Bluebird.all([challenge.save({
|
||||
validateBeforeSave: false, // already validate
|
||||
}), group.save()]);
|
||||
@@ -286,6 +292,12 @@ api.joinChallenge = {
|
||||
|
||||
challenge.memberCount += 1;
|
||||
|
||||
// Add achievement if user's first challenge
|
||||
if (!user.achievements.joinedChallenge) {
|
||||
user.achievements.joinedChallenge = true;
|
||||
user.addNotification('CHALLENGE_JOINED_ACHIEVEMENT');
|
||||
}
|
||||
|
||||
// Add all challenge's tasks to user's tasks and save the challenge
|
||||
let results = await Bluebird.all([challenge.syncToUser(user), challenge.save()]);
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ let schema = new Schema({
|
||||
getwell: Number,
|
||||
royallyLoyal: Boolean,
|
||||
joinedGuild: Boolean,
|
||||
joinedChallenge: Boolean,
|
||||
},
|
||||
|
||||
backer: {
|
||||
|
||||
@@ -20,6 +20,7 @@ const NOTIFICATION_TYPES = [
|
||||
'BOSS_DAMAGE', // Not used currently but kept to avoid validation errors
|
||||
'GUILD_PROMPT',
|
||||
'GUILD_JOINED_ACHIEVEMENT',
|
||||
'CHALLENGE_JOINED_ACHIEVEMENT',
|
||||
];
|
||||
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 506 KiB After Width: | Height: | Size: 506 KiB |
@@ -163,3 +163,14 @@ script(id='modals/achievements/joinedGuild.html', type='text/ng-template')
|
||||
br
|
||||
button.btn.btn-primary(ng-click='$close()')=env.t('huzzah')
|
||||
+achievementFooter
|
||||
|
||||
// Joined Challenge
|
||||
script(id='modals/achievements/joinedChallenge.html', type='text/ng-template')
|
||||
.modal-content(style='min-width:28em')
|
||||
.modal-body.text-center
|
||||
h3(style='margin-bottom:0')=env.t('modalAchievement')
|
||||
+achievementAvatar('challenge',0)
|
||||
p=env.t('joinedChallengeText')
|
||||
br
|
||||
button.btn.btn-primary(ng-click='$close()')=env.t('huzzah')
|
||||
+achievementFooter
|
||||
|
||||
Reference in New Issue
Block a user