- Блоки логиста на модели кадила: по центру на подставке (necroCinerariumLogist) и новый вид у стены на кронштейне (necroCinerariumLogistWall/+Skull); выбор вида - R с урной в руке. - Дух логиста втрое меньше, в покое сидит в кадиле, на перевозку вылетает через окно крышки (у стены - не в стену) и возвращается тем же окном. - Застрял (ящик «куда» полон) - урна мигает (CinerariumBlink) вместо почерневшего духа; прежняя зелёная подмена свечения старой модели убрана. - Команды разработки без мыши: necrospawn, necroexit [quit], necrolook, necroaim, necroplace, necrohold, necrobox, necrourn, necroclick. Проверено в игре (test8): перевозка обоими видами, вылет духа, вид у стены от стены. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
153 lines
5.6 KiB
C#
153 lines
5.6 KiB
C#
using System.Collections.Generic;
|
||
using System.IO;
|
||
using UnityEngine;
|
||
using UnityEngine.Scripting;
|
||
|
||
namespace NecromancerTome
|
||
{
|
||
/// <summary>
|
||
/// Почтовый ящик консоли - только для разработки (03.10: ассистент подбирает позу рук сам, без
|
||
/// клавиатуры). Работает, лишь если есть папка %APPDATA%\7DaysToDie\NecroMailbox - у игроков её
|
||
/// нет. Раз в полсекунды: команды из cmd.txt (по строке) выполняются в консоли игры, как набранные
|
||
/// вручную, файл удаляется, ответ - в лог строками «[NecromancerTome] mailbox:».
|
||
/// </summary>
|
||
public static class NecroMailbox
|
||
{
|
||
public static string Dir => Path.Combine(GameIO.GetUserGameDataDir(), "NecroMailbox");
|
||
static string CmdFile => Path.Combine(Dir, "cmd.txt");
|
||
static float _next;
|
||
|
||
public static void Init()
|
||
{
|
||
ModEvents.UnityUpdate.RegisterHandler(OnUnityUpdate);
|
||
}
|
||
|
||
static void OnUnityUpdate(ref ModEvents.SUnityUpdateData _data)
|
||
{
|
||
if (Time.unscaledTime < _next)
|
||
{
|
||
return;
|
||
}
|
||
_next = Time.unscaledTime + 0.5f;
|
||
if (!File.Exists(CmdFile) || SdtdConsole.Instance == null)
|
||
{
|
||
return;
|
||
}
|
||
string[] lines;
|
||
try
|
||
{
|
||
lines = File.ReadAllLines(CmdFile);
|
||
File.Delete(CmdFile);
|
||
}
|
||
catch (IOException)
|
||
{
|
||
return; // файл ещё пишется - в следующий раз
|
||
}
|
||
foreach (string raw in lines)
|
||
{
|
||
string line = raw.Trim();
|
||
if (line.Length == 0)
|
||
{
|
||
continue;
|
||
}
|
||
Debug.Log("[NecromancerTome] mailbox: > " + line);
|
||
try
|
||
{
|
||
List<string> res = SdtdConsole.Instance.ExecuteSync(line, null);
|
||
if (res != null)
|
||
{
|
||
foreach (string r in res)
|
||
{
|
||
Debug.Log("[NecromancerTome] mailbox: " + r);
|
||
}
|
||
}
|
||
}
|
||
catch (System.Exception ex)
|
||
{
|
||
Debug.LogWarning("[NecromancerTome] mailbox: ошибка - " + ex);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>necroshot [имя] - снимок экрана игры в %APPDATA%\7DaysToDie\NecroMailbox\shots\имя.png
|
||
/// (как F9, только в известное место). Файл появляется в конце кадра.</summary>
|
||
[Preserve]
|
||
public class ConsoleCmdNecroShot : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necroshot" };
|
||
public override string getDescription() => "NecromancerTome: снимок экрана в NecroMailbox/shots/<имя>.png";
|
||
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo)
|
||
{
|
||
string dir = Path.Combine(NecroMailbox.Dir, "shots");
|
||
Directory.CreateDirectory(dir);
|
||
string name = _params.Count > 0 ? _params[0] : System.DateTime.Now.ToString("HHmmss");
|
||
string path = Path.Combine(dir, name + ".png");
|
||
ScreenCapture.CaptureScreenshot(path);
|
||
SdtdConsole.Instance.Output("снимок: " + path);
|
||
}
|
||
}
|
||
|
||
/// <summary>necrospawn - нажать «Появиться» в окне появления (18.10: ассистент сам запускает игру с сейвом
|
||
/// -LoadSaveGame=true и входит в мир без мыши). То же, что кнопка: XUiC_SpawnSelectionWindow.SpawnButtonPressed.</summary>
|
||
[Preserve]
|
||
public class ConsoleCmdNecroSpawn : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necrospawn" };
|
||
public override string getDescription() => "NecromancerTome: нажать «Появиться» (разработка, почтовый ящик)";
|
||
public override bool AllowedInMainMenu => false;
|
||
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo)
|
||
{
|
||
foreach (LocalPlayerUI ui in LocalPlayerUI.PlayerUIs)
|
||
{
|
||
XUiC_SpawnSelectionWindow w = ui?.xui?.GetWindowByType<XUiC_SpawnSelectionWindow>();
|
||
if (w != null && w.IsOpen)
|
||
{
|
||
w.SpawnButtonPressed(SpawnMethod.Invalid);
|
||
SdtdConsole.Instance.Output("necrospawn: нажато «Появиться»");
|
||
return;
|
||
}
|
||
}
|
||
SdtdConsole.Instance.Output("necrospawn: окно появления не открыто");
|
||
}
|
||
}
|
||
|
||
/// <summary>necroexit [quit] - выйти из мира с сохранением, как «Выход» в меню паузы (GameManager.Disconnect); с quit -
|
||
/// затем закрыть игру. Нужно перед сборкой бандлов и заменой DLL (игра держит файлы).</summary>
|
||
[Preserve]
|
||
public class ConsoleCmdNecroExit : ConsoleCmdAbstract
|
||
{
|
||
public override string[] getCommands() => new[] { "necroexit" };
|
||
public override string getDescription() => "NecromancerTome: выйти из мира с сохранением [quit - и закрыть игру] (разработка)";
|
||
public override bool AllowedInMainMenu => true;
|
||
|
||
public override void Execute(List<string> _params, CommandSenderInfo _senderInfo)
|
||
{
|
||
bool quit = _params.Count > 0 && _params[0] == "quit";
|
||
SdtdConsole.Instance.Output("necroexit: выход" + (quit ? " и закрытие игры" : " в меню"));
|
||
ThreadManager.StartCoroutine(ExitCo(quit));
|
||
}
|
||
|
||
static System.Collections.IEnumerator ExitCo(bool _quit)
|
||
{
|
||
if (GameManager.Instance.World != null)
|
||
{
|
||
GameManager.Instance.Disconnect();
|
||
while (GameManager.Instance.World != null)
|
||
{
|
||
yield return null;
|
||
}
|
||
Debug.Log("[NecromancerTome] necroexit: мир сохранён и закрыт");
|
||
}
|
||
if (_quit)
|
||
{
|
||
yield return new WaitForSecondsRealtime(2f);
|
||
Debug.Log("[NecromancerTome] necroexit: закрываю игру");
|
||
Application.Quit();
|
||
}
|
||
}
|
||
}
|
||
}
|