Unstable 0.17.0.0
This commit is contained in:
+154
-97
@@ -13,8 +13,6 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float charge;
|
||||
|
||||
//private float rechargeVoltage;
|
||||
|
||||
//how fast the battery can be recharged
|
||||
private float maxRechargeSpeed;
|
||||
|
||||
@@ -27,45 +25,52 @@ namespace Barotrauma.Items.Components
|
||||
protected Vector2 indicatorPosition, indicatorSize;
|
||||
|
||||
protected bool isHorizontal;
|
||||
|
||||
|
||||
protected override PowerPriority Priority { get { return PowerPriority.Battery; } }
|
||||
|
||||
private float currPowerOutput;
|
||||
public float CurrPowerOutput
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
get { return currPowerOutput; }
|
||||
private set
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(value >= 0.0f);
|
||||
currPowerOutput = Math.Max(0, value);
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize("0,0", true, description: "The position of the progress bar indicating the charge of the item. In pixels as an offset from the upper left corner of the sprite.")]
|
||||
[Serialize("0,0", IsPropertySaveable.Yes, description: "The position of the progress bar indicating the charge of the item. In pixels as an offset from the upper left corner of the sprite.")]
|
||||
public Vector2 IndicatorPosition
|
||||
{
|
||||
get { return indicatorPosition; }
|
||||
set { indicatorPosition = value; }
|
||||
}
|
||||
|
||||
[Serialize("0,0", true, description: "The size of the progress bar indicating the charge of the item (in pixels).")]
|
||||
[Serialize("0,0", IsPropertySaveable.Yes, description: "The size of the progress bar indicating the charge of the item (in pixels).")]
|
||||
public Vector2 IndicatorSize
|
||||
{
|
||||
get { return indicatorSize; }
|
||||
set { indicatorSize = value; }
|
||||
}
|
||||
|
||||
[Serialize(false, true, description: "Should the progress bar indicating the charge of the item fill up horizontally or vertically.")]
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "Should the progress bar indicating the charge of the item fill up horizontally or vertically.")]
|
||||
public bool IsHorizontal
|
||||
{
|
||||
get { return isHorizontal; }
|
||||
set { isHorizontal = value; }
|
||||
}
|
||||
|
||||
[Editable, Serialize(10.0f, true, description: "Maximum output of the device when fully charged (kW).")]
|
||||
[Editable, Serialize(10.0f, IsPropertySaveable.Yes, description: "Maximum output of the device when fully charged (kW).")]
|
||||
public float MaxOutPut { set; get; }
|
||||
|
||||
[Editable, Serialize(10.0f, true, description: "The maximum capacity of the device (kW * min). For example, a value of 1000 means the device can output 100 kilowatts of power for 10 minutes, or 1000 kilowatts for 1 minute.")]
|
||||
[Editable, Serialize(10.0f, IsPropertySaveable.Yes, description: "The maximum capacity of the device (kW * min). For example, a value of 1000 means the device can output 100 kilowatts of power for 10 minutes, or 1000 kilowatts for 1 minute.")]
|
||||
public float Capacity
|
||||
{
|
||||
get { return capacity; }
|
||||
set { capacity = Math.Max(value, 1.0f); }
|
||||
}
|
||||
|
||||
[Editable, Serialize(0.0f, true, description: "The current charge of the device.")]
|
||||
[Editable, Serialize(0.0f, IsPropertySaveable.Yes, description: "The current charge of the device.")]
|
||||
public float Charge
|
||||
{
|
||||
get { return charge; }
|
||||
@@ -87,14 +92,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public float ChargePercentage => MathUtils.Percentage(Charge, Capacity);
|
||||
|
||||
[Editable, Serialize(10.0f, true, description: "How fast the device can be recharged. For example, a recharge speed of 100 kW and a capacity of 1000 kW*min would mean it takes 10 minutes to fully charge the device.")]
|
||||
[Editable, Serialize(10.0f, IsPropertySaveable.Yes, description: "How fast the device can be recharged. For example, a recharge speed of 100 kW and a capacity of 1000 kW*min would mean it takes 10 minutes to fully charge the device.")]
|
||||
public float MaxRechargeSpeed
|
||||
{
|
||||
get { return maxRechargeSpeed; }
|
||||
set { maxRechargeSpeed = Math.Max(value, 1.0f); }
|
||||
}
|
||||
|
||||
[Editable, Serialize(10.0f, true, description: "The current recharge speed of the device.")]
|
||||
[Editable, Serialize(10.0f, IsPropertySaveable.Yes, description: "The current recharge speed of the device.")]
|
||||
public float RechargeSpeed
|
||||
{
|
||||
get { return rechargeSpeed; }
|
||||
@@ -110,14 +115,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(false, true, description: "If true, the recharge speed (and power consumption) of the device goes up exponentially as the recharge rate is increased.")]
|
||||
[Serialize(false, IsPropertySaveable.Yes, description: "If true, the recharge speed (and power consumption) of the device goes up exponentially as the recharge rate is increased.")]
|
||||
public bool ExponentialRechargeSpeed { get; set; }
|
||||
|
||||
[Editable(minValue: 0.0f, maxValue: 10.0f, decimals: 2), Serialize(0.5f, true)]
|
||||
[Editable(minValue: 0.0f, maxValue: 10.0f, decimals: 2), Serialize(0.5f, IsPropertySaveable.Yes)]
|
||||
public float RechargeAdjustSpeed { get; set; }
|
||||
|
||||
private float efficiency;
|
||||
[Editable(minValue: 0.0f, maxValue: 1.0f, decimals: 2), Serialize(0.95f, true, description: "The amount of power you can get out of a item relative to the amount of power that's put into it.")]
|
||||
[Editable(minValue: 0.0f, maxValue: 1.0f, decimals: 2), Serialize(0.95f, IsPropertySaveable.Yes, description: "The amount of power you can get out of a item relative to the amount of power that's put into it.")]
|
||||
public float Efficiency
|
||||
{
|
||||
get { return efficiency; }
|
||||
@@ -130,7 +135,7 @@ namespace Barotrauma.Items.Components
|
||||
private bool isRunning;
|
||||
public bool HasBeenTuned { get; private set; }
|
||||
|
||||
public PowerContainer(Item item, XElement element)
|
||||
public PowerContainer(Item item, ContentXElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
IsActive = true;
|
||||
@@ -154,92 +159,142 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
isRunning = true;
|
||||
float chargeRatio = charge / capacity;
|
||||
float gridPower = 0.0f;
|
||||
float gridLoad = 0.0f;
|
||||
foreach (Connection c in item.Connections)
|
||||
{
|
||||
if (!c.IsPower || !c.IsOutput) { continue; }
|
||||
foreach (Connection c2 in c.Recipients)
|
||||
{
|
||||
if (c2.Item.Condition <= 0.0f) { continue; }
|
||||
|
||||
PowerTransfer pt = c2.Item.GetComponent<PowerTransfer>();
|
||||
if (pt == null)
|
||||
{
|
||||
foreach (Powered powered in c2.Item.GetComponents<Powered>())
|
||||
{
|
||||
if (!powered.IsActive) continue;
|
||||
gridLoad += powered.CurrPowerConsumption;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!pt.IsActive || !pt.CanTransfer) { continue; }
|
||||
gridPower -= pt.CurrPowerConsumption;
|
||||
gridLoad += pt.PowerLoad;
|
||||
}
|
||||
}
|
||||
|
||||
if (chargeRatio > 0.0f)
|
||||
{
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
}
|
||||
|
||||
if (charge >= capacity)
|
||||
float loadReading = 0;
|
||||
if (powerOut != null && powerOut.Grid != null)
|
||||
{
|
||||
//rechargeVoltage = 0.0f;
|
||||
charge = capacity;
|
||||
CurrPowerConsumption = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
float missingCharge = capacity - charge;
|
||||
float targetRechargeSpeed = rechargeSpeed;
|
||||
if (ExponentialRechargeSpeed)
|
||||
{
|
||||
targetRechargeSpeed = MathF.Pow(rechargeSpeed / maxRechargeSpeed, 2) * maxRechargeSpeed;
|
||||
}
|
||||
if (missingCharge < 1.0f)
|
||||
{
|
||||
targetRechargeSpeed *= missingCharge;
|
||||
}
|
||||
if (currPowerConsumption < targetRechargeSpeed)
|
||||
{
|
||||
currPowerConsumption = Math.Min(currPowerConsumption + deltaTime * maxRechargeSpeed * RechargeAdjustSpeed, targetRechargeSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
currPowerConsumption = Math.Max(currPowerConsumption - deltaTime * maxRechargeSpeed * RechargeAdjustSpeed, targetRechargeSpeed);
|
||||
}
|
||||
Charge += currPowerConsumption * Math.Min(Voltage, 1.0f) / 3600.0f * efficiency;
|
||||
}
|
||||
|
||||
if (charge <= 0.0f)
|
||||
{
|
||||
CurrPowerOutput = 0.0f;
|
||||
charge = 0.0f;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//output starts dropping when the charge is less than 10%
|
||||
float maxOutputRatio = 1.0f;
|
||||
if (chargeRatio < 0.1f)
|
||||
{
|
||||
maxOutputRatio = Math.Max(chargeRatio * 10.0f, 0.0f);
|
||||
}
|
||||
|
||||
CurrPowerOutput += (gridLoad - gridPower) * deltaTime;
|
||||
|
||||
float maxOutput = Math.Min(MaxOutPut * maxOutputRatio, gridLoad);
|
||||
CurrPowerOutput = MathHelper.Clamp(CurrPowerOutput, 0.0f, maxOutput);
|
||||
Charge -= CurrPowerOutput / 3600.0f;
|
||||
loadReading = powerOut.Grid.Load;
|
||||
}
|
||||
|
||||
item.SendSignal(((int)Math.Round(-CurrPowerOutput)).ToString(), "power_value_out");
|
||||
item.SendSignal(((int)Math.Round(loadReading)).ToString(), "load_value_out");
|
||||
item.SendSignal(((int)Math.Round(Charge)).ToString(), "charge");
|
||||
item.SendSignal(((int)Math.Round(Charge / capacity * 100)).ToString(), "charge_%");
|
||||
item.SendSignal(((int)Math.Round(RechargeSpeed / maxRechargeSpeed * 100)).ToString(), "charge_rate");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the power consumption if checking the powerIn connection, or a negative value if the output can provide power when checking powerOut.
|
||||
/// Power consumption is proportional to set recharge speed and if there is less than max charge.
|
||||
/// </summary>
|
||||
public override float GetCurrentPowerConsumption(Connection connection = null)
|
||||
{
|
||||
if (connection == powerIn)
|
||||
{
|
||||
//Don't draw power if fully charged
|
||||
if (charge >= capacity)
|
||||
{
|
||||
charge = capacity;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
float missingCharge = capacity - charge;
|
||||
float targetRechargeSpeed = rechargeSpeed;
|
||||
|
||||
if (ExponentialRechargeSpeed)
|
||||
{
|
||||
targetRechargeSpeed = MathF.Pow(rechargeSpeed / maxRechargeSpeed, 2) * maxRechargeSpeed;
|
||||
}
|
||||
//For the last kwMin scale the recharge rate linearly to prevent overcharging and to have a smooth cutoff
|
||||
if (missingCharge < 1.0f)
|
||||
{
|
||||
targetRechargeSpeed *= missingCharge;
|
||||
}
|
||||
|
||||
return MathHelper.Clamp(targetRechargeSpeed, 0, MaxRechargeSpeed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrPowerOutput = 0;
|
||||
return charge > 0 ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum and maximum output for the queried connection.
|
||||
/// Powerin min max equals CurrPowerConsumption as its abnormal for there to be power out.
|
||||
/// PowerOut min power out is zero and max is the maxout unless below 10% charge where
|
||||
/// the output is scaled relative to the 10% charge.
|
||||
/// </summary>
|
||||
/// <param name="connection">Connection being queried</param>
|
||||
/// <param name="load">Current grid load</param>
|
||||
/// <returns>Minimum and maximum power output for the connection</returns>
|
||||
public override PowerRange MinMaxPowerOut(Connection connection, float load = 0)
|
||||
{
|
||||
if (connection == powerOut)
|
||||
{
|
||||
float maxOutput;
|
||||
float chargeRatio = charge / capacity;
|
||||
if (chargeRatio < 0.1f)
|
||||
{
|
||||
maxOutput = Math.Max(chargeRatio * 10.0f, 0.0f) * MaxOutPut;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxOutput = MaxOutPut;
|
||||
}
|
||||
|
||||
//Limit max power out to not exceed the charge of the container
|
||||
maxOutput = Math.Min(maxOutput, charge * 60 / UpdateInterval);
|
||||
return new PowerRange(0.0f, maxOutput);
|
||||
}
|
||||
|
||||
return PowerRange.Zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalized power out from the container for the connection, provided the given grid information
|
||||
/// Output power based on the maxpower all batteries can output. So all batteries can
|
||||
/// equally share powerout based on their output capabilities.
|
||||
/// </summary>
|
||||
/// <param name="connection"></param>
|
||||
/// <param name="power"></param>
|
||||
/// <param name="minMaxPower"></param>
|
||||
/// <param name="load"></param>
|
||||
/// <returns></returns>
|
||||
public override float GetConnectionPowerOut(Connection connection, float power, PowerRange minMaxPower, float load)
|
||||
{
|
||||
if (connection == powerOut)
|
||||
{
|
||||
//Calculate the max power the container can output
|
||||
float maxPowerOutput = MaxOutPut;
|
||||
float chargeRatio = charge / capacity;
|
||||
if (chargeRatio < 0.1f)
|
||||
{
|
||||
maxPowerOutput *= Math.Max(chargeRatio * 10.0f, 0.0f);
|
||||
}
|
||||
|
||||
//Set power output based on the relative max power output capabilities and load demand
|
||||
CurrPowerOutput = MathHelper.Clamp((load - power) / minMaxPower.Max, 0, 1) * maxPowerOutput;
|
||||
return CurrPowerOutput;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When the corresponding grid connection is resolved, adjust the container's charge.
|
||||
/// </summary>
|
||||
public override void GridResolved(Connection conn)
|
||||
{
|
||||
if (conn == powerIn)
|
||||
{
|
||||
//Increase charge based on how much power came in from the grid
|
||||
Charge += (CurrPowerConsumption * Voltage) / 60 * UpdateInterval * efficiency;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Decrease charge based on how much power is leaving the device
|
||||
Charge = Math.Clamp(Charge - CurrPowerOutput / 60 * UpdateInterval, 0, Capacity);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
||||
{
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return false; }
|
||||
@@ -250,8 +305,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (HasBeenTuned) { return true; }
|
||||
|
||||
float targetRatio = string.IsNullOrEmpty(objective.Option) || objective.Option.Equals("charge", StringComparison.OrdinalIgnoreCase) ? aiRechargeTargetRatio : -1;
|
||||
if (targetRatio > 0 || float.TryParse(objective.Option, out targetRatio))
|
||||
float targetRatio = objective.Option.IsEmpty || objective.Option == "charge" ? aiRechargeTargetRatio : -1;
|
||||
if (targetRatio > 0 || float.TryParse(objective.Option.Value, out targetRatio))
|
||||
{
|
||||
if (Math.Abs(rechargeSpeed - maxRechargeSpeed * targetRatio) > 0.05f)
|
||||
{
|
||||
@@ -267,9 +322,10 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
if (character.IsOnPlayerTeam)
|
||||
{
|
||||
character.Speak(TextManager.GetWithVariables("DialogChargeBatteries", new string[2] { "[itemname]", "[rate]" },
|
||||
new string[2] { item.Name, ((int)(rechargeSpeed / maxRechargeSpeed * 100.0f)).ToString() },
|
||||
new bool[2] { true, false }), null, 1.0f, "chargebattery", 10.0f);
|
||||
character.Speak(TextManager.GetWithVariables("DialogChargeBatteries",
|
||||
("[itemname]", item.Name, FormatCapitals.Yes),
|
||||
("[rate]", ((int)(rechargeSpeed / maxRechargeSpeed * 100.0f)).ToString(), FormatCapitals.No)).Value,
|
||||
null, 1.0f, "chargebattery".ToIdentifier(), 10.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -289,9 +345,10 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
if (character.IsOnPlayerTeam)
|
||||
{
|
||||
character.Speak(TextManager.GetWithVariables("DialogStopChargingBatteries", new string[2] { "[itemname]", "[rate]" },
|
||||
new string[2] { item.Name, ((int)(rechargeSpeed / maxRechargeSpeed * 100.0f)).ToString() },
|
||||
new bool[2] { true, false }), null, 1.0f, "chargebattery", 10.0f);
|
||||
character.Speak(TextManager.GetWithVariables("DialogStopChargingBatteries",
|
||||
("[itemname]", item.Name, FormatCapitals.Yes),
|
||||
("[rate]", ((int)(rechargeSpeed / maxRechargeSpeed * 100.0f)).ToString(), FormatCapitals.No)).Value,
|
||||
null, 1.0f, "chargebattery".ToIdentifier(), 10.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user