231 lines
8.5 KiB
C#
231 lines
8.5 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Xml;
|
||
|
||
namespace NecromancerTome
|
||
{
|
||
/// <summary>
|
||
/// Группы предметов для фильтра урны-логиста (16.10.2026): «пиктограммы, которые по умолчанию выбраны и активны...
|
||
/// изображения предмета, символизирующего группу предметов... Дух-логист будет переносить только те предметы, которые
|
||
/// активированы в его урне. Это же прямой путь к автоматизации сортировки». Деление игры (свойство Group) грубое -
|
||
/// «Ресурсы» смешивают руду, слитки, детали и кур, - поэтому группы свои, а предмет относится к группе по классу, тегам и
|
||
/// имени. Предметы других модов разойдутся по тем же правилам; что не подошло никуда - «Прочее».
|
||
/// Номер группы = номер бита в TEFeatureCinerarium.GroupMask - порядок НЕ менять (сейвы), новые - только в конец.
|
||
/// </summary>
|
||
public static class CinerariumGroups
|
||
{
|
||
public const int Cooked = 0, Canned = 1, Raw = 2, Harvest = 3, Flowers = 4, Seeds = 5, Drinks = 6, Medicine = 7, Ore = 8,
|
||
Ingots = 9, Parts = 10, Materials = 11, Chemicals = 12, Tools = 13, Weapons = 14, Ammo = 15, Armor = 16, Mods = 17,
|
||
Books = 18, Blocks = 19, Necro = 20, Other = 21,
|
||
// 17.10: «Корм для кур вынеси в отдельную группу» (был в «Сыром»).
|
||
ChickenFeed = 22;
|
||
public const int Count = 23;
|
||
public const uint All = (1u << Count) - 1;
|
||
|
||
/// <summary>Значок группы - иконка типичного предмета (ItemIconAtlas).</summary>
|
||
public static readonly string[] Icons =
|
||
{
|
||
"foodMeatStew", "foodCanChili", "foodRawMeat", "foodCropCorn", "plantedChrysanthemum3Harvest", "plantedCorn1",
|
||
"drinkJarBoiledWater", "medicalFirstAidKit", "resourceRockSmall", "resourceForgedSteel", "resourceMechanicalParts",
|
||
"resourceWood", "resourceGunPowder", "meleeToolPickT1IronPickaxe", "gunHandgunT1Pistol", "ammo9mmBulletBall",
|
||
"armorMinerHelmet", "modGunLaserSight", "bookArtOfMiningLuckyStrike", "cobblestoneMaster", "necroSkull", "oldCash",
|
||
"resourceChickenFeed"
|
||
};
|
||
|
||
/// <summary>Ключ названия группы в Localization.csv: necroGroup0..necroGroup22.</summary>
|
||
public static string NameKey(int _g) => "necroGroup" + _g;
|
||
|
||
static readonly HashSet<string> OreNames = new HashSet<string>
|
||
{
|
||
"resourceRockSmall", "resourceRockSmallBundle", "resourceScrapIron", "resourceScrapIronBundle", "resourceScrapLead",
|
||
"resourceLeadBundle", "resourceCoal", "resourceCoalBundle", "resourcePotassiumNitratePowder",
|
||
"resourcePotassiumNitratePowderBundle", "resourceOilShale", "resourceOilShaleBundle", "resourceClayLump",
|
||
"resourceCrushedSand", "resourceCobblestones", "resourceGoldNugget", "resourceSilverNugget", "resourceRawDiamond",
|
||
"resourceSnowBall"
|
||
};
|
||
static readonly HashSet<string> IngotNames = new HashSet<string> { "resourceForgedIron", "resourceForgedSteel" };
|
||
static readonly HashSet<string> ChemNames = new HashSet<string>
|
||
{
|
||
"resourceGunPowder", "resourceGunPowderBundle", "resourceOil", "ammoGasCan", "ammoGasCanBundle", "resourceAcid",
|
||
"resourceGlue", "resourcePaint", "resourceTestosteroneExtract"
|
||
};
|
||
static readonly HashSet<string> MaterialNames = new HashSet<string>
|
||
{
|
||
"resourceWood", "resourceWoodBundle", "resourceCloth", "resourceLeather", "resourceBone", "resourceFeather",
|
||
"resourceYuccaFibers", "resourcePaper", "resourceCement", "resourceConcreteMix", "resourceBeeswax", "resourceCandleStick",
|
||
"resourceAnimalFat"
|
||
};
|
||
/// <summary>Детали, которые теги отнесли бы не туда (гвозди - патроны гвоздомёта).</summary>
|
||
static readonly HashSet<string> PartNames = new HashSet<string> { "resourceNail" };
|
||
static readonly HashSet<string> AmmoParts = new HashSet<string>
|
||
{
|
||
"resourceArrowHeadIron", "resourceArrowHeadSteelAP", "resourceBuckshot", "resourceBulletCasing", "resourceBulletTip",
|
||
"resourceRocketCasing", "resourceRocketTip"
|
||
};
|
||
static readonly HashSet<string> RawNames = new HashSet<string>
|
||
{
|
||
"foodRawMeat", "foodRawMeatBundle", "foodEgg", "foodHoney", "foodRottingFlesh"
|
||
};
|
||
|
||
/// <summary>Предметы и блоки самого мода - по его Config/items.xml и blocks.xml (у многих нет «necro» в имени: книги
|
||
/// призыва, браслет, камни портала, прах зомби, кожа жертвы). Читается один раз.</summary>
|
||
static HashSet<string> _modNames;
|
||
|
||
static HashSet<string> ModNames()
|
||
{
|
||
if (_modNames != null)
|
||
{
|
||
return _modNames;
|
||
}
|
||
_modNames = new HashSet<string>();
|
||
foreach (string f in new[] { "items.xml", "blocks.xml" })
|
||
{
|
||
try
|
||
{
|
||
XmlDocument doc = new XmlDocument();
|
||
doc.Load(Path.Combine(ModEntry.Instance.Path, "Config", f));
|
||
foreach (XmlNode n in doc.SelectNodes("//item[@name] | //block[@name]"))
|
||
{
|
||
_modNames.Add(n.Attributes["name"].Value);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
UnityEngine.Debug.LogWarning("[NecromancerTome] CinerariumGroups: " + f + " мода не прочитан (" + e.Message + ")");
|
||
}
|
||
}
|
||
return _modNames;
|
||
}
|
||
|
||
static readonly Dictionary<int, int> _cache = new Dictionary<int, int>();
|
||
|
||
public static int Of(ItemValue _iv)
|
||
{
|
||
ItemClass ic = _iv?.ItemClass;
|
||
if (ic == null)
|
||
{
|
||
return Other;
|
||
}
|
||
if (!_cache.TryGetValue(ic.Id, out int g))
|
||
{
|
||
g = Classify(ic, _iv);
|
||
_cache[ic.Id] = g;
|
||
}
|
||
return g;
|
||
}
|
||
|
||
static bool Tag(ItemClass _ic, string _t)
|
||
{
|
||
return _ic.ItemTags.Test_AnySet(FastTags<TagGroup.Global>.Parse(_t));
|
||
}
|
||
|
||
static int Classify(ItemClass _ic, ItemValue _iv)
|
||
{
|
||
string n = _ic.GetItemName() ?? "";
|
||
// 23.10: жестяные банки - предметы мода, но по смыслу это стеклянные банки игры (кипятить воду) - к ним, не в «Некромантию».
|
||
if (n.StartsWith("tinCan"))
|
||
{
|
||
return Drinks;
|
||
}
|
||
if (n.IndexOf("necro", StringComparison.OrdinalIgnoreCase) >= 0 || ModNames().Contains(n))
|
||
{
|
||
return Necro;
|
||
}
|
||
if (n == "resourceChickenFeed")
|
||
{
|
||
return ChickenFeed;
|
||
}
|
||
if (_ic is ItemClassModifier)
|
||
{
|
||
return Mods;
|
||
}
|
||
if (_ic.IsBlock())
|
||
{
|
||
return new ItemValue(_ic.Id).ToBlockValue().Block is BlockPlantGrowing ? Seeds : Blocks;
|
||
}
|
||
if (_ic is ItemClassArmor || n.StartsWith("armor") || n.StartsWith("clothing"))
|
||
{
|
||
return Armor;
|
||
}
|
||
if (n.StartsWith("book") || n.Contains("Schematic") || n.Contains("Magazine") || Tag(_ic, "books"))
|
||
{
|
||
return Books;
|
||
}
|
||
if (OreNames.Contains(n))
|
||
{
|
||
return Ore;
|
||
}
|
||
if (IngotNames.Contains(n) || n.StartsWith("unit_"))
|
||
{
|
||
return Ingots;
|
||
}
|
||
if (ChemNames.Contains(n))
|
||
{
|
||
return Chemicals;
|
||
}
|
||
if (PartNames.Contains(n))
|
||
{
|
||
return Parts;
|
||
}
|
||
if (MaterialNames.Contains(n))
|
||
{
|
||
return Materials;
|
||
}
|
||
if (AmmoParts.Contains(n) || n.StartsWith("ammo") || n.StartsWith("thrown") || Tag(_ic, "ammo"))
|
||
{
|
||
return Ammo;
|
||
}
|
||
if (n.EndsWith("Parts") || n == "partsMaster" || n.StartsWith("vehicle") && !n.EndsWith("Placeable"))
|
||
{
|
||
return Parts;
|
||
}
|
||
if (n.StartsWith("meleeTool"))
|
||
{
|
||
return Tools; // раньше оружия: у факела тег weapon
|
||
}
|
||
if (n.StartsWith("gun") || n.StartsWith("meleeWpn") || Tag(_ic, "weapon"))
|
||
{
|
||
return Weapons;
|
||
}
|
||
if (n.StartsWith("meleeTool") || n.StartsWith("tool") || n.StartsWith("bucket") || Tag(_ic, "tool"))
|
||
{
|
||
return Tools;
|
||
}
|
||
if (n.StartsWith("foodCan"))
|
||
{
|
||
return Canned;
|
||
}
|
||
if (n.StartsWith("foodCrop"))
|
||
{
|
||
return Harvest;
|
||
}
|
||
if (n.StartsWith("resourceCrop"))
|
||
{
|
||
return Flowers;
|
||
}
|
||
if (RawNames.Contains(n) || n.StartsWith("foodRaw"))
|
||
{
|
||
return Raw;
|
||
}
|
||
if (n.StartsWith("drink") || n.StartsWith("tinCan"))
|
||
{
|
||
return Drinks;
|
||
}
|
||
if (n.StartsWith("medical") || n.StartsWith("drug") || Tag(_ic, "medical"))
|
||
{
|
||
return Medicine;
|
||
}
|
||
if (n.StartsWith("food") || Tag(_ic, "food"))
|
||
{
|
||
return Cooked;
|
||
}
|
||
if (n.StartsWith("resource") || n == "carBattery" || n == "smallEngine" || n == "solarCell")
|
||
{
|
||
return Parts;
|
||
}
|
||
return Other;
|
||
}
|
||
}
|
||
}
|