using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace NecromancerTome
{
///
/// Сумка одержимого зомби (указание 13.10: «всем одержимым зомби с видом от первого лица сумку и возможность вызывать
/// её по Tab»). Решения пользователя 13.10:
/// - своя, одна на всех зомби, число ячеек - по виду зомби (SlotsFor), пока у всех 2;
/// - при выходе из одержимости зомби сбрасывает рюкзаком всё, что было в сумке (и на поясе - когда в поясе
/// появятся предметы);
/// - гибель одержимого - мешок на месте и метка на карте, как у сумки волка.
/// Лут (указание 13.10: «раз у них E свободно, подключай лутание») - как у волка: E на ящик или мешок - обыск с
/// переносом в сумку, E на предмет на земле - подобрать (WolfBag.Target - сумка зомби, пока она есть).
/// Только зомби из списка вида от первого лица (FpArms.Allows), не питомцы. Окно - то же, что у сумки волка
/// (XUiC_BagStorageWindowGroup, без рюкзака персонажа), Tab в зомби открывает его вместо рюкзака.
///
/// ХРАНЕНИЕ. Сумка живёт одно вселение, но пишется в отдельный файл сейва при каждом изменении (как сумка волка,
/// сейв игрока не трогается): вылет посреди вселения вещи не теряет - при следующем вселении то, что осталось в
/// файле, выпадает мешком у тела.
///
public static class ZombieBag
{
const string FileName = "NecromancerTome_zombiebag.bin";
public const int DefaultSlots = 2;
/// Метка выпавшей сумки - ключ локализации (снимается вместе с меткой сумки волка, когда мешок исчез).
public const string WaypointName = "necroZombieBagWaypoint";
public static bool WindowOpen;
static Bag _bag;
static string FilePath => Path.Combine(GameIO.GetSaveGameDir(), FileName);
public static bool Active => _bag != null;
public static Bag Current => _bag;
/// Записать после лута (WolfBag.SaveTarget).
public static void SaveNow() => Save();
/// У кого сумка: зомби с видом от первого лица, не питомцы.
public static bool Has(EntityAlive _z, bool _pet) => !_pet && FpArms.Allows(_z);
/// Ячеек у этого вида зомби (указание: «каким-то добавим, каким-то наоборот») - пока у всех DefaultSlots.
public static int SlotsFor(EntityAlive _z) => DefaultSlots;
/// Вселение началось: то, что осталось в файле после вылета, - мешком у тела; новая пустая сумка.
public static void Begin(EntityPlayerLocal _body, EntityAlive _z)
{
try
{
if (File.Exists(FilePath))
{
Bag old = SpatialVaultPersistence.ParsePayload(File.ReadAllBytes(FilePath));
List left = Items(old);
if (left.Count > 0 && _body != null)
{
WolfBag.DropSack(_body.position + _body.GetForwardVector() * 0.8f, left);
Debug.Log("[NecromancerTome] ZombieBag: в файле осталась сумка прошлого вселения - мешком у тела (" + left.Count + ")");
}
File.Delete(FilePath);
}
}
catch (System.Exception e)
{
Debug.LogWarning("[NecromancerTome] ZombieBag: файл сумки не прочитан (" + e.Message + ") - оставлен как есть");
}
_bag = new Bag(new Vector2i(SlotsFor(_z), 1), XUiC_ItemStack.StackLocationTypes.LootContainer, null);
Debug.Log("[NecromancerTome] ZombieBag: сумка " + _z.EntityName + " - ячеек " + _bag.SlotCount);
}
/// Вселение кончилось: всё из сумки - мешком на месте зомби; погиб - ещё и метка на карте.
public static void End(EntityAlive _z)
{
if (_bag == null)
{
return;
}
CloseWindow();
List items = Items(_bag);
_bag = null;
Save();
if (items.Count == 0 || _z == null)
{
return;
}
bool died = _z.IsDead();
WolfBag.DropSack(_z.position, items);
if (died)
{
WolfBag.AddWaypoint(_z.position, WaypointName);
}
Debug.Log("[NecromancerTome] ZombieBag: " + (died ? "одержимый погиб" : "выход из одержимости") + " - сумка мешком (" + items.Count + ")");
}
static List Items(Bag _b)
{
List items = new List();
if (_b?.ItemGrid?.items == null)
{
return items;
}
foreach (ItemStack s in _b.ItemGrid.items)
{
if (s != null && !s.IsEmpty())
{
items.Add(s.Clone());
}
}
return items;
}
static void Save()
{
try
{
if (_bag == null || _bag.IsEmpty())
{
if (File.Exists(FilePath))
{
File.Delete(FilePath);
}
return;
}
File.WriteAllBytes(FilePath, SpatialVaultPersistence.BuildPayload(_bag));
}
catch (System.Exception e)
{
Debug.LogWarning("[NecromancerTome] ZombieBag: сумка не записана - " + e.Message);
}
}
/// Tab в зомби - окно сумки, как «багажник» волка (WolfBag.OpenWindow).
public static void OpenWindow(EntityPlayerLocal _player, EntityAlive _z)
{
LocalPlayerUI ui = LocalPlayerUI.GetUIForPlayer(_player);
if (ui == null || _bag == null)
{
return;
}
WindowOpen = true;
XUiC_BagStorageWindowGroup.Open(ui.xui, _z, _bag, LootContainer.GetLootContainer("roboticDrone"),
Localization.Get("necroZombieBagWindowTitle"), Save, () =>
{
WindowOpen = false;
Save();
});
Debug.Log("[NecromancerTome] ZombieBag: окно сумки");
}
public static void CloseWindow()
{
if (WindowOpen)
{
LocalPlayerUI.GetUIForPrimaryPlayer()?.windowManager.CloseAllOpenModalWindows();
WindowOpen = false;
}
}
/// Выход из мира - забыть (файл остаётся: при следующем вселении выпадет мешком у тела).
public static void Forget()
{
_bag = null;
WindowOpen = false;
}
}
}