653 lines
18 KiB
HTML
653 lines
18 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<meta name="referrer" content="no-referrer" />
|
|
<title>暗黑破坏神 2 · 全职业技能加点模拟器 (Diablo II Skill Calculator v1.13c)</title>
|
|
<style>
|
|
:root {
|
|
color-scheme: dark;
|
|
--bg-void: #060504;
|
|
--bg-main: #0c0906;
|
|
--bg-panel: rgba(18, 14, 10, 0.97);
|
|
--bg-card: #15110c;
|
|
--border-dim: #2b2219;
|
|
--border-gold: #73572d;
|
|
--border-gold-glow: #c8a15a;
|
|
--border-gold-bright: #eecf87;
|
|
--gold-primary: #c8a15a;
|
|
--gold-bright: #eecf87;
|
|
--gold-light: #f5eedc;
|
|
--text-dim: #998772;
|
|
--text-muted: #6e5e4d;
|
|
--text-red: #ff4d4d;
|
|
--text-green: #55ff55;
|
|
--text-blue: #4880ff;
|
|
--text-orange: #ff9900;
|
|
--text-yellow: #ffff55;
|
|
--btn-bg: #1c1611;
|
|
--btn-hover: #33271c;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html, body {
|
|
margin: 0;
|
|
padding: 0;
|
|
height: 100vh;
|
|
background: var(--bg-void);
|
|
color: var(--gold-light);
|
|
font: 12px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
|
overflow: hidden;
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
}
|
|
|
|
/* Custom Scrollbars */
|
|
::-webkit-scrollbar { width: 8px; height: 8px; }
|
|
::-webkit-scrollbar-track { background: #0c0907; }
|
|
::-webkit-scrollbar-thumb { background: #2f251c; border-radius: 4px; border: 1px solid #4a3825; }
|
|
::-webkit-scrollbar-thumb:hover { background: #523f2f; }
|
|
|
|
/* Top Header */
|
|
header {
|
|
height: 50px;
|
|
background: linear-gradient(180deg, #1c140e 0%, #100b08 100%);
|
|
border-bottom: 2px solid var(--border-gold);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 16px;
|
|
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.7);
|
|
z-index: 100;
|
|
position: relative;
|
|
}
|
|
|
|
.logo-area {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
.logo-title {
|
|
font-family: 'Cinzel', 'Palatino Linotype', 'Book Antiqua', 'Georgia', serif;
|
|
font-size: 15px;
|
|
font-weight: 700;
|
|
color: var(--gold-bright);
|
|
letter-spacing: 1px;
|
|
text-shadow: 0 2px 4px #000;
|
|
}
|
|
.version-badge {
|
|
font-size: 10px;
|
|
padding: 1px 6px;
|
|
border-radius: 3px;
|
|
background: #251b12;
|
|
border: 1px solid var(--border-dim);
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
/* Class Selection Tabs */
|
|
.class-tabs {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
.class-btn {
|
|
background: #140f0b;
|
|
border: 1px solid var(--border-dim);
|
|
border-radius: 3px;
|
|
color: var(--text-dim);
|
|
padding: 6px 12px;
|
|
font-size: 12px;
|
|
font-family: inherit;
|
|
cursor: pointer;
|
|
transition: all 0.15s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.class-btn:hover {
|
|
background: #241b13;
|
|
color: var(--gold-bright);
|
|
border-color: var(--border-gold);
|
|
}
|
|
.class-btn.active {
|
|
background: linear-gradient(180deg, #38281a 0%, #20160e 100%);
|
|
color: var(--gold-bright);
|
|
border-color: var(--border-gold-glow);
|
|
box-shadow: 0 0 8px rgba(200, 161, 90, 0.35);
|
|
font-weight: bold;
|
|
}
|
|
|
|
.header-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.header-link {
|
|
color: var(--text-dim);
|
|
text-decoration: none;
|
|
font-size: 11px;
|
|
padding: 5px 8px;
|
|
border-radius: 3px;
|
|
border: 1px solid var(--border-dim);
|
|
background: #120e0a;
|
|
transition: all 0.15s;
|
|
}
|
|
.header-link:hover {
|
|
color: var(--gold-bright);
|
|
border-color: var(--border-gold);
|
|
}
|
|
.lang-btn {
|
|
background: #19120c;
|
|
border: 1px solid var(--border-gold);
|
|
color: var(--gold-bright);
|
|
border-radius: 3px;
|
|
padding: 5px 10px;
|
|
font-size: 11px;
|
|
cursor: pointer;
|
|
}
|
|
.lang-btn:hover {
|
|
background: #2b2014;
|
|
}
|
|
|
|
/* Stats & Summary Bar */
|
|
.stats-bar {
|
|
height: 44px;
|
|
background: #0f0b08;
|
|
border-bottom: 1px solid var(--border-dim);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 20px;
|
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
|
|
}
|
|
.stats-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
}
|
|
.stat-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
font-size: 12px;
|
|
}
|
|
.stat-label {
|
|
color: var(--text-dim);
|
|
}
|
|
.stat-val {
|
|
color: var(--gold-bright);
|
|
font-weight: bold;
|
|
}
|
|
.stat-val.warning {
|
|
color: var(--text-red);
|
|
}
|
|
.stepper-control {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
margin-left: 4px;
|
|
}
|
|
.stepper-btn {
|
|
width: 20px;
|
|
height: 20px;
|
|
border-radius: 3px;
|
|
border: 1px solid var(--border-dim);
|
|
background: #1b150f;
|
|
color: var(--gold-light);
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: bold;
|
|
padding: 0;
|
|
font-size: 12px;
|
|
line-height: 1;
|
|
}
|
|
.stepper-btn:hover {
|
|
background: #33261a;
|
|
border-color: var(--border-gold);
|
|
color: var(--gold-bright);
|
|
}
|
|
.stepper-val {
|
|
min-width: 24px;
|
|
text-align: center;
|
|
color: var(--text-blue);
|
|
font-weight: bold;
|
|
}
|
|
|
|
.stats-right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
.action-btn {
|
|
background: #19130d;
|
|
border: 1px solid var(--border-gold);
|
|
color: var(--gold-light);
|
|
padding: 5px 12px;
|
|
border-radius: 3px;
|
|
font-size: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.15s;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
}
|
|
.action-btn:hover {
|
|
background: #312316;
|
|
color: var(--gold-bright);
|
|
border-color: var(--border-gold-glow);
|
|
}
|
|
.action-btn.danger:hover {
|
|
background: #3d1414;
|
|
border-color: #8c2e2e;
|
|
color: #ff9999;
|
|
}
|
|
|
|
/* Main Viewport (Isolated Scroll Context) */
|
|
main.trees-viewport {
|
|
height: calc(100vh - 94px);
|
|
overflow-y: auto;
|
|
overflow-x: auto;
|
|
padding: 24px 16px 40px 16px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.trees-container {
|
|
display: flex;
|
|
gap: 20px;
|
|
justify-content: center;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
/* Individual Skill Tree Column (Matching Screenshot) */
|
|
.tree-column {
|
|
width: 260px;
|
|
background: #110d09;
|
|
border: 2px solid var(--border-gold);
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.8), inset 0 0 10px rgba(0, 0, 0, 0.7);
|
|
border-radius: 4px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.tree-header {
|
|
padding: 8px 10px;
|
|
background: linear-gradient(180deg, #201710 0%, #140e0a 100%);
|
|
border-bottom: 1px solid var(--border-dim);
|
|
text-align: center;
|
|
}
|
|
.tree-title {
|
|
font-family: 'Cinzel', 'Palatino Linotype', 'Book Antiqua', 'Georgia', serif;
|
|
font-size: 12.5px;
|
|
font-weight: bold;
|
|
color: var(--gold-bright);
|
|
letter-spacing: 1px;
|
|
text-transform: uppercase;
|
|
text-shadow: 0 2px 4px #000;
|
|
margin-bottom: 3px;
|
|
}
|
|
.tree-points-banner {
|
|
font-size: 10px;
|
|
color: var(--text-dim);
|
|
letter-spacing: 0.5px;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
/* Stone Tree Canvas (256x432) */
|
|
.tree-canvas {
|
|
width: 256px;
|
|
height: 432px;
|
|
position: relative;
|
|
background-color: #0c0907;
|
|
background-repeat: no-repeat;
|
|
background-position: 0 0;
|
|
background-size: 256px 432px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* Skill Socket */
|
|
.skill-socket {
|
|
position: absolute;
|
|
width: 48px;
|
|
height: 48px;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.skill-icon {
|
|
width: 48px;
|
|
height: 48px;
|
|
display: block;
|
|
image-rendering: pixelated;
|
|
cursor: pointer;
|
|
transition: transform 0.05s ease, filter 0.15s ease;
|
|
border-radius: 2px;
|
|
}
|
|
.skill-icon:active {
|
|
transform: scale(0.96);
|
|
}
|
|
|
|
/* Locked state */
|
|
.skill-socket.locked .skill-icon {
|
|
filter: grayscale(85%) brightness(0.5);
|
|
opacity: 0.65;
|
|
cursor: not-allowed;
|
|
}
|
|
.skill-socket.locked .skill-icon:active {
|
|
transform: none;
|
|
}
|
|
|
|
/* Active allocated state */
|
|
.skill-socket.active .skill-icon {
|
|
filter: drop-shadow(0 0 4px rgba(200, 161, 90, 0.4));
|
|
}
|
|
|
|
/* Maxed 20-point state */
|
|
.skill-socket.maxed .skill-icon {
|
|
filter: drop-shadow(0 0 6px rgba(238, 207, 135, 0.7));
|
|
}
|
|
|
|
/* Point Badge (Next to icon or bottom-right) */
|
|
.skill-pts-badge {
|
|
position: absolute;
|
|
width: 18px;
|
|
height: 18px;
|
|
background: #110d09;
|
|
border: 1px solid #4a3825;
|
|
box-shadow: inset 0 0 4px #000;
|
|
border-radius: 2px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 11px;
|
|
font-weight: bold;
|
|
color: var(--text-muted);
|
|
pointer-events: none;
|
|
}
|
|
.skill-pts-badge.has-points {
|
|
color: #ffffff;
|
|
background: #1c150e;
|
|
border-color: var(--border-gold);
|
|
text-shadow: 0 1px 2px #000;
|
|
}
|
|
.skill-pts-badge.has-soft-points {
|
|
color: var(--text-blue);
|
|
background: #141b24;
|
|
border-color: #385d8a;
|
|
text-shadow: 0 0 4px rgba(72, 128, 255, 0.5);
|
|
}
|
|
.skill-pts-badge.is-maxed {
|
|
color: var(--gold-bright);
|
|
border-color: var(--border-gold-glow);
|
|
text-shadow: 0 0 4px rgba(238, 207, 135, 0.6);
|
|
}
|
|
|
|
/* Tree Footer (Tree Soft Points) */
|
|
.tree-footer {
|
|
padding: 8px 10px;
|
|
background: #140e0a;
|
|
border-top: 1px solid var(--border-dim);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
font-size: 11px;
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
/* Floating Diablo II Tooltip */
|
|
#skill-tooltip {
|
|
position: fixed;
|
|
width: 320px;
|
|
max-width: 360px;
|
|
background: rgba(14, 10, 7, 0.97);
|
|
border: 2px solid var(--border-gold);
|
|
outline: 1px solid #2f2115;
|
|
outline-offset: -3px;
|
|
border-radius: 4px;
|
|
padding: 12px 14px;
|
|
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.95), inset 0 0 12px rgba(0, 0, 0, 0.8);
|
|
pointer-events: none;
|
|
z-index: 9999;
|
|
display: none;
|
|
font-size: 12px;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.tt-header {
|
|
margin-bottom: 8px;
|
|
border-bottom: 1px solid var(--border-dim);
|
|
padding-bottom: 6px;
|
|
}
|
|
.tt-title {
|
|
font-family: 'Cinzel', 'Palatino Linotype', 'Book Antiqua', 'Georgia', serif;
|
|
font-size: 15px;
|
|
font-weight: bold;
|
|
color: var(--gold-bright);
|
|
text-shadow: 0 2px 4px #000;
|
|
}
|
|
.tt-subtitle {
|
|
font-size: 11px;
|
|
color: var(--text-dim);
|
|
}
|
|
.tt-level-tag {
|
|
font-size: 12px;
|
|
color: var(--gold-light);
|
|
margin-top: 2px;
|
|
}
|
|
.tt-level-tag .soft-highlight {
|
|
color: var(--text-blue);
|
|
font-weight: bold;
|
|
}
|
|
|
|
.tt-section {
|
|
margin-bottom: 8px;
|
|
}
|
|
.tt-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 2px;
|
|
}
|
|
.tt-label {
|
|
color: var(--text-dim);
|
|
}
|
|
.tt-val {
|
|
color: var(--gold-light);
|
|
font-weight: 500;
|
|
}
|
|
.tt-val.err {
|
|
color: var(--text-red);
|
|
}
|
|
.tt-val.ok {
|
|
color: var(--text-green);
|
|
}
|
|
|
|
.tt-damage-box {
|
|
background: rgba(26, 18, 12, 0.6);
|
|
border: 1px solid var(--border-dim);
|
|
border-radius: 3px;
|
|
padding: 6px 8px;
|
|
margin: 6px 0;
|
|
}
|
|
.tt-damage-main {
|
|
font-size: 13.5px;
|
|
font-weight: bold;
|
|
color: var(--text-orange);
|
|
margin-bottom: 3px;
|
|
}
|
|
.tt-damage-sub {
|
|
font-size: 11px;
|
|
color: var(--text-dim);
|
|
}
|
|
|
|
.tt-effects-box {
|
|
background: rgba(16, 20, 32, 0.6);
|
|
border: 1px solid #2a3550;
|
|
border-radius: 3px;
|
|
padding: 6px 8px;
|
|
margin: 6px 0;
|
|
}
|
|
.tt-effect-line {
|
|
font-size: 12px;
|
|
color: #5588ee;
|
|
line-height: 1.45;
|
|
margin-bottom: 2px;
|
|
text-shadow: 0 1px 2px #000;
|
|
}
|
|
.tt-effect-line:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
.tt-next-level .tt-effect-line {
|
|
color: #4a77cc;
|
|
font-size: 11px;
|
|
}
|
|
|
|
.tt-synergies {
|
|
margin-top: 6px;
|
|
padding-top: 6px;
|
|
border-top: 1px dashed var(--border-dim);
|
|
}
|
|
.tt-syn-title {
|
|
font-size: 11px;
|
|
font-weight: bold;
|
|
color: var(--gold-primary);
|
|
margin-bottom: 3px;
|
|
}
|
|
.tt-syn-item {
|
|
font-size: 11px;
|
|
color: #b0a08e;
|
|
padding-left: 6px;
|
|
margin-bottom: 2px;
|
|
}
|
|
.tt-syn-item.active {
|
|
color: var(--text-green);
|
|
}
|
|
|
|
.tt-next-level {
|
|
margin-top: 8px;
|
|
padding-top: 6px;
|
|
border-top: 1px solid var(--border-dim);
|
|
color: var(--text-dim);
|
|
font-size: 11px;
|
|
}
|
|
.tt-next-title {
|
|
color: var(--gold-primary);
|
|
font-weight: bold;
|
|
margin-bottom: 2px;
|
|
}
|
|
|
|
.tt-desc {
|
|
margin-top: 8px;
|
|
padding-top: 6px;
|
|
border-top: 1px solid var(--border-dim);
|
|
font-size: 11px;
|
|
color: #a89885;
|
|
font-style: italic;
|
|
}
|
|
|
|
.tt-hint {
|
|
margin-top: 8px;
|
|
padding: 4px 6px;
|
|
background: #18120b;
|
|
border-radius: 2px;
|
|
font-size: 10px;
|
|
color: var(--gold-dim);
|
|
text-align: center;
|
|
}
|
|
|
|
/* Toast Notification */
|
|
#toast {
|
|
position: fixed;
|
|
bottom: 24px;
|
|
left: 50%;
|
|
transform: translateX(-50%) translateY(100px);
|
|
background: #1c150e;
|
|
border: 1px solid var(--border-gold-glow);
|
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.8);
|
|
color: var(--gold-bright);
|
|
padding: 8px 18px;
|
|
border-radius: 4px;
|
|
font-size: 13px;
|
|
pointer-events: none;
|
|
transition: transform 0.25s ease, opacity 0.25s ease;
|
|
opacity: 0;
|
|
z-index: 10000;
|
|
}
|
|
#toast.show {
|
|
transform: translateX(-50%) translateY(0);
|
|
opacity: 1;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<div class="logo-area">
|
|
<span class="logo-title" id="txt-app-title">暗黑破坏神 2 · 技能加点模拟器</span>
|
|
<span class="version-badge">v1.13c</span>
|
|
</div>
|
|
|
|
<nav class="class-tabs" id="class-tabs-container">
|
|
<!-- Injected via JS -->
|
|
</nav>
|
|
|
|
<div class="header-actions">
|
|
<a href="./loot.html" class="header-link" id="lnk-loot">战利品模拟</a>
|
|
<a href="./boss.html" class="header-link" id="lnk-boss">首领挑战</a>
|
|
<a href="./acts.html" class="header-link" id="lnk-acts">大地图</a>
|
|
<button class="lang-btn" id="btn-lang" title="Toggle Language">中 / EN</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="stats-bar">
|
|
<div class="stats-left">
|
|
<div class="stat-item">
|
|
<span class="stat-label" id="lbl-req-level">需求角色等级:</span>
|
|
<span class="stat-val" id="val-req-level">1</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-label" id="lbl-points-spent">已用技能点:</span>
|
|
<span class="stat-val" id="val-points-spent">0 / 110</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-label" id="lbl-points-remain">剩余技能点:</span>
|
|
<span class="stat-val" id="val-points-remain">110</span>
|
|
</div>
|
|
<div class="stat-item">
|
|
<span class="stat-label" id="lbl-all-skills">+ 全部技能:</span>
|
|
<div class="stepper-control">
|
|
<button class="stepper-btn" id="btn-all-skills-dec">-</button>
|
|
<span class="stepper-val" id="val-all-skills">0</span>
|
|
<button class="stepper-btn" id="btn-all-skills-inc">+</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="stats-right">
|
|
<button class="action-btn danger" id="btn-respec">重置配点 (Respec)</button>
|
|
<button class="action-btn" id="btn-copy-link">复制配点链接 (Share)</button>
|
|
</div>
|
|
</div>
|
|
|
|
<main class="trees-viewport">
|
|
<div class="trees-container" id="trees-container">
|
|
<!-- 3 Skill Tree Panels Injected Here -->
|
|
</div>
|
|
</main>
|
|
|
|
<!-- Tooltip Element -->
|
|
<div id="skill-tooltip"></div>
|
|
|
|
<!-- Toast Notification -->
|
|
<div id="toast">已复制配点链接到剪贴板!</div>
|
|
|
|
<script type="module" src="/src/skills.ts"></script>
|
|
</body>
|
|
</html>
|