Skip to content
Snippets Groups Projects
Commit 89470950 authored by Jonas Zohren's avatar Jonas Zohren :speech_balloon:
Browse files

Added moar stuff

parent 60ffa253
No related branches found
No related tags found
No related merge requests found
Pipeline #16830 passed
...@@ -909,6 +909,11 @@ ...@@ -909,6 +909,11 @@
} }
} }
}, },
"svelte-local-storage-store": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/svelte-local-storage-store/-/svelte-local-storage-store-0.1.4.tgz",
"integrity": "sha512-XlSJqMdV1UAROsKHYQSKwI9xU0u8En/nQ6ti2flmUhBA0PM+oqXjvCyM2849ONb5JbrpyUO18CwXcSJgxYCR8w=="
},
"svelte-preprocess": { "svelte-preprocess": {
"version": "4.6.9", "version": "4.6.9",
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.6.9.tgz", "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.6.9.tgz",
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
"typescript": "^4.0.0" "typescript": "^4.0.0"
}, },
"dependencies": { "dependencies": {
"sirv-cli": "^1.0.0" "sirv-cli": "^1.0.0",
"svelte-local-storage-store": "^0.1.4"
} }
} }
{ {
"title": "Frank Thorsten Breuer – Studienkoordinator",
"imageUrl": "./Breuer_Frank_Thorsten.jpg",
"startDialogName": "start", "startDialogName": "start",
"dialogs": { "dialogs": {
"start": { "start": {
"title": "Frank Thorsten Breuer – Studienkoordinator", "text": "",
"imageUrl": "./Breuer_Frank_Thorsten.jpg",
"text": "Hallo, kann ich etwas für sie tun?",
"options": [ "options": [
{ {
"text": "Hallo Herr Breuer, ich grüße sie recht herzlich!", "text": "Hallo Herr Breuer, ich grüße sie recht herzlich!",
"linksToDialog": "greetBreuer" "linksToDialog": "greetBreuer"
}, },
{
"text": "Geht es ihnen gut? Sie sehen etwas bleich aus.",
"linksToDialog": "mayIBringSomething",
"forbiddenFacts": ["acceptedFtbMateQuest"]
},
{
"text": "Ich habe ihnen ihre Mate gebracht!",
"linksToDialog": "giveMate",
"requiredFacts": ["collectedFtbMate"],
"forbiddenFacts": ["completedFtbMateQuest"]
},
{ {
"text": "Hallo, ich suche den Hörsaal E23", "text": "Hallo, ich suche den Hörsaal E23",
"forbiddenFacts": ["askedFtbForHs"],
"linksToDialog": "seekHS" "linksToDialog": "seekHS"
} }
] ]
}, },
"mayIBringSomething": {
"text": "Oh ja!\nIch verdurste fast, könnten sie mir eine Mate bringen?\nIch kann hier leider erstmal nicht weg und das selbst tun, zu viel Arbeit...",
"options": [
{
"text": "Klar, warum nicht.",
"linksToDialog": "acceptFtbMateQuest"
},
{
"text": "Danke, kein Interesse",
"linksToDialog": "rejectFtbMateQuest"
}
]
},
"giveMate": {
"text": "Ah, das tut gut. Vielen Dank, das war jetzt nötig. Sie haben was gut bei mir.",
"addFacts": ["completedFtbMateQuest"],
"options": [
{
"text": "Gern geschehen.",
"linksToDialog": "start"
}
]
},
"acceptFtbMateQuest": {
"text": "Ich danke ihnen. Der Kiosk ist direkt links, wenn sie in den Fachschaftsflur kommen. Das ist der Gang auf rechten Seite von der Eingangstür.",
"addFacts": ["acceptedFtbMateQuest"],
"options": [
{
"text": "Ok",
"linksToDialog": "start"
}
]
},
"rejectFtbMateQuest": {
"text": "Schade. Sollten sie sich noch umentscheiden, melden sie sich gerne bei mir.",
"options": [
{
"text": "Ok",
"linksToDialog": "start"
}
]
},
"seekHS": { "seekHS": {
"title": "Frank Thorsten Breuer – Studienkoordinator",
"imageUrl": "./Breuer_Frank_Thorsten.jpg",
"text": "Da müssen sie den Flur wieder zurück gehen und im Foyer nach hinten durchgehen. Den Hörsaal erkennen sie an der großen Doppeltür", "text": "Da müssen sie den Flur wieder zurück gehen und im Foyer nach hinten durchgehen. Den Hörsaal erkennen sie an der großen Doppeltür",
"options": [] "addFacts": ["askedFtbForHs"],
"options": [
{
"text": "Ah, danke",
"linksToDialog": "start"
}
]
}, },
"greetBreuer": { "greetBreuer": {
"title": "Frank Thorsten Breuer – Studienkoordinator",
"imageUrl": "./Breuer_Frank_Thorsten.jpg",
"text": "Ich grüße sie auch recht herzlich, studieren sie zufälligerweise Informatik?", "text": "Ich grüße sie auch recht herzlich, studieren sie zufälligerweise Informatik?",
"options": [ "options": [
{ {
...@@ -38,29 +94,22 @@ ...@@ -38,29 +94,22 @@
] ]
}, },
"longTimeStudent": { "longTimeStudent": {
"title": "Frank Thorsten Breuer – Studienkoordinator",
"imageUrl": "./Breuer_Frank_Thorsten.jpg",
"text": "Dann sollten sie mal schnell weiter studieren gehen!", "text": "Dann sollten sie mal schnell weiter studieren gehen!",
"options": [] "options": []
}, },
"startedToStudy": { "startedToStudy": {
"title": "Frank Thorsten Breuer – Studienkoordinator", "text": "Wunderbar, ich kann deine, verzeihung, ich darf sie doch duzen, oder?\nAlso ich brauche deine Hilfe. Der Studiengang Informatik muss regelmäßig akkreditiert werden, damit wir ihn weiter anbieten dürfen. Jetzt haben leider die verdammten Studenten von der Fachschaft in den letzten genehnmigten Studienplan das Modul \"Angewandte Chaostheorie\" hineingeschmuggelt. Das ist bei uns leider niemanden aufgefallen, der Akkreditierungskommission vom Bildungsministerium aber schon. Wenn wir nicht bald nachweisen können, dass jemand dieses Modul auch belegt und erfolgreich abgeschlossen hat, wird uns die Akkreditierung entzogen und der Informatik-Studiengang muss eingestellt werden. Ich bitte sie, helfen sie mir!",
"imageUrl": "./Breuer_Frank_Thorsten.jpg", "addFacts": ["acceptedMainQuest"],
"text": "Wunderbar, ich kann deine, verzeihung, ich darf sie doch duzen, oder?\\n\\nAlso ich brauche deine Hilfe. Der Studiengang Informatik muss regelmäßig akkreditiert werden, damit wir ihn weiter anbieten dürfen. Jetzt haben leider die verdammten Studenten von der Fachschaft in den letzten genehnmigten Studienplan das Modul \"Angewandte Chaostheorie\" hineingeschmuggelt. Das ist bei uns leider niemanden aufgefallen, der Akkreditierungskommission vom Bildungsministerium aber schon. Wenn wir nicht bald nachweisen können, dass jemand dieses Modul auch belegt und erfolgreich abgeschlossen hat, wird uns die Akkreditierung entzogen und der Informatik-Studiengang muss eingestellt werden. Ich bitte sie, helfen sie mir!",
"options": [ "options": [
{ "text": "Ich helfe gerne!", "linksToDialog": "agreeToHelp" }, { "text": "Ich helfe gerne!", "linksToDialog": "agreeToHelp" },
{ "text": "Was geht mich das denn an?", "linksToDialog": "denyHelp" } { "text": "Was geht mich das denn an?", "linksToDialog": "denyHelp" }
] ]
}, },
"denyHelp": { "denyHelp": {
"title": "Frank Thorsten Breuer – Studienkoordinator",
"imageUrl": "./Breuer_Frank_Thorsten.jpg",
"text": "Schade, ich dachte sie hätten das Zeug dazu. Nun gut, gehen sie studieren, ich finde schon selbst eine Lösung.", "text": "Schade, ich dachte sie hätten das Zeug dazu. Nun gut, gehen sie studieren, ich finde schon selbst eine Lösung.",
"options": [] "options": []
}, },
"agreeToHelp": { "agreeToHelp": {
"title": "Frank Thorsten Breuer – Studienkoordinator",
"imageUrl": "./Breuer_Frank_Thorsten.jpg",
"text": "Wunderbar, sobald mehr Story geschrieben wurde, erhalten sie hier eine epische Quest um die Fakultät vor Schmach und Schande zu retten.", "text": "Wunderbar, sobald mehr Story geschrieben wurde, erhalten sie hier eine epische Quest um die Fakultät vor Schmach und Schande zu retten.",
"options": [] "options": []
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<title>OH14 Workadventure Story</title> <title>OH14 Work Adventure Story</title>
<link rel="icon" type="image/png" href="./favicon.png" /> <link rel="icon" type="image/png" href="./favicon.png" />
<link rel="stylesheet" href="./global.css" /> <link rel="stylesheet" href="./global.css" />
......
<script lang="ts"> <script lang="ts">
import DialogSetComponent from "./DialogSetComponent.svelte"; import DialogSetComponent from "./DialogSetComponent.svelte";
import { fetchDialogSet } from "./utils"; import { fetchDialogSet } from "./utils";
import Debugger from "./Debugger.svelte";
import type { Dialog } from "./types";
const dialogSetPromise = fetchDialogSet(); const dialogSetPromise = fetchDialogSet();
let currentDialog: Dialog;
</script> </script>
<main> <main>
{#await dialogSetPromise then dialogSet} {#await dialogSetPromise then dialogSet}
<DialogSetComponent {...dialogSet} /> <DialogSetComponent bind:currentDialog={currentDialog} {...dialogSet} />
{:catch error}
<br>
<Debugger dialogSet={dialogSet} bind:currentDialog={currentDialog}/>
{:catch _error}
<h3>Oh no :(</h3> <h3>Oh no :(</h3>
<p> <p>
We could not load that dialogSet that you specified in the url. Sorry. We could not load that dialogSet that you specified in the url. Sorry. Please go complain to your friendly admin(s).
</p> </p>
{/await} {/await}
</main> </main>
<script lang="ts">
import { gameFactsStore, addGameFactToFactArray, toggleFactInFactArray } from './gameFacts'
import type { Dialog, DialogMap, DialogSet, FactId } from './types';
export let currentDialog: Dialog;
export let dialogSet: DialogSet;
$: dialogNames = Object.keys(dialogSet.dialogs)
export let selectedDialogName: string
function getDialogFacts(dialogMap: DialogMap): FactId[] {
const dialogs = [];
for (const dmKey of Object.keys(dialogMap)) dialogs.push(dialogMap[dmKey]);
return dialogs.map(dialog => [...(dialog.addFacts || []), ...(dialog.removeFacts || [])]).flat()
}
let seenFactIds = new Set<FactId>([...$gameFactsStore, ...getDialogFacts(dialogSet.dialogs)]);
$: seenFactIdsArray = Array.from(seenFactIds)
let addFactInputValue: string;
</script>
<div>
<h3>Dialog-Debugger</h3>
Jump to dialog:
<!-- svelte-ignore a11y-no-onchange -->
<select bind:value={selectedDialogName} on:change="{() => currentDialog = dialogSet.dialogs[selectedDialogName]}">
{#each dialogNames as dialogName}
<option value={dialogName} selected={dialogName === selectedDialogName}>
{dialogName}
</option>
{/each}
</select>
<hr>
<h3>Quest-Debugger</h3>
<b>GameFacts:</b>
<ul>
{#each seenFactIdsArray as gameFact}
<li>
<input type="checkbox" checked={$gameFactsStore.includes(gameFact)} on:change={() => gameFactsStore.set(toggleFactInFactArray(gameFact, $gameFactsStore))}>
{gameFact}
</li>
{/each}
</ul>
Add fact:
<input type="text" bind:value={addFactInputValue}>
<button style="width: 3rem;" on:click={() => {
gameFactsStore.set(addGameFactToFactArray(addFactInputValue, $gameFactsStore));
seenFactIds = seenFactIds.add(addFactInputValue);
addFactInputValue = '';
}}>Add</button>
</div>
<style>
div {
border: 1px solid;
padding: 10px;
margin: 5px;
}
</style>
\ No newline at end of file
<script lang="ts"> <script lang="ts">
import SingleDialogComponent from "./SingleDialogComponent.svelte"; import SingleDialogComponent from "./SingleDialogComponent.svelte";
import type { DialogMap } from "./types"; import type { DialogMap } from "./types";
export let title: string;
export let imageUrl: string;
export let startDialogName: string; export let startDialogName: string;
export let dialogs: DialogMap; export let dialogs: DialogMap;
let currentDialog = dialogs[startDialogName]; export let currentDialog = dialogs[startDialogName];
function switchDialog(targetDialog: string) { function switchDialog(targetDialog: string) {
currentDialog = dialogs[targetDialog]; currentDialog = dialogs[targetDialog];
...@@ -19,6 +21,6 @@ ...@@ -19,6 +21,6 @@
</script> </script>
<SingleDialogComponent <SingleDialogComponent
{...currentDialog} imageUrl={imageUrl} title={title} {...currentDialog}
on:switchToDialog={(event) => switchDialog(event.detail)} on:switchToDialog={(event) => switchDialog(event.detail)}
/> />
<script lang="ts"> <script lang="ts">
import type { DialogOption } from "./types"; import type { DialogOption, FactId } from "./types";
import { createEventDispatcher } from "svelte"; import { createEventDispatcher } from "svelte";
import { gameFactsStore, addGameFactToFactArray } from './gameFacts'
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
export let imageUrl: string; export let imageUrl: string;
export let title: string | undefined; export let title: string | undefined;
export let text: string; export let text: string;
export let options: DialogOption[]; export let options: DialogOption[] = [];
$: usableOptions = options.filter(option => isDialogOptionAllowedByGameFacts(option, $gameFactsStore))
export let addFacts: FactId[] = [];
$: {
if (Array.isArray(addFacts)) {
const gameFactsAfterAddedFacts = addFacts.reduce((accFacts, factToAdd) => addGameFactToFactArray(factToAdd, accFacts), $gameFactsStore)
$gameFactsStore = gameFactsAfterAddedFacts;
}
}
export let removeFacts: FactId[] = [];
$: {
if (Array.isArray(removeFacts)) {
const gameFactsAfterRemovedFacts = removeFacts.reduce((accFacts, factToRemove) => accFacts.filter(f => f !== factToRemove), $gameFactsStore)
$gameFactsStore = gameFactsAfterRemovedFacts;
}
}
function isDialogOptionAllowedByGameFacts(option: DialogOption, gameFacts: FactId[]): boolean {
// Check if all required facts are given
if (Array.isArray(option.requiredFacts)) {
const isOk = option.requiredFacts.every(requiredFact => gameFacts.includes(requiredFact));
if (!isOk) {
return false;
}
}
// Check if no forbidden facts are given
if (Array.isArray(option.forbiddenFacts)) {
const isOk = option.forbiddenFacts.every(forbiddenFact => !gameFacts.includes(forbiddenFact));
if (!isOk) {
return false;
}
}
return true;
}
function handleDialogOptionClick(option: DialogOption): void {
dispatch("switchToDialog", option.linksToDialog)
}
</script> </script>
{#if typeof title === "string"} {#if typeof title === "string"}
...@@ -19,16 +59,16 @@ ...@@ -19,16 +59,16 @@
<img src={imageUrl} alt="Portrait" /> <img src={imageUrl} alt="Portrait" />
<div> <div>
{#each text.split("\n\n") as para} {#each text.split("\n") as para}
<p>{para}</p> <p>{para}</p>
{/each} {/each}
</div> </div>
<hr /> <hr />
<div> <div>
{#each options as option} {#each usableOptions as option}
<button on:click={() => dispatch("switchToDialog", option.linksToDialog)} <button on:click={() => handleDialogOptionClick(option)}>
>{option.text}</button {option.text}
> </button>
<br /> <br />
{/each} {/each}
</div> </div>
import { writable } from "svelte-local-storage-store";
import type { Writable } from "svelte/store";
import type { FactId } from "./types";
export const gameFactsStore: Writable<FactId[]> = writable("gameFacts", [
"debugRequiredFact",
]);
export function addGameFactToFactArray(
gameFact: FactId,
factArray: FactId[]
): FactId[] {
if (!factArray.includes(gameFact)) {
return [...factArray, gameFact];
} else {
return factArray;
}
}
export function toggleFactInFactArray(
gameFact: FactId,
factArray: FactId[]
): FactId[] {
if (!factArray.includes(gameFact)) {
return [...factArray, gameFact];
} else {
return factArray.filter((f) => f !== gameFact);
}
}
export interface DialogSet { export interface DialogSet {
title?: string;
imageUrl: string;
startDialogName: string; startDialogName: string;
dialogs: DialogMap; dialogs: DialogMap;
} }
...@@ -8,13 +10,19 @@ export type DialogMap = { ...@@ -8,13 +10,19 @@ export type DialogMap = {
}; };
export interface Dialog { export interface Dialog {
imageUrl: string; title?: string; // Can be used to overwrite title from DialogSet
title?: string; imageUrl?: string; // Can be used to overwrite imageUrl from DialogSet
text: string; text?: string;
options: DialogOption[]; options: DialogOption[];
addFacts?: FactId[];
removeFacts?: FactId[];
} }
export interface DialogOption { export interface DialogOption {
text: string; text: string;
linksToDialog: string; linksToDialog: string;
requiredFacts?: FactId[];
forbiddenFacts?: FactId[];
} }
export type FactId = String;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment