Урна рабочего: партия до стака, одна ячейка очереди на предмет, сланец не плавить (#19)
- Рецепт ставится в очередь сразу на столько, на сколько хватает всех ингредиентов, не больше стака любого ингредиента и стака готового (было по одной штуке за шаг - «очень медленно»). - Пока партия предмета в очереди станции, второй такой не ставится - прочие ячейки остаются другим урнам на той же станции. - Горючее сырьё (нефтяной сланец) в кузню не кладётся. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3938f1786a
commit
fb9c50cdf9
@@ -133,13 +133,17 @@ namespace NecromancerTome
|
||||
{
|
||||
continue; // выход полон и ящики «куда» полны (или их нет) - ниже станция погаснет
|
||||
}
|
||||
if (InQueue(st.Te, sample.itemValue.type))
|
||||
{
|
||||
continue; // партия этого предмета уже в очереди - следующая, когда она кончится
|
||||
}
|
||||
foreach (Recipe r in CraftingManager.GetRecipes(name))
|
||||
{
|
||||
if (r.IsScrap || !AreaFits(r, st.Areas) || !ToolFits(r, st.Te) || owner != null && !r.IsUnlocked(owner))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!Ingredients(r, st.Te, src, out Vector3i? srcAt, out string shortUnit))
|
||||
if (!Ingredients(r, st.Te, src, out Vector3i? srcAt, out string shortUnit, out int batches))
|
||||
{
|
||||
// Кузня: не хватает переплавленного материала - положить сырьё во вход (плавит сама, с огнём).
|
||||
if (shortUnit != null && FeedMaterial(st, shortUnit, src, _dry, out Vector3i? rawAt))
|
||||
@@ -158,10 +162,10 @@ namespace NecromancerTome
|
||||
{
|
||||
return st.Pos;
|
||||
}
|
||||
TakeIngredients(r, st.Te, src);
|
||||
Enqueue(st.Te, slot, r);
|
||||
TakeIngredients(r, st.Te, src, batches);
|
||||
Enqueue(st.Te, slot, r, batches);
|
||||
Ignite(st.Te, src, false);
|
||||
Debug.Log("[NecromancerTome] Cinerarium: рабочий поставил " + name + " на станцию " + st.Pos);
|
||||
Debug.Log("[NecromancerTome] Cinerarium: рабочий поставил " + name + " x" + batches + " на станцию " + st.Pos);
|
||||
return st.Pos;
|
||||
}
|
||||
}
|
||||
@@ -289,6 +293,21 @@ namespace NecromancerTome
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>Есть ли в очереди станции рецепт этого предмета. 24.10, пользователь: партия - до стака, и «если бы их было
|
||||
/// двое, то тут нужно занимать очередь на ячейку»: один предмет держит в очереди одну ячейку, прочие - другим урнам на
|
||||
/// той же станции (иначе одна урна забила бы очередь стаками на часы вперёд).</summary>
|
||||
static bool InQueue(TileEntityWorkstation _te, int _itemType)
|
||||
{
|
||||
foreach (RecipeQueueItem q in _te.Queue)
|
||||
{
|
||||
if (q != null && q.Recipe != null && q.Multiplier > 0 && q.Recipe.itemValueType == _itemType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool OutputHasRoom(TileEntityWorkstation _te, ItemStack _sample)
|
||||
{
|
||||
foreach (ItemStack s in _te.Output)
|
||||
@@ -325,11 +344,17 @@ namespace NecromancerTome
|
||||
}
|
||||
|
||||
/// <summary>Хватает ли всего: переплавленное - в кузне, прочее - в ящиках «откуда». _srcAt - ящик, откуда первое;
|
||||
/// _shortUnit - какого переплавленного не хватило (кузне можно подложить сырья).</summary>
|
||||
static bool Ingredients(Recipe _r, TileEntityWorkstation _te, List<(Vector3i p, TEFeatureStorage box)> _src, out Vector3i? _srcAt, out string _shortUnit)
|
||||
/// _shortUnit - какого переплавленного не хватило (кузне можно подложить сырья). _batches - сколько раз рецепт ставится
|
||||
/// в очередь за одно дело (24.10, пользователь: «в бетономешалку кладётся по одному камушку... ожидается, что он будет
|
||||
/// класть хотя бы по целому стаку, а если на стак не хватает, то сколько найдёт»): на сколько хватает каждого
|
||||
/// ингредиента, но не больше стака ни одного ингредиента и не больше стака готового.</summary>
|
||||
static bool Ingredients(Recipe _r, TileEntityWorkstation _te, List<(Vector3i p, TEFeatureStorage box)> _src, out Vector3i? _srcAt, out string _shortUnit, out int _batches)
|
||||
{
|
||||
_srcAt = null;
|
||||
_shortUnit = null;
|
||||
ItemClass outClass = ItemClass.GetForId(_r.itemValueType);
|
||||
_batches = outClass != null && _r.count > 0 ? Mathf.Max(1, outClass.MaxCount / _r.count) : 1;
|
||||
_batches = Mathf.Min(_batches, short.MaxValue);
|
||||
foreach (ItemStack ing in _r.ingredients)
|
||||
{
|
||||
if (ing == null || ing.IsEmpty() || ing.count <= 0)
|
||||
@@ -345,6 +370,7 @@ namespace NecromancerTome
|
||||
_shortUnit = iname;
|
||||
return false;
|
||||
}
|
||||
_batches = Mathf.Min(_batches, _te.Input[us].count / ing.count);
|
||||
continue;
|
||||
}
|
||||
int have = 0;
|
||||
@@ -367,11 +393,14 @@ namespace NecromancerTome
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int stack = ing.itemValue.ItemClass != null ? ing.itemValue.ItemClass.MaxCount : ing.count;
|
||||
_batches = Mathf.Min(_batches, Mathf.Max(1, stack / ing.count), have / ing.count);
|
||||
}
|
||||
_batches = Mathf.Max(1, _batches);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void TakeIngredients(Recipe _r, TileEntityWorkstation _te, List<(Vector3i p, TEFeatureStorage box)> _src)
|
||||
static void TakeIngredients(Recipe _r, TileEntityWorkstation _te, List<(Vector3i p, TEFeatureStorage box)> _src, int _batches)
|
||||
{
|
||||
ItemStack[] input = _te.Input;
|
||||
bool inputChanged = false;
|
||||
@@ -384,11 +413,11 @@ namespace NecromancerTome
|
||||
int us = UnitSlot(_te, ing.itemValue.ItemClass?.GetItemName() ?? "");
|
||||
if (us >= 0)
|
||||
{
|
||||
input[us].count -= ing.count;
|
||||
input[us].count -= ing.count * _batches;
|
||||
inputChanged = true;
|
||||
continue;
|
||||
}
|
||||
int need = ing.count;
|
||||
int need = ing.count * _batches;
|
||||
foreach ((Vector3i p, TEFeatureStorage box) s in _src)
|
||||
{
|
||||
ItemStack[] grid = s.box.ItemGrid.items;
|
||||
@@ -413,7 +442,7 @@ namespace NecromancerTome
|
||||
}
|
||||
}
|
||||
|
||||
static void Enqueue(TileEntityWorkstation _te, int _slot, Recipe _r)
|
||||
static void Enqueue(TileEntityWorkstation _te, int _slot, Recipe _r, int _batches)
|
||||
{
|
||||
RecipeQueueItem[] q = _te.Queue;
|
||||
float t = _r.craftingTime > 0f ? _r.craftingTime : 1f;
|
||||
@@ -421,7 +450,7 @@ namespace NecromancerTome
|
||||
q[_slot] = new RecipeQueueItem
|
||||
{
|
||||
Recipe = _r,
|
||||
Multiplier = 1,
|
||||
Multiplier = (short)_batches,
|
||||
CraftingTimeLeft = t,
|
||||
OneItemCraftTime = t,
|
||||
IsCrafting = _slot == q.Length - 1,
|
||||
@@ -455,11 +484,13 @@ namespace NecromancerTome
|
||||
ItemStack[] input = _st.Te.Input;
|
||||
// 23.10 («вместо камней вплавляет булыжник»): сначала сырьё, у которого нет рецепта (камни, лом), сделанное руками
|
||||
// (булыжник) - только если сырья нет. Раньше - первое подходящее по порядку ячеек.
|
||||
// 24.10 («работник положил сланец в переплавку в печку»): горючее (нефтяной сланец - сырьё для бензина) не плавится
|
||||
// вовсе - рецепта у него нет, и раньше оно шло наравне с камнями.
|
||||
foreach ((Vector3i p, TEFeatureStorage box, int k) s in Ordered(_src, g =>
|
||||
{
|
||||
ItemClass c = g.itemValue.ItemClass;
|
||||
if (c?.MadeOfMaterial?.ForgeCategory == null || !c.MadeOfMaterial.ForgeCategory.EqualsCaseInsensitive(mat) ||
|
||||
c.GetItemName().StartsWith("unit_"))
|
||||
c.GetItemName().StartsWith("unit_") || ItemClass.GetFuelValue(g.itemValue) > 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user