Unstable 1.1.14.0
This commit is contained in:
@@ -211,6 +211,9 @@ namespace Barotrauma.Items.Components
|
||||
#endif
|
||||
public bool DisableHeadRotation { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "If true, this item can't be used if the character is also holding a ranged weapon.")]
|
||||
public bool DisableWhenRangedWeaponEquipped { get; set; }
|
||||
|
||||
[ConditionallyEditable(ConditionallyEditable.ConditionType.Attachable, MinValueFloat = 0.0f, MaxValueFloat = 0.999f, DecimalCount = 3), Serialize(0.55f, IsPropertySaveable.No, description: "Sprite depth that's used when the item is NOT attached to a wall.")]
|
||||
public float SpriteDepthWhenDropped
|
||||
{
|
||||
@@ -343,11 +346,9 @@ namespace Barotrauma.Items.Components
|
||||
DeattachFromWall();
|
||||
}
|
||||
|
||||
if (setTransform)
|
||||
{
|
||||
if (Pusher != null) { Pusher.Enabled = false; }
|
||||
if (item.body != null) { item.body.Enabled = true; }
|
||||
}
|
||||
if (Pusher != null) { Pusher.Enabled = false; }
|
||||
if (item.body != null) { item.body.Enabled = true; }
|
||||
|
||||
IsActive = false;
|
||||
attachTargetCell = null;
|
||||
|
||||
@@ -616,6 +617,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
//set to submarine-relative position
|
||||
item.SetTransform(ConvertUnits.ToSimUnits(item.WorldPosition - attachTarget.Submarine.Position), 0.0f, false);
|
||||
body.SetTransformIgnoreContacts(item.SimPosition, 0.0f);
|
||||
}
|
||||
item.Submarine = attachTarget.Submarine;
|
||||
}
|
||||
@@ -688,6 +690,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (UsageDisabledByRangedWeapon(character)) { return false; }
|
||||
if (!attachable || item.body == null) { return character == null || (character.IsKeyDown(InputType.Aim) && characterUsable); }
|
||||
if (character != null)
|
||||
{
|
||||
@@ -792,19 +795,27 @@ namespace Barotrauma.Items.Components
|
||||
Vector2 userPos = useWorldCoordinates ? user.WorldPosition : user.Position;
|
||||
Vector2 attachPos = userPos + mouseDiff;
|
||||
|
||||
//offset the position by half the size of the grid to get the item to adhere to the grid in the same way as in the sub editor
|
||||
//in the sub editor, we align the top-left corner of the item with the grid
|
||||
//but here the origin of the item is placed at the attach position, so we need to offset it
|
||||
Vector2 offset = new Vector2(
|
||||
-(item.Rect.Width / 2) % Submarine.GridSize.X,
|
||||
(item.Rect.Height / 2) % Submarine.GridSize.Y);
|
||||
|
||||
if (user.Submarine != null)
|
||||
{
|
||||
if (Submarine.PickBody(
|
||||
ConvertUnits.ToSimUnits(user.Position),
|
||||
ConvertUnits.ToSimUnits(user.Position + mouseDiff), collisionCategory: Physics.CollisionWall) != null)
|
||||
{
|
||||
attachPos = userPos + mouseDiff * Submarine.LastPickedFraction;
|
||||
attachPos = userPos + mouseDiff * Submarine.LastPickedFraction + offset;
|
||||
|
||||
//round down if we're placing on the right side and vice versa: ensures we don't round the position inside a wall
|
||||
return
|
||||
new Vector2(
|
||||
mouseDiff.X > 0 ? (float)Math.Floor(attachPos.X / Submarine.GridSize.X) * Submarine.GridSize.X : (float)Math.Ceiling(attachPos.X / Submarine.GridSize.X) * Submarine.GridSize.X,
|
||||
mouseDiff.Y > 0 ? (float)Math.Floor(attachPos.Y / Submarine.GridSize.Y) * Submarine.GridSize.X : (float)Math.Ceiling(attachPos.Y / Submarine.GridSize.Y) * Submarine.GridSize.Y);
|
||||
(mouseDiff.X > 0 ? MathF.Floor(attachPos.X / Submarine.GridSize.X) : MathF.Ceiling(attachPos.X / Submarine.GridSize.X)) * Submarine.GridSize.X,
|
||||
(mouseDiff.Y > 0 ? MathF.Floor(attachPos.Y / Submarine.GridSize.Y) : MathF.Ceiling(attachPos.Y / Submarine.GridSize.Y)) * Submarine.GridSize.Y)
|
||||
- offset;
|
||||
}
|
||||
}
|
||||
else if (Level.Loaded != null)
|
||||
@@ -827,10 +838,9 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
new Vector2(
|
||||
MathUtils.RoundTowardsClosest(attachPos.X, Submarine.GridSize.X),
|
||||
MathUtils.RoundTowardsClosest(attachPos.Y, Submarine.GridSize.Y));
|
||||
return new Vector2(
|
||||
MathUtils.RoundTowardsClosest(attachPos.X + offset.X, Submarine.GridSize.X),
|
||||
MathUtils.RoundTowardsClosest(attachPos.Y + offset.Y, Submarine.GridSize.Y)) - offset;
|
||||
}
|
||||
|
||||
private Voronoi2.VoronoiCell GetAttachTargetCell(float maxDist)
|
||||
@@ -903,7 +913,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.CanAim;
|
||||
bool aim = picker.IsKeyDown(InputType.Aim) && aimPos != Vector2.Zero && picker.CanAim && !UsageDisabledByRangedWeapon(picker);
|
||||
if (aim)
|
||||
{
|
||||
picker.AnimController.HoldItem(deltaTime, item, scaledHandlePos, holdPos + swingPos, aimPos + swingPos, aim, holdAngle, aimAngle);
|
||||
@@ -963,6 +973,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
protected bool UsageDisabledByRangedWeapon(Character character)
|
||||
{
|
||||
if (DisableWhenRangedWeaponEquipped && character != null)
|
||||
{
|
||||
if (character.HeldItems.Any(it => it.GetComponent<RangedWeapon>() != null)) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void ReceiveSignal(Signal signal, Connection connection)
|
||||
{
|
||||
//do nothing
|
||||
@@ -1005,14 +1024,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.ParentInventory != null)
|
||||
if (body != null)
|
||||
{
|
||||
if (body != null)
|
||||
{
|
||||
item.body = body;
|
||||
body.Enabled = false;
|
||||
}
|
||||
}
|
||||
body.SetTransformIgnoreContacts(item.SimPosition, item.Rotation);
|
||||
item.body = body;
|
||||
body.Enabled = item.ParentInventory == null;
|
||||
}
|
||||
DeattachFromWall();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,20 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
|
||||
public string OwnerName { get; set; }
|
||||
|
||||
|
||||
private string ownerNameLocalized;
|
||||
[Serialize("", IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
|
||||
public string OwnerNameLocalized
|
||||
{
|
||||
get { return ownerNameLocalized; }
|
||||
set
|
||||
{
|
||||
if (value.IsNullOrWhiteSpace()) { return; }
|
||||
ownerNameLocalized = value;
|
||||
OwnerName = TextManager.Get(value).Fallback(value).Value;
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
|
||||
public Identifier OwnerJobId { get; set; }
|
||||
|
||||
@@ -67,6 +80,9 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize("0,0", IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
|
||||
public Vector2 OwnerSheetIndex { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes, alwaysUseInstanceValues: true)]
|
||||
public bool SpawnPointTagsGiven { get; set; }
|
||||
|
||||
public IdCard(Item item, ContentXElement element) : base(item, element) { }
|
||||
|
||||
public void Initialize(WayPoint spawnPoint, Character character)
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace Barotrauma.Items.Components
|
||||
private void CreateTriggerBody()
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(trigger == null, "LevelResource trigger already created!");
|
||||
var body = item.body ?? holdable.Body;
|
||||
var body = item.body ?? holdable?.Body;
|
||||
if (body != null && Attached)
|
||||
{
|
||||
trigger = new PhysicsBody(body.Width, body.Height, body.Radius,
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace Barotrauma.Items.Components
|
||||
impactQueue.Clear();
|
||||
return;
|
||||
}
|
||||
if (picker == null && !picker.HeldItems.Contains(item))
|
||||
if (picker == null || !picker.HeldItems.Contains(item))
|
||||
{
|
||||
impactQueue.Clear();
|
||||
IsActive = false;
|
||||
@@ -218,7 +218,8 @@ namespace Barotrauma.Items.Components
|
||||
AnimController ac = picker.AnimController;
|
||||
if (!hitting)
|
||||
{
|
||||
bool aim = item.RequireAimToUse && picker.AllowInput && picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && picker.CanAim;
|
||||
bool aim = item.RequireAimToUse && picker.AllowInput && picker.IsKeyDown(InputType.Aim) && reloadTimer <= 0 && picker.CanAim &&
|
||||
!UsageDisabledByRangedWeapon(picker);
|
||||
if (aim)
|
||||
{
|
||||
UpdateSwingPos(deltaTime, out Vector2 swingPos);
|
||||
@@ -364,7 +365,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
hitTargets.Add(targetStructure);
|
||||
}
|
||||
else if (f2.Body.UserData is Item targetItem)
|
||||
else if ((f2.Body.UserData as Item ?? f2.UserData as Item) is Item targetItem)
|
||||
{
|
||||
if (AllowHitMultiple)
|
||||
{
|
||||
@@ -410,7 +411,7 @@ namespace Barotrauma.Items.Components
|
||||
Limb targetLimb = target.UserData as Limb;
|
||||
Character targetCharacter = targetLimb?.character ?? target.UserData as Character;
|
||||
Structure targetStructure = target.UserData as Structure ?? targetFixture.UserData as Structure;
|
||||
Item targetItem = target.UserData as Item;
|
||||
Item targetItem = target.UserData as Item ?? targetFixture.UserData as Item;
|
||||
Entity targetEntity = targetCharacter ?? targetStructure ?? targetItem ?? target.UserData as Entity;
|
||||
if (Attack != null)
|
||||
{
|
||||
|
||||
@@ -73,6 +73,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
//return if someone is already trying to pick the item
|
||||
if (pickTimer > 0.0f) { return false; }
|
||||
if (PickingTime >= float.MaxValue) { return false; }
|
||||
if (picker == null || picker.Inventory == null) { return false; }
|
||||
if (!picker.Inventory.AccessibleWhenAlive && !picker.Inventory.AccessibleByOwner) { return false; }
|
||||
|
||||
@@ -112,10 +113,16 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public virtual bool OnPicked(Character picker)
|
||||
{
|
||||
return OnPicked(picker, pickDroppedStack: true);
|
||||
}
|
||||
|
||||
public virtual bool OnPicked(Character picker, bool pickDroppedStack)
|
||||
{
|
||||
//if the item has multiple Pickable components (e.g. Holdable and Wearable, check that we don't equip it in hands when the item is worn or vice versa)
|
||||
if (item.GetComponents<Pickable>().Count() > 0)
|
||||
if (item.GetComponents<Pickable>().Any())
|
||||
{
|
||||
bool alreadyEquipped = false;
|
||||
for (int i = 0; i < picker.Inventory.Capacity; i++)
|
||||
@@ -132,11 +139,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (alreadyEquipped) { return false; }
|
||||
}
|
||||
var droppedStack = pickDroppedStack ? item.DroppedStack.ToList() : null;
|
||||
if (picker.Inventory.TryPutItemWithAutoEquipCheck(item, picker, allowedSlots))
|
||||
{
|
||||
if (!picker.HeldItems.Contains(item) && item.body != null) { item.body.Enabled = false; }
|
||||
this.picker = picker;
|
||||
|
||||
|
||||
for (int i = item.linkedTo.Count - 1; i >= 0; i--)
|
||||
{
|
||||
item.linkedTo[i].RemoveLinked(item);
|
||||
@@ -147,14 +156,22 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
ApplyStatusEffects(ActionType.OnPicked, 1.0f, picker);
|
||||
#if CLIENT
|
||||
if (!GameMain.Instance.LoadingScreenOpen && picker == Character.Controlled) SoundPlayer.PlayUISound(GUISoundType.PickItem);
|
||||
if (!GameMain.Instance.LoadingScreenOpen && picker == Character.Controlled) { SoundPlayer.PlayUISound(GUISoundType.PickItem); }
|
||||
PlaySound(ActionType.OnPicked, picker);
|
||||
#endif
|
||||
if (pickDroppedStack)
|
||||
{
|
||||
foreach (var droppedItem in droppedStack)
|
||||
{
|
||||
if (droppedItem == item) { continue; }
|
||||
droppedItem.GetComponent<Pickable>().OnPicked(picker, pickDroppedStack: false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
if (!GameMain.Instance.LoadingScreenOpen && picker == Character.Controlled) SoundPlayer.PlayUISound(GUISoundType.PickItemFail);
|
||||
if (!GameMain.Instance.LoadingScreenOpen && picker == Character.Controlled) { SoundPlayer.PlayUISound(GUISoundType.PickItemFail); }
|
||||
#endif
|
||||
|
||||
return false;
|
||||
@@ -183,12 +200,15 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
Character.Controlled?.UpdateHUDProgressBar(
|
||||
this,
|
||||
item.WorldPosition,
|
||||
pickTimer / requiredTime,
|
||||
GUIStyle.Red, GUIStyle.Green,
|
||||
!string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching");
|
||||
if (requiredTime < float.MaxValue)
|
||||
{
|
||||
Character.Controlled?.UpdateHUDProgressBar(
|
||||
this,
|
||||
item.WorldPosition,
|
||||
pickTimer / requiredTime,
|
||||
GUIStyle.Red, GUIStyle.Green,
|
||||
!string.IsNullOrWhiteSpace(PickingMsg) ? PickingMsg : this is Door ? "progressbar.opening" : "progressbar.deattaching");
|
||||
}
|
||||
#endif
|
||||
picker.AnimController.UpdateUseItem(!picker.IsClimbing, item.WorldPosition + new Vector2(0.0f, 100.0f) * ((pickTimer / 10.0f) % 0.1f));
|
||||
pickTimer += CoroutineManager.DeltaTime;
|
||||
@@ -197,12 +217,14 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
StopPicking(picker);
|
||||
|
||||
bool isNotRemote = true;
|
||||
if (!item.Removed)
|
||||
{
|
||||
bool isNotRemote = true;
|
||||
#if CLIENT
|
||||
isNotRemote = !picker.IsRemotePlayer;
|
||||
isNotRemote = !picker.IsRemotePlayer;
|
||||
#endif
|
||||
if (isNotRemote) OnPicked(picker);
|
||||
if (isNotRemote) { OnPicked(picker); }
|
||||
}
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
@@ -608,6 +608,7 @@ namespace Barotrauma.Items.Components
|
||||
float closestDist = float.MaxValue;
|
||||
foreach (Limb limb in targetCharacter.AnimController.Limbs)
|
||||
{
|
||||
if (limb.Removed || limb.IgnoreCollisions || limb.Hidden || limb.IsSevered) { continue; }
|
||||
float dist = Vector2.DistanceSquared(item.SimPosition, limb.SimPosition);
|
||||
if (dist < closestDist)
|
||||
{
|
||||
@@ -716,7 +717,7 @@ namespace Barotrauma.Items.Components
|
||||
private readonly float repairTimeOut = 5;
|
||||
public override bool CrewAIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
||||
{
|
||||
if (!(objective.OperateTarget is Gap leak))
|
||||
if (objective.OperateTarget is not Gap leak)
|
||||
{
|
||||
Reset();
|
||||
return true;
|
||||
@@ -806,36 +807,50 @@ namespace Barotrauma.Items.Components
|
||||
// Press the trigger only when the tool is approximately facing the target.
|
||||
Vector2 fromItemToLeak = leak.WorldPosition - item.WorldPosition;
|
||||
var angle = VectorExtensions.Angle(VectorExtensions.Forward(item.body.TransformedRotation), fromItemToLeak);
|
||||
bool repair = true;
|
||||
if (angle < MathHelper.PiOver4)
|
||||
{
|
||||
if (Submarine.PickBody(item.SimPosition, leak.SimPosition, collisionCategory: Physics.CollisionWall, allowInsideFixture: true)?.UserData is Item i)
|
||||
{
|
||||
var door = i.GetComponent<Door>();
|
||||
// Hit a door, abandon so that we don't weld it shut.
|
||||
return door != null && !door.CanBeTraversed;
|
||||
{
|
||||
if (i.GetComponent<Door>() is Door door && !door.CanBeTraversed )
|
||||
{
|
||||
// Hit a door, don't repair so that we don't weld it shut.
|
||||
if (door.Stuck > 90)
|
||||
{
|
||||
// Almost stuck -> just abandon.
|
||||
return false;
|
||||
}
|
||||
if (door.Stuck > 50)
|
||||
{
|
||||
repair = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check that we don't hit any friendlies
|
||||
if (Submarine.PickBodies(item.SimPosition, leak.SimPosition, collisionCategory: Physics.CollisionCharacter).None(hit =>
|
||||
if (repair)
|
||||
{
|
||||
if (hit.UserData is Character c)
|
||||
// Check that we don't hit any friendlies
|
||||
if (Submarine.PickBodies(item.SimPosition, leak.SimPosition, collisionCategory: Physics.CollisionCharacter).None(hit =>
|
||||
{
|
||||
if (c == character) { return false; }
|
||||
return HumanAIController.IsFriendly(character, c);
|
||||
if (hit.UserData is Character c)
|
||||
{
|
||||
if (c == character) { return false; }
|
||||
return HumanAIController.IsFriendly(character, c);
|
||||
}
|
||||
return false;
|
||||
}))
|
||||
{
|
||||
character.SetInput(InputType.Shoot, false, true);
|
||||
Use(deltaTime, character);
|
||||
}
|
||||
return false;
|
||||
}))
|
||||
}
|
||||
repairTimer += deltaTime;
|
||||
if (repairTimer > repairTimeOut)
|
||||
{
|
||||
character.SetInput(InputType.Shoot, false, true);
|
||||
Use(deltaTime, character);
|
||||
repairTimer += deltaTime;
|
||||
if (repairTimer > repairTimeOut)
|
||||
{
|
||||
#if DEBUG
|
||||
DebugConsole.NewMessage($"{character.Name}: timed out while welding a leak in {leak.FlowTargetHull.DisplayName}.", color: Color.Yellow);
|
||||
DebugConsole.NewMessage($"{character.Name}: timed out while welding a leak in {leak.FlowTargetHull.DisplayName}.", color: Color.Yellow);
|
||||
#endif
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -912,7 +927,7 @@ namespace Barotrauma.Items.Components
|
||||
// A general purpose system could be better, but it would most likely require changes in the way we define the status effects in xml.
|
||||
foreach (ISerializableEntity target in currentTargets)
|
||||
{
|
||||
if (target is not Door door) { continue; }
|
||||
if (target is not Door door) { continue; }
|
||||
if (!door.CanBeWelded || !door.Item.IsInteractable(user)) { continue; }
|
||||
foreach (var propertyEffect in effect.PropertyEffects)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user