mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 14:17:22 +01:00
Add more achievements to notifications list (#11332)
* Add more achievements to notifications list * use addNotification * Fix logic to not award stable achievements over and over * Improve achievement display * Fix setting notifications for party inviter * Add tests that notifications are added correctly * Fix tests
This commit is contained in:
committed by
Matteo Pagliazzi
parent
ec7ded042b
commit
360aaa9f0b
@@ -384,6 +384,7 @@ describe('User Model', () => {
|
||||
user = await user.save();
|
||||
// verify that it's been awarded
|
||||
expect(user.achievements.beastMaster).to.equal(true);
|
||||
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_BEAST_MASTER')).to.exist;
|
||||
|
||||
// reset the user
|
||||
user.achievements.beastMasterCount = 0;
|
||||
@@ -414,6 +415,25 @@ describe('User Model', () => {
|
||||
expect(user.achievements.beastMaster).to.not.equal(true);
|
||||
});
|
||||
|
||||
it('adds achievements to notification list', async () => {
|
||||
let user = new User();
|
||||
user = await user.save(); // necessary for user.isSelected to work correctly
|
||||
|
||||
// Create conditions for achievements to be awarded
|
||||
user.achievements.beastMasterCount = 3;
|
||||
user.achievements.mountMasterCount = 3;
|
||||
user.achievements.triadBingoCount = 3;
|
||||
expect(user.achievements.beastMaster).to.not.equal(true); // verify that it was not awarded initially
|
||||
expect(user.achievements.mountMaster).to.not.equal(true); // verify that it was not awarded initially
|
||||
expect(user.achievements.triadBingo).to.not.equal(true); // verify that it was not awarded initially
|
||||
|
||||
user = await user.save();
|
||||
// verify that it's been awarded
|
||||
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_BEAST_MASTER')).to.exist;
|
||||
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_MOUNT_MASTER')).to.exist;
|
||||
expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_TRIAD_BINGO')).to.exist;
|
||||
});
|
||||
|
||||
context('manage unallocated stats points notifications', () => {
|
||||
it('doesn\'t add a notification if there are no points to allocate', async () => {
|
||||
let user = new User();
|
||||
|
||||
@@ -314,6 +314,7 @@ describe('POST /group/:groupId/join', () => {
|
||||
name: 'Testing Party',
|
||||
type: 'party',
|
||||
});
|
||||
|
||||
await leader.post(`/groups/${party._id}/invite`, {
|
||||
uuids: [member._id],
|
||||
});
|
||||
@@ -325,7 +326,9 @@ describe('POST /group/:groupId/join', () => {
|
||||
await leader.sync();
|
||||
|
||||
expect(member).to.have.nested.property('achievements.partyUp', true);
|
||||
expect(member.notifications.find(notification => notification.type === 'ACHIEVEMENT_PARTY_UP')).to.exist;
|
||||
expect(leader).to.have.nested.property('achievements.partyUp', true);
|
||||
expect(leader.notifications.find(notification => notification.type === 'ACHIEVEMENT_PARTY_UP')).to.exist;
|
||||
});
|
||||
|
||||
it('does not award Party On achievement to party of size 2', async () => {
|
||||
@@ -349,7 +352,9 @@ describe('POST /group/:groupId/join', () => {
|
||||
await leader.sync();
|
||||
|
||||
expect(member).to.have.nested.property('achievements.partyOn', true);
|
||||
expect(member.notifications.find(notification => notification.type === 'ACHIEVEMENT_PARTY_ON')).to.exist;
|
||||
expect(leader).to.have.nested.property('achievements.partyOn', true);
|
||||
expect(leader.notifications.find(notification => notification.type === 'ACHIEVEMENT_PARTY_ON')).to.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -440,7 +440,6 @@ export default {
|
||||
if (this.isParty) {
|
||||
await this.$store.dispatch('party:getParty', true);
|
||||
this.group = this.$store.state.party.data;
|
||||
this.checkForAchievements();
|
||||
} else {
|
||||
const group = await this.$store.dispatch('guilds:getGroup', {groupId: this.searchId});
|
||||
this.$set(this, 'group', group);
|
||||
@@ -462,21 +461,6 @@ export default {
|
||||
return n.type === 'NEW_CHAT_MESSAGE' && n.data.group.id === groupId;
|
||||
});
|
||||
},
|
||||
checkForAchievements () {
|
||||
// Checks if user's party has reached 2 players for the first time.
|
||||
if (!this.user.achievements.partyUp && this.group.memberCount >= 2) {
|
||||
// @TODO
|
||||
// User.set({'achievements.partyUp':true});
|
||||
// Achievement.displayAchievement('partyUp');
|
||||
}
|
||||
|
||||
// Checks if user's party has reached 4 players for the first time.
|
||||
if (!this.user.achievements.partyOn && this.group.memberCount >= 4) {
|
||||
// @TODO
|
||||
// User.set({'achievements.partyOn':true});
|
||||
// Achievement.displayAchievement('partyOn');
|
||||
}
|
||||
},
|
||||
async join () {
|
||||
if (this.group.cancelledPlan && !confirm(this.$t('aboutToJoinCancelledGroupPlan'))) {
|
||||
return;
|
||||
|
||||
@@ -175,6 +175,43 @@ const NOTIFICATIONS = {
|
||||
label: ($t) => `${$t('achievement')}: ${$t('achievementAridAuthority')}`,
|
||||
modalId: 'generic-achievement',
|
||||
},
|
||||
ACHIEVEMENT_PARTY_UP: {
|
||||
achievement: true,
|
||||
label: ($t) => `${$t('achievement')}: ${$t('achievementPartyUp')}`,
|
||||
modalId: 'generic-achievement',
|
||||
},
|
||||
ACHIEVEMENT_PARTY_ON: {
|
||||
achievement: true,
|
||||
label: ($t) => `${$t('achievement')}: ${$t('achievementPartyOn')}`,
|
||||
modalId: 'generic-achievement',
|
||||
},
|
||||
ACHIEVEMENT_BEAST_MASTER: {
|
||||
achievement: true,
|
||||
label: ($t) => `${$t('achievement')}: ${$t('beastAchievement')}`,
|
||||
modalId: 'generic-achievement',
|
||||
data: {
|
||||
message: ($t) => $t('achievement'),
|
||||
modalText: ($t) => $t('mountAchievement'),
|
||||
},
|
||||
},
|
||||
ACHIEVEMENT_MOUNT_MASTER: {
|
||||
achievement: true,
|
||||
label: ($t) => `${$t('achievement')}: ${$t('mountAchievement')}`,
|
||||
modalId: 'generic-achievement',
|
||||
data: {
|
||||
message: ($t) => $t('achievement'),
|
||||
modalText: ($t) => $t('mountAchievement'),
|
||||
},
|
||||
},
|
||||
ACHIEVEMENT_TRIAD_BINGO: {
|
||||
achievement: true,
|
||||
label: ($t) => `${$t('achievement')}: ${$t('triadBingoAchievement')}`,
|
||||
modalId: 'generic-achievement',
|
||||
data: {
|
||||
message: ($t) => $t('achievement'),
|
||||
modalText: ($t) => $t('triadBingoAchievement'),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
@@ -230,7 +267,8 @@ export default {
|
||||
'ULTIMATE_GEAR_ACHIEVEMENT', 'REBIRTH_ACHIEVEMENT', 'GUILD_JOINED_ACHIEVEMENT',
|
||||
'CHALLENGE_JOINED_ACHIEVEMENT', 'INVITED_FRIEND_ACHIEVEMENT', 'NEW_CONTRIBUTOR_LEVEL',
|
||||
'CRON', 'SCORED_TASK', 'LOGIN_INCENTIVE', 'ACHIEVEMENT_ALL_YOUR_BASE', 'ACHIEVEMENT_BACK_TO_BASICS',
|
||||
'ACHIEVEMENT_DUST_DEVIL', 'ACHIEVEMENT_ARID_AUTHORITY', 'GENERIC_ACHIEVEMENT',
|
||||
'GENERIC_ACHIEVEMENT', 'ACHIEVEMENT_PARTY_UP', 'ACHIEVEMENT_PARTY_ON', 'ACHIEVEMENT_BEAST_MASTER',
|
||||
'ACHIEVEMENT_MOUNT_MASTER', 'ACHIEVEMENT_TRIAD_BINGO', 'ACHIEVEMENT_DUST_DEVIL', 'ACHIEVEMENT_ARID_AUTHORITY',
|
||||
].forEach(type => {
|
||||
handledNotifications[type] = true;
|
||||
});
|
||||
@@ -381,21 +419,30 @@ export default {
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.achievement) {
|
||||
this.playSound('Achievement_Unlocked');
|
||||
} else if (config.sound) {
|
||||
this.playSound(config.sound);
|
||||
}
|
||||
|
||||
let data = {};
|
||||
if (notification.data) {
|
||||
this.notificationData = notification.data;
|
||||
data = notification.data;
|
||||
}
|
||||
|
||||
if (!data.modalText && config.data.modalText) {
|
||||
data.modalText = config.data.modalText(this.$t);
|
||||
}
|
||||
if (!data.message && config.data.message) {
|
||||
data.message = config.data.message(this.$t);
|
||||
}
|
||||
|
||||
this.notificationData = data;
|
||||
if (forceToModal) {
|
||||
this.$root.$emit('bv::show::modal', config.modalId);
|
||||
} else {
|
||||
this.text(config.label(this.$t), () => {
|
||||
this.notificationData = data;
|
||||
this.$root.$emit('bv::show::modal', config.modalId);
|
||||
}, false);
|
||||
}
|
||||
@@ -607,6 +654,11 @@ export default {
|
||||
case 'ACHIEVEMENT_BACK_TO_BASICS':
|
||||
case 'ACHIEVEMENT_DUST_DEVIL':
|
||||
case 'ACHIEVEMENT_ARID_AUTHORITY':
|
||||
case 'ACHIEVEMENT_PARTY_UP':
|
||||
case 'ACHIEVEMENT_PARTY_ON':
|
||||
case 'ACHIEVEMENT_BEAST_MASTER':
|
||||
case 'ACHIEVEMENT_MOUNT_MASTER':
|
||||
case 'ACHIEVEMENT_TRIAD_BINGO':
|
||||
case 'GENERIC_ACHIEVEMENT':
|
||||
this.showNotificationWithModal(notification);
|
||||
break;
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
"achievementDustDevil": "Dust Devil",
|
||||
"achievementDustDevilText": "Has collected all Desert Pets.",
|
||||
"achievementDustDevilModalText": "You collected all the Desert Pets!",
|
||||
"achievementPartyUp": "You teamed up with a party member!",
|
||||
"achievementAridAuthority": "Arid Authority",
|
||||
"achievementAridAuthorityText": "Has tamed all Desert Mounts.",
|
||||
"achievementAridAuthorityModalText": "You tamed all the Desert Mounts!",
|
||||
"achievementKickstarter2019": "Pin Kickstarter Backer",
|
||||
"achievementKickstarter2019Text": "Backed the 2019 Pin Kickstarter Project"
|
||||
"achievementKickstarter2019Text": "Backed the 2019 Pin Kickstarter Project",
|
||||
"achievementPartyOn": "Your party grew to 4 members!"
|
||||
}
|
||||
|
||||
@@ -606,13 +606,25 @@ api.joinGroup = {
|
||||
promises.push(User.update({
|
||||
$or: [{'party._id': group._id}, {_id: user._id}],
|
||||
'achievements.partyUp': {$ne: true},
|
||||
}, {$set: {'achievements.partyUp': true}}, {multi: true}).exec());
|
||||
}, {$set: {'achievements.partyUp': true}, $push: {notifications: {type: 'ACHIEVEMENT_PARTY_UP'}}}, {multi: true}).exec());
|
||||
if (inviter) {
|
||||
if (inviter.achievements.partyUp !== true) {
|
||||
// Since the notification list of the inviter is already updated in this save we need to add the notification here
|
||||
inviter.addNotification('ACHIEVEMENT_PARTY_UP');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (group.memberCount > 3) {
|
||||
promises.push(User.update({
|
||||
$or: [{'party._id': group._id}, {_id: user._id}],
|
||||
'achievements.partyOn': {$ne: true},
|
||||
}, {$set: {'achievements.partyOn': true}}, {multi: true}).exec());
|
||||
}, {$set: {'achievements.partyOn': true}, $push: {notifications: {type: 'ACHIEVEMENT_PARTY_ON'}}}, {multi: true}).exec());
|
||||
if (inviter) {
|
||||
if (inviter.achievements.partyOn !== true) {
|
||||
// Since the notification list of the inviter is already updated in this save we need to add the notification here
|
||||
inviter.addNotification('ACHIEVEMENT_PARTY_ON');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,23 +188,26 @@ schema.pre('save', true, function preSaveUser (next, done) {
|
||||
// Determines if Beast Master should be awarded
|
||||
let beastMasterProgress = common.count.beastMasterProgress(this.items.pets);
|
||||
|
||||
if (beastMasterProgress >= 90 || this.achievements.beastMasterCount > 0) {
|
||||
if ((beastMasterProgress >= 90 || this.achievements.beastMasterCount > 0) && this.achievements.beastMaster !== true) {
|
||||
this.achievements.beastMaster = true;
|
||||
this.addNotification('ACHIEVEMENT_BEAST_MASTER');
|
||||
}
|
||||
|
||||
// Determines if Mount Master should be awarded
|
||||
let mountMasterProgress = common.count.mountMasterProgress(this.items.mounts);
|
||||
|
||||
if (mountMasterProgress >= 90 || this.achievements.mountMasterCount > 0) {
|
||||
if ((mountMasterProgress >= 90 || this.achievements.mountMasterCount > 0) && this.achievements.mountMaster !== true) {
|
||||
this.achievements.mountMaster = true;
|
||||
this.addNotification('ACHIEVEMENT_MOUNT_MASTER');
|
||||
}
|
||||
|
||||
// Determines if Triad Bingo should be awarded
|
||||
let dropPetCount = common.count.dropPetsCurrentlyOwned(this.items.pets);
|
||||
let qualifiesForTriad = dropPetCount >= 90 && mountMasterProgress >= 90;
|
||||
|
||||
if (qualifiesForTriad || this.achievements.triadBingoCount > 0) {
|
||||
if ((qualifiesForTriad || this.achievements.triadBingoCount > 0) && this.achievements.triadBingo !== true) {
|
||||
this.achievements.triadBingo = true;
|
||||
this.addNotification('ACHIEVEMENT_TRIAD_BINGO');
|
||||
}
|
||||
|
||||
// EXAMPLE CODE for allowing all existing and new players to be
|
||||
|
||||
@@ -40,6 +40,11 @@ const NOTIFICATION_TYPES = [
|
||||
'ACHIEVEMENT_MIND_OVER_MATTER',
|
||||
'ACHIEVEMENT_DUST_DEVIL',
|
||||
'ACHIEVEMENT_ARID_AUTHORITY',
|
||||
'ACHIEVEMENT_PARTY_UP',
|
||||
'ACHIEVEMENT_PARTY_ON',
|
||||
'ACHIEVEMENT_BEAST_MASTER',
|
||||
'ACHIEVEMENT_MOUNT_MASTER',
|
||||
'ACHIEVEMENT_TRIAD_BINGO',
|
||||
];
|
||||
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
Reference in New Issue
Block a user