improvements
@@ -2,14 +2,36 @@
|
|||||||
|
|
||||||
<div class="game-over-overlay">
|
<div class="game-over-overlay">
|
||||||
<div class="game-over-card">
|
<div class="game-over-card">
|
||||||
<div class="game-over-title">Výsledky Hry 👑</div>
|
<div class="game-over-title">
|
||||||
|
@if (IsOlympicMode)
|
||||||
|
{
|
||||||
|
<span>🏆 OLYMPIJSKÝ ŠAMPIÓN 👑</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>Výsledky Hry 👑</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (IsOlympicMode && MatchWinner != null)
|
||||||
|
{
|
||||||
|
<div style="background: linear-gradient(135deg, rgba(245, 176, 65, 0.25), rgba(212, 172, 13, 0.15)); border: 2px solid var(--gold); border-radius: 14px; padding: 14px; margin-bottom: 18px; text-align: center;">
|
||||||
|
<div style="font-size: 2.2rem; margin-bottom: 4px;">🥇👑</div>
|
||||||
|
<div style="font-size: 1.35rem; font-weight: 900; color: var(--gold);">
|
||||||
|
@MatchWinner.Avatar @MatchWinner.Name
|
||||||
|
</div>
|
||||||
|
<div style="font-size: 0.9rem; color: #f1f5f9; margin-top: 4px;">
|
||||||
|
Prežil všetky kolá ako jediný hráč a zvíťazil v Olympijskom turnaji!
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="podium-list">
|
<div class="podium-list">
|
||||||
@foreach (var player in Players.OrderBy(p => p.FinishedPosition ?? 99))
|
@foreach (var player in Players.OrderBy(p => p.IsEliminated ? 1 : 0).ThenBy(p => p.FinishedPosition ?? 99))
|
||||||
{
|
{
|
||||||
<div class="podium-row @(player.FinishedPosition == 1 ? "winner" : "")">
|
<div class="podium-row @((MatchWinner != null && player == MatchWinner) || (!IsOlympicMode && player.FinishedPosition == 1) ? "winner" : "")">
|
||||||
<div class="podium-pos">
|
<div class="podium-pos">
|
||||||
@if (player.FinishedPosition == 1) { <span>🥇</span> }
|
@if ((MatchWinner != null && player == MatchWinner) || (!IsOlympicMode && player.FinishedPosition == 1)) { <span>🥇</span> }
|
||||||
else if (player.FinishedPosition == 2) { <span>🥈</span> }
|
else if (player.FinishedPosition == 2) { <span>🥈</span> }
|
||||||
else if (player.FinishedPosition == 3) { <span>🥉</span> }
|
else if (player.FinishedPosition == 3) { <span>🥉</span> }
|
||||||
else { <span>#@(player.FinishedPosition ?? 4)</span> }
|
else { <span>#@(player.FinishedPosition ?? 4)</span> }
|
||||||
@@ -22,8 +44,26 @@
|
|||||||
<span style="font-size: 0.75rem; opacity: 0.7;">(AI)</span>
|
<span style="font-size: 0.75rem; opacity: 0.7;">(AI)</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div style="font-weight: 800;">
|
||||||
@(player.FinishedPosition == 1 ? "Víťaz! 🎉" : $"{player.FinishedPosition}. miesto")
|
@if (IsOlympicMode)
|
||||||
|
{
|
||||||
|
if (player == MatchWinner)
|
||||||
|
{
|
||||||
|
<span style="color: var(--gold);">Šampión! 🏆</span>
|
||||||
|
}
|
||||||
|
else if (player.IsEliminated)
|
||||||
|
{
|
||||||
|
<span style="color: #ef4444;">Vyradený ☠️</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>@player.OlympicCardsCount kariet</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>@(player.FinishedPosition == 1 ? "Víťaz! 🎉" : $"{player.FinishedPosition}. miesto")</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@@ -42,6 +82,8 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter] public List<Player> Players { get; set; } = new();
|
[Parameter] public List<Player> Players { get; set; } = new();
|
||||||
|
[Parameter] public bool IsOlympicMode { get; set; } = false;
|
||||||
|
[Parameter] public Player? MatchWinner { get; set; }
|
||||||
[Parameter] public EventCallback OnPlayAgain { get; set; }
|
[Parameter] public EventCallback OnPlayAgain { get; set; }
|
||||||
[Parameter] public EventCallback OnBackToLobby { get; set; }
|
[Parameter] public EventCallback OnBackToLobby { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,15 +77,17 @@
|
|||||||
<input type="checkbox" @bind="Rules.FourOfAKindBurns" />
|
<input type="checkbox" @bind="Rules.FourOfAKindBurns" />
|
||||||
<span>Spálenie (4 rovnaké karty)</span>
|
<span>Spálenie (4 rovnaké karty)</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="rule-check-item">
|
<label class="rule-check-item" style="grid-column: 1 / -1; background: rgba(245, 176, 65, 0.12); padding: 8px 12px; border-radius: 10px; border: 1px solid rgba(245, 176, 65, 0.3);">
|
||||||
<input type="checkbox" @bind="Rules.PassAndPlayPrivacyScreen" />
|
<input type="checkbox" @bind="Rules.OlympicMode" />
|
||||||
<span>Pass & Play clona pre ľudí</span>
|
<span style="font-weight: 800; color: var(--gold);">🏅 Olympijský Faraón (Turnajový režim)</span>
|
||||||
|
<span style="font-size: 0.8rem; color: #94a3b8; margin-left: 6px;">— porazený má v ďalšom kole o 1 kartu menej</span>
|
||||||
</label>
|
</label>
|
||||||
<div style="display: flex; align-items: center; gap: 8px; font-size: 0.9rem;">
|
<div style="display: flex; align-items: center; gap: 8px; font-size: 0.9rem;">
|
||||||
<span>Kariet do ruky:</span>
|
<span>Počiatočný počet kariet:</span>
|
||||||
<select class="player-setup-select" style="width: auto; padding: 2px 8px;" @bind="Rules.InitialCardCount">
|
<select class="player-setup-select" style="width: auto; padding: 2px 8px;" @bind="Rules.InitialCardCount">
|
||||||
<option value="4">4 karty</option>
|
<option value="4">4 karty</option>
|
||||||
<option value="5">5 kariet</option>
|
<option value="5">5 kariet</option>
|
||||||
|
<option value="6">6 kariet</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,11 +105,23 @@
|
|||||||
<img src="assets/cards/original/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
|
<img src="assets/cards/original/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
|
||||||
</div>
|
</div>
|
||||||
<div class="deck-info">
|
<div class="deck-info">
|
||||||
<div class="deck-name">Tradičný Mariáš (Original)</div>
|
<div class="deck-name">Tradičný Mariáš 🎴</div>
|
||||||
<div class="deck-desc">Autentický dvojhlavý Tell vzor (Piatnik)</div>
|
<div class="deck-desc">Autentický dvojhlavý Tell vzor (Piatnik)</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="deck-option-card @(Rules.SelectedDeck == "janosik" ? "selected-deck" : "")"
|
||||||
|
@onclick='() => Rules.SelectedDeck = "janosik"'>
|
||||||
|
<div class="deck-preview-img-box">
|
||||||
|
<img src="assets/cards/janosik/Hearts_King.webp" class="deck-preview-thumb" alt="Zbojníci" />
|
||||||
|
<img src="assets/cards/janosik/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
|
||||||
|
</div>
|
||||||
|
<div class="deck-info">
|
||||||
|
<div class="deck-name">Zbojníci & Legendy 🪓</div>
|
||||||
|
<div class="deck-desc">Jánošík, Uhorčík, výšivky a tatranský folklór</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="deck-option-card @(Rules.SelectedDeck == "spongebob" ? "selected-deck" : "")"
|
<div class="deck-option-card @(Rules.SelectedDeck == "spongebob" ? "selected-deck" : "")"
|
||||||
@onclick='() => Rules.SelectedDeck = "spongebob"'>
|
@onclick='() => Rules.SelectedDeck = "spongebob"'>
|
||||||
<div class="deck-preview-img-box">
|
<div class="deck-preview-img-box">
|
||||||
@@ -116,7 +130,67 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="deck-info">
|
<div class="deck-info">
|
||||||
<div class="deck-name">SpongeBob Cartoon 🧽</div>
|
<div class="deck-name">SpongeBob Cartoon 🧽</div>
|
||||||
<div class="deck-desc">Bikini Bottom edícia (Krabby Patty & postavičky)</div>
|
<div class="deck-desc">Bikini Bottom edícia (postavičky a veľké symboly)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="deck-option-card @(Rules.SelectedDeck == "cyberpunk" ? "selected-deck" : "")"
|
||||||
|
@onclick='() => Rules.SelectedDeck = "cyberpunk"'>
|
||||||
|
<div class="deck-preview-img-box">
|
||||||
|
<img src="assets/cards/cyberpunk/Leaves_King.webp" class="deck-preview-thumb" alt="Cyberpunk 2077" />
|
||||||
|
<img src="assets/cards/cyberpunk/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
|
||||||
|
</div>
|
||||||
|
<div class="deck-info">
|
||||||
|
<div class="deck-name">Cyberpunk 2077 ⚡</div>
|
||||||
|
<div class="deck-desc">Neónový holografický štýl a kybernetickí hrdinovia</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="deck-option-card @(Rules.SelectedDeck == "fantasy" ? "selected-deck" : "")"
|
||||||
|
@onclick='() => Rules.SelectedDeck = "fantasy"'>
|
||||||
|
<div class="deck-preview-img-box">
|
||||||
|
<img src="assets/cards/fantasy/Acorns_OverKnave.webp" class="deck-preview-thumb" alt="Fantasy RPG" />
|
||||||
|
<img src="assets/cards/fantasy/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
|
||||||
|
</div>
|
||||||
|
<div class="deck-info">
|
||||||
|
<div class="deck-name">Fantasy RPG 🐉</div>
|
||||||
|
<div class="deck-desc">Dračí lordi, mágovia, runy a rytieri</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="deck-option-card @(Rules.SelectedDeck == "egypt" ? "selected-deck" : "")"
|
||||||
|
@onclick='() => Rules.SelectedDeck = "egypt"'>
|
||||||
|
<div class="deck-preview-img-box">
|
||||||
|
<img src="assets/cards/egypt/Bells_King.webp" class="deck-preview-thumb" alt="Staroveký Egypt" />
|
||||||
|
<img src="assets/cards/egypt/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
|
||||||
|
</div>
|
||||||
|
<div class="deck-info">
|
||||||
|
<div class="deck-name">Staroveký Egypt ⚔️</div>
|
||||||
|
<div class="deck-desc">Zlatý papyrus, Tutanchamón, Anubis a pyramídy</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="deck-option-card @(Rules.SelectedDeck == "pets" ? "selected-deck" : "")"
|
||||||
|
@onclick='() => Rules.SelectedDeck = "pets"'>
|
||||||
|
<div class="deck-preview-img-box">
|
||||||
|
<img src="assets/cards/pets/Hearts_OverKnave.webp" class="deck-preview-thumb" alt="Kráľovské zvieratká" />
|
||||||
|
<img src="assets/cards/pets/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
|
||||||
|
</div>
|
||||||
|
<div class="deck-info">
|
||||||
|
<div class="deck-name">Kráľovské Zvieratká 🐱</div>
|
||||||
|
<div class="deck-desc">Mačičky a psíkovia v kráľovských korunkách</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="deck-option-card @(Rules.SelectedDeck == "pixel" ? "selected-deck" : "")"
|
||||||
|
@onclick='() => Rules.SelectedDeck = "pixel"'>
|
||||||
|
<div class="deck-preview-img-box">
|
||||||
|
<img src="assets/cards/pixel/Leaves_Seven.webp" class="deck-preview-thumb" alt="Retro Pixel" />
|
||||||
|
<img src="assets/cards/pixel/Card_Back.webp" class="deck-preview-thumb-back" alt="Rub" />
|
||||||
|
</div>
|
||||||
|
<div class="deck-info">
|
||||||
|
<div class="deck-name">Retro 8-Bit Pixel 🕹️</div>
|
||||||
|
<div class="deck-desc">Nostalgický arkádový štýl klasických hier</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -88,9 +88,9 @@
|
|||||||
int total = Player.Hand.Count;
|
int total = Player.Hand.Count;
|
||||||
double mid = (total - 1) / 2.0;
|
double mid = (total - 1) / 2.0;
|
||||||
double offset = i - mid;
|
double offset = i - mid;
|
||||||
double angle = total > 1 ? offset * (Math.Min(35.0 / total, 5.5)) : 0;
|
double angle = total > 1 ? offset * (Math.Min(35.0 / total, 5.2)) : 0;
|
||||||
double yOffset = Math.Abs(offset) * 4.0;
|
double yOffset = Math.Abs(offset) * 3.5;
|
||||||
double xOffset = offset * (total > 8 ? 26 : 38);
|
double stepFactor = total > 8 ? 0.75 : (total > 5 ? 0.88 : 1.0);
|
||||||
|
|
||||||
// Ak patrí do aktívnej skupiny rovnakej hodnoty, vysunieme ju
|
// Ak patrí do aktívnej skupiny rovnakej hodnoty, vysunieme ju
|
||||||
string slotClasses = "hand-card-slot";
|
string slotClasses = "hand-card-slot";
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
slotClasses += " rank-group-lifted";
|
slotClasses += " rank-group-lifted";
|
||||||
}
|
}
|
||||||
|
|
||||||
string fanSlotStyle = $"transform: translateX({xOffset}px) translateY({yOffset}px) rotate({angle}deg); z-index: {(isSelected ? 140 + i : (isSameRankAsSelected ? 110 + i : i + 1))};";
|
string fanSlotStyle = $"transform: translateX(calc({offset.ToString(System.Globalization.CultureInfo.InvariantCulture)} * var(--fan-card-step) * {stepFactor.ToString(System.Globalization.CultureInfo.InvariantCulture)})) translateY({yOffset.ToString(System.Globalization.CultureInfo.InvariantCulture)}px) rotate({angle.ToString(System.Globalization.CultureInfo.InvariantCulture)}deg); z-index: {(isSelected ? 140 + i : (isSameRankAsSelected ? 110 + i : i + 1))};";
|
||||||
string selectedClass = isSelected ? "card-selected-combo" : (isSameRankAsSelected ? "card-group-active" : "");
|
string selectedClass = isSelected ? "card-selected-combo" : (isSameRankAsSelected ? "card-group-active" : "");
|
||||||
|
|
||||||
<div class="@slotClasses" style="@fanSlotStyle">
|
<div class="@slotClasses" style="@fanSlotStyle">
|
||||||
|
|||||||
@@ -18,7 +18,11 @@
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="avatar-card-count">
|
<div class="avatar-card-count">
|
||||||
@if (Player.HasFinished)
|
@if (Player.IsEliminated)
|
||||||
|
{
|
||||||
|
<span style="color: #ef4444; font-weight: 800;">☠️ Vyradený</span>
|
||||||
|
}
|
||||||
|
else if (Player.HasFinished)
|
||||||
{
|
{
|
||||||
<span>Skončil 🏆</span>
|
<span>Skončil 🏆</span>
|
||||||
}
|
}
|
||||||
@@ -26,11 +30,17 @@
|
|||||||
{
|
{
|
||||||
<span>@Player.Hand.Count @(Player.Hand.Count == 1 ? "karta" : (Player.Hand.Count < 5 ? "karty" : "kariet"))</span>
|
<span>@Player.Hand.Count @(Player.Hand.Count == 1 ? "karta" : (Player.Hand.Count < 5 ? "karty" : "kariet"))</span>
|
||||||
}
|
}
|
||||||
|
@if (IsOlympicMode)
|
||||||
|
{
|
||||||
|
<div style="font-size: 0.72rem; color: var(--gold); margin-top: 2px;">
|
||||||
|
🏅 @Player.OlympicCardsCount @(Player.OlympicCardsCount == 1 ? "karta" : (Player.OlympicCardsCount < 5 ? "karty" : "kariet"))
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Mini karty pre vizuálny odpočet kariet v ruke -->
|
<!-- Mini karty pre vizuálny odpočet kariet v ruke -->
|
||||||
@if (!Player.HasFinished)
|
@if (!Player.HasFinished && !Player.IsEliminated)
|
||||||
{
|
{
|
||||||
<div class="opponent-mini-cards">
|
<div class="opponent-mini-cards">
|
||||||
@for (int i = 0; i < Math.Min(Player.Hand.Count, 8); i++)
|
@for (int i = 0; i < Math.Min(Player.Hand.Count, 8); i++)
|
||||||
@@ -44,5 +54,6 @@
|
|||||||
@code {
|
@code {
|
||||||
[Parameter, EditorRequired] public Player Player { get; set; } = default!;
|
[Parameter, EditorRequired] public Player Player { get; set; } = default!;
|
||||||
[Parameter] public bool IsCurrentTurn { get; set; } = false;
|
[Parameter] public bool IsCurrentTurn { get; set; } = false;
|
||||||
|
[Parameter] public bool IsOlympicMode { get; set; } = false;
|
||||||
[Parameter] public string PositionClass { get; set; } = "slot-top";
|
[Parameter] public string PositionClass { get; set; } = "slot-top";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
@namespace Faraon.Client.Components
|
||||||
|
|
||||||
|
<div class="game-over-overlay">
|
||||||
|
<div class="game-over-card animate-pop" style="max-width: 500px;">
|
||||||
|
<div class="game-over-title" style="font-size: 1.5rem; color: var(--gold);">
|
||||||
|
🏅 Kolo #@RoundNumber Skončené!
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (RoundLoser != null)
|
||||||
|
{
|
||||||
|
<div style="background: rgba(239, 68, 68, 0.15); border: 1px solid rgba(239, 68, 68, 0.4); border-radius: 12px; padding: 10px 14px; margin-bottom: 16px;">
|
||||||
|
<div style="color: #fca5a5; font-weight: 800; font-size: 0.95rem;">
|
||||||
|
Porazený kola: @RoundLoser.Avatar @RoundLoser.Name
|
||||||
|
</div>
|
||||||
|
<div style="color: #cbd5e1; font-size: 0.85rem; margin-top: 3px;">
|
||||||
|
@if (RoundLoser.IsEliminated)
|
||||||
|
{
|
||||||
|
<span style="color: #ef4444; font-weight: 900;">☠️ Stratil všetky karty a VYPADÁVA z Olympijského turnaja!</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>V ďalšom kole začína s <strong>@RoundLoser.OlympicCardsCount @(RoundLoser.OlympicCardsCount == 1 ? "kartou" : (RoundLoser.OlympicCardsCount < 5 ? "kartami" : "kartami"))</strong> (-1 karta)</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div style="font-size: 0.85rem; color: #94a3b8; text-transform: uppercase; font-weight: 700; margin-bottom: 8px; text-align: left;">
|
||||||
|
Stav Olympijského turnaja:
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="podium-list" style="margin-bottom: 20px;">
|
||||||
|
@foreach (var player in Players.OrderBy(p => p.IsEliminated ? 1 : 0).ThenBy(p => p.FinishedPosition ?? 99))
|
||||||
|
{
|
||||||
|
<div class="podium-row @(player.FinishedPosition == 1 ? "winner" : (player.IsEliminated ? "eliminated-row" : ""))">
|
||||||
|
<div class="podium-pos">
|
||||||
|
@if (player.IsEliminated)
|
||||||
|
{
|
||||||
|
<span>☠️</span>
|
||||||
|
}
|
||||||
|
else if (player.FinishedPosition == 1)
|
||||||
|
{
|
||||||
|
<span>🥇</span>
|
||||||
|
}
|
||||||
|
else if (player.FinishedPosition == 2)
|
||||||
|
{
|
||||||
|
<span>🥈</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>#@(player.FinishedPosition ?? 3)</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="podium-player">
|
||||||
|
<span>@player.Avatar</span>
|
||||||
|
<span style="@(player.IsEliminated ? "text-decoration: line-through; opacity: 0.6;" : "")">@player.Name</span>
|
||||||
|
@if (player.Type == PlayerType.AI)
|
||||||
|
{
|
||||||
|
<span style="font-size: 0.75rem; opacity: 0.7;">(AI)</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div style="font-weight: 800; font-size: 0.9rem;">
|
||||||
|
@if (player.IsEliminated)
|
||||||
|
{
|
||||||
|
<span style="color: #ef4444;">Vyradený</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span style="color: var(--gold);">🎴 @player.OlympicCardsCount @(player.OlympicCardsCount == 1 ? "karta" : (player.OlympicCardsCount < 5 ? "karty" : "kariet"))</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="display: flex; gap: 12px; justify-content: center;">
|
||||||
|
<button class="btn-primary-glow" style="padding: 12px 28px; font-size: 1.1rem;" @onclick="OnNextRound">
|
||||||
|
⚔️ Začať Kolo #@(RoundNumber + 1)
|
||||||
|
</button>
|
||||||
|
<button class="btn-pill" style="padding: 12px 20px;" @onclick="OnBackToLobby">
|
||||||
|
Do Lobby 🏠
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public int RoundNumber { get; set; } = 1;
|
||||||
|
[Parameter] public Player? RoundLoser { get; set; }
|
||||||
|
[Parameter] public List<Player> Players { get; set; } = new();
|
||||||
|
[Parameter] public EventCallback OnNextRound { get; set; }
|
||||||
|
[Parameter] public EventCallback OnBackToLobby { get; set; }
|
||||||
|
}
|
||||||
@@ -15,7 +15,15 @@ else
|
|||||||
|
|
||||||
<!-- Horná lišta -->
|
<!-- Horná lišta -->
|
||||||
<header class="game-header">
|
<header class="game-header">
|
||||||
<h1 class="game-title">FARAÓN</h1>
|
<div style="display: flex; align-items: center; gap: 10px;">
|
||||||
|
<h1 class="game-title">FARAÓN</h1>
|
||||||
|
@if (Engine.State.Rules.OlympicMode)
|
||||||
|
{
|
||||||
|
<span style="background: linear-gradient(135deg, #f5b041, #d4ac0d); color: #1a1a1a; font-weight: 900; font-size: 0.78rem; padding: 2px 10px; border-radius: 12px; letter-spacing: 0.5px;">
|
||||||
|
🏅 KOLO #@Engine.State.RoundNumber
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<div style="font-size: 0.95rem; font-weight: 700; color: #a3b899;">
|
<div style="font-size: 0.95rem; font-weight: 700; color: #a3b899;">
|
||||||
Ťah #@Engine.State.TurnCount • Na rade:
|
Ťah #@Engine.State.TurnCount • Na rade:
|
||||||
<span style="color: var(--gold); font-weight: 900;">
|
<span style="color: var(--gold); font-weight: 900;">
|
||||||
@@ -24,8 +32,8 @@ else
|
|||||||
</div>
|
</div>
|
||||||
<div class="game-controls">
|
<div class="game-controls">
|
||||||
<!-- Rýchly prepínač balíčka kariet -->
|
<!-- Rýchly prepínač balíčka kariet -->
|
||||||
<button class="btn-game-icon" title="Zmeniť balíček kariet (Original / SpongeBob)" @onclick="ToggleDeck">
|
<button class="btn-game-icon" title="Zmeniť balíček kariet (@Engine.State.Rules.SelectedDeck)" @onclick="ToggleDeck">
|
||||||
@(Engine.State.Rules.SelectedDeck == "spongebob" ? "🧽" : "🎴")
|
@GetDeckIcon(Engine.State.Rules.SelectedDeck)
|
||||||
</button>
|
</button>
|
||||||
<button class="btn-game-icon" title="Stlmiť / Zapnúť zvuk" @onclick="ToggleMute">
|
<button class="btn-game-icon" title="Stlmiť / Zapnúť zvuk" @onclick="ToggleMute">
|
||||||
@(IsMuted ? "🔇" : "🔊")
|
@(IsMuted ? "🔇" : "🔊")
|
||||||
@@ -43,6 +51,7 @@ else
|
|||||||
{
|
{
|
||||||
<PlayerSlot Player="@opp.Player"
|
<PlayerSlot Player="@opp.Player"
|
||||||
IsCurrentTurn="@(Engine.State.CurrentPlayer == opp.Player)"
|
IsCurrentTurn="@(Engine.State.CurrentPlayer == opp.Player)"
|
||||||
|
IsOlympicMode="@Engine.State.Rules.OlympicMode"
|
||||||
PositionClass="@opp.PositionClass" />
|
PositionClass="@opp.PositionClass" />
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,21 +105,36 @@ else
|
|||||||
<span class="avatar-icon">@ViewingPlayer.Avatar</span>
|
<span class="avatar-icon">@ViewingPlayer.Avatar</span>
|
||||||
<span class="avatar-name">@ViewingPlayer.Name</span>
|
<span class="avatar-name">@ViewingPlayer.Name</span>
|
||||||
<span class="avatar-card-count">(@ViewingPlayer.Hand.Count kariet)</span>
|
<span class="avatar-card-count">(@ViewingPlayer.Hand.Count kariet)</span>
|
||||||
|
@if (Engine.State.Rules.OlympicMode)
|
||||||
|
{
|
||||||
|
<span style="font-size: 0.75rem; color: var(--gold); background: rgba(0,0,0,0.4); padding: 2px 8px; border-radius: 10px; border: 1px solid rgba(245, 176, 65, 0.4);">
|
||||||
|
🏅 @ViewingPlayer.OlympicCardsCount @(ViewingPlayer.OlympicCardsCount == 1 ? "karta" : (ViewingPlayer.OlympicCardsCount < 5 ? "karty" : "kariet"))
|
||||||
|
</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Interaktívna ruka hráča -->
|
<!-- Interaktívna ruka hráča -->
|
||||||
<PlayerHandView Player="@ViewingPlayer"
|
@if (!ViewingPlayer.IsEliminated)
|
||||||
Deck="@Engine.State.Rules.SelectedDeck"
|
{
|
||||||
IsMyTurn="@IsViewingPlayerTurn"
|
<PlayerHandView Player="@ViewingPlayer"
|
||||||
CanPlayCardFunc="@(c => Engine.CanPlayCard(ViewingPlayer, c))"
|
Deck="@Engine.State.Rules.SelectedDeck"
|
||||||
CanPlayCardsFunc="@(cards => Engine.CanPlayCards(ViewingPlayer, cards))"
|
IsMyTurn="@IsViewingPlayerTurn"
|
||||||
OnPlayCards="HandlePlayCards" />
|
CanPlayCardFunc="@(c => Engine.CanPlayCard(ViewingPlayer, c))"
|
||||||
|
CanPlayCardsFunc="@(cards => Engine.CanPlayCards(ViewingPlayer, cards))"
|
||||||
|
OnPlayCards="HandlePlayCards" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div style="padding: 20px; color: #ef4444; font-weight: 800; font-size: 1.1rem; text-shadow: 0 2px 8px rgba(0,0,0,0.8);">
|
||||||
|
☠️ Bol si vyradený z Olympijského turnaja. Sleduj zápas až do konca!
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Akčné tlačidlá pre aktívneho živého hráča -->
|
<!-- Akčné tlačidlá pre aktívneho živého hráča -->
|
||||||
@if (IsViewingPlayerTurn && Engine.State.TurnState == TurnState.Playing)
|
@if (IsViewingPlayerTurn && Engine.State.TurnState == TurnState.Playing && !ViewingPlayer.IsEliminated)
|
||||||
{
|
{
|
||||||
<div style="position: absolute; bottom: 18px; right: 24px; z-index: 60; display: flex; gap: 10px;">
|
<div style="position: absolute; bottom: 18px; right: 24px; z-index: 60; display: flex; gap: 10px;">
|
||||||
@if (CheckFourOfAKindRank(ViewingPlayer) is Rank burnRank)
|
@if (CheckFourOfAKindRank(ViewingPlayer) is Rank burnRank)
|
||||||
@@ -158,9 +182,20 @@ else
|
|||||||
<PassScreenModal Player="@Engine.State.CurrentPlayer" OnContinue="HandlePassContinue" />
|
<PassScreenModal Player="@Engine.State.CurrentPlayer" OnContinue="HandlePassContinue" />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (Engine.State.TurnState == TurnState.RoundOver)
|
||||||
|
{
|
||||||
|
<RoundOverModal RoundNumber="@Engine.State.RoundNumber"
|
||||||
|
RoundLoser="@Engine.State.RoundLoser"
|
||||||
|
Players="@Engine.State.Players"
|
||||||
|
OnNextRound="HandleStartNextRound"
|
||||||
|
OnBackToLobby="ReturnToLobby" />
|
||||||
|
}
|
||||||
|
|
||||||
@if (Engine.State.IsGameOver)
|
@if (Engine.State.IsGameOver)
|
||||||
{
|
{
|
||||||
<GameOverModal Players="@Engine.State.Players"
|
<GameOverModal Players="@Engine.State.Players"
|
||||||
|
IsOlympicMode="@Engine.State.Rules.OlympicMode"
|
||||||
|
MatchWinner="@Engine.State.MatchWinner"
|
||||||
OnPlayAgain="HandlePlayAgain"
|
OnPlayAgain="HandlePlayAgain"
|
||||||
OnBackToLobby="ReturnToLobby" />
|
OnBackToLobby="ReturnToLobby" />
|
||||||
}
|
}
|
||||||
@@ -285,13 +320,29 @@ else
|
|||||||
return "top";
|
return "top";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly string[] AvailableDecks = new[] { "original", "janosik", "spongebob", "cyberpunk", "fantasy", "egypt", "pets", "pixel" };
|
||||||
|
|
||||||
private void ToggleDeck()
|
private void ToggleDeck()
|
||||||
{
|
{
|
||||||
if (Engine == null) return;
|
if (Engine == null) return;
|
||||||
Engine.State.Rules.SelectedDeck = Engine.State.Rules.SelectedDeck == "spongebob" ? "original" : "spongebob";
|
int currentIdx = Array.IndexOf(AvailableDecks, Engine.State.Rules.SelectedDeck);
|
||||||
|
int nextIdx = (currentIdx + 1) % AvailableDecks.Length;
|
||||||
|
Engine.State.Rules.SelectedDeck = AvailableDecks[nextIdx];
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetDeckIcon(string deck) => deck switch
|
||||||
|
{
|
||||||
|
"janosik" => "🪓",
|
||||||
|
"spongebob" => "🧽",
|
||||||
|
"cyberpunk" => "⚡",
|
||||||
|
"fantasy" => "🐉",
|
||||||
|
"egypt" => "⚔️",
|
||||||
|
"pets" => "🐱",
|
||||||
|
"pixel" => "🕹️",
|
||||||
|
_ => "🎴"
|
||||||
|
};
|
||||||
|
|
||||||
private async Task HandlePlayCards(List<Card> cards)
|
private async Task HandlePlayCards(List<Card> cards)
|
||||||
{
|
{
|
||||||
if (Engine == null || cards.Count == 0) return;
|
if (Engine == null || cards.Count == 0) return;
|
||||||
@@ -349,6 +400,14 @@ else
|
|||||||
CheckTriggerAI();
|
CheckTriggerAI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleStartNextRound()
|
||||||
|
{
|
||||||
|
if (Engine == null) return;
|
||||||
|
Engine.StartNextRound();
|
||||||
|
StateHasChanged();
|
||||||
|
CheckTriggerAI();
|
||||||
|
}
|
||||||
|
|
||||||
private async Task HandleBurn(Rank rank)
|
private async Task HandleBurn(Rank rank)
|
||||||
{
|
{
|
||||||
if (Engine == null) return;
|
if (Engine == null) return;
|
||||||
|
|||||||
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 47 KiB |