Add Bonus Intel input for off-level intel sources (POIs etc.)

Players can pick up intel from points of interest on the map beyond what
levelling grants. Add a "Bonus Intel" card alongside the Character XP card
with an editable input. The character totals strip now shows the combined
intel (levels + bonus) with a small "+N" badge when a bonus is present.

Existing builds without the field migrate cleanly via the existing
defaults-merge in store.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vantz Stockwell 2026-05-23 07:55:00 -04:00
parent 99259e64bf
commit 6c7b4b8133
3 changed files with 52 additions and 3 deletions

View file

@ -120,6 +120,10 @@ const totalIntelAtLevel = computed(() => {
if (idx < 0) return 0;
return charXp.value.rows[idx]?.totalIntelPoints || 0;
});
// Intel total including bonus picked up off the map (POIs, etc.)
const totalIntelWithBonus = computed(
() => totalIntelAtLevel.value + (build.character.bonusIntel || 0),
);
// Skill points are a single global pool spent across all 5 trees.
const totalSpentAcrossClasses = computed(() =>
@ -300,7 +304,16 @@ const specMeta: Record<SpecId, { name: string; sym: string }> = {
</div>
<div class="total">
<div class="lbl">Intel Points</div>
<div class="val">{{ totalIntelAtLevel }}</div>
<div class="val">
{{ totalIntelWithBonus }}
<span
v-if="build.character.bonusIntel"
class="unit"
:title="`Includes +${build.character.bonusIntel} bonus`"
>
+{{ build.character.bonusIntel }}
</span>
</div>
</div>
</div>
@ -316,6 +329,37 @@ const specMeta: Record<SpecId, { name: string; sym: string }> = {
@update:level="(n) => (build.character.level = n)"
@update:xp-into="(n) => (build.character.xpInto = n)"
/>
<div class="card">
<div class="sym">INT</div>
<h3>Bonus Intel</h3>
<div class="row single">
<div class="field">
<label>From POIs &amp; other sources</label>
<input
type="number"
min="0"
:value="build.character.bonusIntel"
@input="(e) => (build.character.bonusIntel = Math.max(0, Math.floor(Number((e.target as HTMLInputElement).value) || 0)))"
/>
</div>
</div>
<div class="progress-meta" style="margin-top: 12px">
<span>From levels</span>
<span>{{ totalIntelAtLevel.toLocaleString('en-US') }}</span>
</div>
<div class="progress-meta" style="margin-top: 4px">
<span>Bonus</span>
<span>{{ (build.character.bonusIntel || 0).toLocaleString('en-US') }}</span>
</div>
<div
class="progress-meta"
style="margin-top: 4px; color: var(--sand)"
>
<span>Total</span>
<span>{{ totalIntelWithBonus.toLocaleString('en-US') }}</span>
</div>
</div>
</div>
</section>

View file

@ -15,7 +15,7 @@ export function defaultBuild(): BuildState {
v: 1,
house: 'atreides',
classId: 'swordmaster',
character: { level: 0, xpInto: 0 },
character: { level: 0, xpInto: 0, bonusIntel: 0 },
specs,
faction: { tier: 0, standingInto: 0 },
skills: {},

View file

@ -84,7 +84,12 @@ export interface BuildState {
// classId is just the currently viewed skill-tree tab — players allocate
// into all 5 trees from a single shared skill-point pool.
classId: ClassId;
character: { level: number; xpInto: number };
character: {
level: number;
xpInto: number;
// Extra intel points gained outside levelling (POIs on the map, etc.)
bonusIntel: number;
};
specs: Record<SpecId, SpecProgress>;
faction: { tier: number; standingInto: number };
// Allocated skill points keyed by full tag (e.g. Skills.Ability.BattleCry).