45 lines
1.6 KiB
C#
45 lines
1.6 KiB
C#
|
|
using Theriapolis.Core.Data;
|
||
|
|
|
||
|
|
namespace Theriapolis.Core.Rules.Reputation;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Phase 6 M2 — top-level aggregate of every reputation track owned by
|
||
|
|
/// the player. Hangs off PlayScreen as a parallel-to-Character record
|
||
|
|
/// (deliberate separation: <c>Character</c> is what the player is,
|
||
|
|
/// <c>PlayerReputation</c> is what the world thinks of them).
|
||
|
|
///
|
||
|
|
/// Round-trips through <see cref="Persistence.ReputationSnapshot"/>.
|
||
|
|
/// </summary>
|
||
|
|
public sealed class PlayerReputation
|
||
|
|
{
|
||
|
|
public FactionStanding Factions { get; } = new();
|
||
|
|
public Dictionary<string, PersonalDisposition> Personal { get; } = new(System.StringComparer.OrdinalIgnoreCase);
|
||
|
|
public RepLedger Ledger { get; } = new();
|
||
|
|
|
||
|
|
/// <summary>Get-or-create the per-NPC personal disposition record for <paramref name="roleTag"/>.</summary>
|
||
|
|
public PersonalDisposition PersonalFor(string roleTag)
|
||
|
|
{
|
||
|
|
if (!Personal.TryGetValue(roleTag, out var p))
|
||
|
|
{
|
||
|
|
p = new PersonalDisposition { RoleTag = roleTag };
|
||
|
|
Personal[roleTag] = p;
|
||
|
|
}
|
||
|
|
return p;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Submit a reputation event. Updates faction standing (with opposition
|
||
|
|
/// cascade), the addressed NPC's personal disposition, and the ledger.
|
||
|
|
/// </summary>
|
||
|
|
public void Submit(RepEvent ev, IReadOnlyDictionary<string, FactionDef> factions)
|
||
|
|
{
|
||
|
|
if (!string.IsNullOrEmpty(ev.FactionId) && ev.Magnitude != 0)
|
||
|
|
Factions.Apply(ev.FactionId, ev.Magnitude, factions);
|
||
|
|
|
||
|
|
if (!string.IsNullOrEmpty(ev.RoleTag))
|
||
|
|
PersonalFor(ev.RoleTag).Apply(ev);
|
||
|
|
|
||
|
|
Ledger.Append(ev);
|
||
|
|
}
|
||
|
|
}
|