Unstable 1.1.14.0
This commit is contained in:
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using FarseerPhysics;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -13,6 +14,7 @@ namespace Barotrauma
|
||||
public readonly int MinAmount, MaxAmount;
|
||||
private readonly List<Character> monsters = new List<Character>();
|
||||
|
||||
public readonly float SpawnDistance;
|
||||
private readonly float scatter;
|
||||
private readonly float offset;
|
||||
private readonly float delayBetweenSpawns;
|
||||
@@ -56,7 +58,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public MonsterEvent(EventPrefab prefab)
|
||||
: base (prefab)
|
||||
: base(prefab)
|
||||
{
|
||||
string speciesFile = prefab.ConfigElement.GetAttributeString("characterfile", "");
|
||||
CharacterPrefab characterPrefab = CharacterPrefab.FindByFilePath(speciesFile);
|
||||
@@ -94,7 +96,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
spawnPointTag = prefab.ConfigElement.GetAttributeString("spawnpointtag", string.Empty);
|
||||
|
||||
SpawnDistance = prefab.ConfigElement.GetAttributeFloat("spawndistance", 0);
|
||||
offset = prefab.ConfigElement.GetAttributeFloat("offset", 0);
|
||||
scatter = Math.Clamp(prefab.ConfigElement.GetAttributeFloat("scatter", 500), 0, 3000);
|
||||
delayBetweenSpawns = prefab.ConfigElement.GetAttributeFloat("delaybetweenspawns", 0.1f);
|
||||
@@ -174,6 +176,15 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetDebugInfo()
|
||||
{
|
||||
return
|
||||
$"Finished: {IsFinished.ColorizeObject()}\n" +
|
||||
$"Amount: {MinAmount.ColorizeObject()} - {MaxAmount.ColorizeObject()}\n" +
|
||||
$"Spawn pending: {SpawnPending.ColorizeObject()}\n" +
|
||||
$"Spawn position: {SpawnPos.ColorizeObject()}";
|
||||
}
|
||||
|
||||
private List<Level.InterestingPosition> GetAvailableSpawnPositions()
|
||||
{
|
||||
var availablePositions = Level.Loaded.PositionsOfInterest.FindAll(p => SpawnPosType.HasFlag(p.PositionType));
|
||||
@@ -214,13 +225,14 @@ namespace Barotrauma
|
||||
return availablePositions;
|
||||
}
|
||||
|
||||
private Level.InterestingPosition chosenPosition;
|
||||
private void FindSpawnPosition(bool affectSubImmediately)
|
||||
{
|
||||
if (disallowed) { return; }
|
||||
|
||||
spawnPos = Vector2.Zero;
|
||||
var availablePositions = GetAvailableSpawnPositions();
|
||||
var chosenPosition = new Level.InterestingPosition(Point.Zero, Level.PositionType.MainPath, isValid: false);
|
||||
chosenPosition = new Level.InterestingPosition(Point.Zero, Level.PositionType.MainPath, isValid: false);
|
||||
bool isRuinOrWreck = SpawnPosType.HasFlag(Level.PositionType.Ruin) || SpawnPosType.HasFlag(Level.PositionType.Wreck);
|
||||
if (affectSubImmediately && !isRuinOrWreck && !SpawnPosType.HasFlag(Level.PositionType.Abyss))
|
||||
{
|
||||
@@ -454,52 +466,109 @@ namespace Barotrauma
|
||||
{
|
||||
if (submarine.Info.Type != SubmarineType.Player) { continue; }
|
||||
float minDist = GetMinDistanceToSub(submarine);
|
||||
if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value) < minDist * minDist) { return; }
|
||||
if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value) < minDist * minDist)
|
||||
{
|
||||
// Too close to a player sub.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
float minDistance = Prefab.SpawnDistance;
|
||||
if (minDistance <= 0)
|
||||
float spawnDistance = SpawnDistance;
|
||||
if (spawnDistance <= 0)
|
||||
{
|
||||
if (SpawnPosType.HasFlag(Level.PositionType.Cave))
|
||||
{
|
||||
minDistance = 8000;
|
||||
spawnDistance = 8000;
|
||||
}
|
||||
else if (SpawnPosType.HasFlag(Level.PositionType.Ruin))
|
||||
{
|
||||
minDistance = 5000;
|
||||
spawnDistance = 5000;
|
||||
}
|
||||
else if (SpawnPosType.HasFlag(Level.PositionType.Wreck) || SpawnPosType.HasFlag(Level.PositionType.BeaconStation))
|
||||
{
|
||||
minDistance = 3000;
|
||||
spawnDistance = 3000;
|
||||
}
|
||||
}
|
||||
if (minDistance > 0)
|
||||
if (spawnDistance > 0)
|
||||
{
|
||||
bool someoneNearby = false;
|
||||
foreach (Submarine submarine in Submarine.Loaded)
|
||||
{
|
||||
if (submarine.Info.Type != SubmarineType.Player) { continue; }
|
||||
if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value) < MathUtils.Pow2(minDistance))
|
||||
float distanceSquared = Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value);
|
||||
if (distanceSquared < MathUtils.Pow2(spawnDistance))
|
||||
{
|
||||
someoneNearby = true;
|
||||
break;
|
||||
if (chosenPosition.Submarine != null)
|
||||
{
|
||||
Vector2 from = Submarine.GetRelativeSimPositionFromWorldPosition(spawnPos.Value, chosenPosition.Submarine, chosenPosition.Submarine);
|
||||
Vector2 to = Submarine.GetRelativeSimPositionFromWorldPosition(submarine.WorldPosition, chosenPosition.Submarine, submarine);
|
||||
if (CheckLineOfSight(from, to, chosenPosition.Submarine))
|
||||
{
|
||||
// Line of sight to a player sub -> don't spawn yet.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c == Character.Controlled || c.IsRemotePlayer)
|
||||
{
|
||||
if (Vector2.DistanceSquared(c.WorldPosition, spawnPos.Value) < MathUtils.Pow2(minDistance))
|
||||
float distanceSquared = Vector2.DistanceSquared(c.WorldPosition, spawnPos.Value);
|
||||
if (distanceSquared < MathUtils.Pow2(spawnDistance))
|
||||
{
|
||||
someoneNearby = true;
|
||||
break;
|
||||
if (chosenPosition.Submarine != null)
|
||||
{
|
||||
Vector2 from = Submarine.GetRelativeSimPositionFromWorldPosition(spawnPos.Value, chosenPosition.Submarine, chosenPosition.Submarine);
|
||||
Vector2 to = Submarine.GetRelativeSimPositionFromWorldPosition(c.WorldPosition, chosenPosition.Submarine, c.Submarine);
|
||||
if (CheckLineOfSight(from, to, chosenPosition.Submarine))
|
||||
{
|
||||
// Line of sight to a player character -> don't spawn. Disable the event to prevent monsters "magically" spawning here.
|
||||
Finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!someoneNearby) { return; }
|
||||
|
||||
static bool CheckLineOfSight(Vector2 from, Vector2 to, Submarine targetSub)
|
||||
{
|
||||
var bodies = Submarine.PickBodies(from, to, ignoredBodies: null, Physics.CollisionWall);
|
||||
foreach (var b in bodies)
|
||||
{
|
||||
if (b.UserData is ISpatialEntity spatialEntity && spatialEntity.Submarine != targetSub)
|
||||
{
|
||||
// Different sub -> ignore
|
||||
continue;
|
||||
}
|
||||
if (b.UserData is Structure s && !s.IsPlatform && s.CastShadow)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (b.UserData is Item item && item.GetComponent<Door>() is Door door)
|
||||
{
|
||||
if (!door.IsBroken && !door.IsOpen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (SpawnPosType.HasFlag(Level.PositionType.Abyss) || SpawnPosType.HasFlag(Level.PositionType.AbyssCave))
|
||||
{
|
||||
bool anyInAbyss = false;
|
||||
|
||||
Reference in New Issue
Block a user