(a00338777) v0.9.2.1

This commit is contained in:
Joonas Rikkonen
2019-08-26 19:58:19 +03:00
parent 0f63da27b2
commit 80698b58b0
311 changed files with 11763 additions and 4507 deletions
@@ -82,7 +82,7 @@ namespace Barotrauma.Items.Components
}
}
}
public DockingPort(Item item, XElement element)
: base(item, element)
{
@@ -160,7 +160,7 @@ namespace Barotrauma.Items.Components
if (DockingTarget != null)
{
Undock();
}
}
if (target.item.Submarine == item.Submarine)
{
@@ -168,7 +168,7 @@ namespace Barotrauma.Items.Components
DockingTarget = null;
return;
}
target.InitializeLinks();
if (!item.linkedTo.Contains(target.item)) item.linkedTo.Add(target.item);
@@ -193,7 +193,7 @@ namespace Barotrauma.Items.Components
Math.Sign(DockingTarget.item.WorldPosition.X - item.WorldPosition.X) :
Math.Sign(DockingTarget.item.WorldPosition.Y - item.WorldPosition.Y);
DockingTarget.DockingDir = -DockingDir;
if (door != null && DockingTarget.door != null)
{
WayPoint myWayPoint = WayPoint.WayPointList.Find(wp => door.LinkedGap == wp.ConnectedGap);
@@ -205,7 +205,7 @@ namespace Barotrauma.Items.Components
targetWayPoint.linkedTo.Add(myWayPoint);
}
}
CreateJoint(false);
#if SERVER
@@ -246,7 +246,7 @@ namespace Barotrauma.Items.Components
else if (DockingTarget.item.Submarine.PhysicsBody.Mass < item.Submarine.PhysicsBody.Mass ||
item.Submarine.IsOutpost)
{
DockingTarget.item.Submarine.SubBody.SetPosition(item.Submarine.SubBody.Position - ConvertUnits.ToDisplayUnits(jointDiff));
DockingTarget.item.Submarine.SubBody.SetPosition(DockingTarget.item.Submarine.SubBody.Position - ConvertUnits.ToDisplayUnits(jointDiff));
}
ConnectWireBetweenPorts();
@@ -401,7 +401,7 @@ namespace Barotrauma.Items.Components
}
private void CreateHulls()
{
{
var hullRects = new Rectangle[] { item.WorldRect, DockingTarget.item.WorldRect };
var subs = new Submarine[] { item.Submarine, DockingTarget.item.Submarine };
@@ -416,18 +416,18 @@ namespace Barotrauma.Items.Components
{
DockingTarget.CreateDoorBody();
}
if (IsHorizontal)
{
if (hullRects[0].Center.X > hullRects[1].Center.X)
{
hullRects = new Rectangle[] { DockingTarget.item.WorldRect, item.WorldRect };
subs = new Submarine[] { DockingTarget.item.Submarine,item.Submarine };
subs = new Submarine[] { DockingTarget.item.Submarine, item.Submarine };
}
hullRects[0] = new Rectangle(hullRects[0].Center.X, hullRects[0].Y, ((int)DockedDistance / 2), hullRects[0].Height);
hullRects[1] = new Rectangle(hullRects[1].Center.X - ((int)DockedDistance / 2), hullRects[1].Y, ((int)DockedDistance / 2), hullRects[1].Height);
//expand hulls if needed, so there's no empty space between the sub's hulls and docking port hulls
int leftSubRightSide = int.MinValue, rightSubLeftSide = int.MaxValue;
foreach (Hull hull in Hull.hullList)
@@ -478,7 +478,7 @@ namespace Barotrauma.Items.Components
hullRects[1].Width += rightHullDiff;
}
}
for (int i = 0; i < 2; i++)
{
hullRects[i].Location -= MathUtils.ToPoint((subs[i].WorldPosition - subs[i].HiddenSubPosition));
@@ -503,7 +503,7 @@ namespace Barotrauma.Items.Components
hullRects = new Rectangle[] { DockingTarget.item.WorldRect, item.WorldRect };
subs = new Submarine[] { DockingTarget.item.Submarine, item.Submarine };
}
hullRects[0] = new Rectangle(hullRects[0].X, hullRects[0].Y + (int)(-hullRects[0].Height + DockedDistance) / 2, hullRects[0].Width, ((int)DockedDistance / 2));
hullRects[1] = new Rectangle(hullRects[1].X, hullRects[1].Y - hullRects[1].Height / 2, hullRects[1].Width, ((int)DockedDistance / 2));
@@ -954,7 +954,7 @@ namespace Barotrauma.Items.Components
#endif
}
public void ServerWrite(Lidgren.Network.NetBuffer msg, Client c, object[] extraData = null)
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
msg.Write(docked);
@@ -965,7 +965,7 @@ namespace Barotrauma.Items.Components
}
}
public void ClientRead(ServerNetObject type, Lidgren.Network.NetBuffer msg, float sendingTime)
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
bool isDocked = msg.ReadBoolean();
@@ -313,8 +313,7 @@ namespace Barotrauma.Items.Components
PredictedState = null;
}
}
LinkedGap.Open = openState;
LinkedGap.Open = isBroken ? 1.0f : openState;
}
if (isClosing)
@@ -371,7 +370,7 @@ namespace Barotrauma.Items.Components
{
LinkedGap.AutoOrient();
}
LinkedGap.Open = openState;
LinkedGap.Open = isBroken ? 1.0f : openState;
LinkedGap.PassAmbientLight = Window != Rectangle.Empty;
}
@@ -1,6 +1,5 @@
using Barotrauma.Networking;
using FarseerPhysics;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Xml.Linq;
@@ -286,14 +285,21 @@ namespace Barotrauma.Items.Components
item.SetTransform(rightHand.SimPosition, 0.0f);
}
bool alreadySelected = character.HasEquippedItem(item);
if (picker.TrySelectItem(item) || picker.HasEquippedItem(item))
bool alreadyEquipped = character.HasEquippedItem(item);
bool canSelect = picker.TrySelectItem(item);
if (canSelect || picker.HasEquippedItem(item))
{
if (!canSelect)
{
character.DeselectItem(item);
}
item.body.Enabled = true;
IsActive = true;
#if SERVER
if (!alreadySelected) GameServer.Log(character.LogName + " equipped " + item.Name, ServerLog.MessageType.ItemInteraction);
if (!alreadyEquipped) GameServer.Log(character.LogName + " equipped " + item.Name, ServerLog.MessageType.ItemInteraction);
#endif
}
}
@@ -557,7 +563,7 @@ namespace Barotrauma.Items.Components
DeattachFromWall();
}
}
public override XElement Save(XElement parentElement)
{
if (!attachable)
@@ -581,8 +587,8 @@ namespace Barotrauma.Items.Components
return saveElement;
}
public override void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
public override void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
base.ServerWrite(msg, c, extraData);
if (!attachable || body == null) { return; }
@@ -592,11 +598,11 @@ namespace Barotrauma.Items.Components
msg.Write(body.SimPosition.Y);
}
public override void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
base.ClientRead(type, msg, sendingTime);
bool shouldBeAttached = msg.ReadBoolean();
Vector2 simPosition = new Vector2(msg.ReadFloat(), msg.ReadFloat());
Vector2 simPosition = new Vector2(msg.ReadSingle(), msg.ReadSingle());
if (!attachable)
{
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
@@ -116,7 +115,7 @@ namespace Barotrauma.Items.Components
}
}
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
msg.Write(deattachTimer);
}
@@ -56,11 +56,9 @@ namespace Barotrauma.Items.Components
public MeleeWeapon(Item item, XElement element)
: base(item, element)
{
//throwForce = ToolBox.GetAttributeFloat(element, "throwforce", 1.0f);
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLowerInvariant() != "attack") continue;
if (subElement.Name.ToString().ToLowerInvariant() != "attack") { continue; }
attack = new Attack(subElement, item.Name + ", MeleeWeapon");
}
item.IsShootable = true;
@@ -70,23 +68,22 @@ namespace Barotrauma.Items.Components
public override bool Use(float deltaTime, Character character = null)
{
if (character == null || reloadTimer > 0.0f) return false;
if (Item.RequireAimToUse && !character.IsKeyDown(InputType.Aim) || hitting) return false;
if (character == null || reloadTimer > 0.0f) { return false; }
if (Item.RequireAimToUse && !character.IsKeyDown(InputType.Aim) || hitting) { return false; }
//don't allow hitting if the character is already hitting with another weapon
for (int i = 0; i < 2; i++ )
{
if (character.SelectedItems[i] == null || character.SelectedItems[i] == Item) continue;
if (character.SelectedItems[i] == null || character.SelectedItems[i] == Item) { continue; }
var otherWeapon = character.SelectedItems[i].GetComponent<MeleeWeapon>();
if (otherWeapon == null) continue;
if (otherWeapon.hitting) return false;
if (otherWeapon == null) { continue; }
if (otherWeapon.hitting) { return false; }
}
SetUser(character);
if (hitPos < MathHelper.PiOver4) return false;
if (hitPos < MathHelper.PiOver4) { return false; }
reloadTimer = reload;
@@ -94,21 +91,20 @@ namespace Barotrauma.Items.Components
item.body.FarseerBody.CollidesWith = Physics.CollisionCharacter | Physics.CollisionWall;
item.body.FarseerBody.OnCollision += OnCollision;
foreach (Limb l in character.AnimController.Limbs)
if (!character.AnimController.InWater)
{
//item.body.FarseerBody.IgnoreCollisionWith(l.body.FarseerBody);
if (character.AnimController.InWater) continue;
if (l.type == LimbType.LeftFoot || l.type == LimbType.LeftThigh || l.type == LimbType.LeftLeg) continue;
if (l.type == LimbType.Head || l.type == LimbType.Torso)
foreach (Limb l in character.AnimController.Limbs)
{
l.body.ApplyLinearImpulse(new Vector2(character.AnimController.Dir * 7.0f, -4.0f));
if (l.type == LimbType.LeftFoot || l.type == LimbType.LeftThigh || l.type == LimbType.LeftLeg) { continue; }
if (l.type == LimbType.Head || l.type == LimbType.Torso)
{
l.body.ApplyLinearImpulse(new Vector2(character.AnimController.Dir * 7.0f, -4.0f));
}
else
{
l.body.ApplyLinearImpulse(new Vector2(character.AnimController.Dir * 5.0f, -2.0f));
}
}
else
{
l.body.ApplyLinearImpulse(new Vector2(character.AnimController.Dir * 5.0f, -2.0f));
}
}
hitting = true;
@@ -121,7 +117,6 @@ namespace Barotrauma.Items.Components
public override void Drop(Character dropper)
{
base.Drop(dropper);
hitting = false;
hitPos = 0.0f;
}
@@ -133,17 +128,17 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
if (!item.body.Enabled) return;
if (!picker.HasSelectedItem(item)) IsActive = false;
if (!item.body.Enabled) { return; }
if (!picker.HasSelectedItem(item)) { IsActive = false; }
reloadTimer -= deltaTime;
if (reloadTimer < 0) { reloadTimer = 0; }
if (!picker.IsKeyDown(InputType.Aim) && !hitting) hitPos = 0.0f;
if (!picker.IsKeyDown(InputType.Aim) && !hitting) { hitPos = 0.0f; }
ApplyStatusEffects(ActionType.OnActive, deltaTime, picker);
if (item.body.Dir != picker.AnimController.Dir) Flip();
if (item.body.Dir != picker.AnimController.Dir) { Flip(); }
AnimController ac = picker.AnimController;
@@ -236,16 +231,16 @@ namespace Barotrauma.Items.Components
if (f2.Body.UserData is Limb)
{
targetLimb = (Limb)f2.Body.UserData;
if (targetLimb.IsSevered || targetLimb.character == null) return false;
if (targetLimb.IsSevered || targetLimb.character == null) { return false; }
targetCharacter = targetLimb.character;
if (targetCharacter == picker) return false;
if (targetCharacter == picker){ return false; }
if (AllowHitMultiple)
{
if (hitTargets.Contains(targetCharacter)) return false;
if (hitTargets.Contains(targetCharacter)) { return false; }
}
else
{
if (hitTargets.Any(t => t is Character)) return false;
if (hitTargets.Any(t => t is Character)) { return false; }
}
hitTargets.Add(targetCharacter);
}
@@ -256,11 +251,11 @@ namespace Barotrauma.Items.Components
targetLimb = targetCharacter.AnimController.GetLimb(LimbType.Torso); //Otherwise armor can be bypassed in strange ways
if (AllowHitMultiple)
{
if (hitTargets.Contains(targetCharacter)) return false;
if (hitTargets.Contains(targetCharacter)) { return false; }
}
else
{
if (hitTargets.Any(t => t is Character)) return false;
if (hitTargets.Any(t => t is Character)) { return false; }
}
hitTargets.Add(targetCharacter);
}
@@ -269,11 +264,11 @@ namespace Barotrauma.Items.Components
targetStructure = (Structure)f2.Body.UserData;
if (AllowHitMultiple)
{
if (hitTargets.Contains(targetStructure)) return true;
if (hitTargets.Contains(targetStructure)) { return true; }
}
else
{
if (hitTargets.Any(t => t is Structure)) return true;
if (hitTargets.Any(t => t is Structure)) { return true; }
}
hitTargets.Add(targetStructure);
}
@@ -303,8 +298,8 @@ namespace Barotrauma.Items.Components
return false;
}
}
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) return true;
if (GameMain.NetworkMember != null && GameMain.NetworkMember.IsClient) { return true; }
#if SERVER
if (GameMain.Server != null && targetCharacter != null) //TODO: Log structure hits
@@ -3,7 +3,6 @@ using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using Lidgren.Network;
namespace Barotrauma.Items.Components
{
@@ -233,12 +232,12 @@ namespace Barotrauma.Items.Components
}
}
public virtual void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
public virtual void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
msg.Write(activePicker == null ? (ushort)0 : activePicker.ID);
}
public virtual void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
public virtual void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
ushort pickerID = msg.ReadUInt16();
if (pickerID == 0)
@@ -54,6 +54,9 @@ namespace Barotrauma.Items.Components
[Serialize(false, false)]
public bool RepairMultiple { get; set; }
[Serialize(false, false)]
public bool RepairThroughHoles { get; set; }
[Serialize(0.0f, false)]
public float FireProbability { get; set; }
@@ -146,10 +149,24 @@ 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;
Vector2 rayStart;
Vector2 sourcePos = character?.AnimController == null ? item.SimPosition : character.AnimController.AimSourceSimPos;
Vector2 barrelPos = item.SimPosition + ConvertUnits.ToSimUnits(TransformedBarrelPos);
//make sure there's no obstacles between the base of the item (or the shoulder of the character) and the end of the barrel
if (Submarine.PickBody(sourcePos, barrelPos, collisionCategory: Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking) == null)
{
//no obstacles -> we start the raycast at the end of the barrel
rayStart = ConvertUnits.ToSimUnits(item.WorldPosition + TransformedBarrelPos);
}
else
{
rayStart = ConvertUnits.ToSimUnits(item.WorldPosition);
}
Vector2 rayEnd = rayStart +
ConvertUnits.ToSimUnits(new Vector2(
(float)Math.Cos(item.body.Rotation),
(float)Math.Sin(item.body.Rotation)) * Range * item.body.Dir);
List<Body> ignoredBodies = new List<Body>();
foreach (Limb limb in character.AnimController.Limbs)
@@ -161,11 +178,8 @@ namespace Barotrauma.Items.Components
IsActive = true;
activeTimer = 0.1f;
Vector2 rayStart = ConvertUnits.ToSimUnits(item.WorldPosition);
Vector2 rayEnd = ConvertUnits.ToSimUnits(targetPosition);
debugRayStartPos = item.WorldPosition;
debugRayStartPos = ConvertUnits.ToDisplayUnits(rayStart);
debugRayEndPos = ConvertUnits.ToDisplayUnits(rayEnd);
if (character.Submarine == null)
@@ -203,7 +217,7 @@ namespace Barotrauma.Items.Components
float lastPickedFraction = 0.0f;
if (RepairMultiple)
{
var bodies = Submarine.PickBodies(rayStart, rayEnd, ignoredBodies, collisionCategories, ignoreSensors: false, allowInsideFixture: true);
var bodies = Submarine.PickBodies(rayStart, rayEnd, ignoredBodies, collisionCategories, ignoreSensors: RepairThroughHoles, allowInsideFixture: true);
lastPickedFraction = Submarine.LastPickedFraction;
Type lastHitType = null;
hitCharacters.Clear();
@@ -243,7 +257,7 @@ namespace Barotrauma.Items.Components
{
FixBody(user, deltaTime, degreeOfSuccess,
Submarine.PickBody(rayStart, rayEnd,
ignoredBodies, collisionCategories, ignoreSensors: false,
ignoredBodies, collisionCategories, ignoreSensors: RepairThroughHoles,
customPredicate: (Fixture f) => { return f?.Body?.UserData != null; },
allowInsideFixture: true));
lastPickedFraction = Submarine.LastPickedFraction;
@@ -324,6 +338,7 @@ namespace Barotrauma.Items.Components
}
else if (targetBody.UserData is Character targetCharacter)
{
if (targetCharacter.Removed) { return false; }
targetCharacter.LastDamageSource = item;
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, new List<ISerializableEntity>() { targetCharacter });
FixCharacterProjSpecific(user, deltaTime, targetCharacter);
@@ -331,6 +346,7 @@ namespace Barotrauma.Items.Components
}
else if (targetBody.UserData is Limb targetLimb)
{
if (targetLimb.character == null || targetLimb.character.Removed) { return false; }
targetLimb.character.LastDamageSource = item;
ApplyStatusEffectsOnTarget(user, deltaTime, ActionType.OnUse, new List<ISerializableEntity>() { targetLimb.character, targetLimb });
FixCharacterProjSpecific(user, deltaTime, targetLimb.character);
@@ -506,9 +522,9 @@ namespace Barotrauma.Items.Components
if (propertyName != "stuck") { continue; }
if (door.SerializableProperties == null || !door.SerializableProperties.TryGetValue(propertyName, out SerializableProperty property)) { continue; }
object value = property.GetValue(target);
if (value.GetType() == typeof(float))
if (door.Stuck > 0)
{
var progressBar = user.UpdateHUDProgressBar(door, door.Item.WorldPosition, (float)value / 100, Color.DarkGray * 0.5f, Color.White);
var progressBar = user.UpdateHUDProgressBar(door, door.Item.WorldPosition, door.Stuck / 100, Color.DarkGray * 0.5f, Color.White);
if (progressBar != null) { progressBar.Size = new Vector2(60.0f, 20.0f); }
}
}
@@ -6,12 +6,10 @@ namespace Barotrauma.Items.Components
{
class Throwable : Holdable
{
float throwForce;
private float throwForce, throwPos;
private bool throwing, throwDone;
float throwPos;
bool throwing;
bool throwDone;
private bool midAir;
[Serialize(1.0f, false)]
public float ThrowForce
@@ -57,7 +55,17 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
if (!item.body.Enabled) return;
if (!item.body.Enabled) { return; }
if (midAir)
{
if (item.body.LinearVelocity.LengthSquared() < 0.01f)
{
item.body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionPlatform;
midAir = false;
}
return;
}
if (picker == null || picker.Removed || !picker.HasSelectedItem(item))
{
IsActive = false;
@@ -113,6 +121,10 @@ namespace Barotrauma.Items.Components
item.Drop(thrower, createNetworkEvent: GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer);
item.body.ApplyLinearImpulse(throwVector * throwForce * item.body.Mass * 3.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
//disable platform collisions until the item comes back to rest again
item.body.CollidesWith = Physics.CollisionWall | Physics.CollisionLevel;
midAir = true;
ac.GetLimb(LimbType.Head).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
ac.GetLimb(LimbType.Torso).body.ApplyLinearImpulse(throwVector * 10.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
@@ -82,13 +82,14 @@ namespace Barotrauma.Items.Components
}
}
#endif
if (AITarget != null) AITarget.Enabled = value;
isActive = value;
}
}
private bool drawable = true;
public List<PropertyConditional> IsActiveConditionals;
public bool Drawable
{
get { return drawable; }
@@ -208,11 +209,6 @@ namespace Barotrauma.Items.Components
set;
}
public AITarget AITarget
{
get;
private set;
}
/// <summary>
/// How useful the item is in combat? Used by AI to decide which item it should use as a weapon. For the sake of clarity, use a value between 0 and 100 (not enforced).
@@ -267,6 +263,15 @@ namespace Barotrauma.Items.Components
{
switch (subElement.Name.ToString().ToLowerInvariant())
{
case "activeconditional":
case "isactive":
IsActiveConditionals = IsActiveConditionals ?? new List<PropertyConditional>();
foreach (XAttribute attribute in subElement.Attributes())
{
if (attribute.Name.ToString().ToLowerInvariant() == "targetitemcomponent") { continue; }
IsActiveConditionals.Add(new PropertyConditional(attribute));
}
break;
case "requireditem":
case "requireditems":
RelatedItem ri = RelatedItem.Load(subElement, item.Name);
@@ -308,12 +313,6 @@ namespace Barotrauma.Items.Components
effectList.Add(statusEffect);
break;
case "aitarget":
AITarget = new AITarget(item, subElement)
{
Enabled = isActive
};
break;
default:
if (LoadElemProjSpecific(subElement)) break;
@@ -474,12 +473,6 @@ namespace Barotrauma.Items.Components
delayedCorrectionCoroutine = null;
}
if (AITarget != null)
{
AITarget.Remove();
AITarget = null;
}
RemoveComponentSpecific();
}
@@ -496,11 +489,6 @@ namespace Barotrauma.Items.Components
loopingSoundChannel = null;
}
#endif
if (AITarget != null)
{
AITarget.Remove();
AITarget = null;
}
ShallowRemoveComponentSpecific();
}
@@ -788,6 +776,7 @@ namespace Barotrauma.Items.Components
public virtual void Reset()
{
SerializableProperties = SerializableProperty.DeserializeProperties(this, originalElement);
if (this is Pickable) { canBePicked = true; }
ParseMsg();
OverrideRequiredItems(originalElement);
}
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using System;
using System.Linq;
using System.Xml.Linq;
@@ -84,6 +83,8 @@ namespace Barotrauma.Items.Components
progressState = Math.Min(progressTimer / deconstructTime, 1.0f);
if (progressTimer > deconstructTime)
{
int emptySlots = outputContainer.Inventory.Items.Where(i => i == null).Count();
foreach (DeconstructItem deconstructProduct in targetItem.Prefab.DeconstructItems)
{
float percentageHealth = targetItem.Condition / targetItem.Prefab.Health;
@@ -100,13 +101,14 @@ namespace Barotrauma.Items.Components
itemPrefab.Health * deconstructProduct.OutCondition;
//container full, drop the items outside the deconstructor
if (outputContainer.Inventory.Items.All(i => i != null))
if (emptySlots <= 0)
{
Entity.Spawner.AddToSpawnQueue(itemPrefab, item.Position, item.Submarine, condition);
}
else
{
Entity.Spawner.AddToSpawnQueue(itemPrefab, outputContainer.Inventory, condition);
emptySlots--;
}
}
@@ -196,6 +198,7 @@ namespace Barotrauma.Items.Components
if (inputContainer.Inventory.Items.All(i => i == null)) { active = false; }
IsActive = active;
currPowerConsumption = IsActive ? powerConsumption : 0.0f;
#if SERVER
if (user != null)
@@ -3,7 +3,6 @@ using System;
using System.Globalization;
using System.Xml.Linq;
using Barotrauma.Networking;
using Lidgren.Network;
namespace Barotrauma.Items.Components
{
@@ -98,11 +97,17 @@ namespace Barotrauma.Items.Components
UpdatePropellerDamage(deltaTime);
if (item.AiTarget != null)
{
var aiTarget = item.AiTarget;
aiTarget.SoundRange = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, currForce.Length() / maxForce);
}
if (item.CurrentHull != null)
{
item.CurrentHull.AiTarget.SoundRange = Math.Max(currForce.Length(), item.CurrentHull.AiTarget.SoundRange);
var aiTarget = item.CurrentHull.AiTarget;
float noise = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, currForce.Length() / maxForce);
aiTarget.SoundRange = Math.Max(noise, aiTarget.SoundRange);
}
#if CLIENT
for (int i = 0; i < 5; i++)
{
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -12,6 +12,8 @@ namespace Barotrauma.Items.Components
private float maxFlow;
private float? targetLevel;
private float controlLockTimer;
private bool hasPower;
@@ -57,18 +59,24 @@ namespace Barotrauma.Items.Components
currFlow = 0.0f;
hasPower = false;
controlLockTimer -= deltaTime;
if (targetLevel != null)
{
float hullPercentage = 0.0f;
if (item.CurrentHull != null) hullPercentage = (item.CurrentHull.WaterVolume / item.CurrentHull.Volume) * 100.0f;
if (item.CurrentHull != null) { hullPercentage = (item.CurrentHull.WaterVolume / item.CurrentHull.Volume) * 100.0f; }
FlowPercentage = ((float)targetLevel - hullPercentage) * 10.0f;
if (controlLockTimer <= 0.0f)
{
targetLevel = null;
}
}
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 / item.MaxCondition);
if (voltage < minVoltage) return;
if (voltage < minVoltage) { return; }
UpdateProjSpecific(deltaTime);
@@ -109,6 +117,7 @@ namespace Barotrauma.Items.Components
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempSpeed))
{
flowPercentage = MathHelper.Clamp(tempSpeed, -100.0f, 100.0f);
controlLockTimer = 0.1f;
}
}
else if (connection.Name == "set_targetlevel")
@@ -116,6 +125,7 @@ namespace Barotrauma.Items.Components
if (float.TryParse(signal, NumberStyles.Any, CultureInfo.InvariantCulture, out float tempTarget))
{
targetLevel = MathHelper.Clamp((tempTarget + 100.0f) / 2.0f, 0.0f, 100.0f);
controlLockTimer = 0.1f;
}
}
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -271,7 +270,7 @@ namespace Barotrauma.Items.Components
//calculate how much external power there is in the grid
//(power coming from somewhere else than this reactor, e.g. batteries)
float externalPower = CurrPowerConsumption - pt.CurrPowerConsumption;
float externalPower = Math.Max(CurrPowerConsumption - pt.CurrPowerConsumption, 0);
//reduce the external power from the load to prevent overloading the grid
load = Math.Max(load, pt.PowerLoad - externalPower);
}
@@ -288,10 +287,17 @@ namespace Barotrauma.Items.Components
if (item.CurrentHull != null)
{
//the sound can be heard from 20 000 display units away when running at full power
item.CurrentHull.SoundRange = Math.Max(
(-currPowerConsumption / MaxPowerOutput) * 20000.0f,
item.CurrentHull.AiTarget.SoundRange);
var aiTarget = item.CurrentHull.AiTarget;
float range = Math.Abs(currPowerConsumption) / MaxPowerOutput;
float noise = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, range);
aiTarget.SoundRange = Math.Max(aiTarget.SoundRange, noise);
}
if (item.AiTarget != null)
{
var aiTarget = item.AiTarget;
float range = Math.Abs(currPowerConsumption) / MaxPowerOutput;
aiTarget.SoundRange = MathHelper.Lerp(aiTarget.MinSoundRange, aiTarget.MaxSoundRange, range);
}
}
@@ -439,6 +445,8 @@ namespace Barotrauma.Items.Components
{
base.UpdateBroken(deltaTime, cam);
item.SendSignal(0, ((int)(temperature * 100.0f)).ToString(), "temperature_out", null);
currPowerConsumption = 0.0f;
Temperature -= deltaTime * 1000.0f;
targetFissionRate = Math.Max(targetFissionRate - deltaTime * 10.0f, 0.0f);
@@ -114,9 +114,9 @@ namespace Barotrauma.Items.Components
if (value == Mode.Passive)
{
currentPingIndex = -1;
if (item.CurrentHull != null)
if (item.AiTarget != null)
{
item.CurrentHull.AiTarget.SectorDegrees = 360.0f;
item.AiTarget.SectorDegrees = 360.0f;
}
}
#if CLIENT
@@ -168,15 +168,10 @@ namespace Barotrauma.Items.Components
var activePing = activePings[currentPingIndex];
if (activePing.State > 1.0f)
{
if (item.CurrentHull != null)
{
item.CurrentHull.AiTarget.SoundRange = Math.Max(Range * activePing.State / zoom, item.CurrentHull.AiTarget.SoundRange);
item.CurrentHull.AiTarget.SectorDegrees = activePing.IsDirectional ? DirectionalPingSector : 360.0f;
item.CurrentHull.AiTarget.SectorDir = new Vector2(pingDirection.X, -pingDirection.Y);
}
if (item.AiTarget != null)
{
item.AiTarget.SoundRange = Math.Max(Range * activePing.State / zoom, item.AiTarget.SoundRange);
float range = MathUtils.InverseLerp(item.AiTarget.MinSoundRange, item.AiTarget.MaxSoundRange, Range * activePing.State / zoom);
item.AiTarget.SoundRange = MathHelper.Lerp(item.AiTarget.MinSoundRange, item.AiTarget.MaxSoundRange, range);
item.AiTarget.SectorDegrees = activePing.IsDirectional ? DirectionalPingSector : 360.0f;
item.AiTarget.SectorDir = new Vector2(pingDirection.X, -pingDirection.Y);
}
@@ -200,9 +195,9 @@ namespace Barotrauma.Items.Components
}
else
{
if (item.CurrentHull != null)
if (item.AiTarget != null)
{
item.CurrentHull.AiTarget.SectorDegrees = 360.0f;
item.AiTarget.SectorDegrees = 360.0f;
}
currentPingIndex = -1;
aiPingCheckPending = false;
@@ -345,7 +340,7 @@ namespace Barotrauma.Items.Components
}
}
public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Client c)
public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
{
bool isActive = msg.ReadBoolean();
bool directionalPing = useDirectionalPing;
@@ -388,7 +383,7 @@ namespace Barotrauma.Items.Components
#endif
}
public void ServerWrite(Lidgren.Network.NetBuffer msg, Client c, object[] extraData = null)
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
msg.Write(currentMode == Mode.Active);
if (currentMode == Mode.Active)
@@ -522,7 +522,7 @@ namespace Barotrauma.Items.Components
}
}
public void ServerRead(ClientNetObject type, Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c)
public void ServerRead(ClientNetObject type, IReadMessage msg, Barotrauma.Networking.Client c)
{
bool autoPilot = msg.ReadBoolean();
bool dockingButtonClicked = msg.ReadBoolean();
@@ -537,8 +537,8 @@ namespace Barotrauma.Items.Components
if (maintainPos)
{
newPosToMaintain = new Vector2(
msg.ReadFloat(),
msg.ReadFloat());
msg.ReadSingle(),
msg.ReadSingle());
}
else
{
@@ -547,7 +547,7 @@ namespace Barotrauma.Items.Components
}
else
{
newSteeringInput = new Vector2(msg.ReadFloat(), msg.ReadFloat());
newSteeringInput = new Vector2(msg.ReadSingle(), msg.ReadSingle());
}
if (!item.CanClientAccess(c)) return;
@@ -587,7 +587,7 @@ namespace Barotrauma.Items.Components
unsentChanges = true;
}
public void ServerWrite(Lidgren.Network.NetBuffer msg, Barotrauma.Networking.Client c, object[] extraData = null)
public void ServerWrite(IWriteMessage msg, Barotrauma.Networking.Client c, object[] extraData = null)
{
msg.Write(autoPilot);
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -64,6 +64,13 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(false, false)]
public bool Overload
{
get;
set;
}
//can the component transfer power
private bool canTransfer;
public bool CanTransfer
@@ -115,6 +122,8 @@ namespace Barotrauma.Items.Components
{
base.UpdateBroken(deltaTime, cam);
Overload = false;
if (!isBroken)
{
powerLoad = 0.0f;
@@ -128,7 +137,8 @@ namespace Barotrauma.Items.Components
public override void Update(float deltaTime, Camera cam)
{
RefreshConnections();
if (!CanTransfer) return;
if (!CanTransfer) { return; }
if (isBroken)
{
@@ -143,6 +153,8 @@ namespace Barotrauma.Items.Components
return;
}
Overload = false;
//reset and recalculate the power generated/consumed
//by the constructions connected to the grid
fullPower = 0.0f;
@@ -156,10 +168,11 @@ namespace Barotrauma.Items.Components
foreach (Powered p in connectedList)
{
PowerTransfer pt = p as PowerTransfer;
if (pt == null || pt.updateCount == 0) continue;
if (pt == null || pt.updateCount == 0) { continue; }
if (pt is RelayComponent != this is RelayComponent) continue;
if (pt is RelayComponent != this is RelayComponent) { continue; }
pt.Overload = false;
pt.powerLoad += (fullLoad - pt.powerLoad) / inertia;
pt.currPowerConsumption += (-fullPower - pt.currPowerConsumption) / inertia;
@@ -173,38 +186,38 @@ 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(OverloadVoltage * 0.75f, OverloadVoltage, item.Condition / item.MaxCondition);
float maxOverVoltage = MathHelper.Lerp(OverloadVoltage * 0.75f, OverloadVoltage, pt.item.Condition / pt.item.MaxCondition);
maxOverVoltage = Math.Max(OverloadVoltage, 1.0f);
//if the item can't be fixed, don't allow it to break
if (!item.Repairables.Any() || !CanBeOverloaded) continue;
if (!pt.item.Repairables.Any() || !pt.CanBeOverloaded) { continue; }
//relays don't blow up if the power is higher than load, only if the output is high enough
//(i.e. enough power passing through the relay)
if (this is RelayComponent) continue;
if (pt is RelayComponent) { continue; }
if (-pt.currPowerConsumption < Math.Max(pt.powerLoad, 200.0f) * maxOverVoltage) continue;
if (-pt.currPowerConsumption < Math.Max(pt.powerLoad, 200.0f) * maxOverVoltage) { continue; }
pt.Overload = true;
#if CLIENT
//damage the item if voltage is too high
//(except if running as a client)
if (GameMain.Client != null) { continue; }
#endif
float prevCondition = pt.item.Condition;
pt.item.Condition -= deltaTime * 10.0f;
if (pt.item.Condition <= 0.0f && prevCondition > 0.0f)
{
#if CLIENT
SoundPlayer.PlaySound("zap", item.WorldPosition, hullGuess: item.CurrentHull);
SoundPlayer.PlaySound("zap", item.WorldPosition, hullGuess: pt.item.CurrentHull);
Vector2 baseVel = Rand.Vector(300.0f);
for (int i = 0; i < 10; i++)
{
var particle = GameMain.ParticleManager.CreateParticle("spark", pt.item.WorldPosition,
baseVel + Rand.Vector(100.0f), 0.0f, item.CurrentHull);
baseVel + Rand.Vector(100.0f), 0.0f, pt.item.CurrentHull);
if (particle != null) particle.Size *= Rand.Range(0.5f, 1.0f);
}
@@ -214,8 +227,8 @@ namespace Barotrauma.Items.Components
GameMain.GameSession.EventManager.CurrentIntensity : 0.5f;
//higher probability for fires if the current intensity is low
if (FireProbability > 0.0f &&
Rand.Range(0.0f, 1.0f) < MathHelper.Lerp(FireProbability, FireProbability * 0.1f, currentIntensity))
if (pt.FireProbability > 0.0f &&
Rand.Range(0.0f, 1.0f) < MathHelper.Lerp(pt.FireProbability, pt.FireProbability * 0.1f, currentIntensity))
{
new FireSource(pt.item.WorldPosition);
}
@@ -409,11 +409,11 @@ namespace Barotrauma.Items.Components
private bool OnProjectileCollision(Fixture target, Vector2 collisionNormal)
{
if (User != null && User.Removed) User = null;
if (User != null && User.Removed) { User = null; }
if (IgnoredBodies.Contains(target.Body)) return false;
if (IgnoredBodies.Contains(target.Body)) { return false; }
if (target.UserData is Item) return false;
if (target.UserData is Item) { return false; }
if (target.CollisionCategories == Physics.CollisionCharacter && !(target.Body.UserData is Limb))
{
@@ -447,10 +447,21 @@ namespace Barotrauma.Items.Components
if (attack != null) { attackResult = attack.DoDamage(User, structure, item.WorldPosition, 1.0f); }
}
if (character != null) character.LastDamageSource = item;
ApplyStatusEffects(ActionType.OnUse, 1.0f, character, target.Body.UserData as Limb, user: user);
ApplyStatusEffects(ActionType.OnImpact, 1.0f, character, target.Body.UserData as Limb, user: user);
if (character != null) { character.LastDamageSource = item; }
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
{
ApplyStatusEffects(ActionType.OnUse, 1.0f, character, target.Body.UserData as Limb, user: user);
ApplyStatusEffects(ActionType.OnImpact, 1.0f, character, target.Body.UserData as Limb, user: user);
#if SERVER
if (GameMain.NetworkMember.IsServer)
{
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnUse });
GameMain.Server?.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ApplyStatusEffect, ActionType.OnImpact });
}
#endif
}
item.body.FarseerBody.OnCollision -= OnProjectileCollision;
item.body.CollisionCategories = Physics.CollisionItem;
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Linq;
@@ -10,12 +9,15 @@ namespace Barotrauma.Items.Components
partial class Repairable : ItemComponent, IServerSerializable, IClientSerializable
{
public static float SkillIncreasePerRepair = 5.0f;
public static float SkillIncreasePerSabotage = 3.0f;
private string header;
private float deteriorationTimer;
private float deteriorateAlwaysResetTimer;
bool wasBroken;
bool wasGoodCondition;
public float LastActiveTime;
@@ -40,14 +42,21 @@ namespace Barotrauma.Items.Components
set;
}
[Serialize(50.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, ToolTip = "The item won't deteriorate spontaneously if the condition is below this value. For example, if set to 10, the condition will spontaneously drop to 10 and then stop dropping (unless the item is damaged further by external factors).")]
[Serialize(50.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, ToolTip = "The item won't deteriorate spontaneously if the condition is below this value. For example, if set to 10, the condition will spontaneously drop to 10 and then stop dropping (unless the item is damaged further by external factors). Percentages of max condition.")]
public float MinDeteriorationCondition
{
get;
set;
}
[Serialize(80.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, ToolTip = "The condition of the item has to be below this before the repair UI becomes usable.")]
[Serialize(0f, true)]
public float MinSabotageCondition
{
get;
set;
}
[Serialize(80.0f, true), Editable(MinValueFloat = 0.0f, MaxValueFloat = 100.0f, ToolTip = "The condition of the item has to be below this before the repair UI becomes usable. Percentages of max condition.")]
public float ShowRepairUIThreshold
{
get;
@@ -76,16 +85,20 @@ namespace Barotrauma.Items.Components
set;
}
private Character currentFixer;
public Character CurrentFixer
public Character CurrentFixer { get; private set; }
public enum FixActions : int
{
get { return currentFixer; }
set
{
if (currentFixer == value || item.IsFullCondition) return;
if (currentFixer != null) currentFixer.AnimController.Anim = AnimController.Animation.None;
currentFixer = value;
}
None = 0,
Repair = 1,
Sabotage = 2
}
private FixActions currentFixerAction = FixActions.None;
public FixActions CurrentFixerAction
{
get => currentFixerAction;
private set { currentFixerAction = value; }
}
public Repairable(Item item, XElement element)
@@ -105,18 +118,41 @@ 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);
public void StartRepairing(Character character)
public bool StartRepairing(Character character, FixActions action)
{
CurrentFixer = character;
if (character == null || character.IsDead || action == FixActions.None)
{
DebugConsole.ThrowError("Invalid repair command!");
return false;
}
else
{
CurrentFixer = character;
CurrentFixerAction = action;
return true;
}
}
public bool StopRepairing(Character character)
{
if (CurrentFixer == character)
{
CurrentFixer.AnimController.Anim = AnimController.Animation.None;
CurrentFixer = null;
currentFixerAction = FixActions.None;
#if SERVER
item.CreateServerEvent(this);
#endif
return true;
}
else
{
return false;
}
}
public override void UpdateBroken(float deltaTime, Camera cam)
@@ -129,7 +165,7 @@ namespace Barotrauma.Items.Components
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
item.Condition = item.Prefab.Health;
#if SERVER
//let the clients know the initial deterioration delay
//let the clients know the deterioration delay
item.CreateServerEvent(this);
#endif
}
@@ -140,6 +176,18 @@ namespace Barotrauma.Items.Components
if (CurrentFixer == null)
{
if (deteriorateAlwaysResetTimer > 0.0f)
{
deteriorateAlwaysResetTimer -= deltaTime;
if (deteriorateAlwaysResetTimer <= 0.0f)
{
DeteriorateAlways = false;
#if SERVER
//let the clients know the deterioration delay
item.CreateServerEvent(this);
#endif
}
}
if (!ShouldDeteriorate()) { return; }
if (item.Condition > 0.0f)
{
@@ -155,7 +203,7 @@ namespace Barotrauma.Items.Components
return;
}
if (item.Condition > MinDeteriorationCondition)
if (item.ConditionPercentage > MinDeteriorationCondition)
{
item.Condition -= DeteriorationSpeed * deltaTime;
}
@@ -163,10 +211,9 @@ namespace Barotrauma.Items.Components
return;
}
if (Item.IsFullCondition || CurrentFixer.SelectedConstruction != item || !currentFixer.CanInteractWith(item))
if (CurrentFixer != null && (CurrentFixer.SelectedConstruction != item || !CurrentFixer.CanInteractWith(item) || CurrentFixer.IsDead))
{
currentFixer.AnimController.Anim = AnimController.Animation.None;
currentFixer = null;
StopRepairing(CurrentFixer);
return;
}
@@ -177,44 +224,89 @@ namespace Barotrauma.Items.Components
float successFactor = requiredSkills.Count == 0 ? 1.0f : 0.0f;
//item must have been below the repair threshold for the player to get an achievement or XP for repairing it
if (item.Condition < ShowRepairUIThreshold)
if (item.ConditionPercentage < ShowRepairUIThreshold)
{
wasBroken = true;
}
if (item.ConditionPercentage > MinSabotageCondition)
{
wasGoodCondition = true;
}
float fixDuration = MathHelper.Lerp(FixDurationLowSkill, FixDurationHighSkill, successFactor);
if (fixDuration <= 0.0f)
if (currentFixerAction == FixActions.Repair)
{
item.Condition = item.MaxCondition;
if (fixDuration <= 0.0f)
{
item.Condition = item.MaxCondition;
}
else
{
float conditionIncrease = deltaTime / (fixDuration / item.MaxCondition);
item.Condition += conditionIncrease;
#if SERVER
GameMain.Server.KarmaManager.OnItemRepaired(CurrentFixer, this, conditionIncrease);
#endif
}
if (item.IsFullCondition)
{
if (wasBroken)
{
foreach (Skill skill in requiredSkills)
{
float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier);
CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier,
SkillIncreasePerRepair / Math.Max(characterSkillLevel, 1.0f),
CurrentFixer.WorldPosition + Vector2.UnitY * 100.0f);
}
SteamAchievementManager.OnItemRepaired(item, CurrentFixer);
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
wasBroken = false;
}
StopRepairing(CurrentFixer);
}
}
else if (currentFixerAction == FixActions.Sabotage)
{
if (fixDuration <= 0.0f)
{
item.Condition = item.MaxCondition * (MinSabotageCondition / 100);
}
else
{
float conditionDecrease = deltaTime / (fixDuration / item.MaxCondition);
item.Condition -= conditionDecrease;
}
if (item.ConditionPercentage <= MinSabotageCondition)
{
if (wasGoodCondition)
{
foreach (Skill skill in requiredSkills)
{
float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier);
CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier,
SkillIncreasePerSabotage / Math.Max(characterSkillLevel, 1.0f),
CurrentFixer.WorldPosition + Vector2.UnitY * 100.0f);
}
deteriorationTimer = 0.0f;
deteriorateAlwaysResetTimer = item.Condition / DeteriorationSpeed;
DeteriorateAlways = true;
item.Condition = item.MaxCondition * (MinSabotageCondition / 100);
wasGoodCondition = false;
}
StopRepairing(CurrentFixer);
}
}
else
{
float conditionIncrease = deltaTime / (fixDuration / item.MaxCondition);
item.Condition += conditionIncrease;
#if SERVER
GameMain.Server.KarmaManager.OnItemRepaired(CurrentFixer, this, conditionIncrease);
#endif
}
if (wasBroken && item.IsFullCondition)
{
foreach (Skill skill in requiredSkills)
{
float characterSkillLevel = CurrentFixer.GetSkillLevel(skill.Identifier);
CurrentFixer.Info.IncreaseSkillLevel(skill.Identifier,
SkillIncreasePerRepair / Math.Max(characterSkillLevel, 1.0f),
CurrentFixer.WorldPosition + Vector2.UnitY * 100.0f);
}
SteamAchievementManager.OnItemRepaired(item, currentFixer);
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
wasBroken = false;
#if SERVER
item.CreateServerEvent(this);
#endif
throw new NotImplementedException(currentFixerAction.ToString());
}
}
partial void UpdateProjSpecific(float deltaTime);
private bool ShouldDeteriorate()
@@ -218,6 +218,16 @@ namespace Barotrauma.Items.Components
public void SetWire(int index, Wire wire)
{
Wire previousWire = wires[index];
if (wire != previousWire && previousWire != null)
{
var otherConnection = previousWire.OtherConnection(this);
if (otherConnection != null)
{
otherConnection.recipientsDirty = true;
}
}
wires[index] = wire;
recipientsDirty = true;
if (wire != null)
@@ -1,6 +1,5 @@
using Barotrauma.Networking;
using FarseerPhysics;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -19,7 +18,9 @@ namespace Barotrauma.Items.Components
/// Wires that have been disconnected from the panel, but not removed completely (visible at the bottom of the connection panel).
/// </summary>
public readonly HashSet<Wire> DisconnectedWires = new HashSet<Wire>();
private List<ushort> disconnectedWireIds;
[Serialize(false, true), Editable(ToolTip = "Locked connection panels cannot be rewired in-game.")]
public bool Locked
{
@@ -64,6 +65,19 @@ namespace Barotrauma.Items.Components
{
c.ConnectLinked();
}
if (disconnectedWireIds != null)
{
foreach (ushort disconnectedWireId in disconnectedWireIds)
{
if (!(Entity.FindEntityByID(disconnectedWireId) is Item wireItem)) { continue; }
Wire wire = wireItem.GetComponent<Wire>();
if (wire != null)
{
DisconnectedWires.Add(wire);
}
}
}
}
public override void OnItemLoaded()
@@ -193,6 +207,8 @@ namespace Barotrauma.Items.Components
{
loadedConnections[i].wireId.CopyTo(Connections[i].wireId, 0);
}
disconnectedWireIds = element.GetAttributeUshortArray("disconnectedwires", new ushort[0]).ToList();
}
public override XElement Save(XElement parentElement)
@@ -204,6 +220,11 @@ namespace Barotrauma.Items.Components
c.Save(componentElement);
}
if (DisconnectedWires.Count > 0)
{
componentElement.Add(new XAttribute("disconnectedwires", string.Join(",", DisconnectedWires.Select(w => w.Item.ID))));
}
return componentElement;
}
@@ -214,6 +235,14 @@ namespace Barotrauma.Items.Components
protected override void RemoveComponentSpecific()
{
foreach (Wire wire in DisconnectedWires.ToList())
{
if (wire.OtherConnection(null) == null) //wire not connected to anything else
{
wire.Item.Drop(null);
}
}
DisconnectedWires.Clear();
foreach (Connection c in Connections)
{
@@ -233,7 +262,7 @@ namespace Barotrauma.Items.Components
}
}
public void ClientWrite(NetBuffer msg, object[] extraData = null)
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
{
foreach (Connection connection in Connections)
{
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
@@ -2,7 +2,6 @@
using System;
using System.Xml.Linq;
using Barotrauma.Networking;
using Lidgren.Network;
#if CLIENT
using Microsoft.Xna.Framework.Graphics;
using Barotrauma.Lights;
@@ -251,10 +250,6 @@ namespace Barotrauma.Items.Components
light.Range = range;
#endif
}
if (AITarget != null)
{
UpdateAITarget(AITarget);
}
if (item.AiTarget != null)
{
UpdateAITarget(item.AiTarget);
@@ -267,6 +262,7 @@ namespace Barotrauma.Items.Components
public override void UpdateBroken(float deltaTime, Camera cam)
{
light.Color = Color.Transparent;
lightBrightness = 0.0f;
}
protected override void RemoveComponentSpecific()
@@ -298,7 +294,7 @@ namespace Barotrauma.Items.Components
}
}
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
msg.Write(IsOn);
}
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using System;
using System.Collections.Generic;
using System.Xml.Linq;
@@ -104,12 +103,12 @@ namespace Barotrauma.Items.Components
IsOn = on;
}
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
msg.Write(isOn);
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
SetState(msg.ReadBoolean(), true);
}
@@ -1,5 +1,4 @@
using Barotrauma.Networking;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -282,7 +281,7 @@ namespace Barotrauma.Items.Components
Structure attachTarget = Structure.GetAttachTarget(item.WorldPosition);
canPlaceNode = attachTarget != null;
sub = attachTarget?.Submarine;
sub = sub ?? attachTarget?.Submarine;
newNodePos = sub == null ?
item.WorldPosition :
item.WorldPosition - sub.Position - sub.HiddenSubPosition;
@@ -333,7 +332,8 @@ namespace Barotrauma.Items.Components
}
else
{
newNodePos = RoundNode(item.Position, item.CurrentHull) - sub.HiddenSubPosition;
newNodePos = RoundNode(item.Position, item.CurrentHull);
if (sub != null) { newNodePos -= sub.HiddenSubPosition; }
canPlaceNode = true;
}
@@ -724,7 +724,7 @@ namespace Barotrauma.Items.Components
base.RemoveComponentSpecific();
}
public void ClientRead(ServerNetObject type, NetBuffer msg, float sendingTime)
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
{
int eventIndex = msg.ReadRangedInteger(0, (int)Math.Ceiling(MaxNodeCount / (float)MaxNodesPerNetworkEvent));
int nodeCount = msg.ReadRangedInteger(0, MaxNodesPerNetworkEvent);
@@ -738,7 +738,7 @@ namespace Barotrauma.Items.Components
for (int i = 0; i < nodeCount; i++)
{
nodePositions[nodeStartIndex + i] = new Vector2(msg.ReadFloat(), msg.ReadFloat());
nodePositions[nodeStartIndex + i] = new Vector2(msg.ReadSingle(), msg.ReadSingle());
}
if (nodePositions.Any(n => !MathUtils.IsValid(n)))
@@ -1,6 +1,5 @@
using Barotrauma.Networking;
using FarseerPhysics;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -674,7 +673,7 @@ namespace Barotrauma.Items.Components
}
}
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
{
Item item = (Item)extraData[2];
msg.Write(item.Removed ? (ushort)0 : item.ID);