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"
|
||||
:max="max"
|
||||
:value="value"
|
||||
:unit="unit"
|
||||
@click="complete"
|
||||
:unit="mission.completionCriteria.unit"
|
||||
@click="$emit('click')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
@ -16,22 +16,21 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
value() {
|
||||
return 'cost' in this.mission.completionCriteria
|
||||
? this.$store.state.currency
|
||||
: this.$store.state.playerAge
|
||||
const { unit } = this.mission.completionCriteria
|
||||
|
||||
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() {
|
||||
return 'cost' in this.mission.completionCriteria
|
||||
? this.mission.completionCriteria.cost
|
||||
: this.$store.state.playerAgeMax
|
||||
},
|
||||
unit() {
|
||||
return 'cost' in this.mission.completionCriteria ? 'spareTime' : 'age'
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
complete() {
|
||||
this.$store.commit('completeMission', this.mission)
|
||||
return this.mission.completionCriteria.unit === 'maxAge'
|
||||
? this.$store.state.playerAgeMax
|
||||
: this.mission.completionCriteria.value
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,9 +1,80 @@
|
|||
<template>
|
||||
<responsive-grid>
|
||||
<mission-button
|
||||
v-for="(mission, index) in $store.state.missions"
|
||||
:key="index"
|
||||
:mission="mission"
|
||||
/>
|
||||
</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
|
||||
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"
|
||||
:mission="mission"
|
||||
/>
|
||||
</responsive-grid>
|
||||
</template>
|
||||
</div>
|
||||
</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',
|
||||
worker: 'Engineer',
|
||||
|
||||
unlocked: true,
|
||||
cost: 10,
|
||||
created: false,
|
||||
|
||||
|
@ -73,7 +74,7 @@ export const state = () => ({
|
|||
baseReward: 5, // currency added when the bar is completed
|
||||
|
||||
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
|
||||
|
||||
unlockThreshold: { tech: null, currency: 0 },
|
||||
|
@ -82,6 +83,8 @@ export const state = () => ({
|
|||
instrument: 'Hourglass',
|
||||
worker: 'Glassblower',
|
||||
|
||||
unlocked: false,
|
||||
minDateUnlocked: 1100 * 12,
|
||||
cost: 100,
|
||||
created: false,
|
||||
|
||||
|
@ -90,7 +93,7 @@ export const state = () => ({
|
|||
baseReward: 35,
|
||||
|
||||
workerLevel: 0,
|
||||
nextWorkerCost: 200,
|
||||
nextWorkerCost: 250,
|
||||
nextWorkerFactor: 1.6,
|
||||
|
||||
unlockThreshold: { tech: null, currency: 10000 },
|
||||
|
@ -99,6 +102,8 @@ export const state = () => ({
|
|||
instrument: 'Pocket Watch',
|
||||
worker: 'Miniaturist',
|
||||
|
||||
unlocked: false,
|
||||
minDateUnlocked: 1600 * 12,
|
||||
cost: 1000,
|
||||
created: false,
|
||||
|
||||
|
@ -107,7 +112,7 @@ export const state = () => ({
|
|||
baseReward: 80,
|
||||
|
||||
workerLevel: 0,
|
||||
nextWorkerCost: 2000,
|
||||
nextWorkerCost: 500,
|
||||
nextWorkerFactor: 1.8,
|
||||
|
||||
unlockThreshold: { tech: 0, currency: new Decimal(10e5) },
|
||||
|
@ -124,12 +129,50 @@ export const state = () => ({
|
|||
|
||||
missions: [
|
||||
{
|
||||
name: 'Create the Time Machine',
|
||||
description: 'Soon you will be able to control time itself.',
|
||||
completionCriteria: {
|
||||
cost: 6000,
|
||||
name: 'Train an Apprentice',
|
||||
description:
|
||||
'One man can only spend so much time staring at clocks each day. Hiring a second may make this easier.',
|
||||
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,
|
||||
complete: false,
|
||||
},
|
||||
|
@ -139,24 +182,27 @@ export const state = () => ({
|
|||
'Your body seems to be failing you. ' +
|
||||
'Write a book to pass your knowedge to your younger self through the time machine. ' +
|
||||
"Now where's your pen...",
|
||||
appearanceCriteria: {
|
||||
age: 100,
|
||||
unlockCriteria: {
|
||||
unit: 'timeJumpsBackwards',
|
||||
value: 1,
|
||||
},
|
||||
completionCriteria: {
|
||||
maxAge: true,
|
||||
unit: 'maxAge',
|
||||
},
|
||||
available: true,
|
||||
unlocked: false,
|
||||
viewed: false,
|
||||
complete: false,
|
||||
},
|
||||
],
|
||||
gameDate: 1991 * 12,
|
||||
playerAge: 34 * 12,
|
||||
playerAgeMax: 80 * 12,
|
||||
|
||||
gameDate: 1400 * 12,
|
||||
playerAge: 30 * 12,
|
||||
playerAgeMax: 60 * 12,
|
||||
playerLivedTotal: 0,
|
||||
wisdomGained: 0, // wisdom gained so far on this run, not applied until player sends the book.
|
||||
wisdomApplied: 0, // wisdom from previous runs
|
||||
totalLifetimes: 1,
|
||||
timeJumpsBackwards: 0,
|
||||
})
|
||||
|
||||
export const getters = {
|
||||
|
@ -205,6 +251,22 @@ export const getters = {
|
|||
|
||||
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 = {
|
||||
|
@ -229,10 +291,14 @@ export const mutations = {
|
|||
setMissionViewed: (state, missionIndex) => {
|
||||
Vue.set(state.missions[missionIndex], 'viewed', true)
|
||||
},
|
||||
completeMission: (state, mission) => {
|
||||
const index = state.missions.findIndex((m) => m.name === mission.name)
|
||||
completeMission: (state, missionName) => {
|
||||
const index = state.missions.findIndex((m) => m.name === missionName)
|
||||
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) => {
|
||||
if (process.nextWorkerCost > state.currency) {
|
||||
return
|
||||
|
|
Reference in New Issue