This commit is contained in:
michi 2025-09-05 10:50:28 +02:00
parent e934e234b5
commit b740ae4626
3 changed files with 28 additions and 50 deletions

55
main.js
View File

@ -206,7 +206,6 @@ function updateInventoryDisplay() {
<p>${itemData.description}</p> <p>${itemData.description}</p>
`; `;
// Add hover events for dynamic tooltip positioning
itemElement.addEventListener('mouseenter', (e) => { itemElement.addEventListener('mouseenter', (e) => {
positionTooltip(tooltipElement, itemElement); positionTooltip(tooltipElement, itemElement);
}); });
@ -229,7 +228,6 @@ function toggleInventory() {
// Professional Tooltip Positioning System // Professional Tooltip Positioning System
// ================================================================== // ==================================================================
function positionTooltip(tooltip, item) { function positionTooltip(tooltip, item) {
// Reset positioning and classes
tooltip.style.top = ''; tooltip.style.top = '';
tooltip.style.bottom = ''; tooltip.style.bottom = '';
tooltip.style.left = ''; tooltip.style.left = '';
@ -237,15 +235,13 @@ function positionTooltip(tooltip, item) {
tooltip.style.transform = ''; tooltip.style.transform = '';
tooltip.className = tooltip.className.replace(/tooltip-(top|bottom|left|right)/g, ''); tooltip.className = tooltip.className.replace(/tooltip-(top|bottom|left|right)/g, '');
// Show tooltip temporarily to measure dimensions
tooltip.style.display = 'flex'; tooltip.style.display = 'flex';
tooltip.style.visibility = 'hidden'; tooltip.style.visibility = 'hidden';
// Get actual dimensions
const tooltipRect = tooltip.getBoundingClientRect(); const tooltipRect = tooltip.getBoundingClientRect();
const itemRect = item.getBoundingClientRect(); const itemRect = item.getBoundingClientRect();
// Get viewport boundaries
const viewport = { const viewport = {
top: 0, top: 0,
left: 0, left: 0,
@ -253,14 +249,14 @@ function positionTooltip(tooltip, item) {
bottom: window.innerHeight bottom: window.innerHeight
}; };
// Check if we're in a modal
const modalContent = item.closest('.modal-content'); const modalContent = item.closest('.modal-content');
const containerRect = modalContent ? modalContent.getBoundingClientRect() : viewport; const containerRect = modalContent ? modalContent.getBoundingClientRect() : viewport;
const margin = 16; const margin = 16;
const arrowSize = 8; const arrowSize = 8;
// Calculate available space in each direction
const spaces = { const spaces = {
top: itemRect.top - containerRect.top, top: itemRect.top - containerRect.top,
bottom: containerRect.bottom - itemRect.bottom, bottom: containerRect.bottom - itemRect.bottom,
@ -268,8 +264,8 @@ function positionTooltip(tooltip, item) {
right: containerRect.right - itemRect.right right: containerRect.right - itemRect.right
}; };
// Determine best position based on available space
let position = 'bottom'; // default: show above item let position = 'bottom';
let maxSpace = spaces.top; let maxSpace = spaces.top;
if (spaces.bottom > maxSpace && spaces.bottom >= tooltipRect.height + margin + arrowSize) { if (spaces.bottom > maxSpace && spaces.bottom >= tooltipRect.height + margin + arrowSize) {
@ -287,7 +283,7 @@ function positionTooltip(tooltip, item) {
maxSpace = spaces.right; maxSpace = spaces.right;
} }
// Apply positioning based on determined position
tooltip.classList.add(`tooltip-${position}`); tooltip.classList.add(`tooltip-${position}`);
switch (position) { switch (position) {
@ -320,7 +316,7 @@ function positionTooltip(tooltip, item) {
break; break;
} }
// Ensure tooltip stays within viewport bounds
const finalRect = tooltip.getBoundingClientRect(); const finalRect = tooltip.getBoundingClientRect();
if (finalRect.left < viewport.left + margin) { if (finalRect.left < viewport.left + margin) {
@ -336,7 +332,6 @@ function positionTooltip(tooltip, item) {
tooltip.style.top = `${viewport.bottom - tooltipRect.height - margin}px`; tooltip.style.top = `${viewport.bottom - tooltipRect.height - margin}px`;
} }
// Make tooltip visible
tooltip.style.visibility = 'visible'; tooltip.style.visibility = 'visible';
} }
@ -366,19 +361,16 @@ function openBasebuildingModal() {
} }
function initializeBasebuilding() { function initializeBasebuilding() {
// Initialize cabin size buttons
const sizeButtons = document.querySelectorAll('.size-btn'); const sizeButtons = document.querySelectorAll('.size-btn');
sizeButtons.forEach(btn => { sizeButtons.forEach(btn => {
btn.addEventListener('click', () => changeCabinSize(btn.dataset.size)); btn.addEventListener('click', () => changeCabinSize(btn.dataset.size));
}); });
// Initialize building item buttons
const buildingItems = document.querySelectorAll('.building-item'); const buildingItems = document.querySelectorAll('.building-item');
buildingItems.forEach(btn => { buildingItems.forEach(btn => {
btn.addEventListener('click', () => selectBuildingItem(btn.dataset.item)); btn.addEventListener('click', () => selectBuildingItem(btn.dataset.item));
}); });
// Set current cabin size
currentCabinSize = playerState.baseBuilding.cabinSize || 'm'; currentCabinSize = playerState.baseBuilding.cabinSize || 'm';
updateCabinDisplay(); updateCabinDisplay();
} }
@ -387,7 +379,7 @@ function changeCabinSize(size) {
currentCabinSize = size; currentCabinSize = size;
playerState.baseBuilding.cabinSize = size; playerState.baseBuilding.cabinSize = size;
// Update active button
document.querySelectorAll('.size-btn').forEach(btn => btn.classList.remove('active')); document.querySelectorAll('.size-btn').forEach(btn => btn.classList.remove('active'));
document.querySelector(`[data-size="${size}"]`).classList.add('active'); document.querySelector(`[data-size="${size}"]`).classList.add('active');
@ -397,8 +389,7 @@ function changeCabinSize(size) {
function selectBuildingItem(item) { function selectBuildingItem(item) {
selectedBuildingItem = item; selectedBuildingItem = item;
// Update selected button
document.querySelectorAll('.building-item').forEach(btn => btn.classList.remove('selected')); document.querySelectorAll('.building-item').forEach(btn => btn.classList.remove('selected'));
document.querySelector(`[data-item="${item}"]`).classList.add('selected'); document.querySelector(`[data-item="${item}"]`).classList.add('selected');
} }
@ -406,14 +397,12 @@ function selectBuildingItem(item) {
function updateCabinDisplay() { function updateCabinDisplay() {
const cabinGrid = document.getElementById('cabin-grid'); const cabinGrid = document.getElementById('cabin-grid');
if (!cabinGrid) return; if (!cabinGrid) return;
// Update grid class
cabinGrid.className = `cabin-grid cabin-${currentCabinSize}`; cabinGrid.className = `cabin-grid cabin-${currentCabinSize}`;
// Clear existing cells
cabinGrid.innerHTML = ''; cabinGrid.innerHTML = '';
// Get grid dimensions
const dimensions = { const dimensions = {
'm': { cols: 6, rows: 4 }, 'm': { cols: 6, rows: 4 },
'l': { cols: 8, rows: 6 }, 'l': { cols: 8, rows: 6 },
@ -422,7 +411,7 @@ function updateCabinDisplay() {
const { cols, rows } = dimensions[currentCabinSize]; const { cols, rows } = dimensions[currentCabinSize];
// Create cells
for (let row = 0; row < rows; row++) { for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) { for (let col = 0; col < cols; col++) {
const cell = document.createElement('div'); const cell = document.createElement('div');
@ -452,12 +441,12 @@ function placeBuildingItem(row, col) {
const cellKey = `${row}-${col}`; const cellKey = `${row}-${col}`;
// Check if cell is already occupied
if (playerState.baseBuilding.placedItems[cellKey]) { if (playerState.baseBuilding.placedItems[cellKey]) {
// Remove item if clicking on occupied cell
delete playerState.baseBuilding.placedItems[cellKey]; delete playerState.baseBuilding.placedItems[cellKey];
} else { } else {
// Place new item
playerState.baseBuilding.placedItems[cellKey] = selectedBuildingItem; playerState.baseBuilding.placedItems[cellKey] = selectedBuildingItem;
} }
@ -578,7 +567,7 @@ function showStoryNode(storyNodeId) {
bodyStyle.backgroundAttachment = "fixed"; bodyStyle.backgroundAttachment = "fixed";
bodyStyle.backgroundRepeat = "no-repeat"; bodyStyle.backgroundRepeat = "no-repeat";
// Display story text (support for dynamic text functions)
const storyText = typeof storyNode.text === 'function' ? storyNode.text(playerState) : storyNode.text; const storyText = typeof storyNode.text === 'function' ? storyNode.text(playerState) : storyNode.text;
storyTextElement.innerText = storyText; storyTextElement.innerText = storyText;
@ -589,7 +578,7 @@ function showStoryNode(storyNodeId) {
optionsButtonsElement.removeChild(optionsButtonsElement.firstChild); optionsButtonsElement.removeChild(optionsButtonsElement.firstChild);
} }
// Clear and populate options (support for dynamic options functions)
const options = typeof storyNode.options === 'function' ? storyNode.options(playerState) : storyNode.options; const options = typeof storyNode.options === 'function' ? storyNode.options(playerState) : storyNode.options;
options.forEach((option) => { options.forEach((option) => {
@ -700,23 +689,17 @@ function selectOption(option) {
} }
} }
// Anzeigen aktualisieren
updateStatsDisplay(); updateStatsDisplay();
updateInventoryDisplay(); updateInventoryDisplay();
// Fortschritt speichern
const nextStoryNodeId = option.nextText; const nextStoryNodeId = option.nextText;
if (nextStoryNodeId) { if (nextStoryNodeId) {
playerState.currentSceneId = nextStoryNodeId; playerState.currentSceneId = nextStoryNodeId;
} }
saveGame(); saveGame();
// Game-Over-Check
// if (checkGameOver()) {
// return;
// }
// Nächste Szene laden
if (nextStoryNodeId) { if (nextStoryNodeId) {
showStoryNode(nextStoryNodeId); showStoryNode(nextStoryNodeId);
} }

View File

@ -40,7 +40,6 @@ export default [
} }
]; ];
// Only show leg examination if not already examined
if (!playerState.storyFlags || !playerState.storyFlags.bein_examined) { if (!playerState.storyFlags || !playerState.storyFlags.bein_examined) {
baseOptions.unshift({ baseOptions.unshift({
text: "Mein Bein erneut ansehen.", text: "Mein Bein erneut ansehen.",
@ -83,7 +82,6 @@ export default [
options: [ options: [
{ {
text: "Wasser trinken.", text: "Wasser trinken.",
// Hier könntest du eine Zufalls-Chance auf Krankheit einbauen
setState: (currentState) => ({ ...currentState, thirst: 100 }), setState: (currentState) => ({ ...currentState, thirst: 100 }),
nextText: "bach_getrunken" nextText: "bach_getrunken"
}, },
@ -128,12 +126,11 @@ export default [
options: [ options: [
{ {
text: "Kämpfen!", text: "Kämpfen!",
// Kampf führt wahrscheinlich zu Schaden oder Tod
nextText: "kampf_stiller_1" nextText: "kampf_stiller_1"
}, },
{ {
text: "Wegrennen!", text: "Wegrennen!",
nextText: "absturzstelle_hub" // Du entkommst, aber hast gelernt, dass Schreien gefährlich ist nextText: "absturzstelle_hub"
} }
] ]
}, },
@ -196,7 +193,6 @@ export default [
image: "images/bein_verbunden.png", image: "images/bein_verbunden.png",
soundEffect: "verbandSfx", soundEffect: "verbandSfx",
setState: (currentState) => { setState: (currentState) => {
// Set flag that leg has been examined and treated
if (!currentState.storyFlags) currentState.storyFlags = {}; if (!currentState.storyFlags) currentState.storyFlags = {};
currentState.storyFlags.bein_examined = true; currentState.storyFlags.bein_examined = true;
return currentState; return currentState;
@ -381,7 +377,7 @@ export default [
options: [ options: [
{ {
text: "In den Frachtraum klettern und suchen.", text: "In den Frachtraum klettern und suchen.",
nextText: "frachtraum_suchen" // Nächster großer Bereich nextText: "frachtraum_suchen"
}, },
{ {
text: "Erstmal zurück.", text: "Erstmal zurück.",

View File

@ -307,7 +307,7 @@ body {
} }
/* Professional Tooltip System */
.item-tooltip { .item-tooltip {
display: none; display: none;
position: fixed; position: fixed;
@ -341,7 +341,6 @@ body {
} }
} }
/* Tooltip content layout */
.item-tooltip { .item-tooltip {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -370,7 +369,7 @@ body {
hyphens: auto; hyphens: auto;
} }
/* Tooltip arrow */
.item-tooltip::before { .item-tooltip::before {
content: ''; content: '';
position: absolute; position: absolute;
@ -408,7 +407,7 @@ body {
border-right-color: rgba(52, 152, 219, 0.3); border-right-color: rgba(52, 152, 219, 0.3);
} }
/* Modal content overflow handling */
.modal-content { .modal-content {
position: relative; position: relative;
overflow: visible; overflow: visible;
@ -418,7 +417,7 @@ body {
overflow: visible; overflow: visible;
} }
/* Hover states */
.inventory-item:hover .item-tooltip { .inventory-item:hover .item-tooltip {
display: flex; display: flex;
} }
@ -427,7 +426,7 @@ body {
display: flex; display: flex;
} }
/* Responsive adjustments */
@media (max-width: 768px) { @media (max-width: 768px) {
.item-tooltip { .item-tooltip {
min-width: 240px; min-width: 240px;
@ -475,7 +474,7 @@ body {
} }
/* Modal Base Styles */
.modal { .modal {
position: fixed; position: fixed;
z-index: 1000; z-index: 1000;
@ -570,7 +569,7 @@ body {
transform: none; transform: none;
} }
/* Base Building Styles */
.basebuilding-content { .basebuilding-content {
width: 800px; width: 800px;
max-width: 95%; max-width: 95%;