mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
[#1977] APIv2 WIP - start of a framework where operations are shared
between client & server. If the op is called on the client, it updates the user & then POSTs to the server with op of the same name. If called on server, it updates the user and user.save()s
This commit is contained in:
@@ -17,7 +17,7 @@ window.env.t = function(string){
|
||||
|
||||
window.habitrpg = angular.module('habitrpg',
|
||||
['ngResource', 'ngSanitize', 'userServices', 'groupServices', 'memberServices', 'challengeServices',
|
||||
'sharedServices', 'authServices', 'notificationServices', 'guideServices',
|
||||
'authServices', 'notificationServices', 'guideServices',
|
||||
'ui.bootstrap', 'ui.keypress', 'ui.router', 'chieffancypants.loadingBar', 'At', 'pasvaz.bindonce'])
|
||||
|
||||
// @see https://github.com/angular-ui/ui-router/issues/110 and https://github.com/HabitRPG/habitrpg/issues/1705
|
||||
|
||||
@@ -132,7 +132,7 @@ habitrpg.controller("ChallengesCtrl", ['$scope', 'User', 'Challenges', 'Notifica
|
||||
//------------------------------------------------------------
|
||||
|
||||
$scope.addTask = function(addTo, listDef) {
|
||||
var task = window.habitrpgShared.helpers.taskDefaults({text: listDef.newTask, type: listDef.type});
|
||||
var task = $rootScope.Shared.taskDefaults({text: listDef.newTask, type: listDef.type});
|
||||
addTo.unshift(task);
|
||||
//User.log({op: "addTask", data: task}); //TODO persist
|
||||
delete listDef.newTask;
|
||||
|
||||
@@ -22,7 +22,7 @@ habitrpg.controller("FiltersCtrl", ['$scope', '$rootScope', 'User', 'API_URL', '
|
||||
$scope.createTag = function(name) {
|
||||
user.tags = user.tags || [];
|
||||
user.tags.push({
|
||||
id: window.habitrpgShared.helpers.uuid(),
|
||||
id: $rootScope.Shared.uuid(),
|
||||
name: name
|
||||
});
|
||||
User.log({op:'set',data:{'tags':user.tags}});
|
||||
|
||||
@@ -47,17 +47,16 @@ habitrpg.controller("FooterCtrl", ['$scope', '$rootScope', 'User', '$http', 'Not
|
||||
$scope.addMissedDay = function(){
|
||||
if (!confirm("Are you sure you want to reset the day?")) return;
|
||||
var dayBefore = moment(User.user.lastCron).subtract('days', 1).toDate();
|
||||
User.set('lastCron', dayBefore);
|
||||
User.set({'lastCron': dayBefore});
|
||||
Notification.text('-1 day, remember to refresh');
|
||||
}
|
||||
$scope.addTenGems = function(){
|
||||
console.log(API_URL);
|
||||
$http.post(API_URL + '/api/v1/user/addTenGems').success(function(){
|
||||
User.log({});
|
||||
})
|
||||
}
|
||||
$scope.addLevelsAndGold = function(){
|
||||
User.setMultiple({
|
||||
User.set({
|
||||
'stats.exp': User.user.stats.exp + 10000,
|
||||
'stats.gp': User.user.stats.gp + 10000
|
||||
});
|
||||
|
||||
@@ -66,7 +66,7 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', 'A
|
||||
// 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 = window.habitrpgShared.helpers.countPets(null, member.items.pets);
|
||||
member.petCount = $rootScope.Shared.countPets(null, member.items.pets);
|
||||
$scope.profile = member;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
function($rootScope, $scope, User, API_URL, $http, Notification) {
|
||||
|
||||
var user = User.user;
|
||||
var Items = window.habitrpgShared.items;
|
||||
var Content = $rootScope.Shared.content;
|
||||
|
||||
// convenience vars since these are accessed frequently
|
||||
|
||||
$scope.selectedEgg = null; // {index: 1, name: "Tiger", value: 5}
|
||||
$scope.selectedPotion = null; // {index: 5, name: "Red", value: 3}
|
||||
$scope.totalPets = _.size($scope.Items.eggs) * _.size($scope.Items.hatchingPotions);
|
||||
$scope.totalPets = _.size(Content.eggs) * _.size(Content.hatchingPotions);
|
||||
|
||||
// count egg, food, hatchingPotion stack totals
|
||||
var countStacks = function(items) { return _.reduce(items,function(m,v){return m+v;},0);}
|
||||
@@ -20,10 +20,10 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
|
||||
$scope.$watch('user.items.gear', function(gear){
|
||||
$scope.gear = {
|
||||
base: _.where(Items.items.gear.flat, {klass: 'base'})
|
||||
base: _.where(shared.content.gear.flat, {klass: 'base'})
|
||||
};
|
||||
_.each(gear.owned, function(bool,key){
|
||||
var item = Items.items.gear.flat[key];
|
||||
var item = shared.content.gear.flat[key];
|
||||
if (!$scope.gear[item.klass]) $scope.gear[item.klass] = [];
|
||||
$scope.gear[item.klass].push(item);
|
||||
})
|
||||
@@ -33,7 +33,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
if ($scope.selectedEgg && $scope.selectedEgg.name == egg) {
|
||||
return $scope.selectedEgg = null; // clicked same egg, unselect
|
||||
}
|
||||
var eggData = _.findWhere(Items.items.eggs, {name:egg});
|
||||
var eggData = _.findWhere(shared.content.eggs, {name:egg});
|
||||
if (!$scope.selectedPotion) {
|
||||
$scope.selectedEgg = eggData;
|
||||
} else {
|
||||
@@ -46,7 +46,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
return $scope.selectedPotion = null; // clicked same egg, unselect
|
||||
}
|
||||
// we really didn't think through the way these things are stored and getting passed around...
|
||||
var potionData = _.findWhere(Items.items.hatchingPotions, {name:potion});
|
||||
var potionData = _.findWhere(shared.content.hatchingPotions, {name:potion});
|
||||
if (!$scope.selectedEgg) {
|
||||
$scope.selectedPotion = potionData;
|
||||
} else {
|
||||
@@ -56,42 +56,18 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
|
||||
$scope.chooseFood = function(food){
|
||||
if ($scope.selectedFood && $scope.selectedFood.name == food) return $scope.selectedFood = null;
|
||||
$scope.selectedFood = $scope.Items.food[food];
|
||||
$scope.selectedFood = Content.food[food];
|
||||
}
|
||||
|
||||
$scope.sellInventory = function() {
|
||||
// TODO DRY this
|
||||
if ($scope.selectedEgg) {
|
||||
user.items.eggs[$scope.selectedEgg.name]--;
|
||||
User.setMultiple({
|
||||
'items.eggs': user.items.eggs,
|
||||
'stats.gp': User.user.stats.gp + $scope.selectedEgg.value
|
||||
});
|
||||
if (user.items.eggs[$scope.selectedEgg.name] < 1) {
|
||||
$scope.selectedEgg = null;
|
||||
}
|
||||
|
||||
} else if ($scope.selectedPotion) {
|
||||
user.items.hatchingPotions[$scope.selectedPotion.name]--;
|
||||
User.setMultiple({
|
||||
'items.hatchingPotions': user.items.hatchingPotions,
|
||||
'stats.gp': User.user.stats.gp + $scope.selectedPotion.value
|
||||
});
|
||||
if (user.items.hatchingPotions[$scope.selectedPotion.name] < 1) {
|
||||
$scope.selectedPotion = null;
|
||||
}
|
||||
|
||||
} else if ($scope.selectedFood) {
|
||||
user.items.food[$scope.selectedFood.name]--;
|
||||
User.setMultiple({
|
||||
'items.food': user.items.food,
|
||||
'stats.gp': User.user.stats.gp + $scope.selectedFood.value
|
||||
});
|
||||
if (user.items.food[$scope.selectedFood.name] < 1) {
|
||||
$scope.selectedFood = null;
|
||||
var selected = $scope.selectedEgg ? 'selectedEgg' : $scope.selectedPotion ? 'selectedPotion' : $scope.selectedFood ? 'selectedFood' : undefined;
|
||||
if (selected) {
|
||||
var type = $scope.selectedEgg ? 'eggs' : $scope.selectedPotion ? 'hatchingPotions' : $scope.selectedFood ? 'food' : undefined;
|
||||
user.ops.sell({query:{type:type, key: $scope[selected].name}});
|
||||
if (user.items[type][$scope[selected].name] < 1) {
|
||||
$scope[selected] = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$scope.ownedItems = function(inventory){
|
||||
@@ -99,21 +75,15 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
}
|
||||
|
||||
$scope.hatch = function(egg, potion){
|
||||
var pet = egg.name+"-"+potion.name;
|
||||
if (user.items.pets[pet])
|
||||
return alert("You already have that pet. Try hatching a different combination!");
|
||||
|
||||
var setObj = {};
|
||||
setObj['items.pets.' + pet] = 5;
|
||||
setObj['items.eggs.' + egg.name] = user.items.eggs[egg.name] - 1;
|
||||
setObj['items.hatchingPotions.' + potion.name] = user.items.hatchingPotions[potion.name] - 1;
|
||||
|
||||
User.setMultiple(setObj);
|
||||
|
||||
alert("Your egg hatched! Visit your stable to equip your pet.");
|
||||
|
||||
$scope.selectedEgg = null;
|
||||
$scope.selectedPotion = null;
|
||||
user.ops.hatch({query:{egg:egg.name, hatchingPotion:potion.name}}, function(err, req){
|
||||
// Bypassing the UserServices-injected callback so we can only show alert on success. It's safe, since this means
|
||||
// UserServices callback will be 3rd param and never get called
|
||||
if (err) return Notification.text(err);
|
||||
User.log({op:'hatch', query:req.query});
|
||||
Notification.text("Your egg hatched! Visit your stable to equip your pet.");
|
||||
$scope.selectedEgg = null;
|
||||
$scope.selectedPotion = null;
|
||||
});
|
||||
}
|
||||
|
||||
$scope.buy = function(type, item){
|
||||
@@ -134,7 +104,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
|
||||
// Feeding Pet
|
||||
if ($scope.selectedFood) {
|
||||
if (window.habitrpgShared.items.items.specialPets[pet]) return Notification.text("Can't feed this pet.");
|
||||
if (window.habitrpgShared.shared.content.specialPets[pet]) return Notification.text("Can't feed this pet.");
|
||||
var setObj = {};
|
||||
var userPets = user.items.pets;
|
||||
if (user.items.mounts[pet] && (userPets[pet] >= 50 || $scope.selectedFood.name == 'Saddle'))
|
||||
@@ -163,7 +133,7 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
}
|
||||
setObj['items.pets.' + pet] = userPets[pet];
|
||||
setObj['items.food.' + $scope.selectedFood.name] = user.items.food[$scope.selectedFood.name] - 1;
|
||||
User.setMultiple(setObj);
|
||||
User.set(setObj);
|
||||
$scope.selectedFood = null;
|
||||
|
||||
// Selecting Pet
|
||||
@@ -182,19 +152,5 @@ habitrpg.controller("InventoryCtrl", ['$rootScope', '$scope', 'User', 'API_URL',
|
||||
var mount = egg + '-' + potion;
|
||||
User.set('items.currentMount', (user.items.currentMount == mount) ? '' : mount);
|
||||
}
|
||||
|
||||
$scope.equip = function(user, item, costume) {
|
||||
var equipTo = costume ? 'costume' : 'equipped';
|
||||
if (item.type == 'shield') {
|
||||
var weapon = Items.items.gear.flat[user.items.gear[equipTo].weapon];
|
||||
if (weapon && weapon.twoHanded) return Notification.text(weapon.text + ' is two-handed');
|
||||
}
|
||||
var setVars = {};
|
||||
setVars['items.gear.' + equipTo + '.' + item.type] = item.key;
|
||||
if (item.twoHanded)
|
||||
setVars['items.gear.' + equipTo + '.shield'] = 'warrior_shield_0';
|
||||
User.setMultiple(setVars);
|
||||
}
|
||||
|
||||
}
|
||||
]);
|
||||
@@ -53,7 +53,7 @@ habitrpg.controller('NotificationCtrl',
|
||||
|
||||
$rootScope.$watch('user.items.pets', function(after, before){
|
||||
if(_.size(after) === _.size(before) ||
|
||||
window.habitrpgShared.helpers.countPets(null, after) < 90) return;
|
||||
$rootScope.Shared.countPets(null, after) < 90) return;
|
||||
User.user.achievements.beastMaster = true;
|
||||
$rootScope.modals.achievements.beastMaster = true;
|
||||
}, true);
|
||||
|
||||
@@ -5,12 +5,15 @@
|
||||
|
||||
habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$http', '$state', '$stateParams', 'Notification', 'Groups',
|
||||
function($scope, $rootScope, $location, User, $http, $state, $stateParams, Notification, Groups) {
|
||||
var user = User.user;
|
||||
|
||||
$rootScope.modals = {};
|
||||
$rootScope.modals.achievements = {};
|
||||
$rootScope.User = User;
|
||||
$rootScope.user = User.user;
|
||||
$rootScope.user = user;
|
||||
$rootScope.settings = User.settings;
|
||||
$rootScope.Items = window.habitrpgShared.items.items;
|
||||
$rootScope.Shared = window.habitrpgShared;
|
||||
$rootScope.Content = window.habitrpgShared.content;
|
||||
|
||||
// Angular UI Router
|
||||
$rootScope.$state = $state;
|
||||
@@ -34,10 +37,10 @@ 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 = window.habitrpgShared.helpers.countPets(null, User.user.items.pets);
|
||||
$rootScope.petCount = $rootScope.Shared.countPets(null, User.user.items.pets);
|
||||
|
||||
$rootScope.$watch('user.items.pets', function(pets){
|
||||
$rootScope.petCount = window.habitrpgShared.helpers.countPets($rootScope.countExists(pets), User.user.items.pets);
|
||||
$rootScope.petCount = $rootScope.Shared.countPets($rootScope.countExists(pets), User.user.items.pets);
|
||||
}, true);
|
||||
|
||||
$scope.safeApply = function(fn) {
|
||||
@@ -51,13 +54,6 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
FIXME this is dangerous, organize helpers.coffee better, so we can group them by which controller needs them,
|
||||
and then simply _.defaults($scope, Helpers.user) kinda thing
|
||||
*/
|
||||
_.defaults($rootScope, window.habitrpgShared.algos);
|
||||
_.defaults($rootScope, window.habitrpgShared.helpers);
|
||||
|
||||
$rootScope.set = User.set;
|
||||
$rootScope.authenticated = User.authenticated;
|
||||
|
||||
@@ -150,8 +146,6 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
|
||||
$rootScope.applyingAction = true;
|
||||
$scope.spell = spell;
|
||||
if (spell.target == 'self') {
|
||||
var tasks = User.user.habits.concat(User.user.dailys).concat(User.user.todos);
|
||||
User.user.tasks = _.object(_.pluck(tasks,'id'), tasks);
|
||||
$scope.castEnd(null, 'self');
|
||||
} else if (spell.target == 'party') {
|
||||
var party = Groups.party();
|
||||
|
||||
@@ -16,13 +16,13 @@ habitrpg.controller('SettingsCtrl',
|
||||
// }
|
||||
|
||||
$scope.showTour = function(){
|
||||
User.set('flags.showTour',true);
|
||||
User.set({'flags.showTour':true});
|
||||
Guide.initTour();
|
||||
$location.path('/tasks');
|
||||
}
|
||||
|
||||
$scope.showBailey = function(){
|
||||
User.set('flags.newStuff',true);
|
||||
User.set({'flags.newStuff':true});
|
||||
}
|
||||
|
||||
$scope.saveDayStart = function(){
|
||||
@@ -31,7 +31,7 @@ habitrpg.controller('SettingsCtrl',
|
||||
dayStart = 0;
|
||||
return alert('Please enter a number between 0 and 24');
|
||||
}
|
||||
User.set('preferences.dayStart', dayStart);
|
||||
User.set({'preferences.dayStart': dayStart});
|
||||
}
|
||||
|
||||
$scope.language = window.env.language;
|
||||
@@ -41,7 +41,7 @@ habitrpg.controller('SettingsCtrl',
|
||||
$rootScope.$on('userSynced', function(){
|
||||
location.reload();
|
||||
});
|
||||
User.set('preferences.language', $scope.language.code);
|
||||
User.set({'preferences.language': $scope.language.code});
|
||||
}
|
||||
|
||||
$scope.reroll = function(){
|
||||
@@ -74,24 +74,18 @@ habitrpg.controller('SettingsCtrl',
|
||||
$rootScope.$watch('modals.restore', function(value){
|
||||
if(value === true){
|
||||
$scope.restoreValues.stats = angular.copy(User.user.stats);
|
||||
// $scope.restoreValues.items = angular.copy(User.user.items);
|
||||
$scope.restoreValues.achievements = {streak: User.user.achievements.streak || 0};
|
||||
}
|
||||
})
|
||||
|
||||
$scope.restore = function(){
|
||||
var stats = $scope.restoreValues.stats,
|
||||
// items = $scope.restoreValues.items,
|
||||
achievements = $scope.restoreValues.achievements;
|
||||
User.setMultiple({
|
||||
User.set({
|
||||
"stats.hp": stats.hp,
|
||||
"stats.exp": stats.exp,
|
||||
"stats.gp": stats.gp,
|
||||
"stats.lvl": stats.lvl,
|
||||
// "items.weapon": items.weapon,
|
||||
// "items.armor": items.armor,
|
||||
// "items.head": items.head,
|
||||
// "items.shield": items.shield,
|
||||
"achievements.streak": achievements.streak
|
||||
});
|
||||
$rootScope.modals.restore = false;
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', 'Algos', 'Helpers', 'Notification', '$http', 'API_URL',
|
||||
function($scope, $rootScope, $location, User, Algos, Helpers, Notification, $http, API_URL) {
|
||||
habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User','Notification', '$http', 'API_URL',
|
||||
function($scope, $rootScope, $location, User, Notification, $http, API_URL) {
|
||||
$scope.obj = User.user; // used for task-lists
|
||||
|
||||
$scope.score = function(task, direction) {
|
||||
if (task.type === "reward" && User.user.stats.gp < task.value){
|
||||
return Notification.text('Not enough Gold!');
|
||||
}
|
||||
Algos.score(User.user, task, direction);
|
||||
User.log({op: "score",data: task, dir: direction});
|
||||
|
||||
User.user.ops.score({params:{id: task.id, direction:direction}})
|
||||
};
|
||||
|
||||
$scope.addTask = function(addTo, listDef) {
|
||||
var task = window.habitrpgShared.helpers.taskDefaults({text: listDef.newTask, type: listDef.type}, User.user.filters);
|
||||
addTo.unshift(task);
|
||||
User.log({op: "addTask", data: task});
|
||||
var newTask = {
|
||||
text: listDef.newTask,
|
||||
type: listDef.type,
|
||||
tags: _.transform(User.user.filters, function(m,v,k){
|
||||
if (v) m[k]=v;
|
||||
})
|
||||
}
|
||||
User.user.ops.addTask({body:newTask});
|
||||
delete listDef.newTask;
|
||||
};
|
||||
|
||||
@@ -40,40 +40,12 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', '
|
||||
|
||||
$scope.removeTask = function(list, $index) {
|
||||
if (!confirm("Are you sure you want to delete this task?")) return;
|
||||
User.log({ op: "delTask", data: list[$index] });
|
||||
User.user.ops.deleteTask({params:{id:list[$index].id}})
|
||||
list.splice($index, 1);
|
||||
};
|
||||
|
||||
$scope.saveTask = function(task) {
|
||||
var setVal = function(k, v) {
|
||||
var op;
|
||||
if (typeof v !== "undefined") {
|
||||
op = { op: "set", data: {} };
|
||||
op.data["tasks." + task.id + "." + k] = v;
|
||||
return log.push(op);
|
||||
}
|
||||
};
|
||||
var log = [];
|
||||
setVal("text", task.text);
|
||||
setVal("notes", task.notes);
|
||||
setVal("priority", task.priority);
|
||||
setVal("tags", task.tags);
|
||||
if (task.type === "habit") {
|
||||
setVal("up", task.up);
|
||||
setVal("down", task.down);
|
||||
} else if (task.type === "daily") {
|
||||
setVal("repeat", task.repeat);
|
||||
// TODO we'll remove this once rewrite's running for a while. This was a patch for derby issues
|
||||
setVal("streak", task.streak);
|
||||
|
||||
} else if (task.type === "todo") {
|
||||
setVal("date", task.date);
|
||||
} else {
|
||||
if (task.type === "reward") {
|
||||
setVal("value", task.value);
|
||||
}
|
||||
}
|
||||
User.log(log);
|
||||
User.user.ops.updateTask({params:{id:task.id},body:task});
|
||||
task._editing = false;
|
||||
};
|
||||
|
||||
@@ -104,16 +76,18 @@ habitrpg.controller("TasksCtrl", ['$scope', '$rootScope', '$location', 'User', '
|
||||
------------------------
|
||||
*/
|
||||
|
||||
$scope.itemStore = window.habitrpgShared.items.updateStore(User.user);
|
||||
$rootScope.$on('userSynced', function(){
|
||||
$scope.itemStore = User.user.fns.updateStore();
|
||||
})
|
||||
|
||||
$scope.buy = function(item) {
|
||||
var hasEnough = window.habitrpgShared.items.buyItem(User.user, item);
|
||||
var hasEnough = User.user.ops.buy({query:{key:item.key}});
|
||||
if (hasEnough) {
|
||||
User.log({op: "buy", key: item.key});
|
||||
Notification.text("Item purchased.");
|
||||
$scope.itemStore = window.habitrpgShared.items.updateStore(User.user);
|
||||
$scope.itemStore = User.user.fns.updateStore();
|
||||
} else {
|
||||
Notification.text("Not enough Gold!");
|
||||
// Notification.text("Not enough Gold!");
|
||||
// handled by userServices interceptor
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,56 +12,20 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$
|
||||
});
|
||||
|
||||
$scope.allocate = function(stat){
|
||||
var setObj = {}
|
||||
setObj['stats.' + stat] = User.user.stats[stat] + 1;
|
||||
setObj['stats.points'] = User.user.stats.points - 1;
|
||||
User.setMultiple(setObj);
|
||||
User.user.ops.allocate({query:{stat:stat}});
|
||||
}
|
||||
|
||||
$scope.rerollClass = function(){
|
||||
if (!confirm("Are you sure you want to re-roll? This will reset your character's class and allocated points (you'll get them all back to re-allocate)"))
|
||||
return;
|
||||
User.setMultiple({
|
||||
'flags.classSelected': false,
|
||||
//'stats.points': this is handled on the server
|
||||
'stats.str': 0,
|
||||
'stats.def': 0,
|
||||
'stats.per': 0,
|
||||
'stats.int': 0
|
||||
})
|
||||
}
|
||||
$scope.rerollSubmit = function(){
|
||||
var klass = $scope.selectedClass;
|
||||
var setVars = {
|
||||
"stats.class": klass,
|
||||
"flags.classSelected": true
|
||||
};
|
||||
$scope.changeClass = function(klass){
|
||||
if (!klass) {
|
||||
if (!confirm("Are you sure you want to re-roll? This will reset your character's class and allocated points (you'll get them all back to re-allocate)"))
|
||||
return;
|
||||
return User.user.ops.changeClass({});
|
||||
}
|
||||
|
||||
// Clear their gear and equip their new class's gear (can still equip old gear from inventory)
|
||||
// If they've rolled this class before, restore their progress
|
||||
_.each(['weapon', 'armor','shield','head'], function(type){
|
||||
var foundKey = false;
|
||||
_.findLast(User.user.items.gear.owned, function(v,k){
|
||||
if (~k.indexOf(type + '_' + klass)) {
|
||||
foundKey = k;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
setVars['items.gear.equipped.' + type] =
|
||||
foundKey ? foundKey : // restore progress from when they last rolled this class
|
||||
(type == 'weapon') ? 'weapon_' + klass + '_0' : // weapon_0 is significant, don't reset to base_0
|
||||
(type == 'shield' && klass == 'rogue') ? 'shield_rogue_0' : // rogues start with an off-hand weapon
|
||||
type + '_base_0'; // naked for the rest!
|
||||
|
||||
// Grant them their new class's gear
|
||||
if (type == 'weapon' || (type == 'shield' && klass == 'rogue'))
|
||||
setVars['items.gear.owned.' + type + '_' + klass + '_0'] = true;
|
||||
});
|
||||
|
||||
User.setMultiple(setVars);
|
||||
User.user.ops.changeClass({query:{class:klass}});
|
||||
$scope.selectedClass = undefined;
|
||||
|
||||
//FIXME run updateStore (we need to access a different scope)
|
||||
User.user.fns.updateStore();
|
||||
}
|
||||
|
||||
$scope.save = function(){
|
||||
@@ -72,11 +36,28 @@ habitrpg.controller("UserCtrl", ['$rootScope', '$scope', '$location', 'User', '$
|
||||
if(!curVal || $scope.editingProfile[key].toString() !== curVal.toString())
|
||||
values['profile.' + key] = value;
|
||||
});
|
||||
User.setMultiple(values);
|
||||
User.set(values);
|
||||
$scope._editing.profile = false;
|
||||
}
|
||||
|
||||
$scope.unlock = User.unlock;
|
||||
/**
|
||||
* For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase
|
||||
* @param path: User.preferences <-> User.purchased maps like User.preferences.skin=abc <-> User.purchased.skin.abc.
|
||||
* Pass in this paramater as "skin.abc". Alternatively, pass as an array ["skin.abc", "skin.xyz"] to unlock sets
|
||||
*/
|
||||
$scope.unlock = function(path){
|
||||
var fullSet = ~path.indexOf(',');
|
||||
var cost = fullSet ? 1.25 : 0.5; // 5G per set, 2G per individual
|
||||
|
||||
if (fullSet) {
|
||||
if (confirm("Purchase for 5 Gems?") !== true) return;
|
||||
if (User.user.balance < cost) return $rootScope.modals.buyGems = true;
|
||||
} else if (!User.user.fns.dotGet('purchased.' + path)) {
|
||||
if (confirm("Purchase for 2 Gems?") !== true) return;
|
||||
if (User.user.balance < cost) return $rootScope.modals.buyGems = true;
|
||||
}
|
||||
User.user.ops.unlock({query:{path:path}})
|
||||
}
|
||||
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
angular.module('guideServices', []).
|
||||
factory('Guide', ['$rootScope', 'User', 'Items', 'Helpers', function($rootScope, User, Items, Helpers) {
|
||||
factory('Guide', ['$rootScope', 'User', function($rootScope, User) {
|
||||
|
||||
/**
|
||||
* Init and show the welcome tour. Note we do it listening to a $rootScope broadcasted 'userLoaded' message,
|
||||
@@ -79,7 +79,7 @@ angular.module('guideServices', []).
|
||||
$('.main-herobox').popover('destroy');
|
||||
var tour = new Tour({
|
||||
onEnd: function(){
|
||||
User.set('flags.showTour', false);
|
||||
User.set({'flags.showTour': false});
|
||||
}
|
||||
});
|
||||
tourSteps.forEach(function(step) {
|
||||
@@ -134,7 +134,7 @@ angular.module('guideServices', []).
|
||||
$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);
|
||||
User.set({'achievements.beastMaster': true});
|
||||
$('#beastmaster-achievement-modal').modal('show'); // FIXME
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Services that persists and retrieves user from localStorage.
|
||||
*/
|
||||
|
||||
angular.module('sharedServices', [] ).
|
||||
factory("Items", ['$rootScope', function($rootScope){
|
||||
return window.habitrpgShared.items;
|
||||
}]).
|
||||
factory("Algos", ['$rootScope', function($rootScope){
|
||||
return window.habitrpgShared.algos;
|
||||
}]).
|
||||
factory("Helpers", ['$rootScope', function($rootScope){
|
||||
return window.habitrpgShared.helpers;
|
||||
}]);
|
||||
@@ -21,14 +21,13 @@ angular.module('userServices', []).
|
||||
user = {}; // this is stored as a reference accessible to all controllers, that way updates propagate
|
||||
|
||||
//first we populate user with schema
|
||||
_.extend(user, $window.habitrpgShared.helpers.newUser());
|
||||
user.apiToken = user._id = ''; // we use id / apitoken to determine if registered
|
||||
$window.habitrpgShared.algos.defineComputed(user);
|
||||
|
||||
//than we try to load localStorage
|
||||
if (localStorage.getItem(STORAGE_USER_ID)) {
|
||||
_.extend(user, JSON.parse(localStorage.getItem(STORAGE_USER_ID)));
|
||||
}
|
||||
user._wrapped = false;
|
||||
|
||||
var syncQueue = function (cb) {
|
||||
if (!authenticated) {
|
||||
@@ -71,6 +70,16 @@ angular.module('userServices', []).
|
||||
|
||||
// Update user
|
||||
_.extend(user, data);
|
||||
if (!user._wrapped){
|
||||
$rootScope.Shared.wrap(user);
|
||||
_.each(user.ops, function(op,k){
|
||||
user.ops[k] = _.partialRight(op, function(err, req){
|
||||
//if (err) return Notification.text(err); // FIXME Circular dependency found: Notification <- User
|
||||
if (err) return alert(err);
|
||||
userServices.log({op:k, params: req.params, query:req.query, body:req.body});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Emit event when user is synced
|
||||
$rootScope.$emit('userSynced');
|
||||
@@ -108,6 +117,9 @@ angular.module('userServices', []).
|
||||
};
|
||||
var userServices = {
|
||||
user: user,
|
||||
set: function(updates) {
|
||||
user.ops.update({body:updates});
|
||||
},
|
||||
online: function (status) {
|
||||
if (status===true) {
|
||||
settings.online = true;
|
||||
@@ -130,7 +142,7 @@ angular.module('userServices', []).
|
||||
// If they don't have timezone, set it
|
||||
var offset = moment().zone(); // eg, 240 - this will be converted on server as -(offset/60)
|
||||
if (user.preferences.timezoneOffset !== offset)
|
||||
userServices.set('preferences.timezoneOffset', offset);
|
||||
userServices.set({'preferences.timezoneOffset': offset});
|
||||
cb && cb();
|
||||
});
|
||||
} else {
|
||||
@@ -161,62 +173,6 @@ angular.module('userServices', []).
|
||||
userServices.log({});
|
||||
},
|
||||
|
||||
/*
|
||||
Very simple path-set. `set('preferences.gender','m')` for example. We'll deprecate this once we have a complete API
|
||||
*/
|
||||
set: function(k, v) {
|
||||
var log = { op: 'set', data: {} };
|
||||
$window.habitrpgShared.helpers.dotSet(k, v, this.user);
|
||||
log.data[k] = v;
|
||||
userServices.log(log);
|
||||
},
|
||||
|
||||
setMultiple: function(obj){
|
||||
var log = { op: 'set', data: {} };
|
||||
_.each(obj, function(v,k){
|
||||
$window.habitrpgShared.helpers.dotSet(k, v, userServices.user);
|
||||
log.data[k] = v;
|
||||
});
|
||||
userServices.log(log);
|
||||
},
|
||||
|
||||
revive: function(){
|
||||
$window.habitrpgShared.algos.revive(user);
|
||||
userServices.log({ op: "revive" });
|
||||
},
|
||||
|
||||
/**
|
||||
* For gem-unlockable preferences, (a) if owned, select preference (b) else, purchase
|
||||
* @param path: User.preferences <-> User.purchased maps like User.preferences.skin=abc <-> User.purchased.skin.abc.
|
||||
* Pass in this paramater as "skin.abc". Alternatively, pass as an array ["skin.abc", "skin.xyz"] to unlock sets
|
||||
*/
|
||||
unlock: function(path){
|
||||
var self = userServices; //this; // why isn't this working?
|
||||
|
||||
if (_.isArray(path)) {
|
||||
if (confirm("Purchase for 5 Gems?") !== true) return;
|
||||
if (user.balance < 1.25) return $rootScope.modals.buyGems = true;
|
||||
path = path.join(',');
|
||||
} else {
|
||||
if ($window.habitrpgShared.helpers.dotGet('purchased.' + path, user)) {
|
||||
var pref = path.split('.')[0],
|
||||
val = path.split('.')[1];
|
||||
return self.set('preferences.' + pref, val);
|
||||
} else {
|
||||
if (confirm("Purchase for 2 Gems?") !== true) return;
|
||||
if (user.balance < 0.5) return $rootScope.modals.buyGems = true;
|
||||
}
|
||||
}
|
||||
|
||||
$http.post(API_URL + '/api/v1/user/unlock?path=' + path)
|
||||
.success(function(data, status, headers, config){
|
||||
self.log({}); // sync new unlocked & preferences
|
||||
}).error(function(data, status, headers, config){
|
||||
alert(status + ': ' + data);
|
||||
//FIXME use method used elsewhere for handling this error, this is temp while developing
|
||||
})
|
||||
},
|
||||
|
||||
save: save,
|
||||
|
||||
settings: settings
|
||||
|
||||
Reference in New Issue
Block a user