v0.12.0.2
This commit is contained in:
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
|
||||
protected Vector2[] handlePos;
|
||||
private readonly Vector2[] scaledHandlePos;
|
||||
|
||||
private InputType prevPickKey;
|
||||
private readonly InputType prevPickKey;
|
||||
private string prevMsg;
|
||||
private Dictionary<RelatedItem.RelationType, List<RelatedItem>> prevRequiredItems;
|
||||
|
||||
@@ -29,6 +29,8 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float swingState;
|
||||
|
||||
private Character prevEquipper;
|
||||
|
||||
private bool attachable, attached, attachedByDefault;
|
||||
private Voronoi2.VoronoiCell attachTargetCell;
|
||||
private readonly PhysicsBody body;
|
||||
@@ -301,11 +303,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
item.SetTransform(picker.SimPosition, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
picker.DeselectItem(item);
|
||||
picker.Inventory.RemoveItem(item);
|
||||
picker = null;
|
||||
}
|
||||
@@ -340,34 +340,33 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
bool alreadyEquipped = character.HasEquippedItem(item);
|
||||
bool canSelect = picker.TrySelectItem(item);
|
||||
|
||||
if (canSelect || picker.HasEquippedItem(item))
|
||||
if (picker.HasEquippedItem(item))
|
||||
{
|
||||
if (!canSelect)
|
||||
{
|
||||
character.DeselectItem(item);
|
||||
}
|
||||
|
||||
item.body.Enabled = true;
|
||||
item.body.PhysEnabled = false;
|
||||
IsActive = true;
|
||||
|
||||
#if SERVER
|
||||
if (!alreadyEquipped) GameServer.Log(GameServer.CharacterLogName(character) + " equipped " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
if (picker != prevEquipper) { GameServer.Log(GameServer.CharacterLogName(character) + " equipped " + item.Name, ServerLog.MessageType.ItemInteraction); }
|
||||
#endif
|
||||
prevEquipper = picker;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevEquipper = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Unequip(Character character)
|
||||
{
|
||||
if (picker == null) { return; }
|
||||
|
||||
picker.DeselectItem(item);
|
||||
#if SERVER
|
||||
GameServer.Log(GameServer.CharacterLogName(character) + " unequipped " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
if (prevEquipper != null)
|
||||
{
|
||||
GameServer.Log(GameServer.CharacterLogName(character) + " unequipped " + item.Name, ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
#endif
|
||||
|
||||
prevEquipper = null;
|
||||
if (picker == null) { return; }
|
||||
item.body.PhysEnabled = true;
|
||||
item.body.Enabled = false;
|
||||
IsActive = false;
|
||||
@@ -488,13 +487,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
var containedItems = item.OwnInventory?.Items;
|
||||
var containedItems = item.OwnInventory?.AllItems;
|
||||
if (containedItems != null)
|
||||
{
|
||||
foreach (Item contained in containedItems)
|
||||
{
|
||||
if (contained == null) { continue; }
|
||||
if (contained.body == null) { continue; }
|
||||
if (contained?.body == null) { continue; }
|
||||
contained.SetTransform(item.SimPosition, contained.body.Rotation);
|
||||
}
|
||||
}
|
||||
@@ -673,7 +671,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
item.Submarine = picker.Submarine;
|
||||
|
||||
if (picker.HasSelectedItem(item))
|
||||
if (picker.HeldItems.Contains(item))
|
||||
{
|
||||
scaledHandlePos[0] = handlePos[0] * item.Scale;
|
||||
scaledHandlePos[1] = handlePos[1] * item.Scale;
|
||||
|
||||
@@ -42,13 +42,13 @@ namespace Barotrauma.Items.Components
|
||||
public override void Equip(Character character)
|
||||
{
|
||||
base.Equip(character);
|
||||
character.Info.CheckDisguiseStatus(true, this);
|
||||
character.Info?.CheckDisguiseStatus(true, this);
|
||||
}
|
||||
|
||||
public override void Unequip(Character character)
|
||||
{
|
||||
base.Unequip(character);
|
||||
character.Info.CheckDisguiseStatus(true, this);
|
||||
character.Info?.CheckDisguiseStatus(true, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,6 +58,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(1.0f, false, description: "How much the position of the item can vary from the wall the item spawns on.")]
|
||||
public float RandomOffsetFromWall
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool Attached
|
||||
{
|
||||
get { return holdable != null && holdable.Attached; }
|
||||
|
||||
@@ -50,6 +50,11 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines items that boost the weapon functionality, like battery cell for stun batons.
|
||||
/// </summary>
|
||||
public readonly string[] PreferredContainedItems;
|
||||
|
||||
public MeleeWeapon(Item item, XElement element)
|
||||
: base(item, element)
|
||||
{
|
||||
@@ -61,6 +66,7 @@ namespace Barotrauma.Items.Components
|
||||
item.IsShootable = true;
|
||||
// TODO: should define this in xml if we have melee weapons that don't require aim to use
|
||||
item.RequireAimToUse = true;
|
||||
PreferredContainedItems = element.GetAttributeStringArray("preferredcontaineditems", new string[0], convertToLowerInvariant: true);
|
||||
}
|
||||
|
||||
public override void Equip(Character character)
|
||||
@@ -76,11 +82,9 @@ namespace Barotrauma.Items.Components
|
||||
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++ )
|
||||
foreach (Item heldItem in character.HeldItems)
|
||||
{
|
||||
if (character.SelectedItems[i] == null || character.SelectedItems[i] == Item) { continue; }
|
||||
|
||||
var otherWeapon = character.SelectedItems[i].GetComponent<MeleeWeapon>();
|
||||
var otherWeapon = heldItem.GetComponent<MeleeWeapon>();
|
||||
if (otherWeapon == null) { continue; }
|
||||
if (otherWeapon.hitting) { return false; }
|
||||
}
|
||||
@@ -143,7 +147,7 @@ namespace Barotrauma.Items.Components
|
||||
public override void Update(float deltaTime, Camera cam)
|
||||
{
|
||||
if (!item.body.Enabled) { impactQueue.Clear(); return; }
|
||||
if (picker == null && !picker.HasSelectedItem(item)) { impactQueue.Clear(); IsActive = false; }
|
||||
if (picker == null && !picker.HeldItems.Contains(item)) { impactQueue.Clear(); IsActive = false; }
|
||||
|
||||
while (impactQueue.Count > 0)
|
||||
{
|
||||
@@ -244,12 +248,14 @@ namespace Barotrauma.Items.Components
|
||||
return true;
|
||||
}
|
||||
|
||||
//ignore collision if there's a wall between the user and the weapon to prevent hitting through walls
|
||||
contact.GetWorldManifold(out Vector2 normal, out var points);
|
||||
|
||||
//ignore collision if there's a wall between the user and the contact point to prevent hitting through walls
|
||||
if (Submarine.PickBody(User.AnimController.AimSourceSimPos,
|
||||
item.SimPosition,
|
||||
points[0],
|
||||
collisionCategory: Physics.CollisionWall | Physics.CollisionLevel | Physics.CollisionItemBlocking,
|
||||
allowInsideFixture: true,
|
||||
customPredicate: (Fixture fixture) => { return fixture.CollidesWith.HasFlag(Physics.CollisionItem); }) != null)
|
||||
customPredicate: (Fixture fixture) => { return fixture.CollidesWith.HasFlag(Physics.CollisionItem) && fixture.Body != f2.Body; }) != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
@@ -91,7 +92,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (picker.Inventory.TryPutItemWithAutoEquipCheck(item, picker, allowedSlots))
|
||||
{
|
||||
if (!picker.HasSelectedItem(item) && item.body != null) item.body.Enabled = false;
|
||||
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--)
|
||||
|
||||
@@ -71,11 +71,11 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
character.AnimController.Collider.ApplyForce(propulsion, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
|
||||
if (character.SelectedItems[0] == item)
|
||||
if (character.Inventory.IsInLimbSlot(item, InvSlotType.RightHand))
|
||||
{
|
||||
character.AnimController.GetLimb(LimbType.RightHand)?.body.ApplyForce(propulsion, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
if (character.SelectedItems[1] == item)
|
||||
if (character.Inventory.IsInLimbSlot(item, InvSlotType.LeftHand))
|
||||
{
|
||||
character.AnimController.GetLimb(LimbType.LeftHand)?.body.ApplyForce(propulsion, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public Projectile FindProjectile(bool triggerOnUseOnContainers = false)
|
||||
{
|
||||
var containedItems = item.OwnInventory?.Items;
|
||||
var containedItems = item.OwnInventory?.AllItemsMod;
|
||||
if (containedItems == null) { return null; }
|
||||
|
||||
foreach (Item item in containedItems)
|
||||
@@ -166,7 +166,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (Item it in containedItems)
|
||||
{
|
||||
if (it == null) { continue; }
|
||||
var containedSubItems = it.OwnInventory?.Items;
|
||||
var containedSubItems = it.OwnInventory?.AllItemsMod;
|
||||
if (containedSubItems == null) { continue; }
|
||||
foreach (Item subItem in containedSubItems)
|
||||
{
|
||||
|
||||
@@ -87,6 +87,13 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(false, false, description: "Can the item repair things through holes in walls.")]
|
||||
public bool RepairThroughHoles { get; set; }
|
||||
|
||||
|
||||
[Serialize(100.0f, false, description: "How far two walls need to not be considered overlapping and to stop the ray.")]
|
||||
public float MaxOverlappingWallDist
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
[Serialize(true, false, description: "Can the item hit broken doors.")]
|
||||
public bool HitItems { get; set; }
|
||||
|
||||
@@ -320,9 +327,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
var bodies = Submarine.PickBodies(rayStart, rayEnd, ignoredBodies, collisionCategories,
|
||||
ignoreSensors: false,
|
||||
customPredicate: (Fixture f) =>
|
||||
customPredicate: (Fixture f) =>
|
||||
{
|
||||
if (RepairThroughHoles && f.IsSensor && f.Body?.UserData is Structure || (f.Body?.UserData is Item it && it.GetComponent<Planter>() != null)) { return false; }
|
||||
if (f.IsSensor)
|
||||
{
|
||||
if (RepairThroughHoles && f.Body?.UserData is Structure) { return false; }
|
||||
if (f.Body?.UserData is PhysicsBody) { return false; }
|
||||
}
|
||||
if (f.Body?.UserData is Item it && it.GetComponent<Planter>() != null) { return false; }
|
||||
if (f.Body?.UserData as string == "ruinroom") { return false; }
|
||||
if (f.Body?.UserData is VineTile && !(FireDamage > 0)) { return false; }
|
||||
return true;
|
||||
@@ -361,12 +373,13 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
//if repairing through walls is not allowed and the next wall is more than 100 pixels away from the previous one, stop here
|
||||
//(= repairing multiple overlapping walls is allowed as long as the edges of the walls are less than 100 pixels apart)
|
||||
//(= repairing multiple overlapping walls is allowed as long as the edges of the walls are less than MaxOverlappingWallDist pixels apart)
|
||||
float thisBodyFraction = Submarine.LastPickedBodyDist(body);
|
||||
if (!RepairThroughWalls && lastHitType == typeof(Structure) && Range * (thisBodyFraction - lastPickedFraction) > 100.0f)
|
||||
if (!RepairThroughWalls && lastHitType == typeof(Structure) && Range * (thisBodyFraction - lastPickedFraction) > MaxOverlappingWallDist)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pickedPosition = rayStart + (rayEnd - rayStart) * thisBodyFraction;
|
||||
if (FixBody(user, deltaTime, degreeOfSuccess, body))
|
||||
{
|
||||
lastPickedFraction = thisBodyFraction;
|
||||
@@ -376,13 +389,16 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else
|
||||
{
|
||||
FixBody(user, deltaTime, degreeOfSuccess,
|
||||
Submarine.PickBody(rayStart, rayEnd,
|
||||
ignoredBodies, collisionCategories,
|
||||
var pickedBody = Submarine.PickBody(rayStart, rayEnd,
|
||||
ignoredBodies, collisionCategories,
|
||||
ignoreSensors: false,
|
||||
customPredicate: (Fixture f) =>
|
||||
customPredicate: (Fixture f) =>
|
||||
{
|
||||
if (RepairThroughHoles && f.IsSensor && f.Body?.UserData is Structure) { return false; }
|
||||
if (f.IsSensor)
|
||||
{
|
||||
if (RepairThroughHoles && f.Body?.UserData is Structure) { return false; }
|
||||
if (f.Body?.UserData is PhysicsBody) { return false; }
|
||||
}
|
||||
if (f.Body?.UserData as string == "ruinroom") { return false; }
|
||||
if (f.Body?.UserData is VineTile && !(FireDamage > 0)) { return false; }
|
||||
|
||||
@@ -398,9 +414,11 @@ namespace Barotrauma.Items.Components
|
||||
if (targetItem.Condition <= 0) { return false; }
|
||||
}
|
||||
}
|
||||
return f.Body?.UserData != null;
|
||||
return f.Body?.UserData != null;
|
||||
},
|
||||
allowInsideFixture: true));
|
||||
allowInsideFixture: true);
|
||||
pickedPosition = Submarine.LastPickedPosition;
|
||||
FixBody(user, deltaTime, degreeOfSuccess, pickedBody);
|
||||
lastPickedFraction = Submarine.LastPickedFraction;
|
||||
}
|
||||
|
||||
@@ -495,8 +513,6 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (targetBody?.UserData == null) { return false; }
|
||||
|
||||
pickedPosition = Submarine.LastPickedPosition;
|
||||
|
||||
if (targetBody.UserData is Structure targetStructure)
|
||||
{
|
||||
if (targetStructure.IsPlatform) { return false; }
|
||||
@@ -526,8 +542,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else if (targetBody.UserData is Voronoi2.VoronoiCell cell && cell.IsDestructible)
|
||||
{
|
||||
var levelWall = Level.Loaded?.ExtraWalls.Find(w => w.Body == cell.Body) as DestructibleLevelWall;
|
||||
if (levelWall != null)
|
||||
if (Level.Loaded?.ExtraWalls.Find(w => w.Body == cell.Body) is DestructibleLevelWall levelWall)
|
||||
{
|
||||
levelWall.AddDamage(-LevelWallFixAmount * deltaTime, item.WorldPosition);
|
||||
}
|
||||
@@ -579,7 +594,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
else if (targetBody.UserData is Item targetItem)
|
||||
{
|
||||
if (!HitItems || targetItem.NonInteractable) { return false; }
|
||||
if (!HitItems || !targetItem.IsInteractable(user)) { return false; }
|
||||
|
||||
var levelResource = targetItem.GetComponent<LevelResource>();
|
||||
if (levelResource != null && levelResource.Attached &&
|
||||
@@ -594,7 +609,7 @@ namespace Barotrauma.Items.Components
|
||||
levelResource.DeattachTimer / levelResource.DeattachDuration,
|
||||
GUI.Style.Red, GUI.Style.Green, "progressbar.deattaching");
|
||||
#endif
|
||||
FixItemProjSpecific(user, deltaTime, targetItem);
|
||||
FixItemProjSpecific(user, deltaTime, targetItem, showProgressBar: false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -620,7 +635,7 @@ namespace Barotrauma.Items.Components
|
||||
targetItem.body.ApplyForce(dir * TargetForce, maxVelocity: 10.0f);
|
||||
}
|
||||
|
||||
FixItemProjSpecific(user, deltaTime, targetItem);
|
||||
FixItemProjSpecific(user, deltaTime, targetItem, showProgressBar: true);
|
||||
return true;
|
||||
}
|
||||
else if (targetBody.UserData is BallastFloraBranch branch)
|
||||
@@ -635,7 +650,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void FixStructureProjSpecific(Character user, float deltaTime, Structure targetStructure, int sectionIndex);
|
||||
partial void FixCharacterProjSpecific(Character user, float deltaTime, Character targetCharacter);
|
||||
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem);
|
||||
partial void FixItemProjSpecific(Character user, float deltaTime, Item targetItem, bool showProgressBar);
|
||||
|
||||
private float sinTime;
|
||||
private float repairTimer;
|
||||
@@ -643,74 +658,71 @@ namespace Barotrauma.Items.Components
|
||||
private readonly float repairTimeOut = 5;
|
||||
public override bool AIOperate(float deltaTime, Character character, AIObjectiveOperateItem objective)
|
||||
{
|
||||
if (!(objective.OperateTarget is Gap leak)) { return true; }
|
||||
if (leak.Submarine == null) { return true; }
|
||||
if (!(objective.OperateTarget is Gap leak))
|
||||
{
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
if (leak.Submarine == null)
|
||||
{
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
if (leak != previousGap)
|
||||
{
|
||||
sinTime = 0;
|
||||
repairTimer = 0;
|
||||
Reset();
|
||||
previousGap = leak;
|
||||
}
|
||||
Vector2 fromCharacterToLeak = leak.WorldPosition - character.WorldPosition;
|
||||
float dist = fromCharacterToLeak.Length();
|
||||
float reach = AIObjectiveFixLeak.CalculateReach(this, character);
|
||||
|
||||
//too far away -> consider this done and hope the AI is smart enough to move closer
|
||||
if (dist > reach * 2) { return true; }
|
||||
character.AIController.SteeringManager.Reset();
|
||||
//steer closer if almost in range
|
||||
if (dist > reach)
|
||||
if (dist > reach * 3)
|
||||
{
|
||||
if (character.AnimController.InWater)
|
||||
// Too far away -> consider this done and hope the AI is smart enough to move closer
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
character.AIController.SteeringManager.Reset();
|
||||
if (!character.AnimController.InWater)
|
||||
{
|
||||
// TODO: use the collider size?
|
||||
if (!character.AnimController.InWater && character.AnimController is HumanoidAnimController &&
|
||||
Math.Abs(fromCharacterToLeak.X) < 100.0f && fromCharacterToLeak.Y < 0.0f && fromCharacterToLeak.Y > -150.0f)
|
||||
{
|
||||
if (character.AIController.SteeringManager is IndoorsSteeringManager indoorSteering)
|
||||
((HumanoidAnimController)character.AnimController).Crouching = true;
|
||||
}
|
||||
}
|
||||
if (dist > reach * 0.8f || dist > reach * 0.5f && character.AnimController.Limbs.Any(l => l.inWater))
|
||||
{
|
||||
// Steer closer
|
||||
if (character.AIController.SteeringManager is IndoorsSteeringManager indoorSteering)
|
||||
{
|
||||
// Swimming inside the sub
|
||||
if (indoorSteering.CurrentPath != null && !indoorSteering.IsPathDirty && (indoorSteering.CurrentPath.Unreachable || indoorSteering.CurrentPath.Finished))
|
||||
{
|
||||
// Swimming inside the sub
|
||||
if (indoorSteering.CurrentPath != null && !indoorSteering.IsPathDirty && indoorSteering.CurrentPath.Unreachable)
|
||||
{
|
||||
Vector2 dir = Vector2.Normalize(fromCharacterToLeak);
|
||||
character.AIController.SteeringManager.SteeringManual(deltaTime, dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
character.AIController.SteeringManager.SteeringSeek(character.GetRelativeSimPosition(leak));
|
||||
}
|
||||
Vector2 dir = Vector2.Normalize(fromCharacterToLeak);
|
||||
character.AIController.SteeringManager.SteeringManual(deltaTime, dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Swimming outside the sub
|
||||
character.AIController.SteeringManager.SteeringSeek(character.GetRelativeSimPosition(leak));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: use the collider size?
|
||||
if (!character.AnimController.InWater && character.AnimController is HumanoidAnimController &&
|
||||
Math.Abs(fromCharacterToLeak.X) < 100.0f && fromCharacterToLeak.Y < 0.0f && fromCharacterToLeak.Y > -150.0f)
|
||||
{
|
||||
((HumanoidAnimController)character.AnimController).Crouching = true;
|
||||
}
|
||||
Vector2 standPos = new Vector2(Math.Sign(-fromCharacterToLeak.X), Math.Sign(-fromCharacterToLeak.Y)) / 2;
|
||||
if (leak.IsHorizontal)
|
||||
{
|
||||
standPos.X *= 2;
|
||||
standPos.Y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
standPos.X = 0;
|
||||
}
|
||||
character.AIController.SteeringManager.SteeringSeek(standPos);
|
||||
// Swimming outside the sub
|
||||
character.AIController.SteeringManager.SteeringSeek(character.GetRelativeSimPosition(leak));
|
||||
}
|
||||
}
|
||||
if (dist < reach / 2)
|
||||
else if (dist < reach * 0.25f)
|
||||
{
|
||||
// Too close -> steer away
|
||||
character.AIController.SteeringManager.SteeringManual(deltaTime, Vector2.Normalize(character.SimPosition - leak.SimPosition));
|
||||
}
|
||||
else if (dist < reach * 2)
|
||||
if (dist <= reach)
|
||||
{
|
||||
// In or almost in range
|
||||
// In range
|
||||
character.CursorPosition = leak.WorldPosition;
|
||||
if (character.Submarine != null)
|
||||
{
|
||||
@@ -734,46 +746,52 @@ namespace Barotrauma.Items.Components
|
||||
character.AIController.SteeringManager.SteeringManual(deltaTime, moveDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item.RequireAimToUse)
|
||||
{
|
||||
character.SetInput(InputType.Aim, false, true);
|
||||
sinTime += deltaTime * 5;
|
||||
}
|
||||
// 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);
|
||||
if (angle < MathHelper.PiOver4)
|
||||
{
|
||||
if (Submarine.PickBody(item.SimPosition, leak.SimPosition, collisionCategory: Physics.CollisionWall, allowInsideFixture: true)?.UserData is Item i)
|
||||
if (item.RequireAimToUse)
|
||||
{
|
||||
var door = i.GetComponent<Door>();
|
||||
// Hit a door, abandon so that we don't weld it shut.
|
||||
return door != null && !door.IsOpen && !door.IsBroken;
|
||||
character.SetInput(InputType.Aim, false, true);
|
||||
sinTime += deltaTime * 5;
|
||||
}
|
||||
// Check that we don't hit any friendlies
|
||||
if (Submarine.PickBodies(item.SimPosition, leak.SimPosition, collisionCategory: Physics.CollisionCharacter).None(hit =>
|
||||
// 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);
|
||||
if (angle < MathHelper.PiOver4)
|
||||
{
|
||||
if (hit.UserData is Character c)
|
||||
if (Submarine.PickBody(item.SimPosition, leak.SimPosition, collisionCategory: Physics.CollisionWall, allowInsideFixture: true)?.UserData is Item i)
|
||||
{
|
||||
if (c == character) { return false; }
|
||||
return HumanAIController.IsFriendly(character, c);
|
||||
var door = i.GetComponent<Door>();
|
||||
// Hit a door, abandon so that we don't weld it shut.
|
||||
return door != null && !door.CanBeTraversed;
|
||||
}
|
||||
return false;
|
||||
}))
|
||||
{
|
||||
character.SetInput(InputType.Shoot, false, true);
|
||||
Use(deltaTime, character);
|
||||
repairTimer += deltaTime;
|
||||
if (repairTimer > repairTimeOut)
|
||||
// Check that we don't hit any friendlies
|
||||
if (Submarine.PickBodies(item.SimPosition, leak.SimPosition, collisionCategory: Physics.CollisionCharacter).None(hit =>
|
||||
{
|
||||
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);
|
||||
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
|
||||
return true;
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the timer so that we don't time out if the water forces push us away
|
||||
repairTimer = 0;
|
||||
}
|
||||
|
||||
bool leakFixed = (leak.Open <= 0.0f || leak.Removed) &&
|
||||
(leak.ConnectedWall == null || leak.ConnectedWall.Sections.Average(s => s.damage) < 1);
|
||||
@@ -791,6 +809,12 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
|
||||
return leakFixed;
|
||||
|
||||
void Reset()
|
||||
{
|
||||
sinTime = 0;
|
||||
repairTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyStatusEffectsOnTarget(Character user, float deltaTime, ActionType actionType, IEnumerable<ISerializableEntity> targets)
|
||||
@@ -821,7 +845,7 @@ namespace Barotrauma.Items.Components
|
||||
foreach (ISerializableEntity target in targets)
|
||||
{
|
||||
if (!(target is Door door)) { continue; }
|
||||
if (!door.CanBeWelded || door.Item.NonInteractable) { continue; }
|
||||
if (!door.CanBeWelded || !door.Item.IsInteractable(user)) { continue; }
|
||||
for (int i = 0; i < effect.propertyNames.Length; i++)
|
||||
{
|
||||
string propertyName = effect.propertyNames[i];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
@@ -83,7 +84,7 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
if (picker == null || picker.Removed || !picker.HasSelectedItem(item))
|
||||
if (picker == null || picker.Removed || !picker.HeldItems.Contains(item))
|
||||
{
|
||||
IsActive = false;
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user