Merge branch 'develop' into api-v3
@@ -31,7 +31,6 @@
|
||||
"no-octal": 2,
|
||||
"no-process-env": 2,
|
||||
"no-proto": 2,
|
||||
"no-implied-eval": 2,
|
||||
"yoda": 2,
|
||||
"wrap-iife": 2,
|
||||
"radix": 2,
|
||||
|
||||
1074
common/dist/sprites/spritesmith-main-10.css
vendored
BIN
common/dist/sprites/spritesmith-main-10.png
vendored
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 142 KiB |
2628
common/dist/sprites/spritesmith-main-11.css
vendored
BIN
common/dist/sprites/spritesmith-main-11.png
vendored
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 158 KiB |
144
common/dist/sprites/spritesmith-main-12.css
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
.Pet-Wolf-CottonCandyBlue {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -82px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-CottonCandyPink {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -246px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Desert {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -246px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Golden {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -164px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Peppermint {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: 0px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Red {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -82px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Shade {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -164px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Skeleton {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: 0px 0px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Spooky {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -246px -100px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Veteran {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: 0px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-White {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -82px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet-Wolf-Zombie {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -164px -200px;
|
||||
width: 81px;
|
||||
height: 99px;
|
||||
}
|
||||
.Pet_HatchingPotion_Base {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -294px -300px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_CottonCandyBlue {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -328px -52px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_CottonCandyPink {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -328px -104px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_Desert {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -328px -156px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_Golden {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -328px -208px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_Peppermint {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: 0px -300px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_Red {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -49px -300px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_Shade {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -98px -300px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_Skeleton {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -147px -300px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_Spooky {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -196px -300px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_White {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -245px -300px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.Pet_HatchingPotion_Zombie {
|
||||
background-image: url(spritesmith-main-12.png);
|
||||
background-position: -328px 0px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
BIN
common/dist/sprites/spritesmith-main-12.png
vendored
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
196
common/dist/sprites/spritesmith-main-5.css
vendored
@@ -120,31 +120,31 @@
|
||||
}
|
||||
.shop_body_special_wondercon_black {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -144px;
|
||||
background-position: -697px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_body_special_wondercon_gold {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1066px -1680px;
|
||||
background-position: -1107px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_body_special_wondercon_red {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1025px -1680px;
|
||||
background-position: -1066px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_eyewear_special_wondercon_black {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -984px -1680px;
|
||||
background-position: -1025px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_eyewear_special_wondercon_red {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -943px -1680px;
|
||||
background-position: -984px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
@@ -294,145 +294,145 @@
|
||||
}
|
||||
.shop_head_healer_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -902px -1680px;
|
||||
background-position: -943px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_healer_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -861px -1680px;
|
||||
background-position: -902px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_healer_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -820px -1680px;
|
||||
background-position: -861px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_healer_4 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -779px -1680px;
|
||||
background-position: -820px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_healer_5 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -738px -1680px;
|
||||
background-position: -779px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_rogue_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -697px -1680px;
|
||||
background-position: -738px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_rogue_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -615px -1680px;
|
||||
background-position: -656px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_rogue_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -574px -1680px;
|
||||
background-position: -615px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_rogue_4 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -533px -1680px;
|
||||
background-position: -574px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_rogue_5 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -492px -1680px;
|
||||
background-position: -533px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_special_0 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -451px -1680px;
|
||||
background-position: -492px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_special_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -369px -1680px;
|
||||
background-position: -410px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_special_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -328px -1680px;
|
||||
background-position: -369px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_special_fireCoralCirclet {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -287px -1680px;
|
||||
background-position: -328px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_warrior_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -164px -1680px;
|
||||
background-position: -205px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_warrior_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -123px -1680px;
|
||||
background-position: -164px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_warrior_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -82px -1680px;
|
||||
background-position: -123px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_warrior_4 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -41px -1680px;
|
||||
background-position: -82px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_warrior_5 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: 0px -1680px;
|
||||
background-position: -41px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_wizard_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1380px -1253px;
|
||||
background-position: 0px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_wizard_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1380px -1212px;
|
||||
background-position: -1380px -1253px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_wizard_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1233px -1113px;
|
||||
background-position: -1380px -1212px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_wizard_4 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -431px;
|
||||
background-position: -1700px -442px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_head_wizard_5 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -390px;
|
||||
background-position: -1700px -401px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
@@ -534,37 +534,37 @@
|
||||
}
|
||||
.shop_headAccessory_special_bearEars {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -349px;
|
||||
background-position: -1700px -360px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_headAccessory_special_cactusEars {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -308px;
|
||||
background-position: -1700px -319px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_headAccessory_special_foxEars {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -267px;
|
||||
background-position: -1700px -278px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_headAccessory_special_lionEars {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -226px;
|
||||
background-position: -1700px -237px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_headAccessory_special_pandaEars {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1107px -1680px;
|
||||
background-position: -1148px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_headAccessory_special_pigEars {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -656px -1680px;
|
||||
background-position: -451px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
@@ -714,103 +714,103 @@
|
||||
}
|
||||
.shop_shield_healer_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1087px;
|
||||
background-position: -1700px -1098px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_healer_4 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1046px;
|
||||
background-position: -1700px -1057px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_healer_5 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1005px;
|
||||
background-position: -1700px -1016px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_rogue_0 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -964px;
|
||||
background-position: -1700px -975px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_rogue_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -923px;
|
||||
background-position: -1700px -934px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_rogue_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -882px;
|
||||
background-position: -1700px -893px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_rogue_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -841px;
|
||||
background-position: -1700px -852px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_rogue_4 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -800px;
|
||||
background-position: -1700px -811px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_rogue_5 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -759px;
|
||||
background-position: -1700px -770px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_rogue_6 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -718px;
|
||||
background-position: -1700px -729px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_special_0 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -677px;
|
||||
background-position: -1700px -688px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_special_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -636px;
|
||||
background-position: -1700px -647px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_special_goldenknight {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -595px;
|
||||
background-position: -1700px -606px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_special_moonpearlShield {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -554px;
|
||||
background-position: -1700px -565px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_warrior_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -513px;
|
||||
background-position: -1700px -524px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_warrior_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -472px;
|
||||
background-position: -1700px -483px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_shield_warrior_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -410px -1680px;
|
||||
background-position: -287px -1680px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
@@ -930,85 +930,85 @@
|
||||
}
|
||||
.shop_weapon_special_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1128px;
|
||||
background-position: -1700px -1139px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_special_critical {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -185px;
|
||||
background-position: -1700px -196px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_special_tridentOfCrashingTides {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1169px;
|
||||
background-position: -1700px -1180px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_warrior_0 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1210px;
|
||||
background-position: -1700px -1221px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_warrior_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1251px;
|
||||
background-position: -1700px -1262px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_warrior_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1292px;
|
||||
background-position: -1700px -1303px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_warrior_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1333px;
|
||||
background-position: -1700px -1344px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_warrior_4 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1374px;
|
||||
background-position: -1700px -1385px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_warrior_5 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1415px;
|
||||
background-position: -1700px -1426px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_warrior_6 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1456px;
|
||||
background-position: -1700px -1467px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_wizard_0 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1497px;
|
||||
background-position: -1700px -1508px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_wizard_1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1538px;
|
||||
background-position: -1700px -1549px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_wizard_2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1579px;
|
||||
background-position: -1700px -1590px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
.shop_weapon_wizard_3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1620px;
|
||||
background-position: -1700px -1631px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
@@ -1230,13 +1230,13 @@
|
||||
}
|
||||
.Pet_Currency_Gem {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -104px;
|
||||
background-position: -1700px -156px;
|
||||
width: 45px;
|
||||
height: 39px;
|
||||
}
|
||||
.Pet_Currency_Gem1x {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -1661px;
|
||||
background-position: -1670px -364px;
|
||||
width: 15px;
|
||||
height: 13px;
|
||||
}
|
||||
@@ -1500,7 +1500,7 @@
|
||||
}
|
||||
.zzz {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -205px -1680px;
|
||||
background-position: -1233px -1113px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
@@ -1656,7 +1656,7 @@
|
||||
}
|
||||
.inventory_quest_scroll_dilatoryDistress3_locked {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px -52px;
|
||||
background-position: -1700px -104px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
@@ -1858,78 +1858,84 @@
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_snake {
|
||||
.inventory_quest_scroll_snail {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1078px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_spider {
|
||||
.inventory_quest_scroll_snake {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1127px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_trex {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1225px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_trex_undead {
|
||||
.inventory_quest_scroll_spider {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1176px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_unicorn {
|
||||
.inventory_quest_scroll_trex {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1274px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_vice1 {
|
||||
.inventory_quest_scroll_trex_undead {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1372px -1628px;
|
||||
background-position: -1225px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_vice1_locked {
|
||||
.inventory_quest_scroll_unicorn {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1323px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_vice2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1470px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_vice2_locked {
|
||||
.inventory_quest_scroll_vice1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1421px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_vice3 {
|
||||
.inventory_quest_scroll_vice1_locked {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1568px -1628px;
|
||||
background-position: -1372px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_vice3_locked {
|
||||
.inventory_quest_scroll_vice2 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1519px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_whale {
|
||||
.inventory_quest_scroll_vice2_locked {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1470px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_vice3 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1617px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_vice3_locked {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1568px -1628px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.inventory_quest_scroll_whale {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px 0px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
.quest_atom1 {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -679px -886px;
|
||||
@@ -1986,7 +1992,7 @@
|
||||
}
|
||||
.quest_dilatoryDistress1_fireCoral {
|
||||
background-image: url(spritesmith-main-5.png);
|
||||
background-position: -1700px 0px;
|
||||
background-position: -1700px -52px;
|
||||
width: 48px;
|
||||
height: 51px;
|
||||
}
|
||||
|
||||
BIN
common/dist/sprites/spritesmith-main-5.png
vendored
|
Before Width: | Height: | Size: 317 KiB After Width: | Height: | Size: 319 KiB |
528
common/dist/sprites/spritesmith-main-6.css
vendored
BIN
common/dist/sprites/spritesmith-main-6.png
vendored
|
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 225 KiB |
2712
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: 140 KiB |
622
common/dist/sprites/spritesmith-main-8.css
vendored
BIN
common/dist/sprites/spritesmith-main-8.png
vendored
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 153 KiB |
1784
common/dist/sprites/spritesmith-main-9.css
vendored
BIN
common/dist/sprites/spritesmith-main-9.png
vendored
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 145 KiB |
|
After Width: | Height: | Size: 23 KiB |
BIN
common/img/sprites/spritesmith/quests/quest_snail.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
common/img/sprites/spritesmith/stable/eggs/Pet_Egg_Snail.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
BIN
common/img/sprites/spritesmith/stable/pets/Pet-Snail-Base.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
BIN
common/img/sprites/spritesmith/stable/pets/Pet-Snail-Desert.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
common/img/sprites/spritesmith/stable/pets/Pet-Snail-Golden.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
common/img/sprites/spritesmith/stable/pets/Pet-Snail-Red.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
common/img/sprites/spritesmith/stable/pets/Pet-Snail-Shade.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
BIN
common/img/sprites/spritesmith/stable/pets/Pet-Snail-White.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
common/img/sprites/spritesmith/stable/pets/Pet-Snail-Zombie.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
@@ -49,7 +49,7 @@
|
||||
|
||||
"dropEggBearCubText": "Bear Cub",
|
||||
"dropEggBearCubMountText": "Bear",
|
||||
"dropEggBearCubAdjective": "a cuddly",
|
||||
"dropEggBearCubAdjective": "a brave",
|
||||
|
||||
"questEggGryphonText": "Gryphon",
|
||||
"questEggGryphonMountText": "Gryphon",
|
||||
@@ -69,7 +69,7 @@
|
||||
|
||||
"questEggRatText": "Rat",
|
||||
"questEggRatMountText": "Rat",
|
||||
"questEggRatAdjective": "a dirty",
|
||||
"questEggRatAdjective": "a sociable",
|
||||
|
||||
"questEggOctopusText": "Octopus",
|
||||
"questEggOctopusMountText": "Octopus",
|
||||
@@ -155,6 +155,10 @@
|
||||
"questEggMonkeyMountText": "Monkey",
|
||||
"questEggMonkeyAdjective": "a mischievous",
|
||||
|
||||
"questEggSnailText": "Snail",
|
||||
"questEggSnailMountText": "Snail",
|
||||
"questEggSnailAdjective": "a slow but steady",
|
||||
|
||||
"eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.",
|
||||
|
||||
"hatchingPotionBase": "Base",
|
||||
|
||||
@@ -339,5 +339,12 @@
|
||||
"questMonkeyCompletion": "You did it! No bananas for those fiends today. Overwhelmed by your diligence, the monkeys flee in panic. \"Look,\" says @Misceo. \"They left a few eggs behind.\"<br><br>@Leephon grins. \"Maybe a well-trained pet monkey can help you as much as the wild ones hinder you!\"",
|
||||
"questMonkeyBoss": "Monstrous Mandrill",
|
||||
"questMonkeyDropMonkeyEgg": "Monkey (Egg)",
|
||||
"questMonkeyUnlockText": "Unlocks purchasable Monkey eggs in the Market"
|
||||
"questMonkeyUnlockText": "Unlocks purchasable Monkey eggs in the Market",
|
||||
|
||||
"questSnailText": "The Snail of Drudgery Sludge",
|
||||
"questSnailNotes": "You're excited to begin questing in the abandoned Dungeons of Drudgery, but as soon as you enter, you feel the ground under your feet start to suck at your boots. You look up to the path ahead and see Habiticans mired in slime. @Overomega yells, \"They have too many unimportant tasks and dailies, and they're getting stuck on things that don't matter! Pull them out!\"<br><br>\"You need to find the source of the ooze,\" @Pffernusse agrees, \"or the tasks that they cannot accomplish will drag them down forever!\"<br><br>Pulling out your weapon, you wade through the gooey mud.... and encounter the fearsome Snail of Drudgery Sludge.",
|
||||
"questSnailCompletion": "You bring your weapon down on the great Snail's shell, cracking it in two, releasing a flood of water. The slime is washed away, and the Habiticans around you rejoice. \"Look!\" says @Misceo. \"There's a small group of snail eggs in the remnants of the muck.\"",
|
||||
"questSnailBoss": "Snail of Drudgery Sludge",
|
||||
"questSnailDropSnailEgg": "Snail (Egg)",
|
||||
"questSnailUnlockText": "Unlocks purchasable Snail eggs in the Market"
|
||||
}
|
||||
|
||||
@@ -373,6 +373,13 @@ api.questEggs = {
|
||||
return u.achievements.quests && (u.achievements.quests.monkey != null) > 0;
|
||||
})
|
||||
},
|
||||
Snail: {
|
||||
text: t('questEggSnailText'),
|
||||
adjective: t('questEggSnailAdjective'),
|
||||
canBuy: (function(u) {
|
||||
return u.achievements.quests && (u.achievements.quests.snail != null) > 0;
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
_.each(api.questEggs, function(egg, key) {
|
||||
@@ -2488,6 +2495,38 @@ api.quests = {
|
||||
unlock: t('questMonkeyUnlockText')
|
||||
}
|
||||
},
|
||||
snail: {
|
||||
text: t('questSnailText'),
|
||||
notes: t('questSnailNotes'),
|
||||
completion: t('questSnailCompletion'),
|
||||
value: 4,
|
||||
category: 'pet',
|
||||
boss: {
|
||||
name: t('questSnailBoss'),
|
||||
hp: 500,
|
||||
str: 1.5
|
||||
},
|
||||
drop: {
|
||||
items: [
|
||||
{
|
||||
type: 'eggs',
|
||||
key: 'Snail',
|
||||
text: t('questSnailDropSnailEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Snail',
|
||||
text: t('questSnailDropSnailEgg')
|
||||
}, {
|
||||
type: 'eggs',
|
||||
key: 'Snail',
|
||||
text: t('questSnailDropSnailEgg')
|
||||
}
|
||||
],
|
||||
gp: 37,
|
||||
exp: 275,
|
||||
unlock: t('questSnailUnlockText')
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
_.each(api.quests, function(v, key) {
|
||||
|
||||
56
common/script/fns/autoAllocate.js
Normal file
@@ -0,0 +1,56 @@
|
||||
import _ from 'lodash';
|
||||
import splitWhitespace from '../libs/splitWhitespace';
|
||||
|
||||
/*
|
||||
Updates user stats with new stats. Handles death, leveling up, etc
|
||||
{stats} new stats
|
||||
{update} if aggregated changes, pass in userObj as update. otherwise commits will be made immediately
|
||||
*/
|
||||
|
||||
module.exports = function(user) {
|
||||
return user.stats[(function() {
|
||||
var diff, ideal, lvlDiv7, preference, stats, suggested;
|
||||
switch (user.preferences.allocationMode) {
|
||||
case "flat":
|
||||
stats = _.pick(user.stats, splitWhitespace('con str per int'));
|
||||
return _.invert(stats)[_.min(stats)];
|
||||
case "classbased":
|
||||
lvlDiv7 = user.stats.lvl / 7;
|
||||
ideal = [lvlDiv7 * 3, lvlDiv7 * 2, lvlDiv7, lvlDiv7];
|
||||
preference = (function() {
|
||||
switch (user.stats["class"]) {
|
||||
case "wizard":
|
||||
return ["int", "per", "con", "str"];
|
||||
case "rogue":
|
||||
return ["per", "str", "int", "con"];
|
||||
case "healer":
|
||||
return ["con", "int", "str", "per"];
|
||||
default:
|
||||
return ["str", "con", "per", "int"];
|
||||
}
|
||||
})();
|
||||
diff = [user.stats[preference[0]] - ideal[0], user.stats[preference[1]] - ideal[1], user.stats[preference[2]] - ideal[2], user.stats[preference[3]] - ideal[3]];
|
||||
suggested = _.findIndex(diff, (function(val) {
|
||||
if (val === _.min(diff)) {
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
if (~suggested) {
|
||||
return preference[suggested];
|
||||
} else {
|
||||
return "str";
|
||||
}
|
||||
case "taskbased":
|
||||
suggested = _.invert(user.stats.training)[_.max(user.stats.training)];
|
||||
_.merge(user.stats.training, {
|
||||
str: 0,
|
||||
int: 0,
|
||||
con: 0,
|
||||
per: 0
|
||||
});
|
||||
return suggested || "str";
|
||||
default:
|
||||
return "str";
|
||||
}
|
||||
})()]++;
|
||||
};
|
||||
15
common/script/fns/crit.js
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = function(user, stat, chance) {
|
||||
var s;
|
||||
if (stat == null) {
|
||||
stat = 'str';
|
||||
}
|
||||
if (chance == null) {
|
||||
chance = .03;
|
||||
}
|
||||
s = user._statsComputed[stat];
|
||||
if (user.fns.predictableRandom() <= chance * (1 + s / 100)) {
|
||||
return 1.5 + 4 * s / (s + 200);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
279
common/script/fns/cron.js
Normal file
@@ -0,0 +1,279 @@
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
daysSince,
|
||||
shouldDo,
|
||||
} from '../cron';
|
||||
import {
|
||||
capByLevel,
|
||||
toNextLevel,
|
||||
} from '../statHelpers';
|
||||
/*
|
||||
------------------------------------------------------
|
||||
Cron
|
||||
------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
At end of day, add value to all incomplete Daily & Todo tasks (further incentive)
|
||||
For incomplete Dailys, deduct experience
|
||||
Make sure to run this function once in a while as server will not take care of overnight calculations.
|
||||
And you have to run it every time client connects.
|
||||
{user}
|
||||
*/
|
||||
|
||||
module.exports = function(user, options) {
|
||||
var _progress, analyticsData, base, base1, base2, base3, base4, clearBuffs, dailyChecked, dailyDueUnchecked, daysMissed, expTally, lvl, lvlDiv2, multiDaysCountAsOneDay, now, perfect, plan, progress, ref, ref1, ref2, ref3, todoTally;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
now = +options.now || +(new Date);
|
||||
daysMissed = daysSince(user.lastCron, _.defaults({
|
||||
now: now
|
||||
}, user.preferences));
|
||||
if (!(daysMissed > 0)) {
|
||||
return;
|
||||
}
|
||||
user.auth.timestamps.loggedin = new Date();
|
||||
user.lastCron = now;
|
||||
if (user.items.lastDrop.count > 0) {
|
||||
user.items.lastDrop.count = 0;
|
||||
}
|
||||
perfect = true;
|
||||
clearBuffs = {
|
||||
str: 0,
|
||||
int: 0,
|
||||
per: 0,
|
||||
con: 0,
|
||||
stealth: 0,
|
||||
streaks: false
|
||||
};
|
||||
plan = (ref = user.purchased) != null ? ref.plan : void 0;
|
||||
if (plan != null ? plan.customerId : void 0) {
|
||||
if (typeof plan.dateUpdated === "undefined") {
|
||||
// partial compensation for bug in subscription creation - https://github.com/HabitRPG/habitrpg/issues/6682
|
||||
plan.dateUpdated = new Date();
|
||||
}
|
||||
if (moment(plan.dateUpdated).format('MMYYYY') !== moment().format('MMYYYY')) {
|
||||
plan.gemsBought = 0;
|
||||
plan.dateUpdated = new Date();
|
||||
_.defaults(plan.consecutive, {
|
||||
count: 0,
|
||||
offset: 0,
|
||||
trinkets: 0,
|
||||
gemCapExtra: 0
|
||||
});
|
||||
plan.consecutive.count++;
|
||||
if (plan.consecutive.offset > 0) {
|
||||
plan.consecutive.offset--;
|
||||
} else if (plan.consecutive.count % 3 === 0) {
|
||||
plan.consecutive.trinkets++;
|
||||
plan.consecutive.gemCapExtra += 5;
|
||||
if (plan.consecutive.gemCapExtra > 25) {
|
||||
plan.consecutive.gemCapExtra = 25;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (plan.dateTerminated && moment(plan.dateTerminated).isBefore(+(new Date))) {
|
||||
_.merge(plan, {
|
||||
planId: null,
|
||||
customerId: null,
|
||||
paymentMethod: null
|
||||
});
|
||||
_.merge(plan.consecutive, {
|
||||
count: 0,
|
||||
offset: 0,
|
||||
gemCapExtra: 0
|
||||
});
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('purchased.plan');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (user.preferences.sleep === true) {
|
||||
user.stats.buffs = clearBuffs;
|
||||
user.dailys.forEach(function(daily) {
|
||||
var completed, repeat, thatDay;
|
||||
completed = daily.completed, repeat = daily.repeat;
|
||||
thatDay = moment(now).subtract({
|
||||
days: 1
|
||||
});
|
||||
if (shouldDo(thatDay.toDate(), daily, user.preferences) || completed) {
|
||||
_.each(daily.checklist, (function(box) {
|
||||
box.completed = false;
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
return daily.completed = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
multiDaysCountAsOneDay = true;
|
||||
todoTally = 0;
|
||||
user.todos.forEach(function(task) {
|
||||
var absVal, completed, delta, id;
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
id = task.id, completed = task.completed;
|
||||
delta = user.ops.score({
|
||||
params: {
|
||||
id: task.id,
|
||||
direction: 'down'
|
||||
},
|
||||
query: {
|
||||
times: multiDaysCountAsOneDay != null ? multiDaysCountAsOneDay : {
|
||||
1: daysMissed
|
||||
},
|
||||
cron: true
|
||||
}
|
||||
});
|
||||
absVal = completed ? Math.abs(task.value) : task.value;
|
||||
return todoTally += absVal;
|
||||
});
|
||||
dailyChecked = 0;
|
||||
dailyDueUnchecked = 0;
|
||||
if ((base = user.party.quest.progress).down == null) {
|
||||
base.down = 0;
|
||||
}
|
||||
user.dailys.forEach(function(task) {
|
||||
var EvadeTask, completed, delta, fractionChecked, id, j, n, ref1, ref2, scheduleMisses, thatDay;
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
id = task.id, completed = task.completed;
|
||||
EvadeTask = 0;
|
||||
scheduleMisses = daysMissed;
|
||||
if (completed) {
|
||||
dailyChecked += 1;
|
||||
} else {
|
||||
scheduleMisses = 0;
|
||||
for (n = j = 0, ref1 = daysMissed; 0 <= ref1 ? j < ref1 : j > ref1; n = 0 <= ref1 ? ++j : --j) {
|
||||
thatDay = moment(now).subtract({
|
||||
days: n + 1
|
||||
});
|
||||
if (shouldDo(thatDay.toDate(), task, user.preferences)) {
|
||||
scheduleMisses++;
|
||||
if (user.stats.buffs.stealth) {
|
||||
user.stats.buffs.stealth--;
|
||||
EvadeTask++;
|
||||
}
|
||||
if (multiDaysCountAsOneDay) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scheduleMisses > EvadeTask) {
|
||||
perfect = false;
|
||||
if (((ref2 = task.checklist) != null ? ref2.length : void 0) > 0) {
|
||||
fractionChecked = _.reduce(task.checklist, (function(m, i) {
|
||||
return m + (i.completed ? 1 : 0);
|
||||
}), 0) / task.checklist.length;
|
||||
dailyDueUnchecked += 1 - fractionChecked;
|
||||
dailyChecked += fractionChecked;
|
||||
} else {
|
||||
dailyDueUnchecked += 1;
|
||||
}
|
||||
delta = user.ops.score({
|
||||
params: {
|
||||
id: task.id,
|
||||
direction: 'down'
|
||||
},
|
||||
query: {
|
||||
times: multiDaysCountAsOneDay != null ? multiDaysCountAsOneDay : {
|
||||
1: scheduleMisses - EvadeTask
|
||||
},
|
||||
cron: true
|
||||
}
|
||||
});
|
||||
user.party.quest.progress.down += delta * (task.priority < 1 ? task.priority : 1);
|
||||
}
|
||||
}
|
||||
(task.history != null ? task.history : task.history = []).push({
|
||||
date: +(new Date),
|
||||
value: task.value
|
||||
});
|
||||
task.completed = false;
|
||||
if (completed || (scheduleMisses > 0)) {
|
||||
return _.each(task.checklist, (function(i) {
|
||||
i.completed = false;
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
});
|
||||
user.habits.forEach(function(task) {
|
||||
if (task.up === false || task.down === false) {
|
||||
if (Math.abs(task.value) < 0.1) {
|
||||
return task.value = 0;
|
||||
} else {
|
||||
return task.value = task.value / 2;
|
||||
}
|
||||
}
|
||||
});
|
||||
((base1 = (user.history != null ? user.history : user.history = {})).todos != null ? base1.todos : base1.todos = []).push({
|
||||
date: now,
|
||||
value: todoTally
|
||||
});
|
||||
expTally = user.stats.exp;
|
||||
lvl = 0;
|
||||
while (lvl < (user.stats.lvl - 1)) {
|
||||
lvl++;
|
||||
expTally += toNextLevel(lvl);
|
||||
}
|
||||
((base2 = user.history).exp != null ? base2.exp : base2.exp = []).push({
|
||||
date: now,
|
||||
value: expTally
|
||||
});
|
||||
if (!((ref1 = user.purchased) != null ? (ref2 = ref1.plan) != null ? ref2.customerId : void 0 : void 0)) {
|
||||
user.fns.preenUserHistory();
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('history');
|
||||
}
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('dailys');
|
||||
}
|
||||
}
|
||||
user.stats.buffs = perfect ? ((base3 = user.achievements).perfect != null ? base3.perfect : base3.perfect = 0, user.achievements.perfect++, lvlDiv2 = Math.ceil(capByLevel(user.stats.lvl) / 2), {
|
||||
str: lvlDiv2,
|
||||
int: lvlDiv2,
|
||||
per: lvlDiv2,
|
||||
con: lvlDiv2,
|
||||
stealth: 0,
|
||||
streaks: false
|
||||
}) : clearBuffs;
|
||||
if (dailyDueUnchecked === 0 && dailyChecked === 0) {
|
||||
dailyChecked = 1;
|
||||
}
|
||||
user.stats.mp += _.max([10, .1 * user._statsComputed.maxMP]) * dailyChecked / (dailyDueUnchecked + dailyChecked);
|
||||
if (user.stats.mp > user._statsComputed.maxMP) {
|
||||
user.stats.mp = user._statsComputed.maxMP;
|
||||
}
|
||||
progress = user.party.quest.progress;
|
||||
_progress = _.cloneDeep(progress);
|
||||
_.merge(progress, {
|
||||
down: 0,
|
||||
up: 0
|
||||
});
|
||||
progress.collect = _.transform(progress.collect, (function(m, v, k) {
|
||||
return m[k] = 0;
|
||||
}));
|
||||
if ((base4 = user.flags).cronCount == null) {
|
||||
base4.cronCount = 0;
|
||||
}
|
||||
user.flags.cronCount++;
|
||||
analyticsData = {
|
||||
category: 'behavior',
|
||||
gaLabel: 'Cron Count',
|
||||
gaValue: user.flags.cronCount,
|
||||
uuid: user._id,
|
||||
user: user,
|
||||
resting: user.preferences.sleep,
|
||||
cronCount: user.flags.cronCount,
|
||||
progressUp: _.min([_progress.up, 900]),
|
||||
progressDown: _progress.down
|
||||
};
|
||||
if ((ref3 = options.analytics) != null) {
|
||||
ref3.track('Cron', analyticsData);
|
||||
}
|
||||
return _progress;
|
||||
};
|
||||
5
common/script/fns/dotGet.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import dotGet from '../libs/dotGet';
|
||||
|
||||
module.exports = function(user, path) {
|
||||
return dotGet(user, path);
|
||||
};
|
||||
12
common/script/fns/dotSet.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import dotSet from '../libs/dotSet';
|
||||
|
||||
/*
|
||||
This allows you to set object properties by dot-path. Eg, you can run pathSet('stats.hp',50,user) which is the same as
|
||||
user.stats.hp = 50. This is useful because in our habitrpg-shared functions we're returning changesets as {path:value},
|
||||
so that different consumers can implement setters their own way. Derby needs model.set(path, value) for example, where
|
||||
Angular sets object properties directly - in which case, this function will be used.
|
||||
*/
|
||||
|
||||
module.exports = function(user, path, val) {
|
||||
return dotSet(user, path, val);
|
||||
};
|
||||
11
common/script/fns/getItem.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function(user, type) {
|
||||
var item;
|
||||
item = content.gear.flat[user.items.gear.equipped[type]];
|
||||
if (!item) {
|
||||
return content.gear.flat[type + "_base_0"];
|
||||
}
|
||||
return item;
|
||||
};
|
||||
24
common/script/fns/handleTwoHanded.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
|
||||
module.exports = function(user, item, type, req) {
|
||||
var message, currentWeapon, currentShield;
|
||||
if (type == null) {
|
||||
type = 'equipped';
|
||||
}
|
||||
currentShield = content.gear.flat[user.items.gear[type].shield];
|
||||
currentWeapon = content.gear.flat[user.items.gear[type].weapon];
|
||||
|
||||
if (item.type === "shield" && (currentWeapon ? currentWeapon.twoHanded : false)) {
|
||||
user.items.gear[type].weapon = 'weapon_base_0';
|
||||
message = i18n.t('messageTwoHandedUnequip', {
|
||||
twoHandedText: currentWeapon.text(req.language), offHandedText: item.text(req.language),
|
||||
}, req.language);
|
||||
} else if (item.twoHanded && (currentShield && user.items.gear[type].shield != "shield_base_0")) {
|
||||
user.items.gear[type].shield = "shield_base_0";
|
||||
message = i18n.t('messageTwoHandedEquip', {
|
||||
twoHandedText: item.text(req.language), offHandedText: currentShield.text(req.language),
|
||||
}, req.language);
|
||||
}
|
||||
return message;
|
||||
};
|
||||
31
common/script/fns/index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import getItem from './getItem';
|
||||
import handleTwoHanded from './handleTwoHanded';
|
||||
import predictableRandom from './predictableRandom';
|
||||
import crit from './crit';
|
||||
import randomVal from './randomVal';
|
||||
import dotSet from './dotSet';
|
||||
import dotGet from './dotGet';
|
||||
import randomDrop from './randomDrop';
|
||||
import autoAllocate from './autoAllocate';
|
||||
import updateStats from './updateStats';
|
||||
import cron from './cron';
|
||||
import preenUserHistory from './preenUserHistory';
|
||||
import ultimateGear from './ultimateGear';
|
||||
import nullify from './nullify';
|
||||
|
||||
module.exports = {
|
||||
getItem,
|
||||
handleTwoHanded,
|
||||
predictableRandom,
|
||||
crit,
|
||||
randomVal,
|
||||
dotSet,
|
||||
dotGet,
|
||||
randomDrop,
|
||||
autoAllocate,
|
||||
updateStats,
|
||||
cron,
|
||||
preenUserHistory,
|
||||
ultimateGear,
|
||||
nullify,
|
||||
};
|
||||
5
common/script/fns/nullify.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = function(user) {
|
||||
user.ops = null;
|
||||
user.fns = null;
|
||||
return user = null;
|
||||
};
|
||||
20
common/script/fns/predictableRandom.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import _ from 'lodash';
|
||||
/*
|
||||
Because the same op needs to be performed on the client and the server (critical hits, item drops, etc),
|
||||
we need things to be "random", but technically predictable so that they don't go out-of-sync
|
||||
*/
|
||||
|
||||
module.exports = function(user, seed) {
|
||||
var x;
|
||||
if (!seed || seed === Math.PI) {
|
||||
seed = _.reduce(user.stats, (function(m, v) {
|
||||
if (_.isNumber(v)) {
|
||||
return m + v;
|
||||
} else {
|
||||
return m;
|
||||
}
|
||||
}), 0);
|
||||
}
|
||||
x = Math.sin(seed++) * 10000;
|
||||
return x - Math.floor(x);
|
||||
};
|
||||
25
common/script/fns/preenUserHistory.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import _ from 'lodash';
|
||||
import preenHistory from '../libs/preenHistory';
|
||||
|
||||
module.exports = function(user, minHistLen) {
|
||||
if (minHistLen == null) {
|
||||
minHistLen = 7;
|
||||
}
|
||||
_.each(user.habits.concat(user.dailys), function(task) {
|
||||
var ref;
|
||||
if (((ref = task.history) != null ? ref.length : void 0) > minHistLen) {
|
||||
task.history = preenHistory(task.history);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
_.defaults(user.history, {
|
||||
todos: [],
|
||||
exp: []
|
||||
});
|
||||
if (user.history.exp.length > minHistLen) {
|
||||
user.history.exp = preenHistory(user.history.exp);
|
||||
}
|
||||
if (user.history.todos.length > minHistLen) {
|
||||
return user.history.todos = preenHistory(user.history.todos);
|
||||
}
|
||||
};
|
||||
75
common/script/fns/randomDrop.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import _ from 'lodash';
|
||||
import content from '../content/index';
|
||||
import i18n from '../i18n';
|
||||
import { daysSince } from '../cron';
|
||||
import { diminishingReturns } from '../statHelpers';
|
||||
|
||||
module.exports = function(user, modifiers, req) {
|
||||
var acceptableDrops, base, base1, base2, chance, drop, dropK, dropMultiplier, name, name1, name2, quest, rarity, ref, ref1, ref2, ref3, task;
|
||||
task = modifiers.task;
|
||||
chance = _.min([Math.abs(task.value - 21.27), 37.5]) / 150 + .02;
|
||||
chance *= task.priority * (1 + (task.streak / 100 || 0)) * (1 + (user._statsComputed.per / 100)) * (1 + (user.contributor.level / 40 || 0)) * (1 + (user.achievements.rebirths / 20 || 0)) * (1 + (user.achievements.streak / 200 || 0)) * (user._tmp.crit || 1) * (1 + .5 * (_.reduce(task.checklist, (function(m, i) {
|
||||
return m + (i.completed ? 1 : 0);
|
||||
}), 0) || 0));
|
||||
chance = diminishingReturns(chance, 0.75);
|
||||
quest = content.quests[(ref = user.party.quest) != null ? ref.key : void 0];
|
||||
if ((quest != null ? quest.collect : void 0) && user.fns.predictableRandom(user.stats.gp) < chance) {
|
||||
dropK = user.fns.randomVal(quest.collect, {
|
||||
key: true
|
||||
});
|
||||
user.party.quest.progress.collect[dropK]++;
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('party.quest.progress');
|
||||
}
|
||||
}
|
||||
dropMultiplier = ((ref1 = user.purchased) != null ? (ref2 = ref1.plan) != null ? ref2.customerId : void 0 : void 0) ? 2 : 1;
|
||||
if ((daysSince(user.items.lastDrop.date, user.preferences) === 0) && (user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level || 0)))) {
|
||||
return;
|
||||
}
|
||||
if (((ref3 = user.flags) != null ? ref3.dropsEnabled : void 0) && user.fns.predictableRandom(user.stats.exp) < chance) {
|
||||
rarity = user.fns.predictableRandom(user.stats.gp);
|
||||
if (rarity > .6) {
|
||||
drop = user.fns.randomVal(_.where(content.food, {
|
||||
canDrop: true
|
||||
}));
|
||||
if ((base = user.items.food)[name = drop.key] == null) {
|
||||
base[name] = 0;
|
||||
}
|
||||
user.items.food[drop.key] += 1;
|
||||
drop.type = 'Food';
|
||||
drop.dialog = i18n.t('messageDropFood', {
|
||||
dropArticle: drop.article,
|
||||
dropText: drop.text(req.language),
|
||||
dropNotes: drop.notes(req.language)
|
||||
}, req.language);
|
||||
} else if (rarity > .3) {
|
||||
drop = user.fns.randomVal(content.dropEggs);
|
||||
if ((base1 = user.items.eggs)[name1 = drop.key] == null) {
|
||||
base1[name1] = 0;
|
||||
}
|
||||
user.items.eggs[drop.key]++;
|
||||
drop.type = 'Egg';
|
||||
drop.dialog = i18n.t('messageDropEgg', {
|
||||
dropText: drop.text(req.language),
|
||||
dropNotes: drop.notes(req.language)
|
||||
}, req.language);
|
||||
} else {
|
||||
acceptableDrops = rarity < .02 ? ['Golden'] : rarity < .09 ? ['Zombie', 'CottonCandyPink', 'CottonCandyBlue'] : rarity < .18 ? ['Red', 'Shade', 'Skeleton'] : ['Base', 'White', 'Desert'];
|
||||
drop = user.fns.randomVal(_.pick(content.hatchingPotions, (function(v, k) {
|
||||
return acceptableDrops.indexOf(k) >= 0;
|
||||
})));
|
||||
if ((base2 = user.items.hatchingPotions)[name2 = drop.key] == null) {
|
||||
base2[name2] = 0;
|
||||
}
|
||||
user.items.hatchingPotions[drop.key]++;
|
||||
drop.type = 'HatchingPotion';
|
||||
drop.dialog = i18n.t('messageDropPotion', {
|
||||
dropText: drop.text(req.language),
|
||||
dropNotes: drop.notes(req.language)
|
||||
}, req.language);
|
||||
}
|
||||
user._tmp.drop = drop;
|
||||
user.items.lastDrop.date = +(new Date);
|
||||
return user.items.lastDrop.count++;
|
||||
}
|
||||
};
|
||||
14
common/script/fns/randomVal.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
Get a random property from an object
|
||||
returns random property (the value)
|
||||
*/
|
||||
|
||||
module.exports = function(user, obj, options) {
|
||||
var array, rand;
|
||||
array = (options != null ? options.key : void 0) ? _.keys(obj) : _.values(obj);
|
||||
rand = user.fns.predictableRandom(options != null ? options.seed : void 0);
|
||||
array.sort();
|
||||
return array[Math.floor(rand * array.length)];
|
||||
};
|
||||
33
common/script/fns/ultimateGear.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import content from '../content/index';
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function(user) {
|
||||
var base, owned;
|
||||
owned = typeof window !== "undefined" && window !== null ? user.items.gear.owned : user.items.gear.owned.toObject();
|
||||
if ((base = user.achievements).ultimateGearSets == null) {
|
||||
base.ultimateGearSets = {
|
||||
healer: false,
|
||||
wizard: false,
|
||||
rogue: false,
|
||||
warrior: false
|
||||
};
|
||||
}
|
||||
content.classes.forEach(function(klass) {
|
||||
if (user.achievements.ultimateGearSets[klass] !== true) {
|
||||
return user.achievements.ultimateGearSets[klass] = _.reduce(['armor', 'shield', 'head', 'weapon'], function(soFarGood, type) {
|
||||
var found;
|
||||
found = _.find(content.gear.tree[type][klass], {
|
||||
last: true
|
||||
});
|
||||
return soFarGood && (!found || owned[found.key] === true);
|
||||
}, true);
|
||||
}
|
||||
});
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('achievements.ultimateGearSets');
|
||||
}
|
||||
if (_.contains(user.achievements.ultimateGearSets, true) && user.flags.armoireEnabled !== true) {
|
||||
user.flags.armoireEnabled = true;
|
||||
return typeof user.markModified === "function" ? user.markModified('flags') : void 0;
|
||||
}
|
||||
};
|
||||
109
common/script/fns/updateStats.js
Normal file
@@ -0,0 +1,109 @@
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
MAX_HEALTH,
|
||||
MAX_STAT_POINTS
|
||||
} from '../constants';
|
||||
import { toNextLevel } from '../statHelpers';
|
||||
module.exports = function (user, stats, req, analytics) {
|
||||
let allocatedStatPoints;
|
||||
let totalStatPoints;
|
||||
let experienceToNextLevel;
|
||||
|
||||
if (stats.hp <= 0) {
|
||||
user.stats.hp = 0;
|
||||
return user.stats.hp;
|
||||
}
|
||||
|
||||
user.stats.hp = stats.hp;
|
||||
user.stats.gp = stats.gp >= 0 ? stats.gp : 0;
|
||||
|
||||
experienceToNextLevel = toNextLevel(user.stats.lvl);
|
||||
|
||||
if (stats.exp >= experienceToNextLevel) {
|
||||
user.stats.exp = stats.exp;
|
||||
|
||||
while (stats.exp >= experienceToNextLevel) {
|
||||
stats.exp -= experienceToNextLevel;
|
||||
user.stats.lvl++;
|
||||
|
||||
experienceToNextLevel = toNextLevel(user.stats.lvl);
|
||||
user.stats.hp = MAX_HEALTH;
|
||||
allocatedStatPoints = user.stats.str + user.stats.int + user.stats.con + user.stats.per;
|
||||
totalStatPoints = allocatedStatPoints + user.stats.points;
|
||||
|
||||
if (totalStatPoints >= MAX_STAT_POINTS) {
|
||||
continue; // eslint-disable-line no-continue
|
||||
}
|
||||
if (user.preferences.automaticAllocation) {
|
||||
user.fns.autoAllocate();
|
||||
} else {
|
||||
user.stats.points = user.stats.lvl - allocatedStatPoints;
|
||||
totalStatPoints = user.stats.points + allocatedStatPoints;
|
||||
|
||||
if (totalStatPoints > MAX_STAT_POINTS) {
|
||||
user.stats.points = MAX_STAT_POINTS - allocatedStatPoints;
|
||||
}
|
||||
|
||||
if (user.stats.points < 0) {
|
||||
user.stats.points = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
user.stats.exp = stats.exp;
|
||||
user.flags = user.flags || {};
|
||||
|
||||
if (!user.flags.customizationsNotification && (user.stats.exp > 5 || user.stats.lvl > 1)) {
|
||||
user.flags.customizationsNotification = true;
|
||||
}
|
||||
if (!user.flags.itemsEnabled && (user.stats.exp > 10 || user.stats.lvl > 1)) {
|
||||
user.flags.itemsEnabled = true;
|
||||
}
|
||||
if (!user.flags.dropsEnabled && user.stats.lvl >= 3) {
|
||||
user.flags.dropsEnabled = true;
|
||||
if (user.items.eggs["Wolf"] > 0) {
|
||||
user.items.eggs["Wolf"]++;
|
||||
} else {
|
||||
user.items.eggs["Wolf"] = 1;
|
||||
}
|
||||
}
|
||||
if (!user.flags.classSelected && user.stats.lvl >= 10) {
|
||||
user.flags.classSelected;
|
||||
}
|
||||
_.each({
|
||||
vice1: 30,
|
||||
atom1: 15,
|
||||
moonstone1: 60,
|
||||
goldenknight1: 40
|
||||
}, function(lvl, k) {
|
||||
var analyticsData, base, base1, ref;
|
||||
if (!((ref = user.flags.levelDrops) != null ? ref[k] : void 0) && user.stats.lvl >= lvl) {
|
||||
if ((base = user.items.quests)[k] == null) {
|
||||
base[k] = 0;
|
||||
}
|
||||
user.items.quests[k]++;
|
||||
((base1 = user.flags).levelDrops != null ? base1.levelDrops : base1.levelDrops = {})[k] = true;
|
||||
if (typeof user.markModified === "function") {
|
||||
user.markModified('flags.levelDrops');
|
||||
}
|
||||
analyticsData = {
|
||||
uuid: user._id,
|
||||
itemKey: k,
|
||||
acquireMethod: 'Level Drop',
|
||||
category: 'behavior'
|
||||
};
|
||||
if (analytics != null) {
|
||||
analytics.track('acquire item', analyticsData);
|
||||
}
|
||||
if (!user._tmp) user._tmp = {}
|
||||
return user._tmp.drop = {
|
||||
type: 'Quest',
|
||||
key: k
|
||||
};
|
||||
}
|
||||
});
|
||||
if (!user.flags.rebirthEnabled && (user.stats.lvl >= 50 || user.achievements.beastMaster)) {
|
||||
return user.flags.rebirthEnabled = true;
|
||||
}
|
||||
};
|
||||
19
common/script/libs/appliedTags.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
Are there tags applied?
|
||||
*/
|
||||
|
||||
module.exports = function(userTags, taskTags) {
|
||||
var arr;
|
||||
arr = [];
|
||||
_.each(userTags, function(t) {
|
||||
if (t == null) {
|
||||
return;
|
||||
}
|
||||
if (taskTags != null ? taskTags[t.id] : void 0) {
|
||||
return arr.push(t.name);
|
||||
}
|
||||
});
|
||||
return arr.join(', ');
|
||||
};
|
||||
7
common/script/libs/countExists.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function(items) {
|
||||
return _.reduce(items, (function(m, v) {
|
||||
return m + (v ? 1 : 0);
|
||||
}), 0);
|
||||
};
|
||||
9
common/script/libs/dotGet.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function(obj, path) {
|
||||
return _.reduce(path.split('.'), ((function(_this) {
|
||||
return function(curr, next) {
|
||||
return curr != null ? curr[next] : void 0;
|
||||
};
|
||||
})(this)), obj);
|
||||
};
|
||||
14
common/script/libs/dotSet.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
module.exports = function(obj, path, val) {
|
||||
var arr;
|
||||
arr = path.split('.');
|
||||
return _.reduce(arr, (function(_this) {
|
||||
return function(curr, next, index) {
|
||||
if ((arr.length - 1) === index) {
|
||||
curr[next] = val;
|
||||
}
|
||||
return curr[next] != null ? curr[next] : curr[next] = {};
|
||||
};
|
||||
})(this), obj);
|
||||
};
|
||||
9
common/script/libs/encodeiCalLink.js
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
Encode the download link for .ics iCal file
|
||||
*/
|
||||
|
||||
module.exports = function(uid, apiToken) {
|
||||
var loc, ref;
|
||||
loc = (typeof window !== "undefined" && window !== null ? window.location.host : void 0) || (typeof process !== "undefined" && process !== null ? (ref = process.env) != null ? ref.BASE_URL : void 0 : void 0) || '';
|
||||
return encodeURIComponent("http://" + loc + "/v1/users/" + uid + "/calendar.ics?apiToken=" + apiToken);
|
||||
};
|
||||
9
common/script/libs/friendlyTimestamp.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import moment from 'moment';
|
||||
|
||||
/*
|
||||
Friendly timestamp
|
||||
*/
|
||||
|
||||
module.exports = function(timestamp) {
|
||||
return moment(timestamp).format('MM/DD h:mm:ss a');
|
||||
};
|
||||
7
common/script/libs/gold.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = function(num) {
|
||||
if (num) {
|
||||
return Math.floor(num);
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
};
|
||||
46
common/script/libs/index.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import uuid from './uuid';
|
||||
import taskDefaults from './taskDefaults';
|
||||
import refPush from './refPush';
|
||||
import splitWhitespace from './splitWhitespace';
|
||||
import planGemLimits from './planGemLimits';
|
||||
import preenTodos from './preenTodos';
|
||||
import dotSet from './dotSet';
|
||||
import dotGet from './dotGet';
|
||||
import preenHistory from './preenHistory';
|
||||
import countExists from './countExists';
|
||||
import updateStore from './updateStore';
|
||||
|
||||
import appliedTags from './appliedTags';
|
||||
import encodeiCalLink from './encodeiCalLink';
|
||||
import friendlyTimestamp from './friendlyTimestamp';
|
||||
import gold from './gold';
|
||||
import newChatMessages from './newChatMessages';
|
||||
import noTags from './noTags';
|
||||
import percent from './percent';
|
||||
import removeWhitespace from './removeWhitespace';
|
||||
import silver from './silver';
|
||||
import taskClasses from './taskClasses';
|
||||
|
||||
module.exports = {
|
||||
uuid,
|
||||
taskDefaults,
|
||||
refPush,
|
||||
splitWhitespace,
|
||||
planGemLimits,
|
||||
preenTodos,
|
||||
dotSet,
|
||||
dotGet,
|
||||
preenHistory,
|
||||
countExists,
|
||||
updateStore,
|
||||
appliedTags,
|
||||
encodeiCalLink,
|
||||
friendlyTimestamp,
|
||||
gold,
|
||||
newChatMessages,
|
||||
noTags,
|
||||
percent,
|
||||
removeWhitespace,
|
||||
silver,
|
||||
taskClasses,
|
||||
};
|
||||
10
common/script/libs/newChatMessages.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
Does user have new chat messages?
|
||||
*/
|
||||
|
||||
module.exports = function(messages, lastMessageSeen) {
|
||||
if (!((messages != null ? messages.length : void 0) > 0)) {
|
||||
return false;
|
||||
}
|
||||
return (messages != null ? messages[0] : void 0) && (messages[0].id !== lastMessageSeen);
|
||||
};
|
||||
11
common/script/libs/noTags.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
are any tags active?
|
||||
*/
|
||||
|
||||
module.exports = function(tags) {
|
||||
return _.isEmpty(tags) || _.isEmpty(_.filter(tags, function(t) {
|
||||
return t;
|
||||
}));
|
||||
};
|
||||
17
common/script/libs/percent.js
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = function(x, y, dir) {
|
||||
var roundFn;
|
||||
switch (dir) {
|
||||
case "up":
|
||||
roundFn = Math.ceil;
|
||||
break;
|
||||
case "down":
|
||||
roundFn = Math.floor;
|
||||
break;
|
||||
default:
|
||||
roundFn = Math.round;
|
||||
}
|
||||
if (x === 0) {
|
||||
x = 1;
|
||||
}
|
||||
return Math.max(0, roundFn(x / y * 100));
|
||||
};
|
||||
4
common/script/libs/planGemLimits.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
convRate: 20,
|
||||
convCap: 25,
|
||||
};
|
||||
43
common/script/libs/preenHistory.js
Normal file
@@ -0,0 +1,43 @@
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
Preen history for users with > 7 history entries
|
||||
This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array
|
||||
of averages, condensing more the further back in time we go. Eg, 7 entries each for last 7 days; 1 entry each week
|
||||
of this month; 1 entry for each month of this year; 1 entry per previous year: [day*7 week*4 month*12 year*infinite]
|
||||
*/
|
||||
|
||||
module.exports = function(history) {
|
||||
var newHistory, preen, thisMonth;
|
||||
history = _.filter(history, function(h) {
|
||||
return !!h;
|
||||
});
|
||||
newHistory = [];
|
||||
preen = function(amount, groupBy) {
|
||||
var groups;
|
||||
groups = _.chain(history).groupBy(function(h) {
|
||||
return moment(h.date).format(groupBy);
|
||||
}).sortBy(function(h, k) {
|
||||
return k;
|
||||
}).value();
|
||||
groups = groups.slice(-amount);
|
||||
groups.pop();
|
||||
return _.each(groups, function(group) {
|
||||
newHistory.push({
|
||||
date: moment(group[0].date).toDate(),
|
||||
value: _.reduce(group, (function(m, obj) {
|
||||
return m + obj.value;
|
||||
}), 0) / group.length
|
||||
});
|
||||
return true;
|
||||
});
|
||||
};
|
||||
preen(50, "YYYY");
|
||||
preen(moment().format('MM'), "YYYYMM");
|
||||
thisMonth = moment().format('YYYYMM');
|
||||
newHistory = newHistory.concat(_.filter(history, function(h) {
|
||||
return moment(h.date).format('YYYYMM') === thisMonth;
|
||||
}));
|
||||
return newHistory;
|
||||
};
|
||||
14
common/script/libs/preenTodos.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import moment from 'moment';
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
Preen 3-day past-completed To-Dos from Angular & mobile app
|
||||
*/
|
||||
|
||||
module.exports = function(tasks) {
|
||||
return _.filter(tasks, function(t) {
|
||||
return !t.completed || (t.challenge && t.challenge.id) || moment(t.dateCompleted).isAfter(moment().subtract({
|
||||
days: 3
|
||||
}));
|
||||
});
|
||||
};
|
||||
19
common/script/libs/refPush.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import _ from 'lodash';
|
||||
import uuid from './uuid';
|
||||
|
||||
/*
|
||||
Reflists are arrays, but stored as objects. Mongoose has a helluvatime working with arrays (the main problem for our
|
||||
syncing issues) - so the goal is to move away from arrays to objects, since mongoose can reference elements by ID
|
||||
no problem. To maintain sorting, we use these helper functions:
|
||||
*/
|
||||
|
||||
module.exports = function(reflist, item, prune) {
|
||||
if (prune == null) {
|
||||
prune = 0;
|
||||
}
|
||||
item.sort = _.isEmpty(reflist) ? 0 : _.max(reflist, 'sort').sort + 1;
|
||||
if (!(item.id && !reflist[item.id])) {
|
||||
item.id = uuid();
|
||||
}
|
||||
return reflist[item.id] = item;
|
||||
};
|
||||
10
common/script/libs/removeWhitespace.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
Remove whitespace #FIXME are we using this anywwhere? Should we be?
|
||||
*/
|
||||
|
||||
module.exports = function(str) {
|
||||
if (!str) {
|
||||
return '';
|
||||
}
|
||||
return str.replace(/\s/g, '');
|
||||
};
|
||||
11
common/script/libs/silver.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Silver amount from their money
|
||||
*/
|
||||
|
||||
module.exports = function(num) {
|
||||
if (num) {
|
||||
return ("0" + Math.floor((num - Math.floor(num)) * 100)).slice(-2);
|
||||
} else {
|
||||
return "00";
|
||||
}
|
||||
};
|
||||
3
common/script/libs/splitWhitespace.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function(s) {
|
||||
return s.split(' ');
|
||||
};
|
||||
83
common/script/libs/taskClasses.js
Normal file
@@ -0,0 +1,83 @@
|
||||
import {
|
||||
shouldDo
|
||||
} from '../cron';
|
||||
/*
|
||||
Task classes given everything about the class
|
||||
*/
|
||||
module.exports = function(task, filters, dayStart, lastCron, showCompleted, main) {
|
||||
var classes, completed, enabled, filter, priority, ref, repeat, type, value;
|
||||
if (filters == null) {
|
||||
filters = [];
|
||||
}
|
||||
if (dayStart == null) {
|
||||
dayStart = 0;
|
||||
}
|
||||
if (lastCron == null) {
|
||||
lastCron = +(new Date);
|
||||
}
|
||||
if (showCompleted == null) {
|
||||
showCompleted = false;
|
||||
}
|
||||
if (main == null) {
|
||||
main = false;
|
||||
}
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
type = task.type, completed = task.completed, value = task.value, repeat = task.repeat, priority = task.priority;
|
||||
if (main) {
|
||||
if (!task._editing) {
|
||||
for (filter in filters) {
|
||||
enabled = filters[filter];
|
||||
if (enabled && !((ref = task.tags) != null ? ref[filter] : void 0)) {
|
||||
return 'hidden';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
classes = type;
|
||||
if (task._editing) {
|
||||
classes += " beingEdited";
|
||||
}
|
||||
if (type === 'todo' || type === 'daily') {
|
||||
if (completed || (type === 'daily' && !shouldDo(+(new Date), task, {
|
||||
dayStart: dayStart
|
||||
}))) {
|
||||
classes += " completed";
|
||||
} else {
|
||||
classes += " uncompleted";
|
||||
}
|
||||
} else if (type === 'habit') {
|
||||
if (task.down && task.up) {
|
||||
classes += ' habit-wide';
|
||||
}
|
||||
if (!task.down && !task.up) {
|
||||
classes += ' habit-narrow';
|
||||
}
|
||||
}
|
||||
if (priority === 0.1) {
|
||||
classes += ' difficulty-trivial';
|
||||
} else if (priority === 1) {
|
||||
classes += ' difficulty-easy';
|
||||
} else if (priority === 1.5) {
|
||||
classes += ' difficulty-medium';
|
||||
} else if (priority === 2) {
|
||||
classes += ' difficulty-hard';
|
||||
}
|
||||
if (value < -20) {
|
||||
classes += ' color-worst';
|
||||
} else if (value < -10) {
|
||||
classes += ' color-worse';
|
||||
} else if (value < -1) {
|
||||
classes += ' color-bad';
|
||||
} else if (value < 1) {
|
||||
classes += ' color-neutral';
|
||||
} else if (value < 5) {
|
||||
classes += ' color-good';
|
||||
} else if (value < 10) {
|
||||
classes += ' color-better';
|
||||
} else {
|
||||
classes += ' color-best';
|
||||
}
|
||||
return classes;
|
||||
};
|
||||
71
common/script/libs/taskDefaults.js
Normal file
@@ -0,0 +1,71 @@
|
||||
import uuid from './uuid';
|
||||
import _ from 'lodash';
|
||||
|
||||
/*
|
||||
Even though Mongoose handles task defaults, we want to make sure defaults are set on the client-side before
|
||||
sending up to the server for performance
|
||||
*/
|
||||
|
||||
// TODO revisit
|
||||
|
||||
module.exports = function(task) {
|
||||
var defaults, ref, ref1, ref2;
|
||||
if (task == null) {
|
||||
task = {};
|
||||
}
|
||||
if (!(task.type && ((ref = task.type) === 'habit' || ref === 'daily' || ref === 'todo' || ref === 'reward'))) {
|
||||
task.type = 'habit';
|
||||
}
|
||||
defaults = {
|
||||
id: uuid(),
|
||||
text: task.id != null ? task.id : '',
|
||||
notes: '',
|
||||
priority: 1,
|
||||
challenge: {},
|
||||
attribute: 'str',
|
||||
dateCreated: new Date()
|
||||
};
|
||||
_.defaults(task, defaults);
|
||||
if (task.type === 'habit') {
|
||||
_.defaults(task, {
|
||||
up: true,
|
||||
down: true
|
||||
});
|
||||
}
|
||||
if ((ref1 = task.type) === 'habit' || ref1 === 'daily') {
|
||||
_.defaults(task, {
|
||||
history: []
|
||||
});
|
||||
}
|
||||
if ((ref2 = task.type) === 'daily' || ref2 === 'todo') {
|
||||
_.defaults(task, {
|
||||
completed: false
|
||||
});
|
||||
}
|
||||
if (task.type === 'daily') {
|
||||
_.defaults(task, {
|
||||
streak: 0,
|
||||
repeat: {
|
||||
su: true,
|
||||
m: true,
|
||||
t: true,
|
||||
w: true,
|
||||
th: true,
|
||||
f: true,
|
||||
s: true
|
||||
}
|
||||
}, {
|
||||
startDate: new Date(),
|
||||
everyX: 1,
|
||||
frequency: 'weekly'
|
||||
});
|
||||
}
|
||||
task._id = task.id;
|
||||
if (task.value == null) {
|
||||
task.value = task.type === 'reward' ? 10 : 0;
|
||||
}
|
||||
if (!_.isNumber(task.priority)) {
|
||||
task.priority = 1;
|
||||
}
|
||||
return task;
|
||||
};
|
||||
36
common/script/libs/updateStore.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import _ from 'lodash';
|
||||
import content from '../content/index';
|
||||
|
||||
/*
|
||||
Update the in-browser store with new gear. FIXME this was in user.fns, but it was causing strange issues there
|
||||
*/
|
||||
|
||||
var sortOrder = _.reduce(content.gearTypes, (function(m, v, k) {
|
||||
m[v] = k;
|
||||
return m;
|
||||
}), {});
|
||||
|
||||
module.exports = function(user) {
|
||||
var changes;
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
changes = [];
|
||||
_.each(content.gearTypes, function(type) {
|
||||
var found;
|
||||
found = _.find(content.gear.tree[type][user.stats["class"]], function(item) {
|
||||
return !user.items.gear.owned[item.key];
|
||||
});
|
||||
if (found) {
|
||||
changes.push(found);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
changes = changes.concat(_.filter(content.gear.flat, function(v) {
|
||||
var ref;
|
||||
return ((ref = v.klass) === 'special' || ref === 'mystery' || ref === 'armoire') && !user.items.gear.owned[v.key] && (typeof v.canOwn === "function" ? v.canOwn(user) : void 0);
|
||||
}));
|
||||
return _.sortBy(changes, function(c) {
|
||||
return sortOrder[c.type];
|
||||
});
|
||||
};
|
||||