feat(premium): add premium features

This commit is contained in:
Tyler Renelle
2014-03-08 21:12:55 -07:00
parent 619c8f6f17
commit a38c8761a2
2 changed files with 120 additions and 16 deletions
+76 -12
View File
@@ -13699,6 +13699,11 @@ api.dotGet = function(obj, path) {
})(this)), obj);
};
api.planGemLimits = {
convRate: 20,
convCap: 25
};
/*
------------------------------------------------------
@@ -14734,8 +14739,36 @@ api.wrap = function(user, main) {
return typeof cb === "function" ? cb(null, _.pick(user, $w('items stats'))) : void 0;
},
purchase: function(req, cb, ga) {
var item, key, type, _ref;
var convCap, convRate, item, key, type, _ref, _ref1, _ref2, _ref3;
_ref = req.params, type = _ref.type, key = _ref.key;
if (type === 'gems' && key === 'gem') {
_ref1 = api.planGemLimits, convRate = _ref1.convRate, convCap = _ref1.convCap;
if (!((_ref2 = user.purchased) != null ? (_ref3 = _ref2.plan) != null ? _ref3.planId : void 0 : void 0)) {
return typeof cb === "function" ? cb({
code: 401,
message: "Must subscribe to purchase gems with GP"
}, req) : void 0;
}
if (!(user.stats.gp >= convRate)) {
return typeof cb === "function" ? cb({
code: 401,
message: "Not enough Gold"
}) : void 0;
}
if (user.purchased.plan.gemsBought >= convCap) {
return typeof cb === "function" ? cb({
code: 401,
message: "You've reached the Gold=>Gem conversion cap (" + convCap + ") for this month. We have this to prevent abuse / farming, please wait until the beginning of next month."
}) : void 0;
}
user.balance += .25;
user.purchased.plan.gemsBought++;
user.stats.gp -= convRate;
return typeof cb === "function" ? cb({
code: 200,
message: "+1 Gems"
}, _.pick(user, $w('stats balance'))) : void 0;
}
if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food' && type !== 'quests' && type !== 'special') {
return typeof cb === "function" ? cb({
code: 404,
@@ -15065,6 +15098,28 @@ api.wrap = function(user, main) {
}
return typeof cb === "function" ? cb(null, 'items.special') : void 0;
},
openMysteryItem: function(req, cb, ga) {
var item, _ref, _ref1;
item = (_ref = user.purchased.plan) != null ? (_ref1 = _ref.mysteryItems) != null ? _ref1.shift() : void 0 : void 0;
if (!item) {
return typeof cb === "function" ? cb({
code: 400,
message: "Empty"
}) : void 0;
}
item = content.gear.flat[item];
user.items.gear.owned[item.key] = true;
if (typeof user.markModified === "function") {
user.markModified('purchased.plan.mysteryItems');
}
if (typeof window !== 'undefined') {
(user._tmp != null ? user._tmp : user._tmp = {}).drop = {
type: 'gear',
dialog: "" + (item.text(req.language)) + " inside!"
};
}
return typeof cb === "function" ? cb(null, user.items.gear.owned) : void 0;
},
score: function(req, cb) {
var addPoints, calculateDelta, calculateReverseDelta, changeTaskValue, delta, direction, id, mpDelta, multiplier, num, options, stats, subtractPoints, task, th, _ref;
_ref = req.params, id = _ref.id, direction = _ref.direction;
@@ -15366,7 +15421,7 @@ api.wrap = function(user, main) {
return api.dotGet(user, path);
},
randomDrop: function(modifiers, req) {
var acceptableDrops, chance, drop, dropK, quest, rarity, task, _base, _base1, _base2, _name, _name1, _name2, _ref, _ref1;
var acceptableDrops, chance, drop, dropK, dropMultiplier, quest, rarity, task, _base, _base1, _base2, _name, _name1, _name2, _ref, _ref1, _ref2, _ref3;
task = modifiers.task;
chance = _.min([Math.abs(task.value - 21.27), 37.5]) / 150 + .02;
chance *= task.priority * (1 + (task.streak / 100 || 0)) * (1 + (user._statsComputed.per / 100)) * (1 + (user.contributor.level / 40 || 0)) * (1 + (user.achievements.rebirths / 20 || 0)) * (1 + (user.achievements.streak / 200 || 0)) * (user._tmp.crit || 1) * (1 + .5 * (_.reduce(task.checklist, (function(m, i) {
@@ -15383,10 +15438,11 @@ api.wrap = function(user, main) {
user.markModified('party.quest.progress');
}
}
if ((api.daysSince(user.items.lastDrop.date, user.preferences) === 0) && (user.items.lastDrop.count >= 5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level || 0))) {
dropMultiplier = ((_ref1 = user.purchased) != null ? (_ref2 = _ref1.plan) != null ? _ref2.customerId : void 0 : void 0) ? 2 : 1;
if ((api.daysSince(user.items.lastDrop.date, user.preferences) === 0) && (user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level || 0)))) {
return;
}
if (((_ref1 = user.flags) != null ? _ref1.dropsEnabled : void 0) && user.fns.predictableRandom(user.stats.exp) < chance) {
if (((_ref3 = user.flags) != null ? _ref3.dropsEnabled : void 0) && user.fns.predictableRandom(user.stats.exp) < chance) {
rarity = user.fns.predictableRandom(user.stats.gp);
if (rarity > .6) {
drop = user.fns.randomVal(_.where(content.food, {
@@ -15579,7 +15635,7 @@ api.wrap = function(user, main) {
{user}
*/
cron: function(options) {
var clearBuffs, daysMissed, expTally, lvl, lvlDiv2, now, perfect, plan, progress, todoTally, _base, _base1, _base2, _base3, _progress, _ref;
var clearBuffs, daysMissed, expTally, lvl, lvlDiv2, now, perfect, plan, progress, todoTally, _base, _base1, _base2, _base3, _progress, _ref, _ref1, _ref2, _ref3, _ref4;
if (options == null) {
options = {};
}
@@ -15595,6 +15651,12 @@ api.wrap = function(user, main) {
if (user.items.lastDrop.count > 0) {
user.items.lastDrop.count = 0;
}
if ((_ref = user.purchased) != null ? (_ref1 = _ref.plan) != null ? _ref1.customerId : void 0 : void 0) {
if (moment(user.purchased.plan.dateUpdated).format('MMYYYY') !== moment().format('MMYYYY')) {
user.purchased.plan.gemsBought = 0;
user.purchased.plan.dateUpdated = new Date();
}
}
perfect = true;
clearBuffs = {
str: 0,
@@ -15693,12 +15755,14 @@ api.wrap = function(user, main) {
date: now,
value: expTally
});
user.fns.preenUserHistory();
if (typeof user.markModified === "function") {
user.markModified('history');
}
if (typeof user.markModified === "function") {
user.markModified('dailys');
if (!((_ref2 = user.purchased) != null ? (_ref3 = _ref2.plan) != null ? _ref3.customerId : void 0 : void 0)) {
user.fns.preenUserHistory();
if (typeof user.markModified === "function") {
user.markModified('history');
}
if (typeof user.markModified === "function") {
user.markModified('dailys');
}
}
user.stats.buffs = perfect ? ((_base3 = user.achievements).perfect != null ? _base3.perfect : _base3.perfect = 0, user.achievements.perfect++, user.stats.lvl < 100 ? lvlDiv2 = Math.ceil(user.stats.lvl / 2) : lvlDiv2 = 50, {
str: lvlDiv2,
@@ -15712,7 +15776,7 @@ api.wrap = function(user, main) {
if (user.stats.mp > user._statsComputed.maxMP) {
user.stats.mp = user._statsComputed.maxMP;
}
plan = (_ref = user.purchased) != null ? _ref.plan : void 0;
plan = (_ref4 = user.purchased) != null ? _ref4.plan : void 0;
if (plan && plan.customerId && plan.dateTerminated && moment(plan.dateTerminated).isBefore(+(new Date))) {
_.merge(user.purchased.plan, {
planId: null,
+44 -4
View File
@@ -8,6 +8,7 @@ api.i18n = i18n
# little helper for large arrays of strings. %w"this that another" equivalent from Rails, I really miss that function
$w = api.$w = (s)->s.split(' ')
api.dotSet = (obj,path,val)->
arr = path.split('.')
_.reduce arr, (curr, next, index) =>
@@ -18,6 +19,10 @@ api.dotSet = (obj,path,val)->
api.dotGet = (obj,path)->
_.reduce path.split('.'), ((curr, next) => curr?[next]), obj
api.planGemLimits =
convRate: 20 #how much does a gem cost?
convCap: 25 #how many gems can be converted / month?
###
------------------------------------------------------
Time / Day
@@ -664,6 +669,17 @@ api.wrap = (user, main=true) ->
# buy is for gear, purchase is for gem-purchaseables (i know, I know...)
purchase: (req, cb, ga) ->
{type,key} = req.params
if type is 'gems' and key is 'gem'
{convRate,convCap} = api.planGemLimits
return cb?({code:401,message:"Must subscribe to purchase gems with GP"},req) unless user.purchased?.plan?.planId
return cb?({code:401,message:"Not enough Gold"}) unless user.stats.gp >= convRate
return cb?({code:401,message:"You've reached the Gold=>Gem conversion cap (#{convCap}) for this month. We have this to prevent abuse / farming, please wait until the beginning of next month."}) if user.purchased.plan.gemsBought >= convCap
user.balance += .25
user.purchased.plan.gemsBought++
user.stats.gp -= convRate
return cb? {code:200,message:"+1 Gems"}, _.pick(user,$w 'stats balance')
return cb?({code:404,message:":type must be in [hatchingPotions,eggs,food,quests,special]"},req) unless type in ['eggs','hatchingPotions','food','quests','special']
item = content[type][key]
return cb?({code:404,message:":key not found for Content.#{type}"},req) unless item
@@ -853,6 +869,17 @@ api.wrap = (user, main=true) ->
user.markModified? 'items.special.valentineReceived'
cb? null, 'items.special'
openMysteryItem: (req,cb,ga) ->
item = user.purchased.plan?.mysteryItems?.shift()
return cb?(code:400,message:"Empty") unless item
item = content.gear.flat[item]
user.items.gear.owned[item.key] = true
user.markModified? 'purchased.plan.mysteryItems'
# Could show {code:200} message, but it's yellow with no icon. This is round-about, but prettier. FIXME
(user._tmp?={}).drop = {type: 'gear', dialog: "#{item.text(req.language)} inside!"} if typeof window != 'undefined'
#cb? {code:200, message:"#{item.text} inside!"}, user.items.gear.owned
cb? null, user.items.gear.owned
# ------
# Score
# ------
@@ -1151,7 +1178,8 @@ api.wrap = (user, main=true) ->
user.markModified? 'party.quest.progress'
#console.log {progress:user.party.quest.progress}
return if (api.daysSince(user.items.lastDrop.date, user.preferences) is 0) and (user.items.lastDrop.count >= 5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level or 0))
dropMultiplier = if user.purchased?.plan?.customerId then 2 else 1
return if (api.daysSince(user.items.lastDrop.date, user.preferences) is 0) and (user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level or 0)))
if user.flags?.dropsEnabled and user.fns.predictableRandom(user.stats.exp) < chance
# current breakdown - 1% (adjustable) chance on drop
@@ -1326,6 +1354,13 @@ api.wrap = (user, main=true) ->
if user.items.lastDrop.count > 0
user.items.lastDrop.count = 0
# Reset caps for subscribers
if user.purchased?.plan?.customerId
if moment(user.purchased.plan.dateUpdated).format('MMYYYY') != moment().format('MMYYYY')
#+moment().format('D') >= +moment(user.purchased.plan.dateCreated).format('D') and
user.purchased.plan.gemsBought = 0
user.purchased.plan.dateUpdated = new Date()
# "Perfect Day" achievement for perfect-days
perfect = true
clearBuffs = {str:0,int:0,per:0,con:0,stealth:0,streaks:false}
@@ -1388,9 +1423,14 @@ api.wrap = (user, main=true) ->
lvl++
expTally += api.tnl(lvl)
(user.history.exp ?= []).push { date: now, value: expTally }
user.fns.preenUserHistory()
user.markModified? 'history'
user.markModified? 'dailys' # covers dailys.*.history
# premium subscribers can keep their full history.
# TODO figure out something performance-wise
unless user.purchased?.plan?.customerId
user.fns.preenUserHistory()
user.markModified? 'history'
user.markModified? 'dailys' # covers dailys.*.history
user.stats.buffs =
if perfect
user.achievements.perfect ?= 0