2 using Microsoft.Xna.Framework;
4 using System.Collections.Generic;
12 private class MonsterSet
14 public readonly HashSet<(
CharacterPrefab character, Point amountRange)> MonsterPrefabs =
new HashSet<(
CharacterPrefab character, Point amountRange)>();
15 public float Commonness;
17 public MonsterSet(XElement element)
19 Commonness = element.GetAttributeFloat(
"commonness", 100.0f);
23 private bool swarmSpawned;
24 private readonly List<MonsterSet> monsterSets =
new List<MonsterSet>();
31 foreach (var monsterElement
in prefab.ConfigElement.GetChildElements(
"monster"))
33 if (!monsterSets.Any())
35 monsterSets.Add(
new MonsterSet(monsterElement));
37 LoadMonsters(monsterElement, monsterSets[0]);
39 foreach (var monsterSetElement
in prefab.ConfigElement.GetChildElements(
"monsters"))
41 monsterSets.Add(
new MonsterSet(monsterSetElement));
42 foreach (var monsterElement
in monsterSetElement.GetChildElements(
"monster"))
44 LoadMonsters(monsterElement, monsterSets.Last());
48 sonarLabel = TextManager.Get(
"beaconstationsonarlabel");
49 DebugConsole.NewMessage(
"Initialized beacon mission: " + prefab.Identifier, Color.LightSkyBlue, debugOnly:
true);
52 private void LoadMonsters(XElement monsterElement, MonsterSet
set)
54 Identifier speciesName = monsterElement.GetAttributeIdentifier(
"character", Identifier.Empty);
55 int defaultCount = monsterElement.GetAttributeInt(
"count", -1);
58 defaultCount = monsterElement.GetAttributeInt(
"amount", 1);
60 int min = Math.Min(monsterElement.GetAttributeInt(
"min", defaultCount), 255);
61 int max = Math.Min(Math.Max(min, monsterElement.GetAttributeInt(
"max", defaultCount)), 255);
62 var characterPrefab = CharacterPrefab.FindBySpeciesName(speciesName);
63 if (characterPrefab !=
null)
65 set.MonsterPrefabs.Add((characterPrefab,
new Point(min, max)));
69 DebugConsole.ThrowError($
"Error in beacon mission \"{Prefab.Identifier}\". Could not find a character prefab with the name \"{speciesName}\".",
85 Prefab.SonarLabel.IsNullOrEmpty() ? sonarLabel :
Prefab.SonarLabel,
100 bool isReactor = item.GetComponent<
Reactor>() !=
null;
104 item.GetComponent<
Sonar>() !=
null)
118 availablePositions.RemoveAll(p =>
Level.
Loaded.
ExtraWalls.Any(w => w.IsPointInside(p.Position.ToVector2())));
121 if (availablePositions.Any())
124 float closestDist =
float.PositiveInfinity;
125 foreach (var pos
in availablePositions)
128 if (dist < closestDist)
134 if (closestPos.HasValue)
136 spawnPos = closestPos.Value.
Position.ToVector2();
140 if (monsterSets.Any())
142 var monsterSet = ToolBox.SelectWeightedRandom(monsterSets, m => m.Commonness, Rand.RandSync.Unsynced);
143 foreach ((
CharacterPrefab monsterSpecies, Point monsterCountRange) in monsterSet.MonsterPrefabs)
145 int amount = Rand.Range(monsterCountRange.X, monsterCountRange.Y + 1);
146 for (
int i = 0; i < amount; i++)
148 CoroutineManager.Invoke(() =>
153 }, Rand.Range(0f, amount));
160 #if DEBUG || UNSTABLE
163 DebugConsole.ThrowError(
"Beacon became inactive!");
override bool DetermineCompleted()
override void AdjustLevelData(LevelData levelData)
override void UpdateMissionSpecific(float deltaTime)
BeaconMission(MissionPrefab prefab, Location[] locations, Submarine sub)
override void EndMissionSpecific(bool completed)
override IEnumerable<(LocalizedString Label, Vector2 Position)>? SonarLabels
static EntitySpawner Spawner
void AddCharacterToSpawnQueue(Identifier speciesName, Vector2 worldPosition, Action< Character > onSpawn=null)
static GameSession GameSession
bool InvulnerableToDamage
static readonly List< Item > ItemList
Defines a point in the event that GoTo actions can jump to.
readonly LevelData LevelData
List< LevelWall > ExtraWalls
Special wall chunks that aren't part of the normal level geometry: includes things like the ocean flo...
List< InterestingPosition > PositionsOfInterest
readonly MissionPrefab Prefab
ContentPackage? ContentPackage
readonly Identifier Identifier
override Vector2? WorldPosition
static Submarine FindContaining(Vector2 worldPosition, float inflate=500.0f)
Finds the sub whose world borders contain the position.
IEnumerable< Submarine > GetConnectedSubs()
Returns a list of all submarines that are connected to this one via docking ports,...
Rectangle GetDockedBorders(bool allowDifferentTeam=true)
Returns a rect that contains the borders of this sub and all subs docked to it, excluding outposts