Compare commits

..

1 Commits

Author SHA1 Message Date
CI c07d6ac191 deploy 2025-06-03 05:47:31 +00:00
87 changed files with 101 additions and 13397 deletions
-16
View File
@@ -1,16 +0,0 @@
name: Build Vue
on:
release:
types: [published]
jobs:
build_vue:
runs-on: ubuntu-latest
name: Build Vue
steps:
- uses: actions/checkout@v2
- id: Build-Vue
uses: xRealNeon/VuePagesAction@1.0.1
with:
username: 'YouHaveTrouble'
reponame: 'GuildMaster'
token: ${{ secrets.GITHUB_TOKEN }}
-28
View File
@@ -1,28 +0,0 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
Symlink
+1
View File
@@ -0,0 +1 @@
index.html
-6
View File
@@ -1,6 +0,0 @@
<h1>Guild Master</h1>
<h2>Adventurer's guild management game</h2>
<p>It's a game where you manage an adventurer's guild. You can hire adventurers, assign them to quests to send them on adventures. </p>
<h3>How to play</h3>
Game is playable on <a href="https://guildmaster.yht.one/">guildmaster.yht.one</a> and is always automatically updated when new release is made.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+70 -79
View File
@@ -1,14 +1,75 @@
{
"levelRequirement": {
"F": 1,
"E": 5,
"D": 10,
"C": 25,
"B": 50,
"A": 100,
"S": 250
},
"ranks": {
"A": [
{
"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."
}
],
"B": [
{
"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."
}
],
"C": [
{
"title": "Scratchy, the butcher",
"text": "Scratchy turned evil and is terrorizing its victims. Put a stop to it!"
},
{
"title": "Hobgnoblin subjugation",
"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!"
}
],
"D": [
{
"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."
}
],
"E": [
{
"title": "Gnoblin subjugation",
"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."
}
],
"F": [
{
"title": "Frog Frenzy",
@@ -27,76 +88,6 @@
"text": "Tavern collapsed. Again. Help clean up the debris."
}
],
"E": [
{
"title": "Gnoblin subjugation",
"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."
}
],
"D": [
{
"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."
}
],
"C": [
{
"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!"
}
],
"B": [
{
"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."
}
],
"A": [
{
"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."
}
],
"S": [
{
"title": "The Demon King",
Vendored
-1
View File
@@ -1 +0,0 @@
/// <reference types="vite/client" />
View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 304 KiB

After

Width:  |  Height:  |  Size: 304 KiB

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB

+3 -2
View File
@@ -9,7 +9,6 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=EB+Garamond&display=swap" rel="stylesheet">
<link rel="manifest" href="/manifest.json" />
<link rel="preload" href="/img/promo/chicken_mage.jpg" as="image">
<meta name="description"
content="Guild Master is a browser game where you manage your own adventurer's guild!"/>
<meta property="twitter:title" content="Guild Master - Adventurer's guild management game"/>
@@ -21,12 +20,14 @@
<meta property="og:description"
content="Guild Master is a browser game where you manage your own adventurer's guild!"/>
<meta property="og:image" content="https://guildmaster.yht.one/img/app-icons/icon.png"/>
<script type="module" crossorigin src="/assets/index-981baea9.js"></script>
<link rel="stylesheet" href="/assets/index-87987ee1.css">
</head>
<body>
<div id="app"></div>
<noscript>
This is a javascript game. You need to enable javascript for it to work.
</noscript>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
-12480
View File
File diff suppressed because it is too large Load Diff
-31
View File
@@ -1,31 +0,0 @@
{
"name": "adventurers-guild",
"version": "0.14.0",
"private": true,
"scripts": {
"dev": "vite",
"dev-public": "vite --host",
"build": "run-p build-only && cp -r CNAME dist/CNAME",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"@vueuse/components": "^11.3.0",
"sass": "^1.81.0",
"vue": "^3.5.13",
"vue-router": "^4.4.5"
},
"devDependencies": {
"@types/node": "^18.19.64",
"@vitejs/plugin-vue": "^5.2.0",
"@vue/tsconfig": "^0.6.0",
"eslint": "^9.15.0",
"eslint-plugin-vue": "^9.31.0",
"npm-run-all": "^4.1.5",
"typescript": "~5.7.2",
"vite": "5.4.11",
"vite-plugin-pwa": "^0.21.0",
"vue-tsc": "^2.1.10"
}
}
-82
View File
@@ -1,82 +0,0 @@
[
{
"id": "aldek",
"name": "Aldek"
},
{
"id": "aria",
"name": "Aria"
},
{
"id": "burnett",
"name": "Burnett"
},
{
"id": "charlotte",
"name": "Charlotte"
},
{
"id": "ella",
"name": "Ella"
},
{
"id": "elyza",
"name": "Elyza"
},
{
"id": "emille",
"name": "Emille"
},
{
"id": "garret",
"name": "Garret"
},
{
"id": "gryza",
"name": "Gryza"
},
{
"id": "lestat",
"name": "Lestat"
},
{
"id": "lydia",
"name": "Lydia"
},
{
"id": "noor",
"name": "Noor"
},
{
"id": "noron",
"name": "Noron"
},
{
"id": "oola",
"name": "Oola"
},
{
"id": "owen",
"name": "Owen"
},
{
"id": "ryslette",
"name": "Ryslette"
},
{
"id": "sally",
"name": "Sally"
},
{
"id": "tovu",
"name": "Tovu"
},
{
"id": "wrydio",
"name": "Wrydio"
},
{
"id": "xarya",
"name": "Xarya"
}
]
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

-40
View File
@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="800px" height="800px" viewBox="0 0 569.613 569.614"
xml:space="preserve">
<g>
<g>
<path d="M371.49,563.638l113.052-65.854c5.26-3.063,9.088-8.094,10.64-13.975c1.555-5.888,0.701-12.148-2.359-17.405
l-30.769-52.807c4.789-6.524,9.083-13.115,12.972-19.918c3.893-6.799,7.405-13.84,10.606-21.275l61.114-0.221
c6.086-0.021,11.915-2.464,16.202-6.781c4.287-4.32,6.687-10.165,6.665-16.255l-0.48-130.833
c-0.024-6.089-2.464-11.919-6.784-16.206c-4.299-4.269-10.113-6.662-16.166-6.662c-0.03,0-0.062,0-0.089,0l-61.182,0.242
c-6.444-14.462-14.428-28.14-23.871-40.913l30.417-53.143c6.294-11.001,2.481-25.025-8.52-31.316L369.403,5.335
c-5.281-3.023-11.545-3.822-17.424-2.231c-5.872,1.598-10.872,5.462-13.892,10.747L307.665,67
c-15.766-1.662-31.653-1.613-47.363,0.144l-30.796-52.892c-3.063-5.263-8.094-9.091-13.975-10.646
c-5.884-1.551-12.148-0.704-17.408,2.359L85.068,71.823c-10.949,6.38-14.657,20.429-8.28,31.38l30.765,52.831
c-4.761,6.484-9.048,13.076-12.953,19.899c-3.904,6.824-7.417,13.855-10.6,21.255l-61.139,0.235
C10.187,197.472-0.046,207.785,0,220.456L0.48,351.29c0.024,6.086,2.463,11.919,6.784,16.206
c4.299,4.269,10.11,6.661,16.166,6.661c0.028,0,0.058,0,0.086,0l61.203-0.229c6.432,14.452,14.413,28.131,23.868,40.915
l-30.413,53.141c-3.023,5.284-3.825,11.548-2.231,17.423c1.597,5.872,5.462,10.872,10.747,13.896l113.535,64.977
c3.596,2.056,7.513,3.032,11.38,3.032c7.962,0,15.701-4.146,19.942-11.552l30.417-53.149c15.799,1.671,31.684,1.619,47.348-0.144
l30.799,52.89c3.066,5.26,8.094,9.088,13.978,10.643C359.967,567.552,366.23,566.705,371.49,563.638z M341.129,465.911
c-4.902-8.418-14.599-12.815-24.137-10.994c-20.588,3.935-42.174,3.999-63.128,0.202c-9.572-1.735-19.184,2.741-24.015,11.181
l-26.748,46.745l-73.694-42.18l26.75-46.741c4.832-8.439,3.819-19.006-2.521-26.371c-13.978-16.239-24.685-34.594-31.818-54.554
c-3.265-9.131-11.918-15.227-21.61-15.227c-0.027,0-0.058,0-0.085,0l-53.825,0.199l-0.315-84.937l53.819-0.205
c9.722-0.04,18.366-6.197,21.576-15.374c3.69-10.557,7.962-20.019,13.06-28.917c5.101-8.914,11.089-17.387,18.311-25.897
c6.294-7.417,7.225-17.993,2.334-26.396l-27.081-46.509l73.385-42.754l27.078,46.497c4.893,8.4,14.544,12.821,24.095,11.004
c20.716-3.911,42.317-3.978,63.189-0.19c9.557,1.753,19.189-2.742,24.019-11.178l26.753-46.744l73.697,42.179l-26.753,46.742
c-4.826,8.437-3.816,19,2.521,26.368c13.956,16.221,24.669,34.587,31.842,54.59c3.271,9.119,11.919,15.202,21.604,15.202
c0.031,0,0.062,0,0.092,0l53.789-0.214l0.315,84.927l-53.783,0.192c-9.712,0.037-18.351,6.182-21.569,15.347
c-3.746,10.654-8.023,20.131-13.082,28.975c-5.064,8.847-11.067,17.338-18.356,25.958c-6.271,7.418-7.194,17.978-2.305,26.368
l27.078,46.472l-73.391,42.749L341.129,465.911z"/>
<path d="M392.531,346.458c16.472-28.773,20.746-62.24,12.047-94.232s-29.342-58.685-58.115-75.151
c-18.761-10.74-40.05-16.417-61.562-16.417c-44.446,0-85.762,23.944-107.822,62.485c-33.994,59.404-13.327,135.39,46.071,169.386
c18.764,10.737,40.052,16.411,61.564,16.411C329.158,408.943,370.475,385.001,392.531,346.458z M352.696,323.658
c-13.902,24.293-39.955,39.385-67.985,39.385c-13.528,0-26.934-3.58-38.764-10.349c-37.433-21.426-50.456-69.312-29.033-106.751
c13.905-24.291,39.958-39.385,67.987-39.385c13.528,0,26.932,3.58,38.762,10.355c18.136,10.379,31.142,27.197,36.628,47.359
C365.771,284.435,363.075,305.524,352.696,323.658z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

-1
View File
@@ -1 +0,0 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Discord</title><path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="24" fill="none"/>
<path d="M12,2A10,10,0,0,0,8.84,21.5c.5.08.66-.23.66-.5V19.31C6.73,19.91,6.14,18,6.14,18A2.69,2.69,0,0,0,5,16.5c-.91-.62.07-.6.07-.6a2.1,2.1,0,0,1,1.53,1,2.15,2.15,0,0,0,2.91.83,2.16,2.16,0,0,1,.63-1.34C8,16.17,5.62,15.31,5.62,11.5a3.87,3.87,0,0,1,1-2.71,3.58,3.58,0,0,1,.1-2.64s.84-.27,2.75,1a9.63,9.63,0,0,1,5,0c1.91-1.29,2.75-1,2.75-1a3.58,3.58,0,0,1,.1,2.64,3.87,3.87,0,0,1,1,2.71c0,3.82-2.34,4.66-4.57,4.91a2.39,2.39,0,0,1,.69,1.85V21c0,.27.16.59.67.5A10,10,0,0,0,12,2Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 731 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1018 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 947 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

-235
View File
@@ -1,235 +0,0 @@
<script setup lang="ts">
import {RouterLink, RouterView} from 'vue-router'
import {version} from "../package.json"
</script>
<template>
<section class="loading-screen" :class="{disabled: !loading}">
<div class="title panel note-paper">
<h1>Guild Master</h1>
<h3>Adventurer's guild management game</h3>
<small>v{{ version }}</small>
<div class="lds-ring">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<h3>Loading assets...</h3>
</div>
</section>
<header>
<nav>
<RouterLink
:to="{name: 'guild'}"
>
Guild
</RouterLink>
</nav>
</header>
<RouterView/>
</template>
<script lang="ts">
import {defineComponent} from "vue";
import AdventurerIdentity from "@/models/AdventurerIdentity.ts";
import SaveData from "@/models/SaveData.ts";
export default defineComponent({
name: "GuildMaster",
data: () => ({
loading: true,
screenWakeLock: null as null | WakeLockSentinel,
possibleRecruits: {} as { [key: string]: AdventurerIdentity },
saveData: null as null | SaveData,
}),
methods: {
async acquireScreenWakeLock(): Promise<void> {
if (!("wakeLock" in navigator)) {
return;
}
if (this.screenWakeLock !== null) {
return;
}
try {
this.screenWakeLock = await navigator.wakeLock.request("screen");
} catch (e) {
setTimeout(() => {
this.acquireScreenWakeLock();
}, 1000);
}
},
async loadAdventurerData(): Promise<void> {
await fetch("/data/adventurers.json")
.then(response => response.json())
.then(data => {
if (!Array.isArray(data)) throw new Error("Data was expected to be an array");
for (const rawData of data) {
if (typeof rawData.id !== "string" || typeof rawData.name !== "string" || typeof rawData.portrait !== "string") {
console.error("Failed to load one of the adventurer's data: invalid data");
continue;
}
this.possibleRecruits[rawData.id] = new AdventurerIdentity(
rawData.id,
rawData.name,
rawData.portrait,
);
}
})
.catch(error => {
console.error("Failed to load adventurer data:", error);
});
},
saveGame(): void {
window.localStorage.setItem("saveData", JSON.stringify(this.saveData));
console.debug("Game saved");
},
loadGame(): void {
const saveData = window.localStorage.getItem("saveData");
if (saveData === null) {
this.saveData = new SaveData({}, this.possibleRecruits);
return;
}
const jsonData = JSON.parse(saveData);
if (jsonData === null) return;
this.saveData = new SaveData(jsonData, this.possibleRecruits);
for (const adventurer of this.saveData.adventurers) {
delete this.possibleRecruits[adventurer?.identity?.id];
}
}
},
async mounted() {
await this.acquireScreenWakeLock();
await this.loadAdventurerData();
this.loadGame();
this.loading = false;
console.debug("Game loaded");
setInterval(() => {
this.saveGame();
}, 10 * 1000);
},
})
</script>
<style lang="scss" scoped>
header {
line-height: 1;
max-height: 100vh;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
nav {
width: max-content;
text-align: center;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
padding-inline: 2rem;
padding-bottom: 2rem;
padding-top: 0.5rem;
background-size: 100%;
background-repeat: no-repeat;
background-position: bottom;
filter: drop-shadow(0 0 0.5rem rgba(0, 0, 0, 0.25));
.icon {
width: 2rem;
height: 2rem;
transform: translateY(0.35rem);
}
a {
font-size: 2rem;
color: #000;
text-decoration: none;
&.router-link-active {
text-decoration: underline;
}
}
}
.loading-screen {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 5;
user-select: none;
background-size: cover;
background-position: center;
background-image: url("/img/promo/chicken_mage.jpg");
background-repeat: no-repeat;
display: flex;
justify-content: flex-start;
align-items: flex-start;
transition: opacity 0.25s linear;
.title {
margin-block: 2.5%;
margin-inline: 2.5%;
}
&.disabled {
opacity: 0;
pointer-events: none;
}
.lds-ring {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-ring div {
box-sizing: border-box;
display: block;
position: absolute;
width: 64px;
height: 64px;
margin: 8px;
border: 8px solid;
border-radius: 50%;
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
border-color: #000 transparent transparent transparent;
}
.lds-ring div:nth-child(1) {
animation-delay: -0.45s;
}
.lds-ring div:nth-child(2) {
animation-delay: -0.3s;
}
.lds-ring div:nth-child(3) {
animation-delay: -0.15s;
}
@keyframes lds-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}
</style>
-78
View File
@@ -1,78 +0,0 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: system-ui, sans-serif;
font-weight: normal;
vertical-align: baseline;
overflow-wrap: break-word;
-webkit-font-smoothing: antialiased;
}
body {
line-height: 1.5;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
button {
border: none;
background: none;
outline: none;
font-size: inherit;
}
button:focus-visible {
outline: 2px solid black;
}
input {
border: none;
outline: none;
}
input:focus-visible {
outline: 2px solid black;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
body {
margin: 0;
padding: 0;
min-height: 100vh;
font-family: 'EB Garamond', serif;
overflow-y: scroll;
user-select: none;
background-color: rgb(19, 16, 14);
background-blend-mode: darken;
background-repeat: repeat;
display: flex;
flex-direction: column;
align-items: center;
}
main {
max-width: 69rem;
display: flex;
flex-direction: column;
align-items: center;
}
#app {
width: 100%;
}
-11
View File
@@ -1,11 +0,0 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import '@/assets/main.scss'
const app = createApp(App)
app.use(router)
app.mount('#app')
-39
View File
@@ -1,39 +0,0 @@
import type StatHolder from "@/models/StatHolder.ts";
import AdventurerInventory from "@/models/AdventurerInventory.ts";
import type AdventurerIdentity from "@/models/AdventurerIdentity.ts";
export default class Adventurer implements StatHolder {
identity: AdventurerIdentity;
experience: number = 0;
basePower: number = 0;
baseDefense: number = 0;
inventory: AdventurerInventory;
constructor(
identity: AdventurerIdentity,
experience: number = 0,
basePower: number = 0,
baseDefense: number = 0,
inventory: AdventurerInventory = new AdventurerInventory()
) {
this.identity = identity;
this.experience = experience;
this.basePower = basePower;
this.baseDefense = baseDefense;
this.inventory = inventory;
}
getPower(): number {
let power = this.basePower;
power += this.inventory.getPower();
return power;
}
getDefense(): number {
let defense = this.baseDefense;
defense += this.inventory.getDefense();
return defense;
}
}
-13
View File
@@ -1,13 +0,0 @@
export default class AdventurerIdentity {
id: string;
name: string;
portrait: string;
constructor(id: string, name: string, portrait: string) {
this.id = id;
this.name = name;
this.portrait = portrait;
}
}
-61
View File
@@ -1,61 +0,0 @@
import type Item from "@/models/Item.ts";
import type StatHolder from "@/models/StatHolder.ts";
export default class AdventurerInventory implements StatHolder {
helmetId = 0;
armorId = 1;
bootsId = 2;
weaponId = 3;
items: Array<Item|null> = [];
constructor(
helmet: Item | null = null,
armor: Item | null = null,
boots: Item | null = null,
weapon: Item | null = null
) {
this.items[this.helmetId] = helmet;
this.items[this.armorId] = armor;
this.items[this.bootsId] = boots;
this.items[this.weaponId] = weapon;
}
getHelmet(): Item | null {
return this.items[this.helmetId];
}
getArmor(): Item | null {
return this.items[this.armorId];
}
getBoots(): Item | null {
return this.items[this.bootsId];
}
getWeapon(): Item | null {
return this.items[this.weaponId];
}
getDefense(): number {
let defense = 0;
for (let item of this.items) {
if (item !== null) {
defense += item.getDefense();
}
}
return defense
}
getPower(): number {
let power = 0;
for (let item of this.items) {
if (item !== null) {
power += item.getPower();
}
}
return power;
}
}
-34
View File
@@ -1,34 +0,0 @@
import type StatHolder from "@/models/StatHolder.ts";
import type {ItemType} from "@/models/ItemType.ts";
export default class Item implements StatHolder {
name: string;
description: string;
power: number;
defense: number;
type: ItemType;
constructor(
name: string,
description: string,
power: number,
defense: number,
type: ItemType
) {
this.name = name;
this.description = description;
this.power = power;
this.defense = defense;
this.type = type;
}
getDefense(): number {
return this.defense;
}
getPower(): number {
return this.power;
}
}
-8
View File
@@ -1,8 +0,0 @@
export enum ItemType {
HELMET = 'helmet',
ARMOR = 'armor',
BOOTS = 'boots',
WEAPON = 'weapon',
}
-36
View File
@@ -1,36 +0,0 @@
import Adventurer from "@/models/Adventurer.ts";
import type AdventurerIdentity from "@/models/AdventurerIdentity.ts";
import AdventurerInventory from "@/models/AdventurerInventory.ts";
export default class SaveData {
adventurers: Array<Adventurer> = [];
constructor(
data: {[key:string]: unknown} = {},
adventurerIdentities: {[key:string]: AdventurerIdentity} = {}
) {
if (Array.isArray(data?.adventurers)) {
for (const adventurerData of data.adventurers) {
const identity = adventurerIdentities[adventurerData?.identity?.id];
if (!identity) {
console.error("Adventurer identity not found for adventurer data", adventurerData);
continue;
}
this.adventurers.push(new Adventurer(
identity,
adventurerData?.experience ?? 0,
adventurerData?.basePower ?? 0,
adventurerData?.baseDefense ?? 0,
new AdventurerInventory(
adventurerData?.inventory?.helmet ?? null,
adventurerData?.inventory?.armor ?? null,
adventurerData?.inventory?.boots ?? null,
adventurerData?.inventory?.weapon ?? null,
)
));
}
}
}
}
-6
View File
@@ -1,6 +0,0 @@
export default interface StatHolder {
getPower(): number;
getDefense(): number;
}
-16
View File
@@ -1,16 +0,0 @@
import {createRouter, createWebHashHistory} from 'vue-router'
import HomeView from '@/views/HomeView.vue';
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'guild',
component: HomeView,
},
]
})
export default router
-38
View File
@@ -1,38 +0,0 @@
<template>
<main>
<section class="title panel note-paper">
<h1>Guild Master</h1>
<h3>Adventurer's guild management game</h3>
<small>v{{ version }}</small>
<p class="news">{{ news }}</p>
</section>
</main>
</template>
<script lang="ts">
import {defineComponent} from "vue";
import {version} from "../../package.json"
export default defineComponent({
name: "GuildView",
methods: {},
components: {},
data: () => {
return {
version: version,
}
},
props: {
news: {
type: String,
default: "",
},
}
});
</script>
<style lang="scss">
</style>
-8
View File
@@ -1,8 +0,0 @@
{
"extends": "@vue/tsconfig/tsconfig.json",
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*", "playwright.config.*"],
"compilerOptions": {
"composite": true,
"types": ["node"]
}
}
-16
View File
@@ -1,16 +0,0 @@
{
"extends": "@vue/tsconfig/tsconfig.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"references": [
{
"path": "./tsconfig.config.json"
}
]
}
-26
View File
@@ -1,26 +0,0 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import {VitePWA} from "vite-plugin-pwa";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
VitePWA({
registerType: 'prompt',
injectRegister: 'script',
filename: 'service-worker.js',
workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,jpeg,svg,json}'],
}
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
base: "/"
})