Merge pull request #4550 from HabitRPG/bailey-20150120

Bailey 20150120 & Mount Master
This commit is contained in:
Blade Barringer 2015-01-20 17:06:14 -06:00
commit 5246257f62
14 changed files with 207 additions and 55 deletions

View file

@ -116,7 +116,8 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
// We watch Members.selectedMember because it's asynchronously set, so would be a hassle to handle updates here
$scope.$watch( function() { return Members.selectedMember; }, function (member) {
if(member)
member.petCount = Shared.countPets(null, member.items.pets);
member.petCount = Shared.countPets($rootScope.countExists(member.items.pets), member.items.pets);
member.mountCount = Shared.countMounts($rootScope.countExists(member.items.mounts), member.items.mounts);
$scope.profile = member;
});
$scope.sendPrivateMessage = function(uuid, message){

View file

@ -1,5 +1,6 @@
habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', '$window', 'User', 'Content',
function($rootScope, $scope, $window, User, Content) {
habitrpg.controller("InventoryCtrl",
['$rootScope', '$scope', 'Shared', '$window', 'User', 'Content',
function($rootScope, $scope, Shared, $window, User, Content) {
var user = User.user;
@ -8,12 +9,11 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', '$window', 'User',
$scope.selectedEgg = null; // {index: 1, name: "Tiger", value: 5}
$scope.selectedPotion = null; // {index: 5, name: "Red", value: 3}
$scope.totalPets = _.size(Content.dropEggs) * _.size(Content.hatchingPotions);
$scope.totalMounts = _.size(_.reject(Content.eggs,function(egg){return egg.noMount})) * _.size(Content.hatchingPotions);
$scope.totalMounts = _.size(Content.dropEggs) * _.size(Content.hatchingPotions);
// count egg, food, hatchingPotion stack totals
var countStacks = function(items) { return _.reduce(items,function(m,v){return m+v;},0);}
$scope.$watch('user.items.mounts', function(mounts){ $scope.mountCount = $rootScope.countExists(mounts); }, true);
$scope.$watch('user.items.eggs', function(eggs){ $scope.eggCount = countStacks(eggs); }, true);
$scope.$watch('user.items.hatchingPotions', function(pots){ $scope.potCount = countStacks(pots); }, true);
$scope.$watch('user.items.food', function(food){ $scope.foodCount = countStacks(food); }, true);
@ -77,6 +77,18 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', '$window', 'User',
return _.pick(inventory, function(v,k){return v>0;});
}
$scope.calcTriadBingo = function() {
var hasPets = Shared.countPets(null, User.user.items.pets) >= 90 ;
var hasMounts = Shared.countMounts(null, User.user.items.mounts) >= 90;
if(!(hasPets && hasMounts)) return false;
for (var p in User.user.items.pets) {
if(User.user.items.pets[p] < 0) return false;
}
return true;
}
$scope.hatch = function(egg, potion){
var eggName = Content.eggs[egg.key].text();
var potName = Content.hatchingPotions[potion.key].text();
@ -84,6 +96,20 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', '$window', 'User',
user.ops.hatch({params:{egg:egg.key, hatchingPotion:potion.key}});
$scope.selectedEgg = null;
$scope.selectedPotion = null;
// Checks if beastmaster has been reached for the first time
if(!User.user.achievements.beastMaster
&& Shared.countPets(null, User.user.items.pets) >= 90) {
User.user.achievements.beastMaster = true;
$rootScope.openModal('achievements/beastMaster');
}
// Checks if Triad Bingo has been reached for the first time
if(!User.user.achievements.triadBingo
&& $scope.calcTriadBingo()) {
User.user.achievements.triadBingo = true;
$rootScope.openModal('achievements/triadBingo');
}
}
$scope.purchase = function(type, item){
@ -123,6 +149,14 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', '$window', 'User',
}
User.user.ops.feed({params:{pet: pet, food: food.key}});
$scope.selectedFood = null;
$rootScope.mountCount = Shared.countMounts(null, User.user.items.mounts);
// Checks if mountmaster has been reached for the first time
if(!User.user.achievements.mountMaster
&& Shared.countMounts(null, User.user.items.mounts) >= 90) {
User.user.achievements.mountMaster = true;
$rootScope.openModal('achievements/mountMaster');
}
// Selecting Pet
} else {

View file

@ -104,15 +104,6 @@ habitrpg.controller('NotificationCtrl',
$rootScope.openModal('achievements/ultimateGear');
});
$rootScope.$watch('user.items.pets', function(after, before){
if(_.size(after) === _.size(before) ||
Shared.countPets(null, after) < 90) return;
if (User.user.achievements.beastMaster == false) {
User.user.achievements.beastMaster = true;
$rootScope.openModal('achievements/beastMaster');
}
}, true);
$rootScope.$watch('user.achievements.rebirths', function(after, before){
if(after === before) return;
$rootScope.openModal('achievements/rebirth');

View file

@ -88,7 +88,8 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
// count pets, mounts collected totals, etc
$rootScope.countExists = function(items) {return _.reduce(items,function(m,v){return m+(v?1:0)},0)}
$rootScope.petCount = Shared.countPets(null, User.user.items.pets);
$rootScope.petCount = Shared.countPets($rootScope.countExists(User.user.items.pets), User.user.items.pets);
$rootScope.mountCount = Shared.countMounts($rootScope.countExists(User.user.items.mounts), User.user.items.mounts);
$rootScope.$watch('user.items.pets', function(pets){
$rootScope.petCount = Shared.countPets($rootScope.countExists(pets), User.user.items.pets);

View file

@ -156,13 +156,20 @@ habitrpg.controller('SettingsCtrl',
window.location.href = '/api/v2/coupons?limit='+codes.count+'&_id='+User.user._id+'&apiToken='+User.user.apiToken;
})
}
$scope.release = function() {
User.user.ops.release({});
$scope.releasePets = function() {
User.user.ops.releasePets({});
$rootScope.$state.go('tasks');
}
$scope.release2 = function() {
User.user.ops.release2({});
$scope.releaseMounts = function() {
User.user.ops.releaseMounts({});
$rootScope.mountCount = 0;
$rootScope.$state.go('tasks');
}
$scope.releaseBoth = function() {
User.user.ops.releaseBoth({});
$rootScope.mountCount = 0;
$rootScope.$state.go('tasks');
}

View file

@ -3,7 +3,8 @@
habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$http', '$state', 'Guide', 'Shared',
function($rootScope, $scope, $location, User, $http, $state, Guide, Shared) {
$scope.profile = User.user;
$scope.profile.petCount = Shared.countPets(null, $scope.profile.items.pets);
$scope.profile.petCount = Shared.countPets($rootScope.countExists($scope.profile.items.pets), $scope.profile.items.pets);
$scope.profile.mountCount = Shared.countMounts($rootScope.countExists($scope.profile.items.mounts), $scope.profile.items.mounts);
$scope.hideUserAvatar = function() {
$(".userAvatar").hide();
};

View file

@ -36,6 +36,10 @@ var UserSchema = new Schema({
ultimateGear: Boolean,
beastMaster: Boolean,
beastMasterCount: Number,
mountMaster: Boolean,
mountMasterCount: Number,
triadBingo: Boolean,
triadBingoCount: Number,
veteran: Boolean,
snowball: Number,
spookDust: Number,
@ -429,6 +433,7 @@ UserSchema.pre('save', function(next) {
'Anonymous';
}
// Determines if Beast Master should be awarded
var petCount = shared.countPets(_.reduce(this.items.pets,function(m,v){
//HOTFIX - Remove when solution is found, the first argument passed to reduce is a function
if(_.isFunction(v)) return m;
@ -438,6 +443,29 @@ UserSchema.pre('save', function(next) {
this.achievements.beastMaster = true
}
// Determines if Mount Master should be awarded
var mountCount = shared.countMounts(_.reduce(this.items.mounts,function(m,v){
//HOTFIX - Remove when solution is found, the first argument passed to reduce is a function
if(_.isFunction(v)) return m;
return m+(v?1:0)},0), this.items.mounts);
if (mountCount >= 90 || this.achievements.mountMasterCount > 0) {
this.achievements.mountMaster = true
}
// Determines if Triad Bingo should be awarded
var giveTriadBingo = function(pets) {
for(var p in pets) {
if(pets[p] == -1) return false;
}
return true;
};
if ((mountCount >= 90 && giveTriadBingo(this.items.pets)) || this.achievements.triadBingoCount > 0) {
this.achievements.triadBingo = true;
}
// EXAMPLE CODE for allowing all existing and new players to be
// automatically granted an item during a certain time period:
// if (!this.items.pets['JackOLantern-Base'] && moment().isBefore('2014-11-01'))

View file

@ -226,8 +226,8 @@ script(type='text/ng-template', id='partials/options.inventory.drops.html')
p(ng-show='user.stats.lvl < 100')
| 8&nbsp;
span.Pet_Currency_Gem1x.inline-gems
div(ng-show='petCount >= 90')
button.customize-option(popover=env.t('petKeyPop'), popover-title=env.t('petKeyName'), popover-trigger='mouseenter', popover-placement='top', ng-click='openModal("pet-key")', class='pet_key')
div(ng-show='petCount >= 90 || mountCount >= 90')
button.customize-option(popover=env.t('petKeyPop'), popover-title=env.t('petKeyName'), popover-trigger='mouseenter', popover-placement='top', ng-click='openModal("pet-key", {size:"lg"})', class='pet_key')
p
| 4&nbsp;
span.Pet_Currency_Gem1x.inline-gems

View file

@ -41,7 +41,7 @@ script(type='text/ng-template', id='partials/options.inventory.mounts.html')
a(target='_blank', href='http://www.kickstarter.com/profile/mattboch')=env.t('mattBoch')
.popover-content
p=env.t('mattShall', {name: "{{user.profile.name}}"})
h4= '{{Shared.countMounts(null,User.user.items.mounts) || 0}} / {{totalMounts}} ' + env.t('mountsTamed')
h4= env.t('mountMasterProgress') + ': {{mountCount}} / {{totalMounts}} ' + env.t('mountsTamed')
.col-md-12
+mountList(env.Content.dropEggs)
.col-md-12
@ -66,13 +66,8 @@ script(type='text/ng-template', id='partials/options.inventory.pets.html')
h3.popover-title
a(target='_blank', href='http://www.kickstarter.com/profile/mattboch')=env.t('mattBoch')
.popover-content
p
=env.t('mattBochText1') + ' '
| <a target='_blank' href='https://f.cloud.github.com/assets/2374703/164631/3ed5fa6c-78cd-11e2-8743-f65ac477b55e.png'>
=env.t('mattBochText2')
| </a>
= ' ' + env.t('mattBochText3')
h4= env.t('beastmasterProgress') + ': {{petCount}} / {{totalPets}} ' + env.t('petsFound')
p=env.t('mattBochText1')
h4= env.t('beastMasterProgress') + ': {{petCount}} / {{totalPets}} ' + env.t('petsFound')
.col-md-12
+petList(env.Content.dropEggs)

View file

@ -29,6 +29,29 @@ script(id='modals/achievements/beastMaster.html', type='text/ng-template')
.modal-footer
button.btn.btn-default(ng-click='$close()')=env.t('ok')
// Mount Master
script(id='modals/achievements/mountMaster.html', type='text/ng-template')
.modal-header
h4=env.t('modalAchievement')
.modal-body
p
.achievement.achievement-wolf
=env.t('mountAchievement')
.modal-footer
button.btn.btn-default(ng-click='$close()')=env.t('ok')
// Triad Bingo
script(id='modals/achievements/triadBingo.html', type='text/ng-template')
.modal-header
h4=env.t('modalAchievement')
.modal-body
p
.achievement.achievement-triadbingo
=env.t('triadBingoAchievement')
.modal-footer
button.btn.btn-default(ng-click='$close()')=env.t('ok')
// Contributor
// activated by user.flags.contributor
script(id='modals/achievements/contributor.html', type='text/ng-template')

View file

@ -16,11 +16,14 @@ script(type='text/ng-template', id='modals/dropsEnabled.html')
script(type='text/ng-template', id='modals/pet-key.html')
.modal-header
h4=env.t('petKeyBegin')
// Checks if user has 90 pets and 90 mounts. If so, displays "Beast Master/Mount Master".
// Else if user has 90 pets, displays "Beast Master". Else, displays "Mount Master"
- var masterTitle='{{petCount >= 90 && mountCount >= 90 ? env.t("beastMountMasterName") : petCount >= 90 ? env.t("beastMasterName") : env.t("mountMasterName")}}'
h4=env.t('petKeyBegin', {title: masterTitle})
.modal-body
+gemButton
figure
.npc_alex
.npc_matt
p=env.t('petKeyInfo')
br
p=env.t('petKeyInfo2')
@ -31,10 +34,18 @@ script(type='text/ng-template', id='modals/pet-key.html')
span(ng-if='user.balance < 1')
a.btn.btn-success(ng-click='openModal("buyGems")')=env.t('buyMoreGems')
span.gem-cost=env.t('notEnoughGems')
span(ng-if='user.balance >= 1', ng-controller='SettingsCtrl')
a.btn.btn-danger(ng-click='$close(); release()')=env.t('petKeyPets')
span(ng-if='user.balance >= 1', ng-controller='SettingsCtrl')
a.btn.btn-danger(ng-click='$close(); release2()')=env.t('petKeyMounts')
span.gem-cost
| 4&nbsp;
=env.t('gemsEach')
span(ng-if='user.balance >= 1 && petCount >= 90', ng-controller='SettingsCtrl')
a.btn.btn-danger(ng-click='$close(); releasePets()')
=env.t('petKeyPets')
| : 4&nbsp;
span.Pet_Currency_Gem1x.inline-gems
span(ng-if='user.balance >= 1 && mountCount >= 90', ng-controller='SettingsCtrl')
a.btn.btn-danger(ng-click='$close(); releaseMounts()')
=env.t('petKeyMounts')
| : 4&nbsp;
span.Pet_Currency_Gem1x.inline-gems
span(ng-if='user.balance >= 1.5 && petCount >= 90 && mountCount >= 90', ng-controller='SettingsCtrl')
a.btn.btn-danger(ng-click='$close(); releaseBoth()')
=env.t('petKeyBoth')
| : 6&nbsp;
span.Pet_Currency_Gem1x.inline-gems

View file

@ -1,14 +1,47 @@
h5
h5 MOUNT MASTER AND TRIAD BINGO ACHIEVEMENTS, PARTY SORTING OPTIONS, DATED TO-DOs, AND STRESSBEAST DESPERATION TRIGGERED!
hr
tr
td
h5 1/19/2015 - WORLD BOSS: SECOND STRESS STRIKE!
p AHHHHHHHH!!!!! IT'S GOT ME!!!!! Oh, Habiticans, why didn't you do your Dailies?!
p The World Boss in the <a href='https://habitrpg.com/#/options/groups/tavern' target='_blank'>Tavern</a> has used another Stress Strike, and this time it's attacked me, Bailey the Town Crier! To save me and the other NPCs, complete Dailies and To-Dos to damage the World Boss! Incomplete Dailies fill the Stress Strike Bar. When the Stress Strike bar is full, the World Boss will attack an NPC and regain some health. A World Boss will never damage individual players or accounts in any way. Only active accounts who are not resting in the inn will have their incomplete Dailies tallied.
p by Lemoness, Kiwibot, and SabreCat
h5 Mount Master and Triad Bingo Achievements
.achievement.achievement-wolf
.achievement.achievement-triadbingo
p There are two new achievements you can earn: Mount Master and Triad Bingo! Mount Master is awarded to users who have collected all 90 standard mounts, and Triad Bingo is for those who have collected all 90 standard pets, grown all 90 into mounts, and then rehatched 90 more standard pets. Wow!
P Note that Quest Pets and Quest Mounts do not count towards Mount Master or Triad Bingo. If you currently meet the criteria, you will be awarded the badge, but unfortunately, if you already released your Mounts, you will not receive the badge until you collect them again.
p.small.muted by Taldin, Blade, Lorian, Aiseant, and Hanztan
tr
td
h5 Party Sorting Options
p In the <a href="/#/options/groups/party">Party Page</a> you can now sort your friends' avatars in ascending or descending order! To make the change take effect, you'll have to refresh the page.
p.small.muted by Blade and Viirus
tr
td
h5 Dated To-Dos
p Now you can use To-Do tabs to sort and see your dated To-Dos! Simply click the "Dated" tab and only To-Dos with a due date will be displayed. They are not currently sorted by date, but we will be implementing that feature in the future.
p.small.muted by Alys
tr
td
h5 Stressbeast Desperation Triggered
p We're almost there, Habiticans! With diligence and Dailies, we've whittled the Stressbeast's health down to only 500K! The creature roars and flails in desperation, rage building faster than ever. The monster is --- AHHH! --- swinging me and Matt around at a terrifying pace, raising a blinding snowstorm that makes it harder to hit.
p We'll have to redouble our efforts, but take heart - this is a sign that the Stressbeast knows it is about to be defeated. Don't give up now! Please?
p The Stressbeast raises its Rage and Defense! Complete Dailies and To-Dos to damage the World Boss. A World Boss will never damage individual players or accounts in any way. Only active accounts who are not resting in the inn will have their incomplete Dailies tallied.
p.small.muted by Lemoness, Kiwibot, and SabreCat
hr
a(href='/static/old-news', target='_blank') Read older news
mixin oldNews
h5 1/19/2015
tr
td
h5 WORLD BOSS: SECOND STRESS STRIKE!
p AHHHHHHHH!!!!! IT'S GOT ME!!!!! Oh, Habiticans, why didn't you do your Dailies?!
p The World Boss in the <a href='https://habitrpg.com/#/options/groups/tavern' target='_blank'>Tavern</a> has used another Stress Strike, and this time it's attacked me, Bailey the Town Crier! To save me and the other NPCs, complete Dailies and To-Dos to damage the World Boss! Incomplete Dailies fill the Stress Strike Bar. When the Stress Strike bar is full, the World Boss will attack an NPC and regain some health. A World Boss will never damage individual players or accounts in any way. Only active accounts who are not resting in the inn will have their incomplete Dailies tallied.
p.small.muted by Lemoness, Kiwibot, and SabreCat
h5 1/15/2015
tr
td

View file

@ -81,10 +81,28 @@ div(ng-if='::user._id == profile._id')
div(ng-if='profile.achievements.beastMaster || user._id == profile._id')
.achievement.achievement-rat(ng-show='profile.achievements.beastMaster')
div(ng-class='{muted: !profile.achievements.beastMaster}')
h5=env.t('beastMastName')
small=env.t('beastMastText')
h5=env.t('beastMasterName')
small=env.t('beastMasterText')
small(ng-if='profile.achievements.beastMasterCount')
=env.t('beastMastText2', {count: "{{profile.achievements.beastMasterCount}}"})
=env.t('beastMasterText2', {count: "{{profile.achievements.beastMasterCount}}"})
hr
div(ng-if='profile.achievements.mountMaster || user._id == profile._id')
.achievement.achievement-wolf(ng-show='profile.achievements.mountMaster')
div(ng-class='{muted: !profile.achievements.mountMaster}')
h5=env.t('mountMasterName')
small=env.t('mountMasterText')
small(ng-if='profile.achievements.mountMasterCount')
=env.t('mountMasterText2', {count: "{{profile.achievements.mountMasterCount}}"})
hr
div(ng-if='profile.achievements.triadBingo || user._id == profile._id')
.achievement.achievement-triadbingo(ng-show='profile.achievements.triadBingo')
div(ng-class='{muted: !profile.achievements.triadBingo}')
h5=env.t('triadBingoName')
small=env.t('triadBingoText')
small(ng-if='profile.achievements.triadBingoCount')
=env.t('triadBingoText2', {count: "{{profile.achievements.triadBingoCount}}"})
hr
div(ng-if='profile.achievements.rebirths')
@ -190,4 +208,4 @@ div(ng-if='::profile.achievements.quests.stressbeast')
h5=env.t('achievementStressbeast')
small
=env.t('achievementStressbeastText')
hr
hr

View file

@ -21,7 +21,6 @@ table.table.table-striped
unless mobile
h4.stats-equipment(class=mobile?'item item-divider':'',ng-show='user.flags.itemsEnabled')=env.t('equipment')
table.table.table-striped(ng-show='user.flags.itemsEnabled')
// FIXME this isn't refreshing properly. On first party modal, correct. Second party modal click gives the previous gear. It's always one behind.
tr(ng-repeat='(k,v) in profile.items.gear.equipped', ng-init='piece=Content.gear.flat[v]', ng-show='piece')
td
strong {{piece.text()}}:&nbsp;
@ -65,14 +64,24 @@ table.table.table-striped
strong.hint(popover-title=env.t('streaksFrozen'), popover-trigger='mouseenter', popover-placement='right', popover=env.t('streaksFrozenText'))=env.t('streaksFrozen')
td
h4(class=mobile?'item item-divider':'',ng-show='user.flags.dropsEnabled')=env.t('pets')
table.table.table-striped(ng-show='user.flags.dropsEnabled')
h4(class=mobile?'item item-divider':'',ng-if='user.flags.dropsEnabled')=env.t('pets')
table.table.table-striped(ng-if='user.flags.dropsEnabled')
tr
td
strong=env.t('petsFound')
| : {{profile.petCount}}
// Dunno why this doesn't work //
// tr
| : {{_.size(profile.items.pets)}}
tr
td
strong=env.t('beastMasterProgress')
| : {{profile.petCount}}/90
h4(class=mobile?'item item-divider':'', ng-if='user.flags.dropsEnabled')=env.t('mounts')
table.table.table-striped(ng-if='user.flags.dropsEnabled')
tr
td
strong=env.t('mountsTamed')
| : {{profile.mountCount}} //
| : {{_.size(profile.items.mounts)}}
tr
td
strong=env.t('mountMasterProgress')
| : {{profile.mountCount}}/90