feat: improved missions UI and more sophisticated unlock options
This commit is contained in:
parent
e65587bbb7
commit
4f0b3c7741
|
@ -0,0 +1,20 @@
|
||||||
|
<template>
|
||||||
|
<div class="rounded-lg border text-center py-1">
|
||||||
|
{{ mission.name }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
mission: { type: Object, required: true },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
div {
|
||||||
|
border-color: currentColor;
|
||||||
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -4,8 +4,8 @@
|
||||||
:description="mission.description"
|
:description="mission.description"
|
||||||
:max="max"
|
:max="max"
|
||||||
:value="value"
|
:value="value"
|
||||||
:unit="unit"
|
:unit="mission.completionCriteria.unit"
|
||||||
@click="complete"
|
@click="$emit('click')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -16,22 +16,21 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
value() {
|
value() {
|
||||||
return 'cost' in this.mission.completionCriteria
|
const { unit } = this.mission.completionCriteria
|
||||||
? this.$store.state.currency
|
|
||||||
: this.$store.state.playerAge
|
if (unit === 'maxAge') {
|
||||||
|
return this.$store.state.playerAge
|
||||||
|
} else if (unit === 'spareTime') {
|
||||||
|
return this.$store.state.currency
|
||||||
|
} else {
|
||||||
|
// (unit === 'apprenticeLevels')
|
||||||
|
return this.$store.getters.apprenticeLevels
|
||||||
|
}
|
||||||
},
|
},
|
||||||
max() {
|
max() {
|
||||||
return 'cost' in this.mission.completionCriteria
|
return this.mission.completionCriteria.unit === 'maxAge'
|
||||||
? this.mission.completionCriteria.cost
|
? this.$store.state.playerAgeMax
|
||||||
: this.$store.state.playerAgeMax
|
: this.mission.completionCriteria.value
|
||||||
},
|
|
||||||
unit() {
|
|
||||||
return 'cost' in this.mission.completionCriteria ? 'spareTime' : 'age'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
complete() {
|
|
||||||
this.$store.commit('completeMission', this.mission)
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,80 @@
|
||||||
<template>
|
<template>
|
||||||
<responsive-grid>
|
<div class="missions grid">
|
||||||
|
<responsive-grid
|
||||||
|
v-if="incomplete.length"
|
||||||
|
:class="
|
||||||
|
completed.length &&
|
||||||
|
`pb-6 border-b-2 border-${$store.getters.activeTab.darkColor}`
|
||||||
|
"
|
||||||
|
>
|
||||||
<mission-button
|
<mission-button
|
||||||
v-for="(mission, index) in $store.state.missions"
|
v-for="(mission, index) in incomplete"
|
||||||
|
:key="index"
|
||||||
|
:mission="mission"
|
||||||
|
@click="complete(mission)"
|
||||||
|
/>
|
||||||
|
</responsive-grid>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
:class="
|
||||||
|
completed.length &&
|
||||||
|
`pt-6 pb-10 border-b-2 border-${$store.getters.activeTab.darkColor}`
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<h3 class="text-center">No Missions Currently Available</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-if="completed.length">
|
||||||
|
<h2 class="pt-2 pb-2 text-center text-xl">Completed Missions</h2>
|
||||||
|
<responsive-grid min="1" mid="3" max="6">
|
||||||
|
<completed-mission
|
||||||
|
v-for="(mission, index) in completed"
|
||||||
:key="index"
|
:key="index"
|
||||||
:mission="mission"
|
:mission="mission"
|
||||||
/>
|
/>
|
||||||
</responsive-grid>
|
</responsive-grid>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
unlocked() {
|
||||||
|
return this.$store.state.missions.filter(({ unlockCriteria }) => {
|
||||||
|
if (unlockCriteria.unit === 'instruments') {
|
||||||
|
return unlockCriteria.value <= this.$store.getters.instruments
|
||||||
|
} else if (unlockCriteria.unit === 'apprenticeLevels') {
|
||||||
|
return unlockCriteria.value <= this.$store.getters.apprenticeLevels
|
||||||
|
} else if (unlockCriteria.unit === 'missionsCompleted') {
|
||||||
|
return unlockCriteria.value.every((name) =>
|
||||||
|
this.$store.getters.missionIsCompleted(name)
|
||||||
|
)
|
||||||
|
} else if (unlockCriteria.unit === 'timeJumpsBackwards') {
|
||||||
|
return unlockCriteria.value <= this.$store.state.timeJumpsBackwards
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
incomplete() {
|
||||||
|
return this.unlocked.filter((m) => !m.complete)
|
||||||
|
},
|
||||||
|
completed() {
|
||||||
|
return this.unlocked.filter((m) => m.complete)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
complete(mission) {
|
||||||
|
this.$store.commit('completeMission', mission.name)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.missions {
|
||||||
|
grid-template-rows: minmax(0, 1fr) auto auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
100
store/index.js
100
store/index.js
|
@ -65,6 +65,7 @@ export const state = () => ({
|
||||||
instrument: 'Mechanical Clock',
|
instrument: 'Mechanical Clock',
|
||||||
worker: 'Engineer',
|
worker: 'Engineer',
|
||||||
|
|
||||||
|
unlocked: true,
|
||||||
cost: 10,
|
cost: 10,
|
||||||
created: false,
|
created: false,
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ export const state = () => ({
|
||||||
baseReward: 5, // currency added when the bar is completed
|
baseReward: 5, // currency added when the bar is completed
|
||||||
|
|
||||||
workerLevel: 0, // 0 = not hired; 1+ = hired
|
workerLevel: 0, // 0 = not hired; 1+ = hired
|
||||||
nextWorkerCost: 25, // currency cost of next worker
|
nextWorkerCost: 50, // currency cost of next worker
|
||||||
nextWorkerFactor: 1.5, // worker cost *= this factor after each purchase
|
nextWorkerFactor: 1.5, // worker cost *= this factor after each purchase
|
||||||
|
|
||||||
unlockThreshold: { tech: null, currency: 0 },
|
unlockThreshold: { tech: null, currency: 0 },
|
||||||
|
@ -82,6 +83,8 @@ export const state = () => ({
|
||||||
instrument: 'Hourglass',
|
instrument: 'Hourglass',
|
||||||
worker: 'Glassblower',
|
worker: 'Glassblower',
|
||||||
|
|
||||||
|
unlocked: false,
|
||||||
|
minDateUnlocked: 1100 * 12,
|
||||||
cost: 100,
|
cost: 100,
|
||||||
created: false,
|
created: false,
|
||||||
|
|
||||||
|
@ -90,7 +93,7 @@ export const state = () => ({
|
||||||
baseReward: 35,
|
baseReward: 35,
|
||||||
|
|
||||||
workerLevel: 0,
|
workerLevel: 0,
|
||||||
nextWorkerCost: 200,
|
nextWorkerCost: 250,
|
||||||
nextWorkerFactor: 1.6,
|
nextWorkerFactor: 1.6,
|
||||||
|
|
||||||
unlockThreshold: { tech: null, currency: 10000 },
|
unlockThreshold: { tech: null, currency: 10000 },
|
||||||
|
@ -99,6 +102,8 @@ export const state = () => ({
|
||||||
instrument: 'Pocket Watch',
|
instrument: 'Pocket Watch',
|
||||||
worker: 'Miniaturist',
|
worker: 'Miniaturist',
|
||||||
|
|
||||||
|
unlocked: false,
|
||||||
|
minDateUnlocked: 1600 * 12,
|
||||||
cost: 1000,
|
cost: 1000,
|
||||||
created: false,
|
created: false,
|
||||||
|
|
||||||
|
@ -107,7 +112,7 @@ export const state = () => ({
|
||||||
baseReward: 80,
|
baseReward: 80,
|
||||||
|
|
||||||
workerLevel: 0,
|
workerLevel: 0,
|
||||||
nextWorkerCost: 2000,
|
nextWorkerCost: 500,
|
||||||
nextWorkerFactor: 1.8,
|
nextWorkerFactor: 1.8,
|
||||||
|
|
||||||
unlockThreshold: { tech: 0, currency: new Decimal(10e5) },
|
unlockThreshold: { tech: 0, currency: new Decimal(10e5) },
|
||||||
|
@ -124,12 +129,50 @@ export const state = () => ({
|
||||||
|
|
||||||
missions: [
|
missions: [
|
||||||
{
|
{
|
||||||
name: 'Create the Time Machine',
|
name: 'Train an Apprentice',
|
||||||
description: 'Soon you will be able to control time itself.',
|
description:
|
||||||
completionCriteria: {
|
'One man can only spend so much time staring at clocks each day. Hiring a second may make this easier.',
|
||||||
cost: 6000,
|
unlockCriteria: {
|
||||||
|
unit: 'instruments',
|
||||||
|
value: 1,
|
||||||
},
|
},
|
||||||
available: true,
|
completionCriteria: {
|
||||||
|
unit: 'apprenticeLevels',
|
||||||
|
value: 5,
|
||||||
|
},
|
||||||
|
unlocked: true,
|
||||||
|
viewed: false,
|
||||||
|
complete: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Study Time Magic',
|
||||||
|
description:
|
||||||
|
"As time ticks away you begin to ponder the mysteries of time's origins and possibilities.",
|
||||||
|
unlockCriteria: {
|
||||||
|
unit: 'apprenticeLevels',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
completionCriteria: {
|
||||||
|
unit: 'spareTime',
|
||||||
|
value: 250,
|
||||||
|
},
|
||||||
|
unlocked: true,
|
||||||
|
viewed: false,
|
||||||
|
complete: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Create the Time Machine',
|
||||||
|
description:
|
||||||
|
'Your magnum opus. Soon you will be able to control time itself.',
|
||||||
|
unlockCriteria: {
|
||||||
|
unit: 'missionsCompleted',
|
||||||
|
value: ['Train an Apprentice', 'Study Time Magic'],
|
||||||
|
},
|
||||||
|
completionCriteria: {
|
||||||
|
unit: 'spareTime',
|
||||||
|
value: 1000,
|
||||||
|
},
|
||||||
|
unlocked: false,
|
||||||
viewed: false,
|
viewed: false,
|
||||||
complete: false,
|
complete: false,
|
||||||
},
|
},
|
||||||
|
@ -139,24 +182,27 @@ export const state = () => ({
|
||||||
'Your body seems to be failing you. ' +
|
'Your body seems to be failing you. ' +
|
||||||
'Write a book to pass your knowedge to your younger self through the time machine. ' +
|
'Write a book to pass your knowedge to your younger self through the time machine. ' +
|
||||||
"Now where's your pen...",
|
"Now where's your pen...",
|
||||||
appearanceCriteria: {
|
unlockCriteria: {
|
||||||
age: 100,
|
unit: 'timeJumpsBackwards',
|
||||||
|
value: 1,
|
||||||
},
|
},
|
||||||
completionCriteria: {
|
completionCriteria: {
|
||||||
maxAge: true,
|
unit: 'maxAge',
|
||||||
},
|
},
|
||||||
available: true,
|
unlocked: false,
|
||||||
viewed: false,
|
viewed: false,
|
||||||
complete: false,
|
complete: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
gameDate: 1991 * 12,
|
|
||||||
playerAge: 34 * 12,
|
gameDate: 1400 * 12,
|
||||||
playerAgeMax: 80 * 12,
|
playerAge: 30 * 12,
|
||||||
|
playerAgeMax: 60 * 12,
|
||||||
playerLivedTotal: 0,
|
playerLivedTotal: 0,
|
||||||
wisdomGained: 0, // wisdom gained so far on this run, not applied until player sends the book.
|
wisdomGained: 0, // wisdom gained so far on this run, not applied until player sends the book.
|
||||||
wisdomApplied: 0, // wisdom from previous runs
|
wisdomApplied: 0, // wisdom from previous runs
|
||||||
totalLifetimes: 1,
|
totalLifetimes: 1,
|
||||||
|
timeJumpsBackwards: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
export const getters = {
|
export const getters = {
|
||||||
|
@ -205,6 +251,22 @@ export const getters = {
|
||||||
|
|
||||||
return `${year}y${month}m`
|
return `${year}y${month}m`
|
||||||
},
|
},
|
||||||
|
missionIsCompleted: (state) => (missionName) => {
|
||||||
|
const mission = state.missions.find((m) => m.name === missionName)
|
||||||
|
|
||||||
|
return mission && mission.complete
|
||||||
|
},
|
||||||
|
apprenticeLevels: (state) =>
|
||||||
|
state.processes.reduce(
|
||||||
|
(totalLevels, process) => (totalLevels += process.workerLevel),
|
||||||
|
0
|
||||||
|
),
|
||||||
|
instruments: (state) =>
|
||||||
|
state.processes.reduce(
|
||||||
|
(totalInstruments, process) =>
|
||||||
|
process.created ? totalInstruments + 1 : totalInstruments,
|
||||||
|
0
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mutations = {
|
export const mutations = {
|
||||||
|
@ -229,10 +291,14 @@ export const mutations = {
|
||||||
setMissionViewed: (state, missionIndex) => {
|
setMissionViewed: (state, missionIndex) => {
|
||||||
Vue.set(state.missions[missionIndex], 'viewed', true)
|
Vue.set(state.missions[missionIndex], 'viewed', true)
|
||||||
},
|
},
|
||||||
completeMission: (state, mission) => {
|
completeMission: (state, missionName) => {
|
||||||
const index = state.missions.findIndex((m) => m.name === mission.name)
|
const index = state.missions.findIndex((m) => m.name === missionName)
|
||||||
Vue.set(state.missions[index], 'complete', true)
|
Vue.set(state.missions[index], 'complete', true)
|
||||||
},
|
},
|
||||||
|
unlockMission: (state, missionName) => {
|
||||||
|
const index = state.missions.findIndex((m) => m.name === missionName)
|
||||||
|
Vue.set(state.missions[index], 'unlocked', true)
|
||||||
|
},
|
||||||
levelUpApprentice: (state, process) => {
|
levelUpApprentice: (state, process) => {
|
||||||
if (process.nextWorkerCost > state.currency) {
|
if (process.nextWorkerCost > state.currency) {
|
||||||
return
|
return
|
||||||
|
|
Reference in New Issue