Critical tables page

This commit is contained in:
2026-03-14 12:38:19 +01:00
parent b399840671
commit e4e8995fd8
10 changed files with 828 additions and 103 deletions

View File

@@ -0,0 +1,74 @@
@using System
@using System.Collections.Generic
@using System.Diagnostics.CodeAnalysis
@using RolemasterDb.App.Domain
@using RolemasterDb.App.Features
@if (EffectiveEffects.Count > 0)
{
<div class="affix-badge-list">
@foreach (var effect in EffectiveEffects)
{
if (TryRenderEffect(effect, out var info, out var valueText))
{
<span class="affix-badge" title="@info.Tooltip">
<span class="affix-badge-symbol">@info.Symbol</span>
@if (!string.IsNullOrWhiteSpace(valueText))
{
<span class="affix-badge-value">@valueText</span>
}
</span>
}
else
{
<span class="affix-badge affix-badge-fallback" title="@effect.EffectCode">
@FormatFallback(effect)
</span>
}
}
</div>
}
@code {
[Parameter]
public IReadOnlyList<CriticalEffectLookupResponse>? Effects { get; set; }
private IReadOnlyList<CriticalEffectLookupResponse> EffectiveEffects =>
Effects ?? Array.Empty<CriticalEffectLookupResponse>();
private static bool TryRenderEffect(
CriticalEffectLookupResponse effect,
[NotNullWhen(true)] out AffixDisplayInfo? info,
out string valueText)
{
if (!AffixDisplayMap.TryGet(effect.EffectCode, out info))
{
valueText = string.Empty;
return false;
}
valueText = FormatAffixValue(effect);
return true;
}
private static string FormatAffixValue(CriticalEffectLookupResponse effect) =>
effect.EffectCode switch
{
CriticalEffectCodes.StunnedRounds
or CriticalEffectCodes.MustParryRounds
or CriticalEffectCodes.NoParryRounds => effect.DurationRounds?.ToString() ?? string.Empty,
CriticalEffectCodes.BleedPerRound => effect.PerRound?.ToString() ?? string.Empty,
CriticalEffectCodes.DirectHits => effect.ValueInteger?.ToString() ?? string.Empty,
CriticalEffectCodes.FoePenalty
or CriticalEffectCodes.AttackerBonusNextRound => effect.Modifier?.ToString() ?? string.Empty,
CriticalEffectCodes.PowerPointModifier => effect.ValueExpression ?? string.Empty,
_ => effect.ValueInteger?.ToString()
?? effect.Modifier?.ToString()
?? effect.ValueExpression
?? effect.SourceText
?? string.Empty
};
private static string FormatFallback(CriticalEffectLookupResponse effect) =>
effect.SourceText ?? effect.EffectCode;
}

View File

@@ -0,0 +1,41 @@
@using System.Collections.Generic
@using RolemasterDb.App.Features
<div class="critical-cell">
@if (!string.IsNullOrWhiteSpace(Description))
{
<p class="critical-cell-description">@Description</p>
}
<AffixBadgeList Effects="Effects" />
@if (Branches?.Count > 0)
{
<div class="critical-branch-stack">
@foreach (var branch in Branches)
{
<div class="critical-branch-card">
<span class="critical-branch-condition">
@branch.ConditionText
</span>
@if (!string.IsNullOrWhiteSpace(branch.Description))
{
<p class="critical-branch-description">@branch.Description</p>
}
<AffixBadgeList Effects="branch.Effects" />
</div>
}
</div>
}
</div>
@code {
[Parameter, EditorRequired]
public string Description { get; set; } = string.Empty;
[Parameter]
public IReadOnlyList<CriticalEffectLookupResponse>? Effects { get; set; }
[Parameter]
public IReadOnlyList<CriticalBranchLookupResponse>? Branches { get; set; }
}

View File

@@ -42,93 +42,13 @@
<p class="muted">@Result.TableNotes</p>
}
<p><strong>@Result.Description</strong></p>
@if (!string.IsNullOrWhiteSpace(Result.AffixText))
{
<div class="callout">
<h4>Affix Text</h4>
<p class="stacked-copy">@Result.AffixText</p>
@if (Result.Effects.Count > 0)
{
<div class="effect-stack">
<h5>Parsed Affixes</h5>
<ul class="effect-list">
@foreach (var effect in Result.Effects)
{
<li class="effect-item">
@if (!string.IsNullOrWhiteSpace(effect.SourceText))
{
<code class="effect-token">@effect.SourceText</code>
}
<span>@FormatEffect(effect)</span>
</li>
}
</ul>
</div>
}
</div>
}
else if (Result.Effects.Count > 0)
{
<div class="callout">
<h4>Parsed Affixes</h4>
<ul class="effect-list">
@foreach (var effect in Result.Effects)
{
<li class="effect-item">
@if (!string.IsNullOrWhiteSpace(effect.SourceText))
{
<code class="effect-token">@effect.SourceText</code>
}
<span>@FormatEffect(effect)</span>
</li>
}
</ul>
</div>
}
@if (Result.Branches.Count > 0)
{
<div class="callout">
<h4>Conditional Branches</h4>
<div class="branch-list">
@foreach (var branch in Result.Branches)
{
<section class="branch-card">
<div class="branch-condition">@branch.ConditionText</div>
@if (!string.IsNullOrWhiteSpace(branch.Description))
{
<p class="branch-copy">@branch.Description</p>
}
@if (!string.IsNullOrWhiteSpace(branch.AffixText))
{
<p class="stacked-copy branch-affix">@branch.AffixText</p>
}
@if (branch.Effects.Count > 0)
{
<ul class="effect-list branch-effects">
@foreach (var effect in branch.Effects)
{
<li class="effect-item">
@if (!string.IsNullOrWhiteSpace(effect.SourceText))
{
<code class="effect-token">@effect.SourceText</code>
}
<span>@FormatEffect(effect)</span>
</li>
}
</ul>
}
</section>
}
</div>
</div>
}
<div class="callout">
<h4>Cell details</h4>
<CompactCriticalCell
Description="@Result.Description"
Effects="@Result.Effects"
Branches="@Result.Branches" />
</div>
<details class="details-block">
<summary>Raw Imported Cell</summary>
@@ -170,20 +90,4 @@
}
}
private static string FormatEffect(CriticalEffectLookupResponse effect) =>
effect.EffectCode switch
{
"direct_hits" when effect.ValueInteger is not null => $"{effect.ValueInteger} direct hits",
"must_parry_rounds" when effect.DurationRounds is not null => $"Must parry for {FormatRounds(effect.DurationRounds.Value)}",
"no_parry_rounds" when effect.DurationRounds is not null => $"No parry for {FormatRounds(effect.DurationRounds.Value)}",
"stunned_rounds" when effect.DurationRounds is not null => $"Stunned for {FormatRounds(effect.DurationRounds.Value)}",
"bleed_per_round" when effect.PerRound is not null => $"Bleeds {effect.PerRound} hits per round",
"foe_penalty" when effect.Modifier is not null => $"Foe penalty {effect.Modifier:+#;-#;0}",
"attacker_bonus_next_round" when effect.Modifier is not null => $"Attacker bonus next round {effect.Modifier:+#;-#;0}",
"power_point_modifier" when !string.IsNullOrWhiteSpace(effect.ValueExpression) => $"Foe power-point modifier {effect.ValueExpression}",
_ => effect.EffectCode.Replace('_', ' ')
};
private static string FormatRounds(int value) =>
value == 1 ? "1 round" : $"{value} rounds";
}