minor optimizations and weapon sim

This commit is contained in:
Kamal Tufekcic 2026-07-07 20:23:39 +03:00
commit fc7887ce11
10 changed files with 419 additions and 11 deletions

View file

@ -83,6 +83,12 @@ else
</figure>
}
<div class="notice err" id="sim-drift" hidden>
The simulator's local math no longer matches the server-computed curves (site/mod version drift).
The charts and key points shown are still server truth, but <strong>edited-knob results may be inaccurate</strong>
until the site is updated. Details in the browser console.
</div>
<h2 id="sim">Simulator</h2>
<p class="small muted">
Seeded from the live server config. Edit anything — player state, stat levels, card picks, handicap knobs —
@ -205,13 +211,83 @@ else
</table>
</div>
<p class="muted small">
Weapon-by-weapon time-to-kill tables and per-weapon damage simulation are planned on top of this.
<script type="application/json" id="sim-data">@Html.Raw(Model.SimJson)</script>
}
<h2 id="weapons">Weapons — shots to kill</h2>
@if (Model.Weap is null)
{
<div class="notice">Weapon data hasn't been generated on this host yet (deploy-web/extract-weapons.sh).</div>
}
else
{
<p>
Vanilla CS2 bullet math, computed from numbers extracted out of the <strong>installed game's own files</strong>
(re-extracted on every Valve update — never hand-copied). Shots to kill a <strong>100 HP</strong> target per
hitgroup, with distance falloff, per-weapon armor penetration and the per-weapon headshot multipliers
(the Deagle's ×3.9 and M4A1-S's ×3.475 included). Tick <em>apply my build &amp; handicap</em> to layer your
simulated player from above onto the same math.
</p>
<script type="application/json" id="sim-data">@Html.Raw(Model.SimJson)</script>
<div class="notice err" id="wpn-drift" hidden>
This table's local math no longer matches the server-computed values (site version drift). The numbers shown
are still server truth, but <strong>the controls below may compute inaccurate results</strong> until the site
is updated. Details in the browser console.
</div>
<div class="sim">
<fieldset>
<legend>Target &amp; range</legend>
<div class="fields">
<label>Distance <input type="range" id="wpn-dist" min="0" max="3000" step="25" value="0" autocomplete="off" /> <b id="wpn-distv">0 u</b></label>
<label>Kevlar + helmet <input type="checkbox" id="wpn-armor" checked autocomplete="off" /></label>
<label title="Out × and HS × from the simulator above, versus a bot (100 HP, assault suit — always armored). Crits and abilities stay excluded.">
Apply my build &amp; handicap <input type="checkbox" id="wpn-mod" autocomplete="off" />
</label>
</div>
<p class="muted small">500 units ≈ one falloff step · a &mdash; cell means the weapon's bullets don't reach that distance at all (shotguns cut off earliest) · AWP mid ≈ 1500&ndash;2500 units.</p>
</fieldset>
</div>
<div class="tablewrap">
<table id="wpn-table">
<tr>
<th>Weapon</th>
<th class="num" title="damage per shot into the chest at the chosen distance/armor">Body dmg</th>
<th class="num">Head</th><th class="num">Chest</th><th class="num">Stomach</th><th class="num">Legs</th>
<th class="num" title="(shots 1) × cycle time, chest — the first shot lands at t = 0">TTK</th>
</tr>
@foreach (var (label, rows) in Model.WeaponGroups())
{
<tr class="wcat"><th colspan="7">@label</th></tr>
foreach (var w in rows)
{
var shot = WeaponMath.Hitgroups.Select(hg => WeaponMath.Shot(w, 0, hg, true)).ToArray();
<tr data-wid="@w.Id">
<td>@Html.Raw(Model.IconFor(w))@w.Name @(w.Pellets > 1 ? Html.Raw($"<span class=\"muted small\">&times;{w.Pellets}</span>") : Html.Raw(""))</td>
<td class="num" data-c="dmg">@shot[1]</td>
<td class="num" data-c="head">@TheoryModel.StkStr(shot[0])</td>
<td class="num" data-c="chest">@TheoryModel.StkStr(shot[1])</td>
<td class="num" data-c="stomach">@TheoryModel.StkStr(shot[2])</td>
<td class="num" data-c="legs">@TheoryModel.StkStr(shot[3])</td>
<td class="num" data-c="ttk">@TheoryModel.TtkStr(w, shot[1])</td>
</tr>
}
}
</table>
</div>
<p class="muted small">
From CS2 build @Model.Weap.GameVersion (extracted @(Model.Weap.GeneratedAt is { Length: >= 10 } g ? g[..10] : Model.Weap.GeneratedAt)).
&ldquo;Kevlar + helmet&rdquo; armors every hitgroup except legs — legs never take armor reduction.
Shotgun rows (&times;pellets) assume every pellet lands in the same hitgroup.
Damage is truncated per pellet, exactly like the engine does it.
</p>
<script type="application/json" id="weapons-data">@Html.Raw(Model.WeaponsJson)</script>
}
@section Scripts {
<script src="/js/theory.js" defer></script>
<script src="/js/weapons.js" defer></script>
}