mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Fix: Inconsistent Quest Unlock Behavior (#13734)
* remove quest refactoring, created new branch for that task * remove quest refactoring, created new branch for that task * More trying to figure out how buying a quest actually works * rolling back changes * updated shops/quests/index.vue to disable clicking on locked quests * removed console.log(item) * misc fixes per review comments * changes as requested * incorporated quest refactors updates * removing a couple lines of code
This commit is contained in:
@@ -560,14 +560,8 @@ export default {
|
|||||||
this.selectedItemToBuy = null;
|
this.selectedItemToBuy = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isGearLocked (gear) {
|
|
||||||
if (gear.value > this.userStats.gp) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
selectItem (item) {
|
selectItem (item) {
|
||||||
|
if (item.locked) return;
|
||||||
this.selectedItemToBuy = item;
|
this.selectedItemToBuy = item;
|
||||||
|
|
||||||
this.$root.$emit('bv::show::modal', 'buy-quest-modal');
|
this.$root.$emit('bv::show::modal', 'buy-quest-modal');
|
||||||
|
|||||||
@@ -2,17 +2,15 @@ import defaults from 'lodash/defaults';
|
|||||||
import each from 'lodash/each';
|
import each from 'lodash/each';
|
||||||
import sortBy from 'lodash/sortBy';
|
import sortBy from 'lodash/sortBy';
|
||||||
import t from './translation';
|
import t from './translation';
|
||||||
import {
|
import { USER_CAN_OWN_QUEST_CATEGORIES } from './constants';
|
||||||
USER_CAN_OWN_QUEST_CATEGORIES,
|
import QUEST_GENERIC from './quests/generic';
|
||||||
QUEST_GENERIC,
|
import QUEST_MASTERCLASSER from './quests/masterclasser';
|
||||||
QUEST_MASTERCLASSER,
|
import QUEST_PETS from './quests/pets';
|
||||||
QUEST_PETS,
|
import QUEST_POTIONS from './quests/potions';
|
||||||
QUEST_POTIONS,
|
import QUEST_SEASONAL from './quests/seasonal';
|
||||||
QUEST_SEASONAL,
|
import QUEST_SERIES from './quests/series';
|
||||||
QUEST_SERIES,
|
import QUEST_TIME_TRAVEL from './quests/timeTravel';
|
||||||
QUEST_TIME_TRAVEL,
|
import QUEST_WORLD from './quests/world';
|
||||||
QUEST_WORLD,
|
|
||||||
} from './constants';
|
|
||||||
|
|
||||||
const userCanOwnQuestCategories = USER_CAN_OWN_QUEST_CATEGORIES;
|
const userCanOwnQuestCategories = USER_CAN_OWN_QUEST_CATEGORIES;
|
||||||
const questGeneric = QUEST_GENERIC;
|
const questGeneric = QUEST_GENERIC;
|
||||||
|
|||||||
@@ -335,5 +335,4 @@ const QUEST_POTIONS = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default QUEST_POTIONS;
|
export default QUEST_POTIONS;
|
||||||
|
|||||||
@@ -33,9 +33,6 @@ const QUEST_SEASONAL = {
|
|||||||
gp: 20,
|
gp: 20,
|
||||||
exp: 100,
|
exp: 100,
|
||||||
},
|
},
|
||||||
canBuy () {
|
|
||||||
return this.event && moment().isBetween(this.event.start, this.event.end);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
evilsanta2: {
|
evilsanta2: {
|
||||||
event: CURRENT_EVENT && CURRENT_EVENT.season === 'winter' ? CURRENT_EVENT : null,
|
event: CURRENT_EVENT && CURRENT_EVENT.season === 'winter' ? CURRENT_EVENT : null,
|
||||||
@@ -66,9 +63,6 @@ const QUEST_SEASONAL = {
|
|||||||
gp: 20,
|
gp: 20,
|
||||||
exp: 100,
|
exp: 100,
|
||||||
},
|
},
|
||||||
canBuy () {
|
|
||||||
return this.event && moment().isBetween(this.event.start, this.event.end);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
// spring
|
// spring
|
||||||
egg: {
|
egg: {
|
||||||
@@ -131,8 +125,45 @@ const QUEST_SEASONAL = {
|
|||||||
gp: 0,
|
gp: 0,
|
||||||
exp: 0,
|
exp: 0,
|
||||||
},
|
},
|
||||||
canBuy () {
|
},
|
||||||
return this.event && moment().isBetween(this.event.start, this.event.end);
|
waffle: {
|
||||||
|
text: t('questWaffleText'),
|
||||||
|
notes: t('questWaffleNotes'),
|
||||||
|
completion: t('questWaffleCompletion'),
|
||||||
|
value: 4,
|
||||||
|
category: 'hatchingPotion',
|
||||||
|
event: CURRENT_EVENT && CURRENT_EVENT.season === 'spring' ? CURRENT_EVENT : null,
|
||||||
|
boss: {
|
||||||
|
name: t('questWaffleBoss'),
|
||||||
|
hp: 500,
|
||||||
|
str: 2,
|
||||||
|
rage: {
|
||||||
|
title: t('questWaffleRageTitle'),
|
||||||
|
description: t('questWaffleRageDescription'),
|
||||||
|
value: 50,
|
||||||
|
progressDrain: 0.5,
|
||||||
|
effect: t('questWaffleRageEffect'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
drop: {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
type: 'hatchingPotions',
|
||||||
|
key: 'Dessert',
|
||||||
|
text: t('questWaffleDropDessertPotion'),
|
||||||
|
}, {
|
||||||
|
type: 'hatchingPotions',
|
||||||
|
key: 'Dessert',
|
||||||
|
text: t('questWaffleDropDessertPotion'),
|
||||||
|
}, {
|
||||||
|
type: 'hatchingPotions',
|
||||||
|
key: 'Dessert',
|
||||||
|
text: t('questWaffleDropDessertPotion'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
gp: 40,
|
||||||
|
exp: 500,
|
||||||
|
unlock: t('questWaffleUnlockText'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
virtualpet: {
|
virtualpet: {
|
||||||
@@ -178,49 +209,6 @@ const QUEST_SEASONAL = {
|
|||||||
unlock: t('questVirtualPetUnlockText'),
|
unlock: t('questVirtualPetUnlockText'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
waffle: {
|
|
||||||
text: t('questWaffleText'),
|
|
||||||
notes: t('questWaffleNotes'),
|
|
||||||
completion: t('questWaffleCompletion'),
|
|
||||||
value: 4,
|
|
||||||
category: 'hatchingPotion',
|
|
||||||
event: CURRENT_EVENT && CURRENT_EVENT.season === 'spring' ? CURRENT_EVENT : null,
|
|
||||||
boss: {
|
|
||||||
name: t('questWaffleBoss'),
|
|
||||||
hp: 500,
|
|
||||||
str: 2,
|
|
||||||
rage: {
|
|
||||||
title: t('questWaffleRageTitle'),
|
|
||||||
description: t('questWaffleRageDescription'),
|
|
||||||
value: 50,
|
|
||||||
progressDrain: 0.5,
|
|
||||||
effect: t('questWaffleRageEffect'),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
drop: {
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
type: 'hatchingPotions',
|
|
||||||
key: 'Dessert',
|
|
||||||
text: t('questWaffleDropDessertPotion'),
|
|
||||||
}, {
|
|
||||||
type: 'hatchingPotions',
|
|
||||||
key: 'Dessert',
|
|
||||||
text: t('questWaffleDropDessertPotion'),
|
|
||||||
}, {
|
|
||||||
type: 'hatchingPotions',
|
|
||||||
key: 'Dessert',
|
|
||||||
text: t('questWaffleDropDessertPotion'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
gp: 40,
|
|
||||||
exp: 500,
|
|
||||||
unlock: t('questWaffleUnlockText'),
|
|
||||||
},
|
|
||||||
canBuy () {
|
|
||||||
return this.event && moment().isBetween(this.event.start, this.event.end);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default QUEST_SEASONAL;
|
export default QUEST_SEASONAL;
|
||||||
|
|||||||
@@ -36,11 +36,10 @@ const QUEST_SERIES = {
|
|||||||
notes: t('questAtom2Notes'),
|
notes: t('questAtom2Notes'),
|
||||||
completion: t('questAtom2Completion'),
|
completion: t('questAtom2Completion'),
|
||||||
group: 'questGroupAtom',
|
group: 'questGroupAtom',
|
||||||
prerequisite: {
|
|
||||||
lvl: 15,
|
|
||||||
atom1: true,
|
|
||||||
},
|
|
||||||
previous: 'atom1',
|
previous: 'atom1',
|
||||||
|
prereqQuests: [
|
||||||
|
'atom1',
|
||||||
|
],
|
||||||
value: 4,
|
value: 4,
|
||||||
lvl: 15,
|
lvl: 15,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
@@ -67,12 +66,11 @@ const QUEST_SERIES = {
|
|||||||
notes: t('questAtom3Notes'),
|
notes: t('questAtom3Notes'),
|
||||||
group: 'questGroupAtom',
|
group: 'questGroupAtom',
|
||||||
previous: 'atom2',
|
previous: 'atom2',
|
||||||
|
prereqQuests: [
|
||||||
|
'atom1',
|
||||||
|
'atom2',
|
||||||
|
],
|
||||||
completion: t('questAtom3Completion'),
|
completion: t('questAtom3Completion'),
|
||||||
prerequisite: {
|
|
||||||
lvl: 15,
|
|
||||||
atom1: true,
|
|
||||||
atom2: true,
|
|
||||||
},
|
|
||||||
value: 4,
|
value: 4,
|
||||||
lvl: 15,
|
lvl: 15,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
@@ -135,6 +133,9 @@ const QUEST_SERIES = {
|
|||||||
group: 'questGroupGoldenknight',
|
group: 'questGroupGoldenknight',
|
||||||
value: 4,
|
value: 4,
|
||||||
previous: 'goldenknight1',
|
previous: 'goldenknight1',
|
||||||
|
prereqQuests: [
|
||||||
|
'goldenknight1',
|
||||||
|
],
|
||||||
lvl: 40,
|
lvl: 40,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
boss: {
|
boss: {
|
||||||
@@ -161,6 +162,10 @@ const QUEST_SERIES = {
|
|||||||
group: 'questGroupGoldenknight',
|
group: 'questGroupGoldenknight',
|
||||||
completion: t('questGoldenknight3Completion'),
|
completion: t('questGoldenknight3Completion'),
|
||||||
previous: 'goldenknight2',
|
previous: 'goldenknight2',
|
||||||
|
prereqQuests: [
|
||||||
|
'goldenknight1',
|
||||||
|
'goldenknight2',
|
||||||
|
],
|
||||||
value: 4,
|
value: 4,
|
||||||
lvl: 40,
|
lvl: 40,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
@@ -237,6 +242,9 @@ const QUEST_SERIES = {
|
|||||||
group: 'questGroupMoon',
|
group: 'questGroupMoon',
|
||||||
completion: t('questMoon2Completion'),
|
completion: t('questMoon2Completion'),
|
||||||
previous: 'moon1',
|
previous: 'moon1',
|
||||||
|
prereqQuests: [
|
||||||
|
'moon1',
|
||||||
|
],
|
||||||
value: 4,
|
value: 4,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
unlockCondition: {
|
unlockCondition: {
|
||||||
@@ -267,6 +275,10 @@ const QUEST_SERIES = {
|
|||||||
group: 'questGroupMoon',
|
group: 'questGroupMoon',
|
||||||
completion: t('questMoon3Completion'),
|
completion: t('questMoon3Completion'),
|
||||||
previous: 'moon2',
|
previous: 'moon2',
|
||||||
|
prereqQuests: [
|
||||||
|
'moon1',
|
||||||
|
'moon2',
|
||||||
|
],
|
||||||
value: 4,
|
value: 4,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
unlockCondition: {
|
unlockCondition: {
|
||||||
@@ -326,6 +338,9 @@ const QUEST_SERIES = {
|
|||||||
value: 4,
|
value: 4,
|
||||||
lvl: 60,
|
lvl: 60,
|
||||||
previous: 'moonstone1',
|
previous: 'moonstone1',
|
||||||
|
prereqQuests: [
|
||||||
|
'moonstone1',
|
||||||
|
],
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
boss: {
|
boss: {
|
||||||
name: t('questMoonstone2Boss'),
|
name: t('questMoonstone2Boss'),
|
||||||
@@ -351,6 +366,10 @@ const QUEST_SERIES = {
|
|||||||
group: 'questGroupMoonstone',
|
group: 'questGroupMoonstone',
|
||||||
completion: t('questMoonstone3Completion'),
|
completion: t('questMoonstone3Completion'),
|
||||||
previous: 'moonstone2',
|
previous: 'moonstone2',
|
||||||
|
prereqQuests: [
|
||||||
|
'moonstone1',
|
||||||
|
'moonstone2',
|
||||||
|
],
|
||||||
value: 4,
|
value: 4,
|
||||||
lvl: 60,
|
lvl: 60,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
@@ -438,6 +457,9 @@ const QUEST_SERIES = {
|
|||||||
lvl: 30,
|
lvl: 30,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
previous: 'vice1',
|
previous: 'vice1',
|
||||||
|
prereqQuests: [
|
||||||
|
'vice1',
|
||||||
|
],
|
||||||
collect: {
|
collect: {
|
||||||
lightCrystal: {
|
lightCrystal: {
|
||||||
text: t('questVice2CollectLightCrystal'),
|
text: t('questVice2CollectLightCrystal'),
|
||||||
@@ -463,6 +485,10 @@ const QUEST_SERIES = {
|
|||||||
group: 'questGroupVice',
|
group: 'questGroupVice',
|
||||||
completion: t('questVice3Completion'),
|
completion: t('questVice3Completion'),
|
||||||
previous: 'vice2',
|
previous: 'vice2',
|
||||||
|
prereqQuests: [
|
||||||
|
'vice1',
|
||||||
|
'vice2',
|
||||||
|
],
|
||||||
value: 4,
|
value: 4,
|
||||||
lvl: 30,
|
lvl: 30,
|
||||||
category: 'unlockable',
|
category: 'unlockable',
|
||||||
|
|||||||
@@ -9,13 +9,24 @@ import isFreeRebirth from './isFreeRebirth';
|
|||||||
import getOfficialPinnedItems from './getOfficialPinnedItems';
|
import getOfficialPinnedItems from './getOfficialPinnedItems';
|
||||||
|
|
||||||
function lockQuest (quest, user) {
|
function lockQuest (quest, user) {
|
||||||
if (quest.key === 'lostMasterclasser1') return !(user.achievements.quests.dilatoryDistress3 && user.achievements.quests.mayhemMistiflying3 && user.achievements.quests.stoikalmCalamity3 && user.achievements.quests.taskwoodsTerror3);
|
// checks series quests, including Masterclasser
|
||||||
if (quest.lvl && user.stats.lvl < quest.lvl) return true;
|
if (quest.prereqQuests) {
|
||||||
if (quest.unlockCondition && (quest.key === 'moon1' || quest.key === 'moon2' || quest.key === 'moon3')) {
|
if (!user.achievements.quests) return true;
|
||||||
return user.loginIncentives < quest.unlockCondition.incentiveThreshold;
|
for (const prereq of quest.prereqQuests) {
|
||||||
|
if (!user.achievements.quests[prereq]) return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (user.achievements.quests) return quest.previous && !user.achievements.quests[quest.previous];
|
// checks quest & user level against quest level
|
||||||
return quest.previous;
|
if (quest.lvl && user.stats.lvl < quest.lvl) return true;
|
||||||
|
|
||||||
|
// checks unlockCondition.incentiveThreshold for Lunar Battle
|
||||||
|
if (
|
||||||
|
quest.unlockCondition
|
||||||
|
&& quest.unlockCondition.incentiveThreshold
|
||||||
|
&& user.loginIncentives < quest.unlockCondition.incentiveThreshold
|
||||||
|
) return true;
|
||||||
|
// // then if we've passed all the checks
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isItemSuggested (officialPinnedItems, itemInfo) {
|
function isItemSuggested (officialPinnedItems, itemInfo) {
|
||||||
|
|||||||
Reference in New Issue
Block a user