(bcb06cc5c) Unstable v0.9.9.0

This commit is contained in:
Juan Pablo Arce
2020-03-27 15:22:59 -03:00
parent c81486a993
commit b143329701
326 changed files with 9692 additions and 4364 deletions
@@ -1,6 +1,4 @@
using Microsoft.Xna.Framework;
using System;
using System.Xml.Linq;
namespace Barotrauma
{
@@ -53,7 +51,7 @@ namespace Barotrauma
public override void Init(bool affectSubImmediately)
{
spawnPos = Level.Loaded.GetRandomItemPos(
(Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) < 0.5f) ? Level.PositionType.MainPath : Level.PositionType.Cave | Level.PositionType.Ruin,
(Rand.Value(Rand.RandSync.Server) < 0.5f) ? Level.PositionType.MainPath : Level.PositionType.Cave | Level.PositionType.Ruin,
500.0f, 10000.0f, 30.0f);
spawnPending = true;
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace Barotrauma
{
@@ -219,13 +218,44 @@ namespace Barotrauma
private void CreateEvents(ScriptedEventSet eventSet)
{
if (eventSet.ChooseRandom)
int applyCount = 1;
if (eventSet.PerRuin)
{
if (eventSet.EventPrefabs.Count > 0)
applyCount = Level.Loaded.Ruins.Count();
}
else if (eventSet.PerWreck)
{
applyCount = Submarine.Loaded.Count(s => s.Info.IsWreck && (s.ThalamusAI == null || !s.ThalamusAI.IsAlive));
}
for (int i = 0; i < applyCount; i++)
{
if (eventSet.ChooseRandom)
{
MTRandom rand = new MTRandom(ToolBox.StringToInt(level.Seed));
var eventPrefab = ToolBox.SelectWeightedRandom(eventSet.EventPrefabs, eventSet.EventPrefabs.Select(e => e.Commonness).ToList(), rand);
if (eventPrefab != null)
if (eventSet.EventPrefabs.Count > 0)
{
MTRandom rand = new MTRandom(ToolBox.StringToInt(level.Seed));
var eventPrefab = ToolBox.SelectWeightedRandom(eventSet.EventPrefabs, eventSet.EventPrefabs.Select(e => e.Commonness).ToList(), rand);
if (eventPrefab != null)
{
var newEvent = eventPrefab.CreateInstance();
newEvent.Init(true);
DebugConsole.Log("Initialized event " + newEvent.ToString());
if (!selectedEvents.ContainsKey(eventSet))
{
selectedEvents.Add(eventSet, new List<ScriptedEvent>());
}
selectedEvents[eventSet].Add(newEvent);
}
}
if (eventSet.ChildSets.Count > 0)
{
var newEventSet = SelectRandomEvents(eventSet.ChildSets);
if (newEventSet != null) { CreateEvents(newEventSet); }
}
}
else
{
foreach (ScriptedEventPrefab eventPrefab in eventSet.EventPrefabs)
{
var newEvent = eventPrefab.CreateInstance();
newEvent.Init(true);
@@ -236,30 +266,11 @@ namespace Barotrauma
}
selectedEvents[eventSet].Add(newEvent);
}
}
if (eventSet.ChildSets.Count > 0)
{
var newEventSet = SelectRandomEvents(eventSet.ChildSets);
if (newEventSet != null) { CreateEvents(newEventSet); }
}
}
else
{
foreach (ScriptedEventPrefab eventPrefab in eventSet.EventPrefabs)
{
var newEvent = eventPrefab.CreateInstance();
newEvent.Init(true);
DebugConsole.Log("Initialized event " + newEvent.ToString());
if (!selectedEvents.ContainsKey(eventSet))
{
selectedEvents.Add(eventSet, new List<ScriptedEvent>());
}
selectedEvents[eventSet].Add(newEvent);
}
foreach (ScriptedEventSet childEventSet in eventSet.ChildSets)
{
CreateEvents(childEventSet);
foreach (ScriptedEventSet childEventSet in eventSet.ChildSets)
{
CreateEvents(childEventSet);
}
}
}
}
@@ -296,11 +307,14 @@ namespace Barotrauma
0.0f, 1.0f);
//don't create new events if within 50 meters of the start/end of the level
if (distanceTraveled <= 0.0f ||
distFromStart * Physics.DisplayToRealWorldRatio < 50.0f ||
distFromEnd * Physics.DisplayToRealWorldRatio < 50.0f)
if (!eventSet.AllowAtStart)
{
return false;
if (distanceTraveled <= 0.0f ||
distFromStart * Physics.DisplayToRealWorldRatio < 50.0f ||
distFromEnd * Physics.DisplayToRealWorldRatio < 50.0f)
{
return false;
}
}
if ((Submarine.MainSub == null || distanceTraveled < eventSet.MinDistanceTraveled) &&
@@ -368,17 +382,15 @@ namespace Barotrauma
pendingEventSets.RemoveAt(i);
if (!selectedEvents.ContainsKey(eventSet))
if (selectedEvents.ContainsKey(eventSet))
{
//no events selected from this event set
continue;
//start events in this set
foreach (ScriptedEvent scriptedEvent in selectedEvents[eventSet])
{
activeEvents.Add(scriptedEvent);
}
}
//start events in this set
foreach (ScriptedEvent scriptedEvent in selectedEvents[eventSet])
{
activeEvents.Add(scriptedEvent);
}
//add child event sets to pending
foreach (ScriptedEventSet childEventSet in eventSet.ChildSets)
{
@@ -431,7 +443,7 @@ namespace Barotrauma
enemyDanger = 0.0f;
foreach (Character character in Character.CharacterList)
{
if (character.IsDead || character.IsUnconscious || !character.Enabled) continue;
if (character.IsDead || character.IsIncapacitated || !character.Enabled) continue;
EnemyAIController enemyAI = character.AIController as EnemyAIController;
if (enemyAI == null) continue;
@@ -458,7 +470,7 @@ namespace Barotrauma
int hullCount = 0;
foreach (Hull hull in Hull.hullList)
{
if (hull.Submarine == null || hull.Submarine.IsOutpost) { continue; }
if (hull.Submarine == null || hull.Submarine.Info.Type != SubmarineInfo.SubmarineType.Player) { continue; }
hullCount++;
foreach (Gap gap in hull.ConnectedGaps)
{
@@ -69,7 +69,7 @@ namespace Barotrauma
return;
}
WayPoint cargoSpawnPos = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub, true);
WayPoint cargoSpawnPos = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub, useSyncedRand: true);
if (cargoSpawnPos == null)
{
DebugConsole.ThrowError("Couldn't spawn items for cargo mission, cargo spawnpoint not found");
@@ -44,6 +44,11 @@ namespace Barotrauma
}
}
public override int TeamCount
{
get { return 2; }
}
public CombatMission(MissionPrefab prefab, Location[] locations)
: base(prefab, locations)
{
@@ -113,7 +118,7 @@ namespace Barotrauma
{
for (int i = 0; i < 2; i++)
{
if (wifiComponent.Item.Submarine == subs[i] || subs[i].DockedTo.Contains(wifiComponent.Item.Submarine))
if (wifiComponent.Item.Submarine == subs[i] || subs[i].ConnectedDockingPorts.ContainsKey(wifiComponent.Item.Submarine))
{
wifiComponent.TeamID = subs[i].TeamID;
}
@@ -74,6 +74,11 @@ namespace Barotrauma
get { return true; }
}
public virtual int TeamCount
{
get { return 1; }
}
public virtual IEnumerable<Vector2> SonarPositions
{
get { return Enumerable.Empty<Vector2>(); }
@@ -136,7 +141,7 @@ namespace Barotrauma
}
else
{
allowedMissions.AddRange(MissionPrefab.List.Where(m => ((int)(missionType & m.type)) != 0));
allowedMissions.AddRange(MissionPrefab.List.Where(m => ((int)(missionType & m.Type)) != 0));
}
allowedMissions.RemoveAll(m => isSinglePlayer ? m.MultiplayerOnly : m.SingleplayerOnly);
@@ -168,10 +173,9 @@ namespace Barotrauma
public virtual void Update(float deltaTime) { }
public virtual bool AssignTeamIDs(List<Networking.Client> clients)
public virtual void AssignTeamIDs(List<Networking.Client> clients)
{
clients.ForEach(c => c.TeamID = Character.TeamType.Team1);
return false;
}
protected void ShowMessage(int missionState)
@@ -31,7 +31,7 @@ namespace Barotrauma
private readonly ConstructorInfo constructor;
public readonly MissionType type;
public readonly MissionType Type;
public readonly bool MultiplayerOnly, SingleplayerOnly;
@@ -154,18 +154,18 @@ namespace Barotrauma
}
string missionTypeName = element.GetAttributeString("type", "");
if (!Enum.TryParse(missionTypeName, out type))
if (!Enum.TryParse(missionTypeName, out Type))
{
DebugConsole.ThrowError("Error in mission prefab \"" + Name + "\" - \"" + missionTypeName + "\" is not a valid mission type.");
return;
}
if (type == MissionType.None)
if (Type == MissionType.None)
{
DebugConsole.ThrowError("Error in mission prefab \"" + Name + "\" - mission type cannot be none.");
return;
}
constructor = missionClasses[type].GetConstructor(new[] { typeof(MissionPrefab), typeof(Location[]) });
constructor = missionClasses[Type].GetConstructor(new[] { typeof(MissionPrefab), typeof(Location[]) });
InitProjSpecific(element);
}
@@ -176,11 +176,11 @@ namespace Barotrauma
{
foreach (Pair<string, string> allowedLocationType in AllowedLocationTypes)
{
if (allowedLocationType.First.ToLowerInvariant() == "any" ||
allowedLocationType.First.ToLowerInvariant() == from.Type.Identifier.ToLowerInvariant())
if (allowedLocationType.First.Equals("any", StringComparison.OrdinalIgnoreCase) ||
allowedLocationType.First.Equals(from.Type.Identifier, StringComparison.OrdinalIgnoreCase))
{
if (allowedLocationType.Second.ToLowerInvariant() == "any" ||
allowedLocationType.Second.ToLowerInvariant() == to.Type.Identifier.ToLowerInvariant())
if (allowedLocationType.Second.Equals("any", StringComparison.OrdinalIgnoreCase) ||
allowedLocationType.Second.Equals(to.Type.Identifier, StringComparison.OrdinalIgnoreCase))
{
return true;
}
@@ -189,7 +189,7 @@ namespace Barotrauma
return false;
}
public Mission Instantiate(Location[] locations)
{
return constructor?.Invoke(new object[] { this, locations }) as Mission;
@@ -2,9 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System;
using System.Xml.Linq;
using Barotrauma.Extensions;
using Barotrauma.Networking;
namespace Barotrauma
{
@@ -113,7 +110,25 @@ namespace Barotrauma
private void InitializeMonsters(IEnumerable<Character> monsters)
{
monsters.ForEach(m => m.Enabled = false);
foreach (var monster in monsters)
{
monster.Enabled = false;
if (monster.Params.AI.EnforceAggressiveBehaviorForMissions)
{
foreach (var targetParam in monster.Params.AI.Targets)
{
switch (targetParam.State)
{
case AIState.Avoid:
case AIState.Escape:
case AIState.Flee:
case AIState.PassiveAggressive:
targetParam.State = AIState.Attack;
break;
}
}
}
}
SwarmBehavior.CreateSwarm(monsters.Cast<AICharacter>());
foreach (Character monster in monsters)
{
@@ -191,7 +206,10 @@ namespace Barotrauma
completed = true;
}
public bool IsEliminated(Character enemy) => enemy.Removed || enemy.IsDead || enemy.AIController is EnemyAIController ai && ai.State == AIState.Flee;
public bool IsEliminated(Character enemy) =>
enemy == null ||
enemy.Removed ||
enemy.IsDead ||
enemy.AIController is EnemyAIController ai && ai.State == AIState.Flee;
}
}
@@ -13,6 +13,14 @@ namespace Barotrauma
private Item item;
private readonly Level.PositionType spawnPositionType;
private readonly string containerTag;
private readonly string existingItemTag;
private bool usedExistingItem;
private readonly bool showMessageWhenPickedUp;
public override IEnumerable<Vector2> SonarPositions
{
@@ -24,7 +32,7 @@ namespace Barotrauma
}
else
{
yield return ConvertUnits.ToDisplayUnits(item.SimPosition);
yield return item.WorldPosition;
}
}
}
@@ -32,6 +40,8 @@ namespace Barotrauma
public SalvageMission(MissionPrefab prefab, Location[] locations)
: base(prefab, locations)
{
containerTag = prefab.ConfigElement.GetAttributeString("containertag", "");
if (prefab.ConfigElement.Attribute("itemname") != null)
{
DebugConsole.ThrowError("Error in SalvageMission - use item identifier instead of the name of the item.");
@@ -52,6 +62,9 @@ namespace Barotrauma
}
}
existingItemTag = prefab.ConfigElement.GetAttributeString("existingitemtag", "");
showMessageWhenPickedUp = prefab.ConfigElement.GetAttributeBool("showmessagewhenpickedup", false);
string spawnPositionTypeStr = prefab.ConfigElement.GetAttributeString("spawntype", "");
if (string.IsNullOrWhiteSpace(spawnPositionTypeStr) ||
!Enum.TryParse(spawnPositionTypeStr, true, out spawnPositionType))
@@ -64,20 +77,66 @@ namespace Barotrauma
{
if (!IsClient)
{
//ruin items are allowed to spawn close to the sub
float minDistance = spawnPositionType == Level.PositionType.Ruin ? 0.0f : Level.Loaded.Size.X * 0.3f;
//ruin/wreck items are allowed to spawn close to the sub
float minDistance = spawnPositionType == Level.PositionType.Ruin || spawnPositionType == Level.PositionType.Wreck ?
0.0f : Level.Loaded.Size.X * 0.3f;
Vector2 position = Level.Loaded.GetRandomItemPos(spawnPositionType, 100.0f, minDistance, 30.0f);
item = new Item(itemPrefab, position, null);
item.body.FarseerBody.BodyType = BodyType.Kinematic;
if (item.HasTag("alien"))
if (!string.IsNullOrEmpty(existingItemTag))
{
var suitableItems = Item.ItemList.Where(it => it.HasTag(existingItemTag));
switch (spawnPositionType)
{
case Level.PositionType.Cave:
case Level.PositionType.MainPath:
item = suitableItems.FirstOrDefault(it => Vector2.DistanceSquared(it.WorldPosition, position) < 1000.0f);
break;
case Level.PositionType.Ruin:
item = suitableItems.FirstOrDefault(it => it.ParentRuin != null && it.ParentRuin.Area.Contains(position));
break;
case Level.PositionType.Wreck:
foreach (Item it in suitableItems)
{
if (it.Submarine == null || it.Submarine.Info.Type != SubmarineInfo.SubmarineType.Wreck) { continue; }
Rectangle worldBorders = it.Submarine.Borders;
worldBorders.Location += it.Submarine.WorldPosition.ToPoint();
if (Submarine.RectContains(worldBorders, it.WorldPosition))
{
item = it;
usedExistingItem = true;
break;
}
}
break;
}
}
if (item == null)
{
item = new Item(itemPrefab, position, null);
item.body.FarseerBody.BodyType = BodyType.Kinematic;
item.FindHull();
}
//try to find a container and place the item inside it
if (!string.IsNullOrEmpty(containerTag) && item.ParentInventory == null)
{
//try to find an artifact holder and place the artifact inside it
foreach (Item it in Item.ItemList)
{
if (it.Submarine != null || !it.HasTag("artifactholder")) continue;
if (!it.HasTag(containerTag)) { continue; }
switch (spawnPositionType)
{
case Level.PositionType.Cave:
case Level.PositionType.MainPath:
if (it.Submarine != null || it.ParentRuin != null) { continue; }
break;
case Level.PositionType.Ruin:
if (it.ParentRuin == null) { continue; }
break;
case Level.PositionType.Wreck:
if (it.Submarine == null || it.Submarine.Info.Type != SubmarineInfo.SubmarineType.Wreck) { continue; }
break;
}
var itemContainer = it.GetComponent<Items.Components.ItemContainer>();
if (itemContainer == null) { continue; }
if (itemContainer.Combine(item, user: null)) { break; } // Placement successful
@@ -97,14 +156,21 @@ namespace Barotrauma
{
case 0:
if (item.ParentInventory != null) { item.body.FarseerBody.BodyType = BodyType.Dynamic; }
if (item.CurrentHull?.Submarine == null) { return; }
if (showMessageWhenPickedUp)
{
if (!(item.ParentInventory?.Owner is Character)) { return; }
}
else
{
if (item.CurrentHull?.Submarine == null || item.CurrentHull.Submarine.Info.Type != SubmarineInfo.SubmarineType.Player) { return; }
}
State = 1;
break;
case 1:
if (!Submarine.MainSub.AtEndPosition && !Submarine.MainSub.AtStartPosition) { return; }
State = 2;
break;
}
}
}
public override void End()
@@ -1,50 +1,46 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Extensions;
using Barotrauma.Items.Components;
namespace Barotrauma
{
class MonsterEvent : ScriptedEvent
{
private string speciesName;
private int minAmount, maxAmount;
private readonly string speciesName;
private readonly int minAmount, maxAmount;
private List<Character> monsters;
private bool spawnDeep;
private readonly bool spawnDeep;
private Vector2? spawnPos;
private bool disallowed;
private Level.PositionType spawnPosType;
private readonly bool disallowed;
private readonly Level.PositionType spawnPosType;
private bool spawnPending;
private string characterFileName;
public override Vector2 DebugDrawPos
{
get { return spawnPos.HasValue ? spawnPos.Value : Vector2.Zero; }
get { return spawnPos ?? Vector2.Zero; }
}
public override string ToString()
{
if (maxAmount <= 1)
{
return "MonsterEvent (" + characterFileName + ")";
return "MonsterEvent (" + speciesName + ")";
}
else if (minAmount < maxAmount)
{
return "MonsterEvent (" + characterFileName + " x" + minAmount + "-" + maxAmount + ")";
return "MonsterEvent (" + speciesName + " x" + minAmount + "-" + maxAmount + ")";
}
else
{
return "MonsterEvent (" + characterFileName + " x" + maxAmount + ")";
return "MonsterEvent (" + speciesName + " x" + maxAmount + ")";
}
}
@@ -76,7 +72,6 @@ namespace Barotrauma
}
spawnDeep = prefab.ConfigElement.GetAttributeBool("spawndeep", false);
characterFileName = Path.GetFileName(Path.GetDirectoryName(speciesName)).ToLower();
if (GameMain.NetworkMember != null)
{
@@ -85,7 +80,10 @@ namespace Barotrauma
if (!string.IsNullOrWhiteSpace(tryKey))
{
if (!GameMain.NetworkMember.ServerSettings.MonsterEnabled[tryKey]) disallowed = true; //spawn was disallowed by host
if (!GameMain.NetworkMember.ServerSettings.MonsterEnabled[tryKey])
{
disallowed = true; //spawn was disallowed by host
}
}
}
}
@@ -106,18 +104,8 @@ namespace Barotrauma
public override bool CanAffectSubImmediately(Level level)
{
float maxRange = Items.Components.Sonar.DefaultSonarRange * 0.8f;
List<Vector2> positions = GetAvailableSpawnPositions();
foreach (Vector2 position in positions)
{
if (Vector2.DistanceSquared(position, Submarine.MainSub.WorldPosition) < maxRange * maxRange)
{
return true;
}
}
return false;
float maxRange = Sonar.DefaultSonarRange * 0.8f;
return GetAvailableSpawnPositions().Any(p => Vector2.DistanceSquared(p.Position.ToVector2(), Submarine.MainSub.WorldPosition) < maxRange * maxRange);
}
public override void Init(bool affectSubImmediately)
@@ -128,28 +116,44 @@ namespace Barotrauma
}
}
private List<Vector2> GetAvailableSpawnPositions()
private List<Level.InterestingPosition> GetAvailableSpawnPositions()
{
var availablePositions = Level.Loaded.PositionsOfInterest.FindAll(p => spawnPosType.HasFlag(p.PositionType));
List<Vector2> positions = new List<Vector2>();
foreach (var allowedPosition in availablePositions)
var availablePositions = Level.Loaded.PositionsOfInterest.FindAll(p => spawnPosType.HasFlag(p.PositionType) && !Level.Loaded.UsedPositions.Contains(p));
var removals = new List<Level.InterestingPosition>();
foreach (var position in availablePositions)
{
if (Level.Loaded.ExtraWalls.Any(w => w.Cells.Any(c => c.IsPointInside(allowedPosition.Position.ToVector2())))) { continue; }
positions.Add(allowedPosition.Position.ToVector2());
}
if (spawnDeep)
{
for (int i = 0; i < positions.Count; i++)
if (position.Submarine != null)
{
positions[i] = new Vector2(positions[i].X, positions[i].Y - Level.Loaded.Size.Y);
if (position.Submarine.ThalamusAI != null && position.Submarine.ThalamusAI.IsAlive)
{
removals.Add(position);
}
else
{
continue;
}
}
if (position.PositionType != Level.PositionType.MainPath) { continue; }
if (Level.Loaded.ExtraWalls.Any(w => w.Cells.Any(c => c.IsPointInside(position.Position.ToVector2()))))
{
removals.Add(position);
}
if (spawnDeep)
{
for (int i = 0; i < availablePositions.Count; i++)
{
var pos = availablePositions[i].Position;
pos = new Point(pos.X, pos.Y - Level.Loaded.Size.Y);
availablePositions[i] = new Level.InterestingPosition(pos, availablePositions[i].PositionType);
}
}
if (position.Position.Y < Level.Loaded.GetBottomPosition(position.Position.X).Y)
{
removals.Add(position);
}
}
positions.RemoveAll(pos => pos.Y < Level.Loaded.GetBottomPosition(pos.X).Y);
return positions;
removals.ForEach(r => availablePositions.Remove(r));
return availablePositions;
}
private void FindSpawnPosition(bool affectSubImmediately)
@@ -158,67 +162,98 @@ namespace Barotrauma
spawnPos = Vector2.Zero;
var availablePositions = GetAvailableSpawnPositions();
if (affectSubImmediately && spawnPosType != Level.PositionType.Ruin)
var chosenPosition = new Level.InterestingPosition(Point.Zero, Level.PositionType.MainPath, isValid: false);
var removedPositions = new List<Level.InterestingPosition>();
foreach (var position in availablePositions)
{
if (availablePositions.Count == 0)
if (Rand.Value(Rand.RandSync.Server) > prefab.SpawnProbability)
{
removedPositions.Add(position);
if (prefab.AllowOnlyOnce)
{
Level.Loaded.UsedPositions.Add(position);
}
}
}
removedPositions.ForEach(p => availablePositions.Remove(p));
bool isSubOrWreck = spawnPosType == Level.PositionType.Ruin || spawnPosType == Level.PositionType.Wreck;
if (affectSubImmediately && !isSubOrWreck)
{
if (availablePositions.None())
{
//no suitable position found, disable the event
Finished();
return;
}
float closestDist = float.PositiveInfinity;
//find the closest spawnposition that isn't too close to any of the subs
foreach (Vector2 position in availablePositions)
foreach (var position in availablePositions)
{
float dist = Vector2.DistanceSquared(position, Submarine.MainSub.WorldPosition);
Vector2 pos = position.Position.ToVector2();
float dist = Vector2.DistanceSquared(pos, Submarine.MainSub.WorldPosition);
foreach (Submarine sub in Submarine.Loaded)
{
if (sub.IsOutpost) { continue; }
if (sub.Info.Type != SubmarineInfo.SubmarineType.Player) { continue; }
float minDistToSub = GetMinDistanceToSub(sub);
if (dist > minDistToSub * minDistToSub && dist < closestDist)
{
closestDist = dist;
spawnPos = position;
chosenPosition = position;
}
}
}
//only found a spawnpos that's very far from the sub, pick one that's closer
//and wait for the sub to move further before spawning
if (closestDist > 15000.0f * 15000.0f)
{
foreach (Vector2 position in availablePositions)
foreach (var position in availablePositions)
{
float dist = Vector2.DistanceSquared(position, Submarine.MainSub.WorldPosition);
float dist = Vector2.DistanceSquared(position.Position.ToVector2(), Submarine.MainSub.WorldPosition);
if (dist < closestDist)
{
closestDist = dist;
spawnPos = position;
chosenPosition = position;
}
}
}
}
else
{
float minDist = spawnPosType == Level.PositionType.Ruin ? 0.0f : 20000.0f;
availablePositions.RemoveAll(p => Vector2.Distance(Submarine.MainSub.WorldPosition, p) < minDist);
if (availablePositions.Count == 0)
if (!isSubOrWreck)
{
float minDistance = 20000;
availablePositions.RemoveAll(p => Vector2.DistanceSquared(Submarine.MainSub.WorldPosition, p.Position.ToVector2()) < minDistance * minDistance);
}
if (availablePositions.None())
{
//no suitable position found, disable the event
Finished();
return;
}
spawnPos = availablePositions[Rand.Int(availablePositions.Count, Rand.RandSync.Server)];
chosenPosition = availablePositions.GetRandom();
}
if (chosenPosition.IsValid)
{
spawnPos = chosenPosition.Position.ToVector2();
if (chosenPosition.Submarine != null || chosenPosition.Ruin != null)
{
var spawnPoint = WayPoint.GetRandom(SpawnType.Enemy, sub: chosenPosition.Submarine, useSyncedRand: false);
if (spawnPoint != null)
{
spawnPos = spawnPoint.WorldPosition;
}
}
spawnPending = true;
if (prefab.AllowOnlyOnce)
{
Level.Loaded.UsedPositions.Add(chosenPosition);
}
}
spawnPending = true;
}
private float GetMinDistanceToSub(Submarine submarine)
{
//9000 units is slightly less than the default range of the sonar
return Math.Max(Math.Max(submarine.Borders.Width, submarine.Borders.Height), 9000.0f);
return Math.Max(Math.Max(submarine.Borders.Width, submarine.Borders.Height), Sonar.DefaultSonarRange * 0.9f);
}
public override void Update(float deltaTime)
@@ -243,9 +278,38 @@ namespace Barotrauma
//wait until there are no submarines at the spawnpos
foreach (Submarine submarine in Submarine.Loaded)
{
if (submarine.IsOutpost) { continue; }
if (submarine.Info.Type != SubmarineInfo.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) { return; }
}
//if spawning in a ruin/cave, wait for someone to be close to it to spawning
//unnecessary monsters in places the players might never visit during the round
if (spawnPosType == Level.PositionType.Ruin || spawnPosType == Level.PositionType.Cave || spawnPosType == Level.PositionType.Wreck)
{
bool someoneNearby = false;
float minDist = Sonar.DefaultSonarRange * 0.8f;
foreach (Submarine submarine in Submarine.Loaded)
{
if (submarine.Info.Type != SubmarineInfo.SubmarineType.Player) { continue; }
if (Vector2.DistanceSquared(submarine.WorldPosition, spawnPos.Value) < minDist * minDist)
{
someoneNearby = true;
break;
}
}
foreach (Character c in Character.CharacterList)
{
if (c == Character.Controlled || c.IsRemotePlayer)
{
if (Vector2.DistanceSquared(c.WorldPosition, spawnPos.Value) < minDist * minDist)
{
someoneNearby = true;
break;
}
}
}
if (!someoneNearby) { return; }
}
spawnPending = false;
@@ -280,7 +344,7 @@ namespace Barotrauma
Entity targetEntity = Submarine.FindClosest(GameMain.GameScreen.Cam.WorldViewCenter);
#if CLIENT
if (Character.Controlled != null) targetEntity = (Entity)Character.Controlled;
if (Character.Controlled != null) { targetEntity = Character.Controlled; }
#endif
bool monstersDead = true;
@@ -297,7 +361,7 @@ namespace Barotrauma
}
}
if (monstersDead) Finished();
if (monstersDead) { Finished(); }
}
}
}
@@ -1,6 +1,5 @@
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
@@ -8,7 +7,7 @@ namespace Barotrauma
{
protected bool isFinished;
private readonly ScriptedEventPrefab prefab;
protected readonly ScriptedEventPrefab prefab;
public bool IsFinished
{
@@ -7,12 +7,11 @@ namespace Barotrauma
{
class ScriptedEventPrefab
{
public readonly XElement ConfigElement;
public readonly Type EventType;
public readonly XElement ConfigElement;
public readonly Type EventType;
public readonly string MusicType;
public readonly float SpawnProbability;
public readonly bool AllowOnlyOnce;
public float Commonness;
public ScriptedEventPrefab(XElement element)
@@ -34,6 +33,8 @@ namespace Barotrauma
DebugConsole.ThrowError("Could not find an event class of the type \"" + ConfigElement.Name + "\".");
}
Commonness = element.GetAttributeFloat("commonness", 1.0f);
SpawnProbability = Math.Clamp(element.GetAttributeFloat("spawnprobability", 1.0f), 0, 1);
AllowOnlyOnce = element.GetAttributeBool("allowonlyonce", false);
}
public ScriptedEvent CreateInstance()
@@ -25,6 +25,11 @@ namespace Barotrauma
//the events in this set are delayed if the current EventManager intensity is not between these values
public readonly float MinIntensity, MaxIntensity;
public readonly bool AllowAtStart;
public readonly bool PerRuin;
public readonly bool PerWreck;
public readonly Dictionary<string, float> Commonness;
public readonly List<ScriptedEventPrefab> EventPrefabs;
@@ -54,6 +59,10 @@ namespace Barotrauma
MinDistanceTraveled = element.GetAttributeFloat("mindistancetraveled", 0.0f);
MinMissionTime = element.GetAttributeFloat("minmissiontime", 0.0f);
AllowAtStart = element.GetAttributeBool("allowatstart", false);
PerRuin = element.GetAttributeBool("perruin", false);
PerWreck = element.GetAttributeBool("perwreck", false);
Commonness[""] = 1.0f;
foreach (XElement subElement in element.Elements())
{
@@ -63,7 +72,7 @@ namespace Barotrauma
Commonness[""] = subElement.GetAttributeFloat("commonness", 0.0f);
foreach (XElement overrideElement in subElement.Elements())
{
if (overrideElement.Name.ToString().ToLowerInvariant() == "override")
if (overrideElement.Name.ToString().Equals("override", StringComparison.OrdinalIgnoreCase))
{
string levelType = overrideElement.GetAttributeString("leveltype", "");
if (!Commonness.ContainsKey(levelType))
@@ -116,7 +125,7 @@ namespace Barotrauma
int i = 0;
foreach (XElement element in doc.Root.Elements())
{
if (element.Name.ToString().ToLowerInvariant() != "eventset") { continue; }
if (!element.Name.ToString().Equals("eventset", StringComparison.OrdinalIgnoreCase)) { continue; }
List.Add(new ScriptedEventSet(element, i.ToString()));
i++;
}