diff --git a/package-lock.json b/package-lock.json index c0824f17c2..53822171de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,6 +32,15 @@ "ws": "1.1.5" } }, + "JSONStream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", + "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -1771,9 +1780,9 @@ "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.0.2.tgz", "integrity": "sha1-+GzWzvT1MAyOY+B6TVEvZfv/RTE=", "requires": { + "JSONStream": "1.3.1", "combine-source-map": "0.7.2", "defined": "1.0.0", - "JSONStream": "1.3.1", "through2": "2.0.3", "umd": "3.0.1" } @@ -1803,6 +1812,7 @@ "resolved": "https://registry.npmjs.org/browserify/-/browserify-12.0.2.tgz", "integrity": "sha1-V/IeXm4wj/WYfE2v1EhAsrmPehk=", "requires": { + "JSONStream": "1.3.1", "assert": "1.3.0", "browser-pack": "6.0.2", "browser-resolve": "1.11.2", @@ -1824,7 +1834,6 @@ "inherits": "2.0.3", "insert-module-globals": "7.0.1", "isarray": "0.0.1", - "JSONStream": "1.3.1", "labeled-stream-splicer": "2.0.0", "module-deps": "4.1.1", "os-browserify": "0.1.2", @@ -6711,13 +6720,6 @@ } } }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, "string-width": { "version": "1.0.2", "bundled": true, @@ -6727,6 +6729,13 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, "stringstream": { "version": "0.0.5", "bundled": true, @@ -8899,10 +8908,10 @@ "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.1.tgz", "integrity": "sha1-wDv04BywhtW15azorQr+eInWOMM=", "requires": { + "JSONStream": "1.3.1", "combine-source-map": "0.7.2", "concat-stream": "1.5.2", "is-buffer": "1.1.6", - "JSONStream": "1.3.1", "lexical-scope": "1.2.0", "process": "0.11.10", "through2": "2.0.3", @@ -9738,15 +9747,6 @@ "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=" }, - "JSONStream": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.1.tgz", - "integrity": "sha1-cH92HgHa6eFvG8+TcDt4xwlmV5o=", - "requires": { - "jsonparse": "1.3.1", - "through": "2.3.8" - } - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -11554,6 +11554,7 @@ "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", "requires": { + "JSONStream": "1.3.1", "browser-resolve": "1.11.2", "cached-path-relative": "1.0.1", "concat-stream": "1.5.2", @@ -11561,7 +11562,6 @@ "detective": "4.5.0", "duplexer2": "0.1.4", "inherits": "2.0.3", - "JSONStream": "1.3.1", "parents": "1.0.1", "readable-stream": "2.0.6", "resolve": "1.5.0", @@ -15439,22 +15439,6 @@ "throttleit": "1.0.0" } }, - "require_optional": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", - "requires": { - "resolve-from": "2.0.0", - "semver": "5.4.1" - }, - "dependencies": { - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" - } - } - }, "require-again": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-again/-/require-again-2.0.0.tgz", @@ -15494,6 +15478,22 @@ } } }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "2.0.0", + "semver": "5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + } + } + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -16797,11 +16797,6 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -16812,6 +16807,11 @@ "strip-ansi": "3.0.1" } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -18496,6 +18496,14 @@ "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz", "integrity": "sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==" }, + "vuedraggable": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.15.0.tgz", + "integrity": "sha1-NSat7pJL0itHigG3DAo038nLu08=", + "requires": { + "sortablejs": "1.7.0" + } + }, "vuejs-datepicker": { "version": "git://github.com/habitrpg/vuejs-datepicker.git#825a866b6a9c52dd8c588a3e8b900880875ce914" }, diff --git a/website/client/components/avatar.vue b/website/client/components/avatar.vue index 8e6f711f26..d3bc1a3967 100644 --- a/website/client/components/avatar.vue +++ b/website/client/components/avatar.vue @@ -7,14 +7,14 @@ // Buffs that cause visual changes to avatar: Snowman, Ghost, Flower, etc template(v-for="(klass, item) in visualBuffs") - span(v-if="member.stats.buffs[item]", :class="klass") + span(v-if="member.stats.buffs[item] && showVisualBuffs", :class="klass") // Show flower ALL THE TIME!!! // See https://github.com/HabitRPG/habitica/issues/7133 span(:class="'hair_flower_' + member.preferences.hair.flower") // Show avatar only if not currently affected by visual buff - template(v-if!="!member.stats.buffs.snowball && !member.stats.buffs.spookySparkles && !member.stats.buffs.shinySeed && !member.stats.buffs.seafoam") + template(v-if="showAvatar()") span(:class="'chair_' + member.preferences.chair") span(:class="getGearClass('back')") span(:class="skinClass") @@ -111,6 +111,10 @@ export default { overrideTopPadding: { type: String, }, + showVisualBuffs: { + type: Boolean, + default: true, + }, }, computed: { hasClass () { @@ -179,6 +183,14 @@ export default { if (!this.$store.state.spellOptions.castingSpell) return; this.$root.$emit('castEnd', this.member, 'user', e); }, + showAvatar () { + if (!this.showVisualBuffs) + return true; + + let buffs = this.member.stats.buffs; + + return !buffs.snowball && !buffs.spookySparkles && !buffs.shinySeed && !buffs.seafoam; + }, }, }; diff --git a/website/client/components/inventory/equipment/equipGearModal.vue b/website/client/components/inventory/equipment/equipGearModal.vue index 213c63683c..d54390f70a 100644 --- a/website/client/components/inventory/equipment/equipGearModal.vue +++ b/website/client/components/inventory/equipment/equipGearModal.vue @@ -17,6 +17,7 @@ :withBackground="true", :overrideAvatarGear="memberOverrideAvatarGear(item)", :spritesMargin='"0px auto auto -1px"', + :showVisualBuffs="false", ) h4.title {{ itemText }} diff --git a/website/client/components/shops/buyModal.vue b/website/client/components/shops/buyModal.vue index 29c1000d81..9dcca5bbbe 100644 --- a/website/client/components/shops/buyModal.vue +++ b/website/client/components/shops/buyModal.vue @@ -18,6 +18,7 @@ slot(name="item", :item="item") div(v-if="showAvatar") avatar( + :showVisualBuffs="false", :member="user", :avatarOnly="true", :hideClassBadge="true", @@ -41,14 +42,15 @@ :item="item" ) - .purchase-amount(:class="{'notEnough': !this.enoughCurrency(getPriceClass(), item.value * selectedAmountToBuy)}") + .purchase-amount .how-many-to-buy(v-if='showAmountToBuy(item)') strong {{ $t('howManyToBuy') }} div(v-if='showAmountToBuy(item)') .box input(type='number', min='0', v-model='selectedAmountToBuy') - span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons[getPriceClass()]") - span.value(:class="getPriceClass()") {{ item.value }} + span(:class="{'notEnough': notEnoughCurrency}") + span.svg-icon.inline.icon-32(aria-hidden="true", v-html="icons[getPriceClass()]") + span.value(:class="getPriceClass()") {{ item.value }} .gems-left(v-if='item.key === "gem"') strong(v-if='gemsLeft > 0') {{ gemsLeft }} {{ $t('gemsRemaining') }} @@ -356,6 +358,9 @@ if (this.item && this.item.key && this.item.key === 'gem' && this.selectedAmountToBuy > this.gemsLeft) return true; return false; }, + notEnoughCurrency () { + return !this.enoughCurrency(this.getPriceClass(), this.item.value * this.selectedAmountToBuy); + }, }, watch: { item: function itemChanged () { diff --git a/website/client/components/shops/quests/questInfo.vue b/website/client/components/shops/quests/questInfo.vue index fd98863a28..732b6a99e6 100644 --- a/website/client/components/shops/quests/questInfo.vue +++ b/website/client/components/shops/quests/questInfo.vue @@ -1,11 +1,14 @@ @@ -22,7 +25,7 @@ } .col-8 { - text-align: right; + text-align: left; } .col-8:not(:last-child) { diff --git a/website/client/components/shops/timeTravelers/index.vue b/website/client/components/shops/timeTravelers/index.vue index e5ba5cf019..4fcfcebfbd 100644 --- a/website/client/components/shops/timeTravelers/index.vue +++ b/website/client/components/shops/timeTravelers/index.vue @@ -310,15 +310,6 @@ return c.identifier === 'mounts' || c.identifier === 'pets'; }); - normalGroups.map((group) => { - group.items = group.items.map((item) => { - return { - ...item, - class: `shop_${group.identifier}_${item.key}`, - }; - }); - }); - let setGroups = _filter(apiCategories, (c) => { return c.identifier !== 'mounts' && c.identifier !== 'pets'; }); diff --git a/website/common/locales/en/quests.json b/website/common/locales/en/quests.json index 655ac75144..be23ef00c0 100644 --- a/website/common/locales/en/quests.json +++ b/website/common/locales/en/quests.json @@ -37,7 +37,7 @@ "questCollection": "+ <%= val %> quest item(s) found", "questDamage": "+ <%= val %> damage to boss", "begin": "Begin", - "bossHP": "Boss Health", + "bossHP": "Boss HP", "bossStrength": "Boss Strength", "rage": "Rage", "collect": "Collect", diff --git a/website/common/script/libs/getItemByPathAndType.js b/website/common/script/libs/getItemByPathAndType.js new file mode 100644 index 0000000000..9e844cff3b --- /dev/null +++ b/website/common/script/libs/getItemByPathAndType.js @@ -0,0 +1,17 @@ +import content from '../content/index'; +import get from 'lodash/get'; + +module.exports = function getItemByPathAndType (type, path) { + let item = get(content, path); + + if (type === 'timeTravelersStable') { + let [, animalType, key] = path.split('.'); + + item = { + key, + type: animalType, + }; + } + + return item; +}; diff --git a/website/common/script/libs/getItemInfo.js b/website/common/script/libs/getItemInfo.js index 21c4772191..e0ed2632e2 100644 --- a/website/common/script/libs/getItemInfo.js +++ b/website/common/script/libs/getItemInfo.js @@ -316,6 +316,22 @@ module.exports = function getItemInfo (user, type, item, officialPinnedItems, la }; break; } + case 'timeTravelersStable': { + itemInfo = { + key: item.key, + purchaseType: item.type, + class: `shop_${item.type}_${item.key}`, + text: content.timeTravelStable[item.type][item.key](language), + notes: '', + value: 1, + + locked: false, + currency: 'hourglasses', + path: `timeTravelStable.${item.type}.${item.key}`, + pinType: 'timeTravelersStable', + }; + break; + } } if (itemInfo) { diff --git a/website/common/script/libs/inAppRewards.js b/website/common/script/libs/inAppRewards.js index 8fcc20a09e..98e641c918 100644 --- a/website/common/script/libs/inAppRewards.js +++ b/website/common/script/libs/inAppRewards.js @@ -1,9 +1,8 @@ -import content from '../content/index'; -import get from 'lodash/get'; import getItemInfo from './getItemInfo'; import shops from './shops'; import getOfficialPinnedItems from './getOfficialPinnedItems'; +import getItemByPathAndType from './getItemByPathAndType'; module.exports = function getPinnedItems (user) { let officialPinnedItems = getOfficialPinnedItems(user); @@ -16,7 +15,9 @@ module.exports = function getPinnedItems (user) { const pinnedItems = officialPinnedItemsNotUnpinned.concat(user.pinnedItems); let items = pinnedItems.map(({type, path}) => { - return getItemInfo(user, type, get(content, path), officialPinnedItems); + let item = getItemByPathAndType(type, path); + + return getItemInfo(user, type, item, officialPinnedItems); }); shops.checkMarketGearLocked(user, items); diff --git a/website/common/script/libs/shops.js b/website/common/script/libs/shops.js index 23f3d565f0..2facafad1a 100644 --- a/website/common/script/libs/shops.js +++ b/website/common/script/libs/shops.js @@ -156,12 +156,23 @@ shops.getMarketGearCategories = function getMarketGear (user, language) { }; let result = filter(content.gear.flat, ['klass', classType]); + category.items = map(result, (e) => { let newItem = getItemInfo(user, 'marketGear', e, officialPinnedItems); return newItem; }); + let specialGear = filter(content.gear.flat, (gear) => { + return user.items.gear.owned[gear.key] === false && + gear.specialClass === classType && + gear.klass === 'special'; + }); + + each(specialGear, (gear) => { + category.items.push(getItemInfo(user, 'marketGear', gear)); + }); + shops.checkMarketGearLocked(user, category.items); categories.push(category); @@ -173,7 +184,9 @@ shops.getMarketGearCategories = function getMarketGear (user, language) { }; let falseGear = filter(content.gear.flat, (gear) => { - return user.items.gear.owned[gear.key] === false && gear.klass !== user.stats.class; + return user.items.gear.owned[gear.key] === false && + gear.klass !== user.stats.class && + gear.klass !== 'special'; }); nonClassCategory.items = map(falseGear, (e) => { @@ -314,6 +327,8 @@ shops.getTimeTravelersShop = function getTimeTravelersShop (user, language) { shops.getTimeTravelersCategories = function getTimeTravelersCategories (user, language) { let categories = []; let stable = {pets: 'Pet-', mounts: 'Mount_Icon_'}; + + let officialPinnedItems = getOfficialPinnedItems(user); for (let type in stable) { if (stable.hasOwnProperty(type)) { let category = { @@ -325,18 +340,10 @@ shops.getTimeTravelersCategories = function getTimeTravelersCategories (user, la for (let key in content.timeTravelStable[type]) { if (content.timeTravelStable[type].hasOwnProperty(key)) { if (!user.items[type][key]) { - let item = { + let item = getItemInfo(user, 'timeTravelersStable', { key, - text: content.timeTravelStable[type][key](language), - class: stable[type] + key, type, - purchaseType: type, - value: 1, - notes: '', - locked: false, - currency: 'hourglasses', - pinType: 'IGNORE', - }; + }, officialPinnedItems, language); category.items.push(item); } } diff --git a/website/common/script/ops/pinnedGearUtils.js b/website/common/script/ops/pinnedGearUtils.js index c890cb1dc1..c60660927e 100644 --- a/website/common/script/ops/pinnedGearUtils.js +++ b/website/common/script/ops/pinnedGearUtils.js @@ -3,9 +3,9 @@ import getItemInfo from '../libs/getItemInfo'; import { BadRequest } from '../libs/errors'; import i18n from '../i18n'; import isPinned from '../libs/isPinned'; +import getItemByPathAndType from '../libs/getItemByPathAndType'; import getOfficialPinnedItems from '../libs/getOfficialPinnedItems'; -import get from 'lodash/get'; import each from 'lodash/each'; import sortBy from 'lodash/sortBy'; import lodashFind from 'lodash/find'; @@ -136,9 +136,7 @@ function togglePinnedItem (user, {item, type, path}, req = {}) { // If path isn't passed it means an item was passed path = getItemInfo(user, type, item, officialPinnedItems, req.language).path; } else { - if (!item) { - item = get(content, path); - } + item = getItemByPathAndType(type, path); if (!item && PATHS_WITHOUT_ITEM.indexOf(path) === -1) { // path not exists in our content structure