(a97ef2847) AI improvements: - Fix steering issues when attacking (yet again): We still have to offset the sim positions. - Fix the steering vector when escaping from the enemy that is inside the sub. - Enemies can now navigate out from the sub, when escaping. - Fix door tag not being used when targeting items. Change the priority boosts considering doors. Should now entirely ignore the outer doors when inside and inner doors when outside. - Change the way enemies react to characters that are not in the same sub. Halve the priority when the character is not in the same hull. Add some boost to the priority when escaping.

This commit is contained in:
Joonas Rikkonen
2019-03-25 19:50:02 +02:00
parent 19d5ed5d66
commit fd5d2b86af
12 changed files with 265 additions and 148 deletions

View File

@@ -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);

View File

@@ -1,13 +1,14 @@
using Barotrauma.Networking;
using Barotrauma.Particles;
using Barotrauma.Sounds;
using Lidgren.Network;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Input;
using System.Linq;
using Lidgren.Network;
namespace Barotrauma
{
@@ -18,8 +19,6 @@ namespace Barotrauma
private List<Decal> decals = new List<Decal>();
private float serverUpdateDelay;
private float remoteWaterVolume, remoteOxygenPercentage;
private List<Vector3> remoteFireSources;
private bool networkUpdatePending;
private float networkUpdateTimer;
@@ -140,10 +139,6 @@ namespace Barotrauma
partial void UpdateProjSpecific(float deltaTime, Camera cam)
{
serverUpdateDelay -= deltaTime;
if (serverUpdateDelay <= 0.0f)
{
ApplyRemoteState();
}
if (networkUpdatePending)
{
@@ -552,18 +547,18 @@ namespace Barotrauma
public void ClientRead(ServerNetObject type, NetBuffer message, float sendingTime)
{
remoteWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
float newWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
float newOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
bool hasFireSources = message.ReadBoolean();
int fireSourceCount = 0;
remoteFireSources = new List<Vector3>();
List<Vector3> newFireSources = new List<Vector3>();
if (hasFireSources)
{
fireSourceCount = message.ReadRangedInteger(0, 16);
for (int i = 0; i < fireSourceCount; i++)
{
remoteFireSources.Add(new Vector3(
newFireSources.Add(new Vector3(
MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
message.ReadRangedSingle(0.0f, 1.0f, 8)));
@@ -572,6 +567,41 @@ namespace Barotrauma
if (serverUpdateDelay > 0.0f) { return; }
WaterVolume = newWaterVolume;
OxygenPercentage = newOxygenPercentage;
for (int i = 0; i < fireSourceCount; i++)
{
Vector2 pos = new Vector2(
rect.X + rect.Width * newFireSources[i].X,
rect.Y - rect.Height + (rect.Height * newFireSources[i].Y));
float size = newFireSources[i].Z * rect.Width;
var newFire = i < FireSources.Count ?
FireSources[i] :
new FireSource(Submarine == null ? pos : pos + Submarine.Position, null, true);
newFire.Position = pos;
newFire.Size = new Vector2(size, newFire.Size.Y);
//ignore if the fire wasn't added to this room (invalid position)?
if (!FireSources.Contains(newFire))
{
newFire.Remove();
continue;
}
}
for (int i = FireSources.Count - 1; i >= fireSourceCount; i--)
{
FireSources[i].Remove();
if (i < FireSources.Count)
{
FireSources.RemoveAt(i);
}
}
if (serverUpdateDelay > 0.0f) { return; }
ApplyRemoteState();
}

View File

@@ -20,16 +20,6 @@ namespace Barotrauma
partial void UpdateProjSpecific(float deltaTime, Camera cam)
{
if (IdFreed) { return; }
//don't create updates if all clients are very far from the hull
float hullUpdateDistanceSqr = NetConfig.HullUpdateDistance * NetConfig.HullUpdateDistance;
if (!GameMain.Server.ConnectedClients.Any(c =>
c.Character != null &&
Vector2.DistanceSquared(c.Character.WorldPosition, WorldPosition) < hullUpdateDistanceSqr))
{
return;
}
//update client hulls if the amount of water has changed by >10%
//or if oxygen percentage has changed by 5%
if (Math.Abs(lastSentVolume - waterVolume) > Volume * 0.1f ||
@@ -41,8 +31,8 @@ namespace Barotrauma
GameMain.NetworkMember.CreateEntityEvent(this);
lastSentVolume = waterVolume;
lastSentOxygen = OxygenPercentage;
sendUpdateTimer = NetConfig.HullUpdateInterval;
}
sendUpdateTimer = NetworkUpdateInterval;
}
}
}

View File

@@ -352,6 +352,12 @@ namespace Barotrauma.Networking
client.EntityEventLastSent[entityEvent.ID] = NetTime.Now;
}
foreach (NetEntityEvent entityEvent in sentEvents)
{
(entityEvent as ServerEntityEvent).Sent = true;
client.EntityEventLastSent[entityEvent.ID] = NetTime.Now;
}
foreach (NetEntityEvent entityEvent in sentEvents)
{
(entityEvent as ServerEntityEvent).Sent = true;

View File

@@ -26,7 +26,6 @@ namespace Barotrauma
}
}
public class TargetingPriority
{
public string TargetTag;
@@ -100,6 +99,9 @@ namespace Barotrauma
private readonly float aggressiongreed;
private readonly float aggressionhurt;
// TODO: expose?
private readonly float priorityFearIncreasement = 2;
private readonly float memoryFadeTime = 0.5f;
public bool AttackHumans
{
@@ -385,7 +387,7 @@ namespace Barotrauma
#endregion
#region Escape
private Vector2 escapePoint;
private void UpdateEscape(float deltaTime)
{
if (SelectedAiTarget == null || SelectedAiTarget.Entity == null || SelectedAiTarget.Entity.Removed)
@@ -393,13 +395,44 @@ namespace Barotrauma
State = AIState.Idle;
return;
}
Vector2 escapeDir = Vector2.Normalize(SimPosition - SelectedAiTarget.SimPosition);
if (!MathUtils.IsValid(escapeDir)) escapeDir = Vector2.UnitY;
SteeringManager.SteeringManual(deltaTime, escapeDir);
SteeringManager.SteeringWander();
if (Character.CurrentHull == null)
else if (selectedTargetMemory != null)
{
selectedTargetMemory.Priority += deltaTime * priorityFearIncreasement;
}
if (Character.CurrentHull != null)
{
// Seek exit, if inside
if (SteeringManager is IndoorsSteeringManager indoorSteering && escapePoint == Vector2.Zero)
{
foreach (Gap gap in Gap.GapList)
{
if (gap.Submarine != Character.Submarine) { continue; }
if (gap.Open < 1 || gap.IsRoomToRoom) { continue; }
var path = indoorSteering.PathFinder.FindPath(Character.SimPosition, gap.SimPosition);
if (!path.Unreachable)
{
if (escapePoint != Vector2.Zero)
{
// Ignore the gap if it's further away than the previously assigned escape point
if (Vector2.DistanceSquared(Character.SimPosition, gap.SimPosition) > Vector2.DistanceSquared(Character.SimPosition, escapePoint)) { continue; }
}
escapePoint = gap.SimPosition;
}
}
}
}
if (escapePoint != Vector2.Zero && Vector2.DistanceSquared(Character.SimPosition, escapePoint) > 1)
{
SteeringManager.SteeringSeek(escapePoint);
}
else
{
// If outside or near enough the escapePoint, steer away
escapePoint = Vector2.Zero;
Vector2 escapeDir = Vector2.Normalize(WorldPosition - SelectedAiTarget.WorldPosition);
if (!MathUtils.IsValid(escapeDir)) escapeDir = Vector2.UnitY;
SteeringManager.SteeringManual(deltaTime, escapeDir);
SteeringManager.SteeringWander();
SteeringManager.SteeringAvoid(deltaTime, colliderSize * 3.0f);
}
}
@@ -443,16 +476,7 @@ namespace Barotrauma
raycastTimer = RaycastInterval;
}
if (wallTarget != null)
{
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)
if (SelectedAiTarget.Entity is Character c)
{
//target the closest limb if the target is a character
float closestDist = Vector2.DistanceSquared(SelectedAiTarget.WorldPosition, WorldPosition) * 10.0f;
@@ -469,14 +493,22 @@ namespace Barotrauma
}
}
// Take the sub position into account in the sim pos
if (Character.Submarine == null && SelectedAiTarget.Entity.Submarine != null)
if (wallTarget != null)
{
attackSimPos += SelectedAiTarget.Entity.Submarine.SimPosition;
attackWorldPos = wallTarget.Position;
attackSimPos = ConvertUnits.ToSimUnits(attackWorldPos);
}
else if (Character.Submarine != null && SelectedAiTarget.Entity.Submarine == null)
else
{
attackSimPos -= Character.Submarine.SimPosition;
// 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)
@@ -490,32 +522,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<Door>();
@@ -528,6 +554,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 +565,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;
}
@@ -670,8 +700,11 @@ namespace Barotrauma
{
if (indoorsSteering.CurrentPath.Unreachable)
{
//wander around randomly and decrease the priority faster if no path is found
if (selectedTargetMemory != null) selectedTargetMemory.Priority -= deltaTime * 10.0f;
if (selectedTargetMemory != null)
{
//wander around randomly and decrease the priority faster if no path is found
selectedTargetMemory.Priority -= deltaTime * memoryFadeTime * 10;
}
SteeringManager.SteeringWander();
}
else if (indoorsSteering.CurrentPath.Finished)
@@ -702,6 +735,34 @@ namespace Barotrauma
}
}
private bool SteerThroughGap(Structure wall, WallSection section, Vector2 targetWorldPos, float deltaTime)
{
Hull targetHull = section.gap?.FlowTargetHull;
if (targetHull != null)
{
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 +786,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,7 +793,7 @@ namespace Barotrauma
if (offset)
{
rayStart -= ConvertUnits.ToSimUnits(SelectedAiTarget.Entity.Submarine.Position);
rayStart -= SelectedAiTarget.Entity.Submarine.SimPosition;
}
Body closestBody = Submarine.CheckVisibility(rayStart, rayEnd, ignoreSubs: true);
@@ -785,8 +841,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);
}
}
@@ -945,8 +1005,13 @@ namespace Barotrauma
targetingTag = "dead";
if (targetCharacter.Submarine != Character.Submarine)
{
// In a different sub or the target is outside when we are inside or vice versa -> Significantly reduce the value
valueModifier = 0.1f;
// In a different sub or the target is outside when we are inside or vice versa -> Ignore the target
continue;
}
else if (targetCharacter.CurrentHull != Character.CurrentHull)
{
// In the same sub, halve the priority, if not in the same hull.
valueModifier = 0.5f;
}
}
else if (targetCharacter.AIController is EnemyAIController enemy)
@@ -959,10 +1024,23 @@ namespace Barotrauma
{
targetingTag = "weaker";
}
if (targetCharacter.Submarine != Character.Submarine)
if (State == AIState.Escape && targetingTag == "stronger")
{
// In a different sub or the target is outside when we are inside or vice versa -> Significantly reduce the value
valueModifier = 0.1f;
// Frightened
valueModifier = 2;
}
else
{
if (targetCharacter.Submarine != Character.Submarine)
{
// In a different sub or the target is outside when we are inside or vice versa -> Ignore the target
continue;
}
else if (targetCharacter.CurrentHull != Character.CurrentHull)
{
// In the same sub, halve the priority, if not in the same hull.
valueModifier = 0.5f;
}
}
}
else if (targetCharacter.Submarine != null && Character.Submarine == null)
@@ -1002,14 +1080,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;
}
}
@@ -1021,12 +1112,36 @@ namespace Barotrauma
}
if (door != null)
{
//increase priority if the character is outside and an aggressive boarder, and the door is from outside to inside
if (character.CurrentHull == null && aggressiveBoarding && !door.LinkedGap.IsRoomToRoom)
// If there's not a more specific tag for the door
if (string.IsNullOrEmpty(targetingTag) || targetingTag == "room")
{
valueModifier = door.IsOpen ? 5 : 3;
targetingTag = "door";
}
else if (door.IsOpen || door.Item.Condition <= 0.0f) //ignore broken and open doors
bool isOutdoor = door.LinkedGap?.FlowTargetHull != null && !door.LinkedGap.IsRoomToRoom;
bool isOpen = door.IsOpen || door.Item.Condition <= 0.0f;
//increase priority if the character is outside and an aggressive boarder, and the door is from outside to inside
if (aggressiveBoarding)
{
if (character.CurrentHull == null)
{
valueModifier = isOutdoor ? 1 : 0;
valueModifier *= isOpen ? 5 : 1;
}
}
}
else if (target.Entity is Structure s)
{
targetingTag = "wall";
if (character.CurrentHull == null && aggressiveBoarding)
{
valueModifier = s.HasBody ? 2 : 0;
foreach (var section in s.Sections)
{
valueModifier = isOutdoor ? 0 : 1;
valueModifier *= isOpen ? 0 : 1;
}
}
else if (isOpen) //ignore broken and open doors
{
continue;
}
@@ -1094,7 +1209,6 @@ namespace Barotrauma
return memory;
}
private float memoryFadeTime = 0.5f;
private List<AITarget> removals = new List<AITarget>();
private void UpdateTargetMemories(float deltaTime)
{
@@ -1118,6 +1232,8 @@ namespace Barotrauma
{
latchOntoAI?.DeattachFromBody();
Character.AnimController.ReleaseStuckLimbs();
escapePoint = Vector2.Zero;
wallTarget = null;
}
private int GetMinimumPassableHoleCount()

View File

@@ -520,9 +520,10 @@ namespace Barotrauma
// Ignore blocking on items, because it causes cases where a Mudraptor cannot hit the hatch, for example.
wasHit = true;
}
else if (damageTarget is Structure && structureBody?.UserData is Structure)
else if (damageTarget is Structure wall && structureBody != null &&
(structureBody.UserData is Structure || (structureBody.UserData is Submarine sub && sub == wall.Submarine)))
{
// If the attack is aimed to a structure and hits a structure, it's successful
// If the attack is aimed to a structure (wall) and hits a structure or the sub, it's successful
wasHit = true;
}
else

View File

@@ -208,7 +208,7 @@ namespace Barotrauma
DockingPort myPort = null, outPostPort = null;
foreach (DockingPort port in DockingPort.List)
{
if (port.IsHorizontal || port.Docked) { continue; }
if (port.IsHorizontal) { continue; }
if (port.Item.Submarine == level.StartOutpost)
{
outPostPort = port;

View File

@@ -175,11 +175,12 @@ namespace Barotrauma
LimitSize();
UpdateProjSpecific(growModifier);
if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
{
Remove();
}
#if CLIENT
if (GameMain.Client != null) return;
#endif
if (size.X < 1.0f) Remove();
}
partial void UpdateProjSpecific(float growModifier);
@@ -292,6 +293,10 @@ namespace Barotrauma
//evaporate some of the water
hull.WaterVolume -= extinguishAmount;
#if CLIENT
if (GameMain.Client != null) return;
#endif
if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
{
Remove();
@@ -320,11 +325,12 @@ namespace Barotrauma
size.X -= extinguishAmount;
hull.WaterVolume -= extinguishAmount;
if (size.X < 1.0f && (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer))
{
Remove();
}
#if CLIENT
if (GameMain.Client != null) return;
#endif
if (size.X < 1.0f) Remove();
}
public void Extinguish(float deltaTime, float amount, Vector2 worldPosition)

View File

@@ -1522,40 +1522,14 @@ namespace Barotrauma
outpost.MakeOutpost();
Point? minSize = null;
DockingPort subPort = null;
if (Submarine.MainSub != null)
{
Point subSize = Submarine.MainSub.GetDockedBorders().Size;
Point outpostSize = outpost.GetDockedBorders().Size;
minSize = new Point(Math.Max(subSize.X, outpostSize.X), subSize.Y + outpostSize.Y);
float closestDistance = float.MaxValue;
foreach (DockingPort port in DockingPort.List)
{
if (port.IsHorizontal || port.Docked) { continue; }
if (port.Item.Submarine != Submarine.MainSub) { continue; }
//the submarine port has to be at the top of the sub
if (port.Item.WorldPosition.Y < Submarine.MainSub.WorldPosition.Y) { continue; }
float dist = Math.Abs(port.Item.WorldPosition.X - Submarine.MainSub.WorldPosition.X);
if (dist < closestDistance)
{
subPort = port;
closestDistance = dist;
}
}
}
float subDockingPortOffset = subPort == null ? 0.0f : subPort.Item.WorldPosition.X - Submarine.MainSub.WorldPosition.X;
//don't try to compensate if the port is very far from the sub's center of mass
if (Math.Abs(subDockingPortOffset) > 2000.0f)
{
subDockingPortOffset = MathHelper.Clamp(subDockingPortOffset, -2000.0f, 2000.0f);
string warningMsg = "Docking port very far from the sub's center of mass (submarine: " + Submarine.MainSub.Name + ", dist: " + subDockingPortOffset + "). The level generator may not be able to place the outpost so that docking is possible.";
DebugConsole.NewMessage(warningMsg, Color.Orange);
GameAnalyticsManager.AddErrorEventOnce("Lever.CreateOutposts:DockingPortVeryFar" + Submarine.MainSub.Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Warning, warningMsg);
}
outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize, subDockingPortOffset));
outpost.SetPosition(outpost.FindSpawnPos(i == 0 ? StartPosition : EndPosition, minSize));
if ((i == 0) == !Mirrored)
{
StartOutpost = outpost;

View File

@@ -432,16 +432,12 @@ namespace Barotrauma
{
if (ForceFluctuationStrength > 0.0f)
{
//no need for force fluctuation (or network updates) if the trigger limits velocity and there are no triggerers
if (forceMode != TriggerForceMode.LimitVelocity || triggerers.Any())
forceFluctuationTimer += deltaTime;
if (forceFluctuationTimer > ForceFluctuationInterval)
{
forceFluctuationTimer += deltaTime;
if (forceFluctuationTimer > ForceFluctuationInterval)
{
NeedsNetworkSyncing = true;
currentForceFluctuation = Rand.Range(1.0f - ForceFluctuationStrength, 1.0f);
forceFluctuationTimer = 0.0f;
}
NeedsNetworkSyncing = true;
currentForceFluctuation = Rand.Range(1.0f - ForceFluctuationStrength, 1.0f);
forceFluctuationTimer = 0.0f;
}
}

View File

@@ -494,7 +494,7 @@ namespace Barotrauma
}
}
public Vector2 FindSpawnPos(Vector2 spawnPos, Point? submarineSize = null, float subDockingPortOffset = 0.0f)
public Vector2 FindSpawnPos(Vector2 spawnPos, Point? submarineSize = null)
{
Rectangle dockedBorders = GetDockedBorders();
Vector2 diffFromDockedBorders =
@@ -542,17 +542,17 @@ namespace Barotrauma
else if (minX < 0)
{
//no wall found at the left side, spawn to the left from the right-side wall
spawnPos.X = maxX - minWidth - 100.0f + subDockingPortOffset;
spawnPos.X = maxX - minWidth - 100.0f;
}
else if (maxX > Level.Loaded.Size.X)
{
//no wall found at right side, spawn to the right from the left-side wall
spawnPos.X = minX + minWidth + 100.0f + subDockingPortOffset;
spawnPos.X = minX + minWidth + 100.0f;
}
else
{
//walls found at both sides, use their midpoint
spawnPos.X = (minX + maxX) / 2 + subDockingPortOffset;
spawnPos.X = (minX + maxX) / 2;
}
spawnPos.Y = Math.Min(spawnPos.Y, Level.Loaded.Size.Y - dockedBorders.Height / 2 - 10);

View File

@@ -35,9 +35,8 @@ namespace Barotrauma.Networking
public const float DeleteDisconnectedTime = 20.0f;
public const float ItemConditionUpdateInterval = 0.15f;
public const float LevelObjectUpdateInterval = 0.5f;
public const float HullUpdateInterval = 0.5f;
public const float HullUpdateDistance = 20000.0f;
public const int MaxEventPacketsPerUpdate = 4;