Merge branch 'bosses' into develop

This commit is contained in:
Tyler Renelle 2013-12-25 08:25:06 -07:00
commit c7b5b5e601
18 changed files with 1428 additions and 1267 deletions

View file

@ -2,6 +2,12 @@
margin-left: 1.25em;
}*/
.npc_ian {
background: url("../img/sprites/npc_ian.gif") no-repeat;
width: 78px;
height: 135px;
}
.Gems {
display:inline-block;
margin-right:5px;

1154
dist/customizer.css vendored

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -10010,8 +10010,13 @@ var global=self;/**
target: 'task',
notes: 'With a crack, flames burst from your staff, scorching a task. You deal high damage to the task, and gain additional experience (more experience for greens).',
cast: function(user, target) {
var bonus;
target.value += user._statsComputed.int * .0075 * user.fns.crit('per');
return user.stats.exp += (target.value < 0 ? 1 : target.value + 1) * 2.5;
bonus = (target.value < 0 ? 1 : target.value + 1) * 2.5;
user.stats.exp += bonus;
if (user.party.quest.key) {
return user.party.quest.tally.up += bonus;
}
}
},
mpheal: {
@ -10066,7 +10071,10 @@ var global=self;/**
target: 'task',
notes: "You savagely hit a single task with all of your might, beating it into submission. The task's redness decreases.",
cast: function(user, target) {
return target.value += user._statsComputed.str * .01 * user.fns.crit('per');
target.value += user._statsComputed.str * .01 * user.fns.crit('per');
if (user.party.quest.key) {
return user.party.quest.tally.up += Math.ceil(user._statsComputed.str * .2);
}
}
},
defensiveStance: {
@ -10266,9 +10274,9 @@ var global=self;/**
};
_.each(api.spells, function(spellClass) {
return _.each(spellClass, function(spell, k) {
return _.each(spellClass, function(spell, key) {
var _cast;
spell.name = k;
spell.key = key;
_cast = spell.cast;
return spell.cast = function(user, target) {
_cast(user, target);
@ -10329,10 +10337,10 @@ var global=self;/**
}
};
_.each(api.eggs, function(egg, k) {
_.each(api.eggs, function(egg, key) {
return _.defaults(egg, {
value: 3,
name: k,
key: key,
notes: "Find a hatching potion to pour on this egg, and it will hatch into a " + egg.adjective + " " + egg.text + ".",
mountText: egg.text
});
@ -10342,7 +10350,8 @@ var global=self;/**
'Wolf-Veteran': true,
'Wolf-Cerberus': true,
'Dragon-Hydra': true,
'Turkey-Base': true
'Turkey-Base': true,
'BearCub-Polar': true
};
api.hatchingPotions = {
@ -10388,9 +10397,9 @@ var global=self;/**
}
};
_.each(api.hatchingPotions, function(pot, k) {
_.each(api.hatchingPotions, function(pot, key) {
return _.defaults(pot, {
name: k,
key: key,
value: 2,
notes: "Pour this on an egg, and it will hatch as a " + pot.text + " pet."
});
@ -10444,14 +10453,65 @@ var global=self;/**
}
};
_.each(api.food, function(food, k) {
_.each(api.food, function(food, key) {
return _.defaults(food, {
value: 1,
name: k,
key: key,
notes: "Feed this to a pet and it may grow into a sturdy steed."
});
});
api.quests = {
evilsanta: {
text: "Trapper Santa",
notes: "You hear bemoaned roars deep in the icefields. You follow the roars and growls - punctuated by another voice's cackling - to a clearing in the woods where you see a fully-grown polar bear. She's caged and shackled, roaring for life. Dancing atop the the cage is a malicious little imp wearing castaway Christmas costumes. Vanquish Trapper Santa, and save the beast!",
completion: "Trapper Santa squeels in anger, and bounces off into the night. A grateful she-bear, through roars and growls, tries to tell you something. You take her back to the stables, where Matt Boch the whisperer listens to her tale with a gasp of horror. She has a cub! He ran off into the icefields when mama bear was captured. Help her find her baby!",
value: 4,
boss: {
name: "Trapper Santa",
hp: 300,
str: 1
},
drop: {
type: 'mounts',
key: 'BearCub-Polar',
text: "Polar Bear (Mount)",
gp: 20,
exp: 100
}
},
evilsanta2: {
text: "Find The Cub",
notes: "Mama bear's cub had run off into the icefields when she was captured by the trapper. At the edge of the woods, she sniffs the air. You hear twig-snaps and snow crunch through the crystaline sound of the forest. Paw prints! You both start racing to follow the trail. Find all the prints and broken twigs, and retrieve her cub!",
completion: "You've found the cub! Mama and baby bear couldn't be more grateful. As a token, they've decided to keep you company till the end of days.",
value: 4,
previous: 'evilsanta',
collect: {
tracks: {
text: 'Tracks',
count: 20
},
branches: {
text: 'Broken Twigs',
count: 10
}
},
drop: {
type: 'pets',
key: 'BearCub-Polar',
text: "Polar Bear (Pet)",
gp: 20,
exp: 100
}
}
};
_.each(api.quests, function(v, key) {
return _.defaults(v, {
key: key
});
});
repeat = {
m: true,
t: true,
@ -10688,6 +10748,10 @@ var process=require("__browserify_process");(function() {
return max * (bonus / (bonus + halfway));
};
api.monod = function(bonus, rateOfIncrease, max) {
return rateOfIncrease * max * bonus / (rateOfIncrease * bonus + max);
};
/*
Preen history for users with > 7 history entries
This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array
@ -11293,7 +11357,7 @@ var process=require("__browserify_process");(function() {
message: ":pet not found in user.items.pets"
});
}
if (!((_ref2 = user.items.food) != null ? _ref2[food.name] : void 0)) {
if (!((_ref2 = user.items.food) != null ? _ref2[food.key] : void 0)) {
return cb({
code: 404,
message: ":food not found in user.items.food"
@ -11305,7 +11369,7 @@ var process=require("__browserify_process");(function() {
message: "Can't feed this pet."
});
}
if (user.items.mounts[pet] && (userPets[pet] >= 50 || food.name === 'Saddle')) {
if (user.items.mounts[pet] && (userPets[pet] >= 50 || food.key === 'Saddle')) {
return cb({
code: 401,
message: "You already have that mount"
@ -11320,21 +11384,21 @@ var process=require("__browserify_process");(function() {
}
return message = "You have tamed " + egg + ", let's go for a ride!";
};
if (food.name === 'Saddle') {
if (food.key === 'Saddle') {
evolve();
} else {
if (food.target === potion) {
userPets[pet] += 5;
message = "" + egg + " really likes the " + food.name + "!";
message = "" + egg + " really likes the " + food.key + "!";
} else {
userPets[pet] += 2;
message = "" + egg + " eats the " + food.name + " but doesn't seem to enjoy it.";
message = "" + egg + " eats the " + food.key + " but doesn't seem to enjoy it.";
}
if (userPets[pet] >= 50 && !user.items.mounts[pet]) {
evolve();
}
}
user.items.food[food.name]--;
user.items.food[food.key]--;
return cb({
code: 200,
message: message
@ -11343,10 +11407,10 @@ var process=require("__browserify_process");(function() {
purchase: function(req, cb) {
var item, key, type, _ref;
_ref = req.params, type = _ref.type, key = _ref.key;
if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food' && type !== 'special') {
if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food' && type !== 'quests' && type !== 'special') {
return cb({
code: 404,
message: ":type must be in [hatchingPotions,eggs,food,special]"
message: ":type must be in [hatchingPotions,eggs,food,quests,special]"
}, req);
}
item = content[type][key];
@ -11590,19 +11654,21 @@ var process=require("__browserify_process");(function() {
return cb('Not enough Gold');
}
delta = 0;
calculateDelta = function(adjustvalue) {
if (adjustvalue == null) {
adjustvalue = true;
}
calculateDelta = function() {
return _.times(options.times, function() {
var currVal, nextDelta;
var adjustAmt, currVal, nextDelta, _ref1;
currVal = task.value < -47.27 ? -47.27 : task.value > 21.27 ? 21.27 : task.value;
nextDelta = Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1);
if (adjustvalue) {
task.value += nextDelta;
if (task.type !== 'reward') {
adjustAmt = nextDelta;
if (direction === 'up' && task.type !== 'reward' && !(task.type === 'habit' && !task.down)) {
task.value += nextDelta * user._statsComputed.str * .004;
adjustAmt = nextDelta * (1 + user._statsComputed.str * .004);
user.party.quest.progress.up = user.party.quest.progress.up || 0;
if ((_ref1 = task.type) === 'daily' || _ref1 === 'todo') {
user.party.quest.progress.up += adjustAmt;
}
}
task.value += adjustAmt;
}
return delta += nextDelta;
});
@ -11683,7 +11749,7 @@ var process=require("__browserify_process");(function() {
}
break;
case 'reward':
calculateDelta(false);
calculateDelta();
stats.gp -= Math.abs(task.value);
num = parseFloat(task.value).toFixed(2);
if (stats.gp < 0) {
@ -11805,45 +11871,44 @@ var process=require("__browserify_process");(function() {
}), user);
},
randomDrop: function(modifiers) {
var a, acceptableDrops, alpha, chanceMultiplier, delta, drop, max, priority, rarity, reachedDropLimit, streak, _base, _base1, _base2, _base3, _name, _name1, _name2, _ref, _ref1;
delta = modifiers.delta;
_ref = modifiers.task, priority = _ref.priority, streak = _ref.streak;
if (streak == null) {
streak = 0;
var acceptableDrops, bonus, chance, drop, dropK, quest, rarity, task, _base, _base1, _base2, _name, _name1, _name2, _ref, _ref1;
task = modifiers.task;
bonus = Math.abs(task.value) * task.priority + (task.streak || 0) + (user._statsComputed.per * .5);
bonus /= 100;
chance = api.diminishingReturns(bonus, 1, 0.5);
console.log("Drop Equation: Bonus(" + (bonus.toFixed(3)) + "), Modified Chance(" + (chance.toFixed(3)) + ")\n");
quest = content.quests[(_ref = user.party.quest) != null ? _ref.key : void 0];
if ((quest != null ? quest.collect : void 0) && user.fns.predictableRandom(user.stats.gp) < bonus) {
dropK = user.fns.randomVal(quest.collect, {
key: true
});
user.party.quest.progress.collect[dropK]++;
if (typeof user.markModified === "function") {
user.markModified('party.quest.progress');
}
console.log({
progress: user.party.quest.progress
});
}
if ((_base = user.items).lastDrop == null) {
_base.lastDrop = {
date: +moment().subtract('d', 1),
count: 0
};
}
reachedDropLimit = (api.daysSince(user.items.lastDrop.date, user.preferences) === 0) && (user.items.lastDrop.count >= 5);
if (reachedDropLimit) {
if ((api.daysSince(user.items.lastDrop.date, user.preferences) === 0) && (user.items.lastDrop.count >= 5)) {
return;
}
chanceMultiplier = Math.abs(delta);
chanceMultiplier *= priority;
chanceMultiplier += streak;
chanceMultiplier += user._statsComputed.per * .3;
max = 0.75;
a = 0.1;
alpha = a * max * chanceMultiplier / (a * chanceMultiplier + max);
if (((_ref1 = user.flags) != null ? _ref1.dropsEnabled : void 0) && user.fns.predictableRandom(user.stats.exp) < alpha) {
if (((_ref1 = user.flags) != null ? _ref1.dropsEnabled : void 0) && user.fns.predictableRandom(user.stats.exp) < chance) {
rarity = user.fns.predictableRandom(user.stats.gp);
if (rarity > .6) {
drop = user.fns.randomVal(_.omit(content.food, 'Saddle'));
if ((_base1 = user.items.food)[_name = drop.name] == null) {
_base1[_name] = 0;
if ((_base = user.items.food)[_name = drop.key] == null) {
_base[_name] = 0;
}
user.items.food[drop.name] += 1;
user.items.food[drop.key] += 1;
drop.type = 'Food';
drop.dialog = "You've found a " + drop.text + " Food! " + drop.notes;
} else if (rarity > .3) {
drop = user.fns.randomVal(content.eggs);
if ((_base2 = user.items.eggs)[_name1 = drop.name] == null) {
_base2[_name1] = 0;
if ((_base1 = user.items.eggs)[_name1 = drop.key] == null) {
_base1[_name1] = 0;
}
user.items.eggs[drop.name]++;
user.items.eggs[drop.key]++;
drop.type = 'Egg';
drop.dialog = "You've found a " + drop.text + " Egg! " + drop.notes;
} else {
@ -11851,10 +11916,10 @@ var process=require("__browserify_process");(function() {
drop = user.fns.randomVal(_.pick(content.hatchingPotions, (function(v, k) {
return __indexOf.call(acceptableDrops, k) >= 0;
})));
if ((_base3 = user.items.hatchingPotions)[_name2 = drop.name] == null) {
_base3[_name2] = 0;
if ((_base2 = user.items.hatchingPotions)[_name2 = drop.key] == null) {
_base2[_name2] = 0;
}
user.items.hatchingPotions[drop.name]++;
user.items.hatchingPotions[drop.key]++;
drop.type = 'HatchingPotion';
drop.dialog = "You've found a " + drop.text + " Hatching Potion! " + drop.notes;
}
@ -11952,11 +12017,11 @@ var process=require("__browserify_process");(function() {
*/
cron: function(options) {
var daysMissed, expTally, lvl, now, todoTally, _base, _base1;
var daysMissed, expTally, lvl, now, progress, todoTally, _base, _base1, _base2, _progress;
if (options == null) {
options = {};
}
now = [+options.now || +(new Date)][0];
now = +options.now || +(new Date);
daysMissed = api.daysSince(user.lastCron, _.defaults({
now: now
}, user.preferences));
@ -11984,8 +12049,11 @@ var process=require("__browserify_process");(function() {
return;
}
todoTally = 0;
if ((_base = user.party.quest.progress).down == null) {
_base.down = 0;
}
user.todos.concat(user.dailys).forEach(function(task) {
var absVal, completed, id, repeat, scheduleMisses, type;
var absVal, completed, delta, id, repeat, scheduleMisses, type;
if (!task) {
return;
}
@ -12006,7 +12074,7 @@ var process=require("__browserify_process");(function() {
});
}
if (scheduleMisses > 0) {
user.ops.score({
delta = user.ops.score({
params: {
id: task.id,
direction: 'down'
@ -12016,6 +12084,9 @@ var process=require("__browserify_process");(function() {
cron: true
}
});
if (type === 'daily') {
user.party.quest.progress.down += delta;
}
}
}
switch (type) {
@ -12039,7 +12110,7 @@ var process=require("__browserify_process");(function() {
}
}
});
((_base = (user.history != null ? user.history : user.history = {})).todos != null ? (_base = (user.history != null ? user.history : user.history = {})).todos : _base.todos = []).push({
((_base1 = (user.history != null ? user.history : user.history = {})).todos != null ? (_base1 = (user.history != null ? user.history : user.history = {})).todos : _base1.todos = []).push({
date: now,
value: todoTally
});
@ -12049,7 +12120,7 @@ var process=require("__browserify_process");(function() {
lvl++;
expTally += api.tnl(lvl);
}
((_base1 = user.history).exp != null ? (_base1 = user.history).exp : _base1.exp = []).push({
((_base2 = user.history).exp != null ? (_base2 = user.history).exp : _base2.exp = []).push({
date: now,
value: expTally
});
@ -12068,7 +12139,16 @@ var process=require("__browserify_process");(function() {
stealth: 0,
streaks: false
};
return user;
progress = user.party.quest.progress;
_progress = _.cloneDeep(progress);
_.merge(progress, {
down: 0,
up: 0
});
progress.collect = _.transform(progress.collect, (function(m, v, k) {
return m[k] = 0;
}));
return _progress;
},
preenUserHistory: function(minHistLen) {
if (minHistLen == null) {

1154
dist/spritesmith.css vendored

File diff suppressed because it is too large Load diff

BIN
dist/spritesmith.png vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 308 KiB

After

Width:  |  Height:  |  Size: 248 KiB

View file

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

BIN
img/sprites/npc_ian.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View file

@ -6,8 +6,8 @@
"coffeeify": "0.4.0",
"coffee-script": "1.6.2",
"moment": "~2.4.0",
"grunt-spritesmith": "~1.16.0",
"lodash": "~2.4.1"
"lodash": "~2.4.1",
"grunt-spritesmith": "~1.21.0"
},
"devDependencies": {
"mocha": "*",

View file

@ -220,7 +220,9 @@ api.spells =
notes: 'With a crack, flames burst from your staff, scorching a task. You deal high damage to the task, and gain additional experience (more experience for greens).'
cast: (user, target) ->
target.value += user._statsComputed.int * .0075 * user.fns.crit('per')
user.stats.exp += (if target.value < 0 then 1 else target.value+1) * 2.5
bonus = (if target.value < 0 then 1 else target.value+1) * 2.5
user.stats.exp += bonus
user.party.quest.tally.up += bonus if user.party.quest.key
mpheal:
text: 'Ethereal Surge'
@ -263,6 +265,7 @@ api.spells =
notes: "You savagely hit a single task with all of your might, beating it into submission. The task's redness decreases."
cast: (user, target) ->
target.value += user._statsComputed.str * .01 * user.fns.crit('per')
user.party.quest.tally.up += Math.ceil(user._statsComputed.str * .2) if user.party.quest.key
defensiveStance:
text: 'Defensive Stance'
mana: 25
@ -314,6 +317,7 @@ api.spells =
bonus = (if target.value < 0 then 1 else target.value+1) * _crit
user.stats.exp += bonus
user.stats.gp += bonus
# user.party.quest.tally.up += bonus if user.party.quest.key # remove hurting bosses for rogues, seems OP for now
toolsOfTrade:
text: 'Tools of the Trade'
mana: 25
@ -402,8 +406,8 @@ api.spells =
# Intercept all spells to reduce user.stats.mp after casting the spell
_.each api.spells, (spellClass) ->
_.each spellClass, (spell, k) ->
spell.name = k
_.each spellClass, (spell, key) ->
spell.key = key
_cast = spell.cast
spell.cast = (user, target) ->
#return if spell.target and spell.target != (if target.type then 'task' else 'user')
@ -429,11 +433,10 @@ api.eggs =
Dragon: text: 'Dragon', adjective: 'mighty'
Cactus: text: 'Cactus', adjective: 'prickly'
BearCub: text: 'Bear Cub', mountText: 'Bear', adjective: 'cuddly'
#{text: 'Polar Bear Cub', name: 'PolarBearCub', value: 3}
_.each api.eggs, (egg,k) ->
_.each api.eggs, (egg,key) ->
_.defaults egg,
value: 3
name: k
key: key
notes: "Find a hatching potion to pour on this egg, and it will hatch into a #{egg.adjective} #{egg.text}."
mountText: egg.text
@ -442,6 +445,7 @@ api.specialPets =
'Wolf-Cerberus': true
'Dragon-Hydra': true
'Turkey-Base': true
'BearCub-Polar': true
api.hatchingPotions =
Base: value: 2, text: 'Base'
@ -454,8 +458,8 @@ api.hatchingPotions =
CottonCandyPink: value: 4, text: 'Cotton Candy Pink'
CottonCandyBlue: value: 4, text: 'Cotton Candy Blue'
Golden: value: 5, text: 'Golden'
_.each api.hatchingPotions, (pot,k) ->
_.defaults pot, {name: k, value: 2, notes: "Pour this on an egg, and it will hatch as a #{pot.text} pet."}
_.each api.hatchingPotions, (pot,key) ->
_.defaults pot, {key, value: 2, notes: "Pour this on an egg, and it will hatch as a #{pot.text} pet."}
api.food =
Meat: text: 'Meat', target: 'Base'
@ -473,8 +477,42 @@ api.food =
#Watermelon: text: 'Watermelon', target: 'Golden'
#SeaWeed: text: 'SeaWeed', target: 'Golden'
Saddle: text: 'Saddle', value: 5, notes: 'Instantly raises your pet into a mount.'
_.each api.food, (food,k) ->
_.defaults food, {value: 1, name: k, notes: "Feed this to a pet and it may grow into a sturdy steed."}
_.each api.food, (food,key) ->
_.defaults food, {value: 1, key, notes: "Feed this to a pet and it may grow into a sturdy steed."}
api.quests =
evilsanta:
text: "Trapper Santa" # title of the quest (eg, Deep into Vice's Layer)
notes: "You hear bemoaned roars deep in the icefields. You follow the roars and growls - punctuated by another voice's cackling - to a clearing in the woods where you see a fully-grown polar bear. She's caged and shackled, roaring for life. Dancing atop the the cage is a malicious little imp wearing castaway Christmas costumes. Vanquish Trapper Santa, and save the beast!"
completion: "Trapper Santa squeels in anger, and bounces off into the night. A grateful she-bear, through roars and growls, tries to tell you something. You take her back to the stables, where Matt Boch the whisperer listens to her tale with a gasp of horror. She has a cub! He ran off into the icefields when mama bear was captured. Help her find her baby!"
value: 4 # Gem cost to buy, GP sell-back
#mechanic: enum['perfectDailies', ...]
boss:
name: "Trapper Santa" # name of the boss himself (eg, Vice)
hp: 300
str: 1 # Multiplier of users' missed dailies
drop:
type: 'mounts'
key: 'BearCub-Polar'
text: "Polar Bear (Mount)"
gp: 20
exp: 100 # Exp bonus from defeating the boss
evilsanta2:
text: "Find The Cub"
notes: "Mama bear's cub had run off into the icefields when she was captured by the trapper. At the edge of the woods, she sniffs the air. You hear twig-snaps and snow crunch through the crystaline sound of the forest. Paw prints! You both start racing to follow the trail. Find all the prints and broken twigs, and retrieve her cub!"
completion: "You've found the cub! Mama and baby bear couldn't be more grateful. As a token, they've decided to keep you company till the end of days."
value: 4
previous: 'evilsanta'
collect:
tracks: text: 'Tracks', count: 20
branches: text: 'Broken Twigs', count: 10
drop: type: 'pets', key: 'BearCub-Polar', text: "Polar Bear (Pet)", gp: 20, exp: 100
_.each api.quests, (v,key) ->
_.defaults v, {key}
repeat = {m:true,t:true,w:true,th:true,f:true,s:true,su:true}
api.userDefaults =

View file

@ -74,6 +74,8 @@ api.tnl = (lvl) ->
api.diminishingReturns = (bonus, max, halfway=bonus/2) ->
max*(bonus/(bonus+halfway))
api.monod = (bonus, rateOfIncrease, max) ->
rateOfIncrease*max*bonus/(rateOfIncrease*bonus+max)
###
Preen history for users with > 7 history entries
@ -481,9 +483,9 @@ api.wrap = (user) ->
userPets = user.items.pets
return cb({code:404, message:":pet not found in user.items.pets"}) unless userPets[pet]
return cb({code:404, message:":food not found in user.items.food"}) unless user.items.food?[food.name]
return cb({code:404, message:":food not found in user.items.food"}) unless user.items.food?[food.key]
return cb({code:401, message:"Can't feed this pet."}) if content.specialPets[pet]
return cb({code:401, message:"You already have that mount"}) if user.items.mounts[pet] and (userPets[pet] >= 50 or food.name is 'Saddle')
return cb({code:401, message:"You already have that mount"}) if user.items.mounts[pet] and (userPets[pet] >= 50 or food.key is 'Saddle')
message = ''
evolve = ->
@ -492,24 +494,24 @@ api.wrap = (user) ->
user.items.currentPet = "" if pet is user.items.currentPet
message = "You have tamed #{egg}, let's go for a ride!"
if food.name is 'Saddle'
if food.key is 'Saddle'
evolve()
else
if food.target is potion
userPets[pet] += 5
message = "#{egg} really likes the #{food.name}!"
message = "#{egg} really likes the #{food.key}!"
else
userPets[pet] += 2
message = "#{egg} eats the #{food.name} but doesn't seem to enjoy it."
message = "#{egg} eats the #{food.key} but doesn't seem to enjoy it."
if userPets[pet] >= 50 and !user.items.mounts[pet]
evolve()
user.items.food[food.name]--
user.items.food[food.key]--
cb {code:200, message}, req
# buy is for gear, purchase is for gem-purchaseables (i know, I know...)
purchase: (req, cb) ->
{type,key} = req.params
return cb({code:404,message:":type must be in [hatchingPotions,eggs,food,special]"},req) unless type in ['eggs','hatchingPotions', 'food', 'special']
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
user.items[type][key] = 0 unless user.items[type][key]
@ -667,7 +669,7 @@ api.wrap = (user) ->
delta = 0
calculateDelta = (adjustvalue=true) ->
calculateDelta = ->
# If multiple days have passed, multiply times days missed
_.times options.times, ->
# Each iteration calculate the nextDelta, which is then accumulated in the total delta.
@ -680,13 +682,17 @@ api.wrap = (user) ->
else if task.value > 21.27 then 21.27
else task.value
nextDelta = Math.pow(0.9747, currVal) * (if direction is 'down' then -1 else 1)
if adjustvalue
task.value += nextDelta
unless task.type is 'reward'
adjustAmt = nextDelta
# ===== STRENGTH =====
# (Only for up-scoring, ignore up-onlies and rewards)
# Note, we create a new val (adjustAmt) to add to task.value, since delta will be used in Exp & GP calculations - we don't want STR to bonus that
# TODO STR Improves the amount by which Dailies and +/- Habits decrease in threat when scored, by .25% per point.
if direction is 'up' and task.type != 'reward' and !(task.type is 'habit' and !task.down)
# TODO STR Improves the amount by which Dailies and +/- Habits decrease in threat when scored, by .25% per point.
task.value += nextDelta * user._statsComputed.str * .004
adjustAmt = nextDelta * (1 + user._statsComputed.str * .004)
user.party.quest.progress.up = user.party.quest.progress.up || 0;
user.party.quest.progress.up += adjustAmt if task.type in ['daily','todo']
task.value += adjustAmt
delta += nextDelta
addPoints = ->
@ -765,7 +771,7 @@ api.wrap = (user) ->
when 'reward'
# Don't adjust values for rewards
calculateDelta(false)
calculateDelta()
# purchase item
stats.gp -= Math.abs(task.value)
num = parseFloat(task.value).toFixed(2)
@ -856,32 +862,28 @@ api.wrap = (user) ->
# ----------------------------------------------------------------------
randomDrop: (modifiers) ->
{delta} = modifiers
{priority, streak} = modifiers.task
streak ?= 0
# limit drops to 2 / day
user.items.lastDrop ?=
date: +moment().subtract('d', 1) # trick - set it to yesterday on first run, that way they can get drops today
count: 0
{task} = modifiers
reachedDropLimit = (api.daysSince(user.items.lastDrop.date, user.preferences) is 0) and (user.items.lastDrop.count >= 5)
return if reachedDropLimit
# % chance of getting a drop
bonus =
Math.abs(task.value) * # + Task Redness
task.priority + # * Task Priority
(task.streak or 0) + # + Streak bonus
(user._statsComputed.per * .5) # + Perception
bonus /= 100 # /100 (as a percent)
chance = api.diminishingReturns(bonus, 1, 0.5) # see HabitRPG/habitrpg#1922 for details
console.log "Drop Equation: Bonus(#{bonus.toFixed(3)}), Modified Chance(#{chance.toFixed(3)})\n"
# % chance of getting a pet or meat
chanceMultiplier = Math.abs(delta)
chanceMultiplier *= priority # multiply chance by reddness
chanceMultiplier += streak # streak bonus
chanceMultiplier += user._statsComputed.per*.3
quest = content.quests[user.party.quest?.key]
if quest?.collect and user.fns.predictableRandom(user.stats.gp) < bonus # NOTE: < bonus, higher chance than drops
dropK = user.fns.randomVal quest.collect, {key:true}
user.party.quest.progress.collect[dropK]++
user.markModified? 'party.quest.progress'
console.log {progress:user.party.quest.progress}
# Temporary solution to lower the maximum drop chance to 75 percent. More thorough
# overhaul of drop changes is needed. See HabitRPG/habitrpg#1922 for details.
# Old drop chance:
# if user.flags?.dropsEnabled and Math.random() < (.05 * chanceMultiplier)
max = 0.75 # Max probability of drop
a = 0.1 # rate of increase
alpha = a*max*chanceMultiplier/(a*chanceMultiplier+max) # current probability of drop
return if (api.daysSince(user.items.lastDrop.date, user.preferences) is 0) and (user.items.lastDrop.count >= 5)
if user.flags?.dropsEnabled and user.fns.predictableRandom(user.stats.exp) < chance
if user.flags?.dropsEnabled and user.fns.predictableRandom(user.stats.exp) < alpha
# current breakdown - 1% (adjustable) chance on drop
# If they got a drop: 50% chance of egg, 50% Hatching Potion. If hatchingPotion, broken down further even further
rarity = user.fns.predictableRandom(user.stats.gp)
@ -889,16 +891,16 @@ api.wrap = (user) ->
# Food: 40% chance
if rarity > .6
drop = user.fns.randomVal _.omit(content.food, 'Saddle')
user.items.food[drop.name] ?= 0
user.items.food[drop.name]+= 1
user.items.food[drop.key] ?= 0
user.items.food[drop.key]+= 1
drop.type = 'Food'
drop.dialog = "You've found a #{drop.text} Food! #{drop.notes}"
# Eggs: 30% chance
else if rarity > .3
drop = user.fns.randomVal content.eggs
user.items.eggs[drop.name] ?= 0
user.items.eggs[drop.name]++
user.items.eggs[drop.key] ?= 0
user.items.eggs[drop.key]++
drop.type = 'Egg'
drop.dialog = "You've found a #{drop.text} Egg! #{drop.notes}"
@ -918,8 +920,8 @@ api.wrap = (user) ->
#drop = helpers.randomVal hatchingPotions
drop = user.fns.randomVal _.pick(content.hatchingPotions, ((v,k) -> k in acceptableDrops))
user.items.hatchingPotions[drop.name] ?= 0
user.items.hatchingPotions[drop.name]++
user.items.hatchingPotions[drop.key] ?= 0
user.items.hatchingPotions[drop.key]++
drop.type = 'HatchingPotion'
drop.dialog = "You've found a #{drop.text} Hatching Potion! #{drop.notes}"
@ -1000,7 +1002,7 @@ api.wrap = (user) ->
{user}
###
cron: (options={}) ->
[now] = [+options.now || +new Date]
now = +options.now || +new Date
# They went to a different timezone
# FIXME:
@ -1031,8 +1033,9 @@ api.wrap = (user) ->
user.stats.buffs = {str:0,int:0,per:0,con:0,stealth:0,streaks:false}
return
# Tally each task
# Tally each task
todoTally = 0
user.party.quest.progress.down ?= 0
user.todos.concat(user.dailys).forEach (task) ->
return unless task
@ -1049,7 +1052,8 @@ api.wrap = (user) ->
thatDay = moment(now).subtract('days', n + 1)
scheduleMisses++ if api.shouldDo(thatDay, repeat, user.preferences)
if scheduleMisses > 0
user.ops.score({params:{id:task.id, direction:'down'}, query:{times:scheduleMisses, cron:true}})
delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:scheduleMisses, cron:true}});
user.party.quest.progress.down += delta if type is 'daily'
switch type
when 'daily'
@ -1081,7 +1085,12 @@ api.wrap = (user) ->
user.markModified? 'history'
user.markModified? 'dailys' # covers dailys.*.history
user.stats.buffs = {str:0,int:0,per:0,con:0,stealth:0,streaks:false}
user
# After all is said and done, progress up user's effect on quest, return those values & reset the user's
progress = user.party.quest.progress; _progress = _.cloneDeep progress
_.merge progress, {down:0,up:0}
progress.collect = _.transform progress.collect, ((m,v,k)->m[k]=0)
_progress
# Registered users with some history
preenUserHistory: (minHistLen = 7) ->

View file

@ -12,6 +12,7 @@ _ = require 'lodash'
id = shared.uuid()
user =
stats: {class: 'warrior', buffs: {per:0,int:0,con:0,str:0}}
party: quest: tally: {up:0,down:0}
items:
eggs: {}
hatchingPotions: {}
@ -41,18 +42,21 @@ console.log "================================================\n\n"
clearUser = (lvl=1) ->
_.merge user.stats, {exp:0, gp:0, hp:50, lvl:lvl, str:lvl, con:lvl, per:lvl, int:lvl, mp: 100}
_.merge s.buffs, {str:0,con:0,int:0,per:0}
_.merge user.party.quest.tally, {up:0,down:0}
user.items.lastDrop = {count:0}
_.each [1,50,99], (lvl) ->
console.log "[LEVEL #{lvl}] (#{lvl} points in every attr)\n\n"
_.each {red:-5,yellow:0,green:5}, (taskVal, color) ->
console.log "[task.value = #{taskVal} (#{color})]"
console.log "direction\texpΔ\t\thpΔ\tgpΔ\ttask.valΔ\ttask.valΔ bonus"
console.log "direction\texpΔ\t\thpΔ\tgpΔ\ttask.valΔ\ttask.valΔ bonus\t\tboss-hit"
_.each ['up','down'], (direction) ->
clearUser(lvl)
b4 = {hp:s.hp, taskVal}
task.value = taskVal
task.type = 'daily' if direction is 'up'
delta = user.ops.score params:{id, direction}
console.log "#{if direction is 'up' then '' else ''}\t\t#{s.exp}/#{shared.tnl(s.lvl)}\t\t#{(b4.hp-s.hp).toFixed(1)}\t#{s.gp.toFixed(1)}\t#{delta.toFixed(1)}\t\t#{(task.value-b4.taskVal-delta).toFixed(1)}"
console.log "#{if direction is 'up' then '' else ''}\t\t#{s.exp}/#{shared.tnl(s.lvl)}\t\t#{(b4.hp-s.hp).toFixed(1)}\t#{s.gp.toFixed(1)}\t#{delta.toFixed(1)}\t\t#{(task.value-b4.taskVal-delta).toFixed(1)}\t\t\t#{user.party.quest.tally.up.toFixed(1)}"
str = '- [Wizard]'