Dr. Jackson stocks mining hardware
Uses the game's inventor stock hook (his shop at night and his weekly visit to the player's store) and his own table placement, so prices are item value plus his markup. A rig if the player has none (30% otherwise), two basic cards every time, advanced cards from day 10 (60%, a second at 30%), flagships from day 30 (25%) or always during his special stock from day 20. New, genuine cards only; only after Mining Access is unlocked. A test entry in the dev panel (F9) restocks the counter the way his shop does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
79d4c686a0
commit
a101b58f1c
5 files changed
+110
No files matched your search
@@ -7,3 +7,4 @@
|
|||||||
- mod 本体(第一阶段的第一部分):人脉网络"矿业渠道"(300)交付交易终端、矿架和一张 RZX 50;矿架是带电池槽和 4 个显卡槽的机器,每晚从电池扣电挖 PSCoin;显卡按型号显示算力、耗电与健康度,每晚损耗并可能烧毁;交易终端有钱包、交易(四个交易对、存入信用点、提取 CRC 过合规审查)、报告三页;夜间结算写晨间日志;PSCoin 交易所开业与减半上报纸;状态存进游戏的 mod 存档数据。中英双语。
|
- mod 本体(第一阶段的第一部分):人脉网络"矿业渠道"(300)交付交易终端、矿架和一张 RZX 50;矿架是带电池槽和 4 个显卡槽的机器,每晚从电池扣电挖 PSCoin;显卡按型号显示算力、耗电与健康度,每晚损耗并可能烧毁;交易终端有钱包、交易(四个交易对、存入信用点、提取 CRC 过合规审查)、报告三页;夜间结算写晨间日志;PSCoin 交易所开业与减半上报纸;状态存进游戏的 mod 存档数据。中英双语。
|
||||||
- 物品图:art/sprites.py 生成显卡(Probidia、PMD、烧毁)、矿架、交易终端。
|
- 物品图:art/sprites.py 生成显卡(Probidia、PMD、烧毁)、矿架、交易终端。
|
||||||
- 矿架加入游戏原有的通用模块槽:性能、效率、品质三项百分比折算 1/4 后作用于算力、耗电和显卡损耗,算力最多 +20%、省电最多 25%、损耗最多 −30%;性能加成同时提高损耗与暴毙率。取代原计划的 mod 自带超频模块。
|
- 矿架加入游戏原有的通用模块槽:性能、效率、品质三项百分比折算 1/4 后作用于算力、耗电和显卡损耗,算力最多 +20%、省电最多 25%、损耗最多 −30%;性能加成同时提高损耗与暴毙率。取代原计划的 mod 自带超频模块。
|
||||||
|
- 杰克逊博士上货(游戏给 mod 的进货钩子,夜间去他店里或他每周来本店摆摊时):没有矿架时必有一个,有了之后 30% 再上;基础显卡每次两张;进阶显卡第 10 天起 60%(再 30% 多一张);旗舰第 30 天起 25%,特供货事件时第 20 天起必有。全新真货,价格为物品价值加他的加价。解锁矿业渠道后才上货。开发者模式 F9 有测试入口。
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Decentralized.Domain
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 正规渠道(杰克逊博士)每次进货时上架的挖矿设备:全新、真货。返回物品种类:矿架用 <see cref="Rig"/>,显卡用型号。
|
||||||
|
/// </summary>
|
||||||
|
public static class Dealer
|
||||||
|
{
|
||||||
|
public const string Rig = "RIG";
|
||||||
|
|
||||||
|
public static readonly string[] Basic = { "RZX50", "RZX60", "RZ470", "RZ580" };
|
||||||
|
public static readonly string[] Advanced = { "RZX70", "RZX80Ti", "RZ6800" };
|
||||||
|
public static readonly string[] Flagship = { "RZX90", "RZ7900" };
|
||||||
|
|
||||||
|
public const int AdvancedFromDay = 10, FlagshipFromDay = 30, SpecialFlagshipFromDay = 20;
|
||||||
|
public const double RigRestockChance = 0.30, AdvancedChance = 0.60, AdvancedSecondChance = 0.30, FlagshipChance = 0.25;
|
||||||
|
|
||||||
|
public static List<string> Stock(int day, bool ownsRig, bool specialStock, Rng rng)
|
||||||
|
{
|
||||||
|
var list = new List<string>();
|
||||||
|
if (!ownsRig || rng.Chance(RigRestockChance)) list.Add(Rig);
|
||||||
|
for (int i = 0; i < 2; i++) list.Add(Pick(Basic, rng));
|
||||||
|
if (day >= AdvancedFromDay && rng.Chance(AdvancedChance))
|
||||||
|
{
|
||||||
|
list.Add(Pick(Advanced, rng));
|
||||||
|
if (rng.Chance(AdvancedSecondChance)) list.Add(Pick(Advanced, rng));
|
||||||
|
}
|
||||||
|
if (specialStock && day >= SpecialFlagshipFromDay) list.Add(Pick(Flagship, rng));
|
||||||
|
else if (day >= FlagshipFromDay && rng.Chance(FlagshipChance)) list.Add(Pick(Flagship, rng));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Pick(string[] from, Rng rng) => from[rng.Range(0, from.Length - 1)];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Decentralized.Domain;
|
||||||
|
|
||||||
|
namespace Decentralized
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 杰克逊博士进货时(夜间去他店里,或他每周来本店摆摊)加上挖矿设备。用游戏给 mod 的进货钩子和他自己的上架函数,
|
||||||
|
/// 价格是物品价值加上他的加价(难度规则与夜间事件决定)。解锁矿业渠道之后才上货。
|
||||||
|
/// </summary>
|
||||||
|
public static class DealerStock
|
||||||
|
{
|
||||||
|
public static void Subscribe()
|
||||||
|
{
|
||||||
|
ModHook.OnPlaceInventorInventoryItemLate += OnPlace;
|
||||||
|
// 开发者模式(F9)里的测试入口:像到了杰克逊店里一样,清空并扩大柜台后上货
|
||||||
|
ModHelper.AddDebugFunction(ModInfo.Id, ModInfo.Name, "Dr. Jackson stock (test)", () =>
|
||||||
|
{
|
||||||
|
EmporiumEntry.Instance.ClearFrontInv();
|
||||||
|
EmporiumEntry.Instance.ExpandFrontCounterGrid();
|
||||||
|
StoreClientList.PlaceInventorInventory();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Unsubscribe()
|
||||||
|
{
|
||||||
|
ModHook.OnPlaceInventorInventoryItemLate -= OnPlace;
|
||||||
|
ModHelper.RemoveDebugFunctions(ModInfo.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnPlace(List<GameItem> owned)
|
||||||
|
{
|
||||||
|
if (Session.Data == null || !Unlock.IsUnlocked) return;
|
||||||
|
Log.Guard("杰克逊博士上货", () =>
|
||||||
|
{
|
||||||
|
bool ownsRig = owned != null && owned.Any(i => i.identifier == Items.Rig);
|
||||||
|
bool special = AfterhourEvents.IsActive("special_stock");
|
||||||
|
var placed = new List<string>();
|
||||||
|
foreach (var kind in Dealer.Stock(StoreStation.GetDayCounter(), ownsRig, special, Session.Data.Rng))
|
||||||
|
{
|
||||||
|
var item = ModHelper.SpawnItem(kind == Dealer.Rig ? Items.Rig : Items.GpuId(kind));
|
||||||
|
bool ok = PlayerStore.Instance.TryAddDirectSellingItemToTable(item);
|
||||||
|
placed.Add(ok ? $"{kind}#{item.uniqueId}" : kind + "(柜台已满)");
|
||||||
|
}
|
||||||
|
Log.Info("杰克逊博士上货:" + string.Join(",", placed));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ namespace Decentralized
|
|||||||
Items.OpenTerminal = TerminalWindow.Open;
|
Items.OpenTerminal = TerminalWindow.Open;
|
||||||
Unlock.Register();
|
Unlock.Register();
|
||||||
Night.Subscribe();
|
Night.Subscribe();
|
||||||
|
DealerStock.Subscribe();
|
||||||
ModHook.OnGameLoadedLate += Session.Load;
|
ModHook.OnGameLoadedLate += Session.Load;
|
||||||
ModHook.OnNewGameStarted += OnNewGame;
|
ModHook.OnNewGameStarted += OnNewGame;
|
||||||
Log.Info($"{ModInfo.Name} {ModInfo.Version} 已启用");
|
Log.Info($"{ModInfo.Name} {ModInfo.Version} 已启用");
|
||||||
@@ -23,6 +24,7 @@ namespace Decentralized
|
|||||||
{
|
{
|
||||||
Items.Unsubscribe();
|
Items.Unsubscribe();
|
||||||
Night.Unsubscribe();
|
Night.Unsubscribe();
|
||||||
|
DealerStock.Unsubscribe();
|
||||||
ModHook.OnGameLoadedLate -= Session.Load;
|
ModHook.OnGameLoadedLate -= Session.Load;
|
||||||
ModHook.OnNewGameStarted -= OnNewGame;
|
ModHook.OnNewGameStarted -= OnNewGame;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -290,6 +290,28 @@ internal static class Program
|
|||||||
Check(Near(dr.Received, 900 * (1 - Tuning.ExchangeFee), 1e-6), "CRC 脱锚时按市价兑出");
|
Check(Near(dr.Received, 900 * (1 - Tuning.ExchangeFee), 1e-6), "CRC 脱锚时按市价兑出");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Test("杰克逊博士:没有矿架必上一个;基础卡每次两张;进阶第 10 天起、旗舰第 30 天起;特供货第 20 天起必有旗舰", () =>
|
||||||
|
{
|
||||||
|
var rng = new Rng(11);
|
||||||
|
var first = Dealer.Stock(1, false, false, rng);
|
||||||
|
Check(first.Count(k => k == Dealer.Rig) == 1 && first.Count(k => Dealer.Basic.Contains(k)) == 2 && first.Count == 3, $"第 1 天:矿架 + 两张基础卡:{string.Join(",", first)}");
|
||||||
|
int adv = 0, flag = 0, rigs = 0, n = 4000;
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
var s9 = Dealer.Stock(9, true, false, rng);
|
||||||
|
Check(!s9.Any(k => Dealer.Advanced.Contains(k) || Dealer.Flagship.Contains(k)), "第 9 天没有进阶与旗舰");
|
||||||
|
var s40 = Dealer.Stock(40, true, false, rng);
|
||||||
|
if (s40.Any(k => Dealer.Advanced.Contains(k))) adv++;
|
||||||
|
if (s40.Any(k => Dealer.Flagship.Contains(k))) flag++;
|
||||||
|
if (s40.Contains(Dealer.Rig)) rigs++;
|
||||||
|
}
|
||||||
|
Check(Near(adv / (double)n, 0.60, 0.03) && Near(flag / (double)n, 0.25, 0.03) && Near(rigs / (double)n, 0.30, 0.03),
|
||||||
|
$"第 40 天:进阶 {adv / (double)n:P0}(60%),旗舰 {flag / (double)n:P0}(25%),已有矿架时再上 {rigs / (double)n:P0}(30%)");
|
||||||
|
Check(Dealer.Stock(20, true, true, rng).Any(k => Dealer.Flagship.Contains(k)) && !Dealer.Stock(19, true, true, new Rng(1)).Any(k => Dealer.Flagship.Contains(k)),
|
||||||
|
"特供货:第 20 天起必有旗舰,第 19 天没有");
|
||||||
|
Check(Dealer.Basic.Concat(Dealer.Advanced).Concat(Dealer.Flagship).All(m => Hardware.Specs.ContainsKey(m) && !Hardware.Specs[m].Asic), "上架的型号都是登记过的显卡");
|
||||||
|
});
|
||||||
|
|
||||||
Test("存档:市场、稳定币、全网、钱包、交易所、随机数序列化后读回,之后的结果一致", () =>
|
Test("存档:市场、稳定币、全网、钱包、交易所、随机数序列化后读回,之后的结果一致", () =>
|
||||||
{
|
{
|
||||||
var m = Market.CreateDefault(3);
|
var m = Market.CreateDefault(3);
|
||||||
|
|||||||
Reference in new issue
Block a user