using System.Collections.Generic; using System.Globalization; using System.Text; using UnityEngine; using UnityEngine.Scripting; namespace NecromancerTome { /// /// Команды разработки для проверок без мыши (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 предмет [число] - положить в текущую ячейку пояса и взять в руку /// necroslot [N] - какая ячейка пояса в руке и что в ячейках; N - взять в руку ячейку N (23.10: проверка Archer's Eye без мыши) /// necrofire press|release - ЛКМ предметом в руке: нажать / отпустить (лук: натянуть / выстрелить; 23.10, ошибка в Hit от стрелы) /// 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 - отпущенная ЛКМ/ПКМ ножом для нитей по блоку под прицелом /// 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 _p, int _i) => new Vector3i(int.Parse(_p[_i]), int.Parse(_p[_i + 1]), int.Parse(_p[_i + 2])); /// Общий вход всех команд: игрок есть - выполнить, ошибка - строкой в ответ. public static void Run(string _cmd, List _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 "necrofire": { bool rel = _params.Count > 0 && _params[0] == "release"; pl.inventory.Execute(0, rel, pl.playerInput); Out("necrofire: " + (rel ? "отпущено" : "нажато") + ", в руке " + pl.inventory.holdingItem?.Name + ", заряжено " + pl.inventory.holdingItemItemValue.Meta); break; } case "necroslot": { if (_params.Count > 0) { pl.inventory.SetHoldingItemIdx(int.Parse(_params[0])); } string belt = ""; for (int i = 0; i < pl.inventory.SlotCount; i++) { ItemStack st = pl.inventory.GetItem(i); belt += " " + i + ":" + (st == null || st.IsEmpty() ? "-" : st.itemValue.ItemClass.GetItemName()); } Out("necroslot: в руке " + pl.inventory.holdingItemIdx + ";" + belt); 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 "necrostation": { // necrostation x y z - станция текстом: огонь, топливо, вход, очередь, выход (проверка урны рабочего) TileEntityWorkstation ws = CinerariumThreads.StationAt(w, P(_params, 0)); if (ws == null) { Out("necrostation: нет станции"); break; } string Stacks(ItemStack[] _a) { StringBuilder s = new StringBuilder(); if (_a != null) { foreach (ItemStack st in _a) { if (st != null && !st.IsEmpty()) { s.Append(' ').Append(st.itemValue.ItemClass?.GetItemName()).Append('x').Append(st.count); } } } return s.Length > 0 ? s.ToString() : " -"; } int q = 0; if (ws.Queue != null) { foreach (RecipeQueueItem r in ws.Queue) { if (r != null && r.Recipe != null && r.Multiplier > 0) { q += r.Multiplier; } } } Out("necrostation: огонь " + (ws.IsBurning ? "горит" : "погашен") + ", топливо" + Stacks(ws.Fuel) + ", вход" + Stacks(ws.Input) + ", очередь " + q + ", выход" + Stacks(ws.Output)); break; } case "necrofill": { // necrofill x0 z0 x1 z1 y [блок] [соседей] - засыпать ямы рельефа на уровне y: пустую клетку, у которой рядом по // уровню не меньше двух клеток земли, - землёй с полной плотностью; повторять, пока засыпается. // Ровную землю рядом не поднимает (у неё на этом уровне соседи - воздух). 18.10: ямы в test8. int x0 = int.Parse(_params[0]), z0 = int.Parse(_params[1]), x1 = int.Parse(_params[2]), z1 = int.Parse(_params[3]); int fy = int.Parse(_params[4]); Block fb = Block.GetBlockByName(_params.Count > 5 ? _params[5] : "terrForestGround", true); int total = 0; for (int pass = 0; pass < 20; pass++) { List fill = new List(); 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++) { Vector3i c = new Vector3i(x, fy, z); if (!w.GetBlock(c).isair || w.GetBlock(c - Vector3i.up).isair) { continue; } int n = 0; foreach (Vector3i d in new[] { Vector3i.forward, Vector3i.back, Vector3i.left, Vector3i.right }) { BlockValue nb = w.GetBlock(c + d); if (!nb.isair && nb.Block != null && nb.Block.shape.IsTerrain()) { n++; } } if (n >= (_params.Count > 6 ? int.Parse(_params[6]) : 2)) // седьмой параметр - сколько соседей-земли нужно (широкие ямы - 1) { fill.Add(c); } } } if (fill.Count == 0) { break; } foreach (Vector3i c in fill) { w.SetBlockRPC(c, fb.ToBlockValue(), MarchingCubes.DensityTerrain); } total += fill.Count; } Out("necrofill: засыпано клеток " + total); break; } case "necrosmooth": { // necrosmooth x0 z0 x1 z1 y [плотность] - край насыпи скатом: клеткам земли на уровне y, у которых сбоку воздух, // - неполная плотность (по умолчанию -30; полная земля -128), игра рисует их наклоном. int x0 = int.Parse(_params[0]), z0 = int.Parse(_params[1]), x1 = int.Parse(_params[2]), z1 = int.Parse(_params[3]); int sy = int.Parse(_params[4]); sbyte dens = (sbyte)(_params.Count > 5 ? int.Parse(_params[5]) : -30); List<(Vector3i, BlockValue)> edge = new List<(Vector3i, BlockValue)>(); 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++) { Vector3i c = new Vector3i(x, sy, z); BlockValue bv = w.GetBlock(c); if (bv.isair || bv.Block == null || !bv.Block.shape.IsTerrain() || !w.GetBlock(c + Vector3i.up).isair) { continue; } foreach (Vector3i d in new[] { Vector3i.forward, Vector3i.back, Vector3i.left, Vector3i.right }) { if (w.GetBlock(c + d).isair) { edge.Add((c, bv)); break; } } } } foreach ((Vector3i c, BlockValue bv) in edge) { w.SetBlockRPC(c, bv, dens); } Out("necrosmooth: краевых клеток " + edge.Count); break; } case "necrocanplace": // necrocanplace блок x y z - подсказка, почему урну сюда нельзя (или «можно») Out("necrocanplace: " + (TEFeatureCinerarium.PlacementRefusal(P(_params, 1), Block.GetBlockByName(_params[0], true)) ?? "можно")); 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 _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")); } /// Режим бога и невидимость для ИИ: пока ассистент проверяет, персонаж стоит - зомби тестового мира его не трогают /// (18.10: «пока персонаж просто стоит, его скушают»; «Я обычно ставлю режим Бога»). 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 _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 _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(out TEFeatureStorage s) ? s : null; } static void Box(World _w, List _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()); } /// Черепа на пути нити: тройки координат после конца нити, по порядку от урны. static List Via(List _p, int _i) { List l = new List(); for (int k = _i; k + 2 < _p.Count; k += 3) { l.Add(P(_p, k)); } return l; } static void Urn(World _w, List _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 "contents": CinerariumContents.Open(GameManager.Instance.World.GetPrimaryPlayer(), u); break; case "probe": Out("necrourn: " + pos + " " + CinerariumWork.Probe(GameManager.Instance.World, u)); return; 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(); 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 _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 _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 _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 _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrohold", _params); } [Preserve] public class ConsoleCmdNecroFire : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necrofire" }; public override string getDescription() => "NecromancerTome (разработка): ЛКМ предметом в руке: press|release"; public override bool AllowedInMainMenu => false; public override void Execute(List _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrofire", _params); } [Preserve] public class ConsoleCmdNecroSlot : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necroslot" }; public override string getDescription() => "NecromancerTome (разработка): ячейка пояса в руке: [N]"; public override bool AllowedInMainMenu => false; public override void Execute(List _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necroslot", _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 _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 _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 _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 _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 _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 _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 _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 _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 _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necroclear", _params); } [Preserve] public class ConsoleCmdNecroStation : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necrostation" }; public override string getDescription() => "NecromancerTome (разработка): станция текстом x y z"; public override bool AllowedInMainMenu => false; public override void Execute(List _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrostation", _params); } [Preserve] public class ConsoleCmdNecroFill : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necrofill" }; public override string getDescription() => "NecromancerTome (разработка): засыпать ямы x0 z0 x1 z1 y [блок]"; public override bool AllowedInMainMenu => false; public override void Execute(List _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrofill", _params); } [Preserve] public class ConsoleCmdNecroSmooth : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necrosmooth" }; public override string getDescription() => "NecromancerTome (разработка): край насыпи скатом x0 z0 x1 z1 y [плотность]"; public override bool AllowedInMainMenu => false; public override void Execute(List _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrosmooth", _params); } [Preserve] public class ConsoleCmdNecroCanPlace : ConsoleCmdAbstract { public override string[] getCommands() => new[] { "necrocanplace" }; public override string getDescription() => "NecromancerTome (разработка): почему урну нельзя поставить: блок x y z"; public override bool AllowedInMainMenu => false; public override void Execute(List _params, CommandSenderInfo _senderInfo) => NecroDev.Run("necrocanplace", _params); } }