Files
onlyscavs/templates/gun_detail.html
serversdwn 84768ae587 Add Loadout Planner and Quest Trees templates
- Created loadout.html for a comprehensive loadout planner, allowing users to filter and view gear options across various categories including guns, armor, helmets, headwear, backpacks, and rigs.
- Implemented a build builder feature to calculate total loadout weight and save builds.
- Added quests.html to display quest trees with trader dependencies, filtering options, and quest completion tracking.
2026-02-22 08:51:28 +00:00

320 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html>
<head>
<title>OnlyScavs {{ gun.name }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
:root {
--bg: #121212;
--panel: #1a1a1a;
--text: #eee;
--muted: #bbb;
--border: #333;
--accent: #9ccfff;
--amber: #ffd580;
--key-border: #5a7a3a;
--key-bg: #141e10;
}
body { font-family: sans-serif; background: var(--bg); color: var(--text); margin: 0; padding: 16px; }
.page { max-width: 900px; margin: 0 auto; }
nav { margin-bottom: 20px; }
nav a { color: var(--accent); font-size: 0.9rem; }
a { color: var(--accent); }
h1 { margin: 0 0 2px; font-size: 1.4rem; }
.subtitle { color: var(--muted); font-size: 0.9rem; margin: 0 0 20px; }
/* Gun summary card */
.gun-card {
display: flex;
gap: 16px;
align-items: flex-start;
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
padding: 16px;
margin-bottom: 24px;
}
.gun-card img { width: 96px; height: 96px; object-fit: contain; background: #222; border-radius: 6px; }
.gun-stats { display: flex; gap: 24px; flex-wrap: wrap; margin-top: 8px; }
.stat { display: flex; flex-direction: column; }
.stat .val { font-size: 1.1rem; font-weight: bold; color: var(--amber); }
.stat .lbl { font-size: 0.75rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.05em; }
.gun-name { flex: 1; }
.gun-name h2 { margin: 0 0 4px; font-size: 1.2rem; }
.gun-name .sub { color: var(--muted); font-size: 0.85rem; margin-bottom: 10px; }
/* Total bar */
.total-bar {
background: var(--panel);
border: 1px solid var(--border);
border-radius: 8px;
padding: 12px 20px;
margin-bottom: 24px;
display: flex;
align-items: baseline;
gap: 10px;
}
.total-bar .big { font-size: 1.6rem; font-weight: bold; color: var(--amber); }
.total-bar .lbl { color: var(--muted); font-size: 0.9rem; }
.total-bar .breakdown { color: var(--muted); font-size: 0.82rem; margin-left: auto; }
/* Section headers */
.section-hdr {
font-size: 0.78rem;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--muted);
padding: 10px 0 6px;
border-bottom: 1px solid var(--border);
margin-bottom: 8px;
}
/* Slot cards */
.slot-section { margin-bottom: 24px; }
.slot-card {
border: 1px solid var(--border);
border-radius: 8px;
margin-bottom: 10px;
overflow: hidden;
}
.slot-card.key-slot {
border-color: var(--key-border);
background: var(--key-bg);
}
.slot-header {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
cursor: pointer;
user-select: none;
background: rgba(255,255,255,0.03);
}
.slot-header:hover { background: rgba(255,255,255,0.06); }
.slot-header .slot-name { font-weight: bold; font-size: 0.9rem; flex: 1; }
.slot-header .slot-count { color: var(--muted); font-size: 0.8rem; }
.slot-header .slot-lightest { color: var(--amber); font-size: 0.85rem; white-space: nowrap; }
.slot-header .chevron { color: var(--muted); font-size: 0.8rem; transition: transform 0.15s; }
.slot-card.open .chevron { transform: rotate(90deg); }
.required-badge {
font-size: 0.7rem;
background: #2a2a2a;
border: 1px solid #555;
border-radius: 4px;
padding: 1px 5px;
color: var(--muted);
}
.key-badge {
font-size: 0.7rem;
background: #1a3010;
border: 1px solid var(--key-border);
border-radius: 4px;
padding: 1px 5px;
color: #8fc87f;
}
/* Mod list inside slot */
.mod-list { display: none; border-top: 1px solid var(--border); }
.slot-card.open .mod-list { display: block; }
.mod-row {
display: flex;
align-items: center;
gap: 10px;
padding: 6px 12px;
border-bottom: 1px solid #1a1a1a;
font-size: 0.85rem;
}
.mod-row:last-child { border-bottom: none; }
.mod-row:hover { background: rgba(255,255,255,0.03); }
.mod-row img { width: 36px; height: 36px; object-fit: contain; background: #222; border-radius: 4px; flex-shrink: 0; }
.mod-name { flex: 1; }
.mod-name small { display: block; color: var(--muted); font-size: 0.78rem; }
.mod-weight { font-weight: bold; color: var(--amber); white-space: nowrap; min-width: 60px; text-align: right; }
.mod-weight.lightest { color: #8fc87f; }
.mod-wiki { font-size: 0.78rem; color: var(--muted); }
.no-mods { padding: 10px 12px; color: var(--muted); font-size: 0.85rem; font-style: italic; }
/* Toggle other slots */
.toggle-other {
background: none;
border: 1px solid var(--border);
border-radius: 6px;
color: var(--muted);
padding: 5px 14px;
font-size: 0.85rem;
cursor: pointer;
margin-bottom: 12px;
}
.toggle-other:hover { border-color: var(--accent); color: var(--accent); }
#other-slots { display: none; }
#other-slots.visible { display: block; }
</style>
</head>
<body>
<div class="page">
<nav>
<a href="/loadout?tab=guns">← Back to Guns</a>
</nav>
<div class="gun-card">
{% if gun.grid_image_url %}
<img src="{{ gun.grid_image_url }}" alt="{{ gun.name }}">
{% endif %}
<div class="gun-name">
<h2>{{ gun.name }}</h2>
<div class="sub">
{{ gun.caliber or '?' }}
{% if gun.wiki_url %}&nbsp;<a href="{{ gun.wiki_url }}" target="_blank">wiki ↗</a>{% endif %}
</div>
<div class="gun-stats">
<div class="stat">
<span class="val">{{ "%.3f"|format(gun.weight_kg) if gun.weight_kg is not none else '?' }}</span>
<span class="lbl">Base weight (kg)</span>
</div>
{% if gun.ergonomics %}
<div class="stat">
<span class="val">{{ gun.ergonomics }}</span>
<span class="lbl">Ergonomics</span>
</div>
{% endif %}
{% if gun.recoil_vertical %}
<div class="stat">
<span class="val">{{ gun.recoil_vertical }}</span>
<span class="lbl">Recoil (V)</span>
</div>
{% endif %}
{% if gun.fire_rate %}
<div class="stat">
<span class="val">{{ gun.fire_rate }}</span>
<span class="lbl">Fire rate</span>
</div>
{% endif %}
</div>
</div>
</div>
<div class="total-bar">
<span class="lbl">Lightest possible build:</span>
<span class="big">{{ "%.3f"|format(lightest_total) }} kg</span>
<span class="breakdown">base {{ "%.3f"|format(gun.weight_kg or 0) }} kg + lightest mod per slot</span>
</div>
{% if key_slots %}
<div class="slot-section">
<div class="section-hdr">Key slots</div>
{% for slot in key_slots %}
{% set lightest = slot.mods[0] if slot.mods else none %}
<div class="slot-card key-slot {% if loop.first %}open{% endif %}" id="slot-{{ slot.slot_id }}">
<div class="slot-header" onclick="toggleSlot('slot-{{ slot.slot_id }}')">
<span class="slot-name">{{ slot.slot_name }}</span>
<span class="key-badge">key slot</span>
{% if slot.required %}<span class="required-badge">required</span>{% endif %}
<span class="slot-count">{{ slot.mods | length }} mods</span>
<span class="slot-lightest">
{% if lightest and lightest.weight_kg is not none %}
lightest {{ "%.3f"|format(lightest.weight_kg) }} kg
{% else %}—{% endif %}
</span>
<span class="chevron"></span>
</div>
<div class="mod-list">
{% if slot.mods %}
{% for mod in slot.mods %}
<div class="mod-row">
{% if mod.grid_image_url %}
<img src="{{ mod.grid_image_url }}" loading="lazy" alt="">
{% else %}
<div style="width:36px;height:36px;background:#222;border-radius:4px;flex-shrink:0"></div>
{% endif %}
<div class="mod-name">
{{ mod.mod_name }}
{% if mod.mod_short and mod.mod_short != mod.mod_name %}
<small>{{ mod.mod_short }}</small>
{% endif %}
</div>
{% if mod.wiki_url %}
<a class="mod-wiki" href="{{ mod.wiki_url }}" target="_blank">wiki</a>
{% endif %}
<span class="mod-weight {% if loop.first %}lightest{% endif %}">
{% if mod.weight_kg is not none %}{{ "%.3f"|format(mod.weight_kg) }} kg{% else %}—{% endif %}
</span>
</div>
{% endfor %}
{% else %}
<div class="no-mods">No compatible mods found in database.</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endif %}
{% if other_slots %}
<button class="toggle-other" onclick="toggleOther(this)">Show {{ other_slots | length }} other slots ▼</button>
<div id="other-slots">
<div class="slot-section">
<div class="section-hdr">All other slots</div>
{% for slot in other_slots %}
{% set lightest = slot.mods[0] if slot.mods else none %}
<div class="slot-card" id="slot-{{ slot.slot_id }}">
<div class="slot-header" onclick="toggleSlot('slot-{{ slot.slot_id }}')">
<span class="slot-name">{{ slot.slot_name }}</span>
{% if slot.required %}<span class="required-badge">required</span>{% endif %}
<span class="slot-count">{{ slot.mods | length }} mods</span>
<span class="slot-lightest">
{% if lightest and lightest.weight_kg is not none %}
lightest {{ "%.3f"|format(lightest.weight_kg) }} kg
{% else %}—{% endif %}
</span>
<span class="chevron"></span>
</div>
<div class="mod-list">
{% if slot.mods %}
{% for mod in slot.mods %}
<div class="mod-row">
{% if mod.grid_image_url %}
<img src="{{ mod.grid_image_url }}" loading="lazy" alt="">
{% else %}
<div style="width:36px;height:36px;background:#222;border-radius:4px;flex-shrink:0"></div>
{% endif %}
<div class="mod-name">
{{ mod.mod_name }}
{% if mod.mod_short and mod.mod_short != mod.mod_name %}
<small>{{ mod.mod_short }}</small>
{% endif %}
</div>
{% if mod.wiki_url %}
<a class="mod-wiki" href="{{ mod.wiki_url }}" target="_blank">wiki</a>
{% endif %}
<span class="mod-weight {% if loop.first %}lightest{% endif %}">
{% if mod.weight_kg is not none %}{{ "%.3f"|format(mod.weight_kg) }} kg{% else %}—{% endif %}
</span>
</div>
{% endfor %}
{% else %}
<div class="no-mods">No compatible mods found in database.</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
</div>
<script>
function toggleSlot(id) {
document.getElementById(id).classList.toggle('open');
}
function toggleOther(btn) {
const div = document.getElementById('other-slots');
div.classList.toggle('visible');
btn.textContent = div.classList.contains('visible')
? 'Hide other slots ▲'
: 'Show {{ other_slots | length }} other slots ▼';
}
</script>
</body>
</html>