Stage 6.3: RatDigg ASIC miners, miner dealers on the black market, miner era event
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b249747855
commit
7d13ae2fe8
18 files changed
+395
-19
No files matched your search
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Decentralized.Domain;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Decentralized
|
||||
{
|
||||
/// <summary>
|
||||
/// RatDigg 矿机(M1 / M2 / M3):独立的机器,窗口里有电池槽、模块槽(和矿架同一套效果)和修理槽,没有显卡槽。
|
||||
/// 夜间和矿架一样先从电池扣电、有电才挖;损耗与暴毙沿用 <see cref="Unit"/>(暴毙系数 0.5,每天损耗 0.8)。
|
||||
/// 暴毙后成了"损坏的矿机":往修理槽里按顺序放电子元件修好(见 <see cref="AsicRepair"/>),健康扣 20 点。
|
||||
/// </summary>
|
||||
public static class AsicItems
|
||||
{
|
||||
public const string Prefix = "pd_asic_";
|
||||
public const string StepTag = "PD_REPAIR_STEP", ProgTag = "PD_REPAIR_PROG";
|
||||
|
||||
public static string Id(string model) => Prefix + model.ToLowerInvariant();
|
||||
public static bool Is(GameItem it) => it != null && it.identifier != null && it.identifier.StartsWith(Prefix);
|
||||
|
||||
public static void Register(ModItemDirectory dir)
|
||||
{
|
||||
foreach (var spec in Hardware.Specs.Values.Where(s => s.Asic))
|
||||
{
|
||||
var s = spec;
|
||||
dir.Add(Id(s.Model), () => Create(s));
|
||||
}
|
||||
}
|
||||
|
||||
private static int Step(GameItem m) => m.IsTag(StepTag) ? m.GetTagReadonly(StepTag).GetInt() : 0;
|
||||
private static int Prog(GameItem m) => m.IsTag(ProgTag) ? m.GetTagReadonly(ProgTag).GetInt() : 0;
|
||||
|
||||
private static GameItem Create(HardwareSpec spec)
|
||||
{
|
||||
var battery = new GameSlotInventory();
|
||||
var repair = new GameSlotInventory();
|
||||
var modules = new GameGridInventory(MachineHelper.DEFAULT_MODULE_BAY_CONFIG, 7);
|
||||
var window = MachineHelper.CreateMachineryWindow(true,
|
||||
MachineHelper.PowerPanel(battery),
|
||||
MachineHelper.Panel(L.T("rig.label.modules"), modules, "module"),
|
||||
MachineHelper.Panel(L.T("asic.label.repair"), repair, "upgrade"));
|
||||
var m = ItemDirectory.CreateEmptyItem(Id(spec.Model)).SetContentWindow(window);
|
||||
m.SetSpriteAndShapeFromMod(ModInfo.Id, "asic_" + spec.Model.ToLowerInvariant());
|
||||
m.name = L.T("item.asic.name", spec.Model);
|
||||
m.unitValue = spec.Price;
|
||||
MachineHelper.SetupBatterySlot(battery, m);
|
||||
m.EnableTag("CONTAINER_TAG");
|
||||
m.EnableTag("STANDARD_MACHINE_TAG");
|
||||
MachineryHelper.InitMachinery(m, (int)Math.Ceiling(spec.Kj));
|
||||
MachineHelper.SetupModuleBay(modules, m, () => Update(m, modules));
|
||||
repair.mayInventoryAddItemFunc = (it, _) =>
|
||||
{
|
||||
var u = Items.ToUnit(m);
|
||||
var need = AsicRepair.Need(u.Model, Step(m));
|
||||
return GeneralHelper.IsItemOwned(it) && u.Dead && need != null && it.identifier == need.Value.Item;
|
||||
};
|
||||
repair.onSlotAddItemEndFunc = (it, _, _) => Log.Guard("矿机修理", () => TakeRepair(m, repair, modules, it));
|
||||
m.onLoaded = _ => Update(m, modules);
|
||||
m.onCycleEndEarlySlotItemFunc = (_, _, _) => Log.Guard("矿机扣电", () => NightDraw(m, battery, modules));
|
||||
ModHelper.SetSource(m, ModInfo.Id, ModInfo.Name);
|
||||
Update(m, modules);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// <summary>名字、说明、价值与耗电(耗电按模块效果重算)。</summary>
|
||||
private static void Update(GameItem m, GameInventory modules)
|
||||
{
|
||||
var u = Items.ToUnit(m);
|
||||
var b = Items.Bonus(m, modules);
|
||||
int baseKj = (int)Math.Ceiling(u.Label.Kj);
|
||||
m.ModifyTag("MACHINERY_DRAWN_POWER_BASE", s => s.Enable().SetInt(baseKj));
|
||||
m.ModifyTag(MachineryHelper.MACHINERY_DRAWN_POWER, s => s.Enable().SetInt(u.Dead ? 0 : (int)Math.Ceiling(u.Kj(b))));
|
||||
Describe(m, u);
|
||||
}
|
||||
|
||||
/// <summary>按标签刷新名字、说明、价值(夜间损耗之后也走这里)。</summary>
|
||||
public static void Refresh(GameItem m) => Describe(m, Items.ToUnit(m));
|
||||
|
||||
private static void Describe(GameItem m, Unit u)
|
||||
{
|
||||
var spec = u.Label;
|
||||
m.name = L.T(u.Dead ? "item.asic.dead.name" : "item.asic.name", spec.Model);
|
||||
if (u.Dead)
|
||||
{
|
||||
var need = AsicRepair.Need(u.Model, Step(m));
|
||||
m.shortDescription = need == null ? L.T("item.asic.dead.fixed") : L.T("item.asic.dead.desc", L.T("mat." + need.Value.Item), need.Value.Count - Prog(m));
|
||||
m.unitValue = Math.Max(1, (long)Math.Round(spec.Price * Tuning.AsicDeadValue));
|
||||
return;
|
||||
}
|
||||
string cond = GeneralHelper.IsItemOwned(m)
|
||||
? Mathf.RoundToInt((float)u.Health) + "%"
|
||||
: L.T(u.Health >= 85 ? "item.gpu.grade.1" : u.Health >= 60 ? "item.gpu.grade.2" : u.Health >= 35 ? "item.gpu.grade.3" : "item.gpu.grade.4");
|
||||
m.shortDescription = L.T("item.asic.desc", Fmt.Num(spec.DisplayHash), Fmt.Num(spec.Kj), cond);
|
||||
m.unitValue = CardValue.Of(spec.Model, u.Health);
|
||||
}
|
||||
|
||||
private static void NightDraw(GameItem m, GameSlotInventory battery, GameInventory modules)
|
||||
{
|
||||
var u = Items.ToUnit(m);
|
||||
Session.TonightRigs++;
|
||||
if (u.Dead) return;
|
||||
var b = Items.Bonus(m, modules);
|
||||
int kj = (int)Math.Ceiling(u.Kj(b));
|
||||
if (battery.childItems.Count == 0 || !PowerHelper.DrawPowerSource(battery.childItem, kj)) return;
|
||||
Session.TonightPoweredRigs++;
|
||||
Session.TonightKj += kj;
|
||||
Session.TonightCards.Add(new KeyValuePair<GameItem, ModuleBonus>(m, b));
|
||||
Update(m, modules);
|
||||
}
|
||||
|
||||
private static void TakeRepair(GameItem m, GameSlotInventory slot, GameInventory modules, GameItem item)
|
||||
{
|
||||
var u = Items.ToUnit(m);
|
||||
if (!u.Dead) return;
|
||||
int step = Step(m), prog = Prog(m);
|
||||
int took = AsicRepair.Insert(u.Model, ref step, ref prog, item.identifier, item.unitCount);
|
||||
if (took <= 0) return;
|
||||
m.ModifyTag(StepTag, s => s.Enable().SetInt(step));
|
||||
m.ModifyTag(ProgTag, s => s.Enable().SetInt(prog));
|
||||
if (took >= item.unitCount) { slot.Expel(item); item.Destroy(); }
|
||||
else item.GetSplitItem(took).Destroy();
|
||||
if (AsicRepair.Done(u.Model, step))
|
||||
{
|
||||
u.Dead = false;
|
||||
u.Health = Math.Max(10, u.Health - Tuning.AsicRepairHealthCut);
|
||||
m.ModifyTag(Items.DeadTag, s => s.Disable());
|
||||
m.ModifyTag(StepTag, s => s.Enable().SetInt(0));
|
||||
m.ModifyTag(ProgTag, s => s.Enable().SetInt(0));
|
||||
Items.Store(m, u);
|
||||
EmporiumAudioPlayer.Instance?.ratchet?.Play();
|
||||
Log.Info($"矿机 {u.Model} 修好了,健康 {u.Health:0}");
|
||||
}
|
||||
Update(m, modules);
|
||||
}
|
||||
|
||||
/// <summary>造一台矿机:按健康度写标签。</summary>
|
||||
public static GameItem New(string model, double health)
|
||||
{
|
||||
var item = ModHelper.SpawnItem(Id(model));
|
||||
Items.Store(item, new Unit { Model = model, Health = health });
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user