Ремонтник и лутер: зона из 3x3 квадратов, лишние выключаются (#84)

Сетка «Где работать» в «Содержимом» урны, квадраты очерчены линиями при
показе границ; выключенные квадраты обход пропускает. Сохраняется пятым
числом v6 (старая DLL его пропустит). Консоль: necrourn x y z sectors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-28 10:21:39 +03:00
co-authored by Claude Opus 5.5
parent 9a567b6ac0
commit 96d930e5bb
9 changed files with 302 additions and 17 deletions
+74 -11
View File
@@ -264,8 +264,9 @@ namespace NecromancerTome
AppendVia(via, l);
}
CinerariumWriteHelper.WriteInts(_bw, via.ToArray());
// v6: ремонтник/лутер - сторона зоны, идёт ли проход, где курсор обхода, кто нажал кнопку.
CinerariumWriteHelper.WriteInts(_bw, new[] { ZoneSide, ZoneRunning ? 1 : 0, ZoneCursor, ZonePressedBy });
// v6: ремонтник/лутер - сторона зоны, идёт ли проход, где курсор обхода, кто нажал кнопку; пятое (28.10, #84) -
// выключенные квадраты зоны. Числа идут со счётчиком - старая DLL пятое просто пропустит, версия та же.
CinerariumWriteHelper.WriteInts(_bw, new[] { ZoneSide, ZoneRunning ? 1 : 0, ZoneCursor, ZonePressedBy, ZoneOff });
}
static void AppendVia(List<int> _dst, List<Vector3i> _l)
@@ -411,6 +412,7 @@ namespace NecromancerTome
ZoneRunning = false;
ZoneCursor = 0;
ZonePressedBy = -1;
ZoneOff = 0;
if (version >= 6)
{
int n = _br.ReadInt32();
@@ -423,6 +425,7 @@ namespace NecromancerTome
ZoneRunning = n > 1 && v[1] != 0;
ZoneCursor = n > 2 ? v[2] : 0;
ZonePressedBy = n > 3 ? v[3] : -1;
ZoneOff = n > 4 ? v[4] : 0;
}
_threadsDirty = true;
if (version > SaveVersion)
@@ -1099,19 +1102,11 @@ namespace NecromancerTome
}
_bounds = new GameObject("NecroCinerariumBounds");
_bounds.transform.SetParent(t, false);
LineRenderer lr = _bounds.AddComponent<LineRenderer>();
lr.useWorldSpace = false;
lr.widthMultiplier = 0.06f;
if (_boundsMat == null)
{
_boundsMat = new Material(Shader.Find("Sprites/Default")) { name = "NecroCinerariumBounds" };
}
lr.sharedMaterial = _boundsMat;
Color col = new Color(0.55f, 0.9f, 0.75f, 0.85f);
lr.startColor = col;
lr.endColor = col;
lr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
lr.receiveShadows = false;
LineRenderer lr = BoundsLine(_bounds, BoundsOn);
// Углы по граням блоков: x и z от -2.5 до +2.5 от центра урны, y от низа блока под ней до верха +4. Большая зона
// (ремонтник, лутер) - сторона ZoneSideNow, по высоте весь столб мира.
@@ -1129,6 +1124,74 @@ namespace NecromancerTome
{
lr.SetPosition(i, t.InverseTransformPoint(path[i]));
}
if (IsBigZone)
{
SpawnSectorLines(t, c, x0, z0, y0, y1);
}
}
static readonly Color BoundsOn = new Color(0.55f, 0.9f, 0.75f, 0.85f);
static readonly Color BoundsOff = new Color(0.95f, 0.3f, 0.25f, 0.85f);
/// <summary>Ломаная границ - дочерний объект _parent (уходит с ним в RemoveBounds), материал общий.</summary>
static LineRenderer BoundsLine(GameObject _parent, Color _col)
{
GameObject go = _parent;
if (go.GetComponent<LineRenderer>() != null)
{
go = new GameObject("NecroCinerariumBoundsLine");
go.transform.SetParent(_parent.transform, false);
}
LineRenderer lr = go.AddComponent<LineRenderer>();
lr.useWorldSpace = false;
lr.widthMultiplier = 0.06f;
lr.sharedMaterial = _boundsMat;
lr.startColor = _col;
lr.endColor = _col;
lr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
lr.receiveShadows = false;
return lr;
}
/// <summary>Квадраты большой зоны (#84): на уровне пола урны - рамка каждого квадрата (включён - зелёная, выключен - красная
/// с крестом), чуть отступив внутрь, чтобы соседние не сливались; на границах квадратов - вертикали на всю высоту зоны.</summary>
void SpawnSectorLines(Transform _t, Vector3 _c, float _x0, float _z0, float _y0, float _y1)
{
int side = ZoneSideNow;
float y = _c.y + 0.05f, inset = 0.2f;
float Edge(float _from, int _k) => _from + BandStart(_k, side);
for (int sz = 0; sz < ZoneGrid; sz++)
{
for (int sx = 0; sx < ZoneGrid; sx++)
{
bool on = SectorOn(sx + sz * ZoneGrid);
float ax = Edge(_x0, sx) + inset, bx = Edge(_x0, sx + 1) - inset;
float az = Edge(_z0, sz) + inset, bz = Edge(_z0, sz + 1) - inset;
Vector3 p0 = new Vector3(ax, y, az), p1 = new Vector3(bx, y, az), p2 = new Vector3(bx, y, bz), p3 = new Vector3(ax, y, bz);
Vector3[] path = on ? new[] { p0, p1, p2, p3, p0 } : new[] { p0, p1, p2, p3, p0, p2, p1, p3 };
LineRenderer lr = BoundsLine(_bounds, on ? BoundsOn : BoundsOff);
lr.positionCount = path.Length;
for (int i = 0; i < path.Length; i++)
{
lr.SetPosition(i, _t.InverseTransformPoint(path[i]));
}
}
}
// Вертикали - во всех узлах сетки, кроме углов зоны (их уже рисует рамка).
for (int kz = 0; kz <= ZoneGrid; kz++)
{
for (int kx = 0; kx <= ZoneGrid; kx++)
{
if ((kx == 0 || kx == ZoneGrid) && (kz == 0 || kz == ZoneGrid))
{
continue;
}
LineRenderer lr = BoundsLine(_bounds, BoundsOn);
lr.positionCount = 2;
lr.SetPosition(0, _t.InverseTransformPoint(new Vector3(Edge(_x0, kx), _y0, Edge(_z0, kz))));
lr.SetPosition(1, _t.InverseTransformPoint(new Vector3(Edge(_x0, kx), _y1, Edge(_z0, kz))));
}
}
}
public void RemoveBounds()