182 lines
8.4 KiB
C#
182 lines
8.4 KiB
C#
using System;
|
||||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Text.RegularExpressions;
|
|||
|
|
using Decentralized.Domain;
|
|||
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
namespace Decentralized
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// mod 物品:交易终端、矿架、显卡(每个型号一个物品 id)。显卡的健康度、假卡、翻新、烧毁存在物品标签上,随存档保存。
|
|||
|
|
/// 读档时游戏按 id 重新调用工厂,再把存档里的标签与子物品(矿架里的显卡、电池)恢复回去。
|
|||
|
|
/// </summary>
|
|||
|
|
public static class Items
|
|||
|
|
{
|
|||
|
|
public const string Terminal = "pd_terminal";
|
|||
|
|
public const string Rig = "pd_rig";
|
|||
|
|
public const string GpuPrefix = "pd_gpu_";
|
|||
|
|
|
|||
|
|
public const string HealthTag = "PD_HEALTH";
|
|||
|
|
public const string FakeTag = "PD_FAKE_OF";
|
|||
|
|
public const string RefurbTag = "PD_REFURBISHED";
|
|||
|
|
public const string DeadTag = "PD_DEAD";
|
|||
|
|
|
|||
|
|
public static Action OpenTerminal;
|
|||
|
|
|
|||
|
|
public static void Subscribe() => ModHook.OnModItemDirectoryInit += Register;
|
|||
|
|
public static void Unsubscribe() => ModHook.OnModItemDirectoryInit -= Register;
|
|||
|
|
|
|||
|
|
public static string GpuId(string model) => GpuPrefix + model.ToLowerInvariant();
|
|||
|
|
|
|||
|
|
public static bool IsGpu(GameItem item) => item != null && item.identifier != null && item.identifier.StartsWith(GpuPrefix);
|
|||
|
|
|
|||
|
|
private static void Register(ModItemDirectory dir)
|
|||
|
|
{
|
|||
|
|
dir.Add(Terminal, CreateTerminal);
|
|||
|
|
dir.Add(Rig, CreateRig);
|
|||
|
|
foreach (var spec in Hardware.Specs.Values.Where(s => !s.Asic))
|
|||
|
|
{
|
|||
|
|
var s = spec;
|
|||
|
|
dir.Add(GpuId(s.Model), () => CreateGpu(s));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ---------- 交易终端 ----------
|
|||
|
|
|
|||
|
|
private static GameItem CreateTerminal()
|
|||
|
|
{
|
|||
|
|
var item = ItemDirectory.CreateEmptyItem(Terminal);
|
|||
|
|
item.SetSpriteAndShapeFromMod(ModInfo.Id, "terminal");
|
|||
|
|
item.name = L.T("item.terminal.name");
|
|||
|
|
item.shortDescription = L.T("item.terminal.desc");
|
|||
|
|
item.unitValue = 0;
|
|||
|
|
item.EnableTag(GeneralHelper.IMPORTANT_TAG);
|
|||
|
|
item.EnableTag(TypeHelper.NOT_FOR_RESALE);
|
|||
|
|
item.mayActivateSlotItemFunc = (_, _, _) => true;
|
|||
|
|
item.canActivateSlotItemFunc = (_, _, _) => true;
|
|||
|
|
item.onActivateSlotItemFunc = (_, _, _) => Log.Guard("打开交易终端", () => OpenTerminal?.Invoke());
|
|||
|
|
ModHelper.SetSource(item, ModInfo.Id, ModInfo.Name);
|
|||
|
|
return item;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ---------- 显卡 ----------
|
|||
|
|
|
|||
|
|
/// <summary>RZX70 → "RZX 70",RZX80Ti → "RZX 80 Ti",RZ6800 → "RZ 6800"。</summary>
|
|||
|
|
public static string DisplayModel(string model) => Regex.Replace(Regex.Replace(model, @"(?<=[A-Za-z])(?=\d)", " "), @"(?<=\d)(?=[A-Z])", " ");
|
|||
|
|
|
|||
|
|
private static GameItem CreateGpu(HardwareSpec spec)
|
|||
|
|
{
|
|||
|
|
var item = ItemDirectory.CreateEmptyItem(GpuId(spec.Model));
|
|||
|
|
item.SetSpriteAndShapeFromMod(ModInfo.Id, spec.Brand == Hardware.Probidia ? "gpu_probidia" : "gpu_pmd");
|
|||
|
|
item.SetGameItemType("ELECTRONIC");
|
|||
|
|
item.onLoaded = Refresh;
|
|||
|
|
ModHelper.SetSource(item, ModInfo.Id, ModInfo.Name);
|
|||
|
|
Refresh(item);
|
|||
|
|
return item;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static Unit ToUnit(GameItem item)
|
|||
|
|
{
|
|||
|
|
string model = item.identifier.Substring(GpuPrefix.Length);
|
|||
|
|
model = Hardware.Specs.Keys.First(k => k.ToLowerInvariant() == model);
|
|||
|
|
var u = new Unit { Model = model, Health = 100 };
|
|||
|
|
if (item.IsTag(HealthTag)) u.Health = item.GetTagReadonly(HealthTag).GetDouble();
|
|||
|
|
if (item.IsTag(FakeTag)) u.FakeOf = item.GetTagReadonly(FakeTag).GetString();
|
|||
|
|
u.Refurbished = item.IsTag(RefurbTag);
|
|||
|
|
u.Dead = item.IsTag(DeadTag);
|
|||
|
|
return u;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static void Store(GameItem item, Unit u)
|
|||
|
|
{
|
|||
|
|
item.ModifyTag(HealthTag, s => s.Enable().SetDouble(u.Health));
|
|||
|
|
if (u.FakeOf != null) item.ModifyTag(FakeTag, s => s.Enable().SetString(u.FakeOf));
|
|||
|
|
if (u.Refurbished) item.EnableTag(RefurbTag);
|
|||
|
|
if (u.Dead) item.EnableTag(DeadTag);
|
|||
|
|
Refresh(item);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>按标签更新名字、说明、价值和图:显示的是标签上的型号(假卡也显示被冒充的型号)。</summary>
|
|||
|
|
public static void Refresh(GameItem item)
|
|||
|
|
{
|
|||
|
|
var u = ToUnit(item);
|
|||
|
|
var label = u.Label;
|
|||
|
|
if (u.Dead)
|
|||
|
|
{
|
|||
|
|
item.name = L.T("item.gpu.burnt.name", label.Brand, DisplayModel(label.Model));
|
|||
|
|
item.shortDescription = L.T("item.gpu.burnt.desc");
|
|||
|
|
item.unitValue = Math.Max(1, label.Price / 20);
|
|||
|
|
item.SetSpriteAndShapeFromMod(ModInfo.Id, "gpu_burnt");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
item.name = L.T("item.gpu.name", label.Brand, DisplayModel(label.Model));
|
|||
|
|
item.shortDescription = L.T("item.gpu.desc", Fmt.Num(label.DisplayHash), Fmt.Num(label.Kj), Mathf.RoundToInt((float)u.Health));
|
|||
|
|
item.unitValue = Math.Max(1, (long)Math.Round(label.Price * u.Health / 100));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ---------- 矿架 ----------
|
|||
|
|
|
|||
|
|
private static GameItem CreateRig()
|
|||
|
|
{
|
|||
|
|
var battery = new GameSlotInventory();
|
|||
|
|
var cards = new GameGridInventory(2, 4);
|
|||
|
|
var window = MachineHelper.CreateMachineryWindow(true,
|
|||
|
|
MachineHelper.PowerPanel(battery),
|
|||
|
|
MachineHelper.Panel(L.T("rig.label.cards"), cards, "cards"));
|
|||
|
|
var rig = ItemDirectory.CreateEmptyItem(Rig).SetContentWindow(window);
|
|||
|
|
rig.SetSpriteAndShapeFromMod(ModInfo.Id, "rig");
|
|||
|
|
rig.name = L.T("item.rig.name");
|
|||
|
|
rig.unitValue = Tuning.RigPrice;
|
|||
|
|
MachineHelper.SetupBatterySlot(battery, rig);
|
|||
|
|
rig.EnableTag("CONTAINER_TAG");
|
|||
|
|
rig.EnableTag("STANDARD_MACHINE_TAG");
|
|||
|
|
MachineryHelper.InitMachinery(rig, Tuning.RigKj);
|
|||
|
|
cards.mayInventoryAddItemFunc = (item, _) => GeneralHelper.IsItemOwned(item) && IsGpu(item) && !item.IsTag(DeadTag);
|
|||
|
|
cards.onSlotAddItemEndFunc = (_, _, _) => UpdateRig(rig, cards);
|
|||
|
|
cards.onSlotRemoveItemEndFunc = (_, _, _) => UpdateRig(rig, cards);
|
|||
|
|
rig.onLoaded = _ => UpdateRig(rig, cards);
|
|||
|
|
rig.onCycleEndEarlySlotItemFunc = (_, _, _) => Log.Guard("矿架扣电", () => NightDraw(rig, battery, cards));
|
|||
|
|
ModHelper.SetSource(rig, ModInfo.Id, ModInfo.Name);
|
|||
|
|
UpdateRig(rig, cards);
|
|||
|
|
return rig;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static List<GameItem> Cards(GameInventory cards) => cards.childItems.Where(IsGpu).ToList();
|
|||
|
|
|
|||
|
|
private static int RigKj(GameInventory cards) =>
|
|||
|
|
Tuning.RigKj + Mathf.CeilToInt((float)Cards(cards).Select(ToUnit).Sum(u => u.Kj(false)));
|
|||
|
|
|
|||
|
|
private static void UpdateRig(GameItem rig, GameInventory cards)
|
|||
|
|
{
|
|||
|
|
int kj = RigKj(cards);
|
|||
|
|
rig.ModifyTag(MachineryHelper.MACHINERY_DRAWN_POWER, s => s.Enable().SetInt(kj));
|
|||
|
|
double hash = Cards(cards).Select(ToUnit).Sum(u => u.Hash(false));
|
|||
|
|
rig.shortDescription = L.T("item.rig.desc", Fmt.Num(hash * 10), kj);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>夜间早段:按矿架上的显卡总耗电从电池扣电;扣电成功,登记今晚参与挖矿的显卡。</summary>
|
|||
|
|
private static void NightDraw(GameItem rig, GameSlotInventory battery, GameInventory cards)
|
|||
|
|
{
|
|||
|
|
var list = Cards(cards).Where(c => !c.IsTag(DeadTag)).ToList();
|
|||
|
|
Session.TonightRigs++;
|
|||
|
|
if (list.Count == 0) return;
|
|||
|
|
int kj = RigKj(cards);
|
|||
|
|
if (battery.childItems.Count == 0 || !PowerHelper.DrawPowerSource(battery.childItem, kj)) return;
|
|||
|
|
Session.TonightPoweredRigs++;
|
|||
|
|
Session.TonightKj += kj;
|
|||
|
|
Session.TonightCards.AddRange(list);
|
|||
|
|
UpdateRig(rig, cards);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 放进储藏区(游戏 EmporiumTryAdd 的默认目标,放不下时游戏自己找位置)。
|
|||
|
|
/// 不放柜台:测试中柜台上的物品过夜后会消失(未在正常流程中确认);ModHelper.MoveItemTo* 放满时会静默失败。
|
|||
|
|
/// </summary>
|
|||
|
|
public static void Give(GameItem item)
|
|||
|
|
{
|
|||
|
|
GeneralHelper.SetItemOwned(item, true);
|
|||
|
|
GraphUtils.EmporiumTryAdd(item);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|