'use strict'; /** * Services for each tour step when you unlock features */ angular.module('guideServices', []). factory('Guide', ['$rootScope', 'User', 'Items', 'Helpers', function($rootScope, User, Items, Helpers) { /** * Init and show the welcome tour. Note we do it listening to a $rootScope broadcasted 'userLoaded' message, * this because we need to determine whether to show the tour *after* the user has been pulled from the server, * otherwise it's always start off as true, and then get set to false later */ $rootScope.$on('userUpdated', initTour); function initTour(){ if (User.user.flags.showTour === false) return; var tourSteps = [ { element: ".main-herobox", title: "Welcome to HabitRPG", content: "Welcome to HabitRPG, a habit-tracker which treats your goals like a Role Playing Game. I'm Justin, your guide! " }, { element: "#bars", title: "Achieve goals and level up", content: "As you accomplish goals, you level up. If you fail your goals, you lose hit points. Lose all your HP and you die." }, { element: "ul.habits", title: "Habits", content: "Habits are goals that you constantly track.", placement: "bottom" }, { element: "ul.dailys", title: "Dailies", content: "Dailies are goals that you want to complete once a day.", placement: "bottom" }, { element: "ul.todos", title: "Todos", content: "Todos are one-off goals which need to be completed eventually.", placement: "bottom" }, { element: "ul.rewards", title: "Rewards", content: "As you complete goals, you earn gold to buy rewards. Buy them liberally - rewards are integral in forming good habits.", placement: "bottom" }, { element: "ul.habits li:first-child", title: "Hover over comments", content: "Different task-types have special properties. Hover over each task's comment for more information. When you're ready to get started, delete the existing tasks and add your own.", placement: "right" } ]; _.each(tourSteps, function(step){ step.content = "
" + step.content + "
"; // add Justin NPC img }); $('.main-herobox').popover('destroy'); var tour = new Tour({ onEnd: function(){ User.set('flags.showTour', false); } }); tourSteps.forEach(function(step) { tour.addStep(_.defaults(step, {html: true})); }); tour.restart(); // Tour doesn't quite mesh with our handling of flags.showTour, just restart it on page load //tour.start(true); }; var alreadyShown = function(before, after) { return !(!before && after === true); }; var showPopover = function(selector, title, html, placement) { if (!placement) placement = 'bottom'; $(selector).popover('destroy'); var button = ""; html = "
" + html + '
' + button + '
'; $(selector).popover({ title: title, placement: placement, trigger: 'manual', html: true, content: html }).popover('show'); }; $rootScope.$watch('user.flags.customizationsNotification', function(after, before) { if (alreadyShown(before, after)) return; showPopover('.main-herobox', 'Customize Your Avatar', "Click your avatar to customize your appearance.", 'bottom'); }); $rootScope.$watch('user.flags.itemsEnabled', function(after, before) { if (alreadyShown(before, after)) return; var html = "Congratulations, you have unlocked the Item Store! You can now buy weapons, armor, potions, etc. Read each item's comment for more information."; showPopover('div.rewards', 'Item Store Unlocked', html, 'left'); }); $rootScope.$watch('user.flags.petsEnabled', function(after, before) { //TODO is this ever used? I think dropsEnabled is the one that's used if (alreadyShown(before, after)) return; var html = "You have unlocked Pets! You can now buy pets with Gems (note, you replenish Gems with real-life money - so chose your pets wisely!)"; showPopover('#rewardsTabs', 'Pets Unlocked', html, 'left'); }); $rootScope.$watch('user.flags.partyEnabled', function(after, before) { if (alreadyShown(before, after)) return; var html = "Be social, join a party and play Habit with your friends! You'll be better at your habits with accountability partners. Click User -> Options -> Party, and follow the instructions. LFG anyone?"; showPopover('.user-menu', 'Party System', html, 'bottom'); }); $rootScope.$watch('user.flags.dropsEnabled', function(after, before) { if (alreadyShown(before, after)) return; var drop = Helpers.randomVal(Items.items.pets); var eggs = User.user.items.eggs = []; eggs.push(drop); // FIXME put this on server instead User.set('items.eggs', eggs); $rootScope.modals.dropsEnabled = true; }); $rootScope.$watch('user.items.pets', function(after, before) { if (User.user.achievements && User.user.achievements.beastMaster) return; if (before >= 90) { User.set('achievements.beastMaster', true); $('#beastmaster-achievement-modal').modal('show'); // FIXME } }); $rootScope.$watch('user.items', function(after, before) { if (User.user.achievements && User.user.achievements.ultimateGear) return; var items = User.user.items; if (+items.weapon >= 6 && +items.armor >= 5 && +items.head >= 5 && +items.shield >= 5) { User.set('achievements.ultimateGear', true); // FIXME $('#max-gear-achievement-modal').modal('show'); // FIXME } }); // FIXME how to handle tasks.*.streak? // FIXME move to tasksCtrl /*$rootScope.$watch('user.tasks.*.streak', function(id, after, before) { if (after > 0) { if ((after % 21) === 0) { user.incr('achievements.streak', 1) return $('#streak-achievement-modal').modal('show'); } else if ((before - after === 1) && (before % 21 === 0)) { return user.incr('achievements.streak', -1); } } });*/ return { initTour:initTour }; } ]);