Merge branch 'develop' of github.com:HabitRPG/habitrpg into api-v3
@@ -1,12 +1,12 @@
|
||||
.2014_Fall_HealerPROMO2 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -460px -1051px;
|
||||
background-position: -820px -724px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.2014_Fall_Mage_PROMO9 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -1265px -670px;
|
||||
background-position: -1265px -761px;
|
||||
width: 120px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
.promo_android {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -943px -101px;
|
||||
background-position: -943px -277px;
|
||||
width: 175px;
|
||||
height: 175px;
|
||||
}
|
||||
@@ -34,6 +34,12 @@
|
||||
width: 141px;
|
||||
height: 294px;
|
||||
}
|
||||
.promo_backgrounds_armoire_201603 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -306px -220px;
|
||||
width: 141px;
|
||||
height: 294px;
|
||||
}
|
||||
.promo_backtoschool {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: 0px -1051px;
|
||||
@@ -60,7 +66,7 @@
|
||||
}
|
||||
.promo_dilatoryDistress {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -306px -220px;
|
||||
background-position: -642px -1051px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -84,7 +90,7 @@
|
||||
}
|
||||
.promo_enchanted_armoire_201509 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -306px -402px;
|
||||
background-position: -369px -1051px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -96,13 +102,13 @@
|
||||
}
|
||||
.promo_enchanted_armoire_201601 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -814px -272px;
|
||||
background-position: -915px -1051px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.promo_habitica {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -943px -277px;
|
||||
background-position: -943px -101px;
|
||||
width: 175px;
|
||||
height: 175px;
|
||||
}
|
||||
@@ -132,7 +138,7 @@
|
||||
}
|
||||
.promo_mystery_201405 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -551px -1051px;
|
||||
background-position: -1371px -943px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -156,7 +162,7 @@
|
||||
}
|
||||
.promo_mystery_201409 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -306px -311px;
|
||||
background-position: -460px -1051px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -168,7 +174,7 @@
|
||||
}
|
||||
.promo_mystery_201411 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -820px -724px;
|
||||
background-position: -824px -1051px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -186,13 +192,13 @@
|
||||
}
|
||||
.promo_mystery_201502 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -1371px -943px;
|
||||
background-position: -814px -181px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.promo_mystery_201503 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -814px -181px;
|
||||
background-position: -814px -272px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -204,7 +210,7 @@
|
||||
}
|
||||
.promo_mystery_201505 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -733px -1051px;
|
||||
background-position: -808px -621px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -222,25 +228,25 @@
|
||||
}
|
||||
.promo_mystery_201508 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -1359px -1034px;
|
||||
background-position: -1265px -1034px;
|
||||
width: 93px;
|
||||
height: 90px;
|
||||
}
|
||||
.promo_mystery_201509 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -808px -621px;
|
||||
background-position: -551px -1051px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
.promo_mystery_201510 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -1265px -1034px;
|
||||
background-position: -1359px -1034px;
|
||||
width: 93px;
|
||||
height: 90px;
|
||||
}
|
||||
.promo_mystery_201511 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -369px -1051px;
|
||||
background-position: -733px -1051px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -252,13 +258,13 @@
|
||||
}
|
||||
.promo_mystery_201601 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -1265px -761px;
|
||||
background-position: -1265px -670px;
|
||||
width: 120px;
|
||||
height: 90px;
|
||||
}
|
||||
.promo_mystery_201602 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -642px -1051px;
|
||||
background-position: -1006px -1051px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
@@ -336,13 +342,13 @@
|
||||
}
|
||||
.promo_springclasses2014 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -943px -633px;
|
||||
background-position: -943px -542px;
|
||||
width: 288px;
|
||||
height: 90px;
|
||||
}
|
||||
.promo_springclasses2015 {
|
||||
background-image: url(spritesmith-largeSprites-0.png);
|
||||
background-position: -943px -542px;
|
||||
background-position: -943px -633px;
|
||||
width: 288px;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
BIN
common/dist/sprites/spritesmith-largeSprites-0.png
vendored
|
Before Width: | Height: | Size: 223 KiB After Width: | Height: | Size: 233 KiB |
1160
common/dist/sprites/spritesmith-main-0.css
vendored
BIN
common/dist/sprites/spritesmith-main-0.png
vendored
|
Before Width: | Height: | Size: 286 KiB After Width: | Height: | Size: 291 KiB |
6856
common/dist/sprites/spritesmith-main-1.css
vendored
BIN
common/dist/sprites/spritesmith-main-1.png
vendored
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
738
common/dist/sprites/spritesmith-main-10.css
vendored
BIN
common/dist/sprites/spritesmith-main-10.png
vendored
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 146 KiB |
2118
common/dist/sprites/spritesmith-main-11.css
vendored
BIN
common/dist/sprites/spritesmith-main-11.png
vendored
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 144 KiB |
6596
common/dist/sprites/spritesmith-main-2.css
vendored
BIN
common/dist/sprites/spritesmith-main-2.png
vendored
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 32 KiB |
6136
common/dist/sprites/spritesmith-main-3.css
vendored
BIN
common/dist/sprites/spritesmith-main-3.png
vendored
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 136 KiB |
1030
common/dist/sprites/spritesmith-main-4.css
vendored
BIN
common/dist/sprites/spritesmith-main-4.png
vendored
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 133 KiB |
756
common/dist/sprites/spritesmith-main-5.css
vendored
BIN
common/dist/sprites/spritesmith-main-5.png
vendored
|
Before Width: | Height: | Size: 332 KiB After Width: | Height: | Size: 317 KiB |
546
common/dist/sprites/spritesmith-main-6.css
vendored
BIN
common/dist/sprites/spritesmith-main-6.png
vendored
|
Before Width: | Height: | Size: 211 KiB After Width: | Height: | Size: 216 KiB |
492
common/dist/sprites/spritesmith-main-7.css
vendored
BIN
common/dist/sprites/spritesmith-main-7.png
vendored
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 136 KiB |
632
common/dist/sprites/spritesmith-main-8.css
vendored
BIN
common/dist/sprites/spritesmith-main-8.png
vendored
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 151 KiB |
738
common/dist/sprites/spritesmith-main-9.css
vendored
BIN
common/dist/sprites/spritesmith-main-9.png
vendored
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 144 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 629 B |
|
After Width: | Height: | Size: 528 B |
|
After Width: | Height: | Size: 334 B |
|
After Width: | Height: | Size: 710 B |
|
After Width: | Height: | Size: 519 B |
|
After Width: | Height: | Size: 289 B |
|
After Width: | Height: | Size: 521 B |
|
After Width: | Height: | Size: 601 B |
|
After Width: | Height: | Size: 490 B |
|
After Width: | Height: | Size: 17 KiB |
@@ -167,6 +167,14 @@
|
||||
"backgroundCozyLibraryText": "Cozy Library",
|
||||
"backgroundCozyLibraryNotes": "Read in the Cozy Library.",
|
||||
"backgroundGrandStaircaseText": "Grand Staircase",
|
||||
"backgroundGrandStaircaseNotes": "Stride down the Grand Staircase."
|
||||
"backgroundGrandStaircaseNotes": "Stride down the Grand Staircase.",
|
||||
|
||||
"backgrounds032016": "SET 22: Released March 2016",
|
||||
"backgroundDeepMineText": "Deep Mine",
|
||||
"backgroundDeepMineNotes": "Find precious metals in a Deep Mine.",
|
||||
"backgroundRainforestText": "Rainforest",
|
||||
"backgroundRainforestNotes": "Venture into a Rainforest.",
|
||||
"backgroundStoneCircleText": "Circle of Stones",
|
||||
"backgroundStoneCircleNotes": "Cast spells in a Circle of Stones."
|
||||
}
|
||||
|
||||
|
||||
@@ -193,6 +193,8 @@
|
||||
"weaponArmoireBarristerGavelNotes": "Order! Increases Strength and Constitution by <%= attrs %> each. Enchanted Armoire: Barrister Set (Item 3 of 3).",
|
||||
"weaponArmoireJesterBatonText": "Jester Baton",
|
||||
"weaponArmoireJesterBatonNotes": "With a wave of your baton and some witty repartee, even the most complicated situations become clear. Increases Intelligence and Perception by <%= attrs %> each. Enchanted Armoire: Jester Set (Item 3 of 3).",
|
||||
"weaponArmoireMiningPickaxText": "Mining Pickax",
|
||||
"weaponArmoireMiningPickaxNotes": "Mine the maximum amount of gold from your tasks! Increases Perception by <%= per %>. Enchanted Armoire: Miner Set (Item 3 of 3).",
|
||||
|
||||
"armor": "armor",
|
||||
|
||||
@@ -403,6 +405,8 @@
|
||||
"armorArmoireBarristerRobesNotes": "Very serious and stately. Increases Constitution by <%= con %>. Enchanted Armoire: Barrister Set (Item 2 of 3).",
|
||||
"armorArmoireJesterCostumeText": "Jester Costume",
|
||||
"armorArmoireJesterCostumeNotes": "Tra-la-la! Despite the look of this costume, you are no fool. Increases Intelligence by <%= int %>. Enchanted Armoire: Jester Set (Item 2 of 3).",
|
||||
"armorArmoireMinerOverallsText": "Miner Overalls",
|
||||
"armorArmoireMinerOverallsNotes": "They may seem worn, but they are enchanted to repel dirt. Increases Constitution by <%= con %>. Enchanted Armoire: Miner Set (Item 2 of 3).",
|
||||
|
||||
"headgear": "headgear",
|
||||
|
||||
@@ -627,6 +631,8 @@
|
||||
"headArmoireBarristerWigNotes": "This bouncy wig is enough to frighten away even the fiercest foe. Increases Strength by <%= str %>. Enchanted Armoire: Barrister Set (Item 1 of 3).",
|
||||
"headArmoireJesterCapText": "Jester Cap",
|
||||
"headArmoireJesterCapNotes": "The bells on this hat might distract your opponents, but they just help you focus. Increases Perception by <%= per %>. Enchanted Armoire: Jester Set (Item 1 of 3).",
|
||||
"headArmoireMinerHelmetText": "Miner Helmet",
|
||||
"headArmoireMinerHelmetNotes": "Protect your head from falling tasks! Increases Intelligence by <%= int %>. Enchanted Armoire: Miner Set (Item 1 of 3).",
|
||||
|
||||
"offhand": "shield-hand item",
|
||||
|
||||
@@ -739,6 +745,8 @@
|
||||
"shieldArmoireRoyalCaneNotes": "Hooray for the ruler, worthy of song! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 2 of 3).",
|
||||
"shieldArmoireDragonTamerShieldText": "Dragon Tamer Shield",
|
||||
"shieldArmoireDragonTamerShieldNotes": "Distract enemies with this dragon-shaped shield. Increases Perception by <%= per %>. Enchanted Armoire: Dragon Tamer Set (Item 2 of 3).",
|
||||
"shieldArmoireMysticLampText": "Mystic Lamp",
|
||||
"shieldArmoireMysticLampNotes": "Light the darkest caves with this mystic lamp! Increases Perception by <%= per %>. Enchanted Armoire: Independent Item.",
|
||||
|
||||
"back": "Back Accessory",
|
||||
"backBase0Text": "No Back Accessory",
|
||||
|
||||
@@ -297,6 +297,20 @@ let backgrounds = {
|
||||
notes: t('backgroundGrandStaircaseNotes'),
|
||||
},
|
||||
},
|
||||
backgrounds032016: {
|
||||
deep_mine: {
|
||||
text: t('backgroundDeepMineText'),
|
||||
notes: t('backgroundDeepMineNotes'),
|
||||
},
|
||||
rainforest: {
|
||||
text: t('backgroundRainforestText'),
|
||||
notes: t('backgroundRainforestNotes'),
|
||||
},
|
||||
stone_circle: {
|
||||
text: t('backgroundStoneCircleText'),
|
||||
notes: t('backgroundStoneCircleNotes'),
|
||||
},
|
||||
},
|
||||
};
|
||||
/* eslint-enable quote-props */
|
||||
|
||||
|
||||
@@ -110,6 +110,14 @@ let armor = {
|
||||
set: 'jester',
|
||||
canOwn: ownsItem('armor_armoire_jesterCostume'),
|
||||
},
|
||||
minerOveralls: {
|
||||
text: t('armorArmoireMinerOverallsText'),
|
||||
notes: t('armorArmoireMinerOverallsNotes', { con: 10 }),
|
||||
value: 100,
|
||||
con: 10,
|
||||
set: 'miner',
|
||||
canOwn: ownsItem('armor_armoire_minerOveralls'),
|
||||
},
|
||||
};
|
||||
|
||||
let eyewear = {
|
||||
@@ -298,6 +306,14 @@ let head = {
|
||||
set: 'jester',
|
||||
canOwn: ownsItem('head_armoire_jesterCap'),
|
||||
},
|
||||
minerHelmet: {
|
||||
text: t('headArmoireMinerHelmetText'),
|
||||
notes: t('headArmoireMinerHelmetNotes', { int: 5 }),
|
||||
value: 100,
|
||||
int: 5,
|
||||
set: 'miner',
|
||||
canOwn: ownsItem('head_armoire_minerHelmet'),
|
||||
},
|
||||
};
|
||||
|
||||
let shield = {
|
||||
@@ -336,6 +352,13 @@ let shield = {
|
||||
set: 'dragonTamer',
|
||||
canOwn: ownsItem('shield_armoire_dragonTamerShield'),
|
||||
},
|
||||
mysticLamp: {
|
||||
text: t('shieldArmoireMysticLampText'),
|
||||
notes: t('shieldArmoireMysticLampNotes', { per: 15 }),
|
||||
value: 100,
|
||||
per: 15,
|
||||
canOwn: ownsItem('shield_armoire_mysticLamp'),
|
||||
},
|
||||
};
|
||||
|
||||
let weapon = {
|
||||
@@ -455,6 +478,13 @@ let weapon = {
|
||||
per: 8,
|
||||
canOwn: ownsItem('weapon_armoire_jesterBaton'),
|
||||
},
|
||||
miningPickax: {
|
||||
text: t('weaponArmoireMiningPickaxText'),
|
||||
notes: t('weaponArmoireMiningPickaxNotes', { per: 15 }),
|
||||
value: 100,
|
||||
per: 15,
|
||||
canOwn: ownsItem('weapon_armoire_miningPickax'),
|
||||
},
|
||||
};
|
||||
|
||||
let armoireSet = {
|
||||
|
||||
@@ -22,12 +22,14 @@ import gear from './gear';
|
||||
|
||||
import appearances from './appearance';
|
||||
import backgrounds from './appearance/backgrounds.js'
|
||||
import spells from './spells';
|
||||
|
||||
api.mystery = mysterySets;
|
||||
|
||||
api.itemList = ITEM_LIST;
|
||||
|
||||
api.gear = gear;
|
||||
api.spells = spells;
|
||||
|
||||
/*
|
||||
Time Traveler Store, mystery sets need their items mapped in
|
||||
@@ -100,607 +102,6 @@ api.classes = CLASSES;
|
||||
|
||||
api.gearTypes = GEAR_TYPES;
|
||||
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------
|
||||
Spells
|
||||
---------------------------------------------------------------
|
||||
Text, notes, and mana are obvious. The rest:
|
||||
|
||||
* {target}: one of [task, self, party, user]. This is very important, because if the cast() function is expecting one
|
||||
thing and receives another, it will cause errors. `self` is used for self buffs, multi-task debuffs, AOEs (eg, meteor-shower),
|
||||
etc. Basically, use self for anything that's not [task, party, user] and is an instant-cast
|
||||
|
||||
* {cast}: the function that's run to perform the ability's action. This is pretty slick - because this is exported to the
|
||||
web, this function can be performed on the client and on the server. `user` param is self (needed for determining your
|
||||
own stats for effectiveness of cast), and `target` param is one of [task, party, user]. In the case of `self` spells,
|
||||
you act on `user` instead of `target`. You can trust these are the correct objects, as long as the `target` attr of the
|
||||
spell is correct. Take a look at habitrpg/src/models/user.js and habitrpg/src/models/task.js for what attributes are
|
||||
available on each model. Note `task.value` is its "redness". If party is passed in, it's an array of users,
|
||||
so you'll want to iterate over them like: `_.each(target,function(member){...})`
|
||||
|
||||
Note, user.stats.mp is docked after automatically (it's appended to functions automatically down below in an _.each)
|
||||
*/
|
||||
|
||||
diminishingReturns = function(bonus, max, halfway) {
|
||||
if (halfway == null) {
|
||||
halfway = max / 2;
|
||||
}
|
||||
return max * (bonus / (bonus + halfway));
|
||||
};
|
||||
|
||||
calculateBonus = function(value, stat, crit, stat_scale) {
|
||||
if (crit == null) {
|
||||
crit = 1;
|
||||
}
|
||||
if (stat_scale == null) {
|
||||
stat_scale = 0.5;
|
||||
}
|
||||
return (value < 0 ? 1 : value + 1) + (stat * stat_scale * crit);
|
||||
};
|
||||
|
||||
api.spells = {
|
||||
wizard: {
|
||||
fireball: {
|
||||
text: t('spellWizardFireballText'),
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: t('spellWizardFireballNotes'),
|
||||
cast: function(user, target) {
|
||||
var base, bonus, req;
|
||||
bonus = user._statsComputed.int * user.fns.crit('per');
|
||||
bonus *= Math.ceil((target.value < 0 ? 1 : target.value + 1) * .075);
|
||||
user.stats.exp += diminishingReturns(bonus, 75);
|
||||
if ((base = user.party.quest.progress).up == null) {
|
||||
base.up = 0;
|
||||
}
|
||||
user.party.quest.progress.up += Math.ceil(user._statsComputed.int * .1);
|
||||
req = {
|
||||
language: user.preferences.language
|
||||
};
|
||||
return user.fns.updateStats(user.stats, req);
|
||||
}
|
||||
},
|
||||
mpheal: {
|
||||
text: t('spellWizardMPHealText'),
|
||||
mana: 30,
|
||||
lvl: 12,
|
||||
target: 'party',
|
||||
notes: t('spellWizardMPHealNotes'),
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
var bonus;
|
||||
bonus = user._statsComputed.int;
|
||||
if (user._id !== member._id) {
|
||||
return member.stats.mp += Math.ceil(diminishingReturns(bonus, 25, 125));
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
earth: {
|
||||
text: t('spellWizardEarthText'),
|
||||
mana: 35,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: t('spellWizardEarthNotes'),
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.int - user.stats.buffs.int;
|
||||
if ((base = member.stats.buffs).int == null) {
|
||||
base.int = 0;
|
||||
}
|
||||
return member.stats.buffs.int += Math.ceil(diminishingReturns(bonus, 30, 200));
|
||||
});
|
||||
}
|
||||
},
|
||||
frost: {
|
||||
text: t('spellWizardFrostText'),
|
||||
mana: 40,
|
||||
lvl: 14,
|
||||
target: 'self',
|
||||
notes: t('spellWizardFrostNotes'),
|
||||
cast: function(user, target) {
|
||||
return user.stats.buffs.streaks = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
warrior: {
|
||||
smash: {
|
||||
text: t('spellWarriorSmashText'),
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: t('spellWarriorSmashNotes'),
|
||||
cast: function(user, target) {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.str * user.fns.crit('con');
|
||||
target.value += diminishingReturns(bonus, 2.5, 35);
|
||||
if ((base = user.party.quest.progress).up == null) {
|
||||
base.up = 0;
|
||||
}
|
||||
return user.party.quest.progress.up += diminishingReturns(bonus, 55, 70);
|
||||
}
|
||||
},
|
||||
defensiveStance: {
|
||||
text: t('spellWarriorDefensiveStanceText'),
|
||||
mana: 25,
|
||||
lvl: 12,
|
||||
target: 'self',
|
||||
notes: t('spellWarriorDefensiveStanceNotes'),
|
||||
cast: function(user, target) {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if ((base = user.stats.buffs).con == null) {
|
||||
base.con = 0;
|
||||
}
|
||||
return user.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 40, 200));
|
||||
}
|
||||
},
|
||||
valorousPresence: {
|
||||
text: t('spellWarriorValorousPresenceText'),
|
||||
mana: 20,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: t('spellWarriorValorousPresenceNotes'),
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.str - user.stats.buffs.str;
|
||||
if ((base = member.stats.buffs).str == null) {
|
||||
base.str = 0;
|
||||
}
|
||||
return member.stats.buffs.str += Math.ceil(diminishingReturns(bonus, 20, 200));
|
||||
});
|
||||
}
|
||||
},
|
||||
intimidate: {
|
||||
text: t('spellWarriorIntimidateText'),
|
||||
mana: 15,
|
||||
lvl: 14,
|
||||
target: 'party',
|
||||
notes: t('spellWarriorIntimidateNotes'),
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if ((base = member.stats.buffs).con == null) {
|
||||
base.con = 0;
|
||||
}
|
||||
return member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 24, 200));
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
rogue: {
|
||||
pickPocket: {
|
||||
text: t('spellRoguePickPocketText'),
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: t('spellRoguePickPocketNotes'),
|
||||
cast: function(user, target) {
|
||||
var bonus;
|
||||
bonus = calculateBonus(target.value, user._statsComputed.per);
|
||||
return user.stats.gp += diminishingReturns(bonus, 25, 75);
|
||||
}
|
||||
},
|
||||
backStab: {
|
||||
text: t('spellRogueBackStabText'),
|
||||
mana: 15,
|
||||
lvl: 12,
|
||||
target: 'task',
|
||||
notes: t('spellRogueBackStabNotes'),
|
||||
cast: function(user, target) {
|
||||
var _crit, bonus, req;
|
||||
_crit = user.fns.crit('str', .3);
|
||||
bonus = calculateBonus(target.value, user._statsComputed.str, _crit);
|
||||
user.stats.exp += diminishingReturns(bonus, 75, 50);
|
||||
user.stats.gp += diminishingReturns(bonus, 18, 75);
|
||||
req = {
|
||||
language: user.preferences.language
|
||||
};
|
||||
return user.fns.updateStats(user.stats, req);
|
||||
}
|
||||
},
|
||||
toolsOfTrade: {
|
||||
text: t('spellRogueToolsOfTradeText'),
|
||||
mana: 25,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: t('spellRogueToolsOfTradeNotes'),
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.per - user.stats.buffs.per;
|
||||
if ((base = member.stats.buffs).per == null) {
|
||||
base.per = 0;
|
||||
}
|
||||
return member.stats.buffs.per += Math.ceil(diminishingReturns(bonus, 100, 50));
|
||||
});
|
||||
}
|
||||
},
|
||||
stealth: {
|
||||
text: t('spellRogueStealthText'),
|
||||
mana: 45,
|
||||
lvl: 14,
|
||||
target: 'self',
|
||||
notes: t('spellRogueStealthNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
if ((base = user.stats.buffs).stealth == null) {
|
||||
base.stealth = 0;
|
||||
}
|
||||
return user.stats.buffs.stealth += Math.ceil(diminishingReturns(user._statsComputed.per, user.dailys.length * 0.64, 55));
|
||||
}
|
||||
}
|
||||
},
|
||||
healer: {
|
||||
heal: {
|
||||
text: t('spellHealerHealText'),
|
||||
mana: 15,
|
||||
lvl: 11,
|
||||
target: 'self',
|
||||
notes: t('spellHealerHealNotes'),
|
||||
cast: function(user, target) {
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .075;
|
||||
if (user.stats.hp > 50) {
|
||||
return user.stats.hp = 50;
|
||||
}
|
||||
}
|
||||
},
|
||||
brightness: {
|
||||
text: t('spellHealerBrightnessText'),
|
||||
mana: 15,
|
||||
lvl: 12,
|
||||
target: 'self',
|
||||
notes: t('spellHealerBrightnessNotes'),
|
||||
cast: function(user, target) {
|
||||
return _.each(user.tasks, function(target) {
|
||||
if (target.type === 'reward') {
|
||||
return;
|
||||
}
|
||||
return target.value += 4 * (user._statsComputed.int / (user._statsComputed.int + 40));
|
||||
});
|
||||
}
|
||||
},
|
||||
protectAura: {
|
||||
text: t('spellHealerProtectAuraText'),
|
||||
mana: 30,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: t('spellHealerProtectAuraNotes'),
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if ((base = member.stats.buffs).con == null) {
|
||||
base.con = 0;
|
||||
}
|
||||
return member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 200, 200));
|
||||
});
|
||||
}
|
||||
},
|
||||
heallAll: {
|
||||
text: t('spellHealerHealAllText'),
|
||||
mana: 25,
|
||||
lvl: 14,
|
||||
target: 'party',
|
||||
notes: t('spellHealerHealAllNotes'),
|
||||
cast: function(user, target) {
|
||||
return _.each(target, function(member) {
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .04;
|
||||
if (member.stats.hp > 50) {
|
||||
return member.stats.hp = 50;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
special: {
|
||||
snowball: {
|
||||
text: t('spellSpecialSnowballAuraText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSnowballAuraNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
target.stats.buffs.snowball = true;
|
||||
target.stats.buffs.spookDust = false;
|
||||
target.stats.buffs.shinySeed = false;
|
||||
target.stats.buffs.seafoam = false;
|
||||
if ((base = target.achievements).snowball == null) {
|
||||
base.snowball = 0;
|
||||
}
|
||||
target.achievements.snowball++;
|
||||
return user.items.special.snowball--;
|
||||
}
|
||||
},
|
||||
salt: {
|
||||
text: t('spellSpecialSaltText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialSaltNotes'),
|
||||
cast: function(user, target) {
|
||||
user.stats.buffs.snowball = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
},
|
||||
spookDust: {
|
||||
text: t('spellSpecialSpookDustText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSpookDustNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
target.stats.buffs.snowball = false;
|
||||
target.stats.buffs.spookDust = true;
|
||||
target.stats.buffs.shinySeed = false;
|
||||
target.stats.buffs.seafoam = false;
|
||||
if ((base = target.achievements).spookDust == null) {
|
||||
base.spookDust = 0;
|
||||
}
|
||||
target.achievements.spookDust++;
|
||||
return user.items.special.spookDust--;
|
||||
}
|
||||
},
|
||||
opaquePotion: {
|
||||
text: t('spellSpecialOpaquePotionText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialOpaquePotionNotes'),
|
||||
cast: function(user, target) {
|
||||
user.stats.buffs.spookDust = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
},
|
||||
shinySeed: {
|
||||
text: t('spellSpecialShinySeedText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialShinySeedNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
target.stats.buffs.snowball = false;
|
||||
target.stats.buffs.spookDust = false;
|
||||
target.stats.buffs.shinySeed = true;
|
||||
target.stats.buffs.seafoam = false;
|
||||
if ((base = target.achievements).shinySeed == null) {
|
||||
base.shinySeed = 0;
|
||||
}
|
||||
target.achievements.shinySeed++;
|
||||
return user.items.special.shinySeed--;
|
||||
}
|
||||
},
|
||||
petalFreePotion: {
|
||||
text: t('spellSpecialPetalFreePotionText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialPetalFreePotionNotes'),
|
||||
cast: function(user, target) {
|
||||
user.stats.buffs.shinySeed = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
},
|
||||
seafoam: {
|
||||
text: t('spellSpecialSeafoamText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSeafoamNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
target.stats.buffs.snowball = false;
|
||||
target.stats.buffs.spookDust = false;
|
||||
target.stats.buffs.shinySeed = false;
|
||||
target.stats.buffs.seafoam = true;
|
||||
if ((base = target.achievements).seafoam == null) {
|
||||
base.seafoam = 0;
|
||||
}
|
||||
target.achievements.seafoam++;
|
||||
return user.items.special.seafoam--;
|
||||
}
|
||||
},
|
||||
sand: {
|
||||
text: t('spellSpecialSandText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialSandNotes'),
|
||||
cast: function(user, target) {
|
||||
user.stats.buffs.seafoam = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
},
|
||||
nye: {
|
||||
text: t('nyeCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('nyeCardNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).nye == null) {
|
||||
base.nye = 0;
|
||||
}
|
||||
user.achievements.nye++;
|
||||
} else {
|
||||
_.each([user, target], function(t) {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).nye == null) {
|
||||
base1.nye = 0;
|
||||
}
|
||||
return t.achievements.nye++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.nyeReceived) {
|
||||
target.items.special.nyeReceived = [];
|
||||
}
|
||||
target.items.special.nyeReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.nyeReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
},
|
||||
valentine: {
|
||||
text: t('valentineCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('valentineCardNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).valentine == null) {
|
||||
base.valentine = 0;
|
||||
}
|
||||
user.achievements.valentine++;
|
||||
} else {
|
||||
_.each([user, target], function(t) {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).valentine == null) {
|
||||
base1.valentine = 0;
|
||||
}
|
||||
return t.achievements.valentine++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.valentineReceived) {
|
||||
target.items.special.valentineReceived = [];
|
||||
}
|
||||
target.items.special.valentineReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.valentineReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
},
|
||||
greeting: {
|
||||
text: t('greetingCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('greetingCardNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).greeting == null) {
|
||||
base.greeting = 0;
|
||||
}
|
||||
user.achievements.greeting++;
|
||||
} else {
|
||||
_.each([user, target], function(t) {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).greeting == null) {
|
||||
base1.greeting = 0;
|
||||
}
|
||||
return t.achievements.greeting++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.greetingReceived) {
|
||||
target.items.special.greetingReceived = [];
|
||||
}
|
||||
target.items.special.greetingReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.greetingReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
},
|
||||
thankyou: {
|
||||
text: t('thankyouCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('thankyouCardNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).thankyou == null) {
|
||||
base.thankyou = 0;
|
||||
}
|
||||
user.achievements.thankyou++;
|
||||
} else {
|
||||
_.each([user, target], function(t) {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).thankyou == null) {
|
||||
base1.thankyou = 0;
|
||||
}
|
||||
return t.achievements.thankyou++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.thankyouReceived) {
|
||||
target.items.special.thankyouReceived = [];
|
||||
}
|
||||
target.items.special.thankyouReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.thankyouReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
},
|
||||
birthday: {
|
||||
text: t('birthdayCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('birthdayCardNotes'),
|
||||
cast: function(user, target) {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).birthday == null) {
|
||||
base.birthday = 0;
|
||||
}
|
||||
user.achievements.birthday++;
|
||||
} else {
|
||||
_.each([user, target], function(t) {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).birthday == null) {
|
||||
base1.birthday = 0;
|
||||
}
|
||||
return t.achievements.birthday++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.birthdayReceived) {
|
||||
target.items.special.birthdayReceived = [];
|
||||
}
|
||||
target.items.special.birthdayReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.birthdayReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
api.cardTypes = {
|
||||
greeting: {
|
||||
key: 'greeting',
|
||||
@@ -727,21 +128,8 @@ api.cardTypes = {
|
||||
},
|
||||
};
|
||||
|
||||
_.each(api.spells, function(spellClass) {
|
||||
return _.each(spellClass, function(spell, key) {
|
||||
var _cast;
|
||||
spell.key = key;
|
||||
_cast = spell.cast;
|
||||
return spell.cast = function(user, target) {
|
||||
_cast(user, target);
|
||||
return user.stats.mp -= spell.mana;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
api.special = api.spells.special;
|
||||
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------
|
||||
Drops
|
||||
|
||||
509
common/script/content/spells.js
Normal file
@@ -0,0 +1,509 @@
|
||||
import t from './translation';
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------
|
||||
Spells
|
||||
---------------------------------------------------------------
|
||||
Text, notes, and mana are obvious. The rest:
|
||||
|
||||
* {target}: one of [task, self, party, user]. This is very important, because if the cast() function is expecting one
|
||||
thing and receives another, it will cause errors. `self` is used for self buffs, multi-task debuffs, AOEs (eg, meteor-shower),
|
||||
etc. Basically, use self for anything that's not [task, party, user] and is an instant-cast
|
||||
|
||||
* {cast}: the function that's run to perform the ability's action. This is pretty slick - because this is exported to the
|
||||
web, this function can be performed on the client and on the server. `user` param is self (needed for determining your
|
||||
own stats for effectiveness of cast), and `target` param is one of [task, party, user]. In the case of `self` spells,
|
||||
you act on `user` instead of `target`. You can trust these are the correct objects, as long as the `target` attr of the
|
||||
spell is correct. Take a look at habitrpg/src/models/user.js and habitrpg/src/models/task.js for what attributes are
|
||||
available on each model. Note `task.value` is its "redness". If party is passed in, it's an array of users,
|
||||
so you'll want to iterate over them like: `_.each(target,function(member){...})`
|
||||
|
||||
Note, user.stats.mp is docked after automatically (it's appended to functions automatically down below in an _.each)
|
||||
*/
|
||||
|
||||
function diminishingReturns (bonus, max, halfway) {
|
||||
if (!halfway) halfway = max / 2;
|
||||
return max * (bonus / (bonus + halfway));
|
||||
}
|
||||
|
||||
function calculateBonus (value, stat, crit = 1, statScale = 0.5) {
|
||||
return (value < 0 ? 1 : value + 1) + stat * statScale * crit;
|
||||
}
|
||||
|
||||
let spells = {};
|
||||
|
||||
spells.wizard = {
|
||||
fireball: {
|
||||
text: t('spellWizardFireballText'),
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: t('spellWizardFireballNotes'),
|
||||
cast (user, target) {
|
||||
let bonus = user._statsComputed.int * user.fns.crit('per');
|
||||
bonus *= Math.ceil((target.value < 0 ? 1 : target.value + 1) * 0.075);
|
||||
user.stats.exp += diminishingReturns(bonus, 75);
|
||||
if (!user.party.quest.progress) user.party.quest.progress = 0;
|
||||
user.party.quest.progress.up += Math.ceil(user._statsComputed.int * 9.1);
|
||||
// TODO change, pass req to spell?
|
||||
let req = {language: user.preferences.language};
|
||||
user.fns.updateStats(user.stats, req);
|
||||
},
|
||||
},
|
||||
mpheal: {
|
||||
text: t('spellWizardMPHealText'),
|
||||
mana: 30,
|
||||
lvl: 12,
|
||||
target: 'party',
|
||||
notes: t('spellWizardMPHealNotes'),
|
||||
cast (user, target) {
|
||||
_.each(target, (member) => {
|
||||
let bonus = user._statsComputed.int;
|
||||
if (user._id !== member._id) {
|
||||
member.stats.mp += Math.ceil(diminishingReturns(bonus, 25, 125));
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
earth: {
|
||||
text: t('spellWizardEarthText'),
|
||||
mana: 35,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: t('spellWizardEarthNotes'),
|
||||
cast (user, target) {
|
||||
_.each(target, (member) => {
|
||||
let bonus = user._statsComputed.int - user.stats.buffs.int;
|
||||
if (!member.stats.buffs.int) member.stats.buffs.int = 0;
|
||||
member.stats.buffs.int += Math.ceil(diminishingReturns(bonus, 30, 200));
|
||||
});
|
||||
},
|
||||
},
|
||||
frost: {
|
||||
text: t('spellWizardFrostText'),
|
||||
mana: 40,
|
||||
lvl: 14,
|
||||
target: 'self',
|
||||
notes: t('spellWizardFrostNotes'),
|
||||
cast (user) {
|
||||
user.stats.buffs.streaks = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
spells.warrior = {
|
||||
smash: {
|
||||
text: t('spellWarriorSmashText'),
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: t('spellWarriorSmashNotes'),
|
||||
cast (user, target) {
|
||||
let bonus = user._statsComputed.str * user.fns.crit('con');
|
||||
target.value += diminishingReturns(bonus, 2.5, 35);
|
||||
if (!user.party.quest.progress.up) user.party.quest.progress.base = 0;
|
||||
user.party.quest.progress.up += diminishingReturns(bonus, 55, 70);
|
||||
},
|
||||
},
|
||||
defensiveStance: {
|
||||
text: t('spellWarriorDefensiveStanceText'),
|
||||
mana: 25,
|
||||
lvl: 12,
|
||||
target: 'self',
|
||||
notes: t('spellWarriorDefensiveStanceNotes'),
|
||||
cast (user) {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if (!user.stats.buffs.con) user.stats.buffs.con = 0;
|
||||
user.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 40, 200));
|
||||
},
|
||||
},
|
||||
valorousPresence: {
|
||||
text: t('spellWarriorValorousPresenceText'),
|
||||
mana: 20,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: t('spellWarriorValorousPresenceNotes'),
|
||||
cast (user, target) {
|
||||
_.each(target, (member) => {
|
||||
let bonus = user._statsComputed.str - user.stats.buffs.str;
|
||||
if (!member.stats.buffs.str) member.stats.buffs.str = 0;
|
||||
member.stats.buffs.str += Math.ceil(diminishingReturns(bonus, 20, 200));
|
||||
});
|
||||
},
|
||||
},
|
||||
intimidate: {
|
||||
text: t('spellWarriorIntimidateText'),
|
||||
mana: 15,
|
||||
lvl: 14,
|
||||
target: 'party',
|
||||
notes: t('spellWarriorIntimidateNotes'),
|
||||
cast (user, target) {
|
||||
_.each(target, (member) => {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if (!member.stats.buffs.con) member.stats.buffs.con = 0;
|
||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 24, 200));
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
spells.rogue = {
|
||||
pickPocket: {
|
||||
text: t('spellRoguePickPocketText'),
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
notes: t('spellRoguePickPocketNotes'),
|
||||
cast (user, target) {
|
||||
let bonus = calculateBonus(target.value, user._statsComputed.per);
|
||||
user.stats.gp += diminishingReturns(bonus, 25, 75);
|
||||
},
|
||||
},
|
||||
backStab: {
|
||||
text: t('spellRogueBackStabText'),
|
||||
mana: 15,
|
||||
lvl: 12,
|
||||
target: 'task',
|
||||
notes: t('spellRogueBackStabNotes'),
|
||||
cast (user, target) {
|
||||
let _crit = user.fns.crit('str', 0.3);
|
||||
let bonus = calculateBonus(target.value, user._statsComputed.str, _crit);
|
||||
user.stats.exp += diminishingReturns(bonus, 75, 50);
|
||||
user.stats.gp += diminishingReturns(bonus, 18, 75);
|
||||
let req = {language: user.preferences.language};
|
||||
user.fns.updateStats(user.stats, req);
|
||||
},
|
||||
},
|
||||
toolsOfTrade: {
|
||||
text: t('spellRogueToolsOfTradeText'),
|
||||
mana: 25,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: t('spellRogueToolsOfTradeNotes'),
|
||||
cast (user, target) {
|
||||
_.each(target, (member) => {
|
||||
let bonus = user._statsComputed.per - user.stats.buffs.per;
|
||||
if (!member.stats.buffs.per) member.stats.buffs.per = 0;
|
||||
member.stats.buffs.per += Math.ceil(diminishingReturns(bonus, 100, 50));
|
||||
});
|
||||
},
|
||||
},
|
||||
stealth: {
|
||||
text: t('spellRogueStealthText'),
|
||||
mana: 45,
|
||||
lvl: 14,
|
||||
target: 'self',
|
||||
notes: t('spellRogueStealthNotes'),
|
||||
cast (user) {
|
||||
if (!user.stats.buffs.stealth) user.stats.buffs.stealth = 0;
|
||||
user.stats.buffs.stealth += Math.ceil(diminishingReturns(user._statsComputed.per, user.dailys.length * 0.64, 55));
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
spells.healer = {
|
||||
heal: {
|
||||
text: t('spellHealerHealText'),
|
||||
mana: 15,
|
||||
lvl: 11,
|
||||
target: 'self',
|
||||
notes: t('spellHealerHealNotes'),
|
||||
cast (user) {
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * 0.075;
|
||||
if (user.stats.hp > 50) user.stats.hp = 50;
|
||||
},
|
||||
},
|
||||
brightness: {
|
||||
text: t('spellHealerBrightnessText'),
|
||||
mana: 15,
|
||||
lvl: 12,
|
||||
target: 'self',
|
||||
notes: t('spellHealerBrightnessNotes'),
|
||||
cast (user) {
|
||||
_.each(user.tasks, (task) => {
|
||||
if (task.type !== 'reward') {
|
||||
task.value += 4 * (user._statsComputed.int / (user._statsComputed.int + 40));
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
protectAura: {
|
||||
text: t('spellHealerProtectAuraText'),
|
||||
mana: 30,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
notes: t('spellHealerProtectAuraNotes'),
|
||||
cast (user, target) {
|
||||
_.each(target, (member) => {
|
||||
let bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if (!member.stats.buffs.con) member.stats.buffs.con = 0;
|
||||
member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 200, 200));
|
||||
});
|
||||
},
|
||||
},
|
||||
heallAll: {
|
||||
text: t('spellHealerHealAllText'),
|
||||
mana: 25,
|
||||
lvl: 14,
|
||||
target: 'party',
|
||||
notes: t('spellHealerHealAllNotes'),
|
||||
cast (user, target) {
|
||||
_.each(target, (member) => {
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * 0.04;
|
||||
if (member.stats.hp > 50) member.stats.hp = 50;
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
spells.special = {
|
||||
snowball: {
|
||||
text: t('spellSpecialSnowballAuraText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSnowballAuraNotes'),
|
||||
cast (user, target) {
|
||||
target.stats.buffs.snowball = true;
|
||||
target.stats.buffs.spookDust = false;
|
||||
target.stats.buffs.shinySeed = false;
|
||||
target.stats.buffs.seafoam = false;
|
||||
if (!target.achievements.snowball) target.achievements.snowball = 0;
|
||||
target.achievements.snowball++;
|
||||
user.items.special.snowball--;
|
||||
},
|
||||
},
|
||||
salt: {
|
||||
text: t('spellSpecialSaltText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialSaltNotes'),
|
||||
cast (user) {
|
||||
user.stats.buffs.snowball = false;
|
||||
user.stats.gp -= 5;
|
||||
},
|
||||
},
|
||||
spookDust: {
|
||||
text: t('spellSpecialSpookDustText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSpookDustNotes'),
|
||||
cast (user, target) {
|
||||
target.stats.buffs.snowball = false;
|
||||
target.stats.buffs.spookDust = true;
|
||||
target.stats.buffs.shinySeed = false;
|
||||
target.stats.buffs.seafoam = false;
|
||||
if (!target.achievements.spookDust) target.achievements.spookDust = 0;
|
||||
target.achievements.spookDust++;
|
||||
user.items.special.spookDust--;
|
||||
},
|
||||
},
|
||||
opaquePotion: {
|
||||
text: t('spellSpecialOpaquePotionText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialOpaquePotionNotes'),
|
||||
cast (user) {
|
||||
user.stats.buffs.spookDust = false;
|
||||
user.stats.gp -= 5;
|
||||
},
|
||||
},
|
||||
shinySeed: {
|
||||
text: t('spellSpecialShinySeedText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialShinySeedNotes'),
|
||||
cast (user, target) {
|
||||
target.stats.buffs.snowball = false;
|
||||
target.stats.buffs.spookDust = false;
|
||||
target.stats.buffs.shinySeed = true;
|
||||
target.stats.buffs.seafoam = false;
|
||||
if (!target.achievements.shinySeed) target.achievements.shinySeed = 0;
|
||||
target.achievements.shinySeed++;
|
||||
user.items.special.shinySeed--;
|
||||
},
|
||||
},
|
||||
petalFreePotion: {
|
||||
text: t('spellSpecialPetalFreePotionText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialPetalFreePotionNotes'),
|
||||
cast (user) {
|
||||
user.stats.buffs.shinySeed = false;
|
||||
user.stats.gp -= 5;
|
||||
},
|
||||
},
|
||||
seafoam: {
|
||||
text: t('spellSpecialSeafoamText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSeafoamNotes'),
|
||||
cast (user, target) {
|
||||
target.stats.buffs.snowball = false;
|
||||
target.stats.buffs.spookDust = false;
|
||||
target.stats.buffs.shinySeed = false;
|
||||
target.stats.buffs.seafoam = true;
|
||||
if (!target.achievements.seafoam) target.achievements.seafoam = 0;
|
||||
target.achievements.seafoam++;
|
||||
user.items.special.seafoam--;
|
||||
},
|
||||
},
|
||||
sand: {
|
||||
text: t('spellSpecialSandText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialSandNotes'),
|
||||
cast (user) {
|
||||
user.stats.buffs.seafoam = false;
|
||||
user.stats.gp -= 5;
|
||||
},
|
||||
},
|
||||
nye: {
|
||||
text: t('nyeCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('nyeCardNotes'),
|
||||
cast (user, target) {
|
||||
if (user === target) {
|
||||
if (!user.achievements.nye) user.achievements.nye = 0;
|
||||
user.achievements.nye++;
|
||||
} else {
|
||||
_.each([user, target], (u) => {
|
||||
if (!u.achievements.nye) u.achievements.nye = 0;
|
||||
u.achievements.nye++;
|
||||
});
|
||||
}
|
||||
|
||||
if (!target.items.special.nyeReceived) target.items.special.nyeReceived = [];
|
||||
target.items.special.nyeReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
user.stats.gp -= 10;
|
||||
},
|
||||
},
|
||||
valentine: {
|
||||
text: t('valentineCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('valentineCardNotes'),
|
||||
cast (user, target) {
|
||||
if (user === target) {
|
||||
if (!user.achievements.valentine) user.achievements.valentine = 0;
|
||||
user.achievements.valentine++;
|
||||
} else {
|
||||
_.each([user, target], (u) => {
|
||||
if (!u.achievements.valentine) u.achievements.valentine = 0;
|
||||
u.achievements.valentine++;
|
||||
});
|
||||
}
|
||||
|
||||
if (!target.items.special.valentineReceived) target.items.special.valentineReceived = [];
|
||||
target.items.special.valentineReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
user.stats.gp -= 10;
|
||||
},
|
||||
},
|
||||
greeting: {
|
||||
text: t('greetingCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('greetingCardNotes'),
|
||||
cast (user, target) {
|
||||
if (user === target) {
|
||||
user.achievements.greeting++;
|
||||
} else {
|
||||
_.each([user, target], (u) => {
|
||||
if (!u.achievements.greeting) u.achievements.greeting = 0;
|
||||
u.achievements.greeting++;
|
||||
});
|
||||
}
|
||||
|
||||
if (!target.items.special.greetingReceived) target.items.special.greetingReceived = [];
|
||||
target.items.special.greetingReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
user.stats.gp -= 10;
|
||||
},
|
||||
},
|
||||
thankyou: {
|
||||
text: t('thankyouCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('thankyouCardNotes'),
|
||||
cast (user, target) {
|
||||
if (user === target) {
|
||||
if (!user.achievements.thankyou) user.achievements.thankyou = 0;
|
||||
user.achievements.thankyou++;
|
||||
} else {
|
||||
_.each([user, target], (u) => {
|
||||
if (!u.achievements.thankyou) u.achievements.thankyou = 0;
|
||||
u.achievements.thankyou++;
|
||||
});
|
||||
}
|
||||
|
||||
if (!target.items.special.thankyouReceived) target.items.special.thankyouReceived = [];
|
||||
target.items.special.thankyouReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
user.stats.gp -= 10;
|
||||
},
|
||||
},
|
||||
birthday: {
|
||||
text: t('birthdayCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('birthdayCardNotes'),
|
||||
cast (user, target) {
|
||||
if (user === target) {
|
||||
if (!user.achievements.birthday) user.achievements.birthday = 0;
|
||||
user.achievements.birthday++;
|
||||
} else {
|
||||
_.each([user, target], (u) => {
|
||||
if (!u.achievements.birthday) u.achievements.birthday = 0;
|
||||
u.achievements.birthday++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.birthdayReceived) target.items.special.birthdayReceived = [];
|
||||
target.items.special.birthdayReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
user.stats.gp -= 10;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
_.each(spells, (spellClass) => {
|
||||
_.each(spellClass, (spell, key) => {
|
||||
spell.key = key;
|
||||
let _cast = spell.cast;
|
||||
spell.cast = function castSpell (user, target) {
|
||||
_cast(user, target);
|
||||
user.stats.mp -= spell.mana;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
export default spells;
|
||||
@@ -1,20 +0,0 @@
|
||||
import {contains} from 'lodash';
|
||||
import {translator as t} from './helpers';
|
||||
|
||||
let armoire = {
|
||||
type: 'armoire',
|
||||
text: t('armoireText'),
|
||||
notes: ((user, count) => {
|
||||
if (user.flags.armoireEmpty) {
|
||||
return t('armoireNotesEmpty')();
|
||||
}
|
||||
return t('armoireNotesFull')() + count;
|
||||
}),
|
||||
value: 100,
|
||||
key: 'armoire',
|
||||
canOwn: ((user) => {
|
||||
return contains(user.achievements.ultimateGearSets, true);
|
||||
})
|
||||
};
|
||||
|
||||
export default armoire;
|
||||
@@ -1,30 +0,0 @@
|
||||
import {each} from 'lodash';
|
||||
import {
|
||||
translator as t,
|
||||
generateBackgrounds
|
||||
} from './helpers';
|
||||
|
||||
let sets = {
|
||||
'backgrounds062014': ['beach', 'fairy_ring', 'forest'],
|
||||
'backgrounds072014': ['open_waters', 'coral_reef', 'seafarer_ship'],
|
||||
'backgrounds082014': ['volcano', 'clouds', 'dusty_canyons'],
|
||||
'backgrounds092014': ['thunderstorm', 'autumn_forest', 'harvest_fields'],
|
||||
'backgrounds102014': ['graveyard', 'haunted_house', 'pumpkin_patch'],
|
||||
'backgrounds112014': ['harvest_feast', 'sunset_meadow', 'starry_skies'],
|
||||
'backgrounds122014': ['iceberg', 'twinkly_lights', 'south_pole'],
|
||||
'backgrounds012015': ['ice_cave', 'frigid_peak', 'snowy_pines'],
|
||||
'backgrounds022015': ['blacksmithy', 'crystal_cave', 'distant_castle'],
|
||||
'backgrounds032015': ['spring_rain', 'stained_glass', 'rolling_hills'],
|
||||
'backgrounds042015': ['cherry_trees', 'floral_meadow', 'gumdrop_land'],
|
||||
'backgrounds052015': ['marble_temple', 'mountain_lake', 'pagodas'],
|
||||
'backgrounds062015': ['drifting_raft', 'shimmery_bubbles', 'island_waterfalls'],
|
||||
'backgrounds072015': ['dilatory_ruins', 'giant_wave', 'sunken_ship'],
|
||||
'backgrounds082015': ['pyramids', 'sunset_savannah', 'twinkly_party_lights'],
|
||||
'backgrounds092015': ['market', 'stable', 'tavern'],
|
||||
'backgrounds102015': ['harvest_moon', 'slimy_swamp', 'swarming_darkness'],
|
||||
'backgrounds112015': ['floating_islands', 'night_dunes', 'sunset_oasis']
|
||||
};
|
||||
|
||||
generateBackgrounds(sets);
|
||||
|
||||
export default sets;
|
||||
@@ -1,22 +0,0 @@
|
||||
let cardTypes = {
|
||||
greeting: {
|
||||
key: 'greeting',
|
||||
messageOptions: 4,
|
||||
yearRound: true
|
||||
},
|
||||
nye: {
|
||||
key: 'nye',
|
||||
messageOptions: 5
|
||||
},
|
||||
thankyou: {
|
||||
key: 'thankyou',
|
||||
messageOptions: 4,
|
||||
yearRound: true
|
||||
},
|
||||
valentine: {
|
||||
key: 'valentine',
|
||||
messageOptions: 4
|
||||
}
|
||||
};
|
||||
|
||||
export default cardTypes;
|
||||
@@ -1,26 +0,0 @@
|
||||
import {generateEggs} from '../helpers';
|
||||
|
||||
const DROP_EGGS = [
|
||||
'Wolf',
|
||||
'TigerCub',
|
||||
'PandaCub',
|
||||
'LionCub',
|
||||
'Fox',
|
||||
'FlyingPig',
|
||||
'Dragon',
|
||||
'Cactus',
|
||||
'BearCub',
|
||||
];
|
||||
|
||||
let eggDefaults = {
|
||||
type: 'drop',
|
||||
canBuy: () => {
|
||||
return () => {
|
||||
return true;
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
let eggs = generateEggs(DROP_EGGS, eggDefaults);
|
||||
|
||||
export default eggs;
|
||||
@@ -1,32 +0,0 @@
|
||||
import {merge} from '../helpers';
|
||||
|
||||
//--------------------------------------------------
|
||||
// Eggs are generated from an array of pet keys
|
||||
//
|
||||
// <egg_key> : {
|
||||
// text: t(<type>Egg<egg_key>Text),
|
||||
// mountText: t(<type>Egg<egg_key>MountText),
|
||||
// notes: t(<type>Egg<egg_key>Text,{
|
||||
// eggText: this.text,
|
||||
// eggAdjective: t(<type>Egg<egg_key>Adjective)
|
||||
// }),
|
||||
// canBuy: <canBuy_boolean>,
|
||||
// value: 3,
|
||||
// key: <egg_key>,
|
||||
// }
|
||||
//
|
||||
// <egg_key> is the name of the pet associated with the egg
|
||||
// <type> is the type of egg (drop, quest, etc) passed in as part of an options object
|
||||
// <canBuy_boolean> is a boolean passed in as part of an options object
|
||||
//--------------------------------------------------
|
||||
|
||||
import dropEggs from './drops';
|
||||
import questEggs from './quest';
|
||||
|
||||
let allEggs = merge([dropEggs, questEggs]);
|
||||
|
||||
export default {
|
||||
allEggs: allEggs,
|
||||
dropEggs: dropEggs,
|
||||
questEggs: questEggs,
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import {generateEggs} from '../helpers';
|
||||
|
||||
const QUEST_EGGS = [
|
||||
'Gryphon',
|
||||
'Hedgehog',
|
||||
'Deer',
|
||||
'Egg',
|
||||
'Rat',
|
||||
'Octopus',
|
||||
'Seahorse',
|
||||
'Parrot',
|
||||
'Rooster',
|
||||
'Spider',
|
||||
'Owl',
|
||||
'Penguin',
|
||||
'TRex',
|
||||
'Rock',
|
||||
'Bunny',
|
||||
'Slime',
|
||||
'Sheep',
|
||||
'Cuttlefish',
|
||||
'Whale',
|
||||
'Cheetah',
|
||||
'Horse',
|
||||
'Frog'
|
||||
];
|
||||
|
||||
let eggDefaults = {
|
||||
type: 'quest',
|
||||
canBuy: (key) => {
|
||||
return _generateQuestAchievementRequirement(key);
|
||||
},
|
||||
};
|
||||
|
||||
let eggs = generateEggs(QUEST_EGGS, eggDefaults);
|
||||
|
||||
// Exceptions to normal defaults
|
||||
eggs.TRex.canBuy = (user) => {
|
||||
let achievements = user.achievements.quests;
|
||||
|
||||
if (achievements) {
|
||||
return achievements.trex > 0 ||
|
||||
achievements.trex_undead > 0;
|
||||
}
|
||||
}
|
||||
|
||||
eggs.Deer.canBuy = _generateQuestAchievementRequirement('ghost_stag');
|
||||
eggs.Seahorse.canBuy = _generateQuestAchievementRequirement('dilatory_derby');
|
||||
eggs.Parrot.canBuy = _generateQuestAchievementRequirement('harpy');
|
||||
eggs.Cuttlefish.canBuy = _generateQuestAchievementRequirement('kraken');
|
||||
|
||||
eggs.Egg.canBuy = () => { return false; }
|
||||
|
||||
function _generateQuestAchievementRequirement(name) {
|
||||
return (user) => {
|
||||
let achievements = user.achievements.quests;
|
||||
let questKey = name.toLowerCase();
|
||||
|
||||
if (achievements) {
|
||||
return achievements[questKey] > 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default eggs;
|
||||
@@ -1,24 +0,0 @@
|
||||
import {translator as t} from './helpers';
|
||||
|
||||
const NUMBER_OF_QUESTIONS = 12;
|
||||
|
||||
let faq = {};
|
||||
|
||||
faq.questions = [];
|
||||
|
||||
for (var i = 0; i <= NUMBER_OF_QUESTIONS; i++) {
|
||||
let question = {
|
||||
question: t('faqQuestion' + i),
|
||||
ios: t('iosFaqAnswer' + i),
|
||||
web: t('webFaqAnswer' + i)
|
||||
};
|
||||
|
||||
faq.questions.push(question);
|
||||
}
|
||||
|
||||
faq.stillNeedHelp = {
|
||||
ios: t('iosFaqStillNeedHelp'),
|
||||
web: t('webFaqStillNeedHelp')
|
||||
};
|
||||
|
||||
export default faq;
|
||||
@@ -1,54 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
setFoodDefaults
|
||||
} from '../helpers';
|
||||
|
||||
const CAN_BUY = true;
|
||||
const CAN_DROP = true;
|
||||
|
||||
let baseFood = {
|
||||
Meat: {
|
||||
target: 'Base',
|
||||
article: '',
|
||||
},
|
||||
Milk: {
|
||||
target: 'White',
|
||||
article: '',
|
||||
},
|
||||
Potatoe: {
|
||||
target: 'Desert',
|
||||
article: 'a ',
|
||||
},
|
||||
Strawberry: {
|
||||
target: 'Red',
|
||||
article: 'a ',
|
||||
},
|
||||
Chocolate: {
|
||||
target: 'Shade',
|
||||
article: '',
|
||||
},
|
||||
Fish: {
|
||||
target: 'Skeleton',
|
||||
article: 'a ',
|
||||
},
|
||||
RottenMeat: {
|
||||
target: 'Zombie',
|
||||
article: '',
|
||||
},
|
||||
CottonCandyPink: {
|
||||
target: 'CottonCandyPink',
|
||||
article: '',
|
||||
},
|
||||
CottonCandyBlue: {
|
||||
target: 'CottonCandyBlue',
|
||||
article: '',
|
||||
},
|
||||
Honey: {
|
||||
target: 'Golden',
|
||||
article: '',
|
||||
},
|
||||
};
|
||||
|
||||
setFoodDefaults(baseFood, {canBuy: CAN_BUY, canDrop: CAN_DROP});
|
||||
|
||||
export default baseFood;
|
||||
@@ -1,54 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
setFoodDefaults
|
||||
} from '../helpers';
|
||||
|
||||
const CAN_BUY = false;
|
||||
const CAN_DROP = false;
|
||||
|
||||
let cake = {
|
||||
Cake_Skeleton: {
|
||||
target: 'Skeleton',
|
||||
article: '',
|
||||
},
|
||||
Cake_Base: {
|
||||
target: 'Base',
|
||||
article: '',
|
||||
},
|
||||
Cake_CottonCandyBlue: {
|
||||
target: 'CottonCandyBlue',
|
||||
article: '',
|
||||
},
|
||||
Cake_CottonCandyPink: {
|
||||
target: 'CottonCandyPink',
|
||||
article: '',
|
||||
},
|
||||
Cake_Shade: {
|
||||
target: 'Shade',
|
||||
article: '',
|
||||
},
|
||||
Cake_White: {
|
||||
target: 'White',
|
||||
article: '',
|
||||
},
|
||||
Cake_Golden: {
|
||||
target: 'Golden',
|
||||
article: '',
|
||||
},
|
||||
Cake_Zombie: {
|
||||
target: 'Zombie',
|
||||
article: '',
|
||||
},
|
||||
Cake_Desert: {
|
||||
target: 'Desert',
|
||||
article: '',
|
||||
},
|
||||
Cake_Red: {
|
||||
target: 'Red',
|
||||
article: '',
|
||||
},
|
||||
};
|
||||
|
||||
setFoodDefaults(cake, {canBuy: CAN_BUY, canDrop: CAN_DROP});
|
||||
|
||||
export default cake;
|
||||
@@ -1,54 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
setFoodDefaults
|
||||
} from '../helpers';
|
||||
|
||||
const CAN_BUY = false;
|
||||
const CAN_DROP = false;
|
||||
|
||||
let candy = {
|
||||
Candy_Skeleton: {
|
||||
target: 'Skeleton',
|
||||
article: '',
|
||||
},
|
||||
Candy_Base: {
|
||||
target: 'Base',
|
||||
article: '',
|
||||
},
|
||||
Candy_CottonCandyBlue: {
|
||||
target: 'CottonCandyBlue',
|
||||
article: '',
|
||||
},
|
||||
Candy_CottonCandyPink: {
|
||||
target: 'CottonCandyPink',
|
||||
article: '',
|
||||
},
|
||||
Candy_Shade: {
|
||||
target: 'Shade',
|
||||
article: '',
|
||||
},
|
||||
Candy_White: {
|
||||
target: 'White',
|
||||
article: '',
|
||||
},
|
||||
Candy_Golden: {
|
||||
target: 'Golden',
|
||||
article: '',
|
||||
},
|
||||
Candy_Zombie: {
|
||||
target: 'Zombie',
|
||||
article: '',
|
||||
},
|
||||
Candy_Desert: {
|
||||
target: 'Desert',
|
||||
article: '',
|
||||
},
|
||||
Candy_Red: {
|
||||
target: 'Red',
|
||||
article: '',
|
||||
}
|
||||
};
|
||||
|
||||
setFoodDefaults(candy, {canBuy: CAN_BUY, canDrop: CAN_DROP});
|
||||
|
||||
export default candy;
|
||||
@@ -1,37 +0,0 @@
|
||||
import {each, defaults} from 'lodash';
|
||||
import {
|
||||
translator as t,
|
||||
merge
|
||||
} from '../helpers';
|
||||
|
||||
//--------------------------------------------------
|
||||
// Food are series objects that have defaults applied if not provided
|
||||
//
|
||||
// <food_key> : {
|
||||
// key: <food_key>,
|
||||
// text: t(food<formatted_key>),
|
||||
// notes: t(foodNotes),
|
||||
// article: <article>,
|
||||
// target: <target_key>,
|
||||
// value: <value>,
|
||||
// canBuy: <canBuy_boolean>,
|
||||
// canDrop: <canDrop_boolean>,
|
||||
// }
|
||||
//
|
||||
// <food_key> is the name of the food
|
||||
// <formatted_key> is a screeaming camelCase version of the key
|
||||
// <article> is whether the food requires an indefinite article ('a', 'an', '')
|
||||
// <target_key> is the potion key that this food targets
|
||||
// <value> is the price of the food - defaults to 1
|
||||
// <canBuy_boolean> is a boolean passed in as part of an options object
|
||||
// <canDrop_boolean> is a boolean passed in as part of an options object
|
||||
//--------------------------------------------------
|
||||
|
||||
import baseFood from './base';
|
||||
import saddle from './saddle';
|
||||
import cake from './birthday';
|
||||
import candy from './fall';
|
||||
|
||||
let allFood = merge([baseFood, saddle, cake, candy]);
|
||||
|
||||
export default allFood;
|
||||
@@ -1,19 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
setFoodDefaults
|
||||
} from '../helpers';
|
||||
|
||||
const CAN_BUY = true;
|
||||
const CAN_DROP = false;
|
||||
|
||||
let saddle = {
|
||||
Saddle: {
|
||||
value: 5,
|
||||
text: t('foodSaddleText'),
|
||||
notes: t('foodSaddleNotes'),
|
||||
},
|
||||
};
|
||||
|
||||
setFoodDefaults(saddle, {canBuy: CAN_BUY, canDrop: CAN_DROP});
|
||||
|
||||
export default saddle;
|
||||
@@ -1,59 +0,0 @@
|
||||
import {
|
||||
merge,
|
||||
translator as t,
|
||||
setHatchingPotionDefaults
|
||||
} from './helpers';
|
||||
|
||||
let dropPotions = {
|
||||
Base: {
|
||||
value: 2,
|
||||
},
|
||||
White: {
|
||||
value: 2,
|
||||
},
|
||||
Desert: {
|
||||
value: 2,
|
||||
},
|
||||
Red: {
|
||||
value: 3,
|
||||
},
|
||||
Shade: {
|
||||
value: 3,
|
||||
},
|
||||
Skeleton: {
|
||||
value: 3,
|
||||
},
|
||||
Zombie: {
|
||||
value: 4,
|
||||
},
|
||||
CottonCandyPink: {
|
||||
value: 4,
|
||||
},
|
||||
CottonCandyBlue: {
|
||||
value: 4,
|
||||
},
|
||||
Golden: {
|
||||
value: 5,
|
||||
},
|
||||
};
|
||||
|
||||
let premiumPotions = {
|
||||
Spooky: {
|
||||
value: 2,
|
||||
addlNotes: t('premiumPotionAddlNotes'),
|
||||
premium: true,
|
||||
limited: true,
|
||||
canBuy: () => { return false },
|
||||
},
|
||||
};
|
||||
|
||||
setHatchingPotionDefaults(dropPotions);
|
||||
setHatchingPotionDefaults(premiumPotions);
|
||||
|
||||
let allPotions = merge([dropPotions, premiumPotions]);
|
||||
|
||||
export default {
|
||||
all: allPotions,
|
||||
drop: dropPotions,
|
||||
premium: premiumPotions,
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
import {translator as t} from './helpers';
|
||||
|
||||
let potion = {
|
||||
type: 'potion',
|
||||
text: t('potionText'),
|
||||
notes: t('potionNotes'),
|
||||
value: 25,
|
||||
key: 'potion',
|
||||
};
|
||||
|
||||
export default potion;
|
||||
@@ -1,230 +0,0 @@
|
||||
import { each, defaults, assign, capitalize, camelCase } from 'lodash';
|
||||
|
||||
import i18n from '../i18n';
|
||||
|
||||
//----------------------------------------
|
||||
// Translator Helpers
|
||||
//----------------------------------------
|
||||
export function translator(string, vars={a: 'a'}) {
|
||||
let func = (lang) => {
|
||||
return i18n.t(string, vars, lang);
|
||||
};
|
||||
|
||||
func.i18nLangFunc = true; // Trick to recognize this type of function
|
||||
|
||||
return func;
|
||||
};
|
||||
|
||||
export function formatForTranslator(name) {
|
||||
let camelCasedName = camelCase(name);
|
||||
let capitalCamelCasedName = capitalize(camelCasedName);
|
||||
|
||||
return capitalCamelCasedName;
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
// Object Merger
|
||||
//----------------------------------------
|
||||
|
||||
export function merge(array=[]) {
|
||||
let mergedObject = {};
|
||||
|
||||
each(array, (item) => {
|
||||
assign(mergedObject, item);
|
||||
});
|
||||
|
||||
return mergedObject;
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
// Set Defaults Helpers
|
||||
//----------------------------------------
|
||||
|
||||
export function setSpellDefaults (className, spells) {
|
||||
let capitalClassName = formatForTranslator(className);
|
||||
|
||||
each(spells, (spell, key) => {
|
||||
let capitalSpellKey = formatForTranslator(key);
|
||||
let spellDefaults = {
|
||||
text: translator(`spell${capitalClassName}${capitalSpellKey}Text`),
|
||||
notes: translator(`spell${capitalClassName}${capitalSpellKey}Notes`),
|
||||
};
|
||||
|
||||
defaults(spell, spellDefaults);
|
||||
});
|
||||
};
|
||||
|
||||
export function setFoodDefaults(food, options={}) {
|
||||
each(food, (item, name) => {
|
||||
let formattedName = formatForTranslator(name);
|
||||
let canBuy = () => { return options.canBuy; };
|
||||
|
||||
defaults(item, {
|
||||
key: name,
|
||||
text: translator(`food${formattedName}`),
|
||||
notes: translator('foodNotes'),
|
||||
value: 1,
|
||||
canBuy: canBuy,
|
||||
canDrop: options.canDrop || false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export function setHatchingPotionDefaults(hatchingPotions) {
|
||||
each(hatchingPotions, (potion, key) => {
|
||||
let text = translator(`hatchingPotion${key}`);
|
||||
defaults(potion, {
|
||||
key: key,
|
||||
value: 2,
|
||||
text: text,
|
||||
canBuy: () => { return true },
|
||||
notes: translator('hatchingPotionNotes', {
|
||||
potText: text
|
||||
}),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export function setQuestDefaults(quests) {
|
||||
each(quests, function(quest, key) {
|
||||
let formattedName = formatForTranslator(key);
|
||||
|
||||
let questDefaults = {
|
||||
key: key,
|
||||
text: translator(`quest${formattedName}Text`),
|
||||
notes: translator(`quest${formattedName}Notes`),
|
||||
canBuy: () => { return true; },
|
||||
value: 4,
|
||||
};
|
||||
|
||||
let questBossDefaults = {
|
||||
name: translator(`quest${formattedName}Boss`),
|
||||
str: 1,
|
||||
def: 1,
|
||||
};
|
||||
|
||||
let questBossRageDefaults = {
|
||||
title: translator('bossRageTitle'),
|
||||
description: translator('bossRageDescription'),
|
||||
};
|
||||
|
||||
defaults(quest, questDefaults);
|
||||
|
||||
let boss = quest.boss;
|
||||
|
||||
if (boss) {
|
||||
defaults(boss, questBossDefaults);
|
||||
|
||||
if (boss.rage) {
|
||||
defaults(boss.rage, questBossRageDefaults);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export function setQuestSetDefaults(quests, mainDefaultsFunction, dropDefaultsFunction) {
|
||||
each(quests, (quest, name) => {
|
||||
let formattedName = formatForTranslator(name);
|
||||
let mainDefaults = mainDefaultsFunction(formattedName);
|
||||
|
||||
defaults(quest, mainDefaults);
|
||||
|
||||
if (quest.drop && dropDefaultsFunction) {
|
||||
let dropDefaults = dropDefaultsFunction(formattedName);
|
||||
defaults(quest.drop, dropDefaults);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export function setGearSetDefaults(gearSet, options={}) {
|
||||
let setName = formatForTranslator(options.setName);
|
||||
|
||||
each(gearSet, (gear, gearType) => {
|
||||
each(gear, (item, key) => {
|
||||
let formattedName = formatForTranslator(key);
|
||||
|
||||
let text = `${gearType}${setName}${formattedName}Text`;
|
||||
let notes = `${gearType}${setName}${formattedName}Notes`;
|
||||
let attributes = _getGearAttributes(item);
|
||||
let gearDefaults = {
|
||||
text: translator(text),
|
||||
notes: translator(notes, attributes),
|
||||
canBuy: () => { return false; },
|
||||
}
|
||||
|
||||
defaults(item, gearDefaults);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
// Generators
|
||||
//----------------------------------------
|
||||
|
||||
export function generateBackgrounds(sets) {
|
||||
each(sets, (names, set) => {
|
||||
sets[set] = {};
|
||||
|
||||
each(names, (name) => {
|
||||
let formattedName = formatForTranslator(name);
|
||||
|
||||
sets[set][name] = {
|
||||
text: translator(`background${formattedName}Text`),
|
||||
notes: translator(`background${formattedName}Notes`),
|
||||
};
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export function generateEggs(set, options={}) {
|
||||
let eggs = {};
|
||||
let type = options.type;
|
||||
|
||||
each(set, (pet) => {
|
||||
let text = translator(`${type}Egg${pet}Text`);
|
||||
let adj = translator(`${type}Egg${pet}Adjective`);
|
||||
let canBuy = options.canBuy(pet);
|
||||
|
||||
eggs[pet] = {
|
||||
text: text,
|
||||
mountText: translator(`${type}Egg${pet}MountText`),
|
||||
adjective: adj,
|
||||
canBuy: canBuy,
|
||||
value: 3,
|
||||
key: pet,
|
||||
notes: translator('eggNotes', {
|
||||
eggText: text,
|
||||
eggAdjective: adj,
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
return eggs;
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
// Spell Helpers
|
||||
//----------------------------------------
|
||||
|
||||
export function diminishingReturns(bonus, max, halfway=max/2) {
|
||||
return max * (bonus / (bonus + halfway));
|
||||
};
|
||||
|
||||
export function calculateBonus(value, stat, crit=1, stat_scale=0.5) {
|
||||
return (value < 0 ? 1 : value + 1) + (stat * stat_scale * crit);
|
||||
};
|
||||
|
||||
//----------------------------------------
|
||||
// Gear Helpers
|
||||
//----------------------------------------
|
||||
|
||||
function _getGearAttributes(gear) {
|
||||
let attr = {};
|
||||
|
||||
if (gear.str) { attr.str = gear.str };
|
||||
if (gear.con) { attr.con = gear.con };
|
||||
if (gear.int) { attr.int = gear.int };
|
||||
if (gear.per) { attr.per = gear.per };
|
||||
|
||||
return attr;
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
import classes from './classes';
|
||||
import mysterySets from './mystery-sets';
|
||||
import itemList from './item-list';
|
||||
import {
|
||||
tree as gearTree,
|
||||
flat as gearFlat,
|
||||
gearTypes,
|
||||
} from './gear/index';
|
||||
import timeTravelerStore from './time-traveler-store';
|
||||
import potion from './health-potion';
|
||||
import armoire from './armoire';
|
||||
import spells from './spells/index';
|
||||
import {special} from './spells/index';
|
||||
import cardTypes from './card-types';
|
||||
import {
|
||||
dropEggs,
|
||||
questEggs,
|
||||
allEggs,
|
||||
} from './eggs/index';
|
||||
import {
|
||||
dropPets,
|
||||
premiumPets,
|
||||
questPets,
|
||||
dropMounts,
|
||||
premiumMounts,
|
||||
questMounts,
|
||||
specialPets,
|
||||
specialMounts,
|
||||
} from './pets-mounts/index';
|
||||
import timeTravelStable from './time-traveler-stable';
|
||||
import {
|
||||
all as allHatchingPotions,
|
||||
drop as dropHatchingPotions,
|
||||
premium as premiumHatchingPotions,
|
||||
} from './hatching-potions';
|
||||
import food from './food/index';
|
||||
import {
|
||||
all as allQuests,
|
||||
canOwnCategories as userCanOwnQuestCategories,
|
||||
byLevel as questsByLevel
|
||||
} from './quests/index';
|
||||
import backgrounds from './backgrounds';
|
||||
import subscriptionBlocks from './subscription-blocks';
|
||||
import userDefaults from './user-defaults';
|
||||
import faq from './faq';
|
||||
|
||||
export default {
|
||||
// Constants
|
||||
classes: classes,
|
||||
gearTypes: gearTypes,
|
||||
mystery: mysterySets,
|
||||
itemList: itemList,
|
||||
userCanOwnQuestCategories: userCanOwnQuestCategories,
|
||||
|
||||
// Gear
|
||||
gear: {
|
||||
tree: gearTree,
|
||||
flat: gearFlat
|
||||
},
|
||||
|
||||
// Time Traveler Store
|
||||
timeTravelerStore: timeTravelerStore,
|
||||
timeTravelStable: timeTravelStable,
|
||||
|
||||
// Non-Gear Static Rewards
|
||||
potion: potion,
|
||||
armoire: armoire,
|
||||
|
||||
// Spells
|
||||
spells: spells,
|
||||
cardTypes: cardTypes,
|
||||
special: special,
|
||||
|
||||
// Item Drops
|
||||
dropHatchingPotions: dropHatchingPotions,
|
||||
premiumHatchingPotions: premiumHatchingPotions,
|
||||
hatchingPotions: allHatchingPotions,
|
||||
food: food,
|
||||
|
||||
// Eggs
|
||||
dropEggs: dropEggs,
|
||||
questEggs: questEggs,
|
||||
eggs: allEggs,
|
||||
|
||||
// Pets And Mounts
|
||||
pets: dropPets,
|
||||
premiumPets: premiumPets,
|
||||
questPets: questPets,
|
||||
mounts: dropMounts,
|
||||
premiumMounts: premiumMounts,
|
||||
questMounts: questMounts,
|
||||
specialPets: specialPets,
|
||||
specialMounts: specialMounts,
|
||||
|
||||
// Quests
|
||||
quests: allQuests,
|
||||
questsByLevel: questsByLevel,
|
||||
|
||||
// Backgrounds
|
||||
backgrounds: backgrounds,
|
||||
|
||||
// Subscription Blocks
|
||||
subscriptionBlocks: subscriptionBlocks,
|
||||
|
||||
// Default User Tasks
|
||||
userDefaults: userDefaults,
|
||||
|
||||
// Frequently Asked Questions
|
||||
faq: faq,
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
import {transform, defaults} from 'lodash';
|
||||
|
||||
//--------------------------------------------------
|
||||
// Pets and Mounts are generated by eggs * potions
|
||||
//
|
||||
// { <egg_key>-<potion_key>: true }
|
||||
//
|
||||
// <egg_key> - the key of the egg the animal hatched from
|
||||
// <potion_key> - the potion that hatched the animal
|
||||
//
|
||||
//--------------------------------------------------
|
||||
// Special Pets and Mounts
|
||||
// { <animal_type>-<fake_potion>: <transifex_key> }
|
||||
//
|
||||
// <animal_type> - could be existing animal or a totally new animal
|
||||
// <fake_potion> - if a unique animal, potion is Base, if it's a special version of an existing animal, the fake potion is a different from a normal hatching potion
|
||||
//--------------------------------------------------
|
||||
|
||||
import {
|
||||
drop as dropHatchingPotions,
|
||||
premium as premiumHatchingPotions,
|
||||
} from '../hatching-potions';
|
||||
import dropEggs from '../eggs/drops';
|
||||
import questEggs from '../eggs/quest';
|
||||
|
||||
import specialPets from './special-pets';
|
||||
import specialMounts from './special-mounts';
|
||||
|
||||
let dropPets = generateAnimalSet(dropEggs, dropHatchingPotions);
|
||||
let premiumPets = generateAnimalSet(dropEggs, premiumHatchingPotions);
|
||||
let questPets = generateAnimalSet(questEggs, dropHatchingPotions);
|
||||
let dropMounts = generateAnimalSet(dropEggs, dropHatchingPotions);
|
||||
let premiumMounts = generateAnimalSet(dropEggs, premiumHatchingPotions);
|
||||
let questMounts = generateAnimalSet(questEggs, dropHatchingPotions);
|
||||
|
||||
function generateAnimalSet(eggSet, potionSet) {
|
||||
return transform(eggSet, (m, egg) => {
|
||||
defaults(m, transform(potionSet, (m2, pot) => {
|
||||
return m2[egg.key + "-" + pot.key] = true;
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
export default {
|
||||
dropPets: dropPets,
|
||||
dropMounts: dropMounts,
|
||||
premiumPets: premiumPets,
|
||||
premiumMounts: premiumMounts,
|
||||
questPets: questPets,
|
||||
questMounts: questMounts,
|
||||
specialPets: specialPets,
|
||||
specialMounts: specialMounts,
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
let specialMounts = {
|
||||
'BearCub-Polar': 'polarBear',
|
||||
'LionCub-Ethereal': 'etherealLion',
|
||||
'MantisShrimp-Base': 'mantisShrimp',
|
||||
'Turkey-Base': 'turkey',
|
||||
'Mammoth-Base': 'mammoth',
|
||||
'Orca-Base': 'orca',
|
||||
'Gryphon-RoyalPurple': 'royalPurpleGryphon',
|
||||
'Phoenix-Base': 'phoenix',
|
||||
'JackOLantern-Base': 'jackolantern'
|
||||
}
|
||||
|
||||
export default specialMounts;
|
||||
@@ -1,14 +0,0 @@
|
||||
let specialPets = {
|
||||
'Wolf-Veteran': 'veteranWolf',
|
||||
'Wolf-Cerberus': 'cerberusPup',
|
||||
'Dragon-Hydra': 'hydra',
|
||||
'Turkey-Base': 'turkey',
|
||||
'BearCub-Polar': 'polarBearPup',
|
||||
'MantisShrimp-Base': 'mantisShrimp',
|
||||
'JackOLantern-Base': 'jackolantern',
|
||||
'Mammoth-Base': 'mammoth',
|
||||
'Tiger-Veteran': 'veteranTiger',
|
||||
'Phoenix-Base': 'phoenix'
|
||||
}
|
||||
|
||||
export default specialPets;
|
||||
@@ -1,116 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
merge,
|
||||
setQuestSetDefaults,
|
||||
} from '../helpers';
|
||||
|
||||
let dilatoryDistressSeries = {
|
||||
dilatoryDistress1: {
|
||||
goldValue: 200,
|
||||
collect: {
|
||||
fireCoral: {
|
||||
text: t('questDilatoryDistress1CollectFireCoral'),
|
||||
count: 25
|
||||
},
|
||||
blueFins: {
|
||||
text: t('questDilatoryDistress1CollectBlueFins'),
|
||||
count: 25
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'gear',
|
||||
key: 'armor_special_finnedOceanicArmor',
|
||||
text: t('questDilatoryDistress1DropArmor')
|
||||
}
|
||||
],
|
||||
exp: 75
|
||||
}
|
||||
},
|
||||
dilatoryDistress2: {
|
||||
previous: 'dilatoryDistress1',
|
||||
goldValue: 300,
|
||||
boss: {
|
||||
hp: 500,
|
||||
rage: {
|
||||
title: t('questDilatoryDistress2RageTitle'),
|
||||
description: t('questDilatoryDistress2RageDescription'),
|
||||
value: 50,
|
||||
healing: .3,
|
||||
effect: t('questDilatoryDistress2RageEffect')
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'hatchingPotions',
|
||||
key: 'Skeleton',
|
||||
text: t('questDilatoryDistress2DropSkeletonPotion')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'CottonCandyBlue',
|
||||
text: t('questDilatoryDistress2DropCottonCandyBluePotion')
|
||||
}, {
|
||||
type: 'gear',
|
||||
key: 'head_special_fireCoralCirclet',
|
||||
text: t('questDilatoryDistress2DropHeadgear')
|
||||
}
|
||||
],
|
||||
exp: 500
|
||||
}
|
||||
},
|
||||
dilatoryDistress3: {
|
||||
previous: 'dilatoryDistress2',
|
||||
goldValue: 400,
|
||||
boss: {
|
||||
hp: 1000,
|
||||
str: 2
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'food',
|
||||
key: 'Fish',
|
||||
text: t('questDilatoryDistress3DropFish')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Fish',
|
||||
text: t('questDilatoryDistress3DropFish')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Fish',
|
||||
text: t('questDilatoryDistress3DropFish')
|
||||
}, {
|
||||
type: 'gear',
|
||||
key: 'weapon_special_tridentOfCrashingTides',
|
||||
text: t('questDilatoryDistress3DropWeapon')
|
||||
}, {
|
||||
type: 'gear',
|
||||
key: 'shield_special_moonpearlShield',
|
||||
text: t('questDilatoryDistress3DropShield')
|
||||
}
|
||||
],
|
||||
exp: 650
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let goldPurchasableQuests = merge([dilatoryDistressSeries]);
|
||||
|
||||
let questDefaults = (name) => {
|
||||
return {
|
||||
completion: t(`quest${name}Completion`),
|
||||
category: 'gold',
|
||||
}
|
||||
};
|
||||
|
||||
let dropDefaults = () => {
|
||||
return {
|
||||
gp: 0,
|
||||
}
|
||||
};
|
||||
|
||||
setQuestSetDefaults(goldPurchasableQuests, questDefaults, dropDefaults);
|
||||
|
||||
export default goldPurchasableQuests;
|
||||
@@ -1,126 +0,0 @@
|
||||
import {each, defaults} from 'lodash';
|
||||
import {
|
||||
translator as t,
|
||||
setQuestSetDefaults,
|
||||
} from '../helpers';
|
||||
|
||||
let holidayQuests = {
|
||||
evilsanta: {
|
||||
text: t('questEvilSantaText'),
|
||||
notes: t('questEvilSantaNotes'),
|
||||
completion: t('questEvilSantaCompletion'),
|
||||
boss: {
|
||||
name: t('questEvilSantaBoss'),
|
||||
hp: 300,
|
||||
str: 1
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'mounts',
|
||||
key: 'BearCub-Polar',
|
||||
text: t('questEvilSantaDropBearCubPolarMount')
|
||||
}
|
||||
],
|
||||
gp: 20,
|
||||
exp: 100
|
||||
}
|
||||
},
|
||||
evilsanta2: {
|
||||
text: t('questEvilSanta2Text'),
|
||||
notes: t('questEvilSanta2Notes'),
|
||||
completion: t('questEvilSanta2Completion'),
|
||||
collect: {
|
||||
tracks: {
|
||||
text: t('questEvilSanta2CollectTracks'),
|
||||
count: 20
|
||||
},
|
||||
branches: {
|
||||
text: t('questEvilSanta2CollectBranches'),
|
||||
count: 10
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'pets',
|
||||
key: 'BearCub-Polar',
|
||||
text: t('questEvilSanta2DropBearCubPolarPet')
|
||||
}
|
||||
],
|
||||
gp: 20,
|
||||
exp: 100
|
||||
}
|
||||
},
|
||||
egg: {
|
||||
text: t('questEggHuntText'),
|
||||
notes: t('questEggHuntNotes'),
|
||||
completion: t('questEggHuntCompletion'),
|
||||
value: 1,
|
||||
collect: {
|
||||
plainEgg: {
|
||||
text: t('questEggHuntCollectPlainEgg'),
|
||||
count: 100
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Egg',
|
||||
text: t('questEggHuntDropPlainEgg')
|
||||
}
|
||||
],
|
||||
gp: 0,
|
||||
exp: 0
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let questDefaults = (name) => {
|
||||
return {
|
||||
completion: t(`quest${name}Completion`),
|
||||
canBuy: () => { return false; },
|
||||
category: 'pet',
|
||||
}
|
||||
};
|
||||
|
||||
setQuestSetDefaults(holidayQuests, questDefaults);
|
||||
|
||||
export default holidayQuests;
|
||||
@@ -1,75 +0,0 @@
|
||||
import {sortBy} from 'lodash';
|
||||
import {
|
||||
merge,
|
||||
setQuestDefaults,
|
||||
} from '../helpers';
|
||||
|
||||
//--------------------------------------------------
|
||||
// Quests are series objects that have defaults applied if not provided
|
||||
//
|
||||
// <quest_key> : {
|
||||
// key: <quest_key>,
|
||||
// text: t(quest<formatted_key>text),
|
||||
// notes: t(quest<formatted_key>notes),
|
||||
// canBuy: <canBuy_boolean>,
|
||||
// value: <value>,
|
||||
// boss: <boss_values>
|
||||
// drop: <drop_values>
|
||||
// }
|
||||
//
|
||||
// <quest_key> is the name of the quest
|
||||
// <formatted_key> is a screeaming camelCase version of the key
|
||||
// <canBuy_boolean> is a boolean passed in as part of an options object
|
||||
// <value> is the price of the quest in gems - defaults to 4
|
||||
// <boss_value> only applies to boss quests. An object in this form: {
|
||||
// name: t(quest<formatted_key>Boss),
|
||||
// str: <str_value>,
|
||||
// def: <def_value>,
|
||||
// rage: <rage_values>,
|
||||
// }
|
||||
// <rage_values> only applies to boss quests with rage. An object in this form: {
|
||||
// title: t('bossRageTitle'),
|
||||
// description: t('bossRageDescription')
|
||||
// }
|
||||
// <drop_values> only applies if quest has drops. An object in this form: {
|
||||
// items: <item_array>,
|
||||
// gp: <gp>,
|
||||
// exp: <exp>,
|
||||
// unlock: t(quest<formatted_key>UnlockText),
|
||||
// }
|
||||
// <item_array> an array of objects representing the items that will be dropped
|
||||
// <gp> the amount of gp awarded for completing the quest
|
||||
// <exp> the amount of exp awareded for completing the quest
|
||||
//--------------------------------------------------
|
||||
|
||||
import worldQuests from './world';
|
||||
import holidayQuests from './holiday';
|
||||
import petQuests from './pet';
|
||||
import unlockableQuests from './unlockable';
|
||||
import goldPurchasableQuests from './gold-purchasable';
|
||||
|
||||
let allQuests = merge([
|
||||
worldQuests,
|
||||
holidayQuests,
|
||||
petQuests,
|
||||
unlockableQuests,
|
||||
goldPurchasableQuests
|
||||
]);
|
||||
|
||||
setQuestDefaults(allQuests);
|
||||
|
||||
let questsByLevel = sortBy(allQuests, (quest) => {
|
||||
return quest.lvl || 0;
|
||||
});
|
||||
|
||||
let canOwnCategories = [
|
||||
'unlockable',
|
||||
'gold',
|
||||
'pet',
|
||||
];
|
||||
|
||||
export default {
|
||||
all: allQuests,
|
||||
byLevel: questsByLevel,
|
||||
canOwnCategories: canOwnCategories,
|
||||
};
|
||||
@@ -1,367 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
setQuestSetDefaults,
|
||||
} from '../helpers';
|
||||
|
||||
let petQuests = {
|
||||
gryphon: {
|
||||
boss: {
|
||||
hp: 300,
|
||||
str: 1.5,
|
||||
},
|
||||
drop: {
|
||||
gp: 25,
|
||||
exp: 125,
|
||||
}
|
||||
},
|
||||
hedgehog: {
|
||||
boss: {
|
||||
hp: 400,
|
||||
str: 1.25
|
||||
},
|
||||
drop: {
|
||||
gp: 30,
|
||||
exp: 125,
|
||||
}
|
||||
},
|
||||
ghost_stag: {
|
||||
boss: {
|
||||
hp: 1200,
|
||||
str: 2.5
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'eggs',
|
||||
key: 'Deer',
|
||||
text: t('questGhostStagDropDeerEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Deer',
|
||||
text: t('questGhostStagDropDeerEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Deer',
|
||||
text: t('questGhostStagDropDeerEgg')
|
||||
}
|
||||
],
|
||||
gp: 80,
|
||||
exp: 800,
|
||||
}
|
||||
},
|
||||
rat: {
|
||||
boss: {
|
||||
hp: 1200,
|
||||
str: 2.5
|
||||
},
|
||||
drop: {
|
||||
gp: 80,
|
||||
exp: 800,
|
||||
}
|
||||
},
|
||||
octopus: {
|
||||
boss: {
|
||||
hp: 1200,
|
||||
str: 2.5
|
||||
},
|
||||
drop: {
|
||||
gp: 80,
|
||||
exp: 800,
|
||||
}
|
||||
},
|
||||
dilatory_derby: {
|
||||
text: t('questSeahorseText'),
|
||||
notes: t('questSeahorseNotes'),
|
||||
completion: t('questSeahorseCompletion'),
|
||||
boss: {
|
||||
name: t('questSeahorseBoss'),
|
||||
hp: 300,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'eggs',
|
||||
key: 'Seahorse',
|
||||
text: t('questSeahorseDropSeahorseEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Seahorse',
|
||||
text: t('questSeahorseDropSeahorseEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Seahorse',
|
||||
text: t('questSeahorseDropSeahorseEgg')
|
||||
}
|
||||
],
|
||||
gp: 25,
|
||||
exp: 125,
|
||||
unlock: t('questSeahorseUnlockText')
|
||||
}
|
||||
},
|
||||
harpy: {
|
||||
boss: {
|
||||
hp: 600,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'eggs',
|
||||
key: 'Parrot',
|
||||
text: t('questHarpyDropParrotEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Parrot',
|
||||
text: t('questHarpyDropParrotEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Parrot',
|
||||
text: t('questHarpyDropParrotEgg')
|
||||
}
|
||||
],
|
||||
gp: 43,
|
||||
exp: 350,
|
||||
}
|
||||
},
|
||||
rooster: {
|
||||
boss: {
|
||||
hp: 300,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 25,
|
||||
exp: 125,
|
||||
}
|
||||
},
|
||||
spider: {
|
||||
boss: {
|
||||
hp: 400,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 31,
|
||||
exp: 200,
|
||||
}
|
||||
},
|
||||
owl: {
|
||||
boss: {
|
||||
hp: 500,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 37,
|
||||
exp: 275,
|
||||
}
|
||||
},
|
||||
penguin: {
|
||||
boss: {
|
||||
hp: 400,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 31,
|
||||
exp: 200,
|
||||
}
|
||||
},
|
||||
trex: {
|
||||
text: t('questTRexText'),
|
||||
notes: t('questTRexNotes'),
|
||||
completion: t('questTRexCompletion'),
|
||||
boss: {
|
||||
name: t('questTRexBoss'),
|
||||
hp: 800,
|
||||
str: 2
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'eggs',
|
||||
key: 'TRex',
|
||||
text: t('questTRexDropTRexEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'TRex',
|
||||
text: t('questTRexDropTRexEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'TRex',
|
||||
text: t('questTRexDropTRexEgg')
|
||||
}
|
||||
],
|
||||
gp: 55,
|
||||
exp: 500,
|
||||
unlock: t('questTRexUnlockText')
|
||||
}
|
||||
},
|
||||
trex_undead: {
|
||||
text: t('questTRexUndeadText'),
|
||||
notes: t('questTRexUndeadNotes'),
|
||||
completion: t('questTRexUndeadCompletion'),
|
||||
boss: {
|
||||
name: t('questTRexUndeadBoss'),
|
||||
hp: 500,
|
||||
str: 2,
|
||||
rage: {
|
||||
title: t('questTRexUndeadRageTitle'),
|
||||
description: t('questTRexUndeadRageDescription'),
|
||||
value: 50,
|
||||
healing: .3,
|
||||
effect: t('questTRexUndeadRageEffect')
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'eggs',
|
||||
key: 'TRex',
|
||||
text: t('questTRexDropTRexEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'TRex',
|
||||
text: t('questTRexDropTRexEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'TRex',
|
||||
text: t('questTRexDropTRexEgg')
|
||||
}
|
||||
],
|
||||
gp: 55,
|
||||
exp: 500,
|
||||
unlock: t('questTRexUnlockText')
|
||||
}
|
||||
},
|
||||
rock: {
|
||||
boss: {
|
||||
hp: 400,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 31,
|
||||
exp: 200,
|
||||
}
|
||||
},
|
||||
bunny: {
|
||||
boss: {
|
||||
hp: 300,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 25,
|
||||
exp: 125,
|
||||
}
|
||||
},
|
||||
slime: {
|
||||
boss: {
|
||||
hp: 400,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 31,
|
||||
exp: 200,
|
||||
}
|
||||
},
|
||||
sheep: {
|
||||
boss: {
|
||||
hp: 300,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 25,
|
||||
exp: 125,
|
||||
}
|
||||
},
|
||||
kraken: {
|
||||
boss: {
|
||||
hp: 800,
|
||||
str: 2
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'eggs',
|
||||
key: 'Cuttlefish',
|
||||
text: t('questKrakenDropCuttlefishEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Cuttlefish',
|
||||
text: t('questKrakenDropCuttlefishEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Cuttlefish',
|
||||
text: t('questKrakenDropCuttlefishEgg')
|
||||
}
|
||||
],
|
||||
gp: 55,
|
||||
exp: 500,
|
||||
}
|
||||
},
|
||||
whale: {
|
||||
boss: {
|
||||
hp: 500,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 37,
|
||||
exp: 275,
|
||||
}
|
||||
},
|
||||
cheetah: {
|
||||
boss: {
|
||||
hp: 600,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 43,
|
||||
exp: 350,
|
||||
}
|
||||
},
|
||||
horse: {
|
||||
boss: {
|
||||
hp: 500,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 37,
|
||||
exp: 275,
|
||||
}
|
||||
},
|
||||
frog: {
|
||||
boss: {
|
||||
hp: 300,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
gp: 25,
|
||||
exp: 125,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let questDefaults = (name) => {
|
||||
return {
|
||||
completion: t(`quest${name}Completion`),
|
||||
category: 'pet',
|
||||
}
|
||||
};
|
||||
|
||||
let dropDefaults = (name) => {
|
||||
let eggReward = {
|
||||
type: 'eggs',
|
||||
key: name,
|
||||
text: t(`quest${name}Drop${name}Egg`)
|
||||
};
|
||||
|
||||
return {
|
||||
items: [
|
||||
eggReward,
|
||||
eggReward,
|
||||
eggReward
|
||||
],
|
||||
unlock: t(`quest${name}UnlockText`),
|
||||
};
|
||||
};
|
||||
|
||||
setQuestSetDefaults(petQuests, questDefaults, dropDefaults);
|
||||
|
||||
export default petQuests;
|
||||
@@ -1,362 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
merge,
|
||||
setQuestSetDefaults,
|
||||
} from '../helpers';
|
||||
|
||||
let inviteFriends = {
|
||||
basilist: {
|
||||
unlockCondition: {
|
||||
condition: 'party invite',
|
||||
text: t('inviteFriends')
|
||||
},
|
||||
boss: {
|
||||
hp: 100,
|
||||
str: 0.5
|
||||
},
|
||||
drop: {
|
||||
gp: 8,
|
||||
exp: 42
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let viceSeries = {
|
||||
vice1: {
|
||||
lvl: 30,
|
||||
boss: {
|
||||
hp: 750,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'quests',
|
||||
key: 'vice2',
|
||||
text: t('questVice1DropVice2Quest')
|
||||
}
|
||||
],
|
||||
gp: 20,
|
||||
exp: 100
|
||||
}
|
||||
},
|
||||
vice2: {
|
||||
lvl: 30,
|
||||
previous: 'vice1',
|
||||
collect: {
|
||||
lightCrystal: {
|
||||
text: t('questVice2CollectLightCrystal'),
|
||||
count: 45
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'quests',
|
||||
key: 'vice3',
|
||||
text: t('questVice2DropVice3Quest')
|
||||
}
|
||||
],
|
||||
gp: 20,
|
||||
exp: 75
|
||||
}
|
||||
},
|
||||
vice3: {
|
||||
completion: t('questVice3Completion'),
|
||||
previous: 'vice2',
|
||||
lvl: 30,
|
||||
boss: {
|
||||
hp: 1500,
|
||||
str: 3
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'gear',
|
||||
key: 'weapon_special_2',
|
||||
text: t('questVice3DropWeaponSpecial2')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Dragon',
|
||||
text: t('questVice3DropDragonEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Dragon',
|
||||
text: t('questVice3DropDragonEgg')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Shade',
|
||||
text: t('questVice3DropShadeHatchingPotion')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Shade',
|
||||
text: t('questVice3DropShadeHatchingPotion')
|
||||
}
|
||||
],
|
||||
gp: 100,
|
||||
exp: 1000
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let atomSeries = {
|
||||
atom1: {
|
||||
lvl: 15,
|
||||
collect: {
|
||||
soapBars: {
|
||||
text: t('questAtom1CollectSoapBars'),
|
||||
count: 20
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'quests',
|
||||
key: 'atom2',
|
||||
text: t('questAtom1Drop')
|
||||
}
|
||||
],
|
||||
gp: 7,
|
||||
exp: 50
|
||||
}
|
||||
},
|
||||
atom2: {
|
||||
previous: 'atom1',
|
||||
lvl: 15,
|
||||
boss: {
|
||||
hp: 300,
|
||||
str: 1
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'quests',
|
||||
key: 'atom3',
|
||||
text: t('questAtom2Drop')
|
||||
}
|
||||
],
|
||||
gp: 20,
|
||||
exp: 100
|
||||
}
|
||||
},
|
||||
atom3: {
|
||||
previous: 'atom2',
|
||||
completion: t('questAtom3Completion'),
|
||||
lvl: 15,
|
||||
boss: {
|
||||
hp: 800,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'gear',
|
||||
key: 'head_special_2',
|
||||
text: t('headSpecial2Text')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Base',
|
||||
text: t('questAtom3DropPotion')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Base',
|
||||
text: t('questAtom3DropPotion')
|
||||
}
|
||||
],
|
||||
gp: 25,
|
||||
exp: 125
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let moonstoneSeries = {
|
||||
moonstone1: {
|
||||
lvl: 60,
|
||||
collect: {
|
||||
moonstone: {
|
||||
text: t('questMoonstone1CollectMoonstone'),
|
||||
count: 500
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'quests',
|
||||
key: 'moonstone2',
|
||||
text: t('questMoonstone1DropMoonstone2Quest')
|
||||
}
|
||||
],
|
||||
gp: 50,
|
||||
exp: 100
|
||||
}
|
||||
},
|
||||
moonstone2: {
|
||||
lvl: 60,
|
||||
previous: 'moonstone1',
|
||||
boss: {
|
||||
hp: 1500,
|
||||
str: 3
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'quests',
|
||||
key: 'moonstone3',
|
||||
text: t('questMoonstone2DropMoonstone3Quest')
|
||||
}
|
||||
],
|
||||
gp: 500,
|
||||
exp: 1000
|
||||
}
|
||||
},
|
||||
moonstone3: {
|
||||
completion: t('questMoonstone3Completion'),
|
||||
previous: 'moonstone2',
|
||||
lvl: 60,
|
||||
boss: {
|
||||
hp: 2000,
|
||||
str: 3.5
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'gear',
|
||||
key: 'armor_special_2',
|
||||
text: t('armorSpecial2Text')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'RottenMeat',
|
||||
text: t('questMoonstone3DropRottenMeat')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'RottenMeat',
|
||||
text: t('questMoonstone3DropRottenMeat')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'RottenMeat',
|
||||
text: t('questMoonstone3DropRottenMeat')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'RottenMeat',
|
||||
text: t('questMoonstone3DropRottenMeat')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'RottenMeat',
|
||||
text: t('questMoonstone3DropRottenMeat')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Zombie',
|
||||
text: t('questMoonstone3DropZombiePotion')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Zombie',
|
||||
text: t('questMoonstone3DropZombiePotion')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Zombie',
|
||||
text: t('questMoonstone3DropZombiePotion')
|
||||
}
|
||||
],
|
||||
gp: 900,
|
||||
exp: 1500
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let goldenKnightSeries = {
|
||||
goldenknight1: {
|
||||
lvl: 40,
|
||||
collect: {
|
||||
testimony: {
|
||||
text: t('questGoldenknight1CollectTestimony'),
|
||||
count: 300
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'quests',
|
||||
key: 'goldenknight2',
|
||||
text: t('questGoldenknight1DropGoldenknight2Quest')
|
||||
}
|
||||
],
|
||||
gp: 15,
|
||||
exp: 120
|
||||
}
|
||||
},
|
||||
goldenknight2: {
|
||||
previous: 'goldenknight1',
|
||||
lvl: 40,
|
||||
boss: {
|
||||
hp: 1000,
|
||||
str: 3
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'quests',
|
||||
key: 'goldenknight3',
|
||||
text: t('questGoldenknight2DropGoldenknight3Quest')
|
||||
}
|
||||
],
|
||||
gp: 75,
|
||||
exp: 750
|
||||
}
|
||||
},
|
||||
goldenknight3: {
|
||||
completion: t('questGoldenknight3Completion'),
|
||||
previous: 'goldenknight2',
|
||||
lvl: 40,
|
||||
boss: {
|
||||
hp: 1700,
|
||||
str: 3.5
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'food',
|
||||
key: 'Honey',
|
||||
text: t('questGoldenknight3DropHoney')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Honey',
|
||||
text: t('questGoldenknight3DropHoney')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Honey',
|
||||
text: t('questGoldenknight3DropHoney')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Golden',
|
||||
text: t('questGoldenknight3DropGoldenPotion')
|
||||
}, {
|
||||
type: 'hatchingPotions',
|
||||
key: 'Golden',
|
||||
text: t('questGoldenknight3DropGoldenPotion')
|
||||
}, {
|
||||
type: 'gear',
|
||||
key: 'shield_special_goldenknight',
|
||||
text: t('questGoldenknight3DropWeapon')
|
||||
}
|
||||
],
|
||||
gp: 900,
|
||||
exp: 1500
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let unlockableQuests = merge([
|
||||
inviteFriends,
|
||||
atomSeries,
|
||||
viceSeries,
|
||||
moonstoneSeries,
|
||||
goldenKnightSeries,
|
||||
]);
|
||||
|
||||
let questDefaults = () => {
|
||||
return { category: 'unlockable' }
|
||||
};
|
||||
|
||||
setQuestSetDefaults(unlockableQuests, questDefaults);
|
||||
|
||||
export default unlockableQuests;
|
||||
@@ -1,242 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
setQuestSetDefaults,
|
||||
} from '../helpers';
|
||||
|
||||
let worldQuests = {
|
||||
dilatory: {
|
||||
boss: {
|
||||
name: t('questDilatoryBoss'),
|
||||
hp: 5000000,
|
||||
str: 1,
|
||||
def: 1,
|
||||
rage: {
|
||||
title: t('questDilatoryBossRageTitle'),
|
||||
description: t('questDilatoryBossRageDescription'),
|
||||
value: 4000000,
|
||||
tavern: t('questDilatoryBossRageTavern'),
|
||||
stables: t('questDilatoryBossRageStables'),
|
||||
market: t('questDilatoryBossRageMarket')
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'pets',
|
||||
key: 'MantisShrimp-Base',
|
||||
text: t('questDilatoryDropMantisShrimpPet')
|
||||
}, {
|
||||
type: 'mounts',
|
||||
key: 'MantisShrimp-Base',
|
||||
text: t('questDilatoryDropMantisShrimpMount')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Meat',
|
||||
text: t('foodMeat')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Milk',
|
||||
text: t('foodMilk')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Potatoe',
|
||||
text: t('foodPotatoe')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Strawberry',
|
||||
text: t('foodStrawberry')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Chocolate',
|
||||
text: t('foodChocolate')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Fish',
|
||||
text: t('foodFish')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'RottenMeat',
|
||||
text: t('foodRottenMeat')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'CottonCandyPink',
|
||||
text: t('foodCottonCandyPink')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'CottonCandyBlue',
|
||||
text: t('foodCottonCandyBlue')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Honey',
|
||||
text: t('foodHoney')
|
||||
}
|
||||
],
|
||||
gp: 0,
|
||||
exp: 0
|
||||
}
|
||||
},
|
||||
stressbeast: {
|
||||
completionChat: t('questStressbeastCompletionChat'),
|
||||
boss: {
|
||||
name: t('questStressbeastBoss'),
|
||||
hp: 2750000,
|
||||
str: 1,
|
||||
def: 1,
|
||||
rage: {
|
||||
title: t('questStressbeastBossRageTitle'),
|
||||
description: t('questStressbeastBossRageDescription'),
|
||||
value: 1450000,
|
||||
healing: .3,
|
||||
stables: t('questStressbeastBossRageStables'),
|
||||
bailey: t('questStressbeastBossRageBailey'),
|
||||
guide: t('questStressbeastBossRageGuide')
|
||||
},
|
||||
desperation: {
|
||||
threshold: 500000,
|
||||
str: 3.5,
|
||||
def: 2,
|
||||
text: t('questStressbeastDesperation')
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'pets',
|
||||
key: 'Mammoth-Base',
|
||||
text: t('questStressbeastDropMammothPet')
|
||||
}, {
|
||||
type: 'mounts',
|
||||
key: 'Mammoth-Base',
|
||||
text: t('questStressbeastDropMammothMount')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Meat',
|
||||
text: t('foodMeat')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Milk',
|
||||
text: t('foodMilk')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Potatoe',
|
||||
text: t('foodPotatoe')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Strawberry',
|
||||
text: t('foodStrawberry')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Chocolate',
|
||||
text: t('foodChocolate')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Fish',
|
||||
text: t('foodFish')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'RottenMeat',
|
||||
text: t('foodRottenMeat')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'CottonCandyPink',
|
||||
text: t('foodCottonCandyPink')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'CottonCandyBlue',
|
||||
text: t('foodCottonCandyBlue')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Honey',
|
||||
text: t('foodHoney')
|
||||
}
|
||||
],
|
||||
gp: 0,
|
||||
exp: 0
|
||||
}
|
||||
},
|
||||
burnout: {
|
||||
completionChat: t('questBurnoutCompletionChat'),
|
||||
boss: {
|
||||
name: t('questBurnoutBoss'),
|
||||
hp: 11000000,
|
||||
str: 2.5,
|
||||
def: 1,
|
||||
rage: {
|
||||
title: t('questBurnoutBossRageTitle'),
|
||||
description: t('questBurnoutBossRageDescription'),
|
||||
value: 1000000,
|
||||
quests: t('questBurnoutBossRageQuests'),
|
||||
seasonalShop: t('questBurnoutBossRageSeasonalShop'),
|
||||
tavern: t('questBurnoutBossRageTavern')
|
||||
}
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'pets',
|
||||
key: 'Phoenix-Base',
|
||||
text: t('questBurnoutDropPhoenixPet')
|
||||
}, {
|
||||
type: 'mounts',
|
||||
key: 'Phoenix-Base',
|
||||
text: t('questBurnoutDropPhoenixMount')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_Base',
|
||||
text: t('foodCandyBase')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_White',
|
||||
text: t('foodCandyWhite')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_Desert',
|
||||
text: t('foodCandyDesert')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_Red',
|
||||
text: t('foodCandyRed')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_Shade',
|
||||
text: t('foodCandyShade')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_Skeleton',
|
||||
text: t('foodCandySkeleton')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_Zombie',
|
||||
text: t('foodCandyZombie')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_CottonCandyPink',
|
||||
text: t('foodCandyCottonCandyPink')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_CottonCandyBlue',
|
||||
text: t('foodCandyCottonCandyBlue')
|
||||
}, {
|
||||
type: 'food',
|
||||
key: 'Candy_Golden',
|
||||
text: t('foodCandyGolden')
|
||||
}
|
||||
],
|
||||
gp: 0,
|
||||
exp: 0
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let questDefaults = (name) => {
|
||||
return {
|
||||
completion: t(`quest${name}Completion`),
|
||||
value: 0,
|
||||
canBuy: () => { return false; },
|
||||
category: 'world',
|
||||
}
|
||||
};
|
||||
|
||||
setQuestSetDefaults(worldQuests, questDefaults);
|
||||
|
||||
export default worldQuests;
|
||||
@@ -1,78 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
diminishingReturns,
|
||||
calculateBonus,
|
||||
setSpellDefaults
|
||||
} from '../helpers';
|
||||
|
||||
import {each} from 'lodash';
|
||||
|
||||
let heal = {
|
||||
mana: 15,
|
||||
lvl: 11,
|
||||
target: 'self',
|
||||
cast: (user, target) => {
|
||||
user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .075;
|
||||
if (user.stats.hp > 50) {
|
||||
return user.stats.hp = 50;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let brightness = {
|
||||
mana: 15,
|
||||
lvl: 12,
|
||||
target: 'self',
|
||||
cast: (user, target) => {
|
||||
return each(user.tasks, (target) => {
|
||||
if (target.type === 'reward') {
|
||||
return;
|
||||
}
|
||||
return target.value += 4 * (user._statsComputed.int / (user._statsComputed.int + 40));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let protectAura = {
|
||||
mana: 30,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
cast: (user, target) => {
|
||||
return each(target, (member) => {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if ((base = member.stats.buffs).con == null) {
|
||||
base.con = 0;
|
||||
}
|
||||
return member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 200, 200));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let healAll = {
|
||||
mana: 25,
|
||||
lvl: 14,
|
||||
text: t('spellHealerHealAllText'),
|
||||
notes: t('spellHealerHealAllNotes'),
|
||||
target: 'party',
|
||||
cast: (user, target) => {
|
||||
return each(target, (member) => {
|
||||
member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .04;
|
||||
if (member.stats.hp > 50) {
|
||||
return member.stats.hp = 50;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let healer = {
|
||||
heal: heal,
|
||||
brightness: brightness,
|
||||
protectAura: protectAura,
|
||||
// @TODO APIv3 - correct to healAll
|
||||
heallAll: healAll,
|
||||
};
|
||||
|
||||
setSpellDefaults('healer', healer);
|
||||
|
||||
export default healer;
|
||||
@@ -1,51 +0,0 @@
|
||||
import {each} from 'lodash';
|
||||
|
||||
import wizard from './wizard';
|
||||
import warrior from './warrior';
|
||||
import healer from './healer';
|
||||
import rogue from './rogue';
|
||||
import special from './special';
|
||||
|
||||
/*
|
||||
---------------------------------------------------------------
|
||||
Spells
|
||||
---------------------------------------------------------------
|
||||
Text, notes, and mana are obvious. The rest:
|
||||
|
||||
* {target}: one of [task, self, party, user]. This is very important, because if the cast() function is expecting one
|
||||
thing and receives another, it will cause errors. `self` is used for self buffs, multi-task debuffs, AOEs (eg, meteor-shower),
|
||||
etc. Basically, use self for anything that's not [task, party, user] and is an instant-cast
|
||||
|
||||
* {cast}: the function that's run to perform the ability's action. This is pretty slick - because this is exported to the
|
||||
web, this function can be performed on the client and on the server. `user` param is self (needed for determining your
|
||||
own stats for effectiveness of cast), and `target` param is one of [task, party, user]. In the case of `self` spells,
|
||||
you act on `user` instead of `target`. You can trust these are the correct objects, as long as the `target` attr of the
|
||||
spell is correct. Take a look at habitrpg/src/models/user.js and habitrpg/src/models/task.js for what attributes are
|
||||
available on each model. Note `task.value` is its "redness". If party is passed in, it's an array of users,
|
||||
so you'll want to iterate over them like: `_.each(target,function(member){...})`
|
||||
|
||||
Note, user.stats.mp is docked after automatically (it's appended to functions automatically down below in an _.each)
|
||||
*/
|
||||
|
||||
var spells = {
|
||||
wizard: wizard,
|
||||
warrior: warrior,
|
||||
rogue: rogue,
|
||||
healer: healer,
|
||||
special: special,
|
||||
};
|
||||
|
||||
// Intercept all spells to reduce user.stats.mp after casting the spell
|
||||
each(spells, (spellClass) => {
|
||||
each(spellClass, (spell, key) => {
|
||||
spell.key = key;
|
||||
|
||||
let _cast = spell.cast;
|
||||
spell.cast = (user, target) => {
|
||||
_cast(user, target);
|
||||
return user.stats.mp -= spell.mana;
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
export default spells;
|
||||
@@ -1,75 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
diminishingReturns,
|
||||
calculateBonus,
|
||||
setSpellDefaults
|
||||
} from '../helpers';
|
||||
import {each} from 'lodash';
|
||||
|
||||
let pickPocket = {
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
cast: (user, target) => {
|
||||
var bonus;
|
||||
bonus = calculateBonus(target.value, user._statsComputed.per);
|
||||
return user.stats.gp += diminishingReturns(bonus, 25, 75);
|
||||
}
|
||||
};
|
||||
|
||||
let backStab = {
|
||||
mana: 15,
|
||||
lvl: 12,
|
||||
target: 'task',
|
||||
cast: (user, target) => {
|
||||
var _crit, bonus, req;
|
||||
_crit = user.fns.crit('str', .3);
|
||||
bonus = calculateBonus(target.value, user._statsComputed.str, _crit);
|
||||
user.stats.exp += diminishingReturns(bonus, 75, 50);
|
||||
user.stats.gp += diminishingReturns(bonus, 18, 75);
|
||||
req = {
|
||||
language: user.preferences.language
|
||||
};
|
||||
return user.fns.updateStats(user.stats, req);
|
||||
}
|
||||
};
|
||||
|
||||
let toolsOfTrade = {
|
||||
mana: 25,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
cast: (user, target) => {
|
||||
return each(target, (member) => {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.per - user.stats.buffs.per;
|
||||
if ((base = member.stats.buffs).per == null) {
|
||||
base.per = 0;
|
||||
}
|
||||
return member.stats.buffs.per += Math.ceil(diminishingReturns(bonus, 100, 50));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let stealth = {
|
||||
mana: 45,
|
||||
lvl: 14,
|
||||
target: 'self',
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
if ((base = user.stats.buffs).stealth == null) {
|
||||
base.stealth = 0;
|
||||
}
|
||||
return user.stats.buffs.stealth += Math.ceil(diminishingReturns(user._statsComputed.per, user.dailys.length * 0.64, 55));
|
||||
}
|
||||
};
|
||||
|
||||
let rogue = {
|
||||
pickPocket: pickPocket,
|
||||
backStab: backStab,
|
||||
toolsOfTrade: toolsOfTrade,
|
||||
stealth: stealth,
|
||||
};
|
||||
|
||||
setSpellDefaults('rogue', rogue);
|
||||
|
||||
export default rogue;
|
||||
@@ -1,299 +0,0 @@
|
||||
import { translator as t } from '../helpers';
|
||||
import {each} from 'lodash';
|
||||
|
||||
let snowball = {
|
||||
text: t('spellSpecialSnowballAuraText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSnowballAuraNotes'),
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
resetVisualBuffs(target);
|
||||
target.stats.buffs.snowball = true;
|
||||
|
||||
if ((base = target.achievements).snowball == null) {
|
||||
base.snowball = 0;
|
||||
}
|
||||
target.achievements.snowball++;
|
||||
return user.items.special.snowball--;
|
||||
}
|
||||
};
|
||||
|
||||
let salt = {
|
||||
text: t('spellSpecialSaltText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialSaltNotes'),
|
||||
cast: (user, target) => {
|
||||
user.stats.buffs.snowball = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
};
|
||||
|
||||
let spookDust = {
|
||||
text: t('spellSpecialSpookDustText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSpookDustNotes'),
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
resetVisualBuffs(target);
|
||||
target.stats.buffs.spookDust = true;
|
||||
|
||||
if ((base = target.achievements).spookDust == null) {
|
||||
base.spookDust = 0;
|
||||
}
|
||||
target.achievements.spookDust++;
|
||||
return user.items.special.spookDust--;
|
||||
}
|
||||
};
|
||||
|
||||
let opaquePotion = {
|
||||
text: t('spellSpecialOpaquePotionText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialOpaquePotionNotes'),
|
||||
cast: (user, target) => {
|
||||
user.stats.buffs.spookDust = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
};
|
||||
|
||||
let shinySeed = {
|
||||
text: t('spellSpecialShinySeedText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialShinySeedNotes'),
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
resetVisualBuffs(target);
|
||||
|
||||
target.stats.buffs.shinySeed = true;
|
||||
|
||||
if ((base = target.achievements).shinySeed == null) {
|
||||
base.shinySeed = 0;
|
||||
}
|
||||
target.achievements.shinySeed++;
|
||||
return user.items.special.shinySeed--;
|
||||
}
|
||||
};
|
||||
|
||||
let petalFreePotion = {
|
||||
text: t('spellSpecialPetalFreePotionText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialPetalFreePotionNotes'),
|
||||
cast: (user, target) => {
|
||||
user.stats.buffs.shinySeed = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
};
|
||||
|
||||
let seafoam = {
|
||||
text: t('spellSpecialSeafoamText'),
|
||||
mana: 0,
|
||||
value: 15,
|
||||
target: 'user',
|
||||
notes: t('spellSpecialSeafoamNotes'),
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
resetVisualBuffs(target);
|
||||
target.stats.buffs.seafoam = true;
|
||||
|
||||
if ((base = target.achievements).seafoam == null) {
|
||||
base.seafoam = 0;
|
||||
}
|
||||
target.achievements.seafoam++;
|
||||
return user.items.special.seafoam--;
|
||||
}
|
||||
};
|
||||
|
||||
let sand = {
|
||||
text: t('spellSpecialSandText'),
|
||||
mana: 0,
|
||||
value: 5,
|
||||
immediateUse: true,
|
||||
target: 'self',
|
||||
notes: t('spellSpecialSandNotes'),
|
||||
cast: (user, target) => {
|
||||
user.stats.buffs.seafoam = false;
|
||||
return user.stats.gp -= 5;
|
||||
}
|
||||
};
|
||||
|
||||
let nye = {
|
||||
text: t('nyeCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('nyeCardNotes'),
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).nye == null) {
|
||||
base.nye = 0;
|
||||
}
|
||||
user.achievements.nye++;
|
||||
} else {
|
||||
each([user, target], (t) => {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).nye == null) {
|
||||
base1.nye = 0;
|
||||
}
|
||||
return t.achievements.nye++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.nyeReceived) {
|
||||
target.items.special.nyeReceived = [];
|
||||
}
|
||||
target.items.special.nyeReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.nyeReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
};
|
||||
|
||||
let valentine = {
|
||||
text: t('valentineCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('valentineCardNotes'),
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).valentine == null) {
|
||||
base.valentine = 0;
|
||||
}
|
||||
user.achievements.valentine++;
|
||||
} else {
|
||||
each([user, target], (t) => {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).valentine == null) {
|
||||
base1.valentine = 0;
|
||||
}
|
||||
return t.achievements.valentine++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.valentineReceived) {
|
||||
target.items.special.valentineReceived = [];
|
||||
}
|
||||
target.items.special.valentineReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.valentineReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
};
|
||||
|
||||
let greeting = {
|
||||
text: t('greetingCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('greetingCardNotes'),
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).greeting == null) {
|
||||
base.greeting = 0;
|
||||
}
|
||||
user.achievements.greeting++;
|
||||
} else {
|
||||
each([user, target], (t) => {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).greeting == null) {
|
||||
base1.greeting = 0;
|
||||
}
|
||||
return t.achievements.greeting++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.greetingReceived) {
|
||||
target.items.special.greetingReceived = [];
|
||||
}
|
||||
target.items.special.greetingReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.greetingReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
};
|
||||
|
||||
let thankyou = {
|
||||
text: t('thankyouCard'),
|
||||
mana: 0,
|
||||
value: 10,
|
||||
immediateUse: true,
|
||||
silent: true,
|
||||
target: 'user',
|
||||
notes: t('thankyouCardNotes'),
|
||||
cast: (user, target) => {
|
||||
var base;
|
||||
if (user === target) {
|
||||
if ((base = user.achievements).thankyou == null) {
|
||||
base.thankyou = 0;
|
||||
}
|
||||
user.achievements.thankyou++;
|
||||
} else {
|
||||
each([user, target], (t) => {
|
||||
var base1;
|
||||
if ((base1 = t.achievements).thankyou == null) {
|
||||
base1.thankyou = 0;
|
||||
}
|
||||
return t.achievements.thankyou++;
|
||||
});
|
||||
}
|
||||
if (!target.items.special.thankyouReceived) {
|
||||
target.items.special.thankyouReceived = [];
|
||||
}
|
||||
target.items.special.thankyouReceived.push(user.profile.name);
|
||||
target.flags.cardReceived = true;
|
||||
if (typeof target.markModified === "function") {
|
||||
target.markModified('items.special.thankyouReceived');
|
||||
}
|
||||
return user.stats.gp -= 10;
|
||||
}
|
||||
};
|
||||
|
||||
function resetVisualBuffs(target) {
|
||||
target.stats.buffs.snowball = false;
|
||||
target.stats.buffs.spookDust = false;
|
||||
target.stats.buffs.shinySeed = false;
|
||||
target.stats.buffs.seafoam = false;
|
||||
}
|
||||
|
||||
let special = {
|
||||
snowball: snowball,
|
||||
salt: salt,
|
||||
spookDust: spookDust,
|
||||
opaquePotion: opaquePotion,
|
||||
shinySeed: shinySeed,
|
||||
petalFreePotion: petalFreePotion,
|
||||
seafoam: seafoam,
|
||||
sand: sand,
|
||||
nye: nye,
|
||||
valentine: valentine,
|
||||
greeting: greeting,
|
||||
thankyou: thankyou,
|
||||
};
|
||||
|
||||
export default special;
|
||||
@@ -1,79 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
diminishingReturns,
|
||||
calculateBonus,
|
||||
setSpellDefaults
|
||||
} from '../helpers';
|
||||
import {each} from 'lodash';
|
||||
|
||||
let smash= {
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
cast: (user, target) => {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.str * user.fns.crit('con');
|
||||
target.value += diminishingReturns(bonus, 2.5, 35);
|
||||
if ((base = user.party.quest.progress).up == null) {
|
||||
base.up = 0;
|
||||
}
|
||||
return user.party.quest.progress.up += diminishingReturns(bonus, 55, 70);
|
||||
}
|
||||
};
|
||||
|
||||
let defensiveStance = {
|
||||
mana: 25,
|
||||
lvl: 12,
|
||||
target: 'self',
|
||||
cast: (user, target) => {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if ((base = user.stats.buffs).con == null) {
|
||||
base.con = 0;
|
||||
}
|
||||
return user.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 40, 200));
|
||||
}
|
||||
};
|
||||
|
||||
let valorousPresence = {
|
||||
mana: 20,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
cast: (user, target) => {
|
||||
return each(target, (member) => {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.str - user.stats.buffs.str;
|
||||
if ((base = member.stats.buffs).str == null) {
|
||||
base.str = 0;
|
||||
}
|
||||
return member.stats.buffs.str += Math.ceil(diminishingReturns(bonus, 20, 200));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let intimidate = {
|
||||
mana: 15,
|
||||
lvl: 14,
|
||||
target: 'party',
|
||||
cast: (user, target) => {
|
||||
return each(target, (member) => {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.con - user.stats.buffs.con;
|
||||
if ((base = member.stats.buffs).con == null) {
|
||||
base.con = 0;
|
||||
}
|
||||
return member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 24, 200));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let warrior = {
|
||||
smash: smash,
|
||||
defensiveStance: defensiveStance,
|
||||
valorousPresence: valorousPresence,
|
||||
intimidate: intimidate,
|
||||
};
|
||||
|
||||
setSpellDefaults('warrior', warrior);
|
||||
|
||||
export default warrior;
|
||||
@@ -1,82 +0,0 @@
|
||||
import {
|
||||
translator as t,
|
||||
diminishingReturns,
|
||||
calculateBonus,
|
||||
setSpellDefaults
|
||||
} from '../helpers';
|
||||
import {each} from 'lodash';
|
||||
|
||||
let fireball = {
|
||||
mana: 10,
|
||||
lvl: 11,
|
||||
target: 'task',
|
||||
cast: (user, target) => {
|
||||
let base;
|
||||
|
||||
let bonus = user._statsComputed.int * user.fns.crit('per');
|
||||
bonus *= Math.ceil((target.value < 0 ? 1 : target.value + 1) * .075);
|
||||
|
||||
user.stats.exp += diminishingReturns(bonus, 75);
|
||||
|
||||
if ((base = user.party.quest.progress).up == null) {
|
||||
base.up = 0;
|
||||
}
|
||||
user.party.quest.progress.up += Math.ceil(user._statsComputed.int * .1);
|
||||
let req = {
|
||||
language: user.preferences.language
|
||||
};
|
||||
return user.fns.updateStats(user.stats, req);
|
||||
}
|
||||
};
|
||||
|
||||
let mpheal = {
|
||||
text: t('spellWizardMPHealText'),
|
||||
mana: 30,
|
||||
lvl: 12,
|
||||
target: 'party',
|
||||
notes: t('spellWizardMPHealNotes'),
|
||||
cast: (user, target) => {
|
||||
return each(target, (member) => {
|
||||
let bonus = user._statsComputed.int;
|
||||
if (user._id !== member._id) {
|
||||
return member.stats.mp += Math.ceil(diminishingReturns(bonus, 25, 125));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let earth = {
|
||||
mana: 35,
|
||||
lvl: 13,
|
||||
target: 'party',
|
||||
cast: (user, target) => {
|
||||
return each(target, (member) => {
|
||||
var base, bonus;
|
||||
bonus = user._statsComputed.int - user.stats.buffs.int;
|
||||
if ((base = member.stats.buffs).int == null) {
|
||||
base.int = 0;
|
||||
}
|
||||
return member.stats.buffs.int += Math.ceil(diminishingReturns(bonus, 30, 200));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let frost = {
|
||||
mana: 40,
|
||||
lvl: 14,
|
||||
target: 'self',
|
||||
cast: (user, target) => {
|
||||
return user.stats.buffs.streaks = true;
|
||||
}
|
||||
};
|
||||
|
||||
let wizard = {
|
||||
fireball: fireball,
|
||||
mpheal: mpheal,
|
||||
earth: earth,
|
||||
frost: frost,
|
||||
};
|
||||
|
||||
setSpellDefaults('wizard', wizard);
|
||||
|
||||
export default wizard;
|
||||
@@ -1,32 +0,0 @@
|
||||
import {each} from 'lodash';
|
||||
|
||||
let subscriptionBlocks = {
|
||||
basic_earned: {
|
||||
months: 1,
|
||||
price: 5
|
||||
},
|
||||
basic_3mo: {
|
||||
months: 3,
|
||||
price: 15
|
||||
},
|
||||
basic_6mo: {
|
||||
months: 6,
|
||||
price: 30
|
||||
},
|
||||
google_6mo: {
|
||||
months: 6,
|
||||
price: 24,
|
||||
discount: true,
|
||||
original: 30
|
||||
},
|
||||
basic_12mo: {
|
||||
months: 12,
|
||||
price: 48
|
||||
}
|
||||
};
|
||||
|
||||
each(subscriptionBlocks, function(block, key) {
|
||||
block.key = key;
|
||||
});
|
||||
|
||||
export default subscriptionBlocks;
|
||||
@@ -1,14 +0,0 @@
|
||||
import {translator as t} from './helpers';
|
||||
|
||||
let stable = {
|
||||
pets: {
|
||||
'Mammoth-Base': t('mammoth'),
|
||||
'MantisShrimp-Base': t('mantisShrimp')
|
||||
},
|
||||
mounts: {
|
||||
'Mammoth-Base': t('mammoth'),
|
||||
'MantisShrimp-Base': t('mantisShrimp')
|
||||
}
|
||||
};
|
||||
|
||||
export default stable;
|
||||
@@ -1,15 +0,0 @@
|
||||
import {keys, reduce} from 'lodash';
|
||||
import mystery from './mystery-sets';
|
||||
|
||||
function timeTravelerStore(owned) {
|
||||
var ownedKeys = keys((typeof owned.toObject === "function" ? owned.toObject() : void 0) || owned);
|
||||
return reduce(mystery, (m, v, k) => {
|
||||
if (k === 'wondercon' || ~ownedKeys.indexOf(v.items[0].key)) {
|
||||
return m;
|
||||
}
|
||||
m[k] = v;
|
||||
return m;
|
||||
}, {});
|
||||
};
|
||||
|
||||
export default timeTravelerStore;
|
||||
@@ -1,62 +0,0 @@
|
||||
import {translator as t} from './helpers';
|
||||
|
||||
let habits = [
|
||||
{
|
||||
type: 'habit',
|
||||
text: t('defaultHabit1Text'),
|
||||
value: 0,
|
||||
up: true,
|
||||
down: false,
|
||||
attribute: 'per',
|
||||
}, {
|
||||
type: 'habit',
|
||||
text: t('defaultHabit2Text'),
|
||||
value: 0,
|
||||
up: false,
|
||||
down: true,
|
||||
attribute: 'str',
|
||||
}, {
|
||||
type: 'habit',
|
||||
text: t('defaultHabit3Text'),
|
||||
value: 0,
|
||||
up: true,
|
||||
down: true,
|
||||
attribute: 'str',
|
||||
}
|
||||
];
|
||||
|
||||
let dailys = [];
|
||||
|
||||
let todos = [
|
||||
{
|
||||
type: 'todo',
|
||||
text: t('defaultTodo1Text'),
|
||||
notes: t('defaultTodoNotes'),
|
||||
completed: false,
|
||||
attribute: 'int',
|
||||
}
|
||||
];
|
||||
|
||||
let rewards = [
|
||||
{
|
||||
type: 'reward',
|
||||
text: t('defaultReward1Text'),
|
||||
value: 10,
|
||||
}
|
||||
];
|
||||
|
||||
let tags = [
|
||||
{ name: t('defaultTag1') },
|
||||
{ name: t('defaultTag2') },
|
||||
{ name: t('defaultTag3') },
|
||||
]
|
||||
|
||||
let userDefaults = {
|
||||
habits: habits,
|
||||
dailys: dailys,
|
||||
todos: todos,
|
||||
rewards: rewards,
|
||||
tags: tags
|
||||
};
|
||||
|
||||
export default userDefaults;
|
||||
@@ -1,49 +0,0 @@
|
||||
let _ = require('lodash');
|
||||
|
||||
module.exports = {
|
||||
strings: null,
|
||||
translations: {},
|
||||
t: function(stringName) {
|
||||
var clonedVars, e, locale, string, stringNotFound, vars;
|
||||
vars = arguments[1];
|
||||
if (_.isString(arguments[1])) {
|
||||
vars = null;
|
||||
locale = arguments[1];
|
||||
} else if (arguments[2] != null) {
|
||||
vars = arguments[1];
|
||||
locale = arguments[2];
|
||||
}
|
||||
if ((locale == null) || (!module.exports.strings && !module.exports.translations[locale])) {
|
||||
locale = 'en';
|
||||
}
|
||||
if (module.exports.strings) {
|
||||
string = module.exports.strings[stringName];
|
||||
} else {
|
||||
string = module.exports.translations[locale] && module.exports.translations[locale][stringName];
|
||||
}
|
||||
clonedVars = _.clone(vars) || {};
|
||||
clonedVars.locale = locale;
|
||||
if (string) {
|
||||
try {
|
||||
return _.template(string)(clonedVars);
|
||||
} catch (_error) {
|
||||
e = _error;
|
||||
return 'Error processing the string. Please see Help > Report a Bug.';
|
||||
}
|
||||
} else {
|
||||
if (module.exports.strings) {
|
||||
stringNotFound = module.exports.strings.stringNotFound;
|
||||
} else if (module.exports.translations[locale]) {
|
||||
stringNotFound = module.exports.translations[locale] && module.exports.translations[locale].stringNotFound;
|
||||
}
|
||||
try {
|
||||
return _.template(stringNotFound)({
|
||||
string: stringName
|
||||
});
|
||||
} catch (_error) {
|
||||
e = _error;
|
||||
return 'Error processing the string. Please see Help > Report a Bug.';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -16,7 +16,6 @@ const COMMON_FILES = [
|
||||
// @TODO remove these negations as the files are converted over.
|
||||
'!./common/script/index.js',
|
||||
'!./common/script/content/index.js',
|
||||
'!./common/script/src/**/*.js',
|
||||
'!./common/script/public/**/*.js',
|
||||
];
|
||||
const TEST_FILES = [
|
||||
|
||||
@@ -139,7 +139,7 @@ gulp.task('test:content:clean', (cb) => {
|
||||
});
|
||||
|
||||
gulp.task('test:content:watch', ['test:content:clean'], () => {
|
||||
gulp.watch(['common/script/src/content/**', 'test/**'], ['test:content:clean']);
|
||||
gulp.watch(['common/script/content/**', 'test/**'], ['test:content:clean']);
|
||||
});
|
||||
|
||||
gulp.task('test:content:safe', ['test:prepare:build'], (cb) => {
|
||||
|
||||
89
test/api/v2/groups/POST-groups_id_invite.test.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
createAndPopulateGroup,
|
||||
generateUser,
|
||||
} from '../../../helpers/api-integration/v2';
|
||||
import { each } from 'lodash';
|
||||
|
||||
describe('POST /groups/:id/invite', () => {
|
||||
context('user is a member of the group', () => {
|
||||
each({
|
||||
'public guild': {type: 'guild', privacy: 'public'},
|
||||
'private guild': {type: 'guild', privacy: 'private'},
|
||||
party: {type: 'party', privacy: 'private'},
|
||||
}, (groupDetails, groupType) => {
|
||||
let group, invitee, inviter;
|
||||
|
||||
beforeEach(async () => {
|
||||
invitee = await generateUser();
|
||||
let groupData = await createAndPopulateGroup({
|
||||
groupDetails,
|
||||
members: 1,
|
||||
});
|
||||
group = groupData.group;
|
||||
inviter = groupData.members[0];
|
||||
});
|
||||
|
||||
it(`allows user to send an invitation for a ${groupType}`, async () => {
|
||||
await inviter.post(`/groups/${group._id}/invite`, {
|
||||
uuids: [invitee._id],
|
||||
});
|
||||
await group.sync();
|
||||
expect(group.invites).to.include(invitee._id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('user is a not member of the group', () => {
|
||||
each({
|
||||
'public guild': {type: 'guild', privacy: 'public'},
|
||||
}, (groupDetails, groupType) => {
|
||||
context(`the group is a ${groupType}`, () => {
|
||||
let group, invitee, inviter;
|
||||
|
||||
beforeEach(async () => {
|
||||
invitee = await generateUser();
|
||||
inviter = await generateUser();
|
||||
let groupData = await createAndPopulateGroup({
|
||||
groupDetails,
|
||||
});
|
||||
group = groupData.group;
|
||||
});
|
||||
|
||||
it(`allows user to send an invitation for a ${groupType}`, async () => {
|
||||
await inviter.post(`/groups/${group._id}/invite`, {
|
||||
uuids: [invitee._id],
|
||||
});
|
||||
await group.sync();
|
||||
expect(group.invites).to.include(invitee._id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
each({
|
||||
'private guild': {type: 'guild', privacy: 'private'},
|
||||
party: {type: 'party', privacy: 'private'},
|
||||
}, (groupDetails, groupType) => {
|
||||
context(`the group is a ${groupType}`, () => {
|
||||
let group, invitee, inviter;
|
||||
|
||||
beforeEach(async () => {
|
||||
invitee = await generateUser();
|
||||
inviter = await generateUser();
|
||||
let groupData = await createAndPopulateGroup({
|
||||
groupDetails,
|
||||
});
|
||||
group = groupData.group;
|
||||
});
|
||||
|
||||
it(`does not allows user to send an invitation for a ${groupType}`, async () => {
|
||||
return expect(inviter.post(`/groups/${group._id}/invite`, {
|
||||
uuids: [invitee._id],
|
||||
})).to.eventually.be.rejected.and.eql({
|
||||
code: 401,
|
||||
text: 'Only a member can invite new members!',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString
|
||||
} from '../helpers/content.helper';
|
||||
|
||||
import armoire from '../../common/script/src/content/armoire';
|
||||
|
||||
describe('Armoire Locales', () => {
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(armoire.text);
|
||||
});
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString,
|
||||
describeEachItem
|
||||
} from '../helpers/content.helper';
|
||||
import {each} from 'lodash';
|
||||
|
||||
import backgroundSets from '../../common/script/src/content/backgrounds';
|
||||
|
||||
describe('Backgrounds', () => {
|
||||
each(backgroundSets, (set, name) => {
|
||||
describeEachItem(name, set, (bg, key) => {
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(bg.text);
|
||||
});
|
||||
|
||||
it('has a valid notes attribute', () => {
|
||||
expectValidTranslationString(bg.notes);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString,
|
||||
describeEachItem
|
||||
} from '../helpers/content.helper';
|
||||
|
||||
import {allEggs} from '../../common/script/src/content/eggs';
|
||||
|
||||
describeEachItem('Eggs', allEggs, (egg, key) => {
|
||||
it('has a key attribute', () => {
|
||||
expect(egg.key).to.eql(key);
|
||||
});
|
||||
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(egg.text);
|
||||
});
|
||||
|
||||
it('has a valid mountText attribute', () => {
|
||||
expectValidTranslationString(egg.mountText);
|
||||
});
|
||||
|
||||
it('has a valid notes attribute', () => {
|
||||
expectValidTranslationString(egg.notes);
|
||||
});
|
||||
|
||||
it('has a valid ajective attribute', () => {
|
||||
expectValidTranslationString(egg.adjective);
|
||||
});
|
||||
|
||||
it('has a canBuy function', () => {
|
||||
expect(egg.canBuy).to.be.a('function');
|
||||
});
|
||||
|
||||
it('has a value attribute', () => {
|
||||
expect(egg.value).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
@@ -1,29 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString,
|
||||
describeEachItem
|
||||
} from '../helpers/content.helper';
|
||||
import {each} from 'lodash';
|
||||
|
||||
import allFood from '../../common/script/src/content/food';
|
||||
|
||||
describeEachItem('Food', allFood, (food, key) => {
|
||||
it('has a valid key', () => {
|
||||
expect(food.key).to.eql(key);
|
||||
});
|
||||
|
||||
it('has a valid value attribute', () => {
|
||||
expect(food.value).to.be.greaterThan(0);
|
||||
});
|
||||
|
||||
it('has a canBuy function', () => {
|
||||
expect(food.canBuy).to.be.a('function');
|
||||
});
|
||||
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(food.text);
|
||||
});
|
||||
|
||||
it('has a valid notes attribute', () => {
|
||||
expectValidTranslationString(food.notes);
|
||||
});
|
||||
});
|
||||
@@ -1,29 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString,
|
||||
describeEachItem
|
||||
} from '../helpers/content.helper';
|
||||
import {each} from 'lodash';
|
||||
|
||||
import { all as potions } from '../../common/script/src/content/hatching-potions';
|
||||
|
||||
describeEachItem('Hatching Potions', potions, (potion, key) => {
|
||||
it('has a valid key', () => {
|
||||
expect(potion.key).to.eql(key);
|
||||
});
|
||||
|
||||
it('has a canBuy function', () => {
|
||||
expect(potion.canBuy).to.be.a('function');
|
||||
});
|
||||
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(potion.text);
|
||||
});
|
||||
|
||||
it('has a valid notes attribute', () => {
|
||||
expectValidTranslationString(potion.notes);
|
||||
});
|
||||
|
||||
it('has a valid value', () => {
|
||||
expect(potion.value).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString
|
||||
} from '../helpers/content.helper';
|
||||
|
||||
import healthPotion from '../../common/script/src/content/health-potion';
|
||||
|
||||
describe('Health Potion Locales', () => {
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(healthPotion.text);
|
||||
});
|
||||
|
||||
it('has a valid notes attribute', () => {
|
||||
expectValidTranslationString(healthPotion.notes);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,145 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString,
|
||||
describeEachItem
|
||||
} from '../helpers/content.helper';
|
||||
import {each} from 'lodash';
|
||||
|
||||
import {
|
||||
all as allQuests,
|
||||
byLevel as questsByLevel
|
||||
} from '../../common/script/src/content/quests';
|
||||
|
||||
describeEachItem('Quests', allQuests, (quest, key) => {
|
||||
context('attributes', () => {
|
||||
it('has a key', () => {
|
||||
expect(quest.key).to.eql(key);
|
||||
});
|
||||
|
||||
it('has a category', () => {
|
||||
expect(quest.category).to.not.be.empty;
|
||||
});
|
||||
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(quest.text);
|
||||
});
|
||||
|
||||
it('has a valid notes attribute', () => {
|
||||
expectValidTranslationString(quest.notes);
|
||||
});
|
||||
|
||||
if (quest.previous) {
|
||||
it('has a valid previous quest', () => {
|
||||
expect(allQuests[quest.previous]).to.exist;
|
||||
});
|
||||
}
|
||||
|
||||
if (quest.completion) {
|
||||
it('has a valid completion attribute', () => {
|
||||
expectValidTranslationString(quest.completion);
|
||||
});
|
||||
}
|
||||
|
||||
it('has a canBuy function', () => {
|
||||
expect(quest.canBuy).to.be.a('function');
|
||||
});
|
||||
|
||||
it('has a value', () => {
|
||||
expect(quest.value).to.be.at.least(0);
|
||||
});
|
||||
});
|
||||
|
||||
if (quest.boss) {
|
||||
context('boss', () => {
|
||||
it('has a valid boss name attribute', () => {
|
||||
expectValidTranslationString(quest.boss.name);
|
||||
});
|
||||
|
||||
it('has an hp attribute', () => {
|
||||
expect(quest.boss.hp).to.be.greaterThan(0);
|
||||
});
|
||||
|
||||
it('has a str attribute', () => {
|
||||
expect(quest.boss.str).to.be.greaterThan(0);
|
||||
});
|
||||
|
||||
it('has a def attribute', () => {
|
||||
expect(quest.boss.def).to.be.greaterThan(0);
|
||||
});
|
||||
|
||||
if (quest.boss.rage) {
|
||||
context('rage', () => {
|
||||
it('has a title attribute', () => {
|
||||
expectValidTranslationString(quest.boss.rage.title);
|
||||
});
|
||||
|
||||
it('has a description attribute', () => {
|
||||
expectValidTranslationString(quest.boss.rage.description);
|
||||
});
|
||||
|
||||
it('has a value attribute', () => {
|
||||
expect(quest.boss.rage.value).to.be.greaterThan(0);
|
||||
});
|
||||
|
||||
if (quest.boss.rage.healing) {
|
||||
it('has a healing attribute', () => {
|
||||
expect(quest.boss.rage.healing).to.be.greaterThan(0);
|
||||
});
|
||||
}
|
||||
|
||||
if (quest.boss.rage.effect) {
|
||||
it('has an effect attribute', () => {
|
||||
expectValidTranslationString(quest.boss.rage.effect);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (quest.collect) {
|
||||
context('collection', () => {
|
||||
each(quest.collect, (item, key) => {
|
||||
it(`${key} has a valid text attribute`, () => {
|
||||
expectValidTranslationString(item.text);
|
||||
expect(item.count).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
context('drops', () => {
|
||||
it('has drops', () => {
|
||||
expect(quest.drop).to.exist;
|
||||
});
|
||||
|
||||
it('has a gold value', () => {
|
||||
expect(quest.drop.gp).to.be.at.least(0);
|
||||
});
|
||||
|
||||
it('has a exp value', () => {
|
||||
expect(quest.drop.exp).to.be.at.least(0);
|
||||
});
|
||||
|
||||
if (quest.items) {
|
||||
it('has items', () => {
|
||||
expect(quest.drop.items).to.be.an('array');
|
||||
expect(quest.drop.items).to.have.length.above(0);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Quests by Level', () => {
|
||||
let lastLevel = 0;
|
||||
|
||||
it('orders quests by level', () => {
|
||||
each(questsByLevel, (quest, key) => {
|
||||
let questLvl = quest.lvl || 0;
|
||||
|
||||
expect(questLvl).to.be.at.least(lastLevel);
|
||||
lastLevel = questLvl;
|
||||
});
|
||||
|
||||
expect(lastLevel).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
@@ -1,47 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString,
|
||||
describeEachItem
|
||||
} from '../helpers/content.helper';
|
||||
import {each} from 'lodash';
|
||||
|
||||
import spells from '../../common/script/src/content/spells';
|
||||
|
||||
describe('Spells', () => {
|
||||
each(spells, (spellSet, klass) => {
|
||||
describeEachItem(klass, spellSet, (spell, key) => {
|
||||
checkSpellAttributes(spell, key);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function checkSpellAttributes(spell, key) {
|
||||
describe(`${key}`, () => {
|
||||
it('has a key attribute', () => {
|
||||
expect(spell.key).to.eql(key);
|
||||
});
|
||||
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(spell.text);
|
||||
});
|
||||
|
||||
it('has a valid notes attribute', () => {
|
||||
expectValidTranslationString(spell.notes);
|
||||
});
|
||||
|
||||
it('has a cast function', () => {
|
||||
expect(spell.cast).to.be.a('function');
|
||||
});
|
||||
|
||||
it('has a mana attribute', () => {
|
||||
expect(spell.mana).to.be.at.least(0);
|
||||
});
|
||||
|
||||
it('has a valid target attribute', () => {
|
||||
expect(spell.target).to.match(/self|user|party|task/);
|
||||
});
|
||||
|
||||
it('has a mana attribute', () => {
|
||||
expect(spell.mana).to.be.at.least(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import {STRING_ERROR_MSG, STRING_DOES_NOT_EXIST_MSG} from '../helpers/content.helper';
|
||||
import {translator} from '../../common/script/src/content/helpers';
|
||||
import translator from '../../common/script/content/translation';
|
||||
|
||||
describe('Translator', () => {
|
||||
it('returns error message if string is not properly formatted', () => {
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import {
|
||||
expectValidTranslationString,
|
||||
describeEachItem
|
||||
} from '../helpers/content.helper';
|
||||
import {each} from 'lodash';
|
||||
|
||||
import {
|
||||
habits,
|
||||
dailys,
|
||||
todos,
|
||||
rewards,
|
||||
tags
|
||||
} from '../../common/script/src/content/user-defaults';
|
||||
|
||||
describe('User Defaults', () => {
|
||||
let tasks = {
|
||||
habits: habits,
|
||||
dailys: dailys,
|
||||
todos: todos,
|
||||
rewards: rewards
|
||||
};
|
||||
|
||||
describeEachItem('Tasks', tasks, (type, name) => {
|
||||
each(type, (task, index) => {
|
||||
it('has a valid text attribute', () => {
|
||||
expectValidTranslationString(task.text);
|
||||
});
|
||||
|
||||
it('has a valid type attribute', () => {
|
||||
expect(task.type).to.match(/todo|daily|habit|reward/);
|
||||
});
|
||||
|
||||
if (task.notes) {
|
||||
it('has a valid notes attribute', () => {
|
||||
expectValidTranslationString(task.notes);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describeEachItem('Tags', tags, (tag, index) => {
|
||||
|
||||
it('has a valid name attribute', () => {
|
||||
expectValidTranslationString(tag.name);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,5 @@
|
||||
require('./globals.helper');
|
||||
import {each} from 'lodash';
|
||||
|
||||
import i18n from '../../common/script/src/i18n';
|
||||
import i18n from '../../common/script/i18n';
|
||||
i18n.translations = require('../../website/src/libs/api-v3/i18n').translations;
|
||||
|
||||
export const STRING_ERROR_MSG = 'Error processing the string. Please see Help > Report a Bug.';
|
||||
@@ -16,26 +14,3 @@ export function expectValidTranslationString (attribute) {
|
||||
expect(translatedString).to.not.eql(STRING_ERROR_MSG);
|
||||
expect(translatedString).to.not.match(STRING_DOES_NOT_EXIST_MSG);
|
||||
}
|
||||
|
||||
export function describeEachItem (testDescription, set, cb, describeFunction) {
|
||||
// describeFunction allows you to pass in 'only' or 'skip'
|
||||
// as the last argument for writing/debugging tests.
|
||||
// This should only be used with the helper functions .only and .skip below
|
||||
let describeBlock = describe[describeFunction] || describe;
|
||||
|
||||
describeBlock(testDescription, () => {
|
||||
each(set, (item, key) => {
|
||||
describe(key, () => {
|
||||
cb(item, key);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describeEachItem.only = (des, set, cb) => {
|
||||
describeEachItem(des, set, cb, 'only');
|
||||
};
|
||||
|
||||
describeEachItem.skip = (des, set, cb) => {
|
||||
describeEachItem(des, set, cb, 'skip');
|
||||
};
|
||||
|
||||
@@ -690,6 +690,9 @@ var inviteByEmails = function(invites, group, req, res, next){
|
||||
api.invite = function(req, res, next){
|
||||
var group = res.locals.group;
|
||||
|
||||
if (group.privacy === 'private' && !_.contains(group.members,res.locals.user._id)) {
|
||||
return res.json(401, {err: "Only a member can invite new members!"});
|
||||
}
|
||||
if (req.body.uuids) {
|
||||
inviteByUUIDs(req.body.uuids, group, req, res, next);
|
||||
} else if (req.body.emails) {
|
||||
|
||||
@@ -1,5 +1,38 @@
|
||||
h2 2/24/2016 - PHOENIXES IN THE TIME TRAVEL STABLE! FEBRUARY MYSTERY SET!
|
||||
h2 3/1/2016 - MARCH BACKGROUNDS AND ARMOIRE ITEMS REVEALED! PLUS, WEB DESIGNER NEEDED AND MARCH MYSTERY BOX
|
||||
hr
|
||||
tr
|
||||
td
|
||||
.promo_backgrounds_armoire_201603.pull-right
|
||||
h3 March Backgrounds
|
||||
p There are three new avatar backgrounds in the <a href='/#/options/profile/backgrounds'>Background Shop!</a> Now your avatar can venture into a Rainforest, find precious metals in a Deep Mine, or cast spells in a Circle of Stones.
|
||||
p.small.muted by James Danger, sungabraverday, and UncommonCriminal
|
||||
tr
|
||||
td
|
||||
h3 March Armoire Items Revealed
|
||||
p There is new equipment in Enchanted Armoire, a 100 GP Reward in the Rewards Column which unlocks after you've attained Ultimate Gear!
|
||||
br
|
||||
p Click on the Enchanted Armoire for a random chance at special Equipment, including the Miner Set and the Mystic Lamp! It may also give you random XP or food items. We'll be adding new equipment to it during the first week of each month, but even when you've exhausted the current supply, you can keep clicking for a chance at food and XP.
|
||||
br
|
||||
p Now go spend all that accumulated Gold! May the Random Number Generator smile upon you...
|
||||
p.small.muted by Lemoness and SabreCat
|
||||
p.small.muted Art by Balduranne
|
||||
tr
|
||||
td
|
||||
.inventory_present_03.pull-right
|
||||
h3 March Mystery Box
|
||||
p Ooh... What could it be? All Habiticans who are subscribed during the month of March will receive the March Mystery Item Set! It will be revealed on the 23rd, so keep your eyes peeled. Thanks for supporting the site <3
|
||||
p.small.muted by Lemoness
|
||||
tr
|
||||
td
|
||||
h3 Web UI Designer Needed
|
||||
p We’re looking for UI designers with experience in UX! Do you like user-centered approaches? Are you familiar with web patterns and assets? If that sounds like you, and you’re interested in contributing to Habitica, please email <a href='mailto:vicky@habitica.com' target='_blank'>vicky@habitica.com</a>. We look forward to questing with you!
|
||||
|
||||
if menuItem !== 'oldNews'
|
||||
hr
|
||||
a(href='/static/old-news', target='_blank') Read older news
|
||||
|
||||
mixin oldNews
|
||||
h2 2/24/2016 - PHOENIXES IN THE TIME TRAVEL STABLE! FEBRUARY MYSTERY SET!
|
||||
tr
|
||||
td
|
||||
.Pet-Phoenix-Base.pull-right
|
||||
@@ -13,12 +46,6 @@ h2 2/24/2016 - PHOENIXES IN THE TIME TRAVEL STABLE! FEBRUARY MYSTERY SET!
|
||||
h3 February Subscriber Items
|
||||
p The February Subscriber Items have been revealed: the Heartbreaker Item Set! All February subscribers will receive the Heartbreaker Cape and the Heartbreaker Hood. You still have five days to <a href='/#/options/settings/subscription'>subscribe</a> and receive the item set! Thank you so much for your support - we really do rely on you to keep Habitica free to use and running smoothly.
|
||||
p.small.muted by Lemoness
|
||||
|
||||
if menuItem !== 'oldNews'
|
||||
hr
|
||||
a(href='/static/old-news', target='_blank') Read older news
|
||||
|
||||
mixin oldNews
|
||||
h2 2/17/2016 - ANDROID APP IN PORTUGUESE, LITHUANIAN, AND POLISH! PLUS, NEW YEAR'S RESOLUTION CHALLENGE WINNERS
|
||||
tr
|
||||
td
|
||||
|
||||