impl
This commit is contained in:
+511
-133
@@ -1,174 +1,552 @@
|
||||
@page "/"
|
||||
@using SlaySharp.Core.Run
|
||||
@using SlaySharp.Core.Combat
|
||||
@using SlaySharp.Core.Models
|
||||
@using SlaySharp.Core.Catalogs
|
||||
@using SlaySharp.Core.Relics
|
||||
@using SlaySharp.Web.Components
|
||||
@inject IJSRuntime JS
|
||||
|
||||
<PageTitle>SlaySharp - Visual Studio Code Edition</PageTitle>
|
||||
|
||||
@if (_engine == null || !_gameStarted)
|
||||
@if (_showIntroBoot)
|
||||
{
|
||||
<!-- VS Code Welcome / Get Started Dashboard -->
|
||||
<div class="container-fluid h-100 p-4 d-flex flex-column overflow-y-auto font-mono" style="background-color: var(--vscode-bg-editor);">
|
||||
<!-- Welcome Header -->
|
||||
<div class="mb-4 pb-3 border-bottom border-secondary">
|
||||
<div class="d-flex align-items-center gap-3 mb-1">
|
||||
<span style="font-size: 3rem; color: #007acc;">⚔️</span>
|
||||
<div>
|
||||
<h1 class="text-white fw-bolder mb-0" style="font-size: 2.4rem; letter-spacing: -1px;">
|
||||
SlaySharp <span style="color: #61afef; font-size: 1.4rem;">v1.0</span>
|
||||
</h1>
|
||||
<span class="text-muted" style="font-size: 1rem; font-weight: 800;">
|
||||
C# & .NET Roguelike Deckbuilder
|
||||
</span>
|
||||
<!-- Cyberpunk Roslyn CLR Intro Boot Sequence -->
|
||||
<div class="intro-boot-screen @(_isGlitchTransitioning ? "intro-glitch-out" : "") font-mono" @onclick="EnterTitleScreenAsync">
|
||||
<div class="intro-crt-lines"></div>
|
||||
<div class="intro-content-box p-4 p-md-5">
|
||||
<!-- Terminal Header -->
|
||||
<div class="d-flex align-items-center justify-content-between mb-3 pb-2 border-bottom border-secondary">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span style="color: #e06c75; font-size: 0.9rem;">●</span>
|
||||
<span style="color: #e5c07b; font-size: 0.9rem;">●</span>
|
||||
<span style="color: #98c379; font-size: 0.9rem;">●</span>
|
||||
<span class="text-muted ms-2" style="font-size: 0.78rem;">pwsh -- SlaySharp Roslyn CLR v8.0 Bootstrapper</span>
|
||||
</div>
|
||||
<span class="badge bg-dark text-info border border-info px-2 py-1" style="font-size: 0.7rem;">x64-wasm</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- Left Column: Start Debugging Incidents -->
|
||||
<div class="col-lg-7">
|
||||
<h4 class="text-white mb-3 d-flex align-items-center gap-2 fw-bold">
|
||||
<span style="color: #61afef; font-size: 1.5rem;">🐞</span>
|
||||
<span>Start Incident Session</span>
|
||||
</h4>
|
||||
<!-- Animated Terminal Diagnostics Log -->
|
||||
<div class="intro-term-body mb-4">
|
||||
<div class="text-info">> Microsoft (R) .NET Core CLR 8.0.0-rtm (WebAssembly)</div>
|
||||
<div class="text-success">> [OK] Roslyn C# AST & JIT Tier-1 Optimization Engine loaded</div>
|
||||
<div class="text-muted">> [OK] Allocated 64MB managed memory with GC Generation 0/1/2</div>
|
||||
<div class="text-warning">> [ALERT] 3 Incident Branches detected on CI/CD pipeline!</div>
|
||||
<div class="text-white">> [READY] Principal .NET Architect credentials authenticated.</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<!-- Config 1 -->
|
||||
<div class="card p-4 shadow-sm" style="background-color: #21252b; border: 2px solid #383e4a; border-radius: 12px; cursor: pointer; transition: all 0.2s ease;"
|
||||
@onclick="() => StartEncounter(EncounterType.Standard)">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="text-danger fw-bolder fs-5">💥 [SEV-1] NullReference & Off-By-One</span>
|
||||
<span class="badge bg-danger text-white fs-6 px-3 py-2">Launch (F5) ➔</span>
|
||||
</div>
|
||||
<p class="text-white mb-0" style="font-size: 0.92rem; font-weight: 700;">
|
||||
Patch NullReferenceException (45 HP) and Off-By-One Bug (22 HP). Keep SLA at 100%.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Config 2 -->
|
||||
<div class="card p-4 shadow-sm" style="background-color: #21252b; border: 2px solid #383e4a; border-radius: 12px; cursor: pointer; transition: all 0.2s ease;"
|
||||
@onclick="() => StartEncounter(EncounterType.MemoryLeak)">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="text-warning fw-bolder fs-5">👻 [SEV-2] Memory Leak Spectre</span>
|
||||
<span class="badge bg-warning text-dark fs-6 px-3 py-2">Launch (F5) ➔</span>
|
||||
</div>
|
||||
<p class="text-white mb-0" style="font-size: 0.92rem; font-weight: 700;">
|
||||
Dispose dangling unmanaged event handlers from Memory Leak Spectre (34 HP).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Config 3 -->
|
||||
<div class="card p-4 shadow-sm" style="background-color: #21252b; border: 2px solid #383e4a; border-radius: 12px; cursor: pointer; transition: all 0.2s ease;"
|
||||
@onclick="() => StartEncounter(EncounterType.Chaos)">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="text-info fw-bolder fs-5">🔥 [SEV-0] Friday 5 PM Outage</span>
|
||||
<span class="badge bg-primary text-white fs-6 px-3 py-2">Launch (F5) ➔</span>
|
||||
</div>
|
||||
<p class="text-white mb-0" style="font-size: 0.92rem; font-weight: 700;">
|
||||
Critical Outage: Face NullReferenceException and Memory Leak Spectre simultaneously.
|
||||
</p>
|
||||
</div>
|
||||
<!-- Center ASCII / Neon Title Logo -->
|
||||
<div class="intro-ascii-logo text-center my-3 my-md-4">
|
||||
<pre class="neon-glow-text mb-0" style="color: #61afef; font-size: clamp(0.55rem, 1.4vw, 1.05rem); font-weight: 900; line-height: 1.15;">
|
||||
____ _ ____ _
|
||||
/ ___|| | __ _ _ _/ ___|| |__ __ _ _ __ _ __
|
||||
\___ \| |/ _` | | | \___ \| '_ \ / _` | '__| '_ \
|
||||
___) | | (_| | |_| |___) | | | | (_| | | | |_) |
|
||||
|____/|_|\__,_|\__, |____/|_| |_|\__,_|_| | .__/
|
||||
|___/ |_|
|
||||
</pre>
|
||||
<div class="text-info fw-bolder mt-3" style="font-size: clamp(0.9rem, 2vw, 1.25rem); letter-spacing: 2px;">
|
||||
THE C# & .NET RUNTIME ROGUELIKE DECKBUILDER
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Workspace & Diagnostics Configuration -->
|
||||
<div class="col-lg-5">
|
||||
<h4 class="text-white mb-3 d-flex align-items-center gap-2 fw-bold">
|
||||
<span style="color: #56b6c2; font-size: 1.5rem;">⚙️</span>
|
||||
<span>Active Profile</span>
|
||||
</h4>
|
||||
|
||||
<div class="card p-4 mb-3" style="background-color: #21252b; border: 2px solid #383e4a; border-radius: 12px;">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span style="font-size: 2.2rem;">👨💻</span>
|
||||
<div>
|
||||
<div class="text-info fw-bolder fs-5">Principal .NET Architect</div>
|
||||
<div class="text-white" style="font-size: 0.85rem; font-weight: 800;">3 CPU Cycles / 70 SLA HP</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-muted fw-bold mb-1" style="font-size: 0.78rem;">INSTALLED NUGETS:</div>
|
||||
<div class="d-flex flex-column gap-2 mb-2">
|
||||
<div class="badge bg-dark border border-secondary text-white p-2 d-flex align-items-center justify-content-between" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>📜 Newtonsoft.Json</span>
|
||||
<span class="text-info">+1 Card T1</span>
|
||||
</div>
|
||||
<div class="badge bg-dark border border-secondary text-white p-2 d-flex align-items-center justify-content-between" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>⚡ BenchmarkDotNet</span>
|
||||
<span class="text-warning">+1 CPU / 2T</span>
|
||||
</div>
|
||||
<div class="badge bg-dark border border-secondary text-white p-2 d-flex align-items-center justify-content-between" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>📊 Serilog</span>
|
||||
<span class="text-success">+2 Shield on Attack</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card p-3" style="background-color: #21252b; border: 2px solid #383e4a; border-radius: 12px;">
|
||||
<div class="text-white fw-bolder mb-2" style="font-size: 0.88rem;">CONTROLS</div>
|
||||
<div class="d-flex justify-content-between text-white" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>Play Card</span>
|
||||
<span class="badge bg-dark border border-secondary text-light">Click Card</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between text-white mt-1" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>Target Bug</span>
|
||||
<span class="badge bg-dark border border-secondary text-light">Click Bug</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between text-white mt-1" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>End Turn</span>
|
||||
<span class="badge bg-success text-white">F5 / Click Button</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Glowing Launch CTA -->
|
||||
<div class="text-center mt-4">
|
||||
<button class="btn btn-success btn-lg font-mono fw-bolder px-5 py-3 shadow-lg intro-start-btn" @onclick="EnterTitleScreenAsync">
|
||||
⚡ INITIALIZE WORKSPACE (PRESS ANYWHERE) ➔
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="text-muted text-center mt-3" style="font-size: 0.78rem;">
|
||||
Click anywhere or press Enter to launch IDE Dashboard
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<!-- Live VS Code Combat Workspace -->
|
||||
<CombatArena Engine="@_engine" OnRestartRequested="HandleRestartRequested" />
|
||||
@switch (_run.CurrentScreen)
|
||||
{
|
||||
case RunScreen.Title:
|
||||
<!-- VS Code Welcome / Get Started Dashboard with Cinematic Intro -->
|
||||
<div class="container-fluid h-100 p-4 d-flex flex-column overflow-y-auto font-mono position-relative title-screen-container"
|
||||
style="background: linear-gradient(rgba(24, 26, 31, 0.78), rgba(24, 26, 31, 0.90)), url('images/title_screen_bg.jpg') no-repeat center center; background-size: cover;">
|
||||
|
||||
<!-- Animated Deployment Overlay -->
|
||||
@if (_isDeploying)
|
||||
{
|
||||
<div class="deploying-overlay d-flex flex-column align-items-center justify-content-center">
|
||||
<div class="spinner-border text-info mb-3" style="width: 4rem; height: 4rem;" role="status"></div>
|
||||
<h2 class="text-white fw-bolder font-mono mb-2 neon-glow-text">DEPLOYING TO STAGING...</h2>
|
||||
<div class="text-muted font-mono fs-6 mb-3">Compiling Roslyn IL modules & building Git topology graph...</div>
|
||||
<div class="badge bg-dark border border-info text-info px-4 py-2 font-mono fs-6">
|
||||
✓ 0 Errors | ✓ 0 Warnings | Production SLA 100%
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Welcome Header with Intro Glow & Code Terminal Badge -->
|
||||
<div class="mb-4 pb-3 border-bottom border-secondary d-flex justify-content-between align-items-center flex-wrap gap-3">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="csharp-logo-glow">
|
||||
<span style="font-size: 3.2rem; color: #61afef; font-weight: 900;">C#</span>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-white fw-bolder mb-0 neon-glow-text" style="font-size: 2.6rem; letter-spacing: -1px;">
|
||||
SlaySharp <span style="color: #61afef; font-size: 1.3rem;">v1.3</span>
|
||||
</h1>
|
||||
<span class="text-info" style="font-size: 1rem; font-weight: 800;">
|
||||
C# & .NET Runtime Roguelike Deckbuilder
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Animated Terminal Boot Badge & Replay Intro CTA -->
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<button class="btn btn-outline-secondary btn-sm font-mono fw-bold px-3 py-2" @onclick="() => _showIntroBoot = true">
|
||||
📺 Replay Boot Intro
|
||||
</button>
|
||||
<div class="card p-2 px-3 text-start shadow" style="background-color: rgba(24, 26, 31, 0.92); border: 1px solid #383e4a; border-radius: 8px;">
|
||||
<div class="text-muted" style="font-size: 0.72rem; font-weight: 800;">RUNTIME ENVIRONMENT</div>
|
||||
<div class="text-success font-mono" style="font-size: 0.85rem; font-weight: 800;">
|
||||
🟢 .NET 8.0 CLR [AggressiveTieredOpt]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- Left Column: Start Campaigns & Encounters -->
|
||||
<div class="col-lg-7">
|
||||
<!-- Main Hero CTA: Act 1 Roguelike Campaign -->
|
||||
<div class="card p-4 mb-4 shadow-lg hero-campaign-card"
|
||||
style="background: linear-gradient(135deg, rgba(27, 47, 35, 0.92) 0%, rgba(33, 37, 43, 0.95) 100%); border: 2px solid #98c379; border-radius: 14px; cursor: pointer; backdrop-filter: blur(8px);"
|
||||
@onclick="TriggerCampaignLaunchAsync">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<span style="font-size: 2.5rem;" class="pulse-icon">🗺️</span>
|
||||
<div>
|
||||
<h3 class="text-success fw-bolder mb-0">START CAMPAIGN: ACT 1</h3>
|
||||
<span class="text-muted" style="font-size: 0.82rem; font-weight: 800;">CI/CD Pipeline & Legacy Monolith Boss</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="badge bg-success text-white fs-6 px-4 py-3 fw-bolder shadow launch-btn">
|
||||
Launch Run (F5) ➔
|
||||
</span>
|
||||
</div>
|
||||
<p class="text-white mb-0" style="font-size: 0.95rem; font-weight: 700; line-height: 1.5;">
|
||||
Navigate the 7-floor procedural Git branch graph. Patch production bugs, resolve StackOverflow dilemmas, refactor modules at coffee breaks, and face the Legacy Monolith Boss!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h4 class="text-white mb-3 d-flex align-items-center gap-2 fw-bold">
|
||||
<span style="color: #61afef; font-size: 1.5rem;">⚡</span>
|
||||
<span>Quick Incident Sandboxes (Single Encounters)</span>
|
||||
</h4>
|
||||
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<!-- Config 1 -->
|
||||
<div class="card p-3 shadow-sm sandbox-card" style="background-color: rgba(33, 37, 43, 0.92); border: 2px solid #383e4a; border-radius: 10px; cursor: pointer; backdrop-filter: blur(6px);"
|
||||
@onclick="() => StartSandboxEncounter(1)">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<span class="text-danger fw-bolder fs-6">💥 [SEV-1] NullReference & Off-By-One</span>
|
||||
<span class="badge bg-danger text-white fs-6 px-3 py-1">Quick Battle ➔</span>
|
||||
</div>
|
||||
<p class="text-white mb-0" style="font-size: 0.85rem; font-weight: 700;">
|
||||
Patch NullReferenceException (45 HP) and Off-By-One Bug (22 HP).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Config 2 -->
|
||||
<div class="card p-3 shadow-sm sandbox-card" style="background-color: rgba(33, 37, 43, 0.92); border: 2px solid #383e4a; border-radius: 10px; cursor: pointer; backdrop-filter: blur(6px);"
|
||||
@onclick="() => StartSandboxEncounter(2)">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<span class="text-warning fw-bolder fs-6">👻 [SEV-2] Memory Leak Spectre</span>
|
||||
<span class="badge bg-warning text-dark fs-6 px-3 py-1">Quick Battle ➔</span>
|
||||
</div>
|
||||
<p class="text-white mb-0" style="font-size: 0.85rem; font-weight: 700;">
|
||||
Dispose unmanaged memory from Memory Leak Spectre (34 HP) with Shield gain.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Config 3 -->
|
||||
<div class="card p-3 shadow-sm sandbox-card" style="background-color: rgba(33, 37, 43, 0.92); border: 2px solid #383e4a; border-radius: 10px; cursor: pointer; backdrop-filter: blur(6px);"
|
||||
@onclick="() => StartSandboxEncounter(3)">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<span class="text-info fw-bolder fs-6">👑 [ACT-BOSS] Legacy Monolith (90 HP)</span>
|
||||
<span class="badge bg-primary text-white fs-6 px-3 py-1">Boss Battle ➔</span>
|
||||
</div>
|
||||
<p class="text-white mb-0" style="font-size: 0.85rem; font-weight: 700;">
|
||||
Battle the 90 HP Legacy Monolith Boss with spaghetti code and thread locks.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Workspace & Diagnostics Configuration -->
|
||||
<div class="col-lg-5">
|
||||
<h4 class="text-white mb-3 d-flex align-items-center gap-2 fw-bold">
|
||||
<span style="color: #56b6c2; font-size: 1.5rem;">⚙️</span>
|
||||
<span>Active Profile</span>
|
||||
</h4>
|
||||
|
||||
<div class="card p-4 mb-3" style="background-color: rgba(33, 37, 43, 0.92); border: 2px solid #383e4a; border-radius: 12px; backdrop-filter: blur(6px);">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span style="font-size: 2.2rem;">👨💻</span>
|
||||
<div>
|
||||
<div class="text-info fw-bolder fs-5">Principal .NET Architect</div>
|
||||
<div class="text-white" style="font-size: 0.85rem; font-weight: 800;">3 CPU Cycles / 70 SLA HP</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-muted fw-bold mb-1" style="font-size: 0.78rem;">STARTER NUGET PACKAGES:</div>
|
||||
<div class="d-flex flex-column gap-2 mb-2">
|
||||
<div class="badge bg-dark border border-secondary text-white p-2 d-flex align-items-center justify-content-between" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>📜 Newtonsoft.Json</span>
|
||||
<span class="text-info">+1 Card T1</span>
|
||||
</div>
|
||||
<div class="badge bg-dark border border-secondary text-white p-2 d-flex align-items-center justify-content-between" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>⚡ BenchmarkDotNet</span>
|
||||
<span class="text-warning">+1 CPU / 2T</span>
|
||||
</div>
|
||||
<div class="badge bg-dark border border-secondary text-white p-2 d-flex align-items-center justify-content-between" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>📊 Serilog</span>
|
||||
<span class="text-success">+2 Shield on Attack</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card p-3" style="background-color: rgba(33, 37, 43, 0.92); border: 2px solid #383e4a; border-radius: 12px; backdrop-filter: blur(6px);">
|
||||
<div class="text-white fw-bolder mb-2" style="font-size: 0.88rem;">MECHANICS HIGHLIGHTS</div>
|
||||
<div class="d-flex justify-content-between text-white" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>Branch Prediction Crit</span>
|
||||
<span class="text-warning fw-bolder">25% chance for 2x DMG</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between text-white mt-1" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>Git Procedural Map</span>
|
||||
<span class="text-info fw-bolder">7-Floor Branching Paths</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between text-white mt-1" style="font-size: 0.85rem; font-weight: 800;">
|
||||
<span>Post-Battle PR Review</span>
|
||||
<span class="text-success fw-bolder">Merge 1 of 3 Cards</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
break;
|
||||
|
||||
case RunScreen.Map:
|
||||
<MapView Run="@_run" />
|
||||
break;
|
||||
|
||||
case RunScreen.Combat:
|
||||
@if (_run.ActiveCombat != null)
|
||||
{
|
||||
<CombatArena Engine="@_run.ActiveCombat"
|
||||
OnVictoryCompleted="HandleCombatVictory"
|
||||
OnDefeatCompleted="HandleCombatDefeat"
|
||||
OnRestartRequested="HandleCombatDefeat" />
|
||||
}
|
||||
break;
|
||||
|
||||
case RunScreen.Event:
|
||||
<EventView Run="@_run" />
|
||||
break;
|
||||
|
||||
case RunScreen.RestSite:
|
||||
<RestSiteView Run="@_run" />
|
||||
break;
|
||||
|
||||
case RunScreen.Shop:
|
||||
<ShopView Run="@_run" />
|
||||
break;
|
||||
|
||||
case RunScreen.RunVictory:
|
||||
<!-- Act 1 Victory Screen -->
|
||||
<div class="d-flex flex-column justify-content-center align-items-center h-100 p-4 font-mono"
|
||||
style="background: linear-gradient(rgba(24, 26, 31, 0.80), rgba(24, 26, 31, 0.92)), url('images/title_screen_bg.jpg') no-repeat center center; background-size: cover;">
|
||||
<div class="card p-5 text-center shadow-lg" style="max-width: 750px; background-color: rgba(33, 37, 43, 0.95); border: 3px solid #98c379; border-radius: 16px; backdrop-filter: blur(10px);">
|
||||
<div style="font-size: 4rem;">🏆</div>
|
||||
<h1 class="text-success fw-bolder mb-1" style="font-size: 2.5rem;">ACT 1 DEPLOYMENT SUCCESSFUL!</h1>
|
||||
<h4 class="text-white fw-bold mb-3">The Legacy Monolith Boss Has Been Decoupled & Microserviced.</h4>
|
||||
|
||||
<div class="d-flex justify-content-center gap-4 my-4 p-3 rounded border border-secondary" style="background-color: #181a1f;">
|
||||
<div>
|
||||
<div class="text-muted" style="font-size: 0.8rem; font-weight: 800;">FINAL SLA HEALTH</div>
|
||||
<div class="text-success fs-4 fw-bolder">@_run.Player.CurrentHp / @_run.Player.MaxHp HP</div>
|
||||
</div>
|
||||
<div class="border-start border-secondary ps-4">
|
||||
<div class="text-muted" style="font-size: 0.8rem; font-weight: 800;">DEV CREDITS EARNED</div>
|
||||
<div class="text-warning fs-4 fw-bolder">@_run.DevCredits Credits</div>
|
||||
</div>
|
||||
<div class="border-start border-secondary ps-4">
|
||||
<div class="text-muted" style="font-size: 0.8rem; font-weight: 800;">FINAL DECK SIZE</div>
|
||||
<div class="text-info fs-4 fw-bolder">@_run.Player.MasterDeck.Count Cards</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-center gap-3">
|
||||
<button class="btn btn-success btn-lg font-mono fw-bold px-5 py-3 shadow" @onclick="TriggerCampaignLaunchAsync">
|
||||
🚀 Start New Sprint / Run
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary btn-lg font-mono fw-bold px-4 py-3" @onclick="() => _run.CurrentScreen = RunScreen.Title">
|
||||
Main Dashboard
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
break;
|
||||
|
||||
case RunScreen.RunDefeat:
|
||||
<!-- Run Defeat Screen -->
|
||||
<div class="d-flex flex-column justify-content-center align-items-center h-100 p-4 font-mono"
|
||||
style="background: linear-gradient(rgba(24, 26, 31, 0.85), rgba(24, 26, 31, 0.95)), url('images/combat_arena_bg.jpg') no-repeat center center; background-size: cover;">
|
||||
<div class="card p-5 text-center shadow-lg" style="max-width: 650px; background-color: rgba(33, 37, 43, 0.95); border: 3px solid #e06c75; border-radius: 16px; backdrop-filter: blur(10px);">
|
||||
<div style="font-size: 4.5rem;">💥</div>
|
||||
<h1 class="text-danger fw-bolder mb-1" style="font-size: 2.5rem;">PRODUCTION OUTAGE</h1>
|
||||
<p class="text-white fs-5 mb-4">SLA dropped to 0%. The deployment was rolled back by SRE.</p>
|
||||
|
||||
<div class="d-flex justify-content-center gap-3">
|
||||
<button class="btn btn-danger btn-lg font-mono fw-bold px-5 py-3 shadow" @onclick="TriggerCampaignLaunchAsync">
|
||||
🔄 Retrying Deployment (New Run)
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary btn-lg font-mono fw-bold px-4 py-3" @onclick="() => _run.CurrentScreen = RunScreen.Title">
|
||||
Main Dashboard
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
private CombatEngine? _engine;
|
||||
private bool _gameStarted = false;
|
||||
private EncounterType _lastEncounterType = EncounterType.Standard;
|
||||
<style>
|
||||
/* Intro Boot Screen & Terminal Styles */
|
||||
.intro-boot-screen {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: #0d1117;
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
animation: intro-fade-in 0.4s ease-out;
|
||||
}
|
||||
|
||||
private enum EncounterType
|
||||
@@keyframes intro-fade-in {
|
||||
from { opacity: 0; transform: scale(0.98); }
|
||||
to { opacity: 1; transform: scale(1); }
|
||||
}
|
||||
|
||||
.intro-glitch-out {
|
||||
animation: intro-warp-out 0.45s forwards cubic-bezier(0.7, 0, 0.3, 1);
|
||||
}
|
||||
|
||||
@@keyframes intro-warp-out {
|
||||
0% { opacity: 1; transform: scale(1); filter: brightness(1); }
|
||||
50% { opacity: 0.8; transform: scale(1.05) skewX(2deg); filter: brightness(2); }
|
||||
100% { opacity: 0; transform: scale(1.15); filter: brightness(3); }
|
||||
}
|
||||
|
||||
.intro-crt-lines {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: repeating-linear-gradient(
|
||||
rgba(0, 0, 0, 0.15) 0px,
|
||||
rgba(0, 0, 0, 0.15) 1px,
|
||||
transparent 1px,
|
||||
transparent 2px
|
||||
);
|
||||
pointer-events: none;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.intro-content-box {
|
||||
position: relative;
|
||||
max-width: 820px;
|
||||
width: 90%;
|
||||
background: rgba(22, 27, 34, 0.95);
|
||||
border: 2px solid #383e4a;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 0 50px rgba(0, 122, 204, 0.4), inset 0 0 20px rgba(0, 0, 0, 0.8);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.intro-term-body {
|
||||
background: #0a0c10;
|
||||
border: 1px solid #21262d;
|
||||
border-radius: 8px;
|
||||
padding: 14px 18px;
|
||||
font-size: 0.82rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
box-shadow: inset 0 2px 10px rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
.intro-start-btn {
|
||||
animation: start-btn-glow 1.4s infinite alternate ease-in-out;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
@@keyframes start-btn-glow {
|
||||
0% { transform: scale(1); box-shadow: 0 0 15px rgba(46, 160, 67, 0.6); }
|
||||
100% { transform: scale(1.04); box-shadow: 0 0 35px rgba(46, 160, 67, 1); }
|
||||
}
|
||||
|
||||
.csharp-logo-glow {
|
||||
width: 65px;
|
||||
height: 65px;
|
||||
border-radius: 12px;
|
||||
background: #181a1f;
|
||||
border: 2px solid #61afef;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 0 20px rgba(97, 175, 239, 0.6);
|
||||
animation: logo-pulse 2s infinite alternate ease-in-out;
|
||||
}
|
||||
|
||||
@@keyframes logo-pulse {
|
||||
0% { transform: scale(1); box-shadow: 0 0 15px rgba(97, 175, 239, 0.4); }
|
||||
100% { transform: scale(1.06); box-shadow: 0 0 30px rgba(97, 175, 239, 0.9); }
|
||||
}
|
||||
|
||||
.neon-glow-text {
|
||||
text-shadow: 0 0 12px rgba(97, 175, 239, 0.6);
|
||||
}
|
||||
|
||||
.hero-campaign-card {
|
||||
transition: all 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
|
||||
}
|
||||
|
||||
.hero-campaign-card:hover {
|
||||
transform: translateY(-5px);
|
||||
border-color: #61afef !important;
|
||||
box-shadow: 0 12px 30px rgba(97, 175, 239, 0.3) !important;
|
||||
}
|
||||
|
||||
.sandbox-card {
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.sandbox-card:hover {
|
||||
transform: translateX(6px);
|
||||
border-color: #61afef !important;
|
||||
}
|
||||
|
||||
.deploying-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(15, 17, 21, 0.92);
|
||||
backdrop-filter: blur(12px);
|
||||
z-index: 999;
|
||||
animation: fade-in 0.3s ease-out;
|
||||
}
|
||||
|
||||
@@keyframes fade-in {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
.pulse-icon {
|
||||
animation: pulse-icon-anim 1.5s infinite alternate ease-in-out;
|
||||
}
|
||||
|
||||
@@keyframes pulse-icon-anim {
|
||||
0% { transform: scale(1); }
|
||||
100% { transform: scale(1.15); }
|
||||
}
|
||||
</style>
|
||||
|
||||
@code {
|
||||
private readonly GameRun _run = new();
|
||||
private bool _showIntroBoot = true;
|
||||
private bool _isGlitchTransitioning = false;
|
||||
private bool _isSandboxMode = false;
|
||||
private bool _isDeploying = false;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
Standard,
|
||||
MemoryLeak,
|
||||
Chaos
|
||||
_run.OnRunStateChanged += StateHasChanged;
|
||||
}
|
||||
|
||||
private void StartEncounter(EncounterType type)
|
||||
private async Task EnterTitleScreenAsync()
|
||||
{
|
||||
_lastEncounterType = type;
|
||||
var player = new Player("Senior Dev", 70, maxEnergy: 3);
|
||||
player.MasterDeck.AddRange(StarterDecks.CreateCsharpArchitectDeck());
|
||||
if (_isGlitchTransitioning) return;
|
||||
_isGlitchTransitioning = true;
|
||||
StateHasChanged();
|
||||
_ = JS.InvokeVoidAsync("slayAudio.playIntroChime");
|
||||
|
||||
// Add starter NuGets (Relics)
|
||||
player.Relics.Add(new NewtonsoftJsonRelic());
|
||||
player.Relics.Add(new BenchmarkDotNetRelic());
|
||||
player.Relics.Add(new SerilogRelic());
|
||||
await Task.Delay(400);
|
||||
_showIntroBoot = false;
|
||||
_isGlitchTransitioning = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
var enemies = type switch
|
||||
private async Task TriggerCampaignLaunchAsync()
|
||||
{
|
||||
_isDeploying = true;
|
||||
StateHasChanged();
|
||||
_ = JS.InvokeVoidAsync("slayAudio.playBootSound");
|
||||
|
||||
await Task.Delay(900);
|
||||
_isDeploying = false;
|
||||
|
||||
_isSandboxMode = false;
|
||||
_run.StartNewRun();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void StartSandboxEncounter(int type)
|
||||
{
|
||||
_isSandboxMode = true;
|
||||
_run.Player = new Player("Senior Dev", 70, maxEnergy: 3);
|
||||
_run.Player.MasterDeck.AddRange(StarterDecks.CreateCsharpArchitectDeck());
|
||||
_run.Player.Relics.Add(new NewtonsoftJsonRelic());
|
||||
_run.Player.Relics.Add(new BenchmarkDotNetRelic());
|
||||
_run.Player.Relics.Add(new SerilogRelic());
|
||||
|
||||
List<Enemy> enemies = type switch
|
||||
{
|
||||
EncounterType.Standard => new List<Enemy> { new NullReferenceExceptionEnemy(), new OffByOneBugEnemy() },
|
||||
EncounterType.MemoryLeak => new List<Enemy> { new MemoryLeakSpectreEnemy(), new OffByOneBugEnemy() },
|
||||
EncounterType.Chaos => new List<Enemy> { new NullReferenceExceptionEnemy(), new MemoryLeakSpectreEnemy() },
|
||||
1 => new List<Enemy> { new NullReferenceExceptionEnemy(), new OffByOneBugEnemy() },
|
||||
2 => new List<Enemy> { new MemoryLeakSpectreEnemy(), new OffByOneBugEnemy() },
|
||||
3 => new List<Enemy> { new LegacyMonolithBossEnemy() },
|
||||
_ => new List<Enemy> { new NullReferenceExceptionEnemy() }
|
||||
};
|
||||
|
||||
_engine = new CombatEngine();
|
||||
_engine.StartCombat(player, enemies);
|
||||
_gameStarted = true;
|
||||
_run.ActiveCombat = new CombatEngine();
|
||||
_run.ActiveCombat.StartCombat(_run.Player, enemies);
|
||||
_run.CurrentScreen = RunScreen.Combat;
|
||||
_ = JS.InvokeVoidAsync("slayAudio.playCardSound");
|
||||
}
|
||||
|
||||
private void HandleRestartRequested()
|
||||
private void HandleCombatVictory()
|
||||
{
|
||||
_gameStarted = false;
|
||||
if (_isSandboxMode)
|
||||
{
|
||||
_run.CurrentScreen = RunScreen.Title;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
_run.CompleteCombatAndClaimRewards(25);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCombatDefeat()
|
||||
{
|
||||
if (_isSandboxMode)
|
||||
{
|
||||
_run.CurrentScreen = RunScreen.Title;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
_run.ReturnToMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user