Cards: appearance follows wear, hash depends on fan and contacts, seller confrontation

Fan, contact and scratch levels are recomputed from health and a per-card
seed, so a card looks older as it wears. Fan and contacts scale hashrate.
Each inspection-tray detail now maps to exactly one dimension value. Quoting
dealers price the card as if its condition were fine; the player points out
fan, contacts, bracket, print or sticker in the tray to take the matching
discount or expose a fake (a wrong accusation costs reputation like the
vanilla confrontation). Unowned cards show a coarse grade and rated specs.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Sonnet 5.5 committed 2026-11-03 13:37:48 +08:00
1 parent 68265095a8
commit f93dbc6eec
9 files changed
+279 -76

No files matched your search

+5 -3
View File
@@ -86,6 +86,8 @@ namespace Decentralized.Domain
public bool Refurbished;
/// <summary>外观;新卡(正规渠道)没有记录,按全新画。</summary>
public CardLook Look;
/// <summary>按当前健康度算出的外观。</summary>
public CardLook Appearance => Look.Appearance(Health);
public HardwareSpec Label => Hardware.Specs[Model];
public HardwareSpec Chip => Hardware.Specs[FakeOf ?? Model];
@@ -94,7 +96,7 @@ namespace Decentralized.Domain
public double Hash(ModuleBonus b)
{
if (Dead) return 0;
return Chip.Hash * (Health >= 50 ? 1.0 : 0.6 + 0.4 * Health / 50) * b.Hash;
return Chip.Hash * (Health >= 50 ? 1.0 : 0.6 + 0.4 * Health / 50) * b.Hash * Appearance.HashFactor;
}
public double Kj(ModuleBonus b) => Dead ? 0 : Chip.Kj * b.Kj;
@@ -103,14 +105,14 @@ namespace Decentralized.Domain
public double DeathChance(ModuleBonus b)
{
double p = Tuning.DeathBase + Tuning.DeathWorn * Math.Pow(1 - Health / 100, 2);
return p * Label.DeathFactor * (FakeOf != null ? Tuning.FakeDeathFactor : 1) * b.Death * Look.DeathFactor;
return p * Label.DeathFactor * (FakeOf != null ? Tuning.FakeDeathFactor : 1) * b.Death * Appearance.DeathFactor;
}
/// <summary>一夜的损耗与暴毙判定;返回是否在今晚暴毙。</summary>
public bool Night(ModuleBonus b, Rng rng)
{
if (Dead) return false;
Health = Math.Max(0, Health - Label.WearFactor * b.Wear * Look.WearFactor);
Health = Math.Max(0, Health - Label.WearFactor * b.Wear * Appearance.WearFactor);
if (rng.Chance(DeathChance(b)))
{
Dead = true;