2f107db...5202af9
This commit is contained in:
@@ -167,6 +167,8 @@ namespace Barotrauma.Items.Components
|
||||
DockingTarget = null;
|
||||
return;
|
||||
}
|
||||
|
||||
target.InitializeLinks();
|
||||
|
||||
#if CLIENT
|
||||
PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||
@@ -209,15 +211,19 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
CreateJoint(false);
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Lock(bool isNetworkMessage, bool forcePosition = false)
|
||||
{
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null && !isNetworkMessage) return;
|
||||
#endif
|
||||
|
||||
if (DockingTarget == null)
|
||||
{
|
||||
@@ -249,10 +255,12 @@ namespace Barotrauma.Items.Components
|
||||
ConnectWireBetweenPorts();
|
||||
CreateJoint(true);
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -730,10 +738,12 @@ namespace Barotrauma.Items.Components
|
||||
bodies = null;
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
@@ -819,8 +829,13 @@ namespace Barotrauma.Items.Components
|
||||
gap?.Remove(); gap = null;
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
private bool initialized = false;
|
||||
private void InitializeLinks()
|
||||
{
|
||||
if (initialized) { return; }
|
||||
initialized = true;
|
||||
|
||||
float closestDist = 30.0f * 30.0f;
|
||||
foreach (Item it in Item.ItemList)
|
||||
{
|
||||
if (it.Submarine != item.Submarine) continue;
|
||||
@@ -828,10 +843,11 @@ namespace Barotrauma.Items.Components
|
||||
var doorComponent = it.GetComponent<Door>();
|
||||
if (doorComponent == null) continue;
|
||||
|
||||
if (Vector2.Distance(item.Position, doorComponent.Item.Position) < Submarine.GridSize.X)
|
||||
float distSqr = Vector2.Distance(item.Position, it.Position);
|
||||
if (distSqr < closestDist)
|
||||
{
|
||||
this.door = doorComponent;
|
||||
break;
|
||||
door = doorComponent;
|
||||
closestDist = distSqr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -852,9 +868,20 @@ namespace Barotrauma.Items.Components
|
||||
gap.Remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
InitializeLinks();
|
||||
|
||||
if (!item.linkedTo.Any()) return;
|
||||
|
||||
List<MapEntity> linked = new List<MapEntity>(item.linkedTo);
|
||||
foreach (MapEntity entity in linked)
|
||||
{
|
||||
Item linkedItem = entity as Item;
|
||||
if (linkedItem == null) continue;
|
||||
if (linkedItem == null) { continue; }
|
||||
|
||||
var dockingPort = linkedItem.GetComponent<DockingPort>();
|
||||
if (dockingPort != null)
|
||||
@@ -866,7 +893,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
|
||||
{
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null) return;
|
||||
#endif
|
||||
|
||||
bool wasDocked = docked;
|
||||
DockingPort prevDockingTarget = DockingTarget;
|
||||
@@ -882,6 +911,7 @@ namespace Barotrauma.Items.Components
|
||||
break;
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
if (sender != null && docked != wasDocked)
|
||||
{
|
||||
if (docked)
|
||||
@@ -895,6 +925,7 @@ namespace Barotrauma.Items.Components
|
||||
GameServer.Log(sender.LogName + " undocked " + item.Submarine.Name + " from " + prevDockingTarget.item.Submarine.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ServerWrite(Lidgren.Network.NetBuffer msg, Client c, object[] extraData = null)
|
||||
|
||||
@@ -16,35 +16,24 @@ namespace Barotrauma.Items.Components
|
||||
partial class Door : Pickable, IDrawableComponent, IServerSerializable
|
||||
{
|
||||
private Gap linkedGap;
|
||||
|
||||
private Rectangle window;
|
||||
|
||||
private bool isOpen;
|
||||
|
||||
private float openState;
|
||||
|
||||
private PhysicsBody body;
|
||||
|
||||
private Sprite doorSprite, weldedSprite, brokenSprite;
|
||||
private bool scaleBrokenSprite, fadeBrokenSprite;
|
||||
|
||||
private bool isHorizontal;
|
||||
private bool createdNewGap;
|
||||
private bool autoOrientGap;
|
||||
|
||||
private bool createdNewGap;
|
||||
private bool autoOrientGap;
|
||||
|
||||
private bool isStuck;
|
||||
|
||||
private bool? predictedState;
|
||||
private float resetPredictionTimer;
|
||||
|
||||
private Rectangle doorRect;
|
||||
|
||||
private bool isBroken;
|
||||
|
||||
//openState when the vertices of the convex hull were last calculated
|
||||
private float lastConvexHullState;
|
||||
|
||||
|
||||
public bool IsBroken
|
||||
{
|
||||
get { return isBroken; }
|
||||
@@ -63,10 +52,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public PhysicsBody Body
|
||||
{
|
||||
get { return body; }
|
||||
}
|
||||
public PhysicsBody Body { get; private set; }
|
||||
|
||||
private float stuck;
|
||||
[Serialize(0.0f, false)]
|
||||
@@ -82,10 +68,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public bool? PredictedState
|
||||
{
|
||||
get { return predictedState; }
|
||||
}
|
||||
public bool? PredictedState { get; private set; }
|
||||
|
||||
public Gap LinkedGap
|
||||
{
|
||||
@@ -98,12 +81,12 @@ namespace Barotrauma.Items.Components
|
||||
linkedGap = e as Gap;
|
||||
if (linkedGap != null)
|
||||
{
|
||||
linkedGap.PassAmbientLight = window != Rectangle.Empty;
|
||||
linkedGap.PassAmbientLight = Window != Rectangle.Empty;
|
||||
return linkedGap;
|
||||
}
|
||||
}
|
||||
Rectangle rect = item.Rect;
|
||||
if (isHorizontal)
|
||||
if (IsHorizontal)
|
||||
{
|
||||
rect.Y += 5;
|
||||
rect.Height += 10;
|
||||
@@ -114,10 +97,10 @@ namespace Barotrauma.Items.Components
|
||||
rect.Width += 10;
|
||||
}
|
||||
|
||||
linkedGap = new Gap(rect, !isHorizontal, Item.Submarine)
|
||||
linkedGap = new Gap(rect, !IsHorizontal, Item.Submarine)
|
||||
{
|
||||
Submarine = item.Submarine,
|
||||
PassAmbientLight = window != Rectangle.Empty,
|
||||
PassAmbientLight = Window != Rectangle.Empty,
|
||||
Open = openState
|
||||
};
|
||||
item.linkedTo.Add(linkedGap);
|
||||
@@ -126,18 +109,11 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsHorizontal
|
||||
{
|
||||
get { return isHorizontal; }
|
||||
}
|
||||
|
||||
public bool IsHorizontal { get; private set; }
|
||||
|
||||
[Serialize("0.0,0.0,0.0,0.0", false)]
|
||||
public Rectangle Window
|
||||
{
|
||||
get { return window; }
|
||||
set { window = value; }
|
||||
}
|
||||
|
||||
public Rectangle Window { get; set; }
|
||||
|
||||
[Editable, Serialize(false, true)]
|
||||
public bool IsOpen
|
||||
{
|
||||
@@ -156,7 +132,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
openState = MathHelper.Clamp(value, 0.0f, 1.0f);
|
||||
#if CLIENT
|
||||
float size = isHorizontal ? item.Rect.Width : item.Rect.Height;
|
||||
float size = IsHorizontal ? item.Rect.Width : item.Rect.Height;
|
||||
if (Math.Abs(lastConvexHullState - openState) * size < 5.0f) { return; }
|
||||
UpdateConvexHulls();
|
||||
lastConvexHullState = openState;
|
||||
@@ -174,7 +150,7 @@ namespace Barotrauma.Items.Components
|
||||
public Door(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
isHorizontal = element.GetAttributeBool("horizontal", false);
|
||||
IsHorizontal = element.GetAttributeBool("horizontal", false);
|
||||
canBePicked = element.GetAttributeBool("canbepicked", false);
|
||||
autoOrientGap = element.GetAttributeBool("autoorientgap", false);
|
||||
|
||||
@@ -203,7 +179,7 @@ namespace Barotrauma.Items.Components
|
||||
(int)(doorSprite.size.X * item.Scale),
|
||||
(int)(doorSprite.size.Y * item.Scale));
|
||||
|
||||
body = new PhysicsBody(
|
||||
Body = new PhysicsBody(
|
||||
ConvertUnits.ToSimUnits(Math.Max(doorRect.Width, 1)),
|
||||
ConvertUnits.ToSimUnits(Math.Max(doorRect.Height, 1)),
|
||||
0.0f,
|
||||
@@ -214,7 +190,7 @@ namespace Barotrauma.Items.Components
|
||||
BodyType = BodyType.Static,
|
||||
Friction = 0.5f
|
||||
};
|
||||
body.SetTransform(
|
||||
Body.SetTransform(
|
||||
ConvertUnits.ToSimUnits(new Vector2(doorRect.Center.X, doorRect.Y - doorRect.Height / 2)),
|
||||
0.0f);
|
||||
|
||||
@@ -225,7 +201,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
base.Move(amount);
|
||||
|
||||
body?.SetTransform(body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
Body?.SetTransform(Body.SimPosition + ConvertUnits.ToSimUnits(amount), 0.0f);
|
||||
|
||||
#if CLIENT
|
||||
UpdateConvexHulls();
|
||||
@@ -249,7 +225,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (item.Condition <= 0.0f) return true; //repairs
|
||||
|
||||
SetState(predictedState == null ? !isOpen : !predictedState.Value, false, true); //crowbar function
|
||||
SetState(PredictedState == null ? !isOpen : !PredictedState.Value, false, true); //crowbar function
|
||||
#if CLIENT
|
||||
PlaySound(ActionType.OnPicked, item.WorldPosition, picker);
|
||||
#endif
|
||||
@@ -267,7 +243,7 @@ namespace Barotrauma.Items.Components
|
||||
if (isBroken)
|
||||
{
|
||||
//the door has to be restored to 50% health before collision detection on the body is re-enabled
|
||||
if (item.Condition > 50.0f)
|
||||
if (item.Condition > item.Prefab.Health / 2.0f)
|
||||
{
|
||||
IsBroken = false;
|
||||
}
|
||||
@@ -277,20 +253,20 @@ namespace Barotrauma.Items.Components
|
||||
bool isClosing = false;
|
||||
if (!isStuck)
|
||||
{
|
||||
if (predictedState == null)
|
||||
if (PredictedState == null)
|
||||
{
|
||||
OpenState += deltaTime * (isOpen ? 2.0f : -2.0f);
|
||||
isClosing = openState > 0.0f && openState < 1.0f && !isOpen;
|
||||
}
|
||||
else
|
||||
{
|
||||
OpenState += deltaTime * ((bool)predictedState ? 2.0f : -2.0f);
|
||||
isClosing = openState > 0.0f && openState < 1.0f && !(bool)predictedState;
|
||||
OpenState += deltaTime * ((bool)PredictedState ? 2.0f : -2.0f);
|
||||
isClosing = openState > 0.0f && openState < 1.0f && !(bool)PredictedState;
|
||||
|
||||
resetPredictionTimer -= deltaTime;
|
||||
if (resetPredictionTimer <= 0.0f)
|
||||
{
|
||||
predictedState = null;
|
||||
PredictedState = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +279,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
body.Enabled = Impassable || openState < 1.0f;
|
||||
Body.Enabled = Impassable || openState < 1.0f;
|
||||
}
|
||||
|
||||
//don't use the predicted state here, because it might set
|
||||
@@ -320,7 +296,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (!Impassable)
|
||||
{
|
||||
body.FarseerBody.IsSensor = false;
|
||||
Body.FarseerBody.IsSensor = false;
|
||||
}
|
||||
#if CLIENT
|
||||
UpdateConvexHulls();
|
||||
@@ -334,7 +310,7 @@ namespace Barotrauma.Items.Components
|
||||
//because otherwise repairtool raycasts won't hit it
|
||||
if (!Impassable)
|
||||
{
|
||||
body.FarseerBody.IsSensor = true;
|
||||
Body.FarseerBody.IsSensor = true;
|
||||
}
|
||||
linkedGap.Open = 1.0f;
|
||||
IsOpen = false;
|
||||
@@ -354,7 +330,7 @@ namespace Barotrauma.Items.Components
|
||||
Vector2[] corners = GetConvexHullCorners(Rectangle.Empty);
|
||||
|
||||
convexHull = new ConvexHull(corners, Color.Black, item);
|
||||
if (window != Rectangle.Empty) convexHull2 = new ConvexHull(corners, Color.Black, item);
|
||||
if (Window != Rectangle.Empty) convexHull2 = new ConvexHull(corners, Color.Black, item);
|
||||
|
||||
UpdateConvexHulls();
|
||||
#endif
|
||||
@@ -364,10 +340,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
|
||||
if (body != null)
|
||||
if (Body != null)
|
||||
{
|
||||
body.Remove();
|
||||
body = null;
|
||||
Body.Remove();
|
||||
Body = null;
|
||||
}
|
||||
|
||||
//no need to remove the gap if we're unloading the whole submarine
|
||||
@@ -399,7 +375,7 @@ namespace Barotrauma.Items.Components
|
||||
//push characters out of the doorway when the door is closing/opening
|
||||
Vector2 simPos = ConvertUnits.ToSimUnits(new Vector2(item.Rect.X, item.Rect.Y));
|
||||
|
||||
Vector2 currSize = isHorizontal ?
|
||||
Vector2 currSize = IsHorizontal ?
|
||||
new Vector2(item.Rect.Width * (1.0f - openState), doorSprite.size.Y * item.Scale) :
|
||||
new Vector2(doorSprite.size.X * item.Scale, item.Rect.Height * (1.0f - openState));
|
||||
|
||||
@@ -417,7 +393,7 @@ namespace Barotrauma.Items.Components
|
||||
" Remoteplayer: " + c.IsRemotePlayer);
|
||||
continue;
|
||||
}
|
||||
int dir = isHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
|
||||
int dir = IsHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
|
||||
|
||||
List<PhysicsBody> bodies = c.AnimController.Limbs.Select(l => l.body).ToList();
|
||||
bodies.Add(c.AnimController.Collider);
|
||||
@@ -435,7 +411,7 @@ namespace Barotrauma.Items.Components
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isHorizontal)
|
||||
if (IsHorizontal)
|
||||
{
|
||||
if (body.SimPosition.X < simPos.X || body.SimPosition.X > simPos.X + simSize.X) continue;
|
||||
diff = body.SimPosition.Y - item.SimPosition.Y;
|
||||
@@ -452,7 +428,7 @@ namespace Barotrauma.Items.Components
|
||||
SoundPlayer.PlayDamageSound("LimbBlunt", 1.0f, body);
|
||||
#endif
|
||||
|
||||
if (isHorizontal)
|
||||
if (IsHorizontal)
|
||||
{
|
||||
body.SetTransform(new Vector2(body.SimPosition.X, item.SimPosition.Y + dir * simSize.Y * 2.0f), body.Rotation);
|
||||
body.ApplyLinearImpulse(new Vector2(isOpen ? 0.0f : 1.0f, dir * 2.0f));
|
||||
@@ -464,7 +440,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (isHorizontal)
|
||||
if (IsHorizontal)
|
||||
{
|
||||
if (Math.Abs(body.SimPosition.Y - item.SimPosition.Y) > simSize.Y * 0.5f) continue;
|
||||
|
||||
@@ -486,7 +462,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (isStuck) return;
|
||||
|
||||
bool wasOpen = predictedState == null ? isOpen : predictedState.Value;
|
||||
bool wasOpen = PredictedState == null ? isOpen : PredictedState.Value;
|
||||
|
||||
if (connection.Name == "toggle")
|
||||
{
|
||||
@@ -497,66 +473,19 @@ namespace Barotrauma.Items.Components
|
||||
SetState(signal != "0", false, true);
|
||||
}
|
||||
|
||||
bool newState = predictedState == null ? isOpen : predictedState.Value;
|
||||
if (sender != null && wasOpen != newState)
|
||||
#if SERVER
|
||||
if (sender != null && wasOpen != isOpen)
|
||||
{
|
||||
GameServer.Log(sender.LogName + (newState ? " opened " : " closed ") + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
GameServer.Log(sender.LogName + (isOpen ? " opened " : " closed ") + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage = false)
|
||||
{
|
||||
if (isStuck ||
|
||||
(predictedState == null && isOpen == open) ||
|
||||
(predictedState != null && isOpen == predictedState.Value && isOpen == open)) return;
|
||||
|
||||
if (GameMain.Client != null && !isNetworkMessage)
|
||||
{
|
||||
bool stateChanged = open != predictedState;
|
||||
|
||||
//clients can "predict" that the door opens/closes when a signal is received
|
||||
//the prediction will be reset after 1 second, setting the door to a state
|
||||
//sent by the server, or reverting it back to its old state if no msg from server was received
|
||||
predictedState = open;
|
||||
resetPredictionTimer = CorrectionDelay;
|
||||
#if CLIENT
|
||||
if (stateChanged) PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
isOpen = open;
|
||||
#if CLIENT
|
||||
if (!isNetworkMessage || open != predictedState) PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||
#endif
|
||||
}
|
||||
|
||||
//opening a partially stuck door makes it less stuck
|
||||
if (isOpen) stuck = MathHelper.Clamp(stuck - 30.0f, 0.0f, 100.0f);
|
||||
|
||||
if (sendNetworkMessage)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ServerWrite(Lidgren.Network.NetBuffer msg, Client c, object[] extraData = null)
|
||||
public void TrySetState(bool open, bool isNetworkMessage, bool sendNetworkMessage = false)
|
||||
{
|
||||
base.ServerWrite(msg, c, extraData);
|
||||
|
||||
msg.Write(isOpen);
|
||||
msg.WriteRangedSingle(stuck, 0.0f, 100.0f, 8);
|
||||
SetState(open, isNetworkMessage, sendNetworkMessage);
|
||||
}
|
||||
|
||||
public override void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime)
|
||||
{
|
||||
base.ClientRead(type, msg, sendingTime);
|
||||
|
||||
SetState(msg.ReadBoolean(), true);
|
||||
Stuck = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
|
||||
predictedState = null;
|
||||
}
|
||||
partial void SetState(bool open, bool isNetworkMessage, bool sendNetworkMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +288,9 @@ namespace Barotrauma.Items.Components
|
||||
item.body.Enabled = true;
|
||||
IsActive = true;
|
||||
|
||||
#if SERVER
|
||||
if (!alreadySelected) GameServer.Log(character.LogName + " equipped " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,8 +299,9 @@ namespace Barotrauma.Items.Components
|
||||
if (picker == null) return;
|
||||
|
||||
picker.DeselectItem(item);
|
||||
|
||||
#if SERVER
|
||||
GameServer.Log(character.LogName + " unequipped " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
#endif
|
||||
|
||||
item.body.Enabled = false;
|
||||
IsActive = false;
|
||||
@@ -354,6 +357,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
DeattachFromWall();
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null && attachable)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
@@ -362,6 +366,7 @@ namespace Barotrauma.Items.Components
|
||||
GameServer.Log(picker.LogName + " detached " + item.Name + " from a wall", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -426,11 +431,13 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (!character.IsKeyDown(InputType.Aim)) return false;
|
||||
if (!CanBeAttached()) return false;
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
GameServer.Log(character.LogName + " attached " + item.Name + " to a wall", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
#endif
|
||||
item.Drop();
|
||||
}
|
||||
|
||||
@@ -471,7 +478,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, picker);
|
||||
|
||||
if (item.body.Dir != picker.AnimController.Dir) Flip(item);
|
||||
if (item.body.Dir != picker.AnimController.Dir) Flip();
|
||||
|
||||
item.Submarine = picker.Submarine;
|
||||
|
||||
@@ -507,7 +514,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
protected void Flip(Item item)
|
||||
public void Flip()
|
||||
{
|
||||
handlePos[0].X = -handlePos[0].X;
|
||||
handlePos[1].X = -handlePos[1].X;
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
deattachTimer = Math.Max(0.0f, value);
|
||||
//clients don't deattach the item until the server says so (handled in ClientRead)
|
||||
if (GameMain.Client == null && deattachTimer >= DeattachDuration)
|
||||
if ((GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient) && deattachTimer >= DeattachDuration)
|
||||
{
|
||||
holdable.DeattachFromWall();
|
||||
}
|
||||
@@ -80,6 +80,7 @@ namespace Barotrauma.Items.Components
|
||||
trigger.FarseerBody.IsSensor = true;
|
||||
trigger.FarseerBody.IsStatic = true;
|
||||
trigger.FarseerBody.CollisionCategories = Physics.CollisionWall;
|
||||
trigger.FarseerBody.CollidesWith = Physics.CollisionNone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, picker);
|
||||
|
||||
if (item.body.Dir != picker.AnimController.Dir) Flip(item);
|
||||
if (item.body.Dir != picker.AnimController.Dir) Flip();
|
||||
|
||||
AnimController ac = picker.AnimController;
|
||||
|
||||
@@ -294,8 +294,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.Client != null) return true;
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) return true;
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null && targetCharacter != null) //TODO: Log structure hits
|
||||
{
|
||||
|
||||
@@ -308,13 +309,14 @@ namespace Barotrauma.Items.Components
|
||||
});
|
||||
|
||||
string logStr = picker?.LogName + " used " + item.Name;
|
||||
if (item.ContainedItems != null && item.ContainedItems.Length > 0)
|
||||
if (item.ContainedItems != null && item.ContainedItems.Any())
|
||||
{
|
||||
logStr += "(" + string.Join(", ", item.ContainedItems.Select(i => i?.Name)) + ")";
|
||||
logStr += " (" + string.Join(", ", item.ContainedItems.Select(i => i?.Name)) + ")";
|
||||
}
|
||||
logStr += " on " + targetCharacter.LogName + ".";
|
||||
Networking.GameServer.Log(logStr, Networking.ServerLog.MessageType.Attack);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (targetCharacter != null) //TODO: Allow OnUse to happen on structures too maybe??
|
||||
{
|
||||
|
||||
@@ -66,7 +66,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (picker.PickingItem == null && PickingTime <= float.MaxValue)
|
||||
{
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
CoroutineManager.StartCoroutine(WaitForPick(picker, PickingTime));
|
||||
}
|
||||
return false;
|
||||
@@ -143,7 +145,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
StopPicking(picker);
|
||||
|
||||
if (!picker.IsRemotePlayer || GameMain.Server != null) OnPicked(picker);
|
||||
bool isNotRemote = true;
|
||||
#if CLIENT
|
||||
isNotRemote = !picker.IsRemotePlayer;
|
||||
#endif
|
||||
if (isNotRemote) OnPicked(picker);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
Projectile projectile = null;
|
||||
Item[] containedItems = item.ContainedItems;
|
||||
var containedItems = item.ContainedItems;
|
||||
if (containedItems == null) return true;
|
||||
|
||||
foreach (Item item in containedItems)
|
||||
@@ -105,18 +105,29 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
foreach (Item item in containedItems)
|
||||
{
|
||||
Item[] containedSubItems = item.ContainedItems;
|
||||
foreach (Item subItem in containedSubItems)
|
||||
projectile = item.GetComponent<Projectile>();
|
||||
if (projectile != null) break;
|
||||
}
|
||||
//projectile not found, see if one of the contained items contains projectiles
|
||||
if (projectile == null)
|
||||
{
|
||||
foreach (Item item in containedItems)
|
||||
{
|
||||
projectile = subItem.GetComponent<Projectile>();
|
||||
|
||||
//apply OnUse statuseffects to the container in case it has to react to it somehow
|
||||
//(play a sound, spawn more projectiles, reduce condition...)
|
||||
subItem.GetComponent<ItemContainer>()?.Item.ApplyStatusEffects(ActionType.OnUse, deltaTime);
|
||||
if (projectile != null) break;
|
||||
var containedSubItems = item.ContainedItems;
|
||||
if (containedSubItems == null) { continue; }
|
||||
foreach (Item subItem in containedSubItems)
|
||||
{
|
||||
projectile = subItem.GetComponent<Projectile>();
|
||||
|
||||
//apply OnUse statuseffects to the container in case it has to react to it somehow
|
||||
//(play a sound, spawn more projectiles, reduce condition...)
|
||||
subItem.GetComponent<ItemContainer>()?.Item.ApplyStatusEffects(ActionType.OnUse, deltaTime);
|
||||
if (projectile != null) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (projectile == null) return true;
|
||||
|
||||
float spread = MathHelper.ToRadians(MathHelper.Lerp(Spread, UnskilledSpread, degreeOfFailure));
|
||||
|
||||
@@ -14,52 +14,35 @@ namespace Barotrauma.Items.Components
|
||||
partial class RepairTool : ItemComponent
|
||||
{
|
||||
private readonly List<string> fixableEntities;
|
||||
|
||||
private float range;
|
||||
|
||||
private Vector2 pickedPosition;
|
||||
|
||||
private Vector2 barrelPos;
|
||||
|
||||
private float activeTimer;
|
||||
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float Range
|
||||
{
|
||||
get { return range; }
|
||||
set { range = value; }
|
||||
}
|
||||
public float Range { get; set; }
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float StructureFixAmount
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[Serialize(0.0f, false)]
|
||||
public float LimbFixAmount
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
[Serialize(0.0f, false)]
|
||||
public float ExtinguishAmount
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize("0.0,0.0", false)]
|
||||
public Vector2 BarrelPos
|
||||
{
|
||||
get { return barrelPos; }
|
||||
set { barrelPos = value; }
|
||||
}
|
||||
public Vector2 BarrelPos { get; set; }
|
||||
|
||||
[Serialize(false, false)]
|
||||
public bool RepairThroughWalls { get; set; }
|
||||
|
||||
public Vector2 TransformedBarrelPos
|
||||
{
|
||||
get
|
||||
{
|
||||
Matrix bodyTransform = Matrix.CreateRotationZ(item.body.Rotation);
|
||||
Vector2 flippedPos = barrelPos;
|
||||
Vector2 flippedPos = BarrelPos;
|
||||
if (item.body.Dir < 0.0f) flippedPos.X = -flippedPos.X;
|
||||
return (Vector2.Transform(flippedPos, bodyTransform));
|
||||
}
|
||||
@@ -70,6 +53,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
this.item = item;
|
||||
|
||||
if (element.Attribute("limbfixamount") != null)
|
||||
{
|
||||
DebugConsole.ThrowError("Error in item \"" + item.Name + "\" - RepairTool damage should be configured using a StatusEffect with Afflictions, not the limbfixamount attribute.");
|
||||
}
|
||||
|
||||
fixableEntities = new List<string>();
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
@@ -116,7 +104,7 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 targetPosition = item.WorldPosition;
|
||||
targetPosition += new Vector2(
|
||||
(float)Math.Cos(item.body.Rotation),
|
||||
(float)Math.Sin(item.body.Rotation)) * range * item.body.Dir;
|
||||
(float)Math.Sin(item.body.Rotation)) * Range * item.body.Dir;
|
||||
|
||||
List<Body> ignoredBodies = new List<Body>();
|
||||
foreach (Limb limb in character.AnimController.Limbs)
|
||||
@@ -154,9 +142,20 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void Repair(Vector2 rayStart, Vector2 rayEnd, float deltaTime, Character user, float degreeOfSuccess, List<Body> ignoredBodies)
|
||||
{
|
||||
Body targetBody = Submarine.PickBody(rayStart, rayEnd, ignoredBodies,
|
||||
Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionRepair, false);
|
||||
|
||||
var collisionCategories = Physics.CollisionWall | Physics.CollisionCharacter | Physics.CollisionItem | Physics.CollisionLevel | Physics.CollisionRepair;
|
||||
if (RepairThroughWalls)
|
||||
{
|
||||
var bodies = Submarine.PickBodies(rayStart, rayEnd, ignoredBodies, collisionCategories, ignoreSensors: false);
|
||||
foreach (Body body in bodies)
|
||||
{
|
||||
FixBody(user, deltaTime, degreeOfSuccess, body);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FixBody(user, deltaTime, degreeOfSuccess, Submarine.PickBody(rayStart, rayEnd, ignoredBodies, collisionCategories, ignoreSensors: false));
|
||||
}
|
||||
|
||||
if (ExtinguishAmount > 0.0f && item.CurrentHull != null)
|
||||
{
|
||||
List<FireSource> fireSourcesInRange = new List<FireSource>();
|
||||
@@ -164,7 +163,7 @@ namespace Barotrauma.Items.Components
|
||||
for (float x = 0.0f; x <= Submarine.LastPickedFraction; x += 0.1f)
|
||||
{
|
||||
Vector2 displayPos = ConvertUnits.ToDisplayUnits(rayStart + (rayEnd - rayStart) * x);
|
||||
if (item.CurrentHull.Submarine != null) { displayPos += item.CurrentHull.Submarine.Position; }
|
||||
if (item.CurrentHull.Submarine != null) { displayPos += item.CurrentHull.Submarine.Position; }
|
||||
|
||||
Hull hull = Hull.FindHull(displayPos, item.CurrentHull);
|
||||
if (hull == null) continue;
|
||||
@@ -182,11 +181,14 @@ namespace Barotrauma.Items.Components
|
||||
fs.Extinguish(deltaTime, ExtinguishAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetBody == null || targetBody.UserData == null) return;
|
||||
private void FixBody(Character user, float deltaTime, float degreeOfSuccess, Body targetBody)
|
||||
{
|
||||
if (targetBody?.UserData == null) { return; }
|
||||
|
||||
pickedPosition = Submarine.LastPickedPosition;
|
||||
|
||||
|
||||
if (targetBody.UserData is Structure targetStructure)
|
||||
{
|
||||
if (!fixableEntities.Contains("structure") && !fixableEntities.Contains(targetStructure.Prefab.Identifier)) return;
|
||||
@@ -214,20 +216,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else if (targetBody.UserData is Character targetCharacter)
|
||||
{
|
||||
Vector2 hitPos = ConvertUnits.ToDisplayUnits(pickedPosition);
|
||||
if (targetCharacter.Submarine != null) hitPos += targetCharacter.Submarine.Position;
|
||||
|
||||
targetCharacter.LastDamageSource = item;
|
||||
targetCharacter.AddDamage(hitPos,
|
||||
new List<Affliction>() { AfflictionPrefab.Burn.Instantiate(-LimbFixAmount * degreeOfSuccess, user) }, 0.0f, false, 0.0f, user);
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, new List<ISerializableEntity>() { targetCharacter });
|
||||
FixCharacterProjSpecific(user, deltaTime, targetCharacter);
|
||||
}
|
||||
else if (targetBody.UserData is Limb targetLimb)
|
||||
{
|
||||
targetLimb.character.LastDamageSource = item;
|
||||
targetLimb.character.DamageLimb(targetLimb.WorldPosition, targetLimb,
|
||||
new List<Affliction>() { AfflictionPrefab.Burn.Instantiate(-LimbFixAmount * degreeOfSuccess, user) }, 0.0f, false, 0.0f, user);
|
||||
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, new List<ISerializableEntity>() { targetLimb.character, targetLimb });
|
||||
FixCharacterProjSpecific(user, deltaTime, targetLimb.character);
|
||||
}
|
||||
else if (targetBody.UserData is Item targetItem)
|
||||
@@ -236,7 +232,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
float prevCondition = targetItem.Condition;
|
||||
|
||||
ApplyStatusEffectsOnTarget(deltaTime, ActionType.OnUse, targetItem.AllPropertyObjects);
|
||||
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, targetItem.AllPropertyObjects);
|
||||
|
||||
var levelResource = targetItem.GetComponent<LevelResource>();
|
||||
if (levelResource != null && levelResource.IsActive &&
|
||||
@@ -254,6 +250,11 @@ namespace Barotrauma.Items.Components
|
||||
FixItemProjSpecific(user, deltaTime, targetItem, prevCondition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
partial void FixStructureProjSpecific(Character user, float deltaTime, Structure targetStructure, int sectionIndex);
|
||||
partial void FixCharacterProjSpecific(Character user, float deltaTime, Character targetCharacter);
|
||||
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem, float prevCondition);
|
||||
|
||||
partial void FixStructureProjSpecific(Character user, float deltaTime, Structure targetStructure, int sectionIndex);
|
||||
partial void FixCharacterProjSpecific(Character user, float deltaTime, Character targetCharacter);
|
||||
@@ -267,7 +268,7 @@ namespace Barotrauma.Items.Components
|
||||
float dist = Vector2.Distance(leak.WorldPosition, item.WorldPosition);
|
||||
|
||||
//too far away -> consider this done and hope the AI is smart enough to move closer
|
||||
if (dist > range * 5.0f) return true;
|
||||
if (dist > Range * 5.0f) return true;
|
||||
|
||||
Vector2 gapDiff = leak.WorldPosition - item.WorldPosition;
|
||||
if (!character.AnimController.InWater && character.AnimController is HumanoidAnimController &&
|
||||
@@ -277,13 +278,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
//steer closer if almost in range
|
||||
if (dist > range)
|
||||
if (dist > Range)
|
||||
{
|
||||
Vector2 standPos = leak.IsHorizontal ?
|
||||
new Vector2(Math.Sign(-gapDiff.X), 0.0f)
|
||||
: new Vector2(0.0f, Math.Sign(-gapDiff.Y) * 0.5f);
|
||||
|
||||
standPos = leak.WorldPosition + standPos * range;
|
||||
standPos = leak.WorldPosition + standPos * Range;
|
||||
|
||||
character.AIController.SteeringManager.SteeringManual(deltaTime, (standPos - character.WorldPosition) / 1000.0f);
|
||||
}
|
||||
@@ -315,15 +316,14 @@ namespace Barotrauma.Items.Components
|
||||
return leakFixed;
|
||||
}
|
||||
|
||||
private void ApplyStatusEffectsOnTarget(float deltaTime, ActionType actionType, List<ISerializableEntity> targets)
|
||||
private void ApplyStatusEffectsOnTarget(Character user, float deltaTime, ActionType actionType, IEnumerable<ISerializableEntity> targets)
|
||||
{
|
||||
if (statusEffectLists == null) return;
|
||||
|
||||
List<StatusEffect> statusEffects;
|
||||
if (!statusEffectLists.TryGetValue(actionType, out statusEffects)) return;
|
||||
if (statusEffectLists == null) { return; }
|
||||
if (!statusEffectLists.TryGetValue(actionType, out List<StatusEffect> statusEffects)) { return; }
|
||||
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
{
|
||||
effect.SetUser(user);
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.UseTarget))
|
||||
{
|
||||
effect.Apply(actionType, deltaTime, item, targets);
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, picker);
|
||||
|
||||
if (item.body.Dir != picker.AnimController.Dir) Flip(item);
|
||||
if (item.body.Dir != picker.AnimController.Dir) Flip();
|
||||
|
||||
AnimController ac = picker.AnimController;
|
||||
|
||||
@@ -101,7 +101,9 @@ namespace Barotrauma.Items.Components
|
||||
//throw upwards if cursor is at the position of the character
|
||||
if (!MathUtils.IsValid(throwVector)) throwVector = Vector2.UnitY;
|
||||
|
||||
#if SERVER
|
||||
GameServer.Log(picker.LogName + " threw " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
#endif
|
||||
|
||||
item.Drop();
|
||||
item.body.ApplyLinearImpulse(throwVector * throwForce * item.body.Mass * 3.0f);
|
||||
|
||||
@@ -14,6 +14,11 @@ namespace Barotrauma.Items.Components
|
||||
interface IDrawableComponent
|
||||
{
|
||||
#if CLIENT
|
||||
/// <summary>
|
||||
/// The extents of the sprites or other graphics this component needs to draw. Used to determine which items are visible on the screen.
|
||||
/// </summary>
|
||||
Vector2 DrawSize { get; }
|
||||
|
||||
void Draw(SpriteBatch spriteBatch, bool editing);
|
||||
#endif
|
||||
}
|
||||
@@ -98,12 +103,11 @@ namespace Barotrauma.Items.Components
|
||||
drawable = value;
|
||||
if (drawable)
|
||||
{
|
||||
if (!item.drawableComponents.Contains((IDrawableComponent)this))
|
||||
item.drawableComponents.Add((IDrawableComponent)this);
|
||||
item.EnableDrawableComponent((IDrawableComponent)this);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.drawableComponents.Remove((IDrawableComponent)this);
|
||||
item.DisableDrawableComponent((IDrawableComponent)this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,7 +315,7 @@ namespace Barotrauma.Items.Components
|
||||
if (ic == null) break;
|
||||
|
||||
ic.Parent = this;
|
||||
item.components.Add(ic);
|
||||
item.AddComponent(ic);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -531,6 +535,7 @@ namespace Barotrauma.Items.Components
|
||||
GameAnalyticsManager.AddErrorEventOnce("ItemComponent.DegreeOfSuccess:CharacterNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
return 0.0f;
|
||||
}
|
||||
float average = skillSuccessSum / requiredSkills.Count;
|
||||
|
||||
float skillSuccessSum = 0.0f;
|
||||
for (int i = 0; i < requiredSkills.Count; i++)
|
||||
@@ -623,7 +628,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (XAttribute attribute in componentElement.Attributes())
|
||||
{
|
||||
if (!properties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out SerializableProperty property)) continue;
|
||||
property.TrySetValue(attribute.Value);
|
||||
property.TrySetValue(this, attribute.Value);
|
||||
}
|
||||
#if CLIENT
|
||||
string msg = TextManager.Get(Msg, true);
|
||||
|
||||
@@ -141,6 +141,13 @@ namespace Barotrauma.Items.Components
|
||||
effect.Apply(ActionType.OnContaining, deltaTime, item, item.AllPropertyObjects);
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.Contained))
|
||||
effect.Apply(ActionType.OnContaining, deltaTime, item, contained.AllPropertyObjects);
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.NearbyItems) ||
|
||||
effect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
|
||||
{
|
||||
var targets = new List<ISerializableEntity>();
|
||||
effect.GetNearbyTargets(item.WorldPosition, targets);
|
||||
effect.Apply(ActionType.OnActive, deltaTime, item, targets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +169,24 @@ namespace Barotrauma.Items.Components
|
||||
return base.Select(character);
|
||||
}
|
||||
|
||||
public override bool Select(Character character)
|
||||
{
|
||||
if (item.Container != null) { return false; }
|
||||
|
||||
if (AutoInteractWithContained)
|
||||
{
|
||||
foreach (Item contained in Inventory.Items)
|
||||
{
|
||||
if (contained == null) continue;
|
||||
if (contained.TryInteract(character))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.Select(character);
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
{
|
||||
if (AutoInteractWithContained)
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
namespace Barotrauma.Items.Components
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class ItemLabel : ItemComponent, IDrawableComponent
|
||||
{
|
||||
public Vector2 DrawSize
|
||||
{
|
||||
//use the extents of the item as the draw size
|
||||
get { return Vector2.Zero; }
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0, float signalStrength = 1)
|
||||
{
|
||||
switch (connection.Name)
|
||||
|
||||
@@ -94,7 +94,7 @@ namespace Barotrauma.Items.Components
|
||||
Entity.Spawner.AddToSpawnQueue(itemPrefab, outputContainer.Inventory, condition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inputContainer.Inventory.RemoveItem(targetItem);
|
||||
Entity.Spawner.AddToRemoveQueue(targetItem);
|
||||
MoveInputQueue();
|
||||
@@ -109,7 +109,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void PutItemsToLinkedContainer()
|
||||
{
|
||||
if (GameMain.Client != null) { return; }
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
if (outputContainer.Inventory.Items.All(it => it == null)) return;
|
||||
|
||||
foreach (MapEntity linkedTo in item.linkedTo)
|
||||
@@ -153,10 +153,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
IsActive = active;
|
||||
|
||||
#if SERVER
|
||||
if (user != null)
|
||||
{
|
||||
GameServer.Log(user.LogName + (IsActive ? " activated " : " deactivated ") + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IsActive) { progressState = 0.0f; }
|
||||
|
||||
if (!IsActive) { progressState = 0.0f; }
|
||||
|
||||
@@ -174,22 +178,5 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
inputContainer.Inventory.Locked = IsActive;
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
bool active = msg.ReadBoolean();
|
||||
|
||||
item.CreateServerEvent(this);
|
||||
|
||||
if (item.CanClientAccess(c))
|
||||
{
|
||||
SetActive(active, c.Character);
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(IsActive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
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 / 100.0f);
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.Prefab.Health);
|
||||
|
||||
if (powerConsumption == 0.0f) voltage = 1.0f;
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Vector2 currForce = new Vector2((force / 100.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 / 100.0f);
|
||||
currForce *= MathHelper.Lerp(0.5f, 2.0f, item.Condition / item.Prefab.Health);
|
||||
|
||||
item.Submarine.ApplyForce(currForce);
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
string displayName = element.GetAttributeString("displayname", "");
|
||||
DisplayName = string.IsNullOrEmpty(displayName) ? TargetItem.Name : TextManager.Get(displayName);
|
||||
DisplayName = string.IsNullOrEmpty(displayName) ? TargetItem.Name : TextManager.Get($"DisplayName.{displayName}");
|
||||
|
||||
RequiredSkills = new List<Skill>();
|
||||
RequiredTime = element.GetAttributeFloat("requiredtime", 1.0f);
|
||||
@@ -212,10 +212,12 @@ namespace Barotrauma.Items.Components
|
||||
if (selectedItem == null) return;
|
||||
if (!outputContainer.Inventory.IsEmpty()) return;
|
||||
|
||||
#if SERVER
|
||||
if (user != null)
|
||||
{
|
||||
GameServer.Log(user.LogName + " started fabricating " + selectedItem.DisplayName + " in " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CLIENT
|
||||
itemList.Enabled = false;
|
||||
@@ -235,15 +237,17 @@ namespace Barotrauma.Items.Components
|
||||
outputContainer.Inventory.Locked = true;
|
||||
|
||||
currPowerConsumption = powerConsumption;
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / 100.0f);
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.Prefab.Health);
|
||||
}
|
||||
|
||||
private void CancelFabricating(Character user = null)
|
||||
{
|
||||
#if SERVER
|
||||
if (fabricatedItem != null && user != null)
|
||||
{
|
||||
GameServer.Log(user.LogName + " cancelled the fabrication of " + fabricatedItem.DisplayName + " in " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
#endif
|
||||
|
||||
IsActive = false;
|
||||
fabricatedItem = null;
|
||||
@@ -315,7 +319,12 @@ namespace Barotrauma.Items.Components
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
|
||||
}
|
||||
|
||||
if (GameMain.Client == null && user != null)
|
||||
bool isNotClient = true;
|
||||
#if CLIENT
|
||||
isNotClient = GameMain.Client == null;
|
||||
#endif
|
||||
|
||||
if (isNotClient && user != null)
|
||||
{
|
||||
foreach (Skill skill in fabricatedItem.RequiredSkills)
|
||||
{
|
||||
@@ -426,38 +435,5 @@ namespace Barotrauma.Items.Components
|
||||
item.prefab == requiredItem.ItemPrefab &&
|
||||
item.Condition / item.Prefab.Health >= requiredItem.MinCondition;
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
int itemIndex = msg.ReadRangedInteger(-1, fabricableItems.Count - 1);
|
||||
|
||||
item.CreateServerEvent(this);
|
||||
|
||||
if (!item.CanClientAccess(c)) return;
|
||||
|
||||
if (itemIndex == -1)
|
||||
{
|
||||
CancelFabricating(c.Character);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if already fabricating the selected item, return
|
||||
if (fabricatedItem != null && fabricableItems.IndexOf(fabricatedItem) == itemIndex) return;
|
||||
if (itemIndex < 0 || itemIndex >= fabricableItems.Count) return;
|
||||
#if CLIENT
|
||||
SelectItem(c.Character, fabricableItems[itemIndex]);
|
||||
#endif
|
||||
StartFabricating(fabricableItems[itemIndex], c.Character);
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
int itemIndex = fabricatedItem == null ? -1 : fabricableItems.IndexOf(fabricatedItem);
|
||||
msg.WriteRangedInteger(-1, fabricableItems.Count - 1, itemIndex);
|
||||
UInt16 userID = fabricatedItem == null || user == null ? (UInt16)0 : user.ID;
|
||||
msg.Write(userID);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
currPowerConsumption = powerConsumption;
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / 100.0f);
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.Prefab.Health);
|
||||
|
||||
hasPower = voltage > minVoltage;
|
||||
if (hasPower)
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Barotrauma.Items.Components
|
||||
CurrFlow = 0.0f;
|
||||
currPowerConsumption = powerConsumption;
|
||||
//consume more power when in a bad condition
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / 100.0f);
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.Prefab.Health);
|
||||
|
||||
if (powerConsumption <= 0.0f)
|
||||
{
|
||||
@@ -63,7 +63,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
CurrFlow = Math.Min(voltage, 1.0f) * generatedAmount * 100.0f;
|
||||
//less effective when in bad condition
|
||||
CurrFlow *= MathHelper.Lerp(0.5f, 1.0f, item.Condition / 100.0f);
|
||||
CurrFlow *= MathHelper.Lerp(0.5f, 1.0f, item.Condition / item.Prefab.Health);
|
||||
|
||||
UpdateVents(CurrFlow);
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
currPowerConsumption = powerConsumption * Math.Abs(flowPercentage / 100.0f);
|
||||
//pumps consume more power when in a bad condition
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / 100.0f);
|
||||
currPowerConsumption *= MathHelper.Lerp(2.0f, 1.0f, item.Condition / item.Prefab.Health);
|
||||
|
||||
if (voltage < minVoltage) return;
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
currFlow = flowPercentage / 100.0f * maxFlow * powerFactor;
|
||||
//less effective when in a bad condition
|
||||
currFlow *= MathHelper.Lerp(0.5f, 1.0f, item.Condition / 100.0f);
|
||||
currFlow *= MathHelper.Lerp(0.5f, 1.0f, item.Condition / item.Prefab.Health);
|
||||
|
||||
item.CurrentHull.WaterVolume += currFlow;
|
||||
if (item.CurrentHull.WaterVolume > item.CurrentHull.Volume) { item.CurrentHull.Pressure += 0.5f; }
|
||||
@@ -124,55 +124,29 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
||||
{
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null) return false;
|
||||
#endif
|
||||
|
||||
if (objective.Option.ToLowerInvariant() == "stoppumping")
|
||||
{
|
||||
#if SERVER
|
||||
if (FlowPercentage > 0.0f) item.CreateServerEvent(this);
|
||||
#endif
|
||||
FlowPercentage = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if SERVER
|
||||
if (!IsActive || FlowPercentage > -100.0f)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#endif
|
||||
IsActive = true;
|
||||
FlowPercentage = -100.0f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Client c)
|
||||
{
|
||||
float newFlowPercentage = msg.ReadRangedInteger(-10, 10) * 10.0f;
|
||||
bool newIsActive = msg.ReadBoolean();
|
||||
|
||||
if (item.CanClientAccess(c))
|
||||
{
|
||||
if (newFlowPercentage != FlowPercentage)
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + " set the pumping speed of " + item.Name + " to " + (int)(newFlowPercentage) + " %", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
if (newIsActive != IsActive)
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + (newIsActive ? " turned on " : " turned off ") + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
|
||||
FlowPercentage = newFlowPercentage;
|
||||
IsActive = newIsActive;
|
||||
}
|
||||
|
||||
//notify all clients of the changed state
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
|
||||
public void ServerWrite(Lidgren.Network.NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
//flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this
|
||||
msg.WriteRangedInteger(-10, 10, (int)(flowPercentage / 10.0f));
|
||||
msg.Write(IsActive);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,7 @@ namespace Barotrauma.Items.Components
|
||||
//(adjusts the fission rate and turbine output automatically to keep the
|
||||
//amount of power generated balanced with the load)
|
||||
private bool autoTemp;
|
||||
|
||||
private Client BlameOnBroken;
|
||||
|
||||
|
||||
//automatical adjustment to the power output when
|
||||
//turbine output and temperature are in the optimal range
|
||||
private float autoAdjustAmount;
|
||||
@@ -44,10 +42,7 @@ namespace Barotrauma.Items.Components
|
||||
private float sendUpdateTimer;
|
||||
|
||||
private float degreeOfSuccess;
|
||||
|
||||
private float? nextServerLogWriteTime;
|
||||
private float lastServerLogWriteTime;
|
||||
|
||||
|
||||
private Vector2 optimalTemperature, allowedTemperature;
|
||||
private Vector2 optimalFissionRate, allowedFissionRate;
|
||||
private Vector2 optimalTurbineOutput, allowedTurbineOutput;
|
||||
@@ -174,6 +169,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
#if SERVER
|
||||
if (GameMain.Server != null && nextServerLogWriteTime != null)
|
||||
{
|
||||
if (Timing.TotalTime >= (float)nextServerLogWriteTime)
|
||||
@@ -189,6 +185,7 @@ namespace Barotrauma.Items.Components
|
||||
lastServerLogWriteTime = (float)Timing.TotalTime;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
prevAvailableFuel = AvailableFuel;
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
@@ -260,8 +257,7 @@ namespace Barotrauma.Items.Components
|
||||
if (!connection.IsPower) continue;
|
||||
foreach (Connection recipient in connection.Recipients)
|
||||
{
|
||||
Item it = recipient.Item as Item;
|
||||
if (it == null) continue;
|
||||
if (!(recipient.Item is Item it)) continue;
|
||||
|
||||
PowerTransfer pt = it.GetComponent<PowerTransfer>();
|
||||
if (pt == null) continue;
|
||||
@@ -300,12 +296,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (unsentChanges && sendUpdateTimer <= 0.0f)
|
||||
{
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#endif
|
||||
#if CLIENT
|
||||
else if (GameMain.Client != null)
|
||||
if (GameMain.Client != null)
|
||||
{
|
||||
item.CreateClientEvent(this);
|
||||
}
|
||||
@@ -321,7 +319,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
item.SendSignal(0, "1", "meltdown_warning", null);
|
||||
//faster meltdown if the item is in a bad condition
|
||||
meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / 100.0f);
|
||||
meltDownTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.Prefab.Health);
|
||||
|
||||
if (meltDownTimer > MeltdownDelay)
|
||||
{
|
||||
@@ -338,7 +336,7 @@ namespace Barotrauma.Items.Components
|
||||
if (temperature > optimalTemperature.Y)
|
||||
{
|
||||
float prevFireTimer = fireTimer;
|
||||
fireTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / 100.0f);
|
||||
fireTimer += MathHelper.Lerp(deltaTime * 2.0f, deltaTime, item.Condition / item.Prefab.Health);
|
||||
|
||||
if (fireTimer >= FireDelay && prevFireTimer < fireDelay)
|
||||
{
|
||||
@@ -388,9 +386,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private void MeltDown()
|
||||
{
|
||||
if (item.Condition <= 0.0f || GameMain.Client != null) return;
|
||||
if (item.Condition <= 0.0f) return;
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null) return;
|
||||
#endif
|
||||
|
||||
#if SERVER
|
||||
GameServer.Log("Reactor meltdown!", ServerLog.MessageType.ItemInteraction);
|
||||
#endif
|
||||
|
||||
item.Condition = 0.0f;
|
||||
fireTimer = 0.0f;
|
||||
@@ -405,11 +408,13 @@ namespace Barotrauma.Items.Components
|
||||
containedItem.Condition = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.Server != null && GameMain.Server.ConnectedClients.Contains(BlameOnBroken))
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null && GameMain.Server.ConnectedClients.Contains(blameOnBroken))
|
||||
{
|
||||
BlameOnBroken.Karma = 0.0f;
|
||||
}
|
||||
blameOnBroken.Karma = 0.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override bool Pick(Character picker)
|
||||
@@ -419,7 +424,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
||||
{
|
||||
if (GameMain.Client != null) return false;
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return false; }
|
||||
|
||||
float degreeOfSuccess = DegreeOfSuccess(character);
|
||||
|
||||
@@ -532,49 +537,5 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
bool autoTemp = msg.ReadBoolean();
|
||||
bool shutDown = msg.ReadBoolean();
|
||||
float fissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
float turbineOutput = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
|
||||
if (!item.CanClientAccess(c)) return;
|
||||
|
||||
if (!autoTemp && AutoTemp) BlameOnBroken = c;
|
||||
if (turbineOutput < targetTurbineOutput) BlameOnBroken = c;
|
||||
if (fissionRate > targetFissionRate) BlameOnBroken = c;
|
||||
if (!this.shutDown && shutDown) BlameOnBroken = c;
|
||||
|
||||
AutoTemp = autoTemp;
|
||||
this.shutDown = shutDown;
|
||||
targetFissionRate = fissionRate;
|
||||
targetTurbineOutput = turbineOutput;
|
||||
|
||||
LastUser = c.Character;
|
||||
if (nextServerLogWriteTime == null)
|
||||
{
|
||||
nextServerLogWriteTime = Math.Max(lastServerLogWriteTime + 1.0f, (float)Timing.TotalTime);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
fissionRateScrollBar.BarScroll = 1.0f - targetFissionRate / 100.0f;
|
||||
turbineOutputScrollBar.BarScroll = 1.0f - targetTurbineOutput / 100.0f;
|
||||
onOffSwitch.BarScroll = shutDown ? Math.Max(onOffSwitch.BarScroll, 0.55f) : Math.Min(onOffSwitch.BarScroll, 0.45f);
|
||||
#endif
|
||||
|
||||
//need to create a server event to notify all clients of the changed state
|
||||
unsentChanges = true;
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(autoTemp);
|
||||
msg.Write(shutDown);
|
||||
msg.WriteRangedSingle(temperature, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(targetFissionRate, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(targetTurbineOutput, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(degreeOfSuccess, 0.0f, 1.0f, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +313,8 @@ namespace Barotrauma.Items.Components
|
||||
if (!item.CanClientAccess(c)) return;
|
||||
|
||||
IsActive = isActive;
|
||||
|
||||
//TODO: cleanup
|
||||
#if CLIENT
|
||||
activeTickBox.Selected = IsActive;
|
||||
#endif
|
||||
@@ -331,8 +333,9 @@ namespace Barotrauma.Items.Components
|
||||
directionalSlider.BarScroll = pingDirectionT;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ServerWrite(Lidgren.Network.NetBuffer msg, Client c, object[] extraData = null)
|
||||
|
||||
@@ -187,10 +187,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
networkUpdateTimer = 0.1f;
|
||||
unsentChanges = false;
|
||||
|
||||
@@ -22,9 +22,6 @@ namespace Barotrauma.Items.Components
|
||||
//how fast it's currently being recharged (can be changed, so that
|
||||
//charging can be slowed down or disabled if there's a shortage of power)
|
||||
private float rechargeSpeed;
|
||||
|
||||
private float maxOutput;
|
||||
|
||||
private float lastSentCharge;
|
||||
|
||||
//charge indicator description
|
||||
@@ -32,6 +29,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected bool isHorizontal;
|
||||
|
||||
//a list of powered devices connected directly to this item
|
||||
private readonly List<Pair<Powered, Connection>> directlyConnected = new List<Pair<Powered, Connection>>(10);
|
||||
|
||||
//charge indicator description
|
||||
protected Vector2 indicatorPosition, indicatorSize;
|
||||
|
||||
protected bool isHorizontal;
|
||||
|
||||
public float CurrPowerOutput
|
||||
{
|
||||
get;
|
||||
@@ -60,11 +65,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
[Editable(ToolTip = "Maximum output of the device when fully charged (kW)."), Serialize(10.0f, true)]
|
||||
public float MaxOutPut
|
||||
{
|
||||
set { maxOutput = value; }
|
||||
get { return maxOutput; }
|
||||
}
|
||||
public float MaxOutPut { set; get; }
|
||||
|
||||
[Serialize(10.0f, true), Editable(ToolTip = "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.")]
|
||||
@@ -86,7 +87,9 @@ namespace Barotrauma.Items.Components
|
||||
//send a network event if the charge has changed by more than 5%
|
||||
if (Math.Abs(charge - lastSentCharge) / capacity > 0.05f)
|
||||
{
|
||||
#if SERVER
|
||||
if (GameMain.Server != null) item.CreateServerEvent(this);
|
||||
#endif
|
||||
lastSentCharge = charge;
|
||||
}
|
||||
}
|
||||
@@ -129,11 +132,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
float chargeRatio = (float)(Math.Sqrt(charge / capacity));
|
||||
float chargeRatio = charge / capacity;
|
||||
float gridPower = 0.0f;
|
||||
float gridLoad = 0.0f;
|
||||
directlyConnected.Clear();
|
||||
|
||||
List<Pair<Powered, Connection>> directlyConnected = new List<Pair<Powered, Connection>>();
|
||||
foreach (Connection c in item.Connections)
|
||||
{
|
||||
if (c.Name == "power_in") continue;
|
||||
@@ -187,9 +190,16 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (gridPower < gridLoad)
|
||||
{
|
||||
//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 = MathHelper.Lerp(
|
||||
CurrPowerOutput,
|
||||
Math.Min(maxOutput * chargeRatio, gridLoad),
|
||||
Math.Min(MaxOutPut * maxOutputRatio, gridLoad),
|
||||
deltaTime * 10.0f);
|
||||
}
|
||||
else
|
||||
@@ -212,13 +222,17 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
||||
{
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null) return false;
|
||||
#endif
|
||||
|
||||
if (string.IsNullOrEmpty(objective.Option) || objective.Option.ToLowerInvariant() == "charge")
|
||||
{
|
||||
if (Math.Abs(rechargeSpeed - maxRechargeSpeed * 0.5f) > 0.05f)
|
||||
{
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
RechargeSpeed = maxRechargeSpeed * 0.5f;
|
||||
#if CLIENT
|
||||
rechargeSpeedSlider.BarScroll = RechargeSpeed / Math.Max(maxRechargeSpeed, 1.0f);
|
||||
@@ -232,7 +246,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (rechargeSpeed > 0.0f)
|
||||
{
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
RechargeSpeed = 0.0f;
|
||||
#if CLIENT
|
||||
rechargeSpeedSlider.BarScroll = RechargeSpeed / Math.Max(maxRechargeSpeed, 1.0f);
|
||||
@@ -259,26 +275,5 @@ namespace Barotrauma.Items.Components
|
||||
outputVoltage = power;
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
float newRechargeSpeed = msg.ReadRangedInteger(0, 10) / 10.0f * maxRechargeSpeed;
|
||||
|
||||
if (item.CanClientAccess(c))
|
||||
{
|
||||
RechargeSpeed = newRechargeSpeed;
|
||||
GameServer.Log(c.Character.LogName + " set the recharge speed of " + item.Name + " to " + (int)((rechargeSpeed / maxRechargeSpeed) * 100.0f) + " %", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.WriteRangedInteger(0, 10, (int)(rechargeSpeed / MaxRechargeSpeed * 10));
|
||||
|
||||
float chargeRatio = MathHelper.Clamp(charge / capacity, 0.0f, 1.0f);
|
||||
msg.WriteRangedSingle(chargeRatio, 0.0f, 1.0f, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,9 +169,14 @@ namespace Barotrauma.Items.Components
|
||||
pt.Item.SendSignal(0, "", "power", null, voltage);
|
||||
pt.Item.SendSignal(0, "", "power_out", null, voltage);
|
||||
|
||||
#if CLIENT
|
||||
//damage the item if voltage is too high
|
||||
//(except if running as a client)
|
||||
if (GameMain.Client != null) continue;
|
||||
#endif
|
||||
|
||||
//items in a bad condition are more sensitive to overvoltage
|
||||
float maxOverVoltage = MathHelper.Lerp(Math.Min(OverloadVoltage, 1.0f), OverloadVoltage, item.Condition / item.Prefab.Health);
|
||||
|
||||
//items in a bad condition are more sensitive to overvoltage
|
||||
float maxOverVoltage = MathHelper.Lerp(Math.Min(OverloadVoltage, 1.0f), OverloadVoltage, item.Condition / 100.0f);
|
||||
@@ -313,26 +318,24 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime, null);
|
||||
|
||||
float maxPower = this is RelayComponent relayComponent ? relayComponent.MaxPower : float.PositiveInfinity;
|
||||
|
||||
foreach (Connection c in PowerConnections)
|
||||
{
|
||||
var recipients = c.Recipients;
|
||||
foreach (Connection recipient in recipients)
|
||||
{
|
||||
if (recipient == null) continue;
|
||||
if (recipient?.Item == null) continue;
|
||||
|
||||
Item it = recipient.Item;
|
||||
if (it == null) continue;
|
||||
|
||||
if (it.Condition <= 0.0f) continue;
|
||||
|
||||
foreach (ItemComponent ic in it.components)
|
||||
foreach (ItemComponent ic in it.Components)
|
||||
{
|
||||
Powered powered = ic as Powered;
|
||||
if (powered == null || !powered.IsActive) continue;
|
||||
if (!(ic is Powered powered) || !powered.IsActive) continue;
|
||||
if (connectedList.Contains(powered)) continue;
|
||||
|
||||
PowerTransfer powerTransfer = powered as PowerTransfer;
|
||||
if (powerTransfer != null)
|
||||
if (powered is PowerTransfer powerTransfer)
|
||||
{
|
||||
if (this is RelayComponent == powerTransfer is RelayComponent)
|
||||
{
|
||||
@@ -348,8 +351,7 @@ namespace Barotrauma.Items.Components
|
||||
continue;
|
||||
}
|
||||
|
||||
PowerContainer powerContainer = powered as PowerContainer;
|
||||
if (powerContainer != null)
|
||||
if (powered is PowerContainer powerContainer)
|
||||
{
|
||||
if (recipient.Name == "power_in")
|
||||
{
|
||||
@@ -357,7 +359,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
fullPower += powerContainer.CurrPowerOutput;
|
||||
fullPower += Math.Min(powerContainer.CurrPowerOutput, maxPower);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -372,7 +374,7 @@ namespace Barotrauma.Items.Components
|
||||
//negative power consumption = the construction is a
|
||||
//generator/battery or another junction box
|
||||
{
|
||||
fullPower -= powered.CurrPowerConsumption;
|
||||
fullPower -= Math.Max(powered.CurrPowerConsumption, -maxPower);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -422,7 +424,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (recipient.Item == item || recipient.Item == source) continue;
|
||||
|
||||
foreach (ItemComponent ic in recipient.Item.components)
|
||||
foreach (ItemComponent ic in recipient.Item.Components)
|
||||
{
|
||||
//powertransfer components don't need to receive the signal in the pass-through signal connections
|
||||
//because we relay it straight to the connected items without going through the whole chain of junction boxes
|
||||
|
||||
@@ -12,9 +12,7 @@ namespace Barotrauma.Items.Components
|
||||
public static float SkillIncreaseMultiplier = 0.4f;
|
||||
|
||||
private string header;
|
||||
|
||||
private float lastSentProgress;
|
||||
|
||||
|
||||
private float fixDurationLowSkill, fixDurationHighSkill;
|
||||
|
||||
private float deteriorationTimer;
|
||||
@@ -71,7 +69,7 @@ namespace Barotrauma.Items.Components
|
||||
get { return currentFixer; }
|
||||
set
|
||||
{
|
||||
if (currentFixer == value || item.Condition >= 100.0f) return;
|
||||
if (currentFixer == value || item.Condition >= item.Prefab.Health) return;
|
||||
if (currentFixer != null) currentFixer.AnimController.Anim = AnimController.Animation.None;
|
||||
currentFixer = value;
|
||||
}
|
||||
@@ -93,8 +91,11 @@ namespace Barotrauma.Items.Components
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
|
||||
|
||||
#if SERVER
|
||||
//let the clients know the initial deterioration delay
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element);
|
||||
@@ -119,10 +120,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (deteriorationTimer > 0.0f)
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
if (GameMain.NetworkMember == null || !GameMain.NetworkMember.IsClient)
|
||||
{
|
||||
deteriorationTimer -= deltaTime;
|
||||
#if SERVER
|
||||
if (deteriorationTimer <= 0.0f) { item.CreateServerEvent(this); }
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -144,7 +147,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
UpdateFixAnimation(CurrentFixer);
|
||||
|
||||
if (GameMain.Client != null) return;
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return; }
|
||||
|
||||
float successFactor = requiredSkills.Count == 0 ? 1.0f : 0.0f;
|
||||
foreach (Skill skill in requiredSkills)
|
||||
@@ -166,10 +169,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
item.Condition += deltaTime / (fixDuration / item.Prefab.Health);
|
||||
}
|
||||
|
||||
|
||||
if (wasBroken && item.Condition >= item.Prefab.Health)
|
||||
{
|
||||
SteamAchievementManager.OnItemRepaired(item, currentFixer);
|
||||
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
|
||||
#if SERVER
|
||||
item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Barotrauma.Items.Components
|
||||
source.LastSentSignalRecipients.Add(recipient.item);
|
||||
}
|
||||
|
||||
foreach (ItemComponent ic in recipient.item.components)
|
||||
foreach (ItemComponent ic in recipient.item.Components)
|
||||
{
|
||||
ic.ReceiveSignal(stepsTaken, signal, recipient, source, sender, power, signalStrength);
|
||||
}
|
||||
|
||||
@@ -220,144 +220,5 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
List<Wire>[] wires = new List<Wire>[Connections.Count];
|
||||
|
||||
//read wire IDs for each connection
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
wires[i] = new List<Wire>();
|
||||
for (int j = 0; j < Connection.MaxLinked; j++)
|
||||
{
|
||||
ushort wireId = msg.ReadUInt16();
|
||||
|
||||
Item wireItem = Entity.FindEntityByID(wireId) as Item;
|
||||
if (wireItem == null) continue;
|
||||
|
||||
Wire wireComponent = wireItem.GetComponent<Wire>();
|
||||
if (wireComponent != null)
|
||||
{
|
||||
wires[i].Add(wireComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//don't allow rewiring locked panels
|
||||
if (Locked) return;
|
||||
|
||||
item.CreateServerEvent(this);
|
||||
|
||||
//check if the character can access this connectionpanel
|
||||
//and all the wires they're trying to connect
|
||||
if (!item.CanClientAccess(c)) return;
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
foreach (Wire wire in wires[i])
|
||||
{
|
||||
//wire not found in any of the connections yet (client is trying to connect a new wire)
|
||||
// -> we need to check if the client has access to it
|
||||
if (!Connections.Any(connection => connection.Wires.Contains(wire)))
|
||||
{
|
||||
if (!wire.Item.CanClientAccess(c)) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//go through existing wire links
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
int j = -1;
|
||||
foreach (Wire existingWire in Connections[i].Wires)
|
||||
{
|
||||
j++;
|
||||
if (existingWire == null) continue;
|
||||
|
||||
//existing wire not in the list of new wires -> disconnect it
|
||||
if (!wires[i].Contains(existingWire))
|
||||
{
|
||||
if (existingWire.Locked)
|
||||
{
|
||||
//this should not be possible unless the client is running a modified version of the game
|
||||
GameServer.Log(c.Character.LogName + " attempted to disconnect a locked wire from " +
|
||||
Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.Error);
|
||||
continue;
|
||||
}
|
||||
|
||||
existingWire.RemoveConnection(item);
|
||||
|
||||
if (existingWire.Connections[0] == null && existingWire.Connections[1] == null)
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + " disconnected a wire from " +
|
||||
Connections[i].Item.Name + " (" + Connections[i].Name + ")", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
else if (existingWire.Connections[0] != null)
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + " disconnected a wire from " +
|
||||
Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[0].Item.Name + " (" + existingWire.Connections[0].Name + ")", ServerLog.MessageType.ItemInteraction);
|
||||
|
||||
//wires that are not in anyone's inventory (i.e. not currently being rewired)
|
||||
//can never be connected to only one connection
|
||||
// -> the client must have dropped the wire from the connection panel
|
||||
if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
|
||||
{
|
||||
//let other clients know the item was also disconnected from the other connection
|
||||
existingWire.Connections[0].Item.CreateServerEvent(existingWire.Connections[0].Item.GetComponent<ConnectionPanel>());
|
||||
existingWire.Item.Drop(c.Character);
|
||||
}
|
||||
}
|
||||
else if (existingWire.Connections[1] != null)
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + " disconnected a wire from " +
|
||||
Connections[i].Item.Name + " (" + Connections[i].Name + ") to " + existingWire.Connections[1].Item.Name + " (" + existingWire.Connections[1].Name + ")", ServerLog.MessageType.ItemInteraction);
|
||||
|
||||
if (existingWire.Item.ParentInventory == null && !wires.Any(w => w.Contains(existingWire)))
|
||||
{
|
||||
//let other clients know the item was also disconnected from the other connection
|
||||
existingWire.Connections[1].Item.CreateServerEvent(existingWire.Connections[1].Item.GetComponent<ConnectionPanel>());
|
||||
existingWire.Item.Drop(c.Character);
|
||||
}
|
||||
}
|
||||
|
||||
Connections[i].SetWire(j, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//go through new wires
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
foreach (Wire newWire in wires[i])
|
||||
{
|
||||
//already connected, no need to do anything
|
||||
if (Connections[i].Wires.Contains(newWire)) continue;
|
||||
|
||||
Connections[i].TryAddLink(newWire);
|
||||
newWire.Connect(Connections[i], true, true);
|
||||
|
||||
var otherConnection = newWire.OtherConnection(Connections[i]);
|
||||
|
||||
if (otherConnection == null)
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + " connected a wire to " +
|
||||
Connections[i].Item.Name + " (" + Connections[i].Name + ")",
|
||||
ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameServer.Log(c.Character.LogName + " connected a wire from " +
|
||||
Connections[i].Item.Name + " (" + Connections[i].Name + ") to " +
|
||||
(otherConnection == null ? "none" : otherConnection.Item.Name + " (" + (otherConnection.Name) + ")"),
|
||||
ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
ClientWrite(msg, extraData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,57 +137,5 @@ namespace Barotrauma.Items.Components
|
||||
item.SendSignal(0, ciElement.State ? ciElement.Signal : "0", ciElement.Connection, sender: null, source: item);
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
|
||||
{
|
||||
bool[] elementStates = new bool[customInterfaceElementList.Count];
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
elementStates[i] = msg.ReadBoolean();
|
||||
}
|
||||
|
||||
CustomInterfaceElement clickedButton = null;
|
||||
if (item.CanClientAccess(c))
|
||||
{
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
if (customInterfaceElementList[i].ContinuousSignal)
|
||||
{
|
||||
TickBoxToggled(customInterfaceElementList[i], elementStates[i]);
|
||||
}
|
||||
else if (elementStates[i])
|
||||
{
|
||||
clickedButton = customInterfaceElementList[i];
|
||||
ButtonClicked(customInterfaceElementList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//notify all clients of the new state
|
||||
GameMain.Server.CreateEntityEvent(item, new object[]
|
||||
{
|
||||
NetEntityEvent.Type.ComponentState,
|
||||
item.components.IndexOf(this),
|
||||
clickedButton
|
||||
});
|
||||
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
//extradata contains an array of buttons clicked by a client (or nothing if nothing was clicked)
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
if (customInterfaceElementList[i].ContinuousSignal)
|
||||
{
|
||||
msg.Write(customInterfaceElementList[i].State);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(extraData != null && extraData.Any(d => d as CustomInterfaceElement == customInterfaceElementList[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,9 @@ namespace Barotrauma.Items.Components
|
||||
if (IsActive == value) return;
|
||||
|
||||
IsActive = value;
|
||||
#if SERVER
|
||||
if (GameMain.Server != null) item.CreateServerEvent(this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +154,7 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
|
||||
IsActive = IsOn;
|
||||
item.AddTag("light");
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
@@ -174,7 +177,7 @@ namespace Barotrauma.Items.Components
|
||||
if (body != null)
|
||||
{
|
||||
#if CLIENT
|
||||
light.Rotation = body.Dir > 0.0f ? body.Rotation : body.Rotation - MathHelper.Pi;
|
||||
light.Rotation = body.Dir > 0.0f ? body.DrawRotation : body.DrawRotation - MathHelper.Pi;
|
||||
light.LightSpriteEffect = (body.Dir > 0.0f) ? SpriteEffects.None : SpriteEffects.FlipVertically;
|
||||
#endif
|
||||
if (!body.Enabled)
|
||||
@@ -234,9 +237,16 @@ namespace Barotrauma.Items.Components
|
||||
light.Color = lightColor * lightBrightness * (1.0f - Rand.Range(0.0f, Flicker));
|
||||
light.Range = range;
|
||||
#endif
|
||||
item.SightRange = Math.Max(range * (float)Math.Sqrt(lightBrightness), item.SightRange);
|
||||
}
|
||||
|
||||
if (AITarget != null)
|
||||
{
|
||||
UpdateAITarget(AITarget);
|
||||
}
|
||||
if (item.AiTarget != null)
|
||||
{
|
||||
UpdateAITarget(item.AiTarget);
|
||||
}
|
||||
|
||||
voltage = 0.0f;
|
||||
}
|
||||
|
||||
@@ -279,5 +289,16 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
msg.Write(IsOn);
|
||||
}
|
||||
|
||||
private void UpdateAITarget(AITarget target)
|
||||
{
|
||||
//voltage > minVoltage || powerConsumption <= 0.0f; <- ?
|
||||
target.Enabled = IsActive;
|
||||
if (target.MaxSightRange <= 0)
|
||||
{
|
||||
target.MaxSightRange = Range * 5;
|
||||
}
|
||||
target.SightRange = IsActive ? target.MaxSightRange * lightBrightness : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,13 @@ namespace Barotrauma.Items.Components
|
||||
set { falseOutput = value; }
|
||||
}
|
||||
|
||||
[Editable(ToolTip = "How fast the objects within the detector's range have to be moving (in m/s).", DecimalCount = 3), Serialize(0.01f, true)]
|
||||
public float MinimumVelocity
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
public MotionSensor(Item item, XElement element)
|
||||
: base (item, element)
|
||||
@@ -106,7 +113,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (item.body != null && item.body.Enabled)
|
||||
{
|
||||
if (Math.Abs(item.body.LinearVelocity.X) > 0.01f || Math.Abs(item.body.LinearVelocity.Y) > 0.1f)
|
||||
if (Math.Abs(item.body.LinearVelocity.X) > MinimumVelocity || Math.Abs(item.body.LinearVelocity.Y) > MinimumVelocity)
|
||||
{
|
||||
motionDetected = true;
|
||||
}
|
||||
@@ -130,7 +137,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (Limb limb in c.AnimController.Limbs)
|
||||
{
|
||||
if (limb.LinearVelocity.LengthSquared() <= 0.001f) continue;
|
||||
if (limb.LinearVelocity.LengthSquared() <= MinimumVelocity * MinimumVelocity) continue;
|
||||
if (MathUtils.CircleIntersectsRectangle(limb.WorldPosition, ConvertUnits.ToDisplayUnits(limb.body.GetMaxExtent()), detectRect))
|
||||
{
|
||||
motionDetected = true;
|
||||
|
||||
@@ -51,7 +51,10 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
item.SendSignal(0, IsOn ? "1" : "0", "state_out", null);
|
||||
|
||||
if (Math.Min(-currPowerConsumption, PowerLoad) > maxPower) item.Condition = 0.0f;
|
||||
if (Math.Min(-currPowerConsumption, PowerLoad) > maxPower && CanBeOverloaded)
|
||||
{
|
||||
item.Condition = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
|
||||
@@ -81,12 +84,16 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void SetState(bool on, bool isNetworkMessage)
|
||||
{
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null && !isNetworkMessage) return;
|
||||
#endif
|
||||
|
||||
#if SERVER
|
||||
if (on != IsOn && GameMain.Server != null)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
IsOn = on;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
private string output, falseOutput;
|
||||
|
||||
//how often the detector can switch from state to another
|
||||
const float StateSwitchInterval = 1.0f;
|
||||
|
||||
private bool isInWater;
|
||||
private float stateSwitchDelay;
|
||||
|
||||
[InGameEditable, Serialize("1", true)]
|
||||
public string Output
|
||||
{
|
||||
@@ -28,22 +34,37 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
string signalOut = falseOutput;
|
||||
if (item.InWater)
|
||||
if (stateSwitchDelay > 0.0f)
|
||||
{
|
||||
//item in water -> we definitely want to send the True output
|
||||
signalOut = Output;
|
||||
stateSwitchDelay -= deltaTime;
|
||||
}
|
||||
else if (item.CurrentHull != null)
|
||||
else
|
||||
{
|
||||
//item in not water -> check if there's water anywhere within the rect of the item
|
||||
if (item.CurrentHull.Surface > item.CurrentHull.Rect.Y - item.CurrentHull.Rect.Height + 1 &&
|
||||
item.CurrentHull.Surface > item.Rect.Y - item.Rect.Height)
|
||||
bool prevState = isInWater;
|
||||
|
||||
isInWater = false;
|
||||
if (item.InWater)
|
||||
{
|
||||
signalOut = output;
|
||||
//item in water -> we definitely want to send the True output
|
||||
isInWater = true;
|
||||
}
|
||||
else if (item.CurrentHull != null)
|
||||
{
|
||||
//item in not water -> check if there's water anywhere within the rect of the item
|
||||
if (item.CurrentHull.Surface > item.CurrentHull.Rect.Y - item.CurrentHull.Rect.Height + 1 &&
|
||||
item.CurrentHull.Surface > item.Rect.Y - item.Rect.Height)
|
||||
{
|
||||
isInWater = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevState != isInWater)
|
||||
{
|
||||
stateSwitchDelay = StateSwitchInterval;
|
||||
}
|
||||
}
|
||||
|
||||
string signalOut = isInWater ? output : falseOutput;
|
||||
if (!string.IsNullOrEmpty(signalOut))
|
||||
{
|
||||
item.SendSignal(0, signalOut, "signal_out", null);
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private string prevSignal;
|
||||
|
||||
public byte TeamID;
|
||||
public Character.TeamType TeamID;
|
||||
|
||||
[Serialize(20000.0f, false)]
|
||||
public float Range
|
||||
@@ -134,12 +134,16 @@ namespace Barotrauma.Items.Components
|
||||
if (chatMsg.Length > ChatMessage.MaxLength) chatMsg = chatMsg.Substring(0, ChatMessage.MaxLength);
|
||||
if (string.IsNullOrEmpty(chatMsg)) continue;
|
||||
|
||||
#if CLIENT
|
||||
if (wifiComp.item.ParentInventory.Owner == Character.Controlled)
|
||||
{
|
||||
if (GameMain.Client == null)
|
||||
GameMain.NetworkMember.AddChatMessage(signal, ChatMessageType.Radio, source == null ? "" : source.Name);
|
||||
}
|
||||
else if (GameMain.Server != null)
|
||||
#endif
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
Client recipientClient = GameMain.Server.ConnectedClients.Find(c => c.Character == wifiComp.item.ParentInventory.Owner);
|
||||
if (recipientClient != null)
|
||||
@@ -148,6 +152,7 @@ namespace Barotrauma.Items.Components
|
||||
ChatMessage.Create(source == null ? "" : source.Name, chatMsg, ChatMessageType.Radio, null), recipientClient);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
chatMsgSent = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,24 @@ namespace Barotrauma.Items.Components
|
||||
partial class WireSection
|
||||
{
|
||||
private Vector2 start;
|
||||
private Vector2 end;
|
||||
|
||||
private float angle;
|
||||
private float length;
|
||||
|
||||
public Vector2 Start
|
||||
{
|
||||
get { return start; }
|
||||
}
|
||||
public Vector2 End
|
||||
{
|
||||
get { return end; }
|
||||
}
|
||||
|
||||
public WireSection(Vector2 start, Vector2 end)
|
||||
{
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
||||
angle = MathUtils.VectorToAngle(end - start);
|
||||
length = Vector2.Distance(start, end);
|
||||
@@ -41,6 +52,8 @@ namespace Barotrauma.Items.Components
|
||||
private bool canPlaceNode;
|
||||
private Vector2 newNodePos;
|
||||
|
||||
private Vector2 sectionExtents;
|
||||
|
||||
public bool Hidden;
|
||||
|
||||
private bool locked;
|
||||
@@ -185,7 +198,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (connections[0] != null && connections[1] != null)
|
||||
{
|
||||
foreach (ItemComponent ic in item.components)
|
||||
foreach (ItemComponent ic in item.Components)
|
||||
{
|
||||
if (ic == this) continue;
|
||||
ic.Drop(null);
|
||||
@@ -202,10 +215,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (sendNetworkEvent)
|
||||
{
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
CreateNetworkEvent();
|
||||
}
|
||||
#endif
|
||||
//the wire is active if only one end has been connected
|
||||
IsActive = connections[0] == null ^ connections[1] == null;
|
||||
}
|
||||
@@ -274,8 +289,7 @@ namespace Barotrauma.Items.Components
|
||||
//prevent the wire from extending too far when rewiring
|
||||
if (nodes.Count > 0)
|
||||
{
|
||||
Character user = item.ParentInventory?.Owner as Character;
|
||||
if (user == null) return;
|
||||
if (!(item.ParentInventory?.Owner is Character user)) return;
|
||||
|
||||
Vector2 prevNodePos = nodes[nodes.Count - 1];
|
||||
if (sub != null) { prevNodePos += sub.HiddenSubPosition; }
|
||||
@@ -294,11 +308,17 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
user.AnimController.Collider.ApplyForce(pullBackDir * user.Mass * 50.0f);
|
||||
user.AnimController.UpdateUseItem(true, user.WorldPosition + pullBackDir * 200.0f);
|
||||
if (currLength > MaxLength * 1.5f && GameMain.Client == null)
|
||||
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
ClearConnections();
|
||||
CreateNetworkEvent();
|
||||
return;
|
||||
if (currLength > MaxLength * 1.5f)
|
||||
{
|
||||
ClearConnections();
|
||||
#if SERVER
|
||||
CreateNetworkEvent();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,12 +328,18 @@ namespace Barotrauma.Items.Components
|
||||
newNodePos = RoundNode(item.Position, item.CurrentHull) - sub.HiddenSubPosition;
|
||||
canPlaceNode = true;
|
||||
}
|
||||
|
||||
sectionExtents = new Vector2(
|
||||
Math.Max(Math.Abs((newNodePos.X + sub.HiddenSubPosition.X) - item.Position.X), sectionExtents.X),
|
||||
Math.Max(Math.Abs((newNodePos.Y + sub.HiddenSubPosition.Y) - item.Position.Y), sectionExtents.Y));
|
||||
}
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (character == null) return false;
|
||||
#if CLIENT
|
||||
if (character == Character.Controlled && character.SelectedConstruction != null) return false;
|
||||
#endif
|
||||
|
||||
if (newNodePos != Vector2.Zero && canPlaceNode && nodes.Count > 0 && Vector2.Distance(newNodePos, nodes[nodes.Count - 1]) > nodeDistance)
|
||||
{
|
||||
@@ -328,10 +354,12 @@ namespace Barotrauma.Items.Components
|
||||
Drawable = true;
|
||||
newNodePos = Vector2.Zero;
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
CreateNetworkEvent();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -393,18 +421,33 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
sections.Clear();
|
||||
|
||||
for (int i = 0; i < nodes.Count-1; i++)
|
||||
for (int i = 0; i < nodes.Count - 1; i++)
|
||||
{
|
||||
sections.Add(new WireSection(nodes[i], nodes[i + 1]));
|
||||
}
|
||||
Drawable = IsActive || sections.Count > 0;
|
||||
CalculateExtents();
|
||||
}
|
||||
|
||||
private void CalculateExtents()
|
||||
{
|
||||
sectionExtents = Vector2.Zero;
|
||||
if (sections.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < nodes.Count; i++)
|
||||
{
|
||||
sectionExtents.X = Math.Max(Math.Abs(nodes[i].X - item.Position.X), sectionExtents.X);
|
||||
sectionExtents.Y = Math.Max(Math.Abs(nodes[i].Y - item.Position.Y), sectionExtents.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearConnections(Character user = null)
|
||||
{
|
||||
nodes.Clear();
|
||||
sections.Clear();
|
||||
|
||||
|
||||
#if SERVER
|
||||
if (user != null)
|
||||
{
|
||||
if (connections[0] != null && connections[1] != null)
|
||||
@@ -424,6 +467,7 @@ namespace Barotrauma.Items.Components
|
||||
connections[1].Item.Name + " (" + connections[1].Name + ")", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
SetConnectedDirty();
|
||||
|
||||
@@ -627,33 +671,6 @@ namespace Barotrauma.Items.Components
|
||||
base.RemoveComponentSpecific();
|
||||
}
|
||||
|
||||
private void CreateNetworkEvent()
|
||||
{
|
||||
if (GameMain.Server == null) return;
|
||||
//split into multiple events because one might not be enough to fit all the nodes
|
||||
int eventCount = Math.Max((int)Math.Ceiling(nodes.Count / (float)MaxNodesPerNetworkEvent), 1);
|
||||
for (int i = 0; i < eventCount; i++)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.components.IndexOf(this), i });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
int eventIndex = (int)extraData[2];
|
||||
int nodeStartIndex = eventIndex * MaxNodesPerNetworkEvent;
|
||||
int nodeCount = MathHelper.Clamp(nodes.Count - nodeStartIndex, 0, MaxNodesPerNetworkEvent);
|
||||
|
||||
msg.WriteRangedInteger(0, (int)Math.Ceiling(MaxNodeCount / (float)MaxNodesPerNetworkEvent), eventIndex);
|
||||
msg.WriteRangedInteger(0, MaxNodesPerNetworkEvent, nodeCount);
|
||||
for (int i = nodeStartIndex; i < nodeStartIndex + nodeCount; i++)
|
||||
{
|
||||
msg.Write(nodes[i].X);
|
||||
msg.Write(nodes[i].Y);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
|
||||
{
|
||||
int eventIndex = msg.ReadRangedInteger(0, (int)Math.Ceiling(MaxNodeCount / (float)MaxNodesPerNetworkEvent));
|
||||
|
||||
@@ -189,6 +189,7 @@ namespace Barotrauma.Items.Components
|
||||
#if CLIENT
|
||||
if (lightComponent != null)
|
||||
{
|
||||
lightComponent.Parent = null;
|
||||
lightComponent.Rotation = rotation;
|
||||
lightComponent.Light.Rotation = -rotation;
|
||||
}
|
||||
@@ -258,7 +259,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private bool TryLaunch(float deltaTime, Character character = null)
|
||||
{
|
||||
#if CLIENT
|
||||
if (GameMain.Client != null) return false;
|
||||
#endif
|
||||
|
||||
if (reload > 0.0f) return false;
|
||||
|
||||
@@ -313,27 +316,32 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
battery.Charge -= takePower / 3600.0f;
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
battery.Item.CreateServerEvent(battery);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Launch(projectiles[0].Item, character);
|
||||
|
||||
#if SERVER
|
||||
if (character != null)
|
||||
{
|
||||
string msg = character.LogName + " launched " + item.Name + " (projectile: " + projectiles[0].Item.Name;
|
||||
if (projectiles[0].Item.ContainedItems == null || projectiles[0].Item.ContainedItems.All(i => i == null))
|
||||
var containedItems = projectiles[0].Item.ContainedItems;
|
||||
if (containedItems == null || !containedItems.Any())
|
||||
{
|
||||
msg += ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
msg += ", contained items: " + string.Join(", ", Array.FindAll(projectiles[0].Item.ContainedItems, i => i != null).Select(i => i.Name)) + ")";
|
||||
msg += ", contained items: " + string.Join(", ", containedItems.Select(i => i.Name)) + ")";
|
||||
}
|
||||
GameServer.Log(msg, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -359,10 +367,10 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
if (projectile.Container != null) projectile.Container.RemoveContained(projectile);
|
||||
|
||||
if (GameMain.Server != null)
|
||||
|
||||
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
GameMain.Server.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.components.IndexOf(this), projectile });
|
||||
GameMain.NetworkMember.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), projectile });
|
||||
}
|
||||
|
||||
ApplyStatusEffects(ActionType.OnUse, 1.0f, user: user);
|
||||
@@ -415,18 +423,9 @@ namespace Barotrauma.Items.Components
|
||||
if (containedItems != null)
|
||||
{
|
||||
var container = projectileContainer.GetComponent<ItemContainer>();
|
||||
if (containedItems != null) maxProjectileCount += container.Capacity;
|
||||
|
||||
int projectiles = 0;
|
||||
|
||||
for (int i = 0; i < containedItems.Length; i++)
|
||||
{
|
||||
if (containedItems[i].Condition > 0.0f)
|
||||
{
|
||||
projectiles++;
|
||||
}
|
||||
}
|
||||
maxProjectileCount += container.Capacity;
|
||||
|
||||
int projectiles = containedItems.Count(it => it.Condition > 0.0f);
|
||||
usableProjectileCount += projectiles;
|
||||
}
|
||||
}
|
||||
@@ -465,14 +464,21 @@ namespace Barotrauma.Items.Components
|
||||
foreach (Character enemy in Character.CharacterList)
|
||||
{
|
||||
//ignore humans and characters that are inside the sub
|
||||
if (enemy.IsDead || enemy.SpeciesName == "human" || enemy.AnimController.CurrentHull != null) continue;
|
||||
|
||||
if (enemy.IsDead|| enemy.AnimController.CurrentHull != null || !enemy.Enabled) { continue; }
|
||||
if (enemy.SpeciesName == character.SpeciesName && enemy.TeamID == character.TeamID) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(enemy.WorldPosition, item.WorldPosition);
|
||||
if (dist < closestDist)
|
||||
{
|
||||
closestEnemy = enemy;
|
||||
closestDist = dist;
|
||||
}
|
||||
if (dist > closestDist) { continue; }
|
||||
|
||||
float angle = -MathUtils.VectorToAngle(enemy.WorldPosition - item.WorldPosition);
|
||||
float midRotation = (minRotation + maxRotation) / 2.0f;
|
||||
while (midRotation - angle < -MathHelper.Pi) { angle -= MathHelper.TwoPi; }
|
||||
while (midRotation - angle > MathHelper.Pi) { angle += MathHelper.TwoPi; }
|
||||
|
||||
if (angle < minRotation || angle > maxRotation) { continue; }
|
||||
|
||||
closestEnemy = enemy;
|
||||
closestDist = dist;
|
||||
}
|
||||
|
||||
if (closestEnemy == null) return false;
|
||||
@@ -486,7 +492,7 @@ namespace Barotrauma.Items.Components
|
||||
float enemyAngle = MathUtils.VectorToAngle(closestEnemy.WorldPosition - item.WorldPosition);
|
||||
float turretAngle = -rotation;
|
||||
|
||||
if (Math.Abs(MathUtils.GetShortestAngle(enemyAngle, turretAngle)) > 0.1f) return false;
|
||||
if (Math.Abs(MathUtils.GetShortestAngle(enemyAngle, turretAngle)) > 0.15f) return false;
|
||||
|
||||
var pickedBody = Submarine.PickBody(ConvertUnits.ToSimUnits(item.WorldPosition), closestEnemy.SimPosition, null);
|
||||
if (pickedBody != null && !(pickedBody.UserData is Limb)) return false;
|
||||
@@ -559,9 +565,9 @@ namespace Barotrauma.Items.Components
|
||||
var containedItems = projectileContainer.ContainedItems;
|
||||
if (containedItems == null) return;
|
||||
|
||||
for (int i = 0; i < containedItems.Length; i++)
|
||||
foreach (Item containedItem in containedItems)
|
||||
{
|
||||
var projectileComponent = containedItems[i].GetComponent<Projectile>();
|
||||
var projectileComponent = containedItem.GetComponent<Projectile>();
|
||||
if (projectileComponent != null)
|
||||
{
|
||||
projectiles.Add(projectileComponent);
|
||||
@@ -570,10 +576,10 @@ namespace Barotrauma.Items.Components
|
||||
else
|
||||
{
|
||||
//check if the contained item is another itemcontainer with projectiles inside it
|
||||
if (containedItems[i].ContainedItems == null) continue;
|
||||
for (int j = 0; j < containedItems[i].ContainedItems.Length; j++)
|
||||
if (containedItem.ContainedItems == null) continue;
|
||||
foreach (Item subContainedItem in containedItem.ContainedItems)
|
||||
{
|
||||
projectileComponent = containedItems[i].ContainedItems[j].GetComponent<Projectile>();
|
||||
projectileComponent = subContainedItem.GetComponent<Projectile>();
|
||||
if (projectileComponent != null)
|
||||
{
|
||||
projectiles.Add(projectileComponent);
|
||||
@@ -653,12 +659,9 @@ namespace Barotrauma.Items.Components
|
||||
break;
|
||||
case "toggle":
|
||||
case "toggle_light":
|
||||
foreach (ItemComponent component in item.components)
|
||||
if (lightComponent != null)
|
||||
{
|
||||
if (component.Parent == this && component is LightComponent lightComponent)
|
||||
{
|
||||
lightComponent.IsOn = !lightComponent.IsOn;
|
||||
}
|
||||
lightComponent.IsOn = !lightComponent.IsOn;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -197,9 +197,11 @@ namespace Barotrauma.Items.Components
|
||||
foreach (XElement lightElement in subElement.Elements())
|
||||
{
|
||||
if (lightElement.Name.ToString().ToLowerInvariant() != "lightcomponent") continue;
|
||||
wearableSprites[i].LightComponent = new LightComponent(item, lightElement);
|
||||
wearableSprites[i].LightComponent.Parent = this;
|
||||
item.components.Add(wearableSprites[i].LightComponent);
|
||||
wearableSprites[i].LightComponent = new LightComponent(item, lightElement)
|
||||
{
|
||||
Parent = this
|
||||
};
|
||||
item.AddComponent(wearableSprites[i].LightComponent);
|
||||
}
|
||||
|
||||
i++;
|
||||
@@ -225,9 +227,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
Limb equipLimb = character.AnimController.GetLimb(limbType[i]);
|
||||
if (equipLimb == null) continue;
|
||||
if (equipLimb == null) { continue; }
|
||||
|
||||
item.body.Enabled = false;
|
||||
if (item.body != null)
|
||||
{
|
||||
item.body.Enabled = false;
|
||||
}
|
||||
IsActive = true;
|
||||
if (wearableSprite.LightComponent != null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user