Merge branch 'master' into moStuff

This commit is contained in:
Joonas Rikkonen
2018-01-09 10:38:06 +02:00
committed by GitHub
179 changed files with 116633 additions and 3529 deletions
@@ -454,7 +454,7 @@ namespace Barotrauma.Items.Components
float[] skillSuccess = new float[requiredSkills.Count];
for (int i = 0; i < requiredSkills.Count; i++ )
for (int i = 0; i < requiredSkills.Count; i++)
{
int characterLevel = character.GetSkillLevel(requiredSkills[i].Name);
@@ -463,7 +463,7 @@ namespace Barotrauma.Items.Components
float average = skillSuccess.Average();
return (average+100.0f)/2.0f;
return (average + 100.0f) / 2.0f;
}
public virtual void FlipX() { }
@@ -570,6 +570,7 @@ namespace Barotrauma.Items.Components
case "requireditem":
if (!overrideRequiredItems) requiredItems.Clear();
overrideRequiredItems = true;
RelatedItem newRequiredItem = RelatedItem.Load(subElement);
if (newRequiredItem == null) continue;
@@ -3,6 +3,7 @@ using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma.Items.Components
@@ -141,6 +142,9 @@ namespace Barotrauma.Items.Components
public float AvailableFuel { get; set; }
private float availableHeat, availableCooling;
private float prevTemperature, temperatureChange;
[Serialize(500.0f, true)]
public float ShutDownTemp
{
@@ -191,12 +195,20 @@ namespace Barotrauma.Items.Components
fissionRate = Math.Min(fissionRate, AvailableFuel);
float heat = 80 * fissionRate * (AvailableFuel / 2000.0f);
float heatDissipation = 50 * coolingRate + Math.Max(ExtraCooling, 5.0f);
//the amount of cooling is always non-zero, so that the reactor always needs
//to generate some amount of heat to prevent the temperature from dropping
availableCooling = Math.Max(ExtraCooling, 5.0f);
availableHeat = 80 * (AvailableFuel / 2000.0f);
float deltaTemp = (((heat - heatDissipation) * 5) - temperature) / 10000.0f;
float heat = availableHeat * fissionRate;
float heatDissipation = 50 * coolingRate + availableCooling;
float deltaTemp = (((heat - heatDissipation) * 5) - temperature) / 10000.0f;
Temperature = temperature + deltaTemp;
temperatureChange = Temperature - prevTemperature;
prevTemperature = temperature;
if (temperature > fireTemp && temperature - deltaTemp < fireTemp)
{
#if CLIENT
@@ -345,37 +357,71 @@ namespace Barotrauma.Items.Components
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
{
float degreeOfSuccess = DegreeOfSuccess(character);
//characters with insufficient skill levels don't refuel the reactor
if (degreeOfSuccess > 0.2f)
{
//remove used-up fuel from the reactor
var containedItems = item.ContainedItems;
foreach (Item item in containedItems)
{
if (item != null && item.Condition <= 0.0f)
{
item.Drop();
}
}
//the temperature is too low and not increasing even though the fission rate is high and cooling low
// -> we need more fuel
if (temperature < load * 0.5f && temperatureChange <= 0.0f && fissionRate > 0.9f && coolingRate < 0.1f)
{
var containFuelObjective = new AIObjectiveContainItem(character, new string[] { "Fuel Rod", "reactorfuel" }, item.GetComponent<ItemContainer>());
containFuelObjective.MinContainedAmount = containedItems.Count(i => i != null && i.Prefab.NameMatches("Fuel Rod") || i.HasTag("reactorfuel")) + 1;
containFuelObjective.GetItemPriority = (Item fuelItem) =>
{
if (fuelItem.ParentInventory?.Owner is Item)
{
//don't take fuel from other reactors
if (((Item)fuelItem.ParentInventory.Owner).GetComponent<Reactor>() != null) return 0.0f;
}
return 1.0f;
};
objective.AddSubObjective(containFuelObjective);
return false;
}
}
switch (objective.Option.ToLowerInvariant())
{
case "power up":
float tempDiff = load - temperature;
{
case "power up":
float tempDiff = load - temperature;
shutDownTemp = Math.Min(load + 1000.0f, 7500.0f);
shutDownTemp = Math.Min(load + 1000.0f, 7500.0f);
//temperature too high/low
if (Math.Abs(tempDiff)>500.0f)
{
AutoTemp = false;
FissionRate += deltaTime * 100.0f * Math.Sign(tempDiff);
CoolingRate -= deltaTime * 100.0f * Math.Sign(tempDiff);
}
//temperature OK
else
{
AutoTemp = true;
}
//characters with insufficient skill levels simply set the autotemp on instead of trying to adjust the temperature manually
if (Math.Abs(tempDiff) < 500.0f || degreeOfSuccess < 0.5f)
{
AutoTemp = true;
}
else
{
AutoTemp = false;
//higher skill levels make the character adjust the temperature faster
FissionRate += deltaTime * 100.0f * Math.Sign(tempDiff) * degreeOfSuccess;
CoolingRate -= deltaTime * 100.0f * Math.Sign(tempDiff) * degreeOfSuccess;
}
break;
case "shutdown":
shutDownTemp = 0.0f;
break;
}
break;
case "shutdown":
shutDownTemp = 0.0f;
break;
}
return false;
return false;
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power)
{
switch (connection.Name)
@@ -98,7 +98,6 @@ namespace Barotrauma.Items.Components
: base(item, element)
{
IsActive = true;
InitProjSpecific();
}
@@ -128,8 +127,10 @@ namespace Barotrauma.Items.Components
unsentChanges = false;
}
}
if (voltage < minVoltage && powerConsumption > 0.0f) return;
currPowerConsumption = powerConsumption;
if (voltage < minVoltage && currPowerConsumption > 0.0f) return;
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
@@ -9,9 +9,7 @@ namespace Barotrauma.Items.Components
{
static float fullPower;
static float fullLoad;
//private bool updated;
private int updateTimer;
const float FireProbability = 0.15f;
@@ -19,35 +17,82 @@ namespace Barotrauma.Items.Components
//affects how fast changes in power/load are carried over the grid
static float inertia = 5.0f;
static HashSet<Powered> connectedList = new HashSet<Powered>();
private HashSet<PowerTransfer> connectedPoweredList = new HashSet<PowerTransfer>();
private List<Connection> powerConnections;
private Dictionary<Connection, bool> connectionDirty = new Dictionary<Connection, bool>();
//a list of connections a given connection is connected to, either directly or via other power transfer components
private Dictionary<Connection, HashSet<Connection>> connectedRecipients = new Dictionary<Connection, HashSet<Connection>>();
private float powerLoad;
private bool isBroken;
public float PowerLoad
{
get { return powerLoad; }
}
//can the component transfer power
public virtual bool CanTransfer
private bool canTransfer;
public bool CanTransfer
{
get { return IsActive; }
get { return canTransfer; }
set
{
if (canTransfer == value) return;
canTransfer = value;
SetAllConnectionsDirty();
}
}
public override bool IsActive
{
get
{
return base.IsActive;
}
set
{
if (base.IsActive != value) SetAllConnectionsDirty();
base.IsActive = value;
}
}
public PowerTransfer(Item item, XElement element)
: base(item, element)
{
IsActive = true;
canTransfer = true;
powerConnections = new List<Connection>();
}
public override void UpdateBroken(float deltaTime, Camera cam)
{
base.UpdateBroken(deltaTime, cam);
if (!isBroken)
{
SetAllConnectionsDirty();
isBroken = true;
}
}
public override void Update(float deltaTime, Camera cam)
{
if (!CanTransfer) return;
if (isBroken)
{
SetAllConnectionsDirty();
isBroken = false;
}
RefreshConnections();
if (updateTimer > 0)
{
//this junction box has already been updated this frame
@@ -60,16 +105,13 @@ namespace Barotrauma.Items.Components
fullPower = 0.0f;
fullLoad = 0.0f;
connectedList.Clear();
connectedPoweredList.Clear();
CheckJunctions(deltaTime);
CheckPower(deltaTime);
updateTimer = 0;
foreach (Powered p in connectedList)
{
PowerTransfer pt = p as PowerTransfer;
if (pt == null) continue;
foreach (PowerTransfer pt in connectedPoweredList)
{
pt.powerLoad += (fullLoad - pt.powerLoad) / inertia;
pt.currPowerConsumption += (-fullPower - pt.currPowerConsumption) / inertia;
pt.Item.SendSignal(0, "", "power", null, fullPower / Math.Max(fullLoad, 1.0f));
@@ -112,39 +154,99 @@ namespace Barotrauma.Items.Components
return picker != null;
}
private void RefreshConnections()
{
var connections = item.Connections;
foreach (Connection c in connections)
{
if (!connectionDirty[c]) continue;
HashSet<Connection> connected = new HashSet<Connection>();
if (!connectedRecipients.ContainsKey(c))
{
connectedRecipients.Add(c, connected);
}
else
{
//mark all previous recipients as dirty
foreach (Connection recipient in connectedRecipients[c])
{
var pt = recipient.Item.GetComponent<PowerTransfer>();
if (pt != null) pt.connectionDirty[recipient] = true;
}
}
//find all connections that are connected to this one (directly or via another PowerTransfer)
connected.Add(c);
GetConnected(c, connected);
connectedRecipients[c] = connected;
//go through all the PowerTransfers and we're connected to and set their connections to match the ones we just calculated
//(no need to go through the recursive GetConnected method again)
foreach (Connection recipient in connected)
{
var recipientPowerTransfer = recipient.Item.GetComponent<PowerTransfer>();
if (recipientPowerTransfer == null) continue;
if (!connectedRecipients.ContainsKey(recipient))
{
connectedRecipients.Add(recipient, connected);
}
recipientPowerTransfer.connectedRecipients[recipient] = connected;
recipientPowerTransfer.connectionDirty[recipient] = false;
}
}
}
//Finds all the connections that can receive a signal sent into the given connection and stores them in the hashset.
private void GetConnected(Connection c, HashSet<Connection> connected)
{
var recipients = c.Recipients;
foreach (Connection recipient in recipients)
{
if (recipient == null || connected.Contains(recipient)) continue;
Item it = recipient.Item;
if (it == null || it.Condition <= 0.0f) continue;
connected.Add(recipient);
var powerTransfer = it.GetComponent<PowerTransfer>();
if (powerTransfer != null && powerTransfer.CanTransfer && powerTransfer.IsActive)
{
GetConnected(recipient, connected);
}
}
}
//a recursive function that goes through all the junctions and adds up
//all the generated/consumed power of the constructions connected to the grid
private void CheckJunctions(float deltaTime)
private void CheckPower(float deltaTime)
{
updateTimer = 1;
connectedList.Add(this);
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
connectedPoweredList.Clear();
foreach (Connection c in powerConnections)
{
var recipients = c.Recipients;
HashSet<Connection> recipients = connectedRecipients[c];
foreach (Connection recipient in recipients)
{
if (recipient == null) continue;
Item it = recipient.Item;
if (it == null) continue;
if (it.Condition <= 0.0f) continue;
if (it == null || it.Condition <= 0.0f) continue;
foreach (Powered powered in it.GetComponents<Powered>())
{
if (powered == null || !powered.IsActive) continue;
if (connectedList.Contains(powered)) continue;
PowerTransfer powerTransfer = powered as PowerTransfer;
if (powerTransfer != null)
{
if (!powerTransfer.CanTransfer) continue;
powerTransfer.CheckJunctions(deltaTime);
connectedPoweredList.Add(powerTransfer);
powerTransfer.updateTimer = 1;
continue;
}
@@ -162,25 +264,38 @@ namespace Barotrauma.Items.Components
}
else
{
connectedList.Add(powered);
//positive power consumption = the construction requires power -> increase load
if (powered.CurrPowerConsumption > 0.0f)
{
fullLoad += powered.CurrPowerConsumption;
}
else if (powered.CurrPowerConsumption < 0.0f)
//negative power consumption = the construction is a
//generator/battery or another junction box
//negative power consumption = the construction is a /generator/battery
{
fullPower -= powered.CurrPowerConsumption;
}
}
}
}
}
}
public void SetAllConnectionsDirty()
{
if (item.Connections == null) return;
foreach (Connection c in item.Connections)
{
connectionDirty[c] = true;
}
}
public void SetConnectionDirty(Connection connection)
{
var connections = item.Connections;
if (connections == null || !connections.Contains(connection)) return;
connectionDirty[connection] = true;
}
public override void OnMapLoaded()
{
var connections = item.Connections;
@@ -189,18 +304,38 @@ namespace Barotrauma.Items.Components
IsActive = false;
return;
}
powerConnections = connections.FindAll(c => c.IsPower);
if (powerConnections.Count == 0) IsActive = false;
SetAllConnectionsDirty();
}
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power)
{
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power);
if (!connectedRecipients.ContainsKey(connection)) return;
if (connection.Name.Length > 5 && connection.Name.Substring(0, 6).ToLowerInvariant() == "signal")
{
connection.SendSignal(stepsTaken, signal, source, sender, 0.0f);
foreach (Connection recipient in connectedRecipients[connection])
{
if (recipient.Item == item || recipient.Item == source) continue;
foreach (ItemComponent ic in recipient.Item.components)
{
//powertransfer components don't need to receive the signal because we relay it straight
//to the connected items without going through the whole chain of junction boxes
if (ic is PowerTransfer) continue;
ic.ReceiveSignal(stepsTaken, signal, recipient, source, sender, 0.0f);
}
foreach (StatusEffect effect in recipient.effects)
{
recipient.Item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f);
}
}
}
}
@@ -20,7 +20,7 @@ namespace Barotrauma.Items.Components
private static Wire draggingConnected;
private List<StatusEffect> effects;
public readonly List<StatusEffect> effects;
public readonly ushort[] wireId;
@@ -167,8 +167,6 @@ namespace Barotrauma.Items.Components
foreach (StatusEffect effect in recipient.effects)
{
//effect.Apply(ActionType.OnUse, 1.0f, recipient.item, recipient.item);
recipient.item.ApplyStatusEffect(effect, ActionType.OnUse, 1.0f);
}
}
@@ -31,21 +31,14 @@ namespace Barotrauma.Items.Components
set
{
isOn = value;
CanTransfer = value;
if (!isOn)
{
currPowerConsumption = 0.0f;
}
}
}
public override bool CanTransfer
{
get
{
return isOn;
}
}
public RelayComponent(Item item, XElement element)
: base (item, element)
{
@@ -30,21 +30,13 @@ namespace Barotrauma.Items.Components
const float nodeDistance = 32.0f;
const float heightFromFloor = 128.0f;
static Sprite wireSprite;
private List<Vector2> nodes;
private List<WireSection> sections;
Connection[] connections;
private Connection[] connections;
private Vector2 newNodePos;
private static Wire draggingWire;
private static int? selectedNodeIndex;
private static int? highlightedNodeIndex;
public bool Hidden, Locked;
public Connection[] Connections
@@ -55,12 +47,14 @@ namespace Barotrauma.Items.Components
public Wire(Item item, XElement element)
: base(item, element)
{
#if CLIENT
if (wireSprite == null)
{
wireSprite = new Sprite("Content/Items/wireHorizontal.png", new Vector2(0.5f, 0.5f));
wireSprite.Depth = 0.85f;
}
#endif
nodes = new List<Vector2>();
sections = new List<WireSection>();
@@ -86,14 +80,15 @@ namespace Barotrauma.Items.Components
public void RemoveConnection(Item item)
{
for (int i = 0; i<2; i++)
for (int i = 0; i < 2; i++)
{
if (connections[i]==null || connections[i].Item!=item) continue;
for (int n = 0; n< connections[i].Wires.Length; n++)
if (connections[i] == null || connections[i].Item != item) continue;
for (int n = 0; n < connections[i].Wires.Length; n++)
{
if (connections[i].Wires[n] != this) continue;
SetConnectedDirty();
connections[i].Wires[n] = null;
}
connections[i] = null;
@@ -104,6 +99,8 @@ namespace Barotrauma.Items.Components
{
if (connection == connections[0]) connections[0] = null;
if (connection == connections[1]) connections[1] = null;
SetConnectedDirty();
}
public bool Connect(Connection newConnection, bool addNode = true, bool sendNetworkEvent = false)
@@ -137,8 +134,7 @@ namespace Barotrauma.Items.Components
if (newConnection.Item.Submarine == null) continue;
if (nodes.Count > 0 && nodes[0] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break;
if (nodes.Count > 1 && nodes[nodes.Count-1] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break;
if (nodes.Count > 1 && nodes[nodes.Count - 1] == newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition) break;
if (i == 0)
{
@@ -148,11 +144,12 @@ namespace Barotrauma.Items.Components
{
nodes.Add(newConnection.Item.Position - newConnection.Item.Submarine.HiddenSubPosition);
}
break;
}
SetConnectedDirty();
if (connections[0] != null && connections[1] != null)
{
foreach (ItemComponent ic in item.components)
@@ -323,6 +320,8 @@ namespace Barotrauma.Items.Components
connections[1].Item.Name + " (" + connections[1].Name + ")", ServerLog.MessageType.ItemInteraction);
}
}
SetConnectedDirty();
for (int i = 0; i < 2; i++)
{
@@ -363,6 +362,18 @@ namespace Barotrauma.Items.Components
return position;
}
public void SetConnectedDirty()
{
for (int i = 0; i < 2; i++)
{
if (connections[i]?.Item != null)
{
var pt = connections[i].Item.GetComponent<PowerTransfer>();
if (pt != null) pt.SetConnectionDirty(connections[i]);
}
}
}
private void CleanNodes()
{
for (int i = nodes.Count - 2; i > 0; i--)