Урны ремонтника и лутера: большая зона, запуск кнопкой, кнопки-состояния
- necroCinerariumRepair/+Skull и necroCinerariumLoot/+Skull (пока на модели урны сборщика), рецепты (урна + ремкомплект / отмычка, на крови и на соке), открываются с урнами. - Зона - сторона притязания сервера или 31/21/11 (пункт «Размер зоны»), весь столб мира, каркас по «Показать границы»; работа - по «Запустить», один проход, «Остановить». - Ремонтник: обход столбов из общего бюджета клеток, очередь повреждённых блоков с RepairItems (зоны пересекаются - блок берёт первый), ремонт раз в 2.5 с материалами из ящиков по нитям (доля по повреждению), не хватает - ждёт с мигающей кнопкой. - Лутер: предметы на земле, мешки с зомби, красные трупы (тем же путём, что игрок, с находкой черепа) - в ящик с любой нитью; рюкзаки игроков и аэродроп не трогает. - Кнопки на модели (рендереры «button»): жёлтая - ждёт, мигает - нехватка/ящик полон, зелёная - работа, красная - прилив. Запись урны v6 (зона, проход, курсор, кто нажал). - Тексты 13 языков; команды разработки necrodamage, necrodrop, necrobag, necrocorpse, necrourn run|stop|size. Проверено в игре: ремонтник (нехватка -> материалы -> починил 2 блока), лутер (предметы с земли). Мешки и красные трупы - не проверены. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
85d8036e81
commit
a352a408a4
+83
-19
@@ -27,7 +27,7 @@ namespace NecromancerTome
|
||||
/// Имена команд не должны кончаться на zone_show/zone_hide/effect_on/effect_off: заплатка пирамиды на
|
||||
/// BlockCompositeTileEntity.OnBlockActivated ловит их по EndsWith у ЛЮБОГО составного блока.
|
||||
/// </summary>
|
||||
public class TEFeatureCinerarium : TEFeatureAbs
|
||||
public partial class TEFeatureCinerarium : TEFeatureAbs
|
||||
{
|
||||
public const string BlockName = "necroCinerarium";
|
||||
public const string SkullBlockName = "necroCinerariumSkull";
|
||||
@@ -62,8 +62,9 @@ namespace NecromancerTome
|
||||
return n == WorkerBlockName || n == WorkerSkullBlockName;
|
||||
}
|
||||
|
||||
/// <summary>Урна без зоны (логист, рабочий): ставится вплотную к любым урнам, в лимит не входит, работает по нитям.</summary>
|
||||
public static bool IsZonelessBlock(Block _b) => IsLogistBlock(_b) || IsWorkerBlock(_b);
|
||||
/// <summary>Урна без зоны 5x5 (логист, рабочий, ремонтник, лутер): ставится вплотную к любым урнам, в лимит не входит,
|
||||
/// работает по нитям. У ремонтника и лутера своя большая зона (CinerariumZone.cs) - зоны таких урн могут пересекаться.</summary>
|
||||
public static bool IsZonelessBlock(Block _b) => IsLogistBlock(_b) || IsWorkerBlock(_b) || IsRepairBlock(_b) || IsLootBlock(_b);
|
||||
public const string SkullItemName = "necroSkull";
|
||||
public const int HalfWidth = 2;
|
||||
public const int Below = 1;
|
||||
@@ -71,7 +72,7 @@ namespace NecromancerTome
|
||||
/// <summary>Убийств на одну урну сборщика. 17.10: «лимит урн - ослабить/убрать» - нагрузку теперь держит общий бюджет
|
||||
/// шагов (CinerariumLoad), лимит остался мягким игровым порогом: было 500, стало 200.</summary>
|
||||
public const float KillsPerUrn = 200f;
|
||||
const byte SaveVersion = 5; // 2 - нити, 3 - фильтр логиста (16.10), 4 - нити рабочего «куда» и образец (18.10), 5 - черепа-ретрансляторы (18.10)
|
||||
const byte SaveVersion = 6; // 2 - нити, 3 - фильтр логиста (16.10), 4 - нити рабочего «куда» и образец (18.10), 5 - черепа-ретрансляторы (18.10), 6 - зона и запуск ремонтника/лутера (18.10)
|
||||
|
||||
public bool HasSkull;
|
||||
public bool ZoneShown;
|
||||
@@ -102,7 +103,7 @@ namespace NecromancerTome
|
||||
}
|
||||
}
|
||||
bool _worker;
|
||||
public bool IsZoneless => IsLogist || IsWorker;
|
||||
public bool IsZoneless => IsLogist || IsWorker || IsBigZone;
|
||||
/// <summary>Урна-логист - по блоку (necroCinerariumLogist / ...Skull); узнаётся при постановке или по миру.</summary>
|
||||
public bool IsLogist
|
||||
{
|
||||
@@ -116,6 +117,8 @@ namespace NecromancerTome
|
||||
{
|
||||
_logist = IsLogistBlock(bv.Block);
|
||||
_worker = IsWorkerBlock(bv.Block);
|
||||
_repair = IsRepairBlock(bv.Block);
|
||||
_loot = IsLootBlock(bv.Block);
|
||||
_logistKnown = true;
|
||||
}
|
||||
}
|
||||
@@ -163,15 +166,18 @@ namespace NecromancerTome
|
||||
base.OnAdded(_blockPos, _blockValue);
|
||||
_logist = IsLogistBlock(_blockValue.Block);
|
||||
_worker = IsWorkerBlock(_blockValue.Block);
|
||||
_repair = IsRepairBlock(_blockValue.Block);
|
||||
_loot = IsLootBlock(_blockValue.Block);
|
||||
_logistKnown = true;
|
||||
string placed = _blockValue.Block?.GetBlockName();
|
||||
if (placed == SkullBlockName || placed == LogistSkullBlockName || placed == LogistWallSkullBlockName || placed == WorkerSkullBlockName)
|
||||
if (placed == SkullBlockName || placed == LogistSkullBlockName || placed == LogistWallSkullBlockName || placed == WorkerSkullBlockName ||
|
||||
placed == RepairSkullBlockName || placed == LootSkullBlockName)
|
||||
{
|
||||
HasSkull = true; // поставили урну, поднятую с черепом
|
||||
}
|
||||
if (ConnectionManager.Instance.IsServer)
|
||||
{
|
||||
CinerariumRegistry.Add(_blockPos, Parent?.Owner, _logist || _worker);
|
||||
CinerariumRegistry.Add(_blockPos, Parent?.Owner, _logist || _worker || _repair || _loot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +189,7 @@ namespace NecromancerTome
|
||||
RemoveThreadView();
|
||||
RemoveGenie(false);
|
||||
CinerariumContents.CloseIfShowing(this);
|
||||
ZoneStop(false);
|
||||
if (!ConnectionManager.Instance.IsServer)
|
||||
{
|
||||
return;
|
||||
@@ -253,6 +260,8 @@ namespace NecromancerTome
|
||||
AppendVia(via, l);
|
||||
}
|
||||
CinerariumWriteHelper.WriteInts(_bw, via.ToArray());
|
||||
// v6: ремонтник/лутер - сторона зоны, идёт ли проход, где курсор обхода, кто нажал кнопку.
|
||||
CinerariumWriteHelper.WriteInts(_bw, new[] { ZoneSide, ZoneRunning ? 1 : 0, ZoneCursor, ZonePressedBy });
|
||||
}
|
||||
|
||||
static void AppendVia(List<int> _dst, List<Vector3i> _l)
|
||||
@@ -389,6 +398,23 @@ namespace NecromancerTome
|
||||
}
|
||||
}
|
||||
AlignVia();
|
||||
ZoneSide = 0;
|
||||
ZoneRunning = false;
|
||||
ZoneCursor = 0;
|
||||
ZonePressedBy = -1;
|
||||
if (version >= 6)
|
||||
{
|
||||
int n = _br.ReadInt32();
|
||||
int[] v = new int[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
v[i] = _br.ReadInt32();
|
||||
}
|
||||
ZoneSide = n > 0 ? v[0] : 0;
|
||||
ZoneRunning = n > 1 && v[1] != 0;
|
||||
ZoneCursor = n > 2 ? v[2] : 0;
|
||||
ZonePressedBy = n > 3 ? v[3] : -1;
|
||||
}
|
||||
_threadsDirty = true;
|
||||
if (version > SaveVersion)
|
||||
{
|
||||
@@ -410,13 +436,18 @@ namespace NecromancerTome
|
||||
_addCallback(new BlockActivationCommand("urn_repair", "wrench", _enabled: false), TileEntityComposite.EBlockCommandOrder.Normal, FeatureData);
|
||||
_addCallback(new BlockActivationCommand("bounds_show", "frames", _enabled: false), TileEntityComposite.EBlockCommandOrder.Normal, FeatureData);
|
||||
_addCallback(new BlockActivationCommand("bounds_hide", "frames", _enabled: false), TileEntityComposite.EBlockCommandOrder.Normal, FeatureData);
|
||||
// Ремонтник, лутер (CinerariumZone.cs): запуск прохода кнопкой, остановка, размер зоны.
|
||||
_addCallback(new BlockActivationCommand("zurn_run", "electric_switch", _enabled: false), TileEntityComposite.EBlockCommandOrder.Normal, FeatureData);
|
||||
_addCallback(new BlockActivationCommand("zurn_stop", "electric_switch", _enabled: false), TileEntityComposite.EBlockCommandOrder.Normal, FeatureData);
|
||||
_addCallback(new BlockActivationCommand("zurn_size", "map_cursor", _enabled: false), TileEntityComposite.EBlockCommandOrder.Normal, FeatureData);
|
||||
}
|
||||
|
||||
public override string GetActivationText(WorldBase _world, Vector3i _blockPos, BlockValue _blockValue, EntityAlive _entityFocusing, string _activateHotkeyMarkup, string _focusedTileEntityName)
|
||||
{
|
||||
base.GetActivationText(_world, _blockPos, _blockValue, _entityFocusing, _activateHotkeyMarkup, _focusedTileEntityName);
|
||||
return _activateHotkeyMarkup + " " + _blockValue.Block.GetLocalizedBlockName() + " - " +
|
||||
Localization.Get(HasSkull ? "necroCinerariumStateSkull" : "necroCinerariumStateEmpty");
|
||||
string s = _activateHotkeyMarkup + " " + _blockValue.Block.GetLocalizedBlockName() + " - " +
|
||||
Localization.Get(HasSkull ? "necroCinerariumStateSkull" : "necroCinerariumStateEmpty");
|
||||
return IsBigZone ? s + ZoneStateText() : s;
|
||||
}
|
||||
|
||||
public override void UpdateTick(World _world)
|
||||
@@ -716,6 +747,11 @@ namespace NecromancerTome
|
||||
_pending = false;
|
||||
return;
|
||||
}
|
||||
if (IsBigZone)
|
||||
{
|
||||
ZoneWork(_world); // ремонтник, лутер - CinerariumZone.cs
|
||||
return;
|
||||
}
|
||||
CinerariumGenieMotion motion = _genie != null ? _genie.GetComponent<CinerariumGenieMotion>() : null;
|
||||
if (_pending)
|
||||
{
|
||||
@@ -926,7 +962,7 @@ namespace NecromancerTome
|
||||
foreach (Renderer r in t.GetComponentsInChildren<Renderer>(true))
|
||||
{
|
||||
if (_genie != null && r.transform.IsChildOf(_genie.transform) || _bounds != null && r.transform.IsChildOf(_bounds.transform) ||
|
||||
_threadView != null && r.transform.IsChildOf(_threadView.transform))
|
||||
_threadView != null && r.transform.IsChildOf(_threadView.transform) || CinerariumButtons.IsButton(r))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1013,11 +1049,13 @@ namespace NecromancerTome
|
||||
lr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
||||
lr.receiveShadows = false;
|
||||
|
||||
// Углы по граням блоков: x и z от -2.5 до +2.5 от центра урны, y от низа блока под ней до верха +4.
|
||||
// Углы по граням блоков: x и z от -2.5 до +2.5 от центра урны, y от низа блока под ней до верха +4. Большая зона
|
||||
// (ремонтник, лутер) - сторона ZoneSideNow, по высоте весь столб мира.
|
||||
Vector3 c = World.blockToTransformPos(ToWorldPos()) - Origin.position;
|
||||
float x0 = c.x - HalfWidth - 0.5f, x1 = c.x + HalfWidth + 0.5f;
|
||||
float z0 = c.z - HalfWidth - 0.5f, z1 = c.z + HalfWidth + 0.5f;
|
||||
float y0 = c.y - Below, y1 = c.y + Above + 1f;
|
||||
int hw = IsBigZone ? ZoneSideNow / 2 : HalfWidth;
|
||||
float x0 = c.x - hw - 0.5f, x1 = c.x + hw + 0.5f;
|
||||
float z0 = c.z - hw - 0.5f, z1 = c.z + hw + 0.5f;
|
||||
float y0 = IsBigZone ? -Origin.position.y + 1f : c.y - Below, y1 = IsBigZone ? -Origin.position.y + 254f : c.y + Above + 1f;
|
||||
Vector3 b0 = new Vector3(x0, y0, z0), b1 = new Vector3(x1, y0, z0), b2 = new Vector3(x1, y0, z1), b3 = new Vector3(x0, y0, z1);
|
||||
Vector3 t0 = new Vector3(x0, y1, z0), t1 = new Vector3(x1, y1, z0), t2 = new Vector3(x1, y1, z1), t3 = new Vector3(x0, y1, z1);
|
||||
// Одна ломаная по всем 12 рёбрам (часть рёбер проходится дважды - на глаз не видно).
|
||||
@@ -1046,7 +1084,8 @@ namespace NecromancerTome
|
||||
{
|
||||
string n = _b?.GetBlockName();
|
||||
return n == BlockName || n == SkullBlockName || n == LogistBlockName || n == LogistSkullBlockName ||
|
||||
n == LogistWallBlockName || n == LogistWallSkullBlockName || n == WorkerBlockName || n == WorkerSkullBlockName;
|
||||
n == LogistWallBlockName || n == LogistWallSkullBlockName || n == WorkerBlockName || n == WorkerSkullBlockName ||
|
||||
IsRepairBlock(_b) || IsLootBlock(_b);
|
||||
}
|
||||
|
||||
public static int UrnLimit(EntityPlayer _player)
|
||||
@@ -1261,11 +1300,23 @@ namespace NecromancerTome
|
||||
}
|
||||
else if (text.EndsWith("bounds_show"))
|
||||
{
|
||||
_commands[i].enabled = !urn.ZoneShown && !urn.IsZoneless;
|
||||
_commands[i].enabled = !urn.ZoneShown && (!urn.IsZoneless || urn.IsBigZone);
|
||||
}
|
||||
else if (text.EndsWith("bounds_hide"))
|
||||
{
|
||||
_commands[i].enabled = urn.ZoneShown && !urn.IsZoneless;
|
||||
_commands[i].enabled = urn.ZoneShown && (!urn.IsZoneless || urn.IsBigZone);
|
||||
}
|
||||
else if (text.EndsWith("zurn_run"))
|
||||
{
|
||||
_commands[i].enabled = urn.IsBigZone && urn.HasSkull && !urn.ZoneRunning;
|
||||
}
|
||||
else if (text.EndsWith("zurn_stop"))
|
||||
{
|
||||
_commands[i].enabled = urn.IsBigZone && urn.ZoneRunning;
|
||||
}
|
||||
else if (text.EndsWith("zurn_size"))
|
||||
{
|
||||
_commands[i].enabled = urn.IsBigZone;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1284,7 +1335,8 @@ namespace NecromancerTome
|
||||
bool repair = _commandName.EndsWith("urn_repair");
|
||||
bool bag = _commandName.EndsWith("TEFeatureCinerarium:bag");
|
||||
bool bounds = _commandName.EndsWith("bounds_show") || _commandName.EndsWith("bounds_hide");
|
||||
if (!skull && !bounds && !repair && !bag)
|
||||
bool zone = _commandName.EndsWith("zurn_run") || _commandName.EndsWith("zurn_stop") || _commandName.EndsWith("zurn_size");
|
||||
if (!skull && !bounds && !repair && !bag && !zone)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1299,6 +1351,12 @@ namespace NecromancerTome
|
||||
__result = composite.OnBlockActivated(null, "TEFeatureStorage:Search", world, _blockPos, world.GetBlock(_blockPos), _player);
|
||||
return false;
|
||||
}
|
||||
if (zone)
|
||||
{
|
||||
urn.ZoneCommand(_commandName, _player);
|
||||
__result = true;
|
||||
return false;
|
||||
}
|
||||
if (skull)
|
||||
{
|
||||
CinerariumContents.Open(_player, urn);
|
||||
@@ -1408,7 +1466,13 @@ namespace NecromancerTome
|
||||
bool logist = TEFeatureCinerarium.IsLogistBlock(bv.Block);
|
||||
bool wall = TEFeatureCinerarium.IsLogistWallBlock(bv.Block);
|
||||
bool worker = TEFeatureCinerarium.IsWorkerBlock(bv.Block);
|
||||
ItemValue iv = ItemClass.GetItem(wall
|
||||
bool repairUrn = TEFeatureCinerarium.IsRepairBlock(bv.Block);
|
||||
bool lootUrn = TEFeatureCinerarium.IsLootBlock(bv.Block);
|
||||
ItemValue iv = ItemClass.GetItem(repairUrn
|
||||
? (urn.HasSkull ? TEFeatureCinerarium.RepairSkullBlockName : TEFeatureCinerarium.RepairBlockName)
|
||||
: lootUrn
|
||||
? (urn.HasSkull ? TEFeatureCinerarium.LootSkullBlockName : TEFeatureCinerarium.LootBlockName)
|
||||
: wall
|
||||
? (urn.HasSkull ? TEFeatureCinerarium.LogistWallSkullBlockName : TEFeatureCinerarium.LogistWallBlockName)
|
||||
: logist
|
||||
? (urn.HasSkull ? TEFeatureCinerarium.LogistSkullBlockName : TEFeatureCinerarium.LogistBlockName)
|
||||
|
||||
Reference in New Issue
Block a user