(965c31410a) Unstable v0.10.4.0
This commit is contained in:
@@ -25,9 +25,6 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private readonly Hull[] hulls = new Hull[2];
|
||||
private Gap gap;
|
||||
|
||||
private Door door;
|
||||
|
||||
private Body[] bodies;
|
||||
private Fixture outsideBlocker;
|
||||
private Body doorBody;
|
||||
@@ -68,6 +65,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public DockingPort DockingTarget { get; private set; }
|
||||
|
||||
public Door Door { get; private set; }
|
||||
|
||||
public bool Docked
|
||||
{
|
||||
get
|
||||
@@ -208,7 +207,7 @@ namespace Barotrauma.Items.Components
|
||||
CreateJoint(false);
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
if (GameMain.Server != null && (!item.Submarine?.Loading ?? true))
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
@@ -250,7 +249,7 @@ namespace Barotrauma.Items.Components
|
||||
CreateJoint(true);
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
if (GameMain.Server != null && (!item.Submarine?.Loading ?? true))
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
@@ -272,10 +271,10 @@ namespace Barotrauma.Items.Components
|
||||
CreateHulls();
|
||||
}
|
||||
|
||||
if (door != null && DockingTarget.door != null)
|
||||
if (Door != null && DockingTarget.Door != null)
|
||||
{
|
||||
WayPoint myWayPoint = WayPoint.WayPointList.Find(wp => door.LinkedGap == wp.ConnectedGap);
|
||||
WayPoint targetWayPoint = WayPoint.WayPointList.Find(wp => DockingTarget.door.LinkedGap == wp.ConnectedGap);
|
||||
WayPoint myWayPoint = WayPoint.WayPointList.Find(wp => Door.LinkedGap == wp.ConnectedGap);
|
||||
WayPoint targetWayPoint = WayPoint.WayPointList.Find(wp => DockingTarget.Door.LinkedGap == wp.ConnectedGap);
|
||||
|
||||
if (myWayPoint != null && targetWayPoint != null)
|
||||
{
|
||||
@@ -333,19 +332,19 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (DockingDir != 0) { return DockingDir; }
|
||||
|
||||
if (door != null)
|
||||
if (Door != null)
|
||||
{
|
||||
if (door.LinkedGap.linkedTo.Count == 1)
|
||||
if (Door.LinkedGap.linkedTo.Count == 1)
|
||||
{
|
||||
return IsHorizontal ?
|
||||
Math.Sign(door.Item.WorldPosition.X - door.LinkedGap.linkedTo[0].WorldPosition.X) :
|
||||
Math.Sign(door.Item.WorldPosition.Y - door.LinkedGap.linkedTo[0].WorldPosition.Y);
|
||||
Math.Sign(Door.Item.WorldPosition.X - Door.LinkedGap.linkedTo[0].WorldPosition.X) :
|
||||
Math.Sign(Door.Item.WorldPosition.Y - Door.LinkedGap.linkedTo[0].WorldPosition.Y);
|
||||
}
|
||||
else if (dockingTarget?.door?.LinkedGap != null && dockingTarget.door.LinkedGap.linkedTo.Count == 1)
|
||||
else if (dockingTarget?.Door?.LinkedGap != null && dockingTarget.Door.LinkedGap.linkedTo.Count == 1)
|
||||
{
|
||||
return IsHorizontal ?
|
||||
Math.Sign(dockingTarget.door.LinkedGap.linkedTo[0].WorldPosition.X - dockingTarget.door.Item.WorldPosition.X) :
|
||||
Math.Sign(dockingTarget.door.LinkedGap.linkedTo[0].WorldPosition.Y - dockingTarget.door.Item.WorldPosition.Y);
|
||||
Math.Sign(dockingTarget.Door.LinkedGap.linkedTo[0].WorldPosition.X - dockingTarget.Door.Item.WorldPosition.X) :
|
||||
Math.Sign(dockingTarget.Door.LinkedGap.linkedTo[0].WorldPosition.Y - dockingTarget.Door.Item.WorldPosition.Y);
|
||||
}
|
||||
}
|
||||
if (dockingTarget != null)
|
||||
@@ -367,24 +366,23 @@ namespace Barotrauma.Items.Components
|
||||
private void ConnectWireBetweenPorts()
|
||||
{
|
||||
Wire wire = item.GetComponent<Wire>();
|
||||
if (wire == null) return;
|
||||
if (wire == null) { return; }
|
||||
|
||||
wire.Hidden = true;
|
||||
wire.Locked = true;
|
||||
wire.Hidden = true;
|
||||
|
||||
if (Item.Connections == null) return;
|
||||
if (Item.Connections == null) { return; }
|
||||
|
||||
var powerConnection = Item.Connections.Find(c => c.IsPower);
|
||||
if (powerConnection == null) return;
|
||||
if (powerConnection == null) { return; }
|
||||
|
||||
if (DockingTarget == null || DockingTarget.item.Connections == null) return;
|
||||
if (DockingTarget == null || DockingTarget.item.Connections == null) { return; }
|
||||
var recipient = DockingTarget.item.Connections.Find(c => c.IsPower);
|
||||
if (recipient == null) return;
|
||||
if (recipient == null) { return; }
|
||||
|
||||
wire.RemoveConnection(item);
|
||||
wire.RemoveConnection(DockingTarget.item);
|
||||
|
||||
|
||||
powerConnection.TryAddLink(wire);
|
||||
wire.Connect(powerConnection, false, false);
|
||||
recipient.TryAddLink(wire);
|
||||
@@ -399,13 +397,13 @@ namespace Barotrauma.Items.Components
|
||||
doorBody = null;
|
||||
}
|
||||
|
||||
Vector2 position = ConvertUnits.ToSimUnits(item.Position + (DockingTarget.door.Item.WorldPosition - item.WorldPosition));
|
||||
Vector2 position = ConvertUnits.ToSimUnits(item.Position + (DockingTarget.Door.Item.WorldPosition - item.WorldPosition));
|
||||
if (!MathUtils.IsValid(position))
|
||||
{
|
||||
string errorMsg =
|
||||
"Attempted to create a door body at an invalid position (item pos: " + item.Position
|
||||
+ ", item world pos: " + item.WorldPosition
|
||||
+ ", docking target world pos: " + DockingTarget.door.Item.WorldPosition + ")\n" + Environment.StackTrace;
|
||||
+ ", docking target world pos: " + DockingTarget.Door.Item.WorldPosition + ")\n" + Environment.StackTrace;
|
||||
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
@@ -418,11 +416,11 @@ namespace Barotrauma.Items.Components
|
||||
System.Diagnostics.Debug.Assert(doorBody == null);
|
||||
|
||||
doorBody = GameMain.World.CreateRectangle(
|
||||
DockingTarget.door.Body.width,
|
||||
DockingTarget.door.Body.height,
|
||||
DockingTarget.Door.Body.width,
|
||||
DockingTarget.Door.Body.height,
|
||||
1.0f,
|
||||
position);
|
||||
doorBody.UserData = DockingTarget.door;
|
||||
doorBody.UserData = DockingTarget.Door;
|
||||
doorBody.CollisionCategories = Physics.CollisionWall;
|
||||
doorBody.BodyType = BodyType.Static;
|
||||
}
|
||||
@@ -434,12 +432,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
bodies = new Body[4];
|
||||
|
||||
if (DockingTarget.door != null)
|
||||
if (DockingTarget.Door != null)
|
||||
{
|
||||
CreateDoorBody();
|
||||
}
|
||||
|
||||
if (door != null)
|
||||
if (Door != null)
|
||||
{
|
||||
DockingTarget.CreateDoorBody();
|
||||
}
|
||||
@@ -718,7 +716,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
Gap doorGap = i == 0 ? door?.LinkedGap : DockingTarget?.door?.LinkedGap;
|
||||
Gap doorGap = i == 0 ? Door?.LinkedGap : DockingTarget?.Door?.LinkedGap;
|
||||
if (doorGap == null) continue;
|
||||
doorGap.DisableHullRechecks = true;
|
||||
if (doorGap.linkedTo.Count >= 2) continue;
|
||||
@@ -773,10 +771,10 @@ namespace Barotrauma.Items.Components
|
||||
DockingTarget.item.Submarine.ConnectedDockingPorts.Remove(item.Submarine);
|
||||
item.Submarine.ConnectedDockingPorts.Remove(DockingTarget.item.Submarine);
|
||||
|
||||
if (door != null && DockingTarget.door != null)
|
||||
if (Door != null && DockingTarget.Door != null)
|
||||
{
|
||||
WayPoint myWayPoint = WayPoint.WayPointList.Find(wp => door.LinkedGap == wp.ConnectedGap);
|
||||
WayPoint targetWayPoint = WayPoint.WayPointList.Find(wp => DockingTarget.door.LinkedGap == wp.ConnectedGap);
|
||||
WayPoint myWayPoint = WayPoint.WayPointList.Find(wp => Door.LinkedGap == wp.ConnectedGap);
|
||||
WayPoint targetWayPoint = WayPoint.WayPointList.Find(wp => DockingTarget.Door.LinkedGap == wp.ConnectedGap);
|
||||
|
||||
if (myWayPoint != null && targetWayPoint != null)
|
||||
{
|
||||
@@ -838,7 +836,7 @@ namespace Barotrauma.Items.Components
|
||||
obstructedWayPointsDisabled = false;
|
||||
|
||||
#if SERVER
|
||||
if (GameMain.Server != null)
|
||||
if (GameMain.Server != null && (!item.Submarine?.Loading ?? true))
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
@@ -908,9 +906,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DockingTarget.door != null && doorBody != null)
|
||||
if (DockingTarget.Door != null && doorBody != null)
|
||||
{
|
||||
doorBody.Enabled = DockingTarget.door.Body.Enabled;
|
||||
doorBody.Enabled = DockingTarget.Door.Body.Enabled;
|
||||
}
|
||||
|
||||
item.SendSignal(0, "1", "state_out", null);
|
||||
@@ -927,6 +925,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
list.Remove(this);
|
||||
hulls[0]?.Remove(); hulls[0] = null;
|
||||
hulls[1]?.Remove(); hulls[1] = null;
|
||||
@@ -953,7 +952,7 @@ namespace Barotrauma.Items.Components
|
||||
float distSqr = Vector2.DistanceSquared(item.Position, it.Position);
|
||||
if (distSqr < closestDist)
|
||||
{
|
||||
door = doorComponent;
|
||||
Door = doorComponent;
|
||||
closestDist = distSqr;
|
||||
}
|
||||
}
|
||||
@@ -982,7 +981,18 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
InitializeLinks();
|
||||
|
||||
if (!item.linkedTo.Any()) return;
|
||||
Wire wire = item.GetComponent<Wire>();
|
||||
if (wire != null)
|
||||
{
|
||||
wire.Locked = true;
|
||||
wire.Hidden = true;
|
||||
if (wire.Connections.Contains(null))
|
||||
{
|
||||
wire.Drop(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.linkedTo.Any()) { return; }
|
||||
|
||||
List<MapEntity> linked = new List<MapEntity>(item.linkedTo);
|
||||
foreach (MapEntity entity in linked)
|
||||
@@ -995,6 +1005,7 @@ namespace Barotrauma.Items.Components
|
||||
Dock(dockingPort);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power = 0.0f, float signalStrength = 1.0f)
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float RepairThreshold
|
||||
{
|
||||
get { return item.GetComponent<Repairable>() == null ? 0.0f : item.Prefab.Health; }
|
||||
get { return item.GetComponent<Repairable>() == null ? 0.0f : item.MaxCondition; }
|
||||
}
|
||||
|
||||
public bool CanBeWelded = true;
|
||||
@@ -185,7 +185,10 @@ namespace Barotrauma.Items.Components
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
|
||||
[Serialize(true, true, description: ""), Editable]
|
||||
public bool UseBetweenOutpostModules { get; private set; }
|
||||
|
||||
public Door(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -419,8 +422,8 @@ namespace Barotrauma.Items.Components
|
||||
linkedGap.Open = 1.0f;
|
||||
IsOpen = false;
|
||||
#if CLIENT
|
||||
if (convexHull != null) convexHull.Enabled = false;
|
||||
if (convexHull2 != null) convexHull2.Enabled = false;
|
||||
if (convexHull != null) { convexHull.Enabled = false; }
|
||||
if (convexHull2 != null) { convexHull2.Enabled = false; }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -469,6 +472,14 @@ namespace Barotrauma.Items.Components
|
||||
Body.Remove();
|
||||
Body = null;
|
||||
}
|
||||
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
if (gap.ConnectedDoor == this)
|
||||
{
|
||||
gap.ConnectedDoor = null;
|
||||
}
|
||||
}
|
||||
|
||||
//no need to remove the gap if we're unloading the whole submarine
|
||||
//otherwise the gap will be removed twice and cause console warnings
|
||||
@@ -485,13 +496,19 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
}
|
||||
|
||||
bool itemPosErrorShown;
|
||||
private readonly HashSet<Character> characterPosErrorShown = new HashSet<Character>();
|
||||
private void PushCharactersAway()
|
||||
{
|
||||
if (!MathUtils.IsValid(item.SimPosition))
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ")");
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:DoorPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ").");
|
||||
if (!itemPosErrorShown)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ")");
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:DoorPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the door is not valid (" + item.SimPosition + ").");
|
||||
itemPosErrorShown = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -505,14 +522,18 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (!c.Enabled) continue;
|
||||
if (!c.Enabled) { continue; }
|
||||
if (!MathUtils.IsValid(c.SimPosition))
|
||||
{
|
||||
if (GameSettings.VerboseLogging) { DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")"); }
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:CharacterPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")." +
|
||||
" Removed: " + c.Removed +
|
||||
" Remoteplayer: " + c.IsRemotePlayer);
|
||||
if (!characterPosErrorShown.Contains(c))
|
||||
{
|
||||
if (GameSettings.VerboseLogging) { DebugConsole.ThrowError("Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")"); }
|
||||
GameAnalyticsManager.AddErrorEventOnce("PushCharactersAway:CharacterPosInvalid", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
"Failed to push a character out of a doorway - position of the character \"" + c.Name + "\" is not valid (" + c.SimPosition + ")." +
|
||||
" Removed: " + c.Removed +
|
||||
" Remoteplayer: " + c.IsRemotePlayer);
|
||||
characterPosErrorShown.Add(c);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
int dir = IsHorizontal ? Math.Sign(c.SimPosition.Y - item.SimPosition.Y) : Math.Sign(c.SimPosition.X - item.SimPosition.X);
|
||||
|
||||
@@ -223,7 +223,6 @@ namespace Barotrauma.Items.Components
|
||||
if (attachable)
|
||||
{
|
||||
prevMsg = DisplayMsg;
|
||||
prevPickKey = PickKey;
|
||||
prevRequiredItems = new Dictionary<RelatedItem.RelationType, List<RelatedItem>>(requiredItems);
|
||||
}
|
||||
}
|
||||
@@ -254,9 +253,9 @@ namespace Barotrauma.Items.Components
|
||||
if (item.body != null) { item.body.Enabled = true; }
|
||||
IsActive = false;
|
||||
|
||||
if (picker == null)
|
||||
if (picker == null || picker.Removed)
|
||||
{
|
||||
if (dropper == null) { return; }
|
||||
if (dropper == null || dropper.Removed) { return; }
|
||||
picker = dropper;
|
||||
}
|
||||
if (picker.Inventory == null) { return; }
|
||||
@@ -285,7 +284,7 @@ namespace Barotrauma.Items.Components
|
||||
heldHand = picker.AnimController.GetLimb(LimbType.RightHand);
|
||||
arm = picker.AnimController.GetLimb(LimbType.RightArm);
|
||||
}
|
||||
if (heldHand != null && arm != null)
|
||||
if (heldHand != null && !heldHand.Removed && arm != null && !arm.Removed)
|
||||
{
|
||||
//hand simPosition is actually in the wrist so need to move the item out from it slightly
|
||||
Vector2 diff = new Vector2(
|
||||
@@ -391,6 +390,8 @@ namespace Barotrauma.Items.Components
|
||||
//allow deattaching everywhere in sub editor
|
||||
if (Screen.Selected == GameMain.SubEditorScreen) { return true; }
|
||||
|
||||
if (item.GetComponent<LevelResource>() != null) { return true; }
|
||||
|
||||
//if the item has a connection panel and rewiring is disabled, don't allow deattaching
|
||||
var connectionPanel = item.GetComponent<ConnectionPanel>();
|
||||
if (connectionPanel != null && (connectionPanel.Locked || !(GameMain.NetworkMember?.ServerSettings?.AllowRewiring ?? true)))
|
||||
@@ -581,7 +582,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
Vector2 swing = Vector2.Zero;
|
||||
if (swingAmount != Vector2.Zero)
|
||||
if (swingAmount != Vector2.Zero && !picker.IsUnconscious && picker.Stun <= 0.0f)
|
||||
{
|
||||
swingState += deltaTime;
|
||||
swingState %= 1.0f;
|
||||
@@ -605,7 +606,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
scaledHandlePos[0] = handlePos[0] * item.Scale;
|
||||
scaledHandlePos[1] = handlePos[1] * item.Scale;
|
||||
bool aim = picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero && (picker.SelectedConstruction == null || picker.SelectedConstruction.GetComponent<Ladder>() != null);
|
||||
bool aim = picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero && picker.CanAim;
|
||||
picker.AnimController.HoldItem(deltaTime, item, scaledHandlePos, holdPos + swing, aimPos + swing, aim, holdAngle);
|
||||
}
|
||||
else
|
||||
@@ -678,17 +679,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
var tempMsg = DisplayMsg;
|
||||
var tempPickKey = PickKey;
|
||||
var tempRequiredItems = requiredItems;
|
||||
|
||||
DisplayMsg = prevMsg;
|
||||
PickKey = prevPickKey;
|
||||
requiredItems = prevRequiredItems;
|
||||
|
||||
XElement saveElement = base.Save(parentElement);
|
||||
|
||||
DisplayMsg = tempMsg;
|
||||
PickKey = tempPickKey;
|
||||
requiredItems = tempRequiredItems;
|
||||
|
||||
return saveElement;
|
||||
|
||||
@@ -114,6 +114,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
if (trigger != null)
|
||||
{
|
||||
trigger.Remove();
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float reloadTimer;
|
||||
|
||||
private readonly Attack attack;
|
||||
public Attack Attack { get; private set; }
|
||||
|
||||
private readonly HashSet<Entity> hitTargets = new HashSet<Entity>();
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("attack", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
attack = new Attack(subElement, item.Name + ", MeleeWeapon");
|
||||
Attack = new Attack(subElement, item.Name + ", MeleeWeapon");
|
||||
}
|
||||
item.IsShootable = true;
|
||||
// TODO: should define this in xml if we have melee weapons that don't require aim to use
|
||||
@@ -158,7 +158,7 @@ namespace Barotrauma.Items.Components
|
||||
//TODO: refactor the hitting logic (get rid of the magic numbers, make it possible to use different kinds of animations for different items)
|
||||
if (!hitting)
|
||||
{
|
||||
bool aim = picker.AllowInput && picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && (picker.SelectedConstruction == null || picker.SelectedConstruction.GetComponent<Ladder>() != null);
|
||||
bool aim = picker.AllowInput && picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && picker.CanAim;
|
||||
if (aim)
|
||||
{
|
||||
hitPos = MathUtils.WrapAnglePi(Math.Min(hitPos + deltaTime * 5f, MathHelper.PiOver4));
|
||||
@@ -332,31 +332,31 @@ namespace Barotrauma.Items.Components
|
||||
Structure targetStructure = target.UserData as Structure;
|
||||
Item targetItem = target.UserData as Item;
|
||||
|
||||
if (attack != null)
|
||||
if (Attack != null)
|
||||
{
|
||||
attack.SetUser(User);
|
||||
Attack.SetUser(User);
|
||||
|
||||
if (targetLimb != null)
|
||||
{
|
||||
if (targetLimb.character.Removed) { return; }
|
||||
targetLimb.character.LastDamageSource = item;
|
||||
attack.DoDamageToLimb(User, targetLimb, item.WorldPosition, 1.0f);
|
||||
Attack.DoDamageToLimb(User, targetLimb, item.WorldPosition, 1.0f);
|
||||
}
|
||||
else if (targetCharacter != null)
|
||||
{
|
||||
if (targetCharacter.Removed) { return; }
|
||||
targetCharacter.LastDamageSource = item;
|
||||
attack.DoDamage(User, targetCharacter, item.WorldPosition, 1.0f);
|
||||
Attack.DoDamage(User, targetCharacter, item.WorldPosition, 1.0f);
|
||||
}
|
||||
else if (targetStructure != null)
|
||||
{
|
||||
if (targetStructure.Removed) { return; }
|
||||
attack.DoDamage(User, targetStructure, item.WorldPosition, 1.0f);
|
||||
Attack.DoDamage(User, targetStructure, item.WorldPosition, 1.0f);
|
||||
}
|
||||
else if (targetItem != null && targetItem.Prefab.DamagedByMeleeWeapons && targetItem.Condition > 0)
|
||||
{
|
||||
if (targetItem.Removed) { return; }
|
||||
attack.DoDamage(User, targetItem, item.WorldPosition, 1.0f);
|
||||
Attack.DoDamage(User, targetItem, item.WorldPosition, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -25,7 +25,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public Character Picker
|
||||
{
|
||||
get { return picker; }
|
||||
get
|
||||
{
|
||||
if (picker != null && picker.Removed)
|
||||
{
|
||||
picker = null;
|
||||
}
|
||||
return picker;
|
||||
}
|
||||
}
|
||||
|
||||
public Pickable(Item item, XElement element)
|
||||
|
||||
@@ -178,7 +178,7 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
private Projectile FindProjectile(bool triggerOnUseOnContainers = false)
|
||||
public Projectile FindProjectile(bool triggerOnUseOnContainers = false)
|
||||
{
|
||||
var containedItems = item.ContainedItems;
|
||||
if (containedItems == null) { return null; }
|
||||
|
||||
@@ -604,19 +604,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (item.RequireAimToUse)
|
||||
{
|
||||
bool isOperatingButtons = false;
|
||||
if (character.AIController.SteeringManager is IndoorsSteeringManager indoorSteering)
|
||||
{
|
||||
var door = indoorSteering.CurrentPath?.CurrentNode?.ConnectedDoor;
|
||||
if (door != null && !door.IsOpen)
|
||||
{
|
||||
isOperatingButtons = door.HasIntegratedButtons || door.Item.GetConnectedComponents<Controller>(true).Any();
|
||||
}
|
||||
}
|
||||
if (!isOperatingButtons)
|
||||
{
|
||||
character.SetInput(InputType.Aim, false, true);
|
||||
}
|
||||
character.SetInput(InputType.Aim, false, true);
|
||||
sinTime += deltaTime * 5;
|
||||
}
|
||||
// Press the trigger only when the tool is approximately facing the target.
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
if (picker.IsKeyDown(InputType.Aim) && picker.IsKeyHit(InputType.Shoot)) { throwing = true; }
|
||||
if (!picker.IsKeyDown(InputType.Aim) && !throwing) { throwPos = 0.0f; }
|
||||
bool aim = picker.IsKeyDown(InputType.Aim) && (picker.SelectedConstruction == null || picker.SelectedConstruction.GetComponent<Ladder>() != null);
|
||||
bool aim = picker.IsKeyDown(InputType.Aim) && picker.CanAim;
|
||||
|
||||
if (picker.IsDead || !picker.AllowInput)
|
||||
{
|
||||
|
||||
@@ -220,6 +220,8 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
public virtual bool RecreateGUIOnResolutionChange => false;
|
||||
|
||||
/// <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).
|
||||
/// </summary>
|
||||
@@ -511,7 +513,11 @@ namespace Barotrauma.Items.Components
|
||||
channel.Dispose();
|
||||
}*/
|
||||
|
||||
if (GuiFrame != null) { GUI.RemoveFromUpdateList(GuiFrame, true); }
|
||||
if (GuiFrame != null)
|
||||
{
|
||||
GUI.RemoveFromUpdateList(GuiFrame, true);
|
||||
GuiFrame.RectTransform.Parent = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (delayedCorrectionCoroutine != null)
|
||||
@@ -545,8 +551,10 @@ namespace Barotrauma.Items.Components
|
||||
RemoveComponentSpecific();
|
||||
}
|
||||
|
||||
|
||||
protected virtual void RemoveComponentSpecific()
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
public bool HasRequiredSkills(Character character)
|
||||
{
|
||||
@@ -558,7 +566,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (Skill skill in requiredSkills)
|
||||
{
|
||||
float characterLevel = character.GetSkillLevel(skill.Identifier);
|
||||
if (characterLevel < skill.Level)
|
||||
if (characterLevel < skill.Level * GetSkillMultiplier())
|
||||
{
|
||||
insufficientSkill = skill;
|
||||
return false;
|
||||
@@ -568,6 +576,8 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual float GetSkillMultiplier() { return 1; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns 0.0f-1.0f based on how well the Character can use the itemcomponent
|
||||
/// </summary>
|
||||
@@ -722,16 +732,27 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void ApplyStatusEffects(ActionType type, float deltaTime, Character character = null, Limb targetLimb = null, Entity useTarget = null, Character user = null, Vector2? worldPosition = null)
|
||||
{
|
||||
if (statusEffectLists == null) return;
|
||||
if (statusEffectLists == null) { return; }
|
||||
|
||||
if (!statusEffectLists.TryGetValue(type, out List<StatusEffect> statusEffects)) return;
|
||||
if (!statusEffectLists.TryGetValue(type, out List<StatusEffect> statusEffects)) { return; }
|
||||
|
||||
bool broken = item.Condition <= 0.0f;
|
||||
bool reducesCondition = false;
|
||||
foreach (StatusEffect effect in statusEffects)
|
||||
{
|
||||
if (broken && effect.type != ActionType.OnBroken) { continue; }
|
||||
if (user != null) { effect.SetUser(user); }
|
||||
item.ApplyStatusEffect(effect, type, deltaTime, character, targetLimb, useTarget, false, false, worldPosition);
|
||||
reducesCondition |= effect.ReducesItemCondition();
|
||||
}
|
||||
//if any of the effects reduce the item's condition, set the user for OnBroken effects as well
|
||||
if (reducesCondition && user != null && type != ActionType.OnBroken)
|
||||
{
|
||||
foreach (ItemComponent ic in item.Components)
|
||||
{
|
||||
if (ic.statusEffectLists == null || !ic.statusEffectLists.TryGetValue(ActionType.OnBroken, out List<StatusEffect> brokenEffects)) { continue; }
|
||||
brokenEffects.ForEach(e => e.SetUser(user));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -935,12 +956,12 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
protected AIObjectiveContainItem AIContainItems<T>(ItemContainer container, Character character, AIObjective objective, int itemCount, bool equip, bool removeEmpty) where T : ItemComponent
|
||||
protected AIObjectiveContainItem AIContainItems<T>(ItemContainer container, Character character, AIObjective objective, int itemCount, bool equip, bool removeEmpty, bool spawnItemIfNotFound = false) where T : ItemComponent
|
||||
{
|
||||
AIObjectiveContainItem containObjective = null;
|
||||
if (character.AIController is HumanAIController aiController)
|
||||
{
|
||||
containObjective = new AIObjectiveContainItem(character, container.GetContainableItemIdentifiers.ToArray(), container, objective.objectiveManager)
|
||||
containObjective = new AIObjectiveContainItem(character, container.GetContainableItemIdentifiers.ToArray(), container, objective.objectiveManager, spawnItemIfNotFound: spawnItemIfNotFound)
|
||||
{
|
||||
targetItemCount = itemCount,
|
||||
Equip = equip,
|
||||
|
||||
@@ -107,6 +107,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public IEnumerable<string> GetContainableItemIdentifiers => ContainableItems.SelectMany(ri => ri.Identifiers);
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
public ItemContainer(Item item, XElement element)
|
||||
: base (item, element)
|
||||
{
|
||||
@@ -352,18 +354,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
if (itemIds == null) return;
|
||||
if (itemIds == null) { return; }
|
||||
|
||||
for (ushort i = 0; i < itemIds.Length; i++)
|
||||
{
|
||||
Item item = Entity.FindEntityByID(itemIds[i]) as Item;
|
||||
if (item == null) continue;
|
||||
|
||||
if (i >= Inventory.Capacity)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(Entity.FindEntityByID(itemIds[i]) is Item item)) { continue; }
|
||||
if (i >= Inventory.Capacity) { continue; }
|
||||
Inventory.TryPutItem(item, i, false, false, null, false);
|
||||
}
|
||||
|
||||
@@ -376,6 +372,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
#if CLIENT
|
||||
inventoryTopSprite?.Remove();
|
||||
inventoryBackSprite?.Remove();
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
RemoveProjSpecific();
|
||||
List.Remove(this);
|
||||
}
|
||||
|
||||
@@ -9,15 +9,24 @@ using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
struct LimbPos
|
||||
class LimbPos : ISerializableEntity
|
||||
{
|
||||
public LimbType limbType;
|
||||
public Vector2 position;
|
||||
[Editable]
|
||||
public LimbType LimbType { get; set; }
|
||||
[Editable]
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public LimbPos(LimbType limbType, Vector2 position)
|
||||
public bool AllowUsingLimb;
|
||||
|
||||
public string Name => LimbType.ToString();
|
||||
|
||||
public Dictionary<string, SerializableProperty> SerializableProperties => null;
|
||||
|
||||
public LimbPos(LimbType limbType, Vector2 position, bool allowUsingLimb)
|
||||
{
|
||||
this.limbType = limbType;
|
||||
this.position = position;
|
||||
LimbType = limbType;
|
||||
Position = position;
|
||||
AllowUsingLimb = allowUsingLimb;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,11 +75,32 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(true, false, description: "Should the HUD (inventory, health bar, etc) be hidden when this item is selected.")]
|
||||
public bool HideHUD
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public enum UseEnvironment
|
||||
{
|
||||
Air, Water, Both
|
||||
};
|
||||
|
||||
[Serialize(UseEnvironment.Both, false, description: "Can the item be selected in air, underwater or both.")]
|
||||
public UseEnvironment UsableIn { get; set; }
|
||||
|
||||
public bool ControlCharacterPose
|
||||
{
|
||||
get { return limbPositions.Count > 0; }
|
||||
}
|
||||
|
||||
public bool AllowAiming
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = true;
|
||||
|
||||
public Controller(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -79,25 +109,31 @@ namespace Barotrauma.Items.Components
|
||||
userPos = element.GetAttributeVector2("UserPos", Vector2.Zero);
|
||||
|
||||
Enum.TryParse(element.GetAttributeString("direction", "None"), out dir);
|
||||
|
||||
foreach (XElement el in element.Elements())
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (el.Name != "limbposition") continue;
|
||||
|
||||
LimbPos lp = new LimbPos();
|
||||
|
||||
try
|
||||
if (subElement.Name != "limbposition") { continue; }
|
||||
string limbStr = subElement.GetAttributeString("limb", "");
|
||||
if (!Enum.TryParse(subElement.Attribute("limb").Value, out LimbType limbType))
|
||||
{
|
||||
lp.limbType = (LimbType)Enum.Parse(typeof(LimbType), el.Attribute("limb").Value, true);
|
||||
DebugConsole.ThrowError($"Error in item \"{item.Name}\" - {limbStr} is not a valid limb type.");
|
||||
}
|
||||
catch (Exception e)
|
||||
else
|
||||
{
|
||||
DebugConsole.ThrowError("Error in " + element + ": " + e.Message, e);
|
||||
LimbPos limbPos = new LimbPos(limbType,
|
||||
subElement.GetAttributeVector2("position", Vector2.Zero),
|
||||
subElement.GetAttributeBool("allowusinglimb", false));
|
||||
limbPositions.Add(limbPos);
|
||||
if (!limbPos.AllowUsingLimb)
|
||||
{
|
||||
if (limbType == LimbType.RightHand || limbType == LimbType.RightForearm || limbType == LimbType.RightArm ||
|
||||
limbType == LimbType.LeftHand || limbType == LimbType.LeftForearm || limbType == LimbType.LeftArm)
|
||||
{
|
||||
AllowAiming = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lp.position = el.GetAttributeVector2("position", Vector2.Zero);
|
||||
|
||||
limbPositions.Add(lp);
|
||||
}
|
||||
|
||||
IsActive = true;
|
||||
@@ -115,7 +151,9 @@ namespace Barotrauma.Items.Components
|
||||
if (user == null
|
||||
|| user.Removed
|
||||
|| user.SelectedConstruction != item
|
||||
|| !user.CanInteractWith(item))
|
||||
|| !user.CanInteractWith(item)
|
||||
|| (UsableIn == UseEnvironment.Water && !user.AnimController.InWater)
|
||||
|| (UsableIn == UseEnvironment.Air && user.AnimController.InWater))
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
@@ -187,12 +225,29 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (LimbPos lb in limbPositions)
|
||||
{
|
||||
Limb limb = user.AnimController.GetLimb(lb.limbType);
|
||||
if (limb == null || !limb.body.Enabled) continue;
|
||||
Limb limb = user.AnimController.GetLimb(lb.LimbType);
|
||||
if (limb == null || !limb.body.Enabled) { continue; }
|
||||
|
||||
if (lb.AllowUsingLimb)
|
||||
{
|
||||
switch (lb.LimbType)
|
||||
{
|
||||
case LimbType.RightHand:
|
||||
case LimbType.RightForearm:
|
||||
case LimbType.RightArm:
|
||||
if (user.SelectedItems[0] != null) { continue; }
|
||||
break;
|
||||
case LimbType.LeftHand:
|
||||
case LimbType.LeftForearm:
|
||||
case LimbType.LeftArm:
|
||||
if ( user.SelectedItems[1] != null) { continue; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
limb.Disabled = true;
|
||||
|
||||
Vector2 worldPosition = new Vector2(item.WorldRect.X, item.WorldRect.Y) + lb.position * item.Scale;
|
||||
|
||||
Vector2 worldPosition = new Vector2(item.WorldRect.X, item.WorldRect.Y) + lb.Position * item.Scale;
|
||||
Vector2 diff = worldPosition - limb.WorldPosition;
|
||||
|
||||
limb.PullJointEnabled = true;
|
||||
@@ -255,7 +310,7 @@ namespace Barotrauma.Items.Components
|
||||
Lights.LightManager.ViewTarget = focusTarget;
|
||||
cam.TargetPos = focusTarget.WorldPosition;
|
||||
|
||||
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (focusTarget as Item).Prefab.OffsetOnSelected, deltaTime * 10.0f);
|
||||
cam.OffsetAmount = MathHelper.Lerp(cam.OffsetAmount, (focusTarget as Item).Prefab.OffsetOnSelected * focusTarget.OffsetOnSelectedMultiplier, deltaTime * 10.0f);
|
||||
HideHUDs(true);
|
||||
}
|
||||
#endif
|
||||
@@ -326,8 +381,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
foreach (LimbPos lb in limbPositions)
|
||||
{
|
||||
Limb limb = character.AnimController.GetLimb(lb.limbType);
|
||||
if (limb == null) continue;
|
||||
Limb limb = character.AnimController.GetLimb(lb.LimbType);
|
||||
if (limb == null) { continue; }
|
||||
|
||||
limb.Disabled = false;
|
||||
limb.PullJointEnabled = false;
|
||||
@@ -349,6 +404,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (activator == null || activator.Removed) { return false; }
|
||||
|
||||
if (UsableIn == UseEnvironment.Water && !activator.AnimController.InWater ||
|
||||
UsableIn == UseEnvironment.Air && activator.AnimController.InWater)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//someone already using the item
|
||||
if (user != null && !user.Removed)
|
||||
{
|
||||
@@ -383,14 +444,13 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
for (int i = 0; i < limbPositions.Count; i++)
|
||||
{
|
||||
float diff = (item.Rect.X + limbPositions[i].position.X * item.Scale) - item.Rect.Center.X;
|
||||
float diff = (item.Rect.X + limbPositions[i].Position.X * item.Scale) - item.Rect.Center.X;
|
||||
|
||||
Vector2 flippedPos =
|
||||
new Vector2(
|
||||
(item.Rect.Center.X - diff - item.Rect.X) / item.Scale,
|
||||
limbPositions[i].position.Y);
|
||||
|
||||
limbPositions[i] = new LimbPos(limbPositions[i].limbType, flippedPos);
|
||||
limbPositions[i].Position.Y);
|
||||
limbPositions[i] = new LimbPos(limbPositions[i].LimbType, flippedPos, limbPositions[i].AllowUsingLimb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,14 +460,13 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
for (int i = 0; i < limbPositions.Count; i++)
|
||||
{
|
||||
float diff = (item.Rect.Y + limbPositions[i].position.Y) - item.Rect.Center.Y;
|
||||
float diff = (item.Rect.Y + limbPositions[i].Position.Y) - item.Rect.Center.Y;
|
||||
|
||||
Vector2 flippedPos =
|
||||
new Vector2(
|
||||
limbPositions[i].position.X,
|
||||
limbPositions[i].Position.X,
|
||||
item.Rect.Center.Y - diff - item.Rect.Y);
|
||||
|
||||
limbPositions[i] = new LimbPos(limbPositions[i].limbType, flippedPos);
|
||||
limbPositions[i] = new LimbPos(limbPositions[i].LimbType, flippedPos, limbPositions[i].AllowUsingLimb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,11 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
get { return outputContainer; }
|
||||
}
|
||||
|
||||
[Editable, Serialize(1.0f, true)]
|
||||
public float DeconstructionSpeed { get; set; }
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
public Deconstructor(Item item, XElement element)
|
||||
: base(item, element)
|
||||
@@ -77,7 +82,7 @@ namespace Barotrauma.Items.Components
|
||||
var targetItem = inputContainer.Inventory.Items.LastOrDefault(i => i != null);
|
||||
if (targetItem == null) { return; }
|
||||
|
||||
float deconstructTime = targetItem.Prefab.DeconstructItems.Any() ? targetItem.Prefab.DeconstructTime : 1.0f;
|
||||
float deconstructTime = targetItem.Prefab.DeconstructItems.Any() ? targetItem.Prefab.DeconstructTime / DeconstructionSpeed : 1.0f;
|
||||
|
||||
progressState = Math.Min(progressTimer / deconstructTime, 1.0f);
|
||||
if (progressTimer > deconstructTime)
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
|
||||
partial class Fabricator : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
private readonly List<FabricationRecipe> fabricationRecipes = new List<FabricationRecipe>();
|
||||
@@ -21,6 +20,12 @@ namespace Barotrauma.Items.Components
|
||||
private Character user;
|
||||
|
||||
private ItemContainer inputContainer, outputContainer;
|
||||
|
||||
[Serialize(1.0f, true)]
|
||||
public float FabricationSpeed { get; set; }
|
||||
|
||||
[Serialize(1.0f, true)]
|
||||
public float SkillRequirementMultiplier { get; set; }
|
||||
|
||||
private enum FabricatorState
|
||||
{
|
||||
@@ -56,6 +61,8 @@ namespace Barotrauma.Items.Components
|
||||
get { return outputContainer; }
|
||||
}
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
private float progressState;
|
||||
|
||||
public Fabricator(Item item, XElement element)
|
||||
@@ -287,13 +294,27 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
Character tempUser = user;
|
||||
if (outputContainer.Inventory.Items.All(i => i != null))
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, item.Position, item.Submarine, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition,
|
||||
onSpawned: (Item spawnedItem) => { onItemSpawned(spawnedItem, tempUser); });
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition);
|
||||
Entity.Spawner.AddToSpawnQueue(fabricatedItem.TargetItem, outputContainer.Inventory, fabricatedItem.TargetItem.Health * fabricatedItem.OutCondition,
|
||||
onSpawned: (Item spawnedItem) => { onItemSpawned(spawnedItem, tempUser); });
|
||||
}
|
||||
|
||||
static void onItemSpawned(Item spawnedItem, Character user)
|
||||
{
|
||||
if (user != null && user.TeamID != Character.TeamType.None)
|
||||
{
|
||||
foreach (WifiComponent wifiComponent in spawnedItem.GetComponents<WifiComponent>())
|
||||
{
|
||||
wifiComponent.TeamID = user.TeamID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (user != null && !user.Removed)
|
||||
@@ -334,13 +355,28 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float GetRequiredTime(FabricationRecipe fabricableItem, Character user)
|
||||
{
|
||||
float degreeOfSuccess = DegreeOfSuccess(user, fabricableItem.RequiredSkills);
|
||||
float degreeOfSuccess = FabricationDegreeOfSuccess(user, fabricableItem.RequiredSkills);
|
||||
|
||||
float t = degreeOfSuccess < 0.5f ? degreeOfSuccess * degreeOfSuccess : degreeOfSuccess * 2;
|
||||
|
||||
//fabricating takes 100 times longer if degree of success is close to 0
|
||||
//characters with a higher skill than required can fabricate up to 100% faster
|
||||
return fabricableItem.RequiredTime / MathHelper.Clamp(t, 0.01f, 2.0f);
|
||||
return fabricableItem.RequiredTime / FabricationSpeed / MathHelper.Clamp(t, 0.01f, 2.0f);
|
||||
}
|
||||
|
||||
public float FabricationDegreeOfSuccess(Character character, List<Skill> skills)
|
||||
{
|
||||
if (skills.Count == 0) return 1.0f;
|
||||
|
||||
float skillSum = (from t in skills let characterLevel = character.GetSkillLevel(t.Identifier) select (characterLevel - (t.Level * SkillRequirementMultiplier))).Sum();
|
||||
float average = skillSum / skills.Count;
|
||||
|
||||
return ((average + 100.0f) / 2.0f) / 100.0f;
|
||||
}
|
||||
|
||||
public override float GetSkillMultiplier()
|
||||
{
|
||||
return SkillRequirementMultiplier;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class OutpostTerminal : ItemComponent
|
||||
{
|
||||
public OutpostTerminal(Item item, XElement element) : base(item, element)
|
||||
{
|
||||
InitProjSpecific(element);
|
||||
}
|
||||
|
||||
partial void InitProjSpecific(XElement element);
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,13 @@ namespace Barotrauma.Items.Components
|
||||
set { maxFlow = value; }
|
||||
}
|
||||
|
||||
[Editable, Serialize(false, false, alwaysUseInstanceValues: true)]
|
||||
public bool IsOn
|
||||
{
|
||||
get { return IsActive; }
|
||||
set { IsActive = value; }
|
||||
}
|
||||
|
||||
private float currFlow;
|
||||
public float CurrFlow
|
||||
{
|
||||
|
||||
@@ -172,6 +172,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
private float prevAvailableFuel;
|
||||
|
||||
[Serialize(0.0f, true)]
|
||||
public float AvailableFuel { get; set; }
|
||||
|
||||
public Reactor(Item item, XElement element)
|
||||
@@ -316,9 +318,12 @@ namespace Barotrauma.Items.Components
|
||||
if (item.CurrentHull != null)
|
||||
{
|
||||
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 (aiTarget != null)
|
||||
{
|
||||
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)
|
||||
@@ -447,7 +452,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAutoTemp(float speed, float deltaTime)
|
||||
public void UpdateAutoTemp(float speed, float deltaTime)
|
||||
{
|
||||
float desiredTurbineOutput = (optimalTurbineOutput.X + optimalTurbineOutput.Y) / 2.0f;
|
||||
targetTurbineOutput += MathHelper.Clamp(desiredTurbineOutput - targetTurbineOutput, -speed, speed) * deltaTime;
|
||||
@@ -471,6 +476,19 @@ namespace Barotrauma.Items.Components
|
||||
//for the actual fission rate and temperature to follow
|
||||
targetFissionRate = MathHelper.Clamp(targetFissionRate, FissionRate - 5, FissionRate + 5);
|
||||
}
|
||||
|
||||
public void PowerUpImmediately()
|
||||
{
|
||||
PowerOn = true;
|
||||
AutoTemp = true;
|
||||
prevAvailableFuel = AvailableFuel;
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
Update((float)(Timing.Step * 10.0f), cam: null);
|
||||
UpdateAutoTemp(100.0f, (float)(Timing.Step * 10.0f));
|
||||
AvailableFuel = prevAvailableFuel;
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateBroken(float deltaTime, Camera cam)
|
||||
{
|
||||
@@ -557,7 +575,7 @@ namespace Barotrauma.Items.Components
|
||||
if (objective.SubObjectives.None())
|
||||
{
|
||||
int itemCount = item.ContainedItems.Count(i => i != null && container.ContainableItems.Any(ri => ri.MatchesItem(i))) + 1;
|
||||
AIContainItems<Reactor>(container, character, objective, itemCount, equip: false, removeEmpty: true);
|
||||
AIContainItems<Reactor>(container, character, objective, itemCount, equip: false, removeEmpty: true, spawnItemIfNotFound: character.TeamID == Character.TeamType.FriendlyNPC);
|
||||
character.Speak(TextManager.Get("DialogReactorFuel"), null, 0.0f, "reactorfuel", 30.0f);
|
||||
}
|
||||
return false;
|
||||
@@ -641,6 +659,11 @@ namespace Barotrauma.Items.Components
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
prevAvailableFuel = AvailableFuel;
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item source, Character sender, float power, float signalStrength = 1.0f)
|
||||
{
|
||||
switch (connection.Name)
|
||||
|
||||
@@ -130,6 +130,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
public Sonar(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -230,7 +232,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
return currentPingIndex != -1;
|
||||
return currentPingIndex != -1 && (character == null || characterUsable);
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, List<Character>> targetGroups = new Dictionary<string, List<Character>>();
|
||||
|
||||
@@ -146,6 +146,8 @@ namespace Barotrauma.Items.Components
|
||||
set { posToMaintain = value; }
|
||||
}
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
struct ObstacleDebugInfo
|
||||
{
|
||||
public Vector2 Point1;
|
||||
@@ -330,6 +332,8 @@ namespace Barotrauma.Items.Components
|
||||
private void IncreaseSkillLevel(Character user, float deltaTime)
|
||||
{
|
||||
if (user?.Info == null) { return; }
|
||||
// Do not increase the helm skill when "steering" the sub in an outpost level
|
||||
if (GameMain.GameSession?.Campaign != null && Level.IsLoadedOutpost) { return; }
|
||||
|
||||
float userSkill = user.GetSkillLevel("helm") / 100.0f;
|
||||
user.Info.IncreaseSkillLevel(
|
||||
|
||||
@@ -21,9 +21,12 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (item.CurrentHull == null) return;
|
||||
if (item.CurrentHull == null || item.InWater) { return; }
|
||||
|
||||
if (item.InWater) return;
|
||||
if (oxygenFlow > 0.0f)
|
||||
{
|
||||
ApplyStatusEffects(ActionType.OnActive, deltaTime);
|
||||
}
|
||||
|
||||
item.CurrentHull.Oxygen += oxygenFlow * deltaTime;
|
||||
OxygenFlow -= deltaTime * 1000.0f;
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Barotrauma.Items.Components
|
||||
if (Math.Abs(charge - lastSentCharge) / capacity > 0.05f)
|
||||
{
|
||||
#if SERVER
|
||||
if (GameMain.Server != null) item.CreateServerEvent(this);
|
||||
if (GameMain.Server != null && (!item.Submarine?.Loading ?? true)) { item.CreateServerEvent(this); }
|
||||
#endif
|
||||
lastSentCharge = charge;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace Barotrauma.Items.Components
|
||||
/// List of all powered ItemComponents
|
||||
/// </summary>
|
||||
private static readonly List<Powered> poweredList = new List<Powered>();
|
||||
public static IEnumerable<Powered> PoweredList
|
||||
{
|
||||
get { return poweredList; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Items that have already received the "probe signal" that's used to distribute power and load across the grid
|
||||
@@ -306,6 +310,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
poweredList.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Voronoi2;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -51,7 +52,7 @@ namespace Barotrauma.Items.Components
|
||||
private const float PersistentStickJointDuration = 1.0f;
|
||||
private PrismaticJoint stickJoint;
|
||||
|
||||
private readonly Attack attack;
|
||||
public Attack Attack { get; private set; }
|
||||
|
||||
private Vector2 launchPos;
|
||||
|
||||
@@ -66,7 +67,7 @@ namespace Barotrauma.Items.Components
|
||||
set
|
||||
{
|
||||
user = value;
|
||||
attack?.SetUser(user);
|
||||
Attack?.SetUser(user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,27 +187,27 @@ namespace Barotrauma.Items.Components
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
if (!subElement.Name.ToString().Equals("attack", StringComparison.OrdinalIgnoreCase)) { continue; }
|
||||
attack = new Attack(subElement, item.Name + ", Projectile");
|
||||
Attack = new Attack(subElement, item.Name + ", Projectile");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnItemLoaded()
|
||||
{
|
||||
if (attack != null && attack.DamageRange <= 0.0f && item.body != null)
|
||||
if (Attack != null && Attack.DamageRange <= 0.0f && item.body != null)
|
||||
{
|
||||
switch (item.body.BodyShape)
|
||||
{
|
||||
case PhysicsBody.Shape.Circle:
|
||||
attack.DamageRange = item.body.radius;
|
||||
Attack.DamageRange = item.body.radius;
|
||||
break;
|
||||
case PhysicsBody.Shape.Capsule:
|
||||
attack.DamageRange = item.body.height / 2 + item.body.radius;
|
||||
Attack.DamageRange = item.body.height / 2 + item.body.radius;
|
||||
break;
|
||||
case PhysicsBody.Shape.Rectangle:
|
||||
attack.DamageRange = new Vector2(item.body.width / 2.0f, item.body.height / 2.0f).Length();
|
||||
Attack.DamageRange = new Vector2(item.body.width / 2.0f, item.body.height / 2.0f).Length();
|
||||
break;
|
||||
}
|
||||
attack.DamageRange = ConvertUnits.ToDisplayUnits(attack.DamageRange);
|
||||
Attack.DamageRange = ConvertUnits.ToDisplayUnits(Attack.DamageRange);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +254,7 @@ namespace Barotrauma.Items.Components
|
||||
launchPos = item.SimPosition;
|
||||
|
||||
item.body.Enabled = true;
|
||||
item.body.ApplyLinearImpulse(impulse, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
item.body.ApplyLinearImpulse(impulse, maxVelocity: NetConfig.MaxPhysicsBodyVelocity * 0.9f);
|
||||
|
||||
item.body.FarseerBody.OnCollision += OnProjectileCollision;
|
||||
item.body.FarseerBody.IsBullet = true;
|
||||
@@ -367,6 +368,8 @@ namespace Barotrauma.Items.Components
|
||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) &&
|
||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) { return true; }
|
||||
|
||||
if (fixture.Body.UserData is VoronoiCell && this.item.Submarine != null) { return true; }
|
||||
|
||||
fixture.Body.GetTransform(out FarseerPhysics.Common.Transform transform);
|
||||
if (!fixture.Shape.TestPoint(ref transform, ref rayStart)) { return true; }
|
||||
|
||||
@@ -387,6 +390,15 @@ namespace Barotrauma.Items.Components
|
||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionWall) &&
|
||||
!fixture.CollisionCategories.HasFlag(Physics.CollisionLevel)) { return -1; }
|
||||
|
||||
//ignore level cells if the item the point of impact are inside a sub
|
||||
if (fixture.Body.UserData is VoronoiCell && this.item.Submarine != null)
|
||||
{
|
||||
if (Hull.FindHull(ConvertUnits.ToDisplayUnits(point), this.item.CurrentHull) != null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
hits.Add(new HitscanResult(fixture, point, normal, fraction));
|
||||
|
||||
return hits.Count < 25 ? 1 : 0;
|
||||
@@ -532,25 +544,24 @@ namespace Barotrauma.Items.Components
|
||||
else if (target.Body.UserData is Limb limb)
|
||||
{
|
||||
//severed limbs don't deactivate the projectile (but may still slow it down enough to make it inactive)
|
||||
if (limb.IsSevered)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (limb.IsSevered) { return true; }
|
||||
if (limb.character == null || limb.character.Removed) { return false; }
|
||||
|
||||
limb.character.LastDamageSource = item;
|
||||
if (attack != null) { attackResult = attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f); }
|
||||
if (Attack != null) { attackResult = Attack.DoDamageToLimb(User, limb, item.WorldPosition, 1.0f); }
|
||||
if (limb.character != null) { character = limb.character; }
|
||||
}
|
||||
else if (target.Body.UserData is Item targetItem)
|
||||
{
|
||||
if (attack != null && targetItem.Prefab.DamagedByProjectiles && targetItem.Condition > 0)
|
||||
if (targetItem.Removed) { return false; }
|
||||
if (Attack != null && targetItem.Prefab.DamagedByProjectiles && targetItem.Condition > 0)
|
||||
{
|
||||
attackResult = attack.DoDamage(User, targetItem, item.WorldPosition, 1.0f);
|
||||
attackResult = Attack.DoDamage(User, targetItem, item.WorldPosition, 1.0f);
|
||||
}
|
||||
}
|
||||
else if (target.Body.UserData is IDamageable damageable)
|
||||
{
|
||||
if (attack != null) { attackResult = attack.DoDamage(User, damageable, item.WorldPosition, 1.0f); }
|
||||
if (Attack != null) { attackResult = Attack.DoDamage(User, damageable, item.WorldPosition, 1.0f); }
|
||||
}
|
||||
|
||||
if (character != null) { character.LastDamageSource = item; }
|
||||
@@ -738,6 +749,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
if (stickJoint != null)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
@@ -83,6 +84,30 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
private float skillRequirementMultiplier;
|
||||
|
||||
[Serialize(1.0f, true)]
|
||||
public float SkillRequirementMultiplier
|
||||
{
|
||||
get { return skillRequirementMultiplier; }
|
||||
set
|
||||
{
|
||||
var oldValue = skillRequirementMultiplier;
|
||||
skillRequirementMultiplier = value;
|
||||
#if CLIENT
|
||||
if (!MathUtils.NearlyEqual(oldValue, skillRequirementMultiplier))
|
||||
{
|
||||
RecreateGUI();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public float RepairIconThreshold
|
||||
{
|
||||
get { return RepairThreshold / 2; }
|
||||
}
|
||||
|
||||
public Character CurrentFixer { get; private set; }
|
||||
|
||||
public enum FixActions : int
|
||||
@@ -146,12 +171,27 @@ namespace Barotrauma.Items.Components
|
||||
if (requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical", StringComparison.OrdinalIgnoreCase)) &&
|
||||
item.GetComponent<Powered>() is Powered powered && powered.Voltage < 0.1f) { return true; }
|
||||
|
||||
if (Rand.Range(0.0f, 0.5f) < DegreeOfSuccess(character)) { return true; }
|
||||
if (Rand.Range(0.0f, 0.5f) < RepairDegreeOfSuccess(character, requiredSkills)) { return true; }
|
||||
|
||||
ApplyStatusEffects(ActionType.OnFailure, 1.0f, character);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override float GetSkillMultiplier()
|
||||
{
|
||||
return SkillRequirementMultiplier;
|
||||
}
|
||||
|
||||
public float RepairDegreeOfSuccess(Character character, List<Skill> skills)
|
||||
{
|
||||
if (skills.Count == 0) return 1.0f;
|
||||
|
||||
float skillSum = (from t in skills let characterLevel = character.GetSkillLevel(t.Identifier) select (characterLevel - (t.Level * SkillRequirementMultiplier))).Sum();
|
||||
float average = skillSum / skills.Count;
|
||||
|
||||
return ((average + 100.0f) / 2.0f) / 100.0f;
|
||||
}
|
||||
|
||||
public bool StartRepairing(Character character, FixActions action)
|
||||
{
|
||||
if (character == null || character.IsDead || action == FixActions.None)
|
||||
@@ -213,7 +253,7 @@ namespace Barotrauma.Items.Components
|
||||
public void ResetDeterioration()
|
||||
{
|
||||
deteriorationTimer = Rand.Range(MinDeteriorationDelay, MaxDeteriorationDelay);
|
||||
item.Condition = item.Prefab.Health;
|
||||
item.Condition = item.MaxCondition;
|
||||
#if SERVER
|
||||
//let the clients know the deterioration delay
|
||||
item.CreateServerEvent(this);
|
||||
@@ -271,7 +311,7 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
float successFactor = requiredSkills.Count == 0 ? 1.0f : DegreeOfSuccess(CurrentFixer, requiredSkills);
|
||||
float successFactor = requiredSkills.Count == 0 ? 1.0f : RepairDegreeOfSuccess(CurrentFixer, requiredSkills);
|
||||
|
||||
//item must have been below the repair threshold for the player to get an achievement or XP for repairing it
|
||||
if (item.ConditionPercentage < RepairThreshold)
|
||||
@@ -368,6 +408,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private bool ShouldDeteriorate()
|
||||
{
|
||||
if (Level.IsLoadedOutpost) { return false; }
|
||||
|
||||
if (LastActiveTime > Timing.TotalTime) { return true; }
|
||||
foreach (ItemComponent ic in item.Components)
|
||||
{
|
||||
|
||||
@@ -67,10 +67,10 @@ namespace Barotrauma.Items.Components
|
||||
#if CLIENT
|
||||
if (connector == null)
|
||||
{
|
||||
connector = GUI.Style.GetComponentStyle("ConnectionPanelConnector").Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
||||
wireVertical = GUI.Style.GetComponentStyle("ConnectionPanelWire").Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
||||
connectionSprite = GUI.Style.GetComponentStyle("ConnectionPanelConnection").Sprites[GUIComponent.ComponentState.None][0].Sprite;
|
||||
connectionSpriteHighlight = GUI.Style.GetComponentStyle("ConnectionPanelConnection").Sprites[GUIComponent.ComponentState.Hover][0].Sprite;
|
||||
connector = GUI.Style.GetComponentStyle("ConnectionPanelConnector").GetDefaultSprite();
|
||||
wireVertical = GUI.Style.GetComponentStyle("ConnectionPanelWire").GetDefaultSprite();
|
||||
connectionSprite = GUI.Style.GetComponentStyle("ConnectionPanelConnection").GetDefaultSprite();
|
||||
connectionSpriteHighlight = GUI.Style.GetComponentStyle("ConnectionPanelConnection").GetSprite(GUIComponent.ComponentState.Hover);
|
||||
screwSprites = GUI.Style.GetComponentStyle("ConnectionPanelScrew").Sprites[GUIComponent.ComponentState.None].Select(s => s.Sprite).ToList();
|
||||
}
|
||||
#endif
|
||||
@@ -202,16 +202,17 @@ namespace Barotrauma.Items.Components
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void TryAddLink(Wire wire)
|
||||
public bool TryAddLink(Wire wire)
|
||||
{
|
||||
for (int i = 0; i < MaxLinked; i++)
|
||||
{
|
||||
if (wires[i] == null)
|
||||
{
|
||||
SetWire(i, wire);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetWire(int index, Wire wire)
|
||||
|
||||
@@ -64,7 +64,14 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void InitProjSpecific(XElement element);
|
||||
|
||||
private bool linksInitialized;
|
||||
public override void OnMapLoaded()
|
||||
{
|
||||
if (linksInitialized) { return; }
|
||||
InitializeLinks();
|
||||
}
|
||||
|
||||
public void InitializeLinks()
|
||||
{
|
||||
foreach (Connection c in Connections)
|
||||
{
|
||||
@@ -90,6 +97,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linksInitialized = true;
|
||||
}
|
||||
|
||||
public override void OnItemLoaded()
|
||||
@@ -260,6 +269,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
foreach (Wire wire in DisconnectedWires.ToList())
|
||||
{
|
||||
if (wire.OtherConnection(null) == null) //wire not connected to anything else
|
||||
|
||||
@@ -80,6 +80,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
public override bool RecreateGUIOnResolutionChange => true;
|
||||
|
||||
private List<CustomInterfaceElement> customInterfaceElementList = new List<CustomInterfaceElement>();
|
||||
|
||||
public CustomInterface(Item item, XElement element)
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[InGameEditable, Serialize("255,255,255,255", true, description: "The color of the emitted light (R,G,B,A).", alwaysUseInstanceValues: true)]
|
||||
[InGameEditable(FallBackTextTag = "connection.setcolor"), Serialize("255,255,255,255", true, description: "The color of the emitted light (R,G,B,A).", alwaysUseInstanceValues: true)]
|
||||
public Color LightColor
|
||||
{
|
||||
get { return lightColor; }
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Barotrauma.Items.Components
|
||||
fireInRange = IsFireInRange();
|
||||
fireCheckTimer = FireCheckInterval;
|
||||
}
|
||||
item.SendSignal(0, fireInRange ? "1" : "0", "signal_out", null);
|
||||
item.SendSignal(0, fireInRange ? Output : FalseOutput, "signal_out", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
@@ -205,11 +206,18 @@ namespace Barotrauma.Items.Components
|
||||
Channel = newChannel;
|
||||
}
|
||||
break;
|
||||
case "set_range":
|
||||
if (float.TryParse(signal, NumberStyles.Float, CultureInfo.InvariantCulture, out float newRange))
|
||||
{
|
||||
Range = newRange;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
base.RemoveComponentSpecific();
|
||||
list.Remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private Vector2 sectionExtents;
|
||||
|
||||
private float currLength;
|
||||
|
||||
public bool Hidden;
|
||||
|
||||
private float removeNodeDelay;
|
||||
@@ -287,7 +289,7 @@ namespace Barotrauma.Items.Components
|
||||
Structure attachTarget = Structure.GetAttachTarget(item.WorldPosition);
|
||||
canPlaceNode = attachTarget != null;
|
||||
|
||||
sub = sub ?? attachTarget?.Submarine;
|
||||
sub ??= attachTarget?.Submarine;
|
||||
Vector2 attachPos = GetAttachPosition(user);
|
||||
newNodePos = sub == null ?
|
||||
attachPos :
|
||||
@@ -308,20 +310,25 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 prevNodePos = nodes[nodes.Count - 1];
|
||||
if (sub != null) { prevNodePos += sub.HiddenSubPosition; }
|
||||
|
||||
float currLength = 0.0f;
|
||||
currLength = 0.0f;
|
||||
for (int i = 0; i < nodes.Count - 1; i++)
|
||||
{
|
||||
currLength += Vector2.Distance(nodes[i], nodes[i + 1]);
|
||||
}
|
||||
currLength += Vector2.Distance(nodes[nodes.Count - 1], newNodePos);
|
||||
|
||||
Vector2 itemPos = item.Position;
|
||||
if (sub != null && user.Submarine == null) { prevNodePos += sub.Position; }
|
||||
currLength += Vector2.Distance(prevNodePos, itemPos);
|
||||
if (currLength > MaxLength)
|
||||
{
|
||||
Vector2 diff = nodes[nodes.Count - 1] - newNodePos;
|
||||
Vector2 diff = prevNodePos - user.Position;
|
||||
Vector2 pullBackDir = diff == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(diff);
|
||||
|
||||
user.AnimController.Collider.ApplyForce(pullBackDir * user.Mass * 50.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
user.AnimController.UpdateUseItem(true, user.WorldPosition + pullBackDir * 200.0f);
|
||||
Vector2 forceDir = pullBackDir;
|
||||
if (!user.AnimController.InWater) { forceDir.Y = 0.0f; }
|
||||
user.AnimController.Collider.ApplyForce(forceDir * user.Mass * 50.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity * 0.5f);
|
||||
if (diff.LengthSquared() > 50.0f * 50.0f)
|
||||
{
|
||||
user.AnimController.UpdateUseItem(true, user.WorldPosition + pullBackDir * Math.Min(150.0f, diff.Length()));
|
||||
}
|
||||
|
||||
if (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
@@ -564,7 +571,7 @@ namespace Barotrauma.Items.Components
|
||||
int wireIndex = connections[i].FindWireIndex(item);
|
||||
if (wireIndex == -1) { continue; }
|
||||
#if SERVER
|
||||
if (!connections[i].Item.Removed)
|
||||
if (!connections[i].Item.Removed && (!connections[i].Item.Submarine?.Loading ?? true) && (!Level.Loaded?.Generating ?? true))
|
||||
{
|
||||
connections[i].Item.CreateServerEvent(connections[i].Item.GetComponent<ConnectionPanel>());
|
||||
}
|
||||
|
||||
@@ -315,7 +315,8 @@ namespace Barotrauma.Items.Components
|
||||
float springDamping = MathHelper.Lerp(SpringDampingLowSkill, SpringDampingHighSkill, degreeOfSuccess);
|
||||
float rotationSpeed = MathHelper.Lerp(RotationSpeedLowSkill, RotationSpeedHighSkill, degreeOfSuccess);
|
||||
|
||||
if (user?.Info != null)
|
||||
// Do not increase the weapons skill when operating a turret in an outpost level
|
||||
if (user?.Info != null && (GameMain.GameSession?.Campaign == null || !Level.IsLoadedOutpost))
|
||||
{
|
||||
user.Info.IncreaseSkillLevel("weapons",
|
||||
SkillSettings.Current.SkillIncreasePerSecondWhenOperatingTurret * deltaTime / Math.Max(user.GetSkillLevel("weapons"), 1.0f),
|
||||
@@ -447,6 +448,11 @@ namespace Barotrauma.Items.Components
|
||||
if (launchedProjectile != null || LaunchWithoutProjectile)
|
||||
{
|
||||
Launch(launchedProjectile?.Item, character);
|
||||
if (item.AiTarget != null)
|
||||
{
|
||||
item.AiTarget.SoundRange = item.AiTarget.MaxSoundRange;
|
||||
// Turrets also have a light component, which handles the sight range.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,7 +592,7 @@ namespace Barotrauma.Items.Components
|
||||
closestDist = maxDistance * maxDistance;
|
||||
foreach (Submarine sub in Submarine.Loaded)
|
||||
{
|
||||
if (sub.Info.Type != SubmarineInfo.SubmarineType.Player) { continue; }
|
||||
if (sub.Info.Type != SubmarineType.Player) { continue; }
|
||||
float dist = Vector2.DistanceSquared(sub.WorldPosition, item.WorldPosition);
|
||||
if (dist > closestDist) { continue; }
|
||||
closestSub = sub;
|
||||
|
||||
@@ -224,7 +224,10 @@ namespace Barotrauma.Items.Components
|
||||
if (variant == value) { return; }
|
||||
#if SERVER
|
||||
variant = value;
|
||||
item.CreateServerEvent(this);
|
||||
if (!item.Submarine?.Loading ?? true)
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
#elif CLIENT
|
||||
|
||||
Character character = picker;
|
||||
|
||||
Reference in New Issue
Block a user