Урна necroCinerariumProspector (и ...Skull): в «Содержимом» череп и образец - один из девяти ресурсов (камень, глина, песок, древесина, железо, свинец, уголь, селитра, сланец), нить к ящику. Дух отлетает на соседнюю свободную клетку и уходит на 5 блоков под землю, растворяясь; раз в игровой час поднимается так же, кладёт добычу в ящик и уходит снова. За сутки: камень/глина/песок/древесина 30000, руды 18000, ходка ±20%. Из руды - шанс на алмаз, серебро, золото по шансам игры на каждый «блок» руды. Ящик полон - дух ждёт с добычей. Без зоны и вне лимита урн. Рецепт - кузня: латунь 40, прах 100, кости 10, кровь/сок, железная кирка; открывается с остальными урнами. Консоль necroprospector: on/off, trip, yield, spread, depth, состояние. Тексты - 13 языков; глава книги «Цинерарии» - лист Fig. VIII с шестой урной и фраза про prospektisto. Проверено в игре (test8): ходка железа 625 в ящике, спуск и подъём духа, лист и страница книги помещаются. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
164 lines
6.5 KiB
C#
164 lines
6.5 KiB
C#
using UnityEngine;
|
|
|
|
namespace NecromancerTome
|
|
{
|
|
/// <summary>
|
|
/// «Содержимое» урны-цинерария - ячейка черепа (решение 16.10: «урна как транспорт»; переименовано из «Багажника»).
|
|
/// Окно - родное окно хранилища игры (XUiC_BagStorageWindowGroup, как сумка транспорта и сумка волка) с сумкой на одну
|
|
/// ячейку: перетаскивание, Shift+клик и правый клик - кодом игры (16.10: «Сумки, ящики в игре есть» - своё окно с
|
|
/// ячейкой коллектора не принимало череп ни перетаскиванием, ни Shift+кликом). Своё здесь одно: после каждого изменения
|
|
/// в ячейке остаётся один череп, всё остальное (лишние черепа, чужие предметы) - назад в рюкзак, и урна узнаёт, есть ли
|
|
/// в ней череп. Череп - обычный предмет (ItemClass): он уже в сейвах, менять ему класс на модификацию нельзя.
|
|
/// У урны рабочего (18.10) ячеек две: вторая - образец (любой предмет, стопка целиком - сколько держать в запасе).
|
|
/// У старателя (22.10) вторая ячейка - что добывать: один предмет из TEFeatureCinerarium.Ores, лишнее и чужое - назад.
|
|
/// </summary>
|
|
public static class CinerariumContents
|
|
{
|
|
public const string LootTemplate = "roboticDrone"; // звуки и время открытия, как у сумки волка
|
|
|
|
static TEFeatureCinerarium _urn;
|
|
/// <summary>Урна, чьё «Содержимое» сейчас открыто (окно фильтра логиста), или null.</summary>
|
|
public static TEFeatureCinerarium Urn => _urn;
|
|
static Bag _bag;
|
|
static EntityPlayerLocal _player;
|
|
|
|
public static void Open(EntityPlayerLocal _p, TEFeatureCinerarium _u)
|
|
{
|
|
LocalPlayerUI ui = _p != null ? LocalPlayerUI.GetUIForPlayer(_p) : null;
|
|
ItemValue skull = ItemClass.GetItem(TEFeatureCinerarium.SkullItemName);
|
|
if (ui == null || _u == null)
|
|
{
|
|
return;
|
|
}
|
|
_urn = _u;
|
|
_player = _p;
|
|
_bag = new Bag(new Vector2i(_u.IsWorker || _u.IsProspector ? 2 : 1, 1), XUiC_ItemStack.StackLocationTypes.LootContainer, null);
|
|
if (_u.HasSkull && skull != null && skull.type > 0)
|
|
{
|
|
_bag.SetSlot(0, new ItemStack(skull, 1));
|
|
}
|
|
if ((_u.IsWorker || _u.IsProspector) && _u.Sample != null && !_u.Sample.IsEmpty())
|
|
{
|
|
_bag.SetSlot(1, _u.Sample.Clone());
|
|
}
|
|
XUiC_BagStorageWindowGroup.Open(ui.xui, _p, _bag, LootContainer.GetLootContainer(LootTemplate),
|
|
Localization.Get("necroCinerariumTrunk"), Check, () =>
|
|
{
|
|
Check();
|
|
_urn = null;
|
|
_bag = null;
|
|
_player = null;
|
|
});
|
|
Debug.Log("[NecromancerTome] Cinerarium: «Содержимое» урны " + _u.ToWorldPos() + " открыто, череп " + (_u.HasSkull ? "есть" : "нет"));
|
|
}
|
|
|
|
/// <summary>Оставить в ячейке один череп, остальное - игроку; отметить в урне. У рабочего - запомнить образец; череп во
|
|
/// второй ячейке - не образец, переложить в первую (или вернуть).</summary>
|
|
static void Check()
|
|
{
|
|
if (_bag == null || _urn == null)
|
|
{
|
|
return;
|
|
}
|
|
if ((_urn.IsWorker || _urn.IsProspector) && _bag.ItemGrid.items.Length > 1)
|
|
{
|
|
ItemStack smp = _bag.ItemGrid.items[1];
|
|
ItemStack first = _bag.ItemGrid.items[0];
|
|
if (smp != null && !smp.IsEmpty() && smp.itemValue.ItemClass?.GetItemName() == TEFeatureCinerarium.SkullItemName &&
|
|
(first == null || first.IsEmpty()))
|
|
{
|
|
_bag.SetSlot(0, smp.Clone());
|
|
_bag.SetSlot(1, ItemStack.Empty.Clone());
|
|
smp = _bag.ItemGrid.items[1];
|
|
}
|
|
if (_urn.IsProspector && smp != null && !smp.IsEmpty())
|
|
{
|
|
// Старатель: образец - один предмет из списка добычи; чужое целиком, лишние штуки - назад.
|
|
if (!TEFeatureCinerarium.IsOreSample(smp))
|
|
{
|
|
GiveBack(smp.Clone());
|
|
_bag.SetSlot(1, ItemStack.Empty.Clone());
|
|
if (_player != null)
|
|
{
|
|
GameManager.ShowTooltip(_player, Localization.Get("necroProspectorBadSample"));
|
|
}
|
|
}
|
|
else if (smp.count > 1)
|
|
{
|
|
ItemStack back = smp.Clone();
|
|
back.count = smp.count - 1;
|
|
GiveBack(back);
|
|
ItemStack one = smp.Clone();
|
|
one.count = 1;
|
|
_bag.SetSlot(1, one);
|
|
}
|
|
smp = _bag.ItemGrid.items[1];
|
|
}
|
|
_urn.SetSample(smp != null && !smp.IsEmpty() ? smp.Clone() : ItemStack.Empty.Clone());
|
|
}
|
|
ItemStack s = _bag.ItemGrid.items[0];
|
|
bool has = false;
|
|
if (s != null && !s.IsEmpty())
|
|
{
|
|
ItemStack back = null;
|
|
if (s.itemValue.ItemClass?.GetItemName() != TEFeatureCinerarium.SkullItemName)
|
|
{
|
|
back = s.Clone();
|
|
_bag.SetSlot(0, ItemStack.Empty.Clone());
|
|
}
|
|
else
|
|
{
|
|
has = true;
|
|
if (s.count > 1)
|
|
{
|
|
back = s.Clone();
|
|
back.count = s.count - 1;
|
|
ItemStack one = s.Clone();
|
|
one.count = 1;
|
|
_bag.SetSlot(0, one);
|
|
}
|
|
}
|
|
if (back != null)
|
|
{
|
|
GiveBack(back);
|
|
}
|
|
}
|
|
_urn.SetSkull(has);
|
|
}
|
|
|
|
static void GiveBack(ItemStack _s)
|
|
{
|
|
if (_player == null)
|
|
{
|
|
return;
|
|
}
|
|
if (_player.bag != null && _player.bag.AddItem(_s))
|
|
{
|
|
return;
|
|
}
|
|
if (_player.inventory != null && _player.inventory.AddItem(_s))
|
|
{
|
|
return;
|
|
}
|
|
_player.world.gameManager.ItemDropServer(_s, _player.GetPosition(), Vector3.zero);
|
|
}
|
|
|
|
/// <summary>Урна убрана или выгружена, пока открыто её «Содержимое», - закрыть окно (череп из ячейки не потеряется:
|
|
/// Check успеет отметить его в урне, а урна при разрушении роняет череп).</summary>
|
|
public static void CloseIfShowing(TEFeatureCinerarium _u)
|
|
{
|
|
if (_urn == null || _urn != _u)
|
|
{
|
|
return;
|
|
}
|
|
Check();
|
|
LocalPlayerUI ui = _player != null ? LocalPlayerUI.GetUIForPlayer(_player) : null;
|
|
_urn = null;
|
|
if (ui != null && ui.windowManager.IsWindowOpen(XUiC_BagStorageWindowGroup.ID))
|
|
{
|
|
ui.windowManager.Close(XUiC_BagStorageWindowGroup.ID);
|
|
}
|
|
}
|
|
}
|
|
}
|