feat: improved missions UI and more sophisticated unlock options

This commit is contained in:
pskfyi 2022-01-10 21:48:15 -08:00 committed by John McCardle
parent e65587bbb7
commit 4f0b3c7741
4 changed files with 196 additions and 40 deletions

View File

@ -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>

View File

@ -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
},
},
}

View File

@ -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>

View File

@ -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