v1.0.13.1 (first post-1.0 patch)
This commit is contained in:
@@ -561,6 +561,12 @@ namespace Barotrauma.Items.Components
|
||||
gap.ConnectedDoor = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (OutsideSubmarineFixture != null)
|
||||
{
|
||||
OutsideSubmarineFixture.Body.Remove(OutsideSubmarineFixture);
|
||||
OutsideSubmarineFixture = 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
|
||||
|
||||
@@ -600,7 +600,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
//no further data needed, the event just triggers the discharge
|
||||
msg.WriteUInt16(user?.ID ?? Entity.NullEntityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,7 +700,8 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
Vector2 attachPos = GetAttachPosition(character, useWorldCoordinates: true);
|
||||
Submarine attachSubmarine = Structure.GetAttachTarget(attachPos)?.Submarine ?? item.Submarine;
|
||||
int maxAttachableCount = (int)character.Info.GetSavedStatValue(StatTypes.MaxAttachableCount, item.Prefab.Identifier);
|
||||
int maxAttachableCount = (int)character.Info.GetSavedStatValueWithBotsInMp(StatTypes.MaxAttachableCount, item.Prefab.Identifier);
|
||||
|
||||
int currentlyAttachedCount = Item.ItemList.Count(
|
||||
i => i.Submarine == attachSubmarine && i.GetComponent<Holdable>() is Holdable holdable && holdable.Attached && i.Prefab.Identifier == item.Prefab.Identifier);
|
||||
if (maxAttachableCount == 0)
|
||||
|
||||
@@ -260,7 +260,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Vector2 barrelPos = TransformedBarrelPos + item.body.SimPosition;
|
||||
float rotation = (Item.body.Dir == 1.0f) ? Item.body.Rotation : Item.body.Rotation - MathHelper.Pi;
|
||||
float spread = GetSpread(character) * Projectile.GetSpreadFromPool(projectile.SpreadCounter);
|
||||
float spread = GetSpread(character) * projectile.GetSpreadFromPool();
|
||||
|
||||
var lastProjectile = LastProjectile;
|
||||
if (lastProjectile != projectile)
|
||||
@@ -277,7 +277,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
Item.body.ApplyLinearImpulse(new Vector2((float)Math.Cos(projectile.Item.body.Rotation), (float)Math.Sin(projectile.Item.body.Rotation)) * Item.body.Mass * -50.0f, maxVelocity: NetConfig.MaxPhysicsBodyVelocity);
|
||||
}
|
||||
projectile.Item.body.ApplyTorque(projectile.Item.body.Mass * degreeOfFailure * 20.0f * Projectile.GetSpreadFromPool(projectile.SpreadCounter));
|
||||
projectile.Item.body.ApplyTorque(projectile.Item.body.Mass * degreeOfFailure * 20.0f * projectile.GetSpreadFromPool());
|
||||
}
|
||||
Item.RemoveContained(projectile.Item);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,9 @@ namespace Barotrauma.Items.Components
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Can the item repair multiple things at once, or will it only affect the first thing the ray from the barrel hits.")]
|
||||
public bool RepairMultiple { get; set; }
|
||||
|
||||
[Serialize(true, IsPropertySaveable.No, description: "Can the item repair multiple walls at once? Only relevant if RepairMultiple is true.")]
|
||||
public bool RepairMultipleWalls { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Can the item repair things through holes in walls.")]
|
||||
public bool RepairThroughHoles { get; set; }
|
||||
|
||||
@@ -383,6 +386,7 @@ namespace Barotrauma.Items.Components
|
||||
//stop the ray if it already hit a door/wall and is now about to hit some other type of entity
|
||||
if (lastHitType == typeof(Item) || lastHitType == typeof(Structure)) { break; }
|
||||
}
|
||||
if (!RepairMultipleWalls && (bodyType == typeof(Structure) || (body.UserData as Item)?.GetComponent<Door>() != null)) { break; }
|
||||
|
||||
Character hitCharacter = null;
|
||||
if (body.UserData is Limb limb)
|
||||
|
||||
@@ -236,7 +236,7 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(0f, IsPropertySaveable.No, description: "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). Note that there's also a generic BotPriority for all item prefabs.")]
|
||||
[Serialize(0f, IsPropertySaveable.No, description: "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 forced). Note that there's also a generic BotPriority for all item prefabs.")]
|
||||
public float CombatPriority { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -687,9 +687,10 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public virtual void FlipY(bool relativeToSub) { }
|
||||
|
||||
public bool IsNotEmpty(Character user, bool checkContainedItems = true) =>
|
||||
HasRequiredContainedItems(user, addMessage: false) &&
|
||||
(!checkContainedItems || Item.OwnInventory == null || Item.OwnInventory.AllItems.Any(i => i.Condition > 0));
|
||||
/// <summary>
|
||||
/// Shorthand for !HasRequiredContainedItems()
|
||||
/// </summary>
|
||||
public bool IsEmpty(Character user) => !HasRequiredContainedItems(user, addMessage: false);
|
||||
|
||||
public bool HasRequiredContainedItems(Character user, bool addMessage, LocalizedString msg = null)
|
||||
{
|
||||
|
||||
@@ -511,25 +511,28 @@ namespace Barotrauma.Items.Components
|
||||
if (activeContainedItem.ExcludeFullCondition && contained.IsFullCondition) { continue; }
|
||||
StatusEffect effect = activeContainedItem.StatusEffect;
|
||||
|
||||
targets.Clear();
|
||||
bool wearing = item.GetComponent<Wearable>() is Wearable { IsActive: true };
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.This))
|
||||
{
|
||||
effect.Apply(ActionType.OnContaining, deltaTime, item, item.AllPropertyObjects);
|
||||
targets.AddRange(item.AllPropertyObjects);
|
||||
}
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.Contained))
|
||||
{
|
||||
effect.Apply(ActionType.OnContaining, deltaTime, item, contained.AllPropertyObjects);
|
||||
targets.AddRange(contained.AllPropertyObjects);
|
||||
}
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.Character) && item.ParentInventory?.Owner is Character character)
|
||||
{
|
||||
effect.Apply(ActionType.OnContaining, deltaTime, item, character);
|
||||
targets.Add(character);
|
||||
}
|
||||
if (effect.HasTargetType(StatusEffect.TargetType.NearbyItems) ||
|
||||
effect.HasTargetType(StatusEffect.TargetType.NearbyCharacters))
|
||||
{
|
||||
targets.Clear();
|
||||
effect.AddNearbyTargets(item.WorldPosition, targets);
|
||||
effect.Apply(ActionType.OnActive, deltaTime, item, targets);
|
||||
}
|
||||
effect.Apply(ActionType.OnActive, deltaTime, item, targets);
|
||||
effect.Apply(ActionType.OnContaining, deltaTime, item, targets);
|
||||
if (wearing) { effect.Apply(ActionType.OnWearing, deltaTime, item, targets); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ namespace Barotrauma.Items.Components
|
||||
itemList.Enabled = true;
|
||||
if (amountInput != null)
|
||||
{
|
||||
amountInput.Enabled = true;
|
||||
amountInput.Enabled = amountTextMax.Enabled;
|
||||
}
|
||||
RefreshActivateButtonText();
|
||||
#endif
|
||||
|
||||
@@ -14,19 +14,18 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Projectile : ItemComponent, IServerSerializable
|
||||
{
|
||||
const int SpreadCounterWrapAround = 256;
|
||||
|
||||
private static readonly ImmutableArray<float> spreadPool;
|
||||
static Projectile()
|
||||
{
|
||||
MTRandom random = new MTRandom(0);
|
||||
spreadPool = Enumerable.Range(0, SpreadCounterWrapAround).Select(f => (float)random.NextDouble() - 0.5f).ToImmutableArray();
|
||||
spreadPool = Enumerable.Range(0, byte.MaxValue + 1).Select(f => (float)random.NextDouble() - 0.5f).ToImmutableArray();
|
||||
}
|
||||
|
||||
public static float GetSpreadFromPool(int seed)
|
||||
public static byte SpreadCounter { get; private set; }
|
||||
|
||||
public static void ResetSpreadCounter()
|
||||
{
|
||||
if (seed < 0) { seed = -seed; }
|
||||
return spreadPool[seed % SpreadCounterWrapAround];
|
||||
SpreadCounter = 0;
|
||||
}
|
||||
|
||||
struct HitscanResult
|
||||
@@ -63,7 +62,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private bool removePending;
|
||||
|
||||
public byte SpreadCounter { get; private set; }
|
||||
private byte spreadIndex;
|
||||
|
||||
//continuous collision detection is used while the projectile is moving faster than this
|
||||
const float ContinuousCollisionThreshold = 5.0f;
|
||||
@@ -212,7 +211,7 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Override random spread with static spread; hitscan are launched with an equal amount of angle between them. Only applies when firing multiple hitscan.")]
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Override random spread with static spread; projectiles are launched with an equal amount of angle between them. Only applies when firing multiple projectiles.")]
|
||||
public bool StaticSpread
|
||||
{
|
||||
get;
|
||||
@@ -300,7 +299,8 @@ namespace Barotrauma.Items.Components
|
||||
return;
|
||||
}
|
||||
|
||||
SpreadCounter = (byte)(item.ID % SpreadCounterWrapAround);
|
||||
spreadIndex = SpreadCounter;
|
||||
SpreadCounter++;
|
||||
|
||||
InitProjSpecific(element);
|
||||
}
|
||||
@@ -329,6 +329,12 @@ namespace Barotrauma.Items.Components
|
||||
originalCollisionTargets = item.body.CollidesWith;
|
||||
}
|
||||
|
||||
public float GetSpreadFromPool()
|
||||
{
|
||||
spreadIndex = (byte)MathUtils.PositiveModulo(spreadIndex, spreadPool.Length);
|
||||
return spreadPool[spreadIndex];
|
||||
}
|
||||
|
||||
private void Launch(Character user, Vector2 simPosition, float rotation, float damageMultiplier = 1f, float launchImpulseModifier = 0f)
|
||||
{
|
||||
if (Item.body == null) { return; }
|
||||
@@ -380,8 +386,8 @@ namespace Barotrauma.Items.Components
|
||||
if (createNetworkEvent && !Item.Removed && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
|
||||
{
|
||||
#if SERVER
|
||||
launchRot = rotation;
|
||||
Item.CreateServerEvent(this, new EventData(launch: true, spreadCounter: (byte)(SpreadCounter - 1)));
|
||||
launchRot = rotation;
|
||||
Item.CreateServerEvent(this, new EventData(launch: true, spreadCounter: (byte)(spreadIndex - 1)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -390,24 +396,22 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (character != null && !characterUsable) { return false; }
|
||||
if (item.body == null) { return false; }
|
||||
//can't launch if already launched
|
||||
if (StickTarget != null || IsActive) { return false; }
|
||||
|
||||
float initialRotation = item.body.Rotation;
|
||||
for (int i = 0; i < HitScanCount; i++)
|
||||
{
|
||||
float launchAngle;
|
||||
|
||||
if (StaticSpread)
|
||||
{
|
||||
float staticSpread = Spread / (HitScanCount - 1);
|
||||
// because the position of the item changes as hitscan are fired, we will set an
|
||||
// initial offset on the first hitscan and then increase the item's angle by a set amount as hitscan are fired
|
||||
float offset = i == 0 ? -staticSpread * (HitScanCount -1) : 0f;
|
||||
launchAngle = item.body.Rotation + MathHelper.ToRadians(staticSpread + offset);
|
||||
launchAngle = initialRotation + MathHelper.ToRadians(i - ((float)(HitScanCount - 1) / 2)) * Spread;
|
||||
}
|
||||
else
|
||||
{
|
||||
launchAngle = item.body.Rotation + MathHelper.ToRadians(Spread * GetSpreadFromPool(SpreadCounter));
|
||||
launchAngle = initialRotation + MathHelper.ToRadians(Spread * GetSpreadFromPool());
|
||||
}
|
||||
SpreadCounter++;
|
||||
spreadIndex++;
|
||||
|
||||
Vector2 launchDir = new Vector2((float)Math.Cos(launchAngle), (float)Math.Sin(launchAngle));
|
||||
if (Hitscan)
|
||||
|
||||
@@ -243,14 +243,7 @@ namespace Barotrauma.Items.Components
|
||||
for (int i = 0; i < labels.Length; i++)
|
||||
{
|
||||
labels[i] = i < newLabels.Length ? newLabels[i] : customInterfaceElementList[i].Label;
|
||||
if (Screen.Selected != GameMain.SubEditorScreen)
|
||||
{
|
||||
customInterfaceElementList[i].Label = TextManager.Get(labels[i]).Fallback(labels[i]).Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
customInterfaceElementList[i].Label = labels[i];
|
||||
}
|
||||
customInterfaceElementList[i].Label = labels[i];
|
||||
}
|
||||
UpdateLabelsProjSpecific();
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ namespace Barotrauma.Items.Components
|
||||
Position = item.Position,
|
||||
CastShadows = castShadows,
|
||||
IsBackground = drawBehindSubs,
|
||||
SpriteScale = Vector2.One * item.Scale,
|
||||
SpriteScale = Vector2.One * item.Scale * LightSpriteScale,
|
||||
Range = range
|
||||
};
|
||||
Light.LightSourceParams.Flicker = flicker;
|
||||
@@ -309,13 +309,14 @@ namespace Barotrauma.Items.Components
|
||||
#if CLIENT
|
||||
Light.ParentSub = item.Submarine;
|
||||
#endif
|
||||
if (item.Container != null && item.GetRootInventoryOwner() is not Character)
|
||||
var ownerCharacter = item.GetRootInventoryOwner() as Character;
|
||||
if ((item.Container != null && ownerCharacter == null) ||
|
||||
(ownerCharacter != null && ownerCharacter.InvisibleTimer > 0.0f))
|
||||
{
|
||||
lightBrightness = 0.0f;
|
||||
SetLightSourceState(false, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
SetLightSourceTransformProjSpecific();
|
||||
|
||||
PhysicsBody body = ParentBody ?? item.body;
|
||||
|
||||
@@ -56,11 +56,9 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
private float resetUserTimer;
|
||||
|
||||
private float aiTargetingGraceTimer;
|
||||
|
||||
private float aiFindTargetTimer;
|
||||
private ISpatialEntity currentTarget;
|
||||
private const float CrewAiFindTargetMaxInterval = 3.0f;
|
||||
private const float CrewAiFindTargetMaxInterval = 1.0f;
|
||||
private const float CrewAIFindTargetMinInverval = 0.2f;
|
||||
|
||||
private int currentLoaderIndex;
|
||||
@@ -299,7 +297,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
[Serialize(3000.0f, IsPropertySaveable.Yes, description: "How close to a target the turret has to be for an AI character to fire it.")]
|
||||
[Serialize(3500.0f, IsPropertySaveable.Yes, description: "How close to a target the turret has to be for an AI character to fire it.")]
|
||||
public float AIRange
|
||||
{
|
||||
get;
|
||||
@@ -422,10 +420,7 @@ namespace Barotrauma.Items.Components
|
||||
// Only make the Turret control the LightComponents that are it's children. So it'd be possible to for example have some extra lights on the turret that don't rotate with it.
|
||||
if (lc?.Parent == this)
|
||||
{
|
||||
if (lightComponents == null)
|
||||
{
|
||||
lightComponents = new List<LightComponent>();
|
||||
}
|
||||
lightComponents ??= new List<LightComponent>();
|
||||
lightComponents.Add(lc);
|
||||
}
|
||||
}
|
||||
@@ -439,6 +434,8 @@ namespace Barotrauma.Items.Components
|
||||
light.Parent = null;
|
||||
light.Rotation = Rotation - item.RotationRad;
|
||||
light.Light.Rotation = -rotation;
|
||||
//turret lights are high-prio (don't want the lights to disappear when you're fighting something)
|
||||
light.Light.PriorityMultiplier *= 10.0f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -590,10 +587,6 @@ namespace Barotrauma.Items.Components
|
||||
angularVelocity *= -0.5f;
|
||||
}
|
||||
|
||||
if (aiTargetingGraceTimer > 0f)
|
||||
{
|
||||
aiTargetingGraceTimer -= deltaTime;
|
||||
}
|
||||
if (aiFindTargetTimer > 0.0f)
|
||||
{
|
||||
aiFindTargetTimer -= deltaTime;
|
||||
@@ -620,10 +613,18 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime);
|
||||
|
||||
private bool isUseBeingCalled;
|
||||
|
||||
public override bool Use(float deltaTime, Character character = null)
|
||||
{
|
||||
if (!characterUsable && character != null) { return false; }
|
||||
return TryLaunch(deltaTime, character);
|
||||
//prevent an infinite loop if launching triggers a StatusEffect that Uses this item
|
||||
if (isUseBeingCalled) { return false; }
|
||||
|
||||
isUseBeingCalled = true;
|
||||
bool wasSuccessful = TryLaunch(deltaTime, character);
|
||||
isUseBeingCalled = false;
|
||||
return wasSuccessful;
|
||||
}
|
||||
|
||||
public float GetPowerRequiredToShoot()
|
||||
@@ -1015,6 +1016,7 @@ namespace Barotrauma.Items.Components
|
||||
float dist = Vector2.DistanceSquared(item.WorldPosition, targetItem.WorldPosition);
|
||||
if (dist > closestDist) { continue; }
|
||||
if (dist > shootDistance * shootDistance) { continue; }
|
||||
if (!IsTargetItemCloseEnough(targetItem, dist)) { continue; }
|
||||
if (!CheckTurretAngle(targetItem.WorldPosition)) { continue; }
|
||||
target = targetItem;
|
||||
closestDist = dist / priority;
|
||||
@@ -1130,9 +1132,12 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (character.AIController.SelectedAiTarget?.Entity is Character previousTarget && previousTarget.IsDead)
|
||||
{
|
||||
character.Speak(TextManager.Get("DialogTurretTargetDead").Value,
|
||||
identifier: $"killedtarget{previousTarget.ID}".ToIdentifier(),
|
||||
minDurationBetweenSimilar: 10.0f);
|
||||
if (previousTarget.LastAttacker == null || previousTarget.LastAttacker == character)
|
||||
{
|
||||
character.Speak(TextManager.Get("DialogTurretTargetDead").Value,
|
||||
identifier: $"killedtarget{previousTarget.ID}".ToIdentifier(),
|
||||
minDurationBetweenSimilar: 5.0f);
|
||||
}
|
||||
character.AIController.SelectTarget(null);
|
||||
}
|
||||
|
||||
@@ -1265,18 +1270,27 @@ namespace Barotrauma.Items.Components
|
||||
Vector2? targetPos = null;
|
||||
float maxDistance = 10000;
|
||||
float shootDistance = AIRange * item.OffsetOnSelectedMultiplier;
|
||||
// use full range only if we're actively firing
|
||||
if (aiTargetingGraceTimer <= 0f)
|
||||
{
|
||||
shootDistance *= 0.75f;
|
||||
}
|
||||
|
||||
float closestDistance = maxDistance * maxDistance;
|
||||
|
||||
bool hadCurrentTarget = currentTarget != null;
|
||||
if (hadCurrentTarget)
|
||||
{
|
||||
if (!IsValidTarget(currentTarget))
|
||||
bool isValidTarget = IsValidTarget(currentTarget);
|
||||
if (isValidTarget)
|
||||
{
|
||||
float dist = Vector2.DistanceSquared(item.WorldPosition, currentTarget.WorldPosition);
|
||||
if (dist > closestDistance)
|
||||
{
|
||||
isValidTarget = false;
|
||||
}
|
||||
else if (currentTarget is Item targetItem)
|
||||
{
|
||||
if (!IsTargetItemCloseEnough(targetItem, dist))
|
||||
{
|
||||
isValidTarget = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isValidTarget)
|
||||
{
|
||||
currentTarget = null;
|
||||
aiFindTargetTimer = CrewAIFindTargetMinInverval;
|
||||
@@ -1292,7 +1306,11 @@ namespace Barotrauma.Items.Components
|
||||
if (character.Submarine != null)
|
||||
{
|
||||
if (enemy.Submarine == character.Submarine) { continue; }
|
||||
if (enemy.Submarine != null && enemy.Submarine.TeamID == character.Submarine.TeamID) { continue; }
|
||||
if (enemy.Submarine != null)
|
||||
{
|
||||
if (enemy.Submarine.TeamID == character.Submarine.TeamID) { continue; }
|
||||
if (enemy.Submarine.Info.IsOutpost) { continue; }
|
||||
}
|
||||
}
|
||||
// Don't aim monsters that are inside any submarine.
|
||||
if (!enemy.IsHuman && enemy.CurrentHull != null) { continue; }
|
||||
@@ -1318,6 +1336,7 @@ namespace Barotrauma.Items.Components
|
||||
float dist = Vector2.DistanceSquared(item.WorldPosition, targetItem.WorldPosition);
|
||||
if (dist > closestDistance) { continue; }
|
||||
if (dist > shootDistance * shootDistance) { continue; }
|
||||
if (!IsTargetItemCloseEnough(targetItem, dist)) { continue; }
|
||||
if (!CheckTurretAngle(targetItem.WorldPosition)) { continue; }
|
||||
targetPos = targetItem.WorldPosition;
|
||||
closestDistance = dist / priority;
|
||||
@@ -1325,14 +1344,7 @@ namespace Barotrauma.Items.Components
|
||||
closestEnemy = null;
|
||||
currentTarget = targetItem;
|
||||
}
|
||||
if (currentTarget == null)
|
||||
{
|
||||
aiFindTargetTimer = CrewAIFindTargetMinInverval;
|
||||
}
|
||||
else
|
||||
{
|
||||
aiFindTargetTimer = CrewAiFindTargetMaxInterval;
|
||||
}
|
||||
aiFindTargetTimer = currentTarget == null ? CrewAiFindTargetMaxInterval : CrewAIFindTargetMinInverval;
|
||||
}
|
||||
else if (currentTarget != null)
|
||||
{
|
||||
@@ -1346,6 +1358,10 @@ namespace Barotrauma.Items.Components
|
||||
if (targetCharacter.Submarine != null && targetCharacter.CurrentHull != null && targetCharacter.Submarine != item.Submarine && !targetCharacter.CanSeeTarget(Item))
|
||||
{
|
||||
targetPos = targetCharacter.CurrentHull.WorldPosition;
|
||||
if (closestDistance > maxDistance * maxDistance)
|
||||
{
|
||||
ResetTarget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1365,12 +1381,17 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
if (closestDist > shootDistance * shootDistance)
|
||||
{
|
||||
// Not close enough to shoot.
|
||||
currentTarget = null;
|
||||
closestEnemy = null;
|
||||
targetPos = null;
|
||||
aiFindTargetTimer = CrewAIFindTargetMinInverval;
|
||||
ResetTarget();
|
||||
}
|
||||
}
|
||||
void ResetTarget()
|
||||
{
|
||||
// Not close enough to shoot.
|
||||
currentTarget = null;
|
||||
closestEnemy = null;
|
||||
targetPos = null;
|
||||
}
|
||||
}
|
||||
else if (targetPos == null && item.Submarine != null && Level.Loaded != null)
|
||||
{
|
||||
@@ -1520,10 +1541,11 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
character.SetInput(InputType.Shoot, true, true);
|
||||
}
|
||||
aiTargetingGraceTimer = 5f;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsTargetItemCloseEnough(Item target, float sqrDist) => float.IsPositiveInfinity(target.Prefab.AITurretTargetingMaxDistance) || sqrDist < MathUtils.Pow2(target.Prefab.AITurretTargetingMaxDistance);
|
||||
|
||||
/// <summary>
|
||||
/// Turret doesn't consume grid power, directly takes from the batteries on its grid instead.
|
||||
/// </summary>
|
||||
@@ -1553,6 +1575,10 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (targetItem.ParentInventory != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1568,6 +1594,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (item.Submarine != null)
|
||||
{
|
||||
if (item.Submarine.Info.IsOutpost) { return false; }
|
||||
// Check that the target is not in the friendly team, e.g. pirate or a hostile player sub (PvP).
|
||||
return !target.IsOnFriendlyTeam(item.Submarine.TeamID) && TargetHumans;
|
||||
}
|
||||
@@ -1660,7 +1687,7 @@ namespace Barotrauma.Items.Components
|
||||
return angle >= minRotation && angle <= maxRotation;
|
||||
}
|
||||
|
||||
private bool CheckTurretAngle(Vector2 target) => CheckTurretAngle(-MathUtils.VectorToAngle(target - item.WorldPosition));
|
||||
public bool CheckTurretAngle(Vector2 target) => CheckTurretAngle(-MathUtils.VectorToAngle(target - item.WorldPosition));
|
||||
|
||||
protected override void RemoveComponentSpecific()
|
||||
{
|
||||
|
||||
@@ -288,7 +288,7 @@ namespace Barotrauma.Items.Components
|
||||
public bool AutoEquipWhenFull { get; private set; }
|
||||
public bool DisplayContainedStatus { get; private set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Can the item be used (assuming it has components that are usable in some way) when worn."), Editable(MinValueFloat = -1000.0f, MaxValueFloat = 1000.0f)]
|
||||
[Serialize(false, IsPropertySaveable.No, description: "Can the item be used (assuming it has components that are usable in some way) when worn.")]
|
||||
public bool AllowUseWhenWorn { get; set; }
|
||||
|
||||
public readonly int Variants;
|
||||
|
||||
Reference in New Issue
Block a user