Files
probably-decentralized/src/Decentralized/UsedDealerClient.cs
T
ZHU MINCHAOandClaude Sonnet 5.5 de7d5caafe Used cards: counter quote tag instead of client-temporary feature; item type Material
Client-temporary features are stripped when an item sits on the front
counter, so the scam markup never applied. The quote now lives in a tag and
counts only while the item is not owned. GPU item type ELECTRONIC has no
translation in the game, so cards are typed as Material.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-03 12:00:39 +08:00

94 lines
4.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using Decentralized.Domain;
namespace Decentralized
{
/// <summary>
/// 二手显卡贩子:偶尔上门,把几张卡摆上柜台,玩家按外观自己判断(翻面看背面)。
/// 老实人按真实价值卖,中间商加价,骗子夹带假卡并按标称型号报价;柜台价写在物品的报价标签上,物品归玩家之后只值真实价值。
/// 另外把显卡登记为鉴定公会的鉴定物品,正确价值与实际售价是同一个数。
/// </summary>
public static class UsedDealerClient
{
public const string Appraisal = "pd_gpu_appraisal";
private const double VisitChance = 0.05;
private static int lastVisitDay = -1;
public static void Subscribe()
{
ModHook.OnGenerateCustomerNormal += OnGenerate;
ModHelper.AddAppraisalItem(ModInfo.Id, Appraisal, Items.GpuId("RZX50"), 2, CreateForAppraisal, u => (int)CardValue.True(Items.ToUnit(u)),
Items.IsGpu, null, () => L.T("appraisal.gpu"));
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Used dealer visit (test)", () => Log.Guard("二手贩子(测试)", () =>
{
var m = PlayerStore.Instance.storeClientManager;
m.AddNextClient(Create(DealerKind.Scammer, 40));
Log.Info($"二手贩子(测试)已排入,队列 {m.clientStack.Count} 人");
}));
}
public static void Unsubscribe()
{
ModHook.OnGenerateCustomerNormal -= OnGenerate;
ModHelper.RemoveAppraisalItems(ModInfo.Id);
}
private static void OnGenerate(StoreClientManager manager)
{
if (Session.Data == null || !Unlock.IsUnlocked) return;
Log.Guard("二手贩子", () =>
{
int day = StoreStation.GetDayCounter();
if (day < 3 || day == lastVisitDay || !Session.Data.Rng.Chance(VisitChance)) return;
lastVisitDay = day;
manager.AddClient(Create(UsedDealers.Kind(day, Session.Data.Rng)));
});
}
/// <summary>鉴定公会送来的卡:一成是假卡;默认估价是按标称型号算的价。</summary>
private static GameItem CreateForAppraisal()
{
var rng = Session.Data?.Rng ?? new Rng(1);
int day = StoreStation.GetDayCounter();
var cards = UsedDealers.Cards(DealerKind.Middleman, day, rng);
var c = cards[0];
var item = Items.NewCard(c.Model, c.Health, c.FakeOf, rng);
AppraisalHelper.InitAppraisalItem(item, (int)CardValue.Of(c.Model, c.Health));
return item;
}
private static StoreClient Create(DealerKind kind, int? atDay = null)
{
int day = atDay ?? StoreStation.GetDayCounter();
var rng = Session.Data.Rng;
var cards = UsedDealers.Cards(kind, day, rng);
var client = new StoreClient
{
identifier = "pd_used_dealer",
displayName = L.T("dealer.name"),
spriteName = SpriteDict.GetRandomScavSpriteName(),
clientIntent = StoreClient.ClientIntent.SELL,
};
StoreClientFactionSetup.InitScav(client);
client.mainDialogue.SetText(client.displayName, L.T("dealer.line1." + rng.Range(1, 3))).NextDialogue().SetText(client.displayName, L.T("dealer.line2." + rng.Range(1, 3)))
.SetEndAction(() => Log.Guard("二手贩子上货", () =>
{
NegociationUIManager.Instance.OpenUI();
var placed = new List<string>();
foreach (var c in cards)
{
var item = Items.NewCard(c.Model, c.Health, c.FakeOf, rng);
if (c.MarkupPct != 0) Items.SetQuote(item, (long)Math.Round(CardValue.True(Items.ToUnit(item)) * (1 + c.MarkupPct / 100.0)));
PlayerStore.Instance.AddDirectSellingItemToTable(item);
placed.Add($"{c.Model}{(c.FakeOf != null ? "←" + c.FakeOf : "")} {c.Health:0}% {c.MarkupPct:+0;-0}% 柜台价 {item.unitValue}(真实 {CardValue.True(Items.ToUnit(item))})");
}
Log.Info($"二手贩子({kind}):{string.Join(",", placed)}");
}));
client.AddBasicDialog();
client.CompleteClientCreation();
return client;
}
}
}