- Isometric canvas renderer (depth-sorted, FOV/fog, additive lighting) - 3 classes x 20 skills, 4 acts x 4 floors + boss lairs, torment I-X - Diablo-style loot: rarities, affix tiers, 14 legendaries, vendor, stash - Rogue camp with 6 NPCs: Charsi/Akara/Kashya/Cain/Gheed/storage - NPC quest chain (accept -> hunt -> turn in) with rewards & gating - Procedural WebAudio SFX + generative music, EN/VI localization - Saves, settings, waypoints, hardcore mode, PWA manifest - 93-assertion headless suite + browser E2E via CDP
129 lines
5.2 KiB
HTML
129 lines
5.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
<title>Diablo2D — Shadows of Tristram</title>
|
|
<meta name="description" content="A dark isometric action-RPG. Descend procedurally generated dungeons, slay elites and bosses, collect legendary loot. Playable fully offline in your browser.">
|
|
<meta property="og:title" content="Diablo2D — Shadows of Tristram">
|
|
<meta property="og:description" content="Dark isometric action-RPG in your browser. Procedural dungeons, elite affixes, legendary loot, 3 classes.">
|
|
<meta name="theme-color" content="#0b0908">
|
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='12' fill='%230b0908'/%3E%3Cpath d='M32 10 L52 26 L46 54 L18 54 L12 26 Z' fill='%23a32c22'/%3E%3Cpath d='M32 20 L42 28 L38 46 L26 46 L22 28 Z' fill='%23e9c87b'/%3E%3C/svg%3E">
|
|
<link rel="manifest" href="manifest.webmanifest">
|
|
<link rel="apple-touch-icon" href="icons/icon-180.png">
|
|
<meta name="mobile-web-app-capable" content="yes">
|
|
<link rel="stylesheet" href="css/style.css">
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<canvas id="game-canvas"></canvas>
|
|
|
|
<!-- ======== IN-GAME HUD (DOM over canvas) ======== -->
|
|
<div id="hud" class="hidden">
|
|
<div id="quest-tracker" class="hud-corner"></div>
|
|
|
|
<div id="minimap-box" class="hud-panel">
|
|
<canvas id="minimap" width="216" height="150"></canvas>
|
|
<div id="minimap-label"></div>
|
|
</div>
|
|
|
|
<div id="buff-bar"></div>
|
|
|
|
<div id="bottom-hud">
|
|
<div id="orb-life" class="orb" title="">
|
|
<div class="orb-fill life" id="life-fill"></div>
|
|
<div class="orb-gloss"></div>
|
|
<div class="orb-text" id="life-text">0/0</div>
|
|
</div>
|
|
<div id="center-hud">
|
|
<div id="xp-bar-wrap"><div id="xp-bar"></div><div id="xp-text"></div></div>
|
|
<div id="hotbar">
|
|
<div class="hotbar-group" id="hb-skills"></div>
|
|
<div class="hotbar-sep"></div>
|
|
<div class="hotbar-group" id="hb-potions"></div>
|
|
<div class="hotbar-sep"></div>
|
|
<div class="hotbar-group small" id="hb-menus"></div>
|
|
</div>
|
|
<div id="level-pill"><span id="lvl-num">1</span></div>
|
|
</div>
|
|
<div id="orb-mana" class="orb">
|
|
<div class="orb-fill mana" id="mana-fill"></div>
|
|
<div class="orb-gloss"></div>
|
|
<div class="orb-text" id="mana-text">0/0</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="toasts"></div>
|
|
<div id="boss-bar-wrap" class="hidden">
|
|
<div id="boss-name"></div>
|
|
<div id="boss-bar"><div id="boss-fill"></div></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ======== FLOATING PANELS ======== -->
|
|
<div id="panels"></div>
|
|
<div id="tooltip" class="hidden"></div>
|
|
<div id="drag-ghost" class="hidden"></div>
|
|
|
|
<!-- ======== FULL SCREENS ======== -->
|
|
<div id="screens">
|
|
<div id="screen-loading" class="screen">
|
|
<div class="loading-inner">
|
|
<h1 class="game-logo">DIABLO<span>2D</span></h1>
|
|
<div class="loading-sub">Shadows of Tristram</div>
|
|
<div class="loading-bar"><div id="loading-progress"></div></div>
|
|
<div id="loading-tip"></div>
|
|
</div>
|
|
</div>
|
|
<div id="screen-title" class="screen hidden"></div>
|
|
<div id="screen-classselect" class="screen hidden"></div>
|
|
<div id="screen-settings" class="screen hidden"></div>
|
|
<div id="screen-help" class="screen hidden"></div>
|
|
<div id="screen-death" class="screen hidden"></div>
|
|
<div id="screen-victory" class="screen hidden"></div>
|
|
</div>
|
|
|
|
<!-- ======== PAUSE OVERLAY ======== -->
|
|
<div id="pause-overlay" class="hidden">
|
|
<div class="pause-menu panel-gothic">
|
|
<h2 data-i18n="menu.paused">Paused</h2>
|
|
<button class="btn btn-primary" id="btn-resume" data-i18n="menu.resume">Resume</button>
|
|
<button class="btn" id="btn-pause-settings" data-i18n="menu.settings">Settings</button>
|
|
<button class="btn" id="btn-pause-help" data-i18n="menu.help">Help</button>
|
|
<button class="btn btn-danger" id="btn-save-exit" data-i18n="menu.saveexit">Save & Exit to Title</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Core -->
|
|
<script src="js/core/util.js"></script>
|
|
<script src="js/core/i18n.js"></script>
|
|
<script src="js/core/save.js"></script>
|
|
<script src="js/core/input.js"></script>
|
|
<script src="js/core/audio.js"></script>
|
|
<!-- Data -->
|
|
<script src="js/data/balance.js"></script>
|
|
<script src="js/data/items.js"></script>
|
|
<script src="js/data/monsters.js"></script>
|
|
<script src="js/data/skills.js"></script>
|
|
<!-- Simulation -->
|
|
<script src="js/game/path.js"></script>
|
|
<script src="js/game/fov.js"></script>
|
|
<script src="js/game/world.js"></script>
|
|
<script src="js/game/entities.js"></script>
|
|
<script src="js/game/ai.js"></script>
|
|
<script src="js/game/combat.js"></script>
|
|
<script src="js/game/loot.js"></script>
|
|
<script src="js/game/player.js"></script>
|
|
<!-- Presentation -->
|
|
<script src="js/render/sprites.js"></script>
|
|
<script src="js/render/render.js"></script>
|
|
<script src="js/ui/hud.js"></script>
|
|
<script src="js/ui/panels.js"></script>
|
|
<script src="js/ui/screens.js"></script>
|
|
<!-- State machine & bootstrap -->
|
|
<script src="js/game/game.js"></script>
|
|
<script src="js/main.js"></script>
|
|
</body>
|
|
</html>
|