713 lines
21 KiB
JavaScript
713 lines
21 KiB
JavaScript
import storyNodes from "./story.js";
|
|
import sounds from "./sounds.js";
|
|
import items from "./items.js";
|
|
import recipes from "./recipes.js";
|
|
|
|
// ==================================================================
|
|
// Variablen und Elemente
|
|
// ==================================================================
|
|
const storyTextElement = document.getElementById("story-text");
|
|
const optionsButtonsElement = document.getElementById("options-buttons");
|
|
|
|
const prolog1 = document.getElementById("prolog-1");
|
|
const prolog2 = document.getElementById("prolog-2");
|
|
const gameContainer = document.getElementById("game-container");
|
|
const introContainer = document.getElementById("intro-container");
|
|
const landingPage = document.getElementById("landingpage");
|
|
|
|
const initialStartBtn = document.getElementById("initial-start-btn");
|
|
const startBtn = document.getElementById("weiter-btn");
|
|
const openEyesBtn = document.getElementById("open-eyes-btn");
|
|
|
|
const continueBtn = document.getElementById("continue-btn");
|
|
|
|
const healthFillBar = document.getElementById("health-bar-fill");
|
|
const hungerFillBar = document.getElementById("hunger-bar-fill");
|
|
const thirstFillBar = document.getElementById("thirst-bar-fill");
|
|
|
|
const prologMusic = new Audio(sounds.prologMusic);
|
|
const crashSound = new Audio(sounds.crashSound);
|
|
|
|
const openCraftingBtn = document.getElementById("open-crafting-btn");
|
|
const closeCraftingBtn = document.getElementById("close-crafting-btn");
|
|
const craftingModal = document.getElementById("crafting-modal");
|
|
|
|
const openInventoryBtn = document.getElementById("open-inventory-btn");
|
|
const inventoryModal = document.getElementById("inventory-modal");
|
|
const closeInventoryBtn = document.getElementById("close-inventory-btn");
|
|
|
|
const openBasebuildingBtn = document.getElementById("open-basebuilding-btn");
|
|
const basebuildingModal = document.getElementById("basebuilding-modal");
|
|
const closeBasebuildingBtn = document.getElementById("close-basebuilding-btn");
|
|
|
|
// ==================================================================
|
|
// Savegame Handling
|
|
// ==================================================================
|
|
if (localStorage.getItem("saveGameData")) {
|
|
continueBtn.classList.remove("hidden");
|
|
}
|
|
|
|
// ==================================================================
|
|
// Prolog Music
|
|
// ==================================================================
|
|
prologMusic.loop = true;
|
|
prologMusic.volume = 0.5;
|
|
|
|
// ==================================================================
|
|
// Event Listener Setup
|
|
// ==================================================================
|
|
|
|
// -------Prolog Start-------
|
|
initialStartBtn.addEventListener("click", () => {
|
|
localStorage.removeItem("saveGameData");
|
|
landingPage.classList.add("hidden");
|
|
introContainer.classList.remove("hidden");
|
|
prologMusic.play();
|
|
});
|
|
|
|
// -------Spielstand Laden-------
|
|
continueBtn.addEventListener("click", () => {
|
|
introContainer.classList.add("hidden");
|
|
landingPage.classList.add("hidden");
|
|
gameContainer.classList.remove("hidden");
|
|
loadGame();
|
|
showStoryNode(playerState.currentSceneId);
|
|
});
|
|
|
|
// -------Spiel Start-------
|
|
startBtn.addEventListener("click", () => {
|
|
prologMusic.pause();
|
|
crashSound.play();
|
|
|
|
prolog1.classList.add("hidden");
|
|
prolog2.classList.remove("hidden");
|
|
});
|
|
|
|
// -------Augen öffnen-------
|
|
openEyesBtn.addEventListener("click", () => {
|
|
prolog2.classList.add("hidden");
|
|
introContainer.classList.add("hidden");
|
|
|
|
gameContainer.classList.remove("hidden");
|
|
|
|
updateInventoryDisplay();
|
|
startGame();
|
|
});
|
|
|
|
// ------Open-Crafting------
|
|
openCraftingBtn.addEventListener("click", () => {
|
|
playSound(sounds.uiClick);
|
|
openCraftingMenu();
|
|
});
|
|
|
|
// ------Close-Crafting------
|
|
closeCraftingBtn.addEventListener("click", (event) => {
|
|
if (event.target === closeCraftingBtn) {
|
|
playSound(sounds.uiClick);
|
|
craftingModal.classList.add("hidden");
|
|
}
|
|
});
|
|
|
|
// ------Open-Inventar------
|
|
if (openInventoryBtn) {
|
|
openInventoryBtn.addEventListener('click', () => {
|
|
toggleInventory();
|
|
});
|
|
}
|
|
|
|
window.addEventListener('keydown', (event) => {
|
|
if (event.key.toLowerCase() === 'i') {
|
|
toggleInventory();
|
|
}
|
|
});
|
|
|
|
// ------Close-Inventar-------
|
|
if (closeInventoryBtn) {
|
|
closeInventoryBtn.addEventListener('click', () => {
|
|
if (inventoryModal) inventoryModal.classList.add('hidden');
|
|
});
|
|
}
|
|
|
|
// ------Basebuilding Events------
|
|
if (openBasebuildingBtn) {
|
|
openBasebuildingBtn.addEventListener('click', () => {
|
|
openBasebuildingModal();
|
|
});
|
|
}
|
|
|
|
if (closeBasebuildingBtn) {
|
|
closeBasebuildingBtn.addEventListener('click', () => {
|
|
if (basebuildingModal) basebuildingModal.classList.add('hidden');
|
|
});
|
|
}
|
|
|
|
// ==================================================================
|
|
// Main Game Logic
|
|
// ==================================================================
|
|
|
|
landingPage.classList.remove("hidden");
|
|
|
|
let playerState = {
|
|
health: 100,
|
|
hunger: 100,
|
|
thirst: 100,
|
|
energy: 100,
|
|
inventory: [],
|
|
currentSceneId: "start_game",
|
|
sickness: null,
|
|
storyFlags: {},
|
|
baseBuilding: {
|
|
cabinSize: 'm',
|
|
placedItems: {}
|
|
}
|
|
};
|
|
|
|
// Basebuilding variables
|
|
let currentCabinSize = 'm';
|
|
let selectedBuildingItem = null;
|
|
|
|
function startGame() {
|
|
showStoryNode("start_game");
|
|
}
|
|
|
|
// -------Health, Hunger, Thirst Update-------
|
|
function updateStatsDisplay() {
|
|
healthFillBar.style.width = playerState.health + "%";
|
|
hungerFillBar.style.width = playerState.hunger + "%";
|
|
thirstFillBar.style.width = playerState.thirst + "%";
|
|
}
|
|
|
|
// ==================================================================
|
|
// Inventory Display
|
|
// ==================================================================
|
|
function updateInventoryDisplay() {
|
|
const inventoryItemsElement = document.getElementById("inventory-items");
|
|
|
|
if (inventoryItemsElement) inventoryItemsElement.innerHTML = "";
|
|
|
|
playerState.inventory.forEach((itemName) => {
|
|
const itemData = items[itemName];
|
|
if (!itemData) {
|
|
console.log(`Item "${itemName}" nicht gefunden!`);
|
|
return;
|
|
}
|
|
|
|
const itemElement = document.createElement("div");
|
|
itemElement.classList.add("inventory-item");
|
|
itemElement.addEventListener("click", () => useItem(itemName));
|
|
|
|
const itemImage = document.createElement("img");
|
|
itemImage.src = itemData.image;
|
|
|
|
const tooltipElement = document.createElement("div");
|
|
tooltipElement.classList.add("item-tooltip");
|
|
tooltipElement.innerHTML = `
|
|
<h4>${itemName}</h4>
|
|
<p>${itemData.description}</p>
|
|
`;
|
|
|
|
itemElement.addEventListener('mouseenter', (e) => {
|
|
positionTooltip(tooltipElement, itemElement);
|
|
});
|
|
|
|
itemElement.appendChild(itemImage);
|
|
itemElement.appendChild(tooltipElement);
|
|
if (inventoryItemsElement) inventoryItemsElement.appendChild(itemElement);
|
|
|
|
});
|
|
}
|
|
|
|
function toggleInventory() {
|
|
if (inventoryModal) {
|
|
inventoryModal.classList.toggle('hidden');
|
|
updateInventoryDisplay();
|
|
}
|
|
}
|
|
|
|
// ==================================================================
|
|
// Professional Tooltip Positioning System
|
|
// ==================================================================
|
|
function positionTooltip(tooltip, item) {
|
|
tooltip.style.top = '';
|
|
tooltip.style.bottom = '';
|
|
tooltip.style.left = '';
|
|
tooltip.style.right = '';
|
|
tooltip.style.transform = '';
|
|
tooltip.className = tooltip.className.replace(/tooltip-(top|bottom|left|right)/g, '');
|
|
|
|
tooltip.style.display = 'flex';
|
|
tooltip.style.visibility = 'hidden';
|
|
|
|
const tooltipRect = tooltip.getBoundingClientRect();
|
|
const itemRect = item.getBoundingClientRect();
|
|
|
|
|
|
const viewport = {
|
|
top: 0,
|
|
left: 0,
|
|
right: window.innerWidth,
|
|
bottom: window.innerHeight
|
|
};
|
|
|
|
|
|
const modalContent = item.closest('.modal-content');
|
|
const containerRect = modalContent ? modalContent.getBoundingClientRect() : viewport;
|
|
|
|
const margin = 16;
|
|
const arrowSize = 8;
|
|
|
|
|
|
const spaces = {
|
|
top: itemRect.top - containerRect.top,
|
|
bottom: containerRect.bottom - itemRect.bottom,
|
|
left: itemRect.left - containerRect.left,
|
|
right: containerRect.right - itemRect.right
|
|
};
|
|
|
|
|
|
let position = 'bottom';
|
|
let maxSpace = spaces.top;
|
|
|
|
if (spaces.bottom > maxSpace && spaces.bottom >= tooltipRect.height + margin + arrowSize) {
|
|
position = 'top';
|
|
maxSpace = spaces.bottom;
|
|
}
|
|
|
|
if (spaces.left > maxSpace && spaces.left >= tooltipRect.width + margin + arrowSize) {
|
|
position = 'right';
|
|
maxSpace = spaces.left;
|
|
}
|
|
|
|
if (spaces.right > maxSpace && spaces.right >= tooltipRect.width + margin + arrowSize) {
|
|
position = 'left';
|
|
maxSpace = spaces.right;
|
|
}
|
|
|
|
|
|
tooltip.classList.add(`tooltip-${position}`);
|
|
|
|
switch (position) {
|
|
case 'top':
|
|
tooltip.style.top = `${itemRect.bottom + arrowSize}px`;
|
|
tooltip.style.left = `${Math.max(containerRect.left + margin,
|
|
Math.min(itemRect.left + itemRect.width / 2 - tooltipRect.width / 2,
|
|
containerRect.right - tooltipRect.width - margin))}px`;
|
|
break;
|
|
|
|
case 'bottom':
|
|
tooltip.style.top = `${itemRect.top - tooltipRect.height - arrowSize}px`;
|
|
tooltip.style.left = `${Math.max(containerRect.left + margin,
|
|
Math.min(itemRect.left + itemRect.width / 2 - tooltipRect.width / 2,
|
|
containerRect.right - tooltipRect.width - margin))}px`;
|
|
break;
|
|
|
|
case 'left':
|
|
tooltip.style.top = `${Math.max(containerRect.top + margin,
|
|
Math.min(itemRect.top + itemRect.height / 2 - tooltipRect.height / 2,
|
|
containerRect.bottom - tooltipRect.height - margin))}px`;
|
|
tooltip.style.left = `${itemRect.right + arrowSize}px`;
|
|
break;
|
|
|
|
case 'right':
|
|
tooltip.style.top = `${Math.max(containerRect.top + margin,
|
|
Math.min(itemRect.top + itemRect.height / 2 - tooltipRect.height / 2,
|
|
containerRect.bottom - tooltipRect.height - margin))}px`;
|
|
tooltip.style.left = `${itemRect.left - tooltipRect.width - arrowSize}px`;
|
|
break;
|
|
}
|
|
|
|
|
|
const finalRect = tooltip.getBoundingClientRect();
|
|
|
|
if (finalRect.left < viewport.left + margin) {
|
|
tooltip.style.left = `${viewport.left + margin}px`;
|
|
}
|
|
if (finalRect.right > viewport.right - margin) {
|
|
tooltip.style.left = `${viewport.right - tooltipRect.width - margin}px`;
|
|
}
|
|
if (finalRect.top < viewport.top + margin) {
|
|
tooltip.style.top = `${viewport.top + margin}px`;
|
|
}
|
|
if (finalRect.bottom > viewport.bottom - margin) {
|
|
tooltip.style.top = `${viewport.bottom - tooltipRect.height - margin}px`;
|
|
}
|
|
|
|
tooltip.style.visibility = 'visible';
|
|
}
|
|
|
|
// ==================================================================
|
|
// Story Flags System
|
|
// ==================================================================
|
|
function setStoryFlag(flagName, value = true) {
|
|
if (!playerState.storyFlags) {
|
|
playerState.storyFlags = {};
|
|
}
|
|
playerState.storyFlags[flagName] = value;
|
|
saveGame();
|
|
}
|
|
|
|
function hasStoryFlag(flagName) {
|
|
return playerState.storyFlags && playerState.storyFlags[flagName] === true;
|
|
}
|
|
|
|
// ==================================================================
|
|
// Base Building System
|
|
// ==================================================================
|
|
function openBasebuildingModal() {
|
|
if (basebuildingModal) {
|
|
basebuildingModal.classList.remove('hidden');
|
|
initializeBasebuilding();
|
|
}
|
|
}
|
|
|
|
function initializeBasebuilding() {
|
|
const sizeButtons = document.querySelectorAll('.size-btn');
|
|
sizeButtons.forEach(btn => {
|
|
btn.addEventListener('click', () => changeCabinSize(btn.dataset.size));
|
|
});
|
|
|
|
const buildingItems = document.querySelectorAll('.building-item');
|
|
buildingItems.forEach(btn => {
|
|
btn.addEventListener('click', () => selectBuildingItem(btn.dataset.item));
|
|
});
|
|
|
|
currentCabinSize = playerState.baseBuilding.cabinSize || 'm';
|
|
updateCabinDisplay();
|
|
}
|
|
|
|
function changeCabinSize(size) {
|
|
currentCabinSize = size;
|
|
playerState.baseBuilding.cabinSize = size;
|
|
|
|
|
|
document.querySelectorAll('.size-btn').forEach(btn => btn.classList.remove('active'));
|
|
document.querySelector(`[data-size="${size}"]`).classList.add('active');
|
|
|
|
updateCabinDisplay();
|
|
saveGame();
|
|
}
|
|
|
|
function selectBuildingItem(item) {
|
|
selectedBuildingItem = item;
|
|
|
|
document.querySelectorAll('.building-item').forEach(btn => btn.classList.remove('selected'));
|
|
document.querySelector(`[data-item="${item}"]`).classList.add('selected');
|
|
}
|
|
|
|
function updateCabinDisplay() {
|
|
const cabinGrid = document.getElementById('cabin-grid');
|
|
if (!cabinGrid) return;
|
|
cabinGrid.className = `cabin-grid cabin-${currentCabinSize}`;
|
|
|
|
|
|
cabinGrid.innerHTML = '';
|
|
|
|
|
|
const dimensions = {
|
|
'm': { cols: 6, rows: 4 },
|
|
'l': { cols: 8, rows: 6 },
|
|
'xl': { cols: 10, rows: 8 }
|
|
};
|
|
|
|
const { cols, rows } = dimensions[currentCabinSize];
|
|
|
|
|
|
for (let row = 0; row < rows; row++) {
|
|
for (let col = 0; col < cols; col++) {
|
|
const cell = document.createElement('div');
|
|
cell.className = 'cabin-cell';
|
|
cell.dataset.row = row;
|
|
cell.dataset.col = col;
|
|
|
|
const cellKey = `${row}-${col}`;
|
|
const placedItem = playerState.baseBuilding.placedItems[cellKey];
|
|
|
|
if (placedItem) {
|
|
cell.classList.add('occupied');
|
|
cell.textContent = getItemEmoji(placedItem);
|
|
}
|
|
|
|
cell.addEventListener('click', () => placeBuildingItem(row, col));
|
|
cabinGrid.appendChild(cell);
|
|
}
|
|
}
|
|
}
|
|
|
|
function placeBuildingItem(row, col) {
|
|
if (!selectedBuildingItem) {
|
|
alert('Wähle zuerst ein Objekt zum Platzieren aus!');
|
|
return;
|
|
}
|
|
|
|
const cellKey = `${row}-${col}`;
|
|
|
|
|
|
if (playerState.baseBuilding.placedItems[cellKey]) {
|
|
|
|
delete playerState.baseBuilding.placedItems[cellKey];
|
|
} else {
|
|
|
|
playerState.baseBuilding.placedItems[cellKey] = selectedBuildingItem;
|
|
}
|
|
|
|
updateCabinDisplay();
|
|
saveGame();
|
|
}
|
|
|
|
function getItemEmoji(item) {
|
|
const emojis = {
|
|
'bed': '🛏️',
|
|
'table': '🪑',
|
|
'chest': '📦',
|
|
'fireplace': '🔥',
|
|
'workbench': '🔨'
|
|
};
|
|
return emojis[item] || '❓';
|
|
}
|
|
|
|
// ==================================================================
|
|
// Crafting
|
|
// ==================================================================
|
|
|
|
function craftItem(recipeName) {
|
|
const recipe = recipes[recipeName];
|
|
if (!recipe) {
|
|
console.log(`Rezept "${recipeName}" nicht gefunden`);
|
|
return;
|
|
}
|
|
|
|
recipe.ingredients.forEach((ingredient) => {
|
|
const itemIndex = playerState.inventory.indexOf(ingredient);
|
|
if (itemIndex > -1) {
|
|
playerState.inventory.splice(itemIndex, 1);
|
|
}
|
|
});
|
|
|
|
|
|
const productName = recipe.result || recipe.product;
|
|
if (!productName) {
|
|
console.log(`Rezept "${recipeName}" hat kein result/product Feld`);
|
|
return;
|
|
}
|
|
|
|
playerState.inventory.push(productName);
|
|
playSound(sounds.craftSuccess);
|
|
updateInventoryDisplay();
|
|
saveGame();
|
|
}
|
|
|
|
function openCraftingMenu() {
|
|
const craftingOptionsContainer = document.getElementById('crafting-options');
|
|
craftingOptionsContainer.innerHTML = '';
|
|
|
|
let canCraftSomething = false;
|
|
|
|
Object.keys(recipes).forEach(recipeName => {
|
|
const recipe = recipes[recipeName];
|
|
const canCraft = recipe.ingredients.every(ingredient => playerState.inventory.includes(ingredient));
|
|
|
|
if (canCraft) {
|
|
canCraftSomething = true;
|
|
const button = document.createElement("button");
|
|
const productName = recipe.result || recipe.product || "Unbekanntes Produkt";
|
|
button.innerText = `Herstellen: ${productName}`;
|
|
button.classList.add("btn", "craft-btn");
|
|
button.addEventListener("click", () => {
|
|
craftItem(recipeName);
|
|
openCraftingMenu();
|
|
});
|
|
craftingOptionsContainer.appendChild(button);
|
|
}
|
|
});
|
|
|
|
if (!canCraftSomething) {
|
|
craftingOptionsContainer.innerHTML = '<p>Du hast nicht die richtigen Materialien, um etwas herzustellen.</p>';
|
|
}
|
|
|
|
craftingModal.classList.remove('hidden');
|
|
|
|
updateInventoryDisplay();
|
|
}
|
|
|
|
// ==================================================================
|
|
// STORY NODE HANDLING
|
|
// ==================================================================
|
|
|
|
function showStoryNode(storyNodeId) {
|
|
if (storyNodeId === "restart") {
|
|
localStorage.removeItem("saveGameData");
|
|
return window.location.reload();
|
|
}
|
|
|
|
const storyNode = storyNodes.find((node) => node.id === storyNodeId);
|
|
|
|
if (!storyNode) {
|
|
console.error(`Story-Knoten mit ID "${storyNodeId}" nicht gefunden!`);
|
|
return;
|
|
}
|
|
|
|
if (storyNode.soundEffect) {
|
|
const soundKey = storyNode.soundEffect;
|
|
const soundPath = sounds[soundKey];
|
|
if (soundPath) {
|
|
playSound(soundPath);
|
|
}
|
|
}
|
|
|
|
if (storyNode.setState) {
|
|
if (typeof storyNode.setState === "function") {
|
|
playerState = storyNode.setState(playerState);
|
|
}
|
|
}
|
|
|
|
const bodyStyle = document.body.style;
|
|
bodyStyle.backgroundImage = `url('${storyNode.image}')`;
|
|
bodyStyle.backgroundSize = "cover";
|
|
bodyStyle.backgroundPosition = "center";
|
|
bodyStyle.backgroundAttachment = "fixed";
|
|
bodyStyle.backgroundRepeat = "no-repeat";
|
|
|
|
|
|
const storyText = typeof storyNode.text === 'function' ? storyNode.text(playerState) : storyNode.text;
|
|
storyTextElement.innerText = storyText;
|
|
|
|
updateStatsDisplay();
|
|
updateInventoryDisplay();
|
|
|
|
while (optionsButtonsElement.firstChild) {
|
|
optionsButtonsElement.removeChild(optionsButtonsElement.firstChild);
|
|
}
|
|
|
|
|
|
const options = typeof storyNode.options === 'function' ? storyNode.options(playerState) : storyNode.options;
|
|
|
|
options.forEach((option) => {
|
|
if (option.requiredState && !option.requiredState(playerState)) {
|
|
return;
|
|
}
|
|
const button = document.createElement("button");
|
|
button.innerText = option.text;
|
|
button.classList.add("btn");
|
|
button.addEventListener("click", () => selectOption(option));
|
|
optionsButtonsElement.appendChild(button);
|
|
});
|
|
}
|
|
|
|
// ==================================================================
|
|
// Use Item Logic
|
|
// ==================================================================
|
|
|
|
function useItem(itemName) {
|
|
const item = items[itemName];
|
|
if (!item) return;
|
|
if (item.sound && sounds[item.sound]) {
|
|
playSound(sounds[item.sound]);
|
|
}
|
|
if (item.effect) {
|
|
playerState.health += item.effect.health || 0;
|
|
playerState.hunger += item.effect.hunger || 0;
|
|
playerState.thirst += item.effect.thirst || 0;
|
|
playerState.energy += item.effect.energy || 0;
|
|
|
|
playerState.health = Math.max(0, Math.min(100, playerState.health));
|
|
playerState.hunger = Math.max(0, Math.min(100, playerState.hunger));
|
|
playerState.thirst = Math.max(0, Math.min(100, playerState.thirst));
|
|
playerState.energy = Math.max(0, Math.min(100, playerState.energy));
|
|
}
|
|
|
|
if (item.consumable) {
|
|
const itemIndex = playerState.inventory.indexOf(itemName);
|
|
if (itemIndex > -1) {
|
|
playerState.inventory.splice(itemIndex, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
updateStatsDisplay();
|
|
updateInventoryDisplay();
|
|
|
|
// ==================================================================
|
|
// Savegame Handling & Loadgame Logic
|
|
// ==================================================================
|
|
function saveGame() {
|
|
const gameStateJson = JSON.stringify(playerState);
|
|
localStorage.setItem("saveGameData", gameStateJson);
|
|
console.log("Spiel gespeichert:", playerState);
|
|
}
|
|
|
|
function loadGame() {
|
|
const savedGameJson = localStorage.getItem("saveGameData");
|
|
if (savedGameJson) {
|
|
const savedGameState = JSON.parse(savedGameJson);
|
|
playerState = savedGameState;
|
|
console.log("Spiel geladen:", playerState);
|
|
} else {
|
|
console.log("Kein gespeichertes Spiel gefunden.");
|
|
}
|
|
updateInventoryDisplay();
|
|
}
|
|
|
|
// ==================================================================
|
|
// Option Selection Logic
|
|
// ==================================================================
|
|
function selectOption(option) {
|
|
const allButtons = optionsButtonsElement.querySelectorAll('.btn');
|
|
allButtons.forEach(button => {
|
|
button.disabled = true;
|
|
});
|
|
|
|
|
|
storyTextElement.classList.add('fading-out');
|
|
|
|
|
|
if (option.soundEffect) {
|
|
const soundKey = option.soundEffect;
|
|
const soundPath = sounds[soundKey];
|
|
if (soundPath) {
|
|
playSound(soundPath);
|
|
}
|
|
} else {
|
|
// playSound(sounds.uiClick);
|
|
}
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
storyTextElement.classList.remove('fading-out');
|
|
|
|
if (option.setState) {
|
|
if (typeof option.setState === "function") {
|
|
playerState = option.setState(playerState);
|
|
} else {
|
|
playerState.health += option.setState.health || 0;
|
|
playerState.hunger += option.setState.hunger || 0;
|
|
playerState.thirst += option.setState.thirst || 0;
|
|
|
|
playerState.health = Math.max(0, Math.min(100, playerState.health));
|
|
playerState.hunger = Math.max(0, Math.min(100, playerState.hunger));
|
|
playerState.thirst = Math.max(0, Math.min(100, playerState.thirst));
|
|
}
|
|
}
|
|
|
|
|
|
updateStatsDisplay();
|
|
updateInventoryDisplay();
|
|
|
|
|
|
const nextStoryNodeId = option.nextText;
|
|
if (nextStoryNodeId) {
|
|
playerState.currentSceneId = nextStoryNodeId;
|
|
}
|
|
saveGame();
|
|
|
|
if (nextStoryNodeId) {
|
|
showStoryNode(nextStoryNodeId);
|
|
}
|
|
|
|
}, 800);
|
|
}
|
|
|
|
function playSound(soundFile) {
|
|
new Audio(soundFile).play();
|
|
}
|