feat: Added new injector chart page.

This commit is contained in:
serversdwn
2026-03-01 21:49:32 +00:00
parent 394c7ebde7
commit 4893f3deee
6 changed files with 783 additions and 1 deletions

574
templates/meds.html Normal file
View File

@@ -0,0 +1,574 @@
<!doctype html>
<html>
<head>
<title>OnlyScavs Injector Reference</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
:root {
--bg: #121212;
--panel: #1a1a1a;
--panel2: #1e1e1e;
--text: #eee;
--muted: #888;
--border: #2a2a2a;
--accent: #9ccfff;
--good: #6ec96e;
--bad: #e06060;
--warn: #e0a040;
--neutral: #aaa;
--heal: #5db8a0;
--stam: #6abfdb;
--skill: #a58cf0;
--special: #c8a850;
}
* { box-sizing: border-box; }
body {
font-family: sans-serif;
background: var(--bg);
color: var(--text);
margin: 0;
padding: 16px;
}
.page { max-width: 1200px; margin: 0 auto; }
/* ── Nav ── */
nav {
display: flex;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 24px;
font-size: 0.88rem;
}
nav a {
color: var(--muted);
text-decoration: none;
padding: 4px 10px;
border: 1px solid var(--border);
border-radius: 4px;
}
nav a:hover { color: var(--accent); border-color: var(--accent); }
nav a.active { color: var(--accent); border-color: var(--accent); background: #1a2533; }
h1 { font-size: 1.4rem; margin: 0 0 4px; }
.subtitle { color: var(--muted); font-size: 0.88rem; margin: 0 0 28px; }
/* ── Section headings ── */
.section-head {
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--muted);
border-bottom: 1px solid var(--border);
padding-bottom: 6px;
margin: 32px 0 16px;
}
/* ════════════════════════════════════
SITUATION GUIDE
════════════════════════════════════ */
.sit-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 12px;
}
.sit-card {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
padding: 14px 16px;
}
.sit-label {
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 6px;
}
.sit-label span.icon { font-size: 1rem; }
.sit-item {
display: flex;
align-items: baseline;
gap: 8px;
padding: 5px 0;
border-bottom: 1px solid var(--border);
font-size: 0.85rem;
}
.sit-item:last-child { border-bottom: none; }
.sit-name {
font-weight: 600;
min-width: 90px;
color: var(--accent);
white-space: nowrap;
}
.sit-desc { color: var(--muted); font-size: 0.8rem; flex: 1; }
.sit-warn { color: var(--bad); font-size: 0.75rem; white-space: nowrap; }
/* ════════════════════════════════════
COMPARISON GRID
════════════════════════════════════ */
.grid-wrap {
overflow-x: auto;
border: 1px solid var(--border);
border-radius: 8px;
}
table.comp {
border-collapse: collapse;
width: 100%;
min-width: 900px;
font-size: 0.82rem;
}
table.comp thead th {
background: var(--panel2);
padding: 10px 8px;
text-align: center;
border-right: 1px solid var(--border);
border-bottom: 2px solid var(--border);
font-size: 0.75rem;
white-space: nowrap;
}
table.comp thead th:first-child {
text-align: left;
padding-left: 14px;
min-width: 160px;
background: #151515;
}
table.comp thead .th-icon {
display: block;
margin: 0 auto 4px;
width: 32px;
height: 32px;
object-fit: contain;
}
table.comp thead .th-name {
display: block;
font-weight: 700;
color: var(--accent);
}
table.comp thead .th-short {
display: block;
color: var(--muted);
font-size: 0.7rem;
}
table.comp tbody tr { border-bottom: 1px solid var(--border); }
table.comp tbody tr:last-child { border-bottom: none; }
table.comp tbody tr:hover { background: rgba(255,255,255,0.03); }
table.comp tbody td {
padding: 7px 8px;
text-align: center;
border-right: 1px solid var(--border);
vertical-align: middle;
}
table.comp tbody td:first-child {
text-align: left;
padding-left: 14px;
color: var(--muted);
font-size: 0.78rem;
font-weight: 600;
background: #151515;
white-space: nowrap;
}
table.comp tbody tr.row-group td:first-child {
font-size: 0.68rem;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #555;
padding-top: 10px;
padding-bottom: 4px;
border-bottom: none;
background: #111;
}
table.comp tbody tr.row-group td {
background: #111;
border-bottom: none;
}
/* value cells */
.v-good { color: var(--good); font-weight: 600; }
.v-bad { color: var(--bad); }
.v-warn { color: var(--warn); }
.v-none { color: #383838; }
.v-heal { color: var(--heal); font-weight: 600; }
.v-stam { color: var(--stam); font-weight: 600; }
.v-skill { color: var(--skill); }
.v-special { color: var(--special); }
/* check / cross / dash symbols */
.sym-check { color: var(--good); font-size: 1rem; }
.sym-x { color: var(--bad); font-size: 1rem; }
.sym-dash { color: #333; }
/* duration pill */
.dur {
display: inline-block;
background: #252525;
border-radius: 3px;
padding: 1px 5px;
font-size: 0.72rem;
color: var(--muted);
}
.dur-long { background: #1e2a1e; color: var(--good); }
.dur-med { background: #252020; color: var(--warn); }
.dur-short { background: #2a1818; color: var(--bad); }
/* wiki link in header */
table.comp thead th a {
color: var(--muted);
font-size: 0.65rem;
text-decoration: none;
display: block;
}
table.comp thead th a:hover { color: var(--accent); }
/* ── filter tabs ── */
.filter-bar {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-bottom: 12px;
}
.filter-btn {
background: var(--panel);
border: 1px solid var(--border);
color: var(--muted);
border-radius: 4px;
padding: 4px 12px;
font-size: 0.78rem;
cursor: pointer;
}
.filter-btn:hover { color: var(--text); border-color: #555; }
.filter-btn.active { color: var(--accent); border-color: var(--accent); background: #1a2533; }
</style>
</head>
<body>
<div class="page">
<nav>
<a href="/">Key Ratings</a>
<a href="/quests">Quest Tree</a>
<a href="/collector">Collector</a>
<a href="/loadout">Loadout</a>
<a href="/meds" class="active">Injectors</a>
</nav>
<h1>Injector Quick Reference</h1>
<p class="subtitle">All stim injectors — situation guide + full effect comparison</p>
<!-- ══════════════════════════════════
SITUATION GUIDE
══════════════════════════════════ -->
<div class="section-head">Situation Guide — what to grab when</div>
<div class="sit-grid">
<div class="sit-card">
<div class="sit-label" style="color: var(--heal)"><span class="icon">🩸</span> Bleeding / Wound</div>
{% for inj in situations.bleed %}
<div class="sit-item">
<span class="sit-name">{{ inj.short }}</span>
<span class="sit-desc">{{ inj.desc }}</span>
{% if inj.warn %}<span class="sit-warn">⚠ {{ inj.warn }}</span>{% endif %}
</div>
{% endfor %}
</div>
<div class="sit-card">
<div class="sit-label" style="color: var(--heal)"><span class="icon">❤️</span> HP Regen</div>
{% for inj in situations.regen %}
<div class="sit-item">
<span class="sit-name">{{ inj.short }}</span>
<span class="sit-desc">{{ inj.desc }}</span>
{% if inj.warn %}<span class="sit-warn">⚠ {{ inj.warn }}</span>{% endif %}
</div>
{% endfor %}
</div>
<div class="sit-card">
<div class="sit-label" style="color: var(--stam)"><span class="icon"></span> Stamina / Speed</div>
{% for inj in situations.stam %}
<div class="sit-item">
<span class="sit-name">{{ inj.short }}</span>
<span class="sit-desc">{{ inj.desc }}</span>
{% if inj.warn %}<span class="sit-warn">⚠ {{ inj.warn }}</span>{% endif %}
</div>
{% endfor %}
</div>
<div class="sit-card">
<div class="sit-label" style="color: var(--skill)"><span class="icon">💪</span> Skill Boosts</div>
{% for inj in situations.skill %}
<div class="sit-item">
<span class="sit-name">{{ inj.short }}</span>
<span class="sit-desc">{{ inj.desc }}</span>
{% if inj.warn %}<span class="sit-warn">⚠ {{ inj.warn }}</span>{% endif %}
</div>
{% endfor %}
</div>
<div class="sit-card">
<div class="sit-label" style="color: var(--special)"><span class="icon">🌡️</span> Temperature / Special</div>
{% for inj in situations.special %}
<div class="sit-item">
<span class="sit-name">{{ inj.short }}</span>
<span class="sit-desc">{{ inj.desc }}</span>
{% if inj.warn %}<span class="sit-warn">⚠ {{ inj.warn }}</span>{% endif %}
</div>
{% endfor %}
</div>
<div class="sit-card">
<div class="sit-label" style="color: var(--bad)"><span class="icon">☠️</span> High Risk / Gamble</div>
{% for inj in situations.risky %}
<div class="sit-item">
<span class="sit-name">{{ inj.short }}</span>
<span class="sit-desc">{{ inj.desc }}</span>
{% if inj.warn %}<span class="sit-warn">⚠ {{ inj.warn }}</span>{% endif %}
</div>
{% endfor %}
</div>
</div>
<!-- ══════════════════════════════════
COMPARISON GRID
══════════════════════════════════ -->
<div class="section-head" style="margin-top:40px">Full Comparison Grid</div>
<div class="filter-bar" id="filterBar">
<button class="filter-btn active" data-filter="all">All</button>
<button class="filter-btn" data-filter="heal">Healing</button>
<button class="filter-btn" data-filter="stam">Stamina</button>
<button class="filter-btn" data-filter="skill">Skill</button>
<button class="filter-btn" data-filter="special">Special</button>
</div>
<div class="grid-wrap">
<table class="comp" id="compTable">
<thead>
<tr>
<th>Effect</th>
{% for inj in injectors %}
<th data-tags="{{ inj.tags }}">
{% if inj.icon %}<img class="th-icon" src="{{ inj.icon }}" alt="" onerror="this.style.display='none'">{% endif %}
<span class="th-name">{{ inj.short }}</span>
{% if inj.wiki %}<a href="{{ inj.wiki }}" target="_blank">wiki ↗</a>{% endif %}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
<!-- HP REGENERATION -->
<tr class="row-group">
<td>Healing</td>
{% for inj in injectors %}<td></td>{% endfor %}
</tr>
<tr>
<td>HP regen /s</td>
{% for inj in injectors %}
<td>
{% if inj.hp_regen %}
<span class="v-heal">+{{ inj.hp_regen }}</span>
<span class="dur {% if inj.hp_regen_dur >= 300 %}dur-long{% elif inj.hp_regen_dur >= 60 %}dur-med{% else %}dur-short{% endif %}">{{ inj.hp_regen_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>Stops bleeding</td>
{% for inj in injectors %}
<td>
{% if inj.stops_bleed %}<span class="sym-check"></span>{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>Antidote</td>
{% for inj in injectors %}
<td>
{% if inj.antidote %}<span class="sym-check"></span>{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<!-- STAMINA -->
<tr class="row-group">
<td>Stamina</td>
{% for inj in injectors %}<td></td>{% endfor %}
</tr>
<tr>
<td>Max stamina</td>
{% for inj in injectors %}
<td>
{% if inj.max_stam %}
<span class="{% if inj.max_stam > 0 %}v-stam{% else %}v-bad{% endif %}">
{{ '+' if inj.max_stam > 0 else '' }}{{ inj.max_stam }}
</span>
<span class="dur">{{ inj.max_stam_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>Stam recovery /s</td>
{% for inj in injectors %}
<td>
{% if inj.stam_rec %}
<span class="{% if inj.stam_rec > 0 %}v-stam{% else %}v-bad{% endif %}">
{{ '+' if inj.stam_rec > 0 else '' }}{{ inj.stam_rec }}
</span>
<span class="dur">{{ inj.stam_rec_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>Weight limit</td>
{% for inj in injectors %}
<td>
{% if inj.weight %}
<span class="{% if inj.weight > 0 %}v-good{% else %}v-bad{% endif %}">
{{ '+' if inj.weight > 0 else '' }}{{ (inj.weight * 100)|int }}%
</span>
<span class="dur">{{ inj.weight_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<!-- SKILLS -->
<tr class="row-group">
<td>Skill Buffs</td>
{% for inj in injectors %}<td></td>{% endfor %}
</tr>
{% for skill_name in skill_rows %}
<tr>
<td>{{ skill_name }}</td>
{% for inj in injectors %}
<td>
{% set val = inj.skills.get(skill_name) %}
{% if val %}
<span class="{% if val.value > 0 %}v-skill{% else %}v-bad{% endif %}">
{{ '+' if val.value > 0 else '' }}{{ val.value }}
</span>
<span class="dur">{{ val.duration }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
<!-- SPECIAL -->
<tr class="row-group">
<td>Special</td>
{% for inj in injectors %}<td></td>{% endfor %}
</tr>
<tr>
<td>Body temp Δ</td>
{% for inj in injectors %}
<td>
{% if inj.body_temp %}
<span class="{% if inj.body_temp > 0 %}v-bad{% else %}v-good{% endif %}">
{{ '+' if inj.body_temp > 0 else '' }}{{ inj.body_temp }}°
</span>
<span class="dur">{{ inj.body_temp_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>Energy Δ /s</td>
{% for inj in injectors %}
<td>
{% if inj.energy %}
<span class="{% if inj.energy > 0 %}v-good{% else %}v-bad{% endif %}">
{{ '+' if inj.energy > 0 else '' }}{{ inj.energy }}
</span>
<span class="dur">{{ inj.energy_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>Hydration Δ /s</td>
{% for inj in injectors %}
<td>
{% if inj.hydration %}
<span class="{% if inj.hydration > 0 %}v-good{% else %}v-bad{% endif %}">
{{ '+' if inj.hydration > 0 else '' }}{{ inj.hydration }}
</span>
<span class="dur">{{ inj.hydration_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<!-- SIDE EFFECTS -->
<tr class="row-group">
<td>Side Effects</td>
{% for inj in injectors %}<td></td>{% endfor %}
</tr>
<tr>
<td>Tremors</td>
{% for inj in injectors %}
<td>
{% if inj.tremor %}
<span class="v-bad"></span>
<span class="dur dur-short">{{ inj.tremor_delay }}s delay · {{ inj.tremor_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>Tunnel vision</td>
{% for inj in injectors %}
<td>
{% if inj.tunnel %}
<span class="v-bad"></span>
<span class="dur dur-short">{{ inj.tunnel_delay }}s delay · {{ inj.tunnel_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
<tr>
<td>Pain</td>
{% for inj in injectors %}
<td>
{% if inj.pain %}
<span class="v-bad"></span>
<span class="dur dur-short">{{ inj.pain_delay }}s delay · {{ inj.pain_dur }}s</span>
{% else %}<span class="sym-dash"></span>{% endif %}
</td>
{% endfor %}
</tr>
</tbody>
</table>
</div><!-- /grid-wrap -->
</div><!-- /page -->
<script>
// Filter columns by tag
document.getElementById("filterBar").addEventListener("click", function(e) {
const btn = e.target.closest(".filter-btn");
if (!btn) return;
document.querySelectorAll(".filter-btn").forEach(b => b.classList.remove("active"));
btn.classList.add("active");
const filter = btn.dataset.filter;
const table = document.getElementById("compTable");
const headers = table.querySelectorAll("thead th");
headers.forEach((th, i) => {
if (i === 0) return; // label col
const tags = (th.dataset.tags || "").split(",");
const show = filter === "all" || tags.includes(filter);
// toggle all cells in column i
table.querySelectorAll("tr").forEach(tr => {
const cells = tr.children;
if (cells[i]) cells[i].style.display = show ? "" : "none";
});
});
});
</script>
</body>
</html>