diff --git a/package-lock.json b/package-lock.json index e853f75..909069b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,14 @@ { "name": "adventurers-guild", - "version": "0.0.0", + "version": "0.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "adventurers-guild", - "version": "0.0.0", + "version": "0.0.1", "dependencies": { + "@vueuse/components": "^9.13.0", "sass": "^1.59.3", "vue": "^3.2.45", "vue-router": "^4.1.6" @@ -517,6 +518,11 @@ "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + }, "node_modules/@vitejs/plugin-vue": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.1.0.tgz", @@ -729,6 +735,124 @@ } } }, + "node_modules/@vueuse/components": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-9.13.0.tgz", + "integrity": "sha512-UJ8PjQ4SGb2rsVIy9vhEc6aCu+3+2cc+xEfGNX8/M1NKIuL2Vo6c2Kc2fYFaRzWZkP8HWXu+IcwvnAzL44IEFA==", + "dependencies": { + "@vueuse/core": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + } + }, + "node_modules/@vueuse/components/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", @@ -3700,6 +3824,11 @@ "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true }, + "@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + }, "@vitejs/plugin-vue": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.1.0.tgz", @@ -3892,6 +4021,64 @@ "dev": true, "requires": {} }, + "@vueuse/components": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-9.13.0.tgz", + "integrity": "sha512-UJ8PjQ4SGb2rsVIy9vhEc6aCu+3+2cc+xEfGNX8/M1NKIuL2Vo6c2Kc2fYFaRzWZkP8HWXu+IcwvnAzL44IEFA==", + "requires": { + "@vueuse/core": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "requires": {} + } + } + }, + "@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "requires": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "requires": {} + } + } + }, + "@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==" + }, + "@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "requires": { + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "requires": {} + } + } + }, "acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", diff --git a/package.json b/package.json index fd11295..a0742cc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "adventurers-guild", - "version": "0.0.1", + "version": "0.0.2", "private": true, "scripts": { "dev": "vite", @@ -10,6 +10,7 @@ "type-check": "vue-tsc --noEmit" }, "dependencies": { + "@vueuse/components": "^9.13.0", "sass": "^1.59.3", "vue": "^3.2.45", "vue-router": "^4.1.6" diff --git a/public/data/adventurers.json b/public/data/adventurers.json new file mode 100644 index 0000000..ca59c22 --- /dev/null +++ b/public/data/adventurers.json @@ -0,0 +1,38 @@ +[ + { + "id": "rincewind-diskworld", + "name": "Rincewind", + "portrait": "/img/adventurers/rincewind.png", + "attackExponent": 1.09 + }, + { + "id": "fran-sword-isekai", + "name": "Fran", + "portrait": "/img/adventurers/fran.png", + "attackExponent": 1.115 + }, + { + "id": "kazuma-konosuba", + "name": "Kazuma", + "portrait": "/img/adventurers/kazuma.png", + "attackExponent": 1.1 + }, + { + "id": "rein-beast-tamer", + "name": "Rein", + "portrait": "/img/adventurers/rein.png", + "attackExponent": 1.1 + }, + { + "id": "momon-overlord", + "name": "Momon", + "portrait": "/img/adventurers/momon.png", + "attackExponent": 1.11 + }, + { + "id": "goblin-slayer", + "name": "Goblin Slayer", + "portrait": "/img/adventurers/goblin-slayer.png", + "attackExponent": 1.1 + } +] \ No newline at end of file diff --git a/public/data/quests/RankA.json b/public/data/quests/RankA.json new file mode 100644 index 0000000..a389942 --- /dev/null +++ b/public/data/quests/RankA.json @@ -0,0 +1,14 @@ +[ + { + "title": "Ogre king", + "text": "Ogres have chosen a new king through democratic vote. They all voted for the strongest ogre." + }, + { + "title": "Devilish dungeon", + "text": "New dungeon was discovered. It needs to be mapped and explored so lower rank adventurers can enter." + }, + { + "title": "Eater of Worlds", + "text": "A giant worm emerged from the ground and appears to be consuming the ground itself." + } +] \ No newline at end of file diff --git a/public/data/quests/RankB.json b/public/data/quests/RankB.json new file mode 100644 index 0000000..a5725cd --- /dev/null +++ b/public/data/quests/RankB.json @@ -0,0 +1,14 @@ +[ + { + "title": "Undead horde", + "text": "Due to the spillage of necromancy potion at nearby graveyard we now have an undead army on our doorstep." + }, + { + "title": "Runaway prisoner", + "text": "During the last prison guard strike a prisoner managed to escape. Bring them back to their cell." + }, + { + "title": "The aristocrats", + "text": "Royalty wants an escort for one of their carriages." + } +] \ No newline at end of file diff --git a/public/data/quests/RankC.json b/public/data/quests/RankC.json new file mode 100644 index 0000000..1faa4e7 --- /dev/null +++ b/public/data/quests/RankC.json @@ -0,0 +1,14 @@ +[ + { + "title": "Scratchy, the butcher", + "text": "Scratchy turned evil and is terrorizing its victims. Put a stop to it!" + }, + { + "title": "Hobgnoblin subjegation", + "text": "Gnoblins evolved and are back for vengeance." + }, + { + "title": "Holy", + "text": "Gnoblins summoned their machine god and it started going haywire on everything around it. Destroy it!" + } +] \ No newline at end of file diff --git a/public/data/quests/RankD.json b/public/data/quests/RankD.json new file mode 100644 index 0000000..5dba33a --- /dev/null +++ b/public/data/quests/RankD.json @@ -0,0 +1,14 @@ +[ + { + "title": "Caravan escort", + "text": "Escort a merchant caravan." + }, + { + "title": "Rare ore", + "text": "Obtain laudanium ore for town's blacksmith." + }, + { + "title": "Demonic pests!", + "text": "Clear the fields from cabbage imps." + } +] \ No newline at end of file diff --git a/public/data/quests/RankE.json b/public/data/quests/RankE.json new file mode 100644 index 0000000..01b0803 --- /dev/null +++ b/public/data/quests/RankE.json @@ -0,0 +1,14 @@ +[ + { + "title": "Gnoblin subjegation", + "text": "Kill 3 gnoblins." + }, + { + "title": "Phantom menace", + "text": "Exorcise ghosts out of someone's apartment." + }, + { + "title": "Scratchy in peril", + "text": "Get Scratchy the cat from the tree safe onto the ground." + } +] \ No newline at end of file diff --git a/public/data/quests/RankF.json b/public/data/quests/RankF.json new file mode 100644 index 0000000..7ebd9e2 --- /dev/null +++ b/public/data/quests/RankF.json @@ -0,0 +1,18 @@ +[ + { + "title": "Frog Frenzy", + "text": "Kill 10 demon frogs." + }, + { + "title": "Rats!", + "text": "Get rid of the rats from someone's basement." + }, + { + "title": "Herb gathering", + "text": "Collect medicinal herbs." + }, + { + "title": "Big pile of rubble", + "text": "Tavern collapsed. Again. Help clean up the debris." + } +] \ No newline at end of file diff --git a/public/data/quests/RankS.json b/public/data/quests/RankS.json new file mode 100644 index 0000000..283aa5a --- /dev/null +++ b/public/data/quests/RankS.json @@ -0,0 +1,14 @@ +[ + { + "title": "The Demon King", + "text": "Demon King has awoken and is a threat to whole existence. Heroes needed." + }, + { + "title": "Scratchy, Destruction Incarnate", + "text": "Scratchy was reborn as a machine of pure destruction and needs to be stopped." + }, + { + "title": "Jiggly Jungle", + "text": "A jungle south began rapidly expanding and experts think arson is our only option." + } +] \ No newline at end of file diff --git a/public/img/adventurers/goblin-slayer.png b/public/img/adventurers/goblin-slayer.png new file mode 100644 index 0000000..4a91842 Binary files /dev/null and b/public/img/adventurers/goblin-slayer.png differ diff --git a/src/App.vue b/src/App.vue index f7ec787..b444386 100644 --- a/src/App.vue +++ b/src/App.vue @@ -9,7 +9,6 @@ import {RouterLink, RouterView} from 'vue-router' Adventurers - diff --git a/src/components/AdventurerMiniComponent.vue b/src/components/AdventurerMiniComponent.vue index 19b03d0..234b9ac 100644 --- a/src/components/AdventurerMiniComponent.vue +++ b/src/components/AdventurerMiniComponent.vue @@ -1,3 +1,7 @@ + + @@ -18,7 +19,25 @@ export default defineComponent({ props: { adventurer: { type: Object as PropType, + default() { + return {} as Adventurer; + }, } + }, + data: () => ({ + expProgress: "0%", + }), + watch: { + adventurer: { + deep: true, + handler: function (adventurer: Adventurer) { + this.expProgress = adventurer.getExpPercentage() + "%"; + }, + } + }, + mounted() { + if (this.adventurer === undefined) return; + this.expProgress = this.adventurer.getExpPercentage() + "%"; } }); @@ -37,11 +56,21 @@ export default defineComponent({ top: 0; left: 0; font-size: 1rem; + min-width: 1rem; background-color: rgba(0,0,0, 0.75); border-bottom-right-radius: 0.2rem; padding: 0.1rem; color: #fff; } + .exp { + position: absolute; + bottom: 0; + left: 0; + width: v-bind(expProgress); + height: 3.5%; + background-color: rgba(203, 33, 213, 0.75); + transition: width 1s linear; + } img { width: 100%; height: 100%; diff --git a/src/components/QuestMissive.vue b/src/components/QuestMissive.vue new file mode 100644 index 0000000..9538c61 --- /dev/null +++ b/src/components/QuestMissive.vue @@ -0,0 +1,169 @@ + + + + + \ No newline at end of file diff --git a/src/components/UpgradesList.vue b/src/components/UpgradesList.vue new file mode 100644 index 0000000..84d3695 --- /dev/null +++ b/src/components/UpgradesList.vue @@ -0,0 +1,68 @@ + + + + + \ No newline at end of file diff --git a/src/views/AdventurerView.vue b/src/views/AdventurerView.vue index 5a18ecb..9794ca6 100644 --- a/src/views/AdventurerView.vue +++ b/src/views/AdventurerView.vue @@ -9,11 +9,12 @@ @@ -28,7 +29,7 @@
-

Recruited adventurers

+

Recruited adventurers ({{ Object.keys(adventurers).length }} / {{ guild.adventurerCapacity.getAdventurerCapacity() }})

@@ -43,34 +44,36 @@ import type {PropType} from "vue"; import {defineComponent} from "vue"; import AdventurerTile from "@/components/AdventurerTile.vue"; -import {Adventurer} from "@/classes/Adventurer"; +import type {Adventurer} from "@/classes/Adventurer"; +import { loadAdventurersForHire } from "@/GameData"; +import type {Guild} from "@/classes/Guild"; export default defineComponent({ name: "RecruitView", components: {AdventurerTile}, - data() { + data: () => { return { currentlyForHire: null as Adventurer|null, - adventurersForHire: [ - new Adventurer("rincewind-diskworld", "Rincewind", "/img/adventurers/rincewind.png", 2, 2), - new Adventurer("fran-sword-isekai", "Fran", "/img/adventurers/fran.png", 3, 1.5), - new Adventurer("kazuma-konosuba", "Kazuma", "/img/adventurers/kazuma.png", 2, 2), - new Adventurer("rein-beast-tamer", "Rein", "/img/adventurers/rein.png", 2, 2), - new Adventurer("momon-overlord", "Momon", "/img/adventurers/momon.png", 2, 2), - ] as Array, + adventurersForHire: [] as Array, } }, props: { + guild: { + type: Object as PropType, + default() { + return {} as Guild + }, + }, adventurers: { type: Object as PropType<{ [key: string]: Adventurer }>, default() { - return {}; + return {} as { [key: string]: Adventurer }; }, }, lastRecruitTime: { - type: Number as PropType, + type: Number as PropType, default() { - return null; + return 0; } }, }, @@ -96,19 +99,24 @@ export default defineComponent({ window.localStorage.setItem("currentlyForHire", adventurer.id); }, - hireAdventurer(adventurer: Adventurer): void { + hireAdventurer(adventurer: Adventurer|any): void { + if (Object.keys(this.adventurers).length >= this.guild.adventurerCapacity.getAdventurerCapacity()) return; this.adventurers[adventurer.id] = adventurer; this.currentlyForHire = null; window.localStorage.removeItem("currentlyForHire"); this.$emit("recruitActionTaken", adventurer); }, dismissAdventurer() { + if (Object.keys(this.adventurers).length <= 0) return; this.currentlyForHire = null; this.$emit("recruitActionTaken", null); window.localStorage.removeItem("currentlyForHire"); } }, - mounted() { + async mounted() { + + this.adventurersForHire = await loadAdventurersForHire(Object.keys(this.adventurers)); + if (Object.keys(this.adventurers).length <= 0) { this.currentlyForHire = this.adventurersForHire[0]; window.localStorage.setItem("currentlyForHire", this.adventurersForHire[0].id); @@ -197,7 +205,8 @@ export default defineComponent({ color: #fff; } &.disabled { - color: rgba(0,0,0, 0.5) + color: rgba(0,0,0, 0.5); + cursor: default; } } } @@ -207,4 +216,4 @@ export default defineComponent({ } } - \ No newline at end of file + diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index cd2d6ba..18127d2 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -10,11 +10,14 @@

Guild level: {{ guild.level }}

-
+
+ +
Wipe your save data
@@ -24,13 +27,15 @@ @@ -326,6 +145,7 @@ export default defineComponent({ h1 { font-size: 3rem; + text-align: center; } .missives { @@ -334,51 +154,9 @@ export default defineComponent({ flex-wrap: wrap; width: calc(100% - 2rem); justify-content: center; - align-items: center; + align-items: stretch; padding-inline: 1rem; gap: 1rem; - - .missive { - width: min(100%, 14rem); - text-align: center; - border: 2px solid #000; - padding: 0.5rem; - position: relative; - background-color: rgba(255, 255, 255, 0.2); - - &.done { - cursor: pointer; - - &::after { - position: absolute; - top: 0; - right: 0; - content: "✔"; - font-size: 5rem; - color: green; - transform: translate(45%, -40%); - } - } - - .slots { - display: flex; - flex-direction: row; - flex-wrap: wrap; - justify-content: center; - align-items: center; - - .slot { - padding: 0; - width: 5rem; - height: 5rem; - border: 2px solid #000; - background-color: rgba(0, 0, 0, 0.2); - cursor: pointer; - border-radius: 0.2rem; - position: relative; - } - } - } } }