mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Oct 3 fixes (#9148)
* Only show level after yesterdailies modal * Fixed zindex * Added spcial spells to rewards column * Added single click buy for health and armoire * Prevented task scoring when casting a spell * Renamed generic purchase method * Updated nav for small screen * Hide checklist while casting
This commit is contained in:
@@ -3,9 +3,10 @@ div
|
|||||||
inbox-modal
|
inbox-modal
|
||||||
creator-intro
|
creator-intro
|
||||||
profile
|
profile
|
||||||
nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-lg
|
nav.navbar.navbar-inverse.fixed-top.navbar-toggleable-md
|
||||||
.navbar-header
|
.navbar-header
|
||||||
.logo.svg-icon(v-html="icons.logo")
|
.logo.svg-icon.hidden-lg-down(v-html="icons.logo")
|
||||||
|
.svg-icon.gryphon.hidden-xl-up
|
||||||
b-collapse#nav_collapse.collapse.navbar-collapse(is-nav)
|
b-collapse#nav_collapse.collapse.navbar-collapse(is-nav)
|
||||||
ul.navbar-nav.mr-auto
|
ul.navbar-nav.mr-auto
|
||||||
router-link.nav-item(tag="li", :to="{name: 'tasks'}", exact)
|
router-link.nav-item(tag="li", :to="{name: 'tasks'}", exact)
|
||||||
@@ -93,58 +94,34 @@ div
|
|||||||
@import '~client/assets/scss/colors.scss';
|
@import '~client/assets/scss/colors.scss';
|
||||||
@import '~client/assets/scss/utils.scss';
|
@import '~client/assets/scss/utils.scss';
|
||||||
|
|
||||||
/* Less than Desktops and laptops ----------- */
|
|
||||||
@media only screen and (max-width : 1224px) {
|
|
||||||
#nav_collapse {
|
|
||||||
background: $purple-100;
|
|
||||||
margin-top: 1em;
|
|
||||||
margin-left: 70%;
|
|
||||||
padding-bottom: 1em;
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding: .5em !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-menu {
|
|
||||||
position: absolute !important;
|
|
||||||
left: -10em;
|
|
||||||
top: -.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width : 1224px) and (min-width: 1200px) {
|
|
||||||
#nav_collapse {
|
|
||||||
margin-top: 37em !important;
|
|
||||||
|
|
||||||
a {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-collapse.collapse {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-collapse.collapse.show {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-toggler, .navbar-nav {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-toggleable-lg .navbar-collapse {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 1280px) {
|
@media only screen and (max-width: 1280px) {
|
||||||
.nav-link {
|
.nav-link {
|
||||||
padding: .8em 1em !important;
|
padding: .8em 1em !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 1200px) {
|
||||||
|
.navbar-header {
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gryphon {
|
||||||
|
background-image: url('~assets/images/melior@3x.png');
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
background-size: cover;
|
||||||
|
color: $white;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 990px) {
|
||||||
|
#nav_collapse {
|
||||||
|
margin-top: 1.3em;
|
||||||
|
background-color: $purple-200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nav.navbar {
|
nav.navbar {
|
||||||
background: $purple-100 url(~assets/svg/for-css/bits.svg) right no-repeat;
|
background: $purple-100 url(~assets/svg/for-css/bits.svg) right no-repeat;
|
||||||
padding-left: 25px;
|
padding-left: 25px;
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ export default {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
yesterDailies: [],
|
yesterDailies: [],
|
||||||
|
levelBeforeYesterdailies: 0,
|
||||||
notificationData: {},
|
notificationData: {},
|
||||||
unlockLevels,
|
unlockLevels,
|
||||||
lastShownNotifications,
|
lastShownNotifications,
|
||||||
@@ -256,12 +257,8 @@ export default {
|
|||||||
this.mp(mana);
|
this.mp(mana);
|
||||||
},
|
},
|
||||||
userLvl (after, before) {
|
userLvl (after, before) {
|
||||||
if (after <= before) return;
|
if (after <= before || this.isRunningYesterdailies) return;
|
||||||
this.lvl();
|
this.showLevelUpNotifications(after);
|
||||||
this.playSound('Level_Up');
|
|
||||||
if (this.user._tmp && this.user._tmp.drop && this.user._tmp.drop.type === 'Quest') return;
|
|
||||||
if (this.unlockLevels[`${after}`]) return;
|
|
||||||
if (!this.user.preferences.suppressModals.levelUp) this.$root.$emit('show::modal', 'level-up');
|
|
||||||
},
|
},
|
||||||
userClassSelect (after) {
|
userClassSelect (after) {
|
||||||
if (!after) return;
|
if (!after) return;
|
||||||
@@ -334,6 +331,13 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
showLevelUpNotifications (newlevel) {
|
||||||
|
this.lvl();
|
||||||
|
this.playSound('Level_Up');
|
||||||
|
if (this.user._tmp && this.user._tmp.drop && this.user._tmp.drop.type === 'Quest') return;
|
||||||
|
if (this.unlockLevels[`${newlevel}`]) return;
|
||||||
|
if (!this.user.preferences.suppressModals.levelUp) this.$root.$emit('show::modal', 'level-up');
|
||||||
|
},
|
||||||
playSound (sound) {
|
playSound (sound) {
|
||||||
this.$root.$emit('playSound', sound);
|
this.$root.$emit('playSound', sound);
|
||||||
},
|
},
|
||||||
@@ -390,6 +394,7 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.levelBeforeYesterdailies = this.user.stats.lvl;
|
||||||
this.$root.$emit('show::modal', 'yesterdaily');
|
this.$root.$emit('show::modal', 'yesterdaily');
|
||||||
},
|
},
|
||||||
async runYesterDailiesAction () {
|
async runYesterDailiesAction () {
|
||||||
@@ -405,6 +410,10 @@ export default {
|
|||||||
this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true}),
|
this.$store.dispatch('tasks:fetchUserTasks', {forceLoad: true}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (this.levelBeforeYesterdailies < this.user.stats.lvl) {
|
||||||
|
this.showLevelUpNotifications(this.user.stats.lvl);
|
||||||
|
}
|
||||||
|
|
||||||
this.handleUserNotifications(this.user.notifications);
|
this.handleUserNotifications(this.user.notifications);
|
||||||
this.scheduleNextCron();
|
this.scheduleNextCron();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -209,6 +209,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||||
import * as Analytics from 'client/libs/analytics';
|
import * as Analytics from 'client/libs/analytics';
|
||||||
|
import spellsMixin from 'client/mixins/spells';
|
||||||
|
|
||||||
import svgClose from 'assets/svg/close.svg';
|
import svgClose from 'assets/svg/close.svg';
|
||||||
import svgGold from 'assets/svg/gold.svg';
|
import svgGold from 'assets/svg/gold.svg';
|
||||||
@@ -220,6 +221,7 @@
|
|||||||
import BalanceInfo from './balanceInfo.vue';
|
import BalanceInfo from './balanceInfo.vue';
|
||||||
import currencyMixin from './_currencyMixin';
|
import currencyMixin from './_currencyMixin';
|
||||||
import notifications from 'client/mixins/notifications';
|
import notifications from 'client/mixins/notifications';
|
||||||
|
import buyMixin from 'client/mixins/buy';
|
||||||
|
|
||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
|
|
||||||
@@ -233,7 +235,7 @@
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [currencyMixin, notifications],
|
mixins: [currencyMixin, notifications, spellsMixin, buyMixin],
|
||||||
components: {
|
components: {
|
||||||
bModal,
|
bModal,
|
||||||
BalanceInfo,
|
BalanceInfo,
|
||||||
@@ -301,17 +303,11 @@
|
|||||||
this.$emit('change', $event);
|
this.$emit('change', $event);
|
||||||
},
|
},
|
||||||
buyItem () {
|
buyItem () {
|
||||||
if (this.genericPurchase) {
|
if (this.item.cast) {
|
||||||
this.$store.dispatch('shops:genericPurchase', {
|
this.castStart(this.item);
|
||||||
pinType: this.item.pinType,
|
} else if (this.genericPurchase) {
|
||||||
type: this.item.purchaseType,
|
this.makeGenericPurchase(this.item);
|
||||||
key: this.item.key,
|
|
||||||
currency: this.item.currency,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.purchased(this.item.text);
|
this.purchased(this.item.text);
|
||||||
this.$root.$emit('buyModal::boughtItem', this.item);
|
|
||||||
this.$root.$emit('playSound', 'Reward');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emit('buyPressed', this.item);
|
this.$emit('buyPressed', this.item);
|
||||||
|
|||||||
@@ -46,6 +46,11 @@
|
|||||||
min-height: 556px;
|
min-height: 556px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.task-wrapper {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
.task-wrapper + .reward-items {
|
.task-wrapper + .reward-items {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
@@ -104,7 +109,7 @@
|
|||||||
.column-background {
|
.column-background {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 32px;
|
bottom: 32px;
|
||||||
z-index: 7;
|
z-index: 1;
|
||||||
|
|
||||||
&.initial-description {
|
&.initial-description {
|
||||||
top: 30%;
|
top: 30%;
|
||||||
@@ -160,19 +165,25 @@
|
|||||||
<script>
|
<script>
|
||||||
import Task from './task';
|
import Task from './task';
|
||||||
import sortBy from 'lodash/sortBy';
|
import sortBy from 'lodash/sortBy';
|
||||||
|
import throttle from 'lodash/throttle';
|
||||||
|
import bModal from 'bootstrap-vue/lib/components/modal';
|
||||||
|
|
||||||
|
import sortable from 'client/directives/sortable.directive';
|
||||||
|
import buyMixin from 'client/mixins/buy';
|
||||||
import { mapState, mapActions } from 'client/libs/store';
|
import { mapState, mapActions } from 'client/libs/store';
|
||||||
|
import shopItem from '../shops/shopItem';
|
||||||
|
|
||||||
import { shouldDo } from 'common/script/cron';
|
import { shouldDo } from 'common/script/cron';
|
||||||
import inAppRewards from 'common/script/libs/inAppRewards';
|
import inAppRewards from 'common/script/libs/inAppRewards';
|
||||||
|
import spells from 'common/script/content/spells';
|
||||||
|
|
||||||
import habitIcon from 'assets/svg/habit.svg';
|
import habitIcon from 'assets/svg/habit.svg';
|
||||||
import dailyIcon from 'assets/svg/daily.svg';
|
import dailyIcon from 'assets/svg/daily.svg';
|
||||||
import todoIcon from 'assets/svg/todo.svg';
|
import todoIcon from 'assets/svg/todo.svg';
|
||||||
import rewardIcon from 'assets/svg/reward.svg';
|
import rewardIcon from 'assets/svg/reward.svg';
|
||||||
import bModal from 'bootstrap-vue/lib/components/modal';
|
|
||||||
import shopItem from '../shops/shopItem';
|
|
||||||
import throttle from 'lodash/throttle';
|
|
||||||
import sortable from 'client/directives/sortable.directive';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [buyMixin],
|
||||||
components: {
|
components: {
|
||||||
Task,
|
Task,
|
||||||
bModal,
|
bModal,
|
||||||
@@ -252,8 +263,30 @@ export default {
|
|||||||
},
|
},
|
||||||
inAppRewards () {
|
inAppRewards () {
|
||||||
let watchRefresh = this.forceRefresh; // eslint-disable-line
|
let watchRefresh = this.forceRefresh; // eslint-disable-line
|
||||||
|
let rewards = inAppRewards(this.user);
|
||||||
|
|
||||||
return inAppRewards(this.user);
|
|
||||||
|
// Add season rewards if user is affected
|
||||||
|
// @TODO: Add buff coniditional
|
||||||
|
const seasonalSkills = {
|
||||||
|
snowball: 'salt',
|
||||||
|
spookySparkles: 'opaquePotion',
|
||||||
|
shinySeed: 'petalFreePotion',
|
||||||
|
seafoam: 'sand',
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let key in seasonalSkills) {
|
||||||
|
if (this.user.stats.buffs[key]) {
|
||||||
|
let debuff = seasonalSkills[key];
|
||||||
|
let item = Object.assign({}, spells.special[debuff]);
|
||||||
|
item.text = item.text();
|
||||||
|
item.notes = item.notes();
|
||||||
|
item.class = `shop_${key}`;
|
||||||
|
rewards.push(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rewards;
|
||||||
},
|
},
|
||||||
hasRewardsList () {
|
hasRewardsList () {
|
||||||
return this.isUser === true && this.type === 'reward' && this.activeFilters[this.type].label !== 'custom';
|
return this.isUser === true && this.type === 'reward' && this.activeFilters[this.type].label !== 'custom';
|
||||||
@@ -378,6 +411,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
openBuyDialog (rewardItem) {
|
openBuyDialog (rewardItem) {
|
||||||
|
// Buy armoire and health potions immediately
|
||||||
|
let itemsToPurchaseImmediately = ['potion', 'armoire'];
|
||||||
|
if (itemsToPurchaseImmediately.indexOf(rewardItem.key) !== -1) {
|
||||||
|
this.makeGenericPurchase(rewardItem);
|
||||||
|
this.$emit('buyPressed', rewardItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (rewardItem.purchaseType !== 'gear' || !rewardItem.locked) {
|
if (rewardItem.purchaseType !== 'gear' || !rewardItem.locked) {
|
||||||
this.$emit('openBuyDialog', rewardItem);
|
this.$emit('openBuyDialog', rewardItem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,14 +148,13 @@ div(v-if='user.stats.lvl > 10')
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
|
||||||
import isArray from 'lodash/isArray';
|
|
||||||
import bPopover from 'bootstrap-vue/lib/directives/popover';
|
import bPopover from 'bootstrap-vue/lib/directives/popover';
|
||||||
|
|
||||||
import spells from '../../../common/script/content/spells';
|
import spells from '../../../common/script/content/spells';
|
||||||
|
|
||||||
import { mapState } from 'client/libs/store';
|
import { mapState } from 'client/libs/store';
|
||||||
import notifications from 'client/mixins/notifications';
|
import notifications from 'client/mixins/notifications';
|
||||||
|
import spellsMixin from 'client/mixins/spells';
|
||||||
import Drawer from 'client/components/ui/drawer';
|
import Drawer from 'client/components/ui/drawer';
|
||||||
import MouseMoveDirective from 'client/directives/mouseposition.directive';
|
import MouseMoveDirective from 'client/directives/mouseposition.directive';
|
||||||
|
|
||||||
@@ -164,7 +163,7 @@ import quests from 'common/script/content/quests';
|
|||||||
import { CONSTANTS, setLocalSetting, getLocalSetting } from 'client/libs/userlocalManager';
|
import { CONSTANTS, setLocalSetting, getLocalSetting } from 'client/libs/userlocalManager';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [notifications],
|
mixins: [notifications, spellsMixin],
|
||||||
components: {
|
components: {
|
||||||
Drawer,
|
Drawer,
|
||||||
},
|
},
|
||||||
@@ -245,122 +244,6 @@ export default {
|
|||||||
|
|
||||||
return notes;
|
return notes;
|
||||||
},
|
},
|
||||||
async castStart (spell) {
|
|
||||||
if (this.$store.state.spellOptions.castingSpell) {
|
|
||||||
this.castCancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.user.stats.mp < spell.mana) return this.text(this.$t('notEnoughMana'));
|
|
||||||
|
|
||||||
if (spell.immediateUse && this.user.stats.gp < spell.value) {
|
|
||||||
return this.text('Not enough gold.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.potionClickMode = true;
|
|
||||||
this.applyingAction = true;
|
|
||||||
this.$store.state.spellOptions.castingSpell = true;
|
|
||||||
this.spell = spell;
|
|
||||||
|
|
||||||
if (spell.target === 'self') {
|
|
||||||
this.castEnd(null, spell.target);
|
|
||||||
} else if (spell.target === 'party') {
|
|
||||||
if (!this.user.party._id) {
|
|
||||||
let party = [this.user];
|
|
||||||
this.castEnd(party, spell.target);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let party = this.$store.state.party.members;
|
|
||||||
party = isArray(party) ? party : [];
|
|
||||||
party = party.concat(this.user);
|
|
||||||
this.castEnd(party, spell.target);
|
|
||||||
} else if (spell.target === 'tasks') {
|
|
||||||
let userTasks = this.$store.state.tasks.data;
|
|
||||||
// exclude rewards
|
|
||||||
let tasks = userTasks.habits
|
|
||||||
.concat(userTasks.dailys)
|
|
||||||
.concat(userTasks.todos);
|
|
||||||
// exclude challenge and group plan tasks
|
|
||||||
tasks = tasks.filter((task) => {
|
|
||||||
if (task.challenge && task.challenge.id && !task.challenge.broken) return false;
|
|
||||||
if (task.group && task.group.id && !task.group.broken) return false;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
this.castEnd(tasks, spell.target);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async castEnd (target, type) {
|
|
||||||
if (!this.$store.state.spellOptions.castingSpell) return;
|
|
||||||
let beforeQuestProgress = this.questProgress();
|
|
||||||
|
|
||||||
if (!this.applyingAction) return 'No applying action';
|
|
||||||
|
|
||||||
if (this.spell.target !== type) return this.text(this.$t('invalidTarget'));
|
|
||||||
if (target && target.type && target.type === 'reward') return this.text(this.$t('invalidTarget'));
|
|
||||||
if (target && target.challenge && target.challenge.id) return this.text(this.$t('invalidTarget'));
|
|
||||||
if (target && target.group && target.group.id) return this.text(this.$t('invalidTarget'));
|
|
||||||
|
|
||||||
// @TODO: just call castCancel?
|
|
||||||
this.$store.state.spellOptions.castingSpell = false;
|
|
||||||
this.potionClickMode = false;
|
|
||||||
|
|
||||||
this.spell.cast(this.user, target);
|
|
||||||
// User.save(); // @TODO:
|
|
||||||
|
|
||||||
let spell = this.spell;
|
|
||||||
let targetId = target ? target._id : null;
|
|
||||||
this.spell = null;
|
|
||||||
this.applyingAction = false;
|
|
||||||
|
|
||||||
let spellUrl = `/api/v3/user/class/cast/${spell.key}`;
|
|
||||||
if (targetId) spellUrl += `?targetId=${targetId}`;
|
|
||||||
|
|
||||||
await axios.post(spellUrl);
|
|
||||||
let msg = this.$t('youCast', {
|
|
||||||
spell: spell.text(),
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'task':
|
|
||||||
msg = this.$t('youCastTarget', {
|
|
||||||
spell: spell.text(),
|
|
||||||
target: target.text,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'user':
|
|
||||||
msg = this.$t('youCastTarget', {
|
|
||||||
spell: spell.text(),
|
|
||||||
target: target.profile.name,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 'party':
|
|
||||||
msg = this.$t('youCastParty', {
|
|
||||||
spell: spell.text(),
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.markdown(msg); // @TODO: mardown directive?
|
|
||||||
// @TODO:
|
|
||||||
let questProgress = this.questProgress() - beforeQuestProgress;
|
|
||||||
if (questProgress > 0) {
|
|
||||||
let userQuest = this.quests[this.user.party.quest.key];
|
|
||||||
if (userQuest.boss) {
|
|
||||||
this.quest('questDamage', questProgress.toFixed(1));
|
|
||||||
} else if (userQuest.collection && userQuest.collect) {
|
|
||||||
this.quest('questCollection', questProgress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// @TOOD: User.sync();
|
|
||||||
},
|
|
||||||
castCancel () {
|
|
||||||
this.potionClickMode = false;
|
|
||||||
this.applyingAction = false;
|
|
||||||
this.spell = null;
|
|
||||||
document.querySelector('body').style.cursor = 'initial';
|
|
||||||
this.$store.state.spellOptions.castingSpell = false;
|
|
||||||
},
|
|
||||||
questProgress () {
|
questProgress () {
|
||||||
let user = this.user;
|
let user = this.user;
|
||||||
if (!user.party.quest) return 0;
|
if (!user.party.quest) return 0;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
.task-notes.small-text(v-markdown="task.notes")
|
.task-notes.small-text(v-markdown="task.notes")
|
||||||
.checklist(v-if="canViewchecklist")
|
.checklist(v-if="canViewchecklist")
|
||||||
label.custom-control.custom-checkbox.checklist-item(
|
label.custom-control.custom-checkbox.checklist-item(
|
||||||
|
v-if='!castingSpell',
|
||||||
v-for="item in task.checklist", :class="{'checklist-item-done': item.completed}",
|
v-for="item in task.checklist", :class="{'checklist-item-done': item.completed}",
|
||||||
)
|
)
|
||||||
input.custom-control-input(type="checkbox", :checked="item.completed", @change="toggleChecklistItem(item)")
|
input.custom-control-input(type="checkbox", :checked="item.completed", @change="toggleChecklistItem(item)")
|
||||||
@@ -339,7 +340,10 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState({user: 'user.data'}),
|
...mapState({
|
||||||
|
user: 'user.data',
|
||||||
|
castingSpell: 'spellOptions.castingSpell',
|
||||||
|
}),
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
getTagsFor: 'tasks:getTagsFor',
|
getTagsFor: 'tasks:getTagsFor',
|
||||||
getTaskClasses: 'tasks:getTaskClasses',
|
getTaskClasses: 'tasks:getTaskClasses',
|
||||||
@@ -390,6 +394,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
...mapActions({scoreChecklistItem: 'tasks:scoreChecklistItem'}),
|
...mapActions({scoreChecklistItem: 'tasks:scoreChecklistItem'}),
|
||||||
toggleChecklistItem (item) {
|
toggleChecklistItem (item) {
|
||||||
|
if (this.castingSpell) return;
|
||||||
item.completed = !item.completed;
|
item.completed = !item.completed;
|
||||||
this.scoreChecklistItem({taskId: this.task._id, itemId: item.id});
|
this.scoreChecklistItem({taskId: this.task._id, itemId: item.id});
|
||||||
},
|
},
|
||||||
@@ -407,6 +412,8 @@ export default {
|
|||||||
this.$root.$emit('castEnd', task, 'task', e);
|
this.$root.$emit('castEnd', task, 'task', e);
|
||||||
},
|
},
|
||||||
async score (direction) {
|
async score (direction) {
|
||||||
|
if (this.castingSpell) return;
|
||||||
|
|
||||||
// TODO move to an action
|
// TODO move to an action
|
||||||
const Content = this.$store.state.content;
|
const Content = this.$store.state.content;
|
||||||
const user = this.user;
|
const user = this.user;
|
||||||
|
|||||||
14
website/client/mixins/buy.js
Normal file
14
website/client/mixins/buy.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
makeGenericPurchase (item) {
|
||||||
|
this.$store.dispatch('shops:genericPurchase', {
|
||||||
|
pinType: item.pinType,
|
||||||
|
type: item.purchaseType,
|
||||||
|
key: item.key,
|
||||||
|
currency: item.currency,
|
||||||
|
});
|
||||||
|
this.$root.$emit('buyModal::boughtItem', item);
|
||||||
|
this.$root.$emit('playSound', 'Reward');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
128
website/client/mixins/spells.js
Normal file
128
website/client/mixins/spells.js
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import isArray from 'lodash/isArray';
|
||||||
|
|
||||||
|
// @TODO: Let's separate some of the business logic out of Vue if possible
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
async castStart (spell) {
|
||||||
|
if (this.$store.state.spellOptions.castingSpell) {
|
||||||
|
this.castCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.user.stats.mp < spell.mana) return this.text(this.$t('notEnoughMana'));
|
||||||
|
|
||||||
|
if (spell.immediateUse && this.user.stats.gp < spell.value) {
|
||||||
|
return this.text('Not enough gold.');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.potionClickMode = true;
|
||||||
|
this.applyingAction = true;
|
||||||
|
this.$store.state.spellOptions.castingSpell = true;
|
||||||
|
this.spell = spell;
|
||||||
|
|
||||||
|
if (spell.target === 'self') {
|
||||||
|
this.castEnd(null, spell.target);
|
||||||
|
} else if (spell.target === 'party') {
|
||||||
|
if (!this.user.party._id) {
|
||||||
|
let party = [this.user];
|
||||||
|
this.castEnd(party, spell.target);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let party = this.$store.state.party.members;
|
||||||
|
party = isArray(party) ? party : [];
|
||||||
|
party = party.concat(this.user);
|
||||||
|
this.castEnd(party, spell.target);
|
||||||
|
} else if (spell.target === 'tasks') {
|
||||||
|
let userTasks = this.$store.state.tasks.data;
|
||||||
|
// exclude rewards
|
||||||
|
let tasks = userTasks.habits
|
||||||
|
.concat(userTasks.dailys)
|
||||||
|
.concat(userTasks.todos);
|
||||||
|
// exclude challenge and group plan tasks
|
||||||
|
tasks = tasks.filter((task) => {
|
||||||
|
if (task.challenge && task.challenge.id && !task.challenge.broken) return false;
|
||||||
|
if (task.group && task.group.id && !task.group.broken) return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
this.castEnd(tasks, spell.target);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async castEnd (target, type) {
|
||||||
|
if (!this.$store.state.spellOptions.castingSpell) return;
|
||||||
|
let beforeQuestProgress;
|
||||||
|
if (this.spell.target === 'party') beforeQuestProgress = this.questProgress();
|
||||||
|
|
||||||
|
if (!this.applyingAction) return 'No applying action';
|
||||||
|
|
||||||
|
if (this.spell.target !== type) return this.text(this.$t('invalidTarget'));
|
||||||
|
if (target && target.type && target.type === 'reward') return this.text(this.$t('invalidTarget'));
|
||||||
|
if (target && target.challenge && target.challenge.id) return this.text(this.$t('invalidTarget'));
|
||||||
|
if (target && target.group && target.group.id) return this.text(this.$t('invalidTarget'));
|
||||||
|
|
||||||
|
// @TODO: just call castCancel?
|
||||||
|
this.$store.state.spellOptions.castingSpell = false;
|
||||||
|
this.potionClickMode = false;
|
||||||
|
|
||||||
|
this.spell.cast(this.user, target);
|
||||||
|
// User.save(); // @TODO:
|
||||||
|
|
||||||
|
let spell = this.spell;
|
||||||
|
let targetId = target ? target._id : null;
|
||||||
|
this.spell = null;
|
||||||
|
this.applyingAction = false;
|
||||||
|
|
||||||
|
let spellUrl = `/api/v3/user/class/cast/${spell.key}`;
|
||||||
|
if (targetId) spellUrl += `?targetId=${targetId}`;
|
||||||
|
|
||||||
|
let spellText = typeof spell.text === 'function' ? spell.text() : spell.text;
|
||||||
|
|
||||||
|
await axios.post(spellUrl);
|
||||||
|
let msg = this.$t('youCast', {
|
||||||
|
spell: spellText,
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'task':
|
||||||
|
msg = this.$t('youCastTarget', {
|
||||||
|
spell: spellText,
|
||||||
|
target: target.text,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'user':
|
||||||
|
msg = this.$t('youCastTarget', {
|
||||||
|
spell: spellText,
|
||||||
|
target: target.profile.name,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'party':
|
||||||
|
msg = this.$t('youCastParty', {
|
||||||
|
spell: spellText,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.markdown(msg); // @TODO: mardown directive?
|
||||||
|
// @TODO:
|
||||||
|
if (!beforeQuestProgress) return;
|
||||||
|
let questProgress = this.questProgress() - beforeQuestProgress;
|
||||||
|
if (questProgress > 0) {
|
||||||
|
let userQuest = this.quests[this.user.party.quest.key];
|
||||||
|
if (userQuest.boss) {
|
||||||
|
this.quest('questDamage', questProgress.toFixed(1));
|
||||||
|
} else if (userQuest.collection && userQuest.collect) {
|
||||||
|
this.quest('questCollection', questProgress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @TOOD: User.sync();
|
||||||
|
},
|
||||||
|
castCancel () {
|
||||||
|
this.potionClickMode = false;
|
||||||
|
this.applyingAction = false;
|
||||||
|
this.spell = null;
|
||||||
|
document.querySelector('body').style.cursor = 'initial';
|
||||||
|
this.$store.state.spellOptions.castingSpell = false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user