Phase 2: customers paying in coin (CRC/CRT/CRA/PSC), taint from stolen goods

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Sonnet 5.5 committed 2026-11-03 16:01:20 +08:00
1 parent 1ba0652705
commit 090a973d23
10 files changed
+149

No files matched your search

+78
View File
@@ -0,0 +1,78 @@
using System.Collections.Generic;
using Decentralized.Domain;
namespace Decentralized
{
/// <summary>
/// 用币付款的顾客:每天排队的买家里,按派系(上层 CRC、黑市 CRT、革命派 CRA、下层 PSC)有一小部分改用币结算。
/// 成交时在店里扣回刚入账的信用点,换成币进热钱包;赃物的款项不记销赃,改成币带污点(货值 × 赃物热度%)。
/// </summary>
public static class CoinCustomers
{
private static readonly HashSet<StoreClient> Marked = new HashSet<StoreClient>();
private static int markDay = -1;
public static void Subscribe()
{
ModHook.OnGenerateCustomerLate += OnGenerate;
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Coin buyer (test)", () => Log.Guard("用币付款顾客(测试)", () =>
{
var c = new StoreClient
{
identifier = "pd_coin_test", displayName = "Coin buyer", spriteName = SpriteDict.GetRandomScavSpriteName(),
clientFaction = "FACTION_BLACK_MARKET", useClientBudget = true, clientIntent = StoreClient.ClientIntent.BUY,
canClientExposeFeature = ClientCanExposeFunc.BasicClientExposeCapacity,
};
c.SetBudget(5000);
c.clientBuyingTagList.Add("WATER"); c.clientBuyingTagList.Add("BREVAGE");
c.mainDialogue.SetText(c.displayName, "CRT.").SetEndAction(() => { });
c.AddBasicDialog();
c.CompleteClientCreation();
Mark(c, Assets.CRT);
PlayerStore.Instance.currentClientInstance = StoreClientInstance.CreateClientInstance(c); // 测试:直接换成这位顾客
}));
}
public static void Unsubscribe() => ModHook.OnGenerateCustomerLate -= OnGenerate;
private static void OnGenerate(StoreClientManager manager)
{
if (Session.Data == null || !Unlock.IsUnlocked) return;
Log.Guard("用币付款", () =>
{
int day = StoreStation.GetDayCounter();
if (day != markDay) { Marked.Clear(); markDay = day; }
foreach (var c in manager.clientStack)
{
if (c == null || c.isSecurity || Marked.Contains(c) || c.clientIntent != StoreClient.ClientIntent.BUY || c.isNoContributeToEvidence) continue;
Marked.Add(c);
string asset = CoinPayment.AssetFor(c.clientFaction);
if (asset == null || !Session.Data.Rng.Chance(CoinPayment.Chance(asset))) continue;
Mark(c, asset);
}
});
}
private static void Mark(StoreClient c, string asset)
{
var before = c.onItemBought;
c.isNoContributeToEvidence = true;
c.onItemBought = (item, cost) =>
{
before?.Invoke(item, cost);
Log.Guard("用币付款成交", () => Pay(asset, item, cost));
};
}
private static void Pay(string asset, GameItem item, int cost)
{
var d = Session.Data;
double price = Session.Price(asset);
if (cost <= 0 || price <= 0) return;
int heat = item.IsTag("STOLEN_VALUE_INT") ? item.GetTagReadonly("STOLEN_VALUE_INT").GetInt() : 0;
ModHelper.AddCredit(-cost, false);
double qty = CoinPayment.Receive(d.Hot, asset, cost, price, heat);
d.CoinSalesToday += cost;
Log.Info($"用币付款:{item.name} {cost} 信用点 → {qty:0.####} {asset},污点 +{cost * heat / 100.0:0}");
}
}
}
+2
View File
@@ -16,6 +16,7 @@ namespace Decentralized
Night.Subscribe();
DealerStock.Subscribe();
UsedDealerClient.Subscribe();
CoinCustomers.Subscribe();
GpuInspectView.Ensure();
ModHook.OnGameLoadedLate += Session.Load;
ModHook.OnNewGameStarted += OnNewGame;
@@ -28,6 +29,7 @@ namespace Decentralized
Night.Unsubscribe();
DealerStock.Unsubscribe();
UsedDealerClient.Unsubscribe();
CoinCustomers.Unsubscribe();
GpuInspectView.Remove();
ModHook.OnGameLoadedLate -= Session.Load;
ModHook.OnNewGameStarted -= OnNewGame;
@@ -50,6 +50,7 @@ report.burnt,Cards burnt out: {0}
report.price,PSC price: {0} credits
nightlog.mined,Mining rigs produced {0} PSC.
nightlog.burnt,A {0} burnt out.
nightlog.coinpay,Customers paying in coin settled {0} credits; the coins went to the hot wallet.
nightlog.unpowered,{0} mining rig(s) had no power.
news.open.title,Poinbase Lists PSC
news.open.desc,The Upper Level exchange Poinbase now lists PSC against CRC. Graphics cards are in demand across the station.
1 # Probably Decentralized localization table: English (en)
50 report.price
51 nightlog.mined
52 nightlog.burnt
53 nightlog.coinpay
54 nightlog.unpowered
55 news.open.title
56 news.open.desc
@@ -49,6 +49,7 @@ report.burnt,烧毁的显卡:{0}
report.price,PSC 价格:{0} 信用点
nightlog.mined,矿架挖出 {0} PSC。
nightlog.burnt,一张 {0} 烧毁了。
nightlog.coinpay,用币付款的顾客共结算 {0} 信用点,已换成币进了热钱包。
nightlog.unpowered,{0} 个矿架没有电。
news.open.title,Poinbase 上架 PSC
news.open.desc,上层交易所 Poinbase 上架 PSC/CRC 交易对。全站显卡需求上升。
1 # Probably Decentralized 本地化表:简体中文(zh)
49 report.price
50 nightlog.mined
51 nightlog.burnt
52 nightlog.coinpay
53 nightlog.unpowered
54 news.open.title
55 news.open.desc
+2
View File
@@ -120,6 +120,8 @@ namespace Decentralized
foreach (var name in report.Burnt) ps.AddNightLog(L.T("nightlog.burnt", name), "cc7755");
int unpowered = report.Rigs - report.PoweredRigs;
if (unpowered > 0 && units.Count + unpowered > 0) ps.AddNightLog(L.T("nightlog.unpowered", unpowered), "cc7755");
if (d.CoinSalesToday > 0) ps.AddNightLog(L.T("nightlog.coinpay", Fmt.Credits(d.CoinSalesToday)));
d.CoinSalesToday = 0;
Session.Save();
}
}
+2
View File
@@ -28,6 +28,8 @@ namespace Decentralized
public List<MarketEvent> ActiveEvents = new List<MarketEvent>();
public NightReport LastNight;
public bool OpeningNewsShown;
/// <summary>当天用币付款的成交额(信用点),夜间清零。</summary>
public double CoinSalesToday;
}
/// <summary>当前这一局的状态:读档 / 新游戏时载入,睡觉结算后写回。</summary>