160 lines
5.2 KiB
C#
160 lines
5.2 KiB
C#
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Xml.Linq;
|
|
using Barotrauma.Networking;
|
|
using Lidgren.Network;
|
|
|
|
namespace Barotrauma.Items.Components
|
|
{
|
|
partial class Engine : Powered, IServerSerializable, IClientSerializable
|
|
{
|
|
private float force;
|
|
|
|
private float targetForce;
|
|
|
|
private float maxForce;
|
|
|
|
private Attack propellerDamage;
|
|
|
|
private float damageTimer;
|
|
|
|
private bool hasPower;
|
|
|
|
private float prevVoltage;
|
|
|
|
[Editable(0.0f, 10000000.0f, ToolTip = "The amount of force exerted on the submarine when the engine is operating at full power."),
|
|
Serialize(2000.0f, true)]
|
|
public float MaxForce
|
|
{
|
|
get { return maxForce; }
|
|
set
|
|
{
|
|
maxForce = Math.Max(0.0f, value);
|
|
}
|
|
}
|
|
|
|
[Editable, Serialize("0.0,0.0", true)]
|
|
public Vector2 PropellerPos
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public float Force
|
|
{
|
|
get { return force;}
|
|
set { force = MathHelper.Clamp(value, -100.0f, 100.0f); }
|
|
}
|
|
|
|
public float CurrentVolume
|
|
{
|
|
get { return Math.Abs((force / 100.0f) * (minVoltage <= 0.0f ? 1.0f : Math.Min(prevVoltage / minVoltage, 1.0f))); }
|
|
}
|
|
|
|
public Engine(Item item, XElement element)
|
|
: base(item, element)
|
|
{
|
|
IsActive = true;
|
|
|
|
foreach (XElement subElement in element.Elements())
|
|
{
|
|
switch (subElement.Name.ToString().ToLowerInvariant())
|
|
{
|
|
case "propellerdamage":
|
|
propellerDamage = new Attack(subElement, item.Name + ", Engine");
|
|
break;
|
|
}
|
|
}
|
|
|
|
InitProjSpecific(element);
|
|
}
|
|
|
|
partial void InitProjSpecific(XElement element);
|
|
|
|
public override void Update(float deltaTime, Camera cam)
|
|
{
|
|
UpdateOnActiveEffects(deltaTime);
|
|
|
|
UpdateAnimation(deltaTime);
|
|
|
|
currPowerConsumption = Math.Abs(targetForce) / 100.0f * powerConsumption;
|
|
//pumps consume more power when in a bad condition
|
|
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.MaxCondition);
|
|
|
|
if (powerConsumption == 0.0f) voltage = 1.0f;
|
|
|
|
prevVoltage = voltage;
|
|
hasPower = voltage > minVoltage;
|
|
|
|
Force = MathHelper.Lerp(force, (voltage < minVoltage) ? 0.0f : targetForce, 0.1f);
|
|
if (Math.Abs(Force) > 1.0f)
|
|
{
|
|
Vector2 currForce = new Vector2((force / 10.0f) * maxForce * Math.Min(voltage / minVoltage, 1.0f), 0.0f);
|
|
//less effective when in a bad condition
|
|
currForce *= MathHelper.Lerp(0.5f, 2.0f, item.Condition / item.MaxCondition);
|
|
|
|
item.Submarine.ApplyForce(currForce);
|
|
|
|
UpdatePropellerDamage(deltaTime);
|
|
|
|
if (item.CurrentHull != null)
|
|
{
|
|
item.CurrentHull.AiTarget.SoundRange = Math.Max(currForce.Length(), item.CurrentHull.AiTarget.SoundRange);
|
|
}
|
|
|
|
#if CLIENT
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
GameMain.ParticleManager.CreateParticle("bubbles", item.WorldPosition + PropellerPos,
|
|
-currForce / 5.0f + new Vector2(Rand.Range(-100.0f, 100.0f), Rand.Range(-50f, 50f)),
|
|
0.0f, item.CurrentHull);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
voltage = 0.0f;
|
|
}
|
|
|
|
private void UpdatePropellerDamage(float deltaTime)
|
|
{
|
|
damageTimer += deltaTime;
|
|
if (damageTimer < 0.5f) return;
|
|
damageTimer = 0.1f;
|
|
|
|
if (propellerDamage == null) return;
|
|
Vector2 propellerWorldPos = item.WorldPosition + PropellerPos;
|
|
foreach (Character character in Character.CharacterList)
|
|
{
|
|
if (character.Submarine != null || !character.Enabled || character.Removed) continue;
|
|
|
|
float dist = Vector2.DistanceSquared(character.WorldPosition, propellerWorldPos);
|
|
if (dist > propellerDamage.DamageRange * propellerDamage.DamageRange) continue;
|
|
|
|
character.LastDamageSource = item;
|
|
propellerDamage.DoDamage(null, character, propellerWorldPos, 1.0f, true);
|
|
}
|
|
}
|
|
|
|
partial void UpdateAnimation(float deltaTime);
|
|
|
|
public override void UpdateBroken(float deltaTime, Camera cam)
|
|
{
|
|
force = MathHelper.Lerp(force, 0.0f, 0.1f);
|
|
}
|
|
|
|
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
|
|
{
|
|
base.ReceiveSignal(stepsTaken, signal, connection, source, sender, power, signalStrength);
|
|
|
|
if (connection.Name == "set_force")
|
|
{
|
|
if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float tempForce))
|
|
{
|
|
targetForce = MathHelper.Clamp(tempForce, -100.0f, 100.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|