diff --git a/languages/de.json b/languages/de.json index 08391f4..15dc5b6 100644 --- a/languages/de.json +++ b/languages/de.json @@ -19,14 +19,34 @@ "ShowCommunityHint": "Sichtbarkeit der Charaktergemeinschaft.", "Choices": { "CharTop": "Charakter-Name Oben (Spieler Unten)", + "PlayerTop": "Spieler-Name Oben (Charakter Unten)", + "NoPlayer": "Spieler-Name ausblenden", "MenuLabel": "Stream-Overlay", - "PlayerNameDisplay": "Spielernamen-Anzeige" + "PlayerNameDisplay": "Spielernamen-Anzeige", + "Standard": "Standard (Breitbild)", + "Vertical": "Vertikal (Sammelkarte)", + "RefFade": "Ausblenden (Fade)", + "RefSlide": "Gleiten (Slide)", + "RefZoom": "Zoomen (Zoom)", + "RefCycle": "Zyklus (In Rotation)", + "RefStatic": "Statisch (Immer sichtbar)", + "RefHidden": "Versteckt (Im Karussell)" }, "PlayerNameDisplayHint": "Wo der Spielername relativ zum Charakternamen angezeigt werden soll.", "HideFearLabel": "Fear-Label verbergen", "HideFearLabelHint": "Verbirgt die Textbeschriftung 'FEAR' neben den Fear-Tokens.", "ShowResourceLabels": "Ressourcen-Bezeichnungen anzeigen", - "ShowResourceLabelsHint": "Text-Bezeichnungen (HP, Stress, Hoffnung) neben Icons anzeigen." + "ShowResourceLabelsHint": "Text-Bezeichnungen (HP, Stress, Hoffnung) neben Icons anzeigen.", + "CardLayout": "Karten-Layout Modus", + "CardLayoutHint": "Wähle zwischen der Standard-Breitbild-Karte oder einem vertikalen Sammelkarten-Layout.", + "CarouselEnabled": "Karussell-Modus aktivieren", + "CarouselEnabledHint": "Wechsle automatisch nacheinander durch Spieler.", + "CarouselSpeed": "Karussell-Geschwindigkeit (s)", + "CarouselSpeedHint": "Sekunden, die jede Karte angezeigt wird, bevor gewechselt wird.", + "CarouselEffect": "Übergangseffekt", + "CarouselEffectHint": "Animationseffekt beim Wechseln der Karten.", + "CarouselGMMode": "GM Karussell-Verhalten", + "CarouselGMModeHint": "Wie der GM im Karussell behandelt werden soll." }, "OpenStream": "Stream-Ansicht öffnen", "ModeNumeric": "Numerisch (3/6)", diff --git a/languages/en.json b/languages/en.json index cb63cc1..f0c4367 100644 --- a/languages/en.json +++ b/languages/en.json @@ -24,7 +24,15 @@ "Choices": { "CharTop": "Character Name Top (Player Bottom)", "PlayerTop": "Player Name Top (Character Bottom)", - "NoPlayer": "Hide Player Name" + "NoPlayer": "Hide Player Name", + "Standard": "Standard (Horizontal Card)", + "Vertical": "Vertical (Trading Card)", + "RefFade": "Fade", + "RefSlide": "Slide", + "RefZoom": "Zoom", + "RefCycle": "Cycle (In Rotation)", + "RefStatic": "Static (Always Visible)", + "RefHidden": "Hidden (In Carousel)" }, "MenuLabel": "Stream Overlay", "PlayerNameDisplay": "Player Name Display", @@ -32,7 +40,21 @@ "HideFearLabel": "Hide Fear Label", "HideFearLabelHint": "Hide the text label 'FEAR' next to the fear tokens.", "ShowResourceLabels": "Show Resource Labels", - "ShowResourceLabelsHint": "Show text labels (HP, Stress, Hope) next to icons." + "ShowResourceLabelsHint": "Show text labels (HP, Stress, Hope) next to icons.", + "AutoExpandChat": "Auto-Expand Chat Messages", + "AutoExpandChatHint": "Automatically expand all chat messages to show full content (rolls, descriptions) without needing to click.", + "HideChatActions": "Hide Chat Action Buttons", + "HideChatActionsHint": "Hides buttons like 'Apply Damage', 'Place Template', or other interactive elements from chat cards to keep the view clean.", + "CardLayout": "Card Layout Mode", + "CardLayoutHint": "Choose between the standard wide card or a vertical trading-card style.", + "CarouselEnabled": "Enable Carousel Mode", + "CarouselEnabledHint": "Cycle through players one by one automatically.", + "CarouselSpeed": "Carousel Speed (s)", + "CarouselSpeedHint": "Seconds to show each player card before switching.", + "CarouselEffect": "Transition Effect", + "CarouselEffectHint": "Animation effect when switching cards.", + "CarouselGMMode": "GM Carousel Behavior", + "CarouselGMModeHint": "How the GM should constitute in the carousel." }, "OpenStream": "Open Stream View", "ModeNumeric": "Numeric (3/6)", diff --git a/module.json b/module.json index dc4241a..11b8a18 100644 --- a/module.json +++ b/module.json @@ -1,7 +1,7 @@ { "id": "dh-stream-overlay", "title": "Daggerheart Stream Overlay", - "version": "1.0.0", + "version": "2.0.0", "compatibility": { "minimum": "13", "verified": "13" @@ -44,7 +44,7 @@ ], "packFolders": [], "url": "https://github.com/cptn-cosmo/dh-stream-overlay", - "manifest": "https://github.com/cptn-cosmo/dh-stream-overlay/releases/latest/download/module.json", - "download": "https://github.com/cptn-cosmo/dh-stream-overlay/releases/download/1.0.0/dh-stream-overlay.zip", + "manifest": "https://git.geeks.gay/cosmo/dh-stream-overlay/raw/branch/main/module.json", + "download": "https://git.geeks.gay/cosmo/dh-stream-overlay/releases/download/2.0.0/dh-stream-overlay.zip", "description": "A stream overlay module for Daggerheart that displays chat and a linked party actor sheet." } \ No newline at end of file diff --git a/scripts/module.js b/scripts/module.js index 07db141..96c0080 100644 --- a/scripts/module.js +++ b/scripts/module.js @@ -191,7 +191,149 @@ Hooks.once("init", () => { scope: "world", config: false, type: Boolean, default: true }); + game.settings.register("dh-stream-overlay", "autoExpandChat", { + name: "DH_STREAM_OVERLAY.Settings.AutoExpandChat", + hint: "DH_STREAM_OVERLAY.Settings.AutoExpandChatHint", + scope: "world", + config: true, + type: Boolean, + default: true, + onChange: () => { if (document.body.classList.contains("stream")) location.reload(); } + }); + + game.settings.register("dh-stream-overlay", "hideChatActions", { + name: "DH_STREAM_OVERLAY.Settings.HideChatActions", + hint: "DH_STREAM_OVERLAY.Settings.HideChatActionsHint", + scope: "world", + config: true, + type: Boolean, + default: true, + onChange: () => { if (document.body.classList.contains("stream")) location.reload(); } + }); + + + game.settings.register("dh-stream-overlay", "cardLayout", { + name: "DH_STREAM_OVERLAY.Settings.CardLayout", + hint: "DH_STREAM_OVERLAY.Settings.CardLayoutHint", + scope: "world", + config: true, + type: String, + choices: { + "standard": "DH_STREAM_OVERLAY.Settings.Choices.Standard", + "vertical": "DH_STREAM_OVERLAY.Settings.Choices.Vertical" + }, + default: "standard", + onChange: () => { if (document.body.classList.contains("stream")) location.reload(); } + }); + + + game.settings.register("dh-stream-overlay", "carouselEnabled", { + name: "DH_STREAM_OVERLAY.Settings.CarouselEnabled", + hint: "DH_STREAM_OVERLAY.Settings.CarouselEnabledHint", + scope: "world", + config: true, + type: Boolean, + default: false, + onChange: () => { if (document.body.classList.contains("stream")) location.reload(); } + }); + + game.settings.register("dh-stream-overlay", "carouselSpeed", { + name: "DH_STREAM_OVERLAY.Settings.CarouselSpeed", + hint: "DH_STREAM_OVERLAY.Settings.CarouselSpeedHint", + scope: "world", + config: true, + type: Number, + default: 5, + range: { min: 2, max: 60, step: 1 }, + onChange: () => { if (document.body.classList.contains("stream")) location.reload(); } + }); + + game.settings.register("dh-stream-overlay", "carouselEffect", { + name: "DH_STREAM_OVERLAY.Settings.CarouselEffect", + hint: "DH_STREAM_OVERLAY.Settings.CarouselEffectHint", + scope: "world", + config: true, + type: String, + choices: { + "fade": "DH_STREAM_OVERLAY.Settings.Choices.RefFade", + "slide": "DH_STREAM_OVERLAY.Settings.Choices.RefSlide", + "zoom": "DH_STREAM_OVERLAY.Settings.Choices.RefZoom" + }, + default: "fade", + onChange: () => { if (document.body.classList.contains("stream")) location.reload(); } + }); + + game.settings.register("dh-stream-overlay", "carouselGMMode", { + name: "DH_STREAM_OVERLAY.Settings.CarouselGMMode", + hint: "DH_STREAM_OVERLAY.Settings.CarouselGMModeHint", + scope: "world", + config: true, + type: String, + choices: { + "cycle": "DH_STREAM_OVERLAY.Settings.Choices.RefCycle", + "static": "DH_STREAM_OVERLAY.Settings.Choices.RefStatic", + "hidden": "DH_STREAM_OVERLAY.Settings.Choices.RefHidden" + }, + default: "cycle", + onChange: () => { if (document.body.classList.contains("stream")) location.reload(); } + }); + }); + +// ============================================================================= +// CAROUSEL LOGIC +// ============================================================================= +let carouselIndex = 0; +let carouselTimer = null; + +function startCarousel() { + if (carouselTimer) clearInterval(carouselTimer); + const speed = game.settings.get("dh-stream-overlay", "carouselSpeed") || 5; + carouselTimer = setInterval(() => { + cycleCarousel(); + }, speed * 1000); +} + +function stopCarousel() { + if (carouselTimer) { + clearInterval(carouselTimer); + carouselTimer = null; + } +} + +function cycleCarousel() { + const container = document.querySelector(".dh-party-grid.carousel-mode"); + if (!container) return; + + const cards = container.querySelectorAll(".dh-party-card"); + if (cards.length === 0) return; + + // Increment + carouselIndex++; + if (carouselIndex >= cards.length) carouselIndex = 0; + + updateCarouselClasses(container); +} + +function updateCarouselClasses(container) { + if (!container) return; + const cards = container.querySelectorAll(".dh-party-card"); + + // Safety: Ensure index is valid + if (carouselIndex >= cards.length) carouselIndex = 0; + + cards.forEach((card, idx) => { + // Reset classes + card.classList.remove("active-slide", "exit-slide"); + + if (idx === carouselIndex) { + card.classList.add("active-slide"); + } else { + // Optional: Mark previous slide for exit animation if needed + // For simple fade, just lacking 'active-slide' hides it + } + }); +} // ... // ... inside renderPartyOverlay function ... @@ -353,24 +495,45 @@ function renderPartyOverlay(container) { const gms = game.users.filter(u => u.isGM); if (players.length === 0 && gms.length === 0) { - container.innerHTML = `