Overhaul fabricators and deconstructors to have minCondition, maxCondition (deconstructor) and outCondition

Implement several suggestions listed in https://github.com/Regalis11/Barotrauma/issues/196
Add more fabricatables and deconstructables
This commit is contained in:
Alex Noir
2017-12-22 21:33:14 +03:00
parent 9610444e67
commit 6d30557860
13 changed files with 172 additions and 64 deletions
@@ -57,7 +57,8 @@ namespace Barotrauma.Items.Components
foreach (DeconstructItem deconstructProduct in targetItem.Prefab.DeconstructItems)
{
if (deconstructProduct.RequireFullCondition && targetItem.Condition < targetItem.Prefab.Health) continue;
float percentageHealth = targetItem.Condition / targetItem.Prefab.Health;
if (percentageHealth <= deconstructProduct.MinCondition || percentageHealth > deconstructProduct.MaxCondition) continue;
var itemPrefab = MapEntityPrefab.Find(deconstructProduct.ItemPrefabName) as ItemPrefab;
if (itemPrefab == null)
@@ -69,11 +70,11 @@ namespace Barotrauma.Items.Components
//container full, drop the items outside the deconstructor
if (containers[1].Inventory.Items.All(i => i != null))
{
Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine);
Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine, itemPrefab.Health * deconstructProduct.OutCondition);
}
else
{
Entity.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory);
Entity.Spawner.AddToSpawnQueue(itemPrefab, containers[1].Inventory, itemPrefab.Health * deconstructProduct.OutCondition);
}
}
@@ -12,10 +12,12 @@ namespace Barotrauma.Items.Components
{
public readonly ItemPrefab TargetItem;
public readonly List<Tuple<ItemPrefab, int>> RequiredItems;
public readonly List<Tuple<ItemPrefab, int, float, bool>> RequiredItems;
public readonly float RequiredTime;
public readonly float OutCondition; //Percentage-based from 0 to 1
public readonly List<Skill> RequiredSkills;
public FabricableItem(XElement element)
@@ -31,8 +33,9 @@ namespace Barotrauma.Items.Components
RequiredSkills = new List<Skill>();
RequiredTime = element.GetAttributeFloat("requiredtime", 1.0f);
RequiredItems = new List<Tuple<ItemPrefab, int>>();
OutCondition = element.GetAttributeFloat("outcondition", 1.0f);
RequiredItems = new List<Tuple<ItemPrefab, int, float, bool>>();
//Backwards compatibility for string lists
string[] requiredItemNames = element.GetAttributeString("requireditems", "").Split(',');
foreach (string requiredItemName in requiredItemNames)
{
@@ -48,12 +51,12 @@ namespace Barotrauma.Items.Components
var existing = RequiredItems.Find(r => r.Item1 == requiredItem);
if (existing == null)
{
RequiredItems.Add(new Tuple<ItemPrefab, int>(requiredItem, 1));
RequiredItems.Add(new Tuple<ItemPrefab, int, float, bool>(requiredItem, 1, 1.0f, false));
}
else
{
RequiredItems.Remove(existing);
RequiredItems.Add(new Tuple<ItemPrefab, int>(requiredItem, existing.Item2 + 1));
RequiredItems.Add(new Tuple<ItemPrefab, int, float, bool>(requiredItem, existing.Item2 + 1, 1.0f, false));
}
}
@@ -66,6 +69,34 @@ namespace Barotrauma.Items.Components
subElement.GetAttributeString("name", ""),
subElement.GetAttributeInt("level", 0)));
break;
case "item": //New system allowing for setting minimal item condition
string requiredItemName = subElement.GetAttributeString("name", "");
float minCondition = subElement.GetAttributeFloat("mincondition", 1.0f);
//Substract mincondition from required item's condition or delete it regardless?
bool useCondition = subElement.GetAttributeBool("usecondition", false);
int count = subElement.GetAttributeInt("count", 1);
if (string.IsNullOrWhiteSpace(requiredItemName)) continue;
ItemPrefab requiredItem = MapEntityPrefab.Find(requiredItemName.Trim()) as ItemPrefab;
if (requiredItem == null)
{
DebugConsole.ThrowError("Error in fabricable item " + name + "! Required item \"" + requiredItemName + "\" not found.");
continue;
}
var existing = RequiredItems.Find(r => r.Item1 == requiredItem);
if (existing == null)
{
RequiredItems.Add(new Tuple<ItemPrefab, int, float, bool>(requiredItem, count, minCondition, useCondition));
}
else
{
RequiredItems.Remove(existing);
RequiredItems.Add(new Tuple<ItemPrefab, int, float, bool>(requiredItem, existing.Item2 + count, minCondition, useCondition));
}
break;
}
}
@@ -236,25 +267,32 @@ namespace Barotrauma.Items.Components
return;
}
foreach (Tuple<ItemPrefab, int> ip in fabricatedItem.RequiredItems)
foreach (Tuple<ItemPrefab, int, float, bool> ip in fabricatedItem.RequiredItems)
{
for (int i = 0; i < ip.Item2; i++)
{
var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1);
var requiredItem = containers[0].Inventory.Items.FirstOrDefault(it => it != null && it.Prefab == ip.Item1 && it.Condition >= ip.Item1.Health * ip.Item3);
if (requiredItem == null) continue;
//Item4 = use condition bool
if (ip.Item4 && requiredItem.Condition - ip.Item1.Health * ip.Item3 > 0.0f) //Leave it behind with reduced condition if it has enough to stay above 0
{
requiredItem.Condition -= ip.Item1.Health * ip.Item3;
continue;
}
Entity.Spawner.AddToRemoveQueue(requiredItem);
containers[0].Inventory.RemoveItem(requiredItem);
}
}
//TODO: apply OutCondition
if (containers[1].Inventory.Items.All(i => i != null))
{
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine);
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
}
else
{
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, containers[1].Inventory);
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, containers[1].Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
}
CancelFabricating(null);
@@ -269,11 +307,10 @@ namespace Barotrauma.Items.Components
{
return false;
}
ItemContainer container = item.GetComponent<ItemContainer>();
foreach (Tuple<ItemPrefab, int> ip in fabricableItem.RequiredItems)
foreach (Tuple<ItemPrefab, int, float, bool> ip in fabricableItem.RequiredItems)
{
if (Array.FindAll(container.Inventory.Items, it => it != null && it.Prefab == ip.Item1).Length < ip.Item2) return false;
if (Array.FindAll(container.Inventory.Items, it => it != null && it.Prefab == ip.Item1 && it.Condition >= ip.Item1.Health * ip.Item3).Length < ip.Item2) return false;
}
return true;
@@ -335,18 +335,18 @@ namespace Barotrauma
}
}
public Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine)
public Item(ItemPrefab itemPrefab, Vector2 position, Submarine submarine, float? spawnCondition = null)
: this(new Rectangle(
(int)(position.X - itemPrefab.sprite.size.X / 2),
(int)(position.Y + itemPrefab.sprite.size.Y / 2),
(int)itemPrefab.sprite.size.X,
(int)itemPrefab.sprite.size.Y),
itemPrefab, submarine)
itemPrefab, submarine, spawnCondition)
{
}
public Item(Rectangle newRect, ItemPrefab itemPrefab, Submarine submarine)
public Item(Rectangle newRect, ItemPrefab itemPrefab, Submarine submarine, float? spawnCondition = null)
: base(itemPrefab, submarine)
{
prefab = itemPrefab;
@@ -361,8 +361,8 @@ namespace Barotrauma
rect = newRect;
condition = prefab.Health;
lastSentCondition = prefab.Health;
condition = (float)(spawnCondition ?? prefab.Health);
lastSentCondition = condition;
XElement element = prefab.ConfigElement;
if (element == null) return;
@@ -10,12 +10,16 @@ namespace Barotrauma
struct DeconstructItem
{
public readonly string ItemPrefabName;
public readonly bool RequireFullCondition;
public readonly float MinCondition;
public readonly float MaxCondition;
public readonly float OutCondition;
public DeconstructItem(string itemPrefabName, bool requireFullCondition)
public DeconstructItem(string itemPrefabName, float minCondition, float maxCondition, float outCondition)
{
ItemPrefabName = itemPrefabName;
RequireFullCondition = requireFullCondition;
MinCondition = minCondition;
MaxCondition = maxCondition;
OutCondition = outCondition;
}
}
@@ -301,9 +305,14 @@ namespace Barotrauma
{
string deconstructItemName = deconstructItem.GetAttributeString("name", "not found");
bool requireFullCondition = deconstructItem.GetAttributeBool("requirefullcondition", false);
//minCondition does <= check, meaning that below or equeal to min condition will be skipped.
float minCondition = deconstructItem.GetAttributeFloat("mincondition", -0.1f);
//maxCondition does > check, meaning that above this max the deconstruct item will be skipped.
float maxCondition = deconstructItem.GetAttributeFloat("maxcondition", 1.0f);
//Condition of item on creation
float outCondition = deconstructItem.GetAttributeFloat("outcondition", 1.0f);
DeconstructItems.Add(new DeconstructItem(deconstructItemName, requireFullCondition));
DeconstructItems.Add(new DeconstructItem(deconstructItemName, minCondition, maxCondition, outCondition));
}
@@ -22,24 +22,28 @@ namespace Barotrauma
public readonly Vector2 Position;
public readonly Inventory Inventory;
public readonly Submarine Submarine;
public readonly float Condition;
public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition)
public ItemSpawnInfo(ItemPrefab prefab, Vector2 worldPosition, float? condition = null)
{
Prefab = prefab;
Position = worldPosition;
Condition = (float)(condition ?? prefab.Health);
}
public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub)
public ItemSpawnInfo(ItemPrefab prefab, Vector2 position, Submarine sub, float? condition = null)
{
Prefab = prefab;
Position = position;
Submarine = sub;
Condition = (float)(condition ?? prefab.Health);
}
public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory)
public ItemSpawnInfo(ItemPrefab prefab, Inventory inventory, float? condition = null)
{
Prefab = prefab;
Inventory = inventory;
Condition = (float)(condition ?? prefab.Health);
}
public Entity Spawn()
@@ -48,12 +52,12 @@ namespace Barotrauma
if (Inventory != null)
{
spawnedItem = new Item(Prefab, Vector2.Zero, null);
spawnedItem = new Item(Prefab, Vector2.Zero, null, Condition);
Inventory.TryPutItem(spawnedItem, null, spawnedItem.AllowedSlots);
}
else
{
spawnedItem = new Item(Prefab, Position, Submarine);
spawnedItem = new Item(Prefab, Position, Submarine, Condition);
}
return spawnedItem;
@@ -83,25 +87,25 @@ namespace Barotrauma
removeQueue = new Queue<Entity>();
}
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition)
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 worldPosition, float? condition = null)
{
if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition));
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, worldPosition, condition));
}
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub)
public void AddToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, Submarine sub, float? condition = null)
{
if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub));
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, position, sub, condition));
}
public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory)
public void AddToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, float? condition = null)
{
if (GameMain.Client != null) return;
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory));
spawnQueue.Enqueue(new ItemSpawnInfo(itemPrefab, inventory, condition));
}
public void AddToRemoveQueue(Entity entity)