feat(premium): add premium features
This commit is contained in:
Vendored
+76
-12
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user