Stage 7.3: NPC scams (wicks, phishing airdrops, rug pools, fake support, forged transfers)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4279d48374
commit
6c5db17758
13 files changed
+691
-11
No files matched your search
@@ -11,7 +11,7 @@ namespace Decentralized
|
||||
public static class CoinCustomers
|
||||
{
|
||||
private static readonly HashSet<StoreClient> Marked = new HashSet<StoreClient>();
|
||||
private static int markDay = -1;
|
||||
private static int markDay = -1, supportDay = -1;
|
||||
|
||||
public static void Subscribe()
|
||||
{
|
||||
@@ -152,7 +152,7 @@ namespace Decentralized
|
||||
c.mainDialogue.SetText(c.displayName, "CRT.").SetEndAction(() => { });
|
||||
c.AddBasicDialog();
|
||||
c.CompleteClientCreation();
|
||||
Mark(c, Assets.CRT);
|
||||
Mark(c, Assets.CRT, false);
|
||||
Log.Info($"用币付款顾客(测试)已设置,钱包污点 {Session.Data.Hot.Taint:0.##},当前顾客 {PlayerStore.Instance.currentClientInstance?.GetClientBlueprint()?.identifier},队列 {PlayerStore.Instance.storeClientManager.clientStack.Count} 人");
|
||||
PlayerStore.Instance.currentClientInstance = null; // 测试:丢掉在场的顾客(开局的高利贷者不可遣散)
|
||||
PlayerStore.Instance.storeClientManager.clientStack.Insert(0, c);
|
||||
@@ -171,29 +171,80 @@ namespace Decentralized
|
||||
{
|
||||
int day = StoreStation.GetDayCounter();
|
||||
if (day != markDay) { Marked.Clear(); markDay = day; }
|
||||
// 假客服:一天最多一次
|
||||
if (day >= Tuning.ScamMinDay && supportDay != day)
|
||||
{
|
||||
supportDay = day;
|
||||
if (Session.Data.Rng.Chance(Tuning.FakeSupportChance)) manager.AddClient(FakeSupport());
|
||||
}
|
||||
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);
|
||||
Mark(c, asset, day >= Tuning.ScamMinDay && Session.Data.Rng.Chance(Tuning.FakeTransferShare));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void Mark(StoreClient c, string asset)
|
||||
/// <summary>
|
||||
/// 标成用币付款的顾客。开口先说用什么币付:正常的说"链上确认要一会儿";骗子(伪造转账)说"已经转了,给你看截图,快给货"——
|
||||
/// 成交后信用点照样被扣回,币却不会到账。玩家能做的就是听清这句话,不卖给他。
|
||||
/// </summary>
|
||||
private static void Mark(StoreClient c, string asset, bool fake)
|
||||
{
|
||||
var before = c.onItemBought;
|
||||
double total = 0; // 这位顾客这一单一共付了多少币
|
||||
c.isNoContributeToEvidence = true;
|
||||
var intro = new Dialogue().SetText(c.displayName, L.T(fake ? "coinpay.intro.fake" : "coinpay.intro", asset));
|
||||
intro.SetNextDialogue(c.mainDialogue);
|
||||
c.mainDialogue = intro;
|
||||
c.onItemBought = (item, cost) =>
|
||||
{
|
||||
before?.Invoke(item, cost);
|
||||
Log.Guard("用币付款成交", () => { total += Pay(c, asset, item, cost); Say(c, asset, total); });
|
||||
Log.Guard("用币付款成交", () =>
|
||||
{
|
||||
if (fake) { FakePay(c, asset, item, cost); total += cost / Session.Price(asset); }
|
||||
else total += Pay(c, asset, item, cost);
|
||||
Say(c, asset, total);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>伪造转账:信用点扣回(顾客没真付),币不会到账,晨间日志说明。</summary>
|
||||
private static void FakePay(StoreClient client, string asset, GameItem item, int cost)
|
||||
{
|
||||
if (cost <= 0) return;
|
||||
ModHelper.AddCredit(-cost, false);
|
||||
Session.Data.FakePaidToday.Add(L.T("coinpay.fake.entry", client.displayName, item.name, cost));
|
||||
Log.Info($"伪造转账:{client.displayName} 拿走 {item.name}({cost} 信用点),{asset} 不会到账");
|
||||
}
|
||||
|
||||
/// <summary>假客服:自称 Poinbase 客服,说账户被风控,要把 CRC 转到"安全地址"。Poinbase 从不上门,也从不要求转账;转过去的币就没了。</summary>
|
||||
public static StoreClient FakeSupportForTest() => FakeSupport();
|
||||
|
||||
private static StoreClient FakeSupport()
|
||||
{
|
||||
var d = Session.Data;
|
||||
string addr = ChainAddress.Make(d.Rng.NextUInt());
|
||||
d.Scams.ScamAddrs.Add(addr);
|
||||
int amount = 100 * d.Rng.Range(3, 15);
|
||||
var c = new StoreClient
|
||||
{
|
||||
identifier = "pd_fake_support", displayName = L.T("scam.support.name"), spriteName = SpriteDict.GetRandomUpperSpriteName(),
|
||||
clientIntent = StoreClient.ClientIntent.DIALOGUE,
|
||||
};
|
||||
c.mainDialogue.SetText(c.displayName, L.T("scam.support.1")).NextDialogue()
|
||||
.SetText(c.displayName, L.T("scam.support.2", amount, addr)).NextDialogue()
|
||||
.SetText(c.displayName, L.T("scam.support.3"));
|
||||
ModHelper.SetClientSource(c, ModInfo.Id);
|
||||
c.AddBasicDialog();
|
||||
c.CompleteClientCreation();
|
||||
Log.Info($"假客服上门:要 {amount} CRC 转到 {addr}");
|
||||
return c;
|
||||
}
|
||||
|
||||
/// <summary>成交后顾客说的话:告诉玩家这单是币到账,不是信用点。</summary>
|
||||
private static void Say(StoreClient client, string asset, double total)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user