- Модели (BlenderWork/necroCinerariumRepair, necroCinerariumLoot): ремонтник - квадратная фляга, лутер - глазурованный мешок с верёвкой; на обоих - четыре латунных звонка с черепом-кнопкой (деталь *_button - подсветка состояния) и руны кровью футарком («RIPARU ĜIS LA LASTA BRIKO», «KOLEKTU ĜIS LA LASTA PECETO»), светятся по черепу. - Лутер: цели, из которых за проход нечего взять, второй раз не обыскиваются (не зацикливается). - Разработка: necroclear (убрать только растения), necrobag с сумкой по списку добычи. Проверено в игре: мешок с зомби и красный труп (прах, кожа жертвы) - в ящик, проход заканчивается сам. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
468 lines
20 KiB
C#
468 lines
20 KiB
C#
using System.Collections.Generic;
|
||
using System.Globalization;
|
||
using System.Text;
|
||
using UnityEngine;
|
||
using UnityEngine.Scripting;
|
||
|
||
namespace NecromancerTome
|
||
{
|
||
/// <summary>
|
||
/// Команды разработки для проверок без мыши (18.10.2026: «И управление персонажем тоже, чтобы ты мог его повернуть как надо,
|
||
/// довести куда надо»). Набираются через почтовый ящик (NecroMailbox), ответы - в лог. Перемещение - teleport игры
|
||
/// (tp x y z), время - settime, предметы - giveself; здесь - то, чего у игры нет.
|
||
/// necrolook yaw [pitch] | necrolook at x y z - повернуть взгляд (градусы; север 0, восток 90; pitch вверх +, вниз -)
|
||
/// necroaim - позиция игрока и блок под прицелом
|
||
/// necroplace блок x y z [поворот 0-3] - поставить блок (как игрок: OnBlockAdded, TE)
|
||
/// necrohold предмет [число] - положить в текущую ячейку пояса и взять в руку
|
||
/// necrobox x y z list|clear|add предмет число - содержимое хранилища (ящик, сумка урны)
|
||
/// necrourn x y z info|skull 0|1|from|to|out bx by bz|clear|sample предмет число|group все|нет - урна
|
||
/// necroclick 0|1 - отпущенная ЛКМ/ПКМ ножом для нитей по блоку под прицелом
|
||
/// </summary>
|
||
public static class NecroDev
|
||
{
|
||
static void Out(string _s) => SdtdConsole.Instance.Output(_s);
|
||
|
||
static float F(string _s) => float.Parse(_s, CultureInfo.InvariantCulture);
|
||
|
||
static Vector3i P(List<string> _p, int _i) => new Vector3i(int.Parse(_p[_i]), int.Parse(_p[_i + 1]), int.Parse(_p[_i + 2]));
|
||
|
||
/// <summary>Общий вход всех команд: игрок есть - выполнить, ошибка - строкой в ответ.</summary>
|
||
public static void Run(string _cmd, List<string> _params)
|
||
{
|
||
World w = GameManager.Instance.World;
|
||
EntityPlayerLocal pl = w?.GetPrimaryPlayer();
|
||
if (pl == null)
|
||
{
|
||
Out(_cmd + ": нет игрока");
|
||
return;
|
||
}
|
||
try
|
||
{
|
||
switch (_cmd)
|
||
{
|
||
case "necrolook": Look(pl, _params); break;
|
||
case "necroaim": Aim(w, pl); break;
|
||
case "necroplace": PlaceBlock(w, _params); break;
|
||
case "necrohold": Hold(pl, _params); break;
|
||
case "necrobox": Box(w, _params); break;
|
||
case "necrourn": Urn(w, _params); break;
|
||
case "necrodamage":
|
||
{
|
||
// necrodamage x y z урон - повредить блок (проверка ремонтника)
|
||
Vector3i dp = P(_params, 0);
|
||
BlockValue dbv = w.GetBlock(dp);
|
||
dbv.damage = Mathf.Min(dbv.Block.MaxDamage - 1, dbv.damage + int.Parse(_params[3]));
|
||
w.SetBlockRPC(dp, dbv);
|
||
Out("necrodamage: " + dbv.Block.GetBlockName() + " в " + dp + " повреждение " + dbv.damage + "/" + dbv.Block.MaxDamage);
|
||
break;
|
||
}
|
||
case "necrodrop":
|
||
{
|
||
// necrodrop предмет число x y z - бросить на землю (проверка лутера)
|
||
ItemValue div = ItemClass.GetItem(_params[0], true);
|
||
GameManager.Instance.ItemDropServer(new ItemStack(div, int.Parse(_params[1])), P(_params, 2).ToVector3() + new Vector3(0.5f, 0.5f, 0.5f), Vector3.zero);
|
||
Out("necrodrop: " + _params[0] + " x" + _params[1]);
|
||
break;
|
||
}
|
||
case "necrobag":
|
||
{
|
||
// necrobag x y z - мешок с зомби (EntityLootContainer со списком cntDropBag), нетронутый
|
||
Entity bag = EntityFactory.CreateEntity(EntityClass.FromString("DroppedLootContainer"), P(_params, 0).ToVector3() + new Vector3(0.5f, 0.3f, 0.5f));
|
||
bag.lootList = "cntDropBag";
|
||
LootContainer lc = LootContainer.GetLootContainer(bag.lootList, false);
|
||
if (lc != null)
|
||
{
|
||
bag.bag = new Bag(lc.size, XUiC_ItemStack.StackLocationTypes.LootContainer, bag);
|
||
}
|
||
w.SpawnEntityInWorld(bag);
|
||
Out("necrobag: " + bag.entityId);
|
||
break;
|
||
}
|
||
case "necrocorpse":
|
||
{
|
||
// necrocorpse x y z [класс] - зомби, убитый и помеченный красным трупом (как VictimPatch)
|
||
string cls = _params.Count > 3 ? _params[3] : "zombieArlene";
|
||
EntityAlive z = EntityFactory.CreateEntity(EntityClass.FromString(cls), P(_params, 0).ToVector3() + new Vector3(0.5f, 0.1f, 0.5f)) as EntityAlive;
|
||
w.SpawnEntityInWorld(z);
|
||
ThreadManager.StartCoroutine(KillAndMark(z));
|
||
Out("necrocorpse: " + z.entityId + " " + cls);
|
||
break;
|
||
}
|
||
case "necroclear":
|
||
{
|
||
// necroclear x0 z0 x1 z1 [y0 y1] - убрать только растения (трава, кусты) в прямоугольнике; землю и постройки
|
||
// не трогает (18.10: «necroplace air» по ровной высоте срезал рельеф - яма в test8).
|
||
int x0 = int.Parse(_params[0]), z0 = int.Parse(_params[1]), x1 = int.Parse(_params[2]), z1 = int.Parse(_params[3]);
|
||
int y0 = _params.Count > 5 ? int.Parse(_params[4]) : 1, y1 = _params.Count > 5 ? int.Parse(_params[5]) : 250;
|
||
int n = 0;
|
||
for (int x = Mathf.Min(x0, x1); x <= Mathf.Max(x0, x1); x++)
|
||
{
|
||
for (int z = Mathf.Min(z0, z1); z <= Mathf.Max(z0, z1); z++)
|
||
{
|
||
for (int y = y0; y <= y1; y++)
|
||
{
|
||
BlockValue cb = w.GetBlock(x, y, z);
|
||
if (!cb.isair && cb.Block != null && cb.Block.IsPlant())
|
||
{
|
||
w.SetBlockRPC(new Vector3i(x, y, z), BlockValue.Air);
|
||
n++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
Out("necroclear: растений убрано " + n);
|
||
break;
|
||
}
|
||
case "necrogod": God(pl, _params.Count == 0 || _params[0] != "off"); break;
|
||
case "necroclick":
|
||
// necroclick 0|1 [x y z] - по блоку под прицелом или по указанной клетке (луч не всегда попадает в низкий череп).
|
||
if (_params.Count >= 4)
|
||
{
|
||
CinerariumThreads.ClickAt(pl, w, P(_params, 1), _params[0] == "1");
|
||
}
|
||
else
|
||
{
|
||
CinerariumThreads.Click(pl, _params.Count > 0 && _params[0] == "1");
|
||
}
|
||
Out("necroclick: ok");
|
||
break;
|
||
}
|
||
}
|
||
catch (System.Exception e)
|
||
{
|
||
Out(_cmd + ": ошибка - " + e.Message);
|
||
}
|
||
}
|
||
|
||
static void Look(EntityPlayerLocal _pl, List<string> _p)
|
||
{
|
||
float yaw, pitch = 0f;
|
||
if (_p.Count >= 4 && _p[0] == "at")
|
||
{
|
||
Vector3 eye = _pl.getHeadPosition();
|
||
Vector3 t = new Vector3(F(_p[1]) + 0.5f, F(_p[2]) + 0.5f, F(_p[3]) + 0.5f);
|
||
Vector3 d = t - eye;
|
||
yaw = Mathf.Atan2(d.x, d.z) * Mathf.Rad2Deg;
|
||
pitch = Mathf.Atan2(d.y, new Vector2(d.x, d.z).magnitude) * Mathf.Rad2Deg; // в игре + вверх
|
||
}
|
||
else
|
||
{
|
||
yaw = F(_p[0]);
|
||
if (_p.Count > 1)
|
||
{
|
||
pitch = F(_p[1]);
|
||
}
|
||
}
|
||
_pl.TeleportToPosition(_pl.position, false, new Vector3(pitch, yaw, 0f));
|
||
Out("necrolook: yaw " + yaw.ToString("F0") + ", pitch " + pitch.ToString("F0"));
|
||
}
|
||
|
||
/// <summary>Режим бога и невидимость для ИИ: пока ассистент проверяет, персонаж стоит - зомби тестового мира его не трогают
|
||
/// (18.10: «пока персонаж просто стоит, его скушают»; «Я обычно ставлю режим Бога»).</summary>
|
||
static void God(EntityPlayerLocal _pl, bool _on)
|
||
{
|
||
_pl.IsGodMode.Value = _on;
|
||
_pl.SetIgnoredByAI(_on);
|
||
Out("necrogod: " + (_on ? "бог, ИИ не видит" : "обычный"));
|
||
}
|
||
|
||
static System.Collections.IEnumerator KillAndMark(EntityAlive _z)
|
||
{
|
||
yield return new WaitForSeconds(1f);
|
||
_z.DamageEntity(new DamageSource(EnumDamageSource.Internal, EnumDamageTypes.Suicide), 99999, false);
|
||
yield return new WaitForSeconds(1f);
|
||
if (_z.IsDead())
|
||
{
|
||
CorpseLoot.MarkCorpse(_z);
|
||
}
|
||
UnityEngine.Debug.Log("[NecromancerTome] mailbox: necrocorpse: " + _z.entityId + (_z.IsDead() ? " убит и помечен" : " НЕ умер"));
|
||
}
|
||
|
||
static void Aim(World _w, EntityPlayerLocal _pl)
|
||
{
|
||
StringBuilder sb = new StringBuilder("necroaim: игрок ").Append(_pl.position.ToString("F1")).Append(", взгляд ").Append(_pl.rotation.ToString("F0"));
|
||
WorldRayHitInfo hi = _pl.HitInfo;
|
||
if (hi != null && hi.bHitValid)
|
||
{
|
||
BlockValue bv = _w.GetBlock(hi.hit.blockPos);
|
||
sb.Append(", под прицелом ").Append(hi.hit.blockPos).Append(' ').Append(bv.Block?.GetBlockName()).Append(" rot ").Append(bv.rotation)
|
||
.Append(", дальность ").Append(Mathf.Sqrt(hi.hit.distanceSq).ToString("F1"));
|
||
}
|
||
else
|
||
{
|
||
sb.Append(", под прицелом ничего");
|
||
}
|
||
Out(sb.ToString());
|
||
}
|
||
|
||
static void PlaceBlock(World _w, List<string> _p)
|
||
{
|
||
Block b = Block.GetBlockByName(_p[0], true);
|
||
if (b == null)
|
||
{
|
||
Out("necroplace: нет блока " + _p[0]);
|
||
return;
|
||
}
|
||
BlockValue bv = b.ToBlockValue();
|
||
if (_p.Count > 4)
|
||
{
|
||
bv.rotation = (byte)int.Parse(_p[4]);
|
||
}
|
||
Vector3i pos = P(_p, 1);
|
||
_w.SetBlockRPC(pos, bv);
|
||
// Как поставленный игроком (хозяин - мы): ящики без хозяина нити и духи не считают ящиками игрока.
|
||
if (_w.GetTileEntity(pos) is TileEntityComposite comp && comp.Owner == null)
|
||
{
|
||
comp.SetOwner(Platform.PlatformManager.InternalLocalUserIdentifier);
|
||
}
|
||
Out("necroplace: " + b.GetBlockName() + " в " + pos + " rot " + bv.rotation);
|
||
}
|
||
|
||
static void Hold(EntityPlayerLocal _pl, List<string> _p)
|
||
{
|
||
ItemValue iv = ItemClass.GetItem(_p[0], true);
|
||
if (iv == null || iv.IsEmpty())
|
||
{
|
||
Out("necrohold: нет предмета " + _p[0]);
|
||
return;
|
||
}
|
||
int n = _p.Count > 1 ? int.Parse(_p[1]) : 1;
|
||
if (iv.ItemClass.HasQuality)
|
||
{
|
||
iv = new ItemValue(iv.type, 1, 1, true);
|
||
}
|
||
_pl.inventory.SetItem(_pl.inventory.holdingItemIdx, new ItemStack(iv, n));
|
||
Out("necrohold: " + iv.ItemClass.GetItemName() + " x" + n + " в ячейке " + _pl.inventory.holdingItemIdx);
|
||
}
|
||
|
||
static TEFeatureStorage StorageAt(World _w, Vector3i _p)
|
||
{
|
||
BlockValue bv = _w.GetBlock(_p);
|
||
Vector3i owner = bv.ischild ? _p + bv.parent : _p;
|
||
return _w.GetTileEntity(owner) is TileEntityComposite c && c.TryGetSelfOrFeature<TEFeatureStorage>(out TEFeatureStorage s) ? s : null;
|
||
}
|
||
|
||
static void Box(World _w, List<string> _p)
|
||
{
|
||
TEFeatureStorage s = StorageAt(_w, P(_p, 0));
|
||
if (s == null)
|
||
{
|
||
Out("necrobox: нет хранилища в " + P(_p, 0));
|
||
return;
|
||
}
|
||
string op = _p.Count > 3 ? _p[3] : "list";
|
||
if (op == "fill")
|
||
{
|
||
// Все пустые ячейки - полной стопкой предмета (ящик «полон» по-честному).
|
||
ItemValue iv = ItemClass.GetItem(_p[4], true);
|
||
for (int i = 0; i < s.ItemGrid.Length; i++)
|
||
{
|
||
if (s.ItemGrid[i] == null || s.ItemGrid[i].IsEmpty())
|
||
{
|
||
s.UpdateSlot(i, new ItemStack(iv.Clone(), iv.ItemClass.Stacknumber.Value));
|
||
}
|
||
}
|
||
s.SetModified();
|
||
}
|
||
else if (op == "clear")
|
||
{
|
||
for (int i = 0; i < s.ItemGrid.Length; i++)
|
||
{
|
||
s.UpdateSlot(i, ItemStack.Empty.Clone());
|
||
}
|
||
s.SetModified();
|
||
}
|
||
else if (op == "add")
|
||
{
|
||
ItemValue iv = ItemClass.GetItem(_p[4], true);
|
||
ItemStack st = new ItemStack(iv, int.Parse(_p[5]));
|
||
CinerariumWork.Place(st, new[] { s });
|
||
s.SetModified();
|
||
if (st.count > 0)
|
||
{
|
||
Out("necrobox: не влезло " + st.count);
|
||
}
|
||
}
|
||
StringBuilder sb = new StringBuilder("necrobox: ").Append(P(_p, 0)).Append(':');
|
||
for (int i = 0; i < s.ItemGrid.Length; i++)
|
||
{
|
||
ItemStack st = s.ItemGrid[i];
|
||
if (st != null && !st.IsEmpty())
|
||
{
|
||
sb.Append(' ').Append(st.itemValue.ItemClass?.GetItemName()).Append('x').Append(st.count);
|
||
}
|
||
}
|
||
Out(sb.ToString());
|
||
}
|
||
|
||
/// <summary>Черепа на пути нити: тройки координат после конца нити, по порядку от урны.</summary>
|
||
static List<Vector3i> Via(List<string> _p, int _i)
|
||
{
|
||
List<Vector3i> l = new List<Vector3i>();
|
||
for (int k = _i; k + 2 < _p.Count; k += 3)
|
||
{
|
||
l.Add(P(_p, k));
|
||
}
|
||
return l;
|
||
}
|
||
|
||
static void Urn(World _w, List<string> _p)
|
||
{
|
||
Vector3i pos = P(_p, 0);
|
||
TEFeatureCinerarium u = CinerariumThreads.UrnAt(_w, pos);
|
||
if (u == null)
|
||
{
|
||
Out("necrourn: нет урны в " + pos);
|
||
return;
|
||
}
|
||
string op = _p.Count > 3 ? _p[3] : "info";
|
||
switch (op)
|
||
{
|
||
case "skull": u.SetSkull(_p[4] == "1"); break;
|
||
case "from": u.AddThreadFrom(P(_p, 4), Via(_p, 7)); break;
|
||
case "to": u.SetThreadTo(P(_p, 4), Via(_p, 7)); break;
|
||
case "out": u.AddThreadOut(P(_p, 4), Via(_p, 7)); break;
|
||
case "clear": u.ClearThreads(); break;
|
||
case "sample":
|
||
u.SetSample(_p.Count > 5 ? new ItemStack(ItemClass.GetItem(_p[4], true), int.Parse(_p[5])) : ItemStack.Empty.Clone());
|
||
break;
|
||
case "run": u.ZoneCommand("zurn_run", GameManager.Instance.World.GetPrimaryPlayer()); break;
|
||
case "stop": u.ZoneCommand("zurn_stop", null); break;
|
||
case "size": u.ZoneSide = int.Parse(_p[4]); u.SetModified(); break;
|
||
case "group":
|
||
u.GroupMask = _p[4] == "нет" || _p[4] == "none" ? 0u : CinerariumGroups.All;
|
||
u.SetModified();
|
||
break;
|
||
}
|
||
string blink = "нет";
|
||
Chunk ch = _w.GetChunkFromWorldPos(pos) as Chunk;
|
||
BlockEntityData be = ch?.GetBlockEntity(pos);
|
||
if (be != null && be.bHasTransform)
|
||
{
|
||
CinerariumBlink cb = be.transform.GetComponent<CinerariumBlink>();
|
||
blink = cb == null ? "нет" : (cb.enabled ? "мигает" : "выкл") + " (" + cb.Renderers.Count + " рендер.)";
|
||
}
|
||
Out("necrourn: " + pos + " " + _w.GetBlock(pos).Block?.GetBlockName() + ", череп " + u.HasSkull + ", застрял " + u.Stuck + ", мигание " + blink +
|
||
", откуда " + u.ThreadFrom.Count + ", куда " + (u.HasThreadTo ? u.ThreadTo.ToString() : "нет") + ", от урны " + u.ThreadOut.Count +
|
||
", зона " + (u.IsBigZone ? u.ZoneSideNow + (u.ZoneRunning ? " идёт" : " ждёт") + (u.ZoneLacking ? " нехватка" : "") + " курсор " + u.ZoneCursor : "-") + ", образец " + (u.Sample == null || u.Sample.IsEmpty() ? "нет" : u.Sample.itemValue.ItemClass?.GetItemName() + "x" + u.Sample.count));
|
||
}
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroLook : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrolook" };
|
||
public override string getDescription() => "NecromancerTome (разработка): повернуть взгляд: yaw [pitch] | at x y z";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrolook", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroAim : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necroaim" };
|
||
public override string getDescription() => "NecromancerTome (разработка): позиция игрока и блок под прицелом";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necroaim", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroPlace : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necroplace" };
|
||
public override string getDescription() => "NecromancerTome (разработка): поставить блок: имя x y z [поворот]";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necroplace", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroHold : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrohold" };
|
||
public override string getDescription() => "NecromancerTome (разработка): предмет в руку: имя [число]";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrohold", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroBox : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrobox" };
|
||
public override string getDescription() => "NecromancerTome (разработка): хранилище: x y z list|clear|add предмет число";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrobox", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroUrn : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrourn" };
|
||
public override string getDescription() => "NecromancerTome (разработка): урна: x y z info|skull|from|to|out|clear|sample|group";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrourn", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroClick : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necroclick" };
|
||
public override string getDescription() => "NecromancerTome (разработка): нож для нитей: 0 - ЛКМ, 1 - ПКМ по блоку под прицелом";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necroclick", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroGod : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrogod" };
|
||
public override string getDescription() => "NecromancerTome (разработка): режим бога и невидимость для ИИ [off]";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrogod", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroDamage : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrodamage" };
|
||
public override string getDescription() => "NecromancerTome (разработка): повредить блок x y z урон";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrodamage", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroDrop : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrodrop" };
|
||
public override string getDescription() => "NecromancerTome (разработка): бросить предмет: имя число x y z";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrodrop", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroBag : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrobag" };
|
||
public override string getDescription() => "NecromancerTome (разработка): мешок с зомби x y z";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrobag", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroCorpse : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrocorpse" };
|
||
public override string getDescription() => "NecromancerTome (разработка): красный труп x y z [класс]";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrocorpse", _params);
|
||
}
|
||
|
||
[Preserve]
|
||
public class ConsoleCmdNecroClear : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necroclear" };
|
||
public override string getDescription() => "NecromancerTome (разработка): убрать растения x0 z0 x1 z1 [y0 y1]";
|
||
public override bool AllowedInMainMenu => false;
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necroclear", _params);
|
||
}
|
||
}
|