v1.4.4.1 (Blood in the Water Update)

This commit is contained in:
Regalis11
2024-04-24 18:09:05 +03:00
parent 89b91d1c3e
commit ff1b8951a7
397 changed files with 15250 additions and 6479 deletions
@@ -176,12 +176,13 @@ namespace Barotrauma
}
}
public override bool CanEnterSubmarine
public override CanEnterSubmarine CanEnterSubmarine
{
get
{
//can't enter a submarine when attached to something
return Character.AnimController.CanEnterSubmarine && (LatchOntoAI == null || !LatchOntoAI.IsAttachedToSub);
//can't enter a submarine when attached to one
if (LatchOntoAI is { IsAttachedToSub: true }) { return CanEnterSubmarine.False; }
return Character.AnimController.CanEnterSubmarine;
}
}
@@ -535,12 +536,27 @@ namespace Barotrauma
FadeMemories(updateMemoriesInverval);
updateMemoriesTimer = updateMemoriesInverval;
}
if (Math.Max(Character.HealthPercentage, 0) < FleeHealthThreshold && SelectedAiTarget != null &&
SelectedAiTarget.Entity is Character target && (target.IsHuman && CanPerceive(SelectedAiTarget) || IsBeingChasedBy(target)))
if (Math.Max(Character.HealthPercentage, 0) < FleeHealthThreshold && SelectedAiTarget != null)
{
// Keep fleeing if being chased
State = AIState.Flee;
Character target = SelectedAiTarget.Entity as Character;
if (target == null && SelectedAiTarget.Entity is Item targetItem)
{
target = GetOwner(targetItem);
}
bool shouldFlee = false;
if (target != null)
{
// Keep fleeing if being chased or if we see a human target (that don't have enemy ai).
shouldFlee = target.IsHuman && CanPerceive(SelectedAiTarget) || IsBeingChasedBy(target);
}
// If we should not flee, just idle. Don't allow any other AI state when below the health threshold.
State = shouldFlee ? AIState.Flee : AIState.Idle;
wallTarget = null;
if (State != AIState.Flee)
{
SelectedAiTarget = null;
_lastAiTarget = null;
}
}
else
{
@@ -614,7 +630,7 @@ namespace Barotrauma
steeringManager = outsideSteering;
}
}
bool useSteeringLengthAsMovementSpeed = State == AIState.Idle && Character.AnimController.InWater;
bool run = false;
switch (State)
@@ -870,11 +886,11 @@ namespace Barotrauma
}
// Ensure that the creature keeps inside the level
SteerInsideLevel(deltaTime);
float defaultSpeed = Character.AnimController.GetCurrentSpeed(run && Character.CanRun);
//calculate a normalized Steering value at this point: we multiply it with the actual, desired speed in ApplyMovementLimits
steeringManager.Update(1.0f);
float speed = useSteeringLengthAsMovementSpeed ? Steering.Length() : defaultSpeed;
Character.AnimController.TargetMovement = Character.ApplyMovementLimits(Steering, speed);
float speed = Character.AnimController.GetCurrentSpeed(run && Character.CanRun);
// Doesn't work if less than 1, when we use steering length as movement speed.
steeringManager.Update(Math.Max(speed, 1.0f));
float movementSpeed = useSteeringLengthAsMovementSpeed ? Steering.Length() : speed;
Character.AnimController.TargetMovement = Character.ApplyMovementLimits(Steering, movementSpeed);
if (Character.CurrentHull != null && Character.AnimController.InWater)
{
// Limit the swimming speed inside the sub.
@@ -1087,6 +1103,22 @@ namespace Barotrauma
// How long the monster tries to reach out for the target when it's close to it before ignoring it.
private const float reachTimeOut = 10;
private bool IsSameTarget(AITarget target, AITarget otherTarget)
{
if (target?.Entity == otherTarget?.Entity) { return true; }
if (IsItemInCharacterInventory(target, otherTarget) || IsItemInCharacterInventory(otherTarget, target)) { return true; }
return false;
bool IsItemInCharacterInventory(AITarget potentialItem, AITarget potentialCharacter)
{
if (potentialItem?.Entity is Item item && potentialCharacter?.Entity is Character character)
{
return item.ParentInventory?.Owner == character;
}
return false;
}
}
private void UpdateAttack(float deltaTime)
{
if (SelectedAiTarget == null || SelectedAiTarget.Entity == null || SelectedAiTarget.Entity.Removed)
@@ -1132,7 +1164,7 @@ namespace Barotrauma
attackSimPos = Character.GetRelativeSimPosition(SelectedAiTarget.Entity);
}
if (Character.AnimController.CanEnterSubmarine)
if (Character.AnimController.CanEnterSubmarine == CanEnterSubmarine.True)
{
if (TrySteerThroughGaps(deltaTime))
{
@@ -1177,13 +1209,21 @@ namespace Barotrauma
if (IsCoolDownRunning && (_previousAttackLimb == null || AttackLimb == null || AttackLimb.attack.CoolDownTimer > 0))
{
var currentAttackLimb = AttackLimb ?? _previousAttackLimb;
if (currentAttackLimb.attack.CoolDownTimer >= currentAttackLimb.attack.CoolDown + currentAttackLimb.attack.CurrentRandomCoolDown - currentAttackLimb.attack.AfterAttackDelay)
if (currentAttackLimb.attack.CoolDownTimer >=
currentAttackLimb.attack.CoolDown + currentAttackLimb.attack.CurrentRandomCoolDown - currentAttackLimb.attack.AfterAttackDelay)
{
return;
}
AIBehaviorAfterAttack activeBehavior = currentAttackLimb.attack.AfterAttack;
currentAttackLimb.attack.AfterAttackTimer += deltaTime;
AIBehaviorAfterAttack activeBehavior =
currentAttackLimb.attack.AfterAttackSecondaryDelay > 0 && currentAttackLimb.attack.AfterAttackTimer > currentAttackLimb.attack.AfterAttackSecondaryDelay ?
currentAttackLimb.attack.AfterAttackSecondary :
currentAttackLimb.attack.AfterAttack;
switch (activeBehavior)
{
case AIBehaviorAfterAttack.Eat:
UpdateEating(deltaTime);
return;
case AIBehaviorAfterAttack.Pursue:
case AIBehaviorAfterAttack.PursueIfCanAttack:
if (currentAttackLimb.attack.SecondaryCoolDown <= 0)
@@ -1205,7 +1245,7 @@ namespace Barotrauma
if (currentAttackLimb.attack.SecondaryCoolDownTimer <= 0)
{
// Don't allow attacking when the attack target has just changed.
if (_previousAiTarget != null && SelectedAiTarget != _previousAiTarget)
if (_previousAiTarget != null && !IsSameTarget(SelectedAiTarget, _previousAiTarget))
{
canAttack = false;
if (activeBehavior == AIBehaviorAfterAttack.PursueIfCanAttack)
@@ -1266,27 +1306,24 @@ namespace Barotrauma
if (currentAttackLimb.attack.SecondaryCoolDownTimer <= 0)
{
// Don't allow attacking when the attack target has just changed.
if (_previousAiTarget != null && SelectedAiTarget != _previousAiTarget)
if (_previousAiTarget != null && !IsSameTarget(SelectedAiTarget, _previousAiTarget))
{
UpdateFallBack(attackWorldPos, deltaTime, activeBehavior == AIBehaviorAfterAttack.FollowThroughUntilCanAttack);
return;
}
// If the secondary cooldown is defined and expired, check if we can switch the attack
var newLimb = GetAttackLimb(attackWorldPos, currentAttackLimb);
if (newLimb != null)
{
// Attack with the new limb
AttackLimb = newLimb;
}
else
{
// If the secondary cooldown is defined and expired, check if we can switch the attack
var newLimb = GetAttackLimb(attackWorldPos, currentAttackLimb);
if (newLimb != null)
{
// Attack with the new limb
AttackLimb = newLimb;
}
else
{
// No new limb was found.
UpdateFallBack(attackWorldPos, deltaTime, activeBehavior == AIBehaviorAfterAttack.FollowThroughUntilCanAttack);
return;
}
}
// No new limb was found.
UpdateFallBack(attackWorldPos, deltaTime, activeBehavior == AIBehaviorAfterAttack.FollowThroughUntilCanAttack);
return;
}
}
else
{
@@ -1308,27 +1345,24 @@ namespace Barotrauma
if (currentAttackLimb.attack.SecondaryCoolDownTimer <= 0)
{
// Don't allow attacking when the attack target has just changed.
if (_previousAiTarget != null && SelectedAiTarget != _previousAiTarget)
if (_previousAiTarget != null && !IsSameTarget(SelectedAiTarget, _previousAiTarget))
{
UpdateIdle(deltaTime, followLastTarget: false);
return;
}
// If the secondary cooldown is defined and expired, check if we can switch the attack
var newLimb = GetAttackLimb(attackWorldPos, currentAttackLimb);
if (newLimb != null)
{
// Attack with the new limb
AttackLimb = newLimb;
}
else
{
// If the secondary cooldown is defined and expired, check if we can switch the attack
var newLimb = GetAttackLimb(attackWorldPos, currentAttackLimb);
if (newLimb != null)
{
// Attack with the new limb
AttackLimb = newLimb;
}
else
{
// No new limb was found.
UpdateIdle(deltaTime, followLastTarget: false);
return;
}
}
// No new limb was found.
UpdateIdle(deltaTime, followLastTarget: false);
return;
}
}
else
{
@@ -1341,6 +1375,9 @@ namespace Barotrauma
case AIBehaviorAfterAttack.FollowThrough:
UpdateFallBack(attackWorldPos, deltaTime, followThrough: true);
return;
case AIBehaviorAfterAttack.FollowThroughWithoutObstacleAvoidance:
UpdateFallBack(attackWorldPos, deltaTime, followThrough: true, avoidObstacles: false);
return;
case AIBehaviorAfterAttack.FallBack:
case AIBehaviorAfterAttack.Reverse:
default:
@@ -1724,7 +1761,7 @@ namespace Barotrauma
circleRotationSpeed *= Rand.Range(1 - selectedTargetingParams.CircleRandomRotationFactor, 1 + selectedTargetingParams.CircleRandomRotationFactor);
aggressionIntensity = Math.Clamp(aggressionIntensity, AIParams.StartAggression, AIParams.MaxAggression);
DisableAttacksIfLimbNotRanged();
if (targetSub != null && targetSub.Borders.Width < 1000 && AttackLimb?.attack is { Ranged: false })
if (targetSub is { Borders.Width: < 1000 } && AttackLimb?.attack is { Ranged: false })
{
breakCircling = true;
CirclePhase = CirclePhase.CloseIn;
@@ -1982,7 +2019,7 @@ namespace Barotrauma
Entity targetEntity = wallTarget?.Structure ?? SelectedAiTarget?.Entity;
if (AttackLimb?.attack is Attack { Ranged: true } attack)
{
AimRangedAttack(attack, targetEntity);
AimRangedAttack(attack, attackTargetLimb as ISpatialEntity ?? targetEntity);
}
if (canAttack)
{
@@ -2005,9 +2042,10 @@ namespace Barotrauma
}
}
public void AimRangedAttack(Attack attack, Entity targetEntity)
public void AimRangedAttack(Attack attack, ISpatialEntity targetEntity)
{
if (attack is not { Ranged: true } || targetEntity is not { Removed: false }) { return; }
if (attack is not { Ranged: true }) { return; }
if (targetEntity is Entity { Removed: true }) { return; }
Character.SetInput(InputType.Aim, false, true);
if (attack.AimRotationTorque <= 0) { return; }
Limb limb = GetLimbToRotate(attack);
@@ -2115,7 +2153,10 @@ namespace Barotrauma
bool wasLatched = IsLatchedOnSub;
Character.AnimController.ReleaseStuckLimbs();
LatchOntoAI?.DeattachFromBody(reset: true, cooldown: 1);
if (attackResult.Damage > 0)
{
LatchOntoAI?.DeattachFromBody(reset: true, cooldown: 1);
}
if (attacker == null || attacker.AiTarget == null || attacker.Removed || attacker.IsDead) { return; }
if (attackResult.Damage >= AIParams.DamageThreshold)
{
@@ -2283,7 +2324,7 @@ namespace Barotrauma
Limb referenceLimb = GetLimbToRotate(ActiveAttack);
if (referenceLimb != null)
{
Vector2 toTarget = spatialTarget.WorldPosition - referenceLimb.WorldPosition;
Vector2 toTarget = attackWorldPos - referenceLimb.WorldPosition;
float offset = referenceLimb.Params.GetSpriteOrientation() - MathHelper.PiOver2;
Vector2 forward = VectorExtensions.Forward(referenceLimb.body.TransformedRotation - offset * referenceLimb.Dir);
float angle = MathHelper.ToDegrees(VectorExtensions.Angle(forward, toTarget));
@@ -2456,7 +2497,7 @@ namespace Barotrauma
}
private Vector2? attackVector = null;
private bool UpdateFallBack(Vector2 attackWorldPos, float deltaTime, bool followThrough, bool checkBlocking = false)
private bool UpdateFallBack(Vector2 attackWorldPos, float deltaTime, bool followThrough, bool checkBlocking = false, bool avoidObstacles = true)
{
if (attackVector == null)
{
@@ -2468,7 +2509,7 @@ namespace Barotrauma
dir = Vector2.UnitY;
}
steeringManager.SteeringManual(deltaTime, dir);
if (Character.AnimController.InWater && !Reverse)
if (Character.AnimController.InWater && !Reverse && avoidObstacles)
{
SteeringManager.SteeringAvoid(deltaTime, lookAheadDistance: avoidLookAheadDistance, weight: 15);
}
@@ -2779,10 +2820,16 @@ namespace Barotrauma
// Ignore inner walls when outside (walltargets still work)
continue;
}
if (!Character.AnimController.CanEnterSubmarine && IsWallDisabled(s))
bool attemptToGetInside =
Character.AnimController.CanEnterSubmarine == CanEnterSubmarine.True ||
//characters that are aggressive boarders can partially enter the sub can attempt to push through holes
(Character.AnimController.CanEnterSubmarine == CanEnterSubmarine.Partial && IsAggressiveBoarder);
if (!attemptToGetInside && IsWallDisabled(s))
{
continue;
}
// Prefer weaker walls (200 is the default for normal hull walls)
valueModifier = 200f / s.MaxHealth;
for (int i = 0; i < s.Sections.Length; i++)
@@ -2790,7 +2837,7 @@ namespace Barotrauma
var section = s.Sections[i];
if (section.gap == null) { continue; }
bool leadsInside = !section.gap.IsRoomToRoom && section.gap.FlowTargetHull != null;
if (Character.AnimController.CanEnterSubmarine)
if (attemptToGetInside)
{
if (!isCharacterInside)
{
@@ -2873,9 +2920,11 @@ namespace Barotrauma
{
if (!canAttackDoors) { continue; }
}
else if (!Character.AnimController.CanEnterSubmarine)
else if (Character.AnimController.CanEnterSubmarine != CanEnterSubmarine.True)
{
// Ignore broken and open doors, if cannot enter submarine
// Also ignore them if the monster can only partially enter the sub:
// these monsters tend to be too large to get through doors anyway.
continue;
}
if (IsAggressiveBoarder)
@@ -2911,6 +2960,13 @@ namespace Barotrauma
if (targetParams.IgnoreInside && Character.CurrentHull != null) { continue; }
if (targetParams.IgnoreOutside && Character.CurrentHull == null) { continue; }
if (targetParams.IgnoreIncapacitated && targetCharacter != null && targetCharacter.IsIncapacitated) { continue; }
if (targetParams.IgnoreTargetInside && aiTarget.Entity.Submarine != null) { continue; }
if (targetParams.IgnoreTargetOutside && aiTarget.Entity.Submarine == null) { continue; }
if (aiTarget.Entity is ISerializableEntity se)
{
if (targetParams.Conditionals.Any(c => !c.TargetSelf && !c.Matches(se))) { continue; }
}
if (targetParams.Conditionals.Any(c => c.TargetSelf && !c.Matches(Character))) { continue; }
if (targetParams.IgnoreIfNotInSameSub)
{
if (aiTarget.Entity.Submarine != Character.Submarine) { continue; }
@@ -2981,6 +3037,16 @@ namespace Barotrauma
{
dist *= 0.9f;
}
if (targetParams.PerceptionDistanceMultiplier > 0.0f)
{
dist /= targetParams.PerceptionDistanceMultiplier;
}
if (targetParams.MaxPerceptionDistance > 0.0f &&
dist * dist > targetParams.MaxPerceptionDistance * targetParams.MaxPerceptionDistance)
{
continue;
}
if (!CanPerceive(aiTarget, dist, checkVisibility: SelectedAiTarget != aiTarget))
{
@@ -3196,7 +3262,7 @@ namespace Barotrauma
{
if ((SelectedAiTarget != null || wallTarget != null) && IsLatchedOnSub)
{
if (!(SelectedAiTarget?.Entity is Structure wall))
if (SelectedAiTarget?.Entity is not Structure wall)
{
wall = wallTarget?.Structure;
}
@@ -3251,9 +3317,10 @@ namespace Barotrauma
if (HasValidPath(requireNonDirty: true)) { return; }
wallHits.Clear();
Structure wall = null;
Vector2 rayStart = AttackLimb != null ? AttackLimb.SimPosition : SimPosition;
Vector2 refPos = AttackLimb != null ? AttackLimb.SimPosition : SimPosition;
if (AIParams.WallTargetingMethod.HasFlag(WallTargetingMethod.Target))
{
Vector2 rayStart = refPos;
Vector2 rayEnd = SelectedAiTarget.SimPosition;
if (SelectedAiTarget.Entity.Submarine != null && Character.Submarine == null)
{
@@ -3267,6 +3334,7 @@ namespace Barotrauma
}
if (AIParams.WallTargetingMethod.HasFlag(WallTargetingMethod.Heading))
{
Vector2 rayStart = refPos;
Vector2 rayEnd = rayStart + VectorExtensions.Forward(Character.AnimController.Collider.Rotation + MathHelper.PiOver2, avoidLookAheadDistance * 5);
if (SelectedAiTarget.Entity.Submarine != null && Character.Submarine == null)
{
@@ -3282,6 +3350,7 @@ namespace Barotrauma
}
if (AIParams.WallTargetingMethod.HasFlag(WallTargetingMethod.Steering))
{
Vector2 rayStart = refPos;
Vector2 rayEnd = rayStart + Steering * 5;
if (SelectedAiTarget.Entity.Submarine != null && Character.Submarine == null)
{
@@ -3297,18 +3366,25 @@ namespace Barotrauma
}
if (wallHits.Any())
{
Vector2 targetdiff = ConvertUnits.ToSimUnits(SelectedAiTarget.WorldPosition - (AttackLimb != null ? AttackLimb.WorldPosition : WorldPosition));
float targetDistance = targetdiff.LengthSquared();
Body closestBody = null;
float closestDistance = 0;
int sectionIndex = -1;
Vector2 sectionPos = Vector2.Zero;
foreach ((Body body, int index, Vector2 sectionPosition) in wallHits)
{
float distance = Vector2.DistanceSquared(SimPosition, sectionPosition);
Structure structure = body.UserData as Structure;
float distance = Vector2.DistanceSquared(
refPos,
Submarine.GetRelativeSimPosition(ConvertUnits.ToSimUnits(sectionPosition), Character.Submarine, structure.Submarine));
//if the wall is further than the target (e.g. at the other side of the sub?), we shouldn't be targeting it
if (distance > targetDistance) { continue; }
if (closestBody == null || closestDistance == 0 || distance < closestDistance)
{
closestBody = body;
closestDistance = distance;
wall = closestBody.UserData as Structure;
wall = structure;
sectionPos = sectionPosition;
sectionIndex = index;
}
@@ -3326,14 +3402,18 @@ namespace Barotrauma
sectionPos.X += (wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2 * attachTargetNormal.X;
}
LatchOntoAI?.SetAttachTarget(wall, ConvertUnits.ToSimUnits(sectionPos), attachTargetNormal);
if (Character.AnimController.CanEnterSubmarine || !wall.SectionBodyDisabled(sectionIndex) && !IsWallDisabled(wall))
if (Character.AnimController.CanEnterSubmarine == CanEnterSubmarine.True ||
!wall.SectionBodyDisabled(sectionIndex) && !IsWallDisabled(wall))
{
if (wall.NoAITarget && Character.AnimController.CanEnterSubmarine)
if (wall.NoAITarget && Character.AnimController.CanEnterSubmarine == CanEnterSubmarine.True)
{
bool isTargetingDoor = SelectedAiTarget.Entity is Item i && i.GetComponent<Door>() != null;
// Blocked by a wall that shouldn't be targeted. The main intention here is to prevent monsters from entering the the tail and the nose pieces.
if (!isTargetingDoor)
{
//TODO: this might cause problems: many wall pieces (like smaller shuttle pieces
//and small decorative wall structures are currently marked as having no AI target,
//which can mean a monster very frequently ignores targets inside because they're blocked by those structures
IgnoreTarget(SelectedAiTarget);
ResetAITarget();
}
@@ -3353,7 +3433,9 @@ namespace Barotrauma
void DoRayCast(Vector2 rayStart, Vector2 rayEnd)
{
Body hitTarget = Submarine.CheckVisibility(rayStart, rayEnd, ignoreSubs: true, ignoreSensors: CanEnterSubmarine, ignoreDisabledWalls: CanEnterSubmarine);
Body hitTarget = Submarine.CheckVisibility(rayStart, rayEnd, ignoreSubs: true,
ignoreSensors: CanEnterSubmarine != CanEnterSubmarine.False,
ignoreDisabledWalls: CanEnterSubmarine != CanEnterSubmarine.False);
if (hitTarget != null && IsValid(hitTarget, out wall))
{
int sectionIndex = wall.FindSectionIndex(ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition));
@@ -3371,7 +3453,8 @@ namespace Barotrauma
{
if (wall.SectionBodyDisabled(i))
{
if (Character.AnimController.CanEnterSubmarine && CanPassThroughHole(wall, i, requiredHoleCount))
if (Character.AnimController.CanEnterSubmarine != CanEnterSubmarine.False &&
CanPassThroughHole(wall, i, requiredHoleCount))
{
sectionIndex = i;
break;
@@ -3394,14 +3477,14 @@ namespace Barotrauma
{
wall = null;
if (Submarine.LastPickedFraction == 1.0f) { return false; }
if (!(hit.UserData is Structure w)) { return false; }
if (hit.UserData is not Structure w) { return false; }
if (w.Submarine == null) { return false; }
if (w.Submarine != SelectedAiTarget.Entity.Submarine) { return false; }
if (Character.Submarine == null)
{
if (w.Prefab.Tags.Contains("inner"))
{
if (!Character.AnimController.CanEnterSubmarine) { return false; }
if (Character.AnimController.CanEnterSubmarine == CanEnterSubmarine.False) { return false; }
}
else if (!AIParams.TargetOuterWalls)
{
@@ -3731,7 +3814,7 @@ namespace Barotrauma
}
reachTimer = 0;
sinTime = 0;
if (breakCircling && strikeTimer <= 0)
if (breakCircling && strikeTimer <= 0 && CirclePhase != CirclePhase.CloseIn)
{
CirclePhase = CirclePhase.Start;
}
@@ -3757,7 +3840,7 @@ namespace Barotrauma
blockCheckTimer = 0;
reachTimer = 0;
sinTime = 0;
if (breakCircling && strikeTimer <= 0)
if (breakCircling && strikeTimer <= 0 && CirclePhase != CirclePhase.CloseIn)
{
CirclePhase = CirclePhase.Start;
}
@@ -3765,7 +3848,12 @@ namespace Barotrauma
private void SetStateResetTimer() => stateResetTimer = stateResetCooldown * Rand.Range(0.75f, 1.25f);
private float GetPerceivingRange(AITarget target) => Math.Max(target.SightRange * Sight, target.SoundRange * Hearing);
private float GetPerceivingRange(AITarget target)
{
float maxSightOrSoundRange = Math.Max(target.SightRange * Sight, target.SoundRange * Hearing);
if (AIParams.MaxPerceptionDistance >= 0 && maxSightOrSoundRange > AIParams.MaxPerceptionDistance) { return AIParams.MaxPerceptionDistance; }
return maxSightOrSoundRange;
}
private bool CanPerceive(AITarget target, float dist = -1, float distSquared = -1, bool checkVisibility = false)
{
@@ -3783,6 +3871,7 @@ namespace Barotrauma
}
if (dist > 0)
{
if (AIParams.MaxPerceptionDistance >= 0 && dist > AIParams.MaxPerceptionDistance) { return false; }
insideSightRange = IsInRange(dist, target.SightRange, Sight);
if (!checkVisibility && insideSightRange) { return true; }
insideSoundRange = IsInRange(dist, target.SoundRange, Hearing);
@@ -3793,6 +3882,7 @@ namespace Barotrauma
{
distSquared = Vector2.DistanceSquared(Character.WorldPosition, target.WorldPosition);
}
if (AIParams.MaxPerceptionDistance >= 0 && distSquared > AIParams.MaxPerceptionDistance * AIParams.MaxPerceptionDistance) { return false; }
insideSightRange = IsInRangeSqr(distSquared, target.SightRange, Sight);
if (!checkVisibility && insideSightRange) { return true; }
insideSoundRange = IsInRangeSqr(distSquared, target.SoundRange, Hearing);