diff --git a/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs index cb2c213d0..c18e14dee 100644 --- a/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaClient/Source/Characters/AI/EnemyAIController.cs @@ -21,7 +21,6 @@ namespace Barotrauma if (wallTarget != null) { Vector2 wallTargetPos = wallTarget.Position; - if (wallTarget.Structure.Submarine != null) wallTargetPos += wallTarget.Structure.Submarine.Position; wallTargetPos.Y = -wallTargetPos.Y; GUI.DrawRectangle(spriteBatch, wallTargetPos - new Vector2(10.0f, 10.0f), new Vector2(20.0f, 20.0f), Color.Red, false); GUI.DrawLine(spriteBatch, pos, wallTargetPos, Color.Orange * 0.5f, 0, 5); diff --git a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs index 19904cd90..75fabb3e9 100644 --- a/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs +++ b/Barotrauma/BarotraumaShared/Source/Characters/AI/EnemyAIController.cs @@ -447,10 +447,6 @@ namespace Barotrauma { attackWorldPos = wallTarget.Position; attackSimPos = ConvertUnits.ToSimUnits(attackWorldPos); - if (Character.Submarine == null && wallTarget.Structure.Submarine != null) - { - attackWorldPos += wallTarget.Structure.Submarine.Position; - } } else if (SelectedAiTarget.Entity is Character c) { @@ -471,15 +467,6 @@ namespace Barotrauma // Take the sub position into account in the sim pos if (Character.Submarine == null && SelectedAiTarget.Entity.Submarine != null) - { - attackSimPos += SelectedAiTarget.Entity.Submarine.SimPosition; - } - else if (Character.Submarine != null && SelectedAiTarget.Entity.Submarine == null) - { - attackSimPos -= Character.Submarine.SimPosition; - } - - if (Math.Abs(Character.AnimController.movement.X) > 0.1f && !Character.AnimController.InWater) { Character.AnimController.TargetDir = Character.WorldPosition.X < attackWorldPos.X ? Direction.Right : Direction.Left; } @@ -490,32 +477,26 @@ namespace Barotrauma if (wallTarget != null && wallTarget.SectionIndex > -1 && CanPassThroughHole(wallTarget.Structure, wallTarget.SectionIndex)) { WallSection section = wallTarget.Structure.GetSection(wallTarget.SectionIndex); - Hull targetHull = section.gap?.FlowTargetHull; - if (targetHull != null && !section.gap.IsRoomToRoom) + Vector2 targetPos = wallTarget.Structure.SectionPosition(wallTarget.SectionIndex, true); + if (section?.gap != null && section.gap.IsRoomToRoom && SteerThroughGap(wallTarget.Structure, section, targetPos, deltaTime)) { - Vector2 targetPos = wallTarget.Structure.SectionPosition(wallTarget.SectionIndex, true); - if (wallTarget.Structure.IsHorizontal) - { - targetPos.Y = targetHull.WorldRect.Y - targetHull.Rect.Height / 2; - } - else - { - targetPos.X = targetHull.WorldRect.Center.X; - } - - latchOntoAI?.DeattachFromBody(); - Character.AnimController.ReleaseStuckLimbs(); - if (steeringManager is IndoorsSteeringManager) - { - steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetPos - Character.WorldPosition)); - } - else - { - steeringManager.SteeringSeek(ConvertUnits.ToSimUnits(targetPos)); - } return; } } + else if (SelectedAiTarget.Entity is Structure wall) + { + for (int i = 0; i < wall.Sections.Length; i++) + { + WallSection section = wall.Sections[i]; + if (CanPassThroughHole(wall, i) && section?.gap != null) + { + if (SteerThroughGap(wall, section, section.gap.WorldPosition, deltaTime)) + { + return; + } + } + } + } else if (SelectedAiTarget.Entity is Item i) { var door = i.GetComponent(); @@ -528,6 +509,8 @@ namespace Barotrauma if (Character.WorldPosition.Y < door.Item.WorldRect.Y && Character.WorldPosition.Y > door.Item.WorldRect.Y - door.Item.Rect.Height) { velocity.Y = 0; + latchOntoAI?.DeattachFromBody(); + Character.AnimController.ReleaseStuckLimbs(); steeringManager.SteeringManual(deltaTime, velocity); return; } @@ -537,6 +520,8 @@ namespace Barotrauma if (Character.WorldPosition.X < door.Item.WorldRect.X && Character.WorldPosition.X > door.Item.WorldRect.Right) { velocity.X = 0; + latchOntoAI?.DeattachFromBody(); + Character.AnimController.ReleaseStuckLimbs(); steeringManager.SteeringManual(deltaTime, velocity); return; } @@ -702,6 +687,34 @@ namespace Barotrauma } } + private bool SteerThroughGap(Structure wall, WallSection section, Vector2 targetWorldPos, float deltaTime) + { + Hull targetHull = section.gap?.FlowTargetHull; + if (targetHull != null) // && !section.gap.IsRoomToRoom + { + if (wall.IsHorizontal) + { + targetWorldPos.Y = targetHull.WorldRect.Y - targetHull.Rect.Height / 2; + } + else + { + targetWorldPos.X = targetHull.WorldRect.Center.X; + } + latchOntoAI?.DeattachFromBody(); + Character.AnimController.ReleaseStuckLimbs(); + if (steeringManager is IndoorsSteeringManager) + { + steeringManager.SteeringManual(deltaTime, Vector2.Normalize(targetWorldPos - Character.WorldPosition)); + } + else + { + steeringManager.SteeringSeek(ConvertUnits.ToSimUnits(targetWorldPos)); + } + return true; + } + return false; + } + private Limb GetAttackLimb(Vector2 attackWorldPos, Limb ignoredLimb = null) { AttackContext currentContext = Character.GetAttackContext(); @@ -725,11 +738,6 @@ namespace Barotrauma { wallTarget = null; - if (Character.AnimController.CurrentHull != null) - { - return; - } - //check if there's a wall between the target and the Character Vector2 rayStart = SimPosition; Vector2 rayEnd = SelectedAiTarget.SimPosition; @@ -737,10 +745,10 @@ namespace Barotrauma if (offset) { - rayStart -= ConvertUnits.ToSimUnits(SelectedAiTarget.Entity.Submarine.Position); + rayStart -= SelectedAiTarget.Entity.Submarine.SimPosition; } - Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd); + Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd, ignoreSubs: true); if (Submarine.LastPickedFraction == 1.0f || closestBody == null) { @@ -785,8 +793,12 @@ namespace Barotrauma sectionPos.X += (wall.BodyWidth <= 0.0f ? wall.Rect.Width : wall.BodyWidth) / 2 * attachTargetNormal.X; } + latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, sectionPos, attachTargetNormal); + if (wall.Submarine != null) + { + sectionPos += wall.Submarine.Position; + } wallTarget = new WallTarget(sectionPos, wall, sectionIndex); - latchOntoAI?.SetAttachTarget(wall.Submarine.PhysicsBody.FarseerBody, wall.Submarine, ConvertUnits.ToSimUnits(sectionPos), attachTargetNormal); } } @@ -1002,14 +1014,27 @@ namespace Barotrauma else if (target.Entity is Structure s) { targetingTag = "wall"; - if (character.CurrentHull == null && aggressiveBoarding) + if (aggressiveBoarding) { - valueModifier = s.HasBody ? 2 : 0; - foreach (var section in s.Sections) + // Ignore walls when inside. + valueModifier = character.CurrentHull == null ? 2 : 0; + if (valueModifier > 0) { - if (section.gap != null) + // Ignore structures that doesn't have a body (not walls) + valueModifier *= s.HasBody ? 1 : 0; + } + for (int i = 0; i < s.Sections.Length; i++) + { + var section = s.Sections[i]; + if (CanPassThroughHole(s, i)) { - // up to 100% more priority for every gap in the wall + // Ignore walls that can be passed through + valueModifier = 0; + break; + } + else if (section.gap != null) + { + // up to 100% priority increase for every gap in the wall valueModifier *= 1 + section.gap.Open; } }