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

View File

@@ -111,9 +111,9 @@ namespace Barotrauma.Items.Components
if (!inadequateSkills.Any())
{
text = "Required items:\n";
foreach (Tuple<ItemPrefab, int> ip in targetItem.RequiredItems)
foreach (Tuple<ItemPrefab, int, float, bool> ip in targetItem.RequiredItems)
{
text += " - " + ip.Item1.Name + " x" + ip.Item2 + "\n";
text += " - " + ip.Item1.Name + " x" + ip.Item2 + (ip.Item3 < 1.0f ? ", " + ip.Item3 * 100 + "% condition\n" : "\n");
}
text += "Required time: " + targetItem.RequiredTime + " s";
}

View File

@@ -134,8 +134,9 @@
<Deconstruct time="20">
<Item name="Steel Bar"/>
<Item name="Copper Bar"/>
<Item name="Polycarbonate Bar"/>
<Item name="Polycarbonate Bar"/>
<Item name="FPGA Circuit"/>
</Deconstruct>
<Sprite texture ="Scooter.png" depth="0.55"/>

View File

@@ -99,6 +99,11 @@
price="100"
description="Field-programmable gate array - a multi-purpose circuit which can be reconfigured for use in a large variety of electrical devices.">
<Deconstruct time="5">
<Item name="Copper Bar"/>
<Item name="Copper Bar"/>
</Deconstruct>
<Sprite texture="signalcomp.png" depth="0.8" sourcerect="32,16,16,16"/>
<Body width="16" height="16" density="30"/>

View File

@@ -15,16 +15,22 @@
<sound file="fabricator.ogg" type="OnActive" range="1000.0" loop="true"/>
<fabricableitem name="Harpoon Gun" requireditems="Steel Bar, Polycarbonate Bar, Aluminium" requiredtime="20">
<fabricableitem name="Harpoon Gun" requireditems="Steel Bar, Polycarbonate Bar" requiredtime="20">
<RequiredSkill name="Construction" level="30"/>
<Item name="Aluminium" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name="Spear" requireditems="Steel Bar" requiredtime="10"/>
<fabricableitem name="Plasma Cutter" requireditems="Steel Bar, Polycarbonate Bar, Aluminium" requiredtime="20">
<RequiredSkill name="Construction" level="30"/>
<fabricableitem name="Revolver Round" requireditems="Copper Bar" requiredtime="10">
<Item name="Aluminium" mincondition="0.5" usecondition="true"/>
</fabricableitem>
<fabricableitem name="Welding Tool" requireditems="Steel Bar, Polycarbonate Bar, Aluminium" requiredtime="20">
<fabricableitem name="Plasma Cutter" requireditems="Steel Bar, Polycarbonate Bar" requiredtime="20">
<RequiredSkill name="Construction" level="30"/>
<Item name="Aluminium" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name="Welding Tool" requireditems="Steel Bar, Polycarbonate Bar" requiredtime="20">
<RequiredSkill name="Construction" level="30"/>
<Item name="Aluminium" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name="Railgun Shell" requireditems="Steel Bar, Steel Bar, Polycarbonate Bar" requiredtime="20">
@@ -33,13 +39,23 @@
<fabricableitem name="Nuclear Shell" requireditems="Steel Bar, Steel Bar, Uranium Bar, Polycarbonate Bar" requiredtime="30">
<RequiredSkill name="Construction" level="40"/>
</fabricableitem>
<fabricableitem name="Depth Charge Shell" requireditems="Steel Bar, Steel Bar" requiredtime="20">
<RequiredSkill name="Construction" level="25"/>
</fabricableitem>
<fabricableitem name="Nuclear Depth Charge Shell" requireditems="Steel Bar, Steel Bar, Uranium Bar" requiredtime="30">
<RequiredSkill name="Construction" level="40"/>
</fabricableitem>
<fabricableitem name="Diving Mask" requireditems="Polycarbonate Bar" requiredtime="20">
<RequiredSkill name="Construction" level="25"/>
</fabricableitem>
<fabricableitem name="Diving Suit" requireditems="Steel Bar, Aluminium, Aluminium, Polycarbonate Bar, Polycarbonate Bar" requiredtime="30">
<fabricableitem name="Diving Suit" requireditems="Steel Bar, Polycarbonate Bar, Polycarbonate Bar" requiredtime="30">
<RequiredSkill name="Construction" level="40"/>
<Item name="Aluminium" count="2" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name="Fire Extinguisher" requireditems="Steel Bar, Polycarbonate Bar" requiredtime="10"/>
<fabricableitem name="Flashlight" requireditems="Copper Bar, Polycarbonate Bar" requiredtime="10"/>
<fabricableitem name="Wire" requireditems="Copper Bar" requiredtime="5"/>
<fabricableitem name="Button" requireditems="Steel Bar, FPGA Circuit" requiredtime="10"/>
@@ -62,25 +78,42 @@
<fabricableitem name="Underwater Scooter" requireditems="Steel Bar, Polycarbonate Bar, Polycarbonate Bar, FPGA Circuit" requiredtime="30"/>
<fabricableitem name="Fulgurium Battery Cell" requireditems="Steel Bar, Fulgurium Bar, Sulphuric Acid" requiredtime="10"/>
<fabricableitem name="Flare" requireditems="Phosphorus,Aluminium" requiredtime="10"/>
<fabricableitem name ="Stun Grenade" requireditems="Steel Bar, Flash Powder, Chloral Hydrate" requiredtime="20">
<RequiredSkill name="Construction" level="30"/>
<fabricableitem name="Fulgurium Battery Cell" requireditems="Steel Bar, Fulgurium Bar" requiredtime="10">
<Item name="Sulphuric Acid" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name ="Incendium Grenade" requireditems="Stun Grenade, Incendium Bar" requiredtime="20">
<fabricableitem name="Flare" requiredtime="10">
<Item name="Phosphorus" mincondition="0.25" usecondition="true"/>
<Item name="Aluminium" mincondition="0.25" usecondition="true"/>
</fabricableitem>
<fabricableitem name ="Stun Grenade" requireditems="Steel Bar" requiredtime="20">
<RequiredSkill name="Construction" level="30"/>
<Item name="Flash Powder" mincondition="0.75"/>
<Item name="Chloral Hydrate" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name ="Incendium Grenade" requireditems="Steel Bar, Incendium Bar" requiredtime="20">
<RequiredSkill name="Construction" level="40"/>
<Item name="Flash Powder" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name ="IC-4 Block" requireditems="C-4 Block, Incendium Bar" requiredtime="20"/>
<fabricableitem name="Battery Cell" requireditems="Steel Bar, Copper Bar, Sulphuric Acid" requiredtime="10"/>
<fabricableitem name="Battery Cell" requireditems="Steel Bar, Copper Bar" requiredtime="10">
<Item name="Sulphuric Acid" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name="Fuel Rod" requireditems="Steel Bar, Uranium Bar"/>
<fabricableitem name="Incendium Fuel Rod" requireditems="Steel Bar, Incendium Bar"/>
<fabricableitem name="Uranium Bar">
<Item name="Uranium Powder" count="3" mincondition="0.75"/>
</fabricableitem>
<fabricableitem name="Oxygen Tank" requireditems="Steel Bar" outcondition="0.0"/>
<fabricableitem name="Welding Fuel Tank" requireditems="Steel Bar" outcondition="0.0"/>
</Fabricator>
<ConnectionPanel selectkey="Action" canbeselected = "true">

View File

@@ -4,7 +4,9 @@
category="Equipment"
tags="smallitem"
description="Allows remote communication between the crew.">
description="Allows remote communication between the crew."
price="10">
<Sprite texture ="headset.png" depth="0.6"/>

View File

@@ -61,7 +61,9 @@
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="Uranium Bar" requirefullcondition="true"/>
<Item name="Uranium Powder" mincondition="0.1" maxcondition="0.5"/>
<Item name="Uranium Powder" mincondition="0.1" maxcondition="0.9"/>
<Item name="Uranium Bar" mincondition="0.9"/>
</Deconstruct>
<Sprite texture ="fuelrod.png" depth="0.55"/>
@@ -79,7 +81,7 @@
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="Incendium Bar" requirefullcondition="true"/>
<Item name="Incendium Bar" mincondition="0.95"/>
</Deconstruct>
<Sprite texture ="fuelrod.png" depth="0.55"/>
@@ -93,7 +95,7 @@
<Item
name="Heat Absorber"
Tags="smallitem"
>
price="50">
<Sprite texture ="heatabsorber.png"/>

View File

@@ -271,8 +271,10 @@
tags="smallitem">
<Deconstruct time="10">
<Item name="Phosphorus"/>
<Item name="Aluminium"/>
<Item name="Phosphorus" mincondition="0.9" outcondition="0.25"/>
<Item name="Aluminium" mincondition="0.9" outcondition="0.25"/>
<Item name="Phosphorus" mincondition="0.5" maxcondition="0.9" outcondition="0.1"/>
<Item name="Aluminium" mincondition="0.5" maxcondition="0.9" outcondition="0.1"/>
</Deconstruct>

View File

@@ -144,6 +144,12 @@
price="200"
tags="smallitem,weapon">
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="Flash Powder" mincondition="0.9"/>
<Item name="Chloral Hydrate" mincondition="0.9"/>
</Deconstruct>
<Sprite texture="weapons.png" sourcerect="98,0,11,24" depth="0.55"/>
<Body width="11" height="24" density="30"/>
@@ -161,6 +167,12 @@
category="Equipment"
tags="smallitem,weapon">
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="Flash Powder" mincondition="0.9"/>
<Item name="Incendium Bar" mincondition="0.9"/>
</Deconstruct>
<Sprite texture="weapons.png" sourcerect="98,0,11,24" depth="0.55"/>
<Body width="11" height="24" density="30"/>
@@ -222,8 +234,8 @@
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="FPGA Circuit"/>
<Item name="Sulphuric Acid"/>
<Item name="Copper Bar" mincondition="0.5"/>
<Item name="Sulphuric Acid" mincondition="0.9"/>
</Deconstruct>
<Sprite texture="weapons.png" sourcerect="0,0,20,9" depth="0.8"/>
@@ -242,8 +254,8 @@
<Deconstruct time="10">
<Item name="Steel Bar"/>
<Item name="FPGA Circuit"/>
<Item name="Fulgurium Bar"/>
<Item name="Fulgurium Bar" mincondition="0.8"/>
<Item name="Sulphuric Acid" mincondition="0.9"/>
</Deconstruct>
<Sprite texture="weapons.png" sourcerect="0,0,20,9" depth="0.8"/>

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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));
}

View File

@@ -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)