Client LuaCsForBarotrauma
EventSet.cs
2 using System;
3 using System.Collections.Generic;
4 using System.Collections.Immutable;
5 using System.Linq;
6 using System.Xml.Linq;
7 
8 namespace Barotrauma
9 {
10 #if CLIENT
12  {
14 
15  public readonly Sprite Sprite;
16 
17  public EventSprite(ContentXElement element, RandomEventsFile file) : base(file, element.GetAttributeIdentifier("identifier", Identifier.Empty))
18  {
19  Sprite = new Sprite(element);
20  }
21 
22  public override void Dispose() { Sprite?.Remove(); }
23  }
24 #endif
25 
30  sealed class EventSet : Prefab
31  {
32  internal class EventDebugStats
33  {
34  public readonly EventSet RootSet;
35  public readonly Dictionary<Identifier, int> MonsterCounts = new Dictionary<Identifier, int>();
36  public float MonsterStrength;
37 
38  public EventDebugStats(EventSet rootSet)
39  {
40  RootSet = rootSet;
41  }
42  }
43 
45 #if CLIENT
46  public static Sprite GetEventSprite(string identifier)
47  {
48  if (string.IsNullOrWhiteSpace(identifier)) { return null; }
49 
50  if (EventSprite.Prefabs.TryGet(identifier.ToIdentifier(), out EventSprite sprite))
51  {
52  return sprite.Sprite;
53  }
54 
55 #if DEBUG || UNSTABLE
56  DebugConsole.ThrowError($"Could not find the event sprite \"{identifier}\"");
57 #else
58  DebugConsole.AddWarning($"Could not find the event sprite \"{identifier}\"");
59 #endif
60  return null;
61  }
62 #endif
63 
64  public static List<EventPrefab> GetAllEventPrefabs()
65  {
66  List<EventPrefab> eventPrefabs = EventPrefab.Prefabs.ToList();
67  foreach (var eventSet in Prefabs)
68  {
69  AddSetEventPrefabsToList(eventPrefabs, eventSet);
70  }
71  return eventPrefabs;
72  }
73 
74  public static void AddSetEventPrefabsToList(List<EventPrefab> list, EventSet set)
75  {
76  list.AddRange(set.EventPrefabs.SelectMany(ep => ep.EventPrefabs));
77  foreach (var childSet in set.ChildSets) { AddSetEventPrefabsToList(list, childSet); }
78  }
79 
80  public static EventPrefab GetEventPrefab(Identifier identifier)
81  {
82  return GetAllEventPrefabs().Find(prefab => prefab.Identifier == identifier);
83  }
84 
88  public readonly bool IsCampaignSet;
89 
93  public readonly float MinLevelDifficulty;
97  public readonly float MaxLevelDifficulty;
98 
102  public readonly Identifier BiomeIdentifier;
103 
107  public readonly LevelData.LevelType LevelType;
108 
112  public readonly Identifier RequiredLayer;
113 
117  public readonly ImmutableArray<Identifier> LocationTypeIdentifiers;
118 
122  public readonly Identifier Faction;
123 
127  public readonly bool ChooseRandom;
128 
132  private readonly int eventCount = 1;
133  public readonly int SubSetCount = 1;
134  private readonly Dictionary<Identifier, int> overrideEventCount = new Dictionary<Identifier, int>();
135 
139  public readonly bool Exhaustible;
140 
144  public readonly float MinDistanceTraveled;
145 
149  public readonly float MinMissionTime;
150 
151  //the events in this set are delayed if the current EventManager intensity is not between these values
152  public readonly float MinIntensity, MaxIntensity;
153 
157  public readonly bool AllowAtStart;
158 
162  public readonly bool IgnoreCoolDown;
163 
167  public readonly bool TriggerEventCooldown;
168 
172  public readonly bool IgnoreIntensity;
173 
177  public readonly bool PerRuin;
178 
182  public readonly bool PerCave;
183 
187  public readonly bool PerWreck;
188 
192  public readonly bool DisableInHuntingGrounds;
193 
197  public readonly bool OncePerLevel;
198 
202  public readonly bool DelayWhenCrewAway;
203 
209  public readonly bool Additive;
210 
214  public readonly float DefaultCommonness;
215  public readonly ImmutableDictionary<Identifier, float> OverrideCommonness;
216 
220  public readonly float ResetTime;
221 
225  public readonly int ForceAtDiscoveredNr;
226 
230  public readonly int ForceAtVisitedNr;
231 
235  public readonly bool CampaignTutorialOnly;
236 
237  public readonly struct SubEventPrefab
238  {
239  public SubEventPrefab(Either<Identifier[], EventPrefab> prefabOrIdentifiers, float? commonness, float? probability, Identifier factionId)
240  {
241  PrefabOrIdentifier = prefabOrIdentifiers;
242  SelfCommonness = commonness;
243  SelfProbability = probability;
244  Faction = factionId;
245  }
246 
247  public readonly Either<Identifier[], EventPrefab> PrefabOrIdentifier;
248  public IEnumerable<EventPrefab> EventPrefabs
249  {
250  get
251  {
252  if (PrefabOrIdentifier.TryGet(out EventPrefab p))
253  {
254  yield return p;
255  }
256  else
257  {
258  foreach (var id in (Identifier[])PrefabOrIdentifier)
259  {
260  if (EventPrefab.Prefabs.TryGet(id, out EventPrefab prefab))
261  {
262  yield return prefab;
263  }
264  }
265  }
266  }
267  }
268 
269  public readonly float? SelfCommonness;
270  public float Commonness => SelfCommonness ?? EventPrefabs.MaxOrNull(p => p.Commonness) ?? 0.0f;
271 
272  public readonly float? SelfProbability;
273  public float Probability => SelfProbability ?? EventPrefabs.MaxOrNull(p => p.Probability) ?? 0.0f;
274 
275  public readonly Identifier Faction;
276 
277  public void Deconstruct(out IEnumerable<EventPrefab> eventPrefabs, out float commonness, out float probability)
278  {
279  eventPrefabs = EventPrefabs;
280  commonness = Commonness;
281  probability = Probability;
282  }
283 
284  public IEnumerable<Identifier> GetMissingIdentifiers()
285  {
286  if (PrefabOrIdentifier.TryCast<Identifier[]>(out var ids))
287  {
288  foreach (var id in ids)
289  {
290  if (!EventPrefab.Prefabs.ContainsKey(id))
291  {
292  yield return id;
293  }
294  }
295  }
296  }
297  }
298  public readonly ImmutableArray<SubEventPrefab> EventPrefabs;
299 
300  public readonly ImmutableArray<EventSet> ChildSets;
301 
302  private static Identifier DetermineIdentifier(EventSet parent, XElement element, RandomEventsFile file)
303  {
304  Identifier retVal = element.GetAttributeIdentifier("identifier", Identifier.Empty);
305 
306  if (retVal.IsEmpty)
307  {
308  if (parent is null)
309  {
310  if (file.ContentPackage is CorePackage)
311  {
312  throw new Exception($"Error in {file.Path}: All root EventSets in a core package must have identifiers");
313  }
314  else
315  {
316  DebugConsole.AddWarning($"{file.Path}: All root EventSets should have an identifier",
317  file.ContentPackage);
318  }
319  }
320 
321  XElement currElement = element;
322  string siblingIndices = "";
323  while (currElement.Parent != null)
324  {
325  int siblingIndex = currElement.ElementsBeforeSelf().Count();
326  siblingIndices = $"-{siblingIndex}{siblingIndices}";
327  if (parent != null) { break; }
328  currElement = currElement.Parent;
329  }
330 
331  retVal =
332  ((parent != null
333  ? parent.Identifier.Value
334  : $"{file.ContentPackage.Name}-{file.Path}")
335  + siblingIndices)
336  .ToIdentifier();
337  }
338  return retVal;
339  }
340 
341  public EventSet(ContentXElement element, RandomEventsFile file, EventSet parentSet = null)
342  : base(file, DetermineIdentifier(parentSet, element, file))
343  {
344  var eventPrefabs = new List<SubEventPrefab>();
345  var childSets = new List<EventSet>();
346  var overrideCommonness = new Dictionary<Identifier, float>();
347 
348  BiomeIdentifier = element.GetAttributeIdentifier("biome", Barotrauma.Identifier.Empty);
349  MinLevelDifficulty = element.GetAttributeFloat("minleveldifficulty", 0);
350  MaxLevelDifficulty = Math.Max(element.GetAttributeFloat("maxleveldifficulty", 100), MinLevelDifficulty);
351 
352  Additive = element.GetAttributeBool("additive", false);
353 
354  string levelTypeStr = element.GetAttributeString("leveltype", parentSet?.LevelType.ToString() ?? "LocationConnection");
355  if (!Enum.TryParse(levelTypeStr, true, out LevelType))
356  {
357  DebugConsole.ThrowError($"Error in event set \"{Identifier}\". \"{levelTypeStr}\" is not a valid level type.",
358  contentPackage: element.ContentPackage);
359  }
360 
361  Faction = element.GetAttributeIdentifier(nameof(Faction), Identifier.Empty);
362 
363  Identifier[] locationTypeStr = element.GetAttributeIdentifierArray("locationtype", null);
364  if (locationTypeStr != null)
365  {
366  LocationTypeIdentifiers = locationTypeStr.ToImmutableArray();
367  //if (LocationType.List.Any()) { CheckLocationTypeErrors(); } //TODO: perform validation elsewhere
368  }
369 
370  MinIntensity = element.GetAttributeFloat("minintensity", 0.0f);
371  MaxIntensity = Math.Max(element.GetAttributeFloat("maxintensity", 100.0f), MinIntensity);
372 
373  ChooseRandom = element.GetAttributeBool("chooserandom", false);
374  eventCount = element.GetAttributeInt("eventcount", 1);
375  SubSetCount = element.GetAttributeInt("setcount", 1);
376  Exhaustible = element.GetAttributeBool("exhaustible", parentSet?.Exhaustible ?? false);
377  MinDistanceTraveled = element.GetAttributeFloat("mindistancetraveled", 0.0f);
378  MinMissionTime = element.GetAttributeFloat("minmissiontime", 0.0f);
379 
380  AllowAtStart = element.GetAttributeBool("allowatstart", parentSet?.AllowAtStart ?? false);
381  PerRuin = element.GetAttributeBool("perruin", false);
382  PerCave = element.GetAttributeBool("percave", false);
383  PerWreck = element.GetAttributeBool("perwreck", false);
384  DisableInHuntingGrounds = element.GetAttributeBool("disableinhuntinggrounds", parentSet?.DisableInHuntingGrounds ?? false);
385  IgnoreCoolDown = element.GetAttributeBool("ignorecooldown", parentSet?.IgnoreCoolDown ?? (PerRuin || PerCave || PerWreck));
386  IgnoreIntensity = element.GetAttributeBool("ignoreintensity", parentSet?.IgnoreIntensity ?? false);
387  DelayWhenCrewAway = element.GetAttributeBool("delaywhencrewaway", parentSet?.DelayWhenCrewAway ?? (!PerRuin && !PerCave && !PerWreck));
388  OncePerLevel = element.GetAttributeBool("onceperlevel", element.GetAttributeBool("onceperoutpost", parentSet?.OncePerLevel ?? false));
389  TriggerEventCooldown = element.GetAttributeBool("triggereventcooldown", parentSet?.TriggerEventCooldown ?? true);
390  IsCampaignSet = element.GetAttributeBool("campaign", LevelType == LevelData.LevelType.Outpost || (parentSet?.IsCampaignSet ?? false));
391  ResetTime = element.GetAttributeFloat(nameof(ResetTime), parentSet?.ResetTime ?? 0);
392  CampaignTutorialOnly = element.GetAttributeBool(nameof(CampaignTutorialOnly), parentSet?.CampaignTutorialOnly ?? false);
393 
395 
397  ForceAtVisitedNr = element.GetAttributeInt(nameof(ForceAtVisitedNr), -1);
398  if (ForceAtDiscoveredNr >= 0 && ForceAtVisitedNr >= 0)
399  {
400  DebugConsole.ThrowError($"Error with event set \"{Identifier}\" - both ForceAtDiscoveredNr and ForceAtVisitedNr are defined, this could lead to unexpected behavior",
401  contentPackage: element.ContentPackage);
402  }
403 
404  DefaultCommonness = element.GetAttributeFloat("commonness", 1.0f);
405  foreach (var subElement in element.Elements())
406  {
407  switch (subElement.Name.ToString().ToLowerInvariant())
408  {
409  case "commonness":
410  DefaultCommonness = subElement.GetAttributeFloat("commonness", DefaultCommonness);
411  foreach (XElement overrideElement in subElement.Elements())
412  {
413  if (overrideElement.NameAsIdentifier() == "override")
414  {
415  Identifier levelType = overrideElement.GetAttributeIdentifier("leveltype", "");
416  if (!overrideCommonness.ContainsKey(levelType))
417  {
418  overrideCommonness.Add(levelType, overrideElement.GetAttributeFloat("commonness", 0.0f));
419  }
420  }
421  }
422  break;
423  case "eventset":
424  childSets.Add(new EventSet(subElement, file, this));
425  break;
426  case "overrideeventcount":
427  Identifier locationType = subElement.GetAttributeIdentifier("locationtype", "");
428  if (!overrideEventCount.ContainsKey(locationType))
429  {
430  overrideEventCount.Add(locationType, subElement.GetAttributeInt("eventcount", eventCount));
431  }
432  break;
433  default:
434  //an element with just an identifier = reference to an event prefab
435  if (!subElement.HasElements && subElement.Attributes().First().Name.ToString().Equals("identifier", StringComparison.OrdinalIgnoreCase))
436  {
437  Identifier[] identifiers = subElement.GetAttributeIdentifierArray("identifier", Array.Empty<Identifier>());
438  float commonness = subElement.GetAttributeFloat("commonness", -1f);
439  float probability = subElement.GetAttributeFloat("probability", -1f);
440  Identifier factionId = subElement.GetAttributeIdentifier(nameof(Faction), Identifier.Empty);
441  eventPrefabs.Add(new SubEventPrefab(
442  identifiers,
443  commonness >= 0f ? commonness : (float?)null,
444  probability >= 0f ? probability : (float?)null,
445  factionId));
446  }
447  else
448  {
449  var prefab = new EventPrefab(subElement, file, $"{Identifier}-{subElement.ElementsBeforeSelf().Count()}".ToIdentifier());
450  eventPrefabs.Add(new SubEventPrefab(prefab, prefab.Commonness, prefab.Probability, prefab.Faction));
451  }
452  break;
453  }
454  }
455 
456  EventPrefabs = eventPrefabs.ToImmutableArray();
457  ChildSets = childSets.ToImmutableArray();
458  OverrideCommonness = overrideCommonness.ToImmutableDictionary();
459 
460  if ((PerRuin && PerCave) || (PerWreck && PerCave) || (PerRuin && PerWreck))
461  {
462  DebugConsole.AddWarning($"Error in event set \"{Identifier}\". Only one of the settings {nameof(PerRuin)}, {nameof(PerCave)} or {nameof(PerWreck)} can be enabled at the time.");
463  }
464  }
465 
467  {
468  if (LocationTypeIdentifiers == null) { return; }
469  foreach (Identifier locationTypeId in LocationTypeIdentifiers)
470  {
471  if (!LocationType.Prefabs.ContainsKey(locationTypeId))
472  {
473  DebugConsole.ThrowError($"Error in event set \"{Identifier}\". Location type \"{locationTypeId}\" not found.");
474  }
475  }
476  }
477 
478  public float GetCommonness(Level level)
479  {
480  if (level.GenerationParams?.Identifier is { IsEmpty: false } &&
481  OverrideCommonness.TryGetValue(level.GenerationParams.Identifier, out float generationParamsCommonness))
482  {
483  return generationParamsCommonness;
484  }
485  else if (level.StartOutpost?.Info.OutpostGenerationParams?.Identifier is { IsEmpty: false } &&
486  OverrideCommonness.TryGetValue(level.StartOutpost.Info.OutpostGenerationParams.Identifier, out float startOutpostParamsCommonness))
487  {
488  return startOutpostParamsCommonness;
489  }
490  else if (level.EndOutpost?.Info.OutpostGenerationParams?.Identifier is { IsEmpty: false } &&
491  OverrideCommonness.TryGetValue(level.EndOutpost.Info.OutpostGenerationParams.Identifier, out float endOutpostParamsCommonness))
492  {
493  return endOutpostParamsCommonness;
494  }
495  return DefaultCommonness;
496  }
497 
498  public int GetEventCount(Level level)
499  {
500  int finishedEventCount = 0;
501  if (level is not null)
502  {
503  level.LevelData.FinishedEvents.TryGetValue(this, out finishedEventCount);
504  }
505  if (level.StartLocation == null || !overrideEventCount.TryGetValue(level.StartLocation.Type.Identifier, out int count))
506  {
507  return eventCount - finishedEventCount;
508  }
509  return count - finishedEventCount;
510  }
511 
512  public static List<string> GetDebugStatistics(int simulatedRoundCount = 100, Func<MonsterEvent, bool> filter = null, bool fullLog = false)
513  {
514  List<string> debugLines = new List<string>();
515 
516  foreach (var eventSet in Prefabs)
517  {
518  List<EventDebugStats> stats = new List<EventDebugStats>();
519  for (int i = 0; i < simulatedRoundCount; i++)
520  {
521  var newStats = new EventDebugStats(eventSet);
522  CheckEventSet(newStats, eventSet, filter);
523  stats.Add(newStats);
524  }
525  debugLines.Add($"Event stats ({eventSet.Identifier}): ");
526  LogEventStats(stats, debugLines, fullLog);
527  }
528 
529  return debugLines;
530 
531  static void CheckEventSet(EventDebugStats stats, EventSet thisSet, Func<MonsterEvent, bool> filter = null)
532  {
533  if (thisSet.ChooseRandom)
534  {
535  var unusedEvents = thisSet.EventPrefabs.ToList();
536  if (unusedEvents.Any())
537  {
538  for (int i = 0; i < thisSet.eventCount; i++)
539  {
540  var eventPrefab = ToolBox.SelectWeightedRandom(unusedEvents, unusedEvents.Select(e => e.Commonness).ToList(), Rand.RandSync.Unsynced);
541  if (eventPrefab.EventPrefabs.Any(p => p != null))
542  {
543  AddEvents(stats, eventPrefab.EventPrefabs, filter);
544  unusedEvents.Remove(eventPrefab);
545  }
546  }
547  }
548  List<float> values = thisSet.ChildSets
549  .SelectMany(s => s.DefaultCommonness.ToEnumerable().Concat(s.OverrideCommonness.Values))
550  .ToList();
551  EventSet childSet = ToolBox.SelectWeightedRandom(thisSet.ChildSets, values, Rand.RandSync.Unsynced);
552  if (childSet != null)
553  {
554  CheckEventSet(stats, childSet, filter);
555  }
556  }
557  else
558  {
559  foreach (var eventPrefab in thisSet.EventPrefabs)
560  {
561  AddEvents(stats, eventPrefab.EventPrefabs, filter);
562  }
563  foreach (var childSet in thisSet.ChildSets)
564  {
565  CheckEventSet(stats, childSet, filter);
566  }
567  }
568  }
569 
570  static void AddEvents(EventDebugStats stats, IEnumerable<EventPrefab> eventPrefabs, Func<MonsterEvent, bool> filter = null)
571  => eventPrefabs.ForEach(p => AddEvent(stats, p, filter));
572 
573  static void AddEvent(EventDebugStats stats, EventPrefab eventPrefab, Func<MonsterEvent, bool> filter = null)
574  {
575  if (eventPrefab.EventType == typeof(MonsterEvent) &&
576  eventPrefab.TryCreateInstance(GameMain.GameSession?.EventManager?.RandomSeed ?? 0, out MonsterEvent monsterEvent))
577  {
578  if (filter != null && !filter(monsterEvent)) { return; }
579  float spawnProbability = monsterEvent.Prefab?.Probability ?? 0.0f;
580  if (Rand.Value() > spawnProbability) { return; }
581  int count = Rand.Range(monsterEvent.MinAmount, monsterEvent.MaxAmount + 1);
582  if (count <= 0) { return; }
583  Identifier character = monsterEvent.SpeciesName;
584  if (stats.MonsterCounts.TryGetValue(character, out int currentCount))
585  {
586  if (currentCount >= monsterEvent.MaxAmountPerLevel) { return; }
587  }
588  else
589  {
590  stats.MonsterCounts[character] = 0;
591  }
592  stats.MonsterCounts[character] += count;
593 
594  var aiElement = CharacterPrefab.FindBySpeciesName(character)?.ConfigElement?.GetChildElement("ai");
595  if (aiElement != null)
596  {
597  stats.MonsterStrength += aiElement.GetAttributeFloat("combatstrength", 0) * count;
598  }
599  }
600  }
601 
602  static void LogEventStats(List<EventDebugStats> stats, List<string> debugLines, bool fullLog)
603  {
604  if (stats.Count == 0 || stats.All(s => s.MonsterCounts.Values.Sum() == 0))
605  {
606  debugLines.Add(" No monster spawns");
607  debugLines.Add($" ");
608  }
609  else
610  {
611  var allMonsters = new Dictionary<Identifier, int>();
612  foreach (var stat in stats)
613  {
614  foreach (var monster in stat.MonsterCounts)
615  {
616  if (!allMonsters.TryAdd(monster.Key, monster.Value))
617  {
618  allMonsters[monster.Key] += monster.Value;
619  }
620  }
621  }
622  allMonsters = allMonsters.OrderBy(m => m.Key).ToDictionary(m => m.Key, m => m.Value);
623  stats.Sort((s1, s2) => s1.MonsterCounts.Values.Sum().CompareTo(s2.MonsterCounts.Values.Sum()));
624  debugLines.Add($" Average monster count: {StringFormatter.FormatZeroDecimal((float)stats.Average(s => s.MonsterCounts.Values.Sum()))} (Min: {stats.First().MonsterCounts.Values.Sum()}, Max: {stats.Last().MonsterCounts.Values.Sum()})");
625  debugLines.Add($" {LogMonsterCounts(allMonsters, divider: stats.Count)}");
626  if (fullLog)
627  {
628  debugLines.Add($" All samples:");
629  stats.ForEach(s => debugLines.Add($" {LogMonsterCounts(s.MonsterCounts)}"));
630  }
631  stats.Sort((s1, s2) => s1.MonsterStrength.CompareTo(s2.MonsterStrength));
632  debugLines.Add($" Average monster strength: {StringFormatter.FormatZeroDecimal(stats.Average(s => s.MonsterStrength))} (Min: {StringFormatter.FormatZeroDecimal(stats.First().MonsterStrength)}, Max: {StringFormatter.FormatZeroDecimal(stats.Last().MonsterStrength)})");
633  debugLines.Add($" ");
634  }
635  }
636 
637  static string LogMonsterCounts(Dictionary<Identifier, int> stats, float divider = 0)
638  {
639  if (divider > 0)
640  {
641  return string.Join("\n ", stats.Select(mc => mc.Key + " x " + (mc.Value / divider).FormatSingleDecimal()));
642  }
643  else
644  {
645  return string.Join(", ", stats.Select(mc => mc.Key + " x " + mc.Value));
646  }
647  }
648  }
649 
650  public override string ToString()
651  {
652  return $"{base.ToString()} ({Identifier.Value})";
653  }
654 
655  public override void Dispose() { }
656  }
657 }
static CharacterPrefab FindBySpeciesName(Identifier speciesName)
ContentXElement ConfigElement
readonly ContentPackage ContentPackage
Definition: ContentFile.cs:136
string? GetAttributeString(string key, string? def)
Identifier[] GetAttributeIdentifierArray(Identifier[] def, params string[] keys)
float GetAttributeFloat(string key, float def)
ContentPackage? ContentPackage
ContentXElement? GetChildElement(string name)
bool GetAttributeBool(string key, bool def)
int GetAttributeInt(string key, int def)
Identifier GetAttributeIdentifier(string key, string def)
readonly Type EventType
Definition: EventPrefab.cs:12
static readonly PrefabCollection< EventPrefab > Prefabs
Definition: EventPrefab.cs:9
Event sets are sets of random events that occur within a level (most commonly, monster spawns and scr...
Definition: EventSet.cs:31
static EventPrefab GetEventPrefab(Identifier identifier)
Definition: EventSet.cs:80
static Sprite GetEventSprite(string identifier)
Definition: EventSet.cs:46
readonly bool PerWreck
The set is applied once per each wreck in the level. Can be used to ensure there's a consistent amoun...
Definition: EventSet.cs:187
readonly bool DisableInHuntingGrounds
If enabled, this event will not be applied if the level contains hunting grounds.
Definition: EventSet.cs:192
readonly bool ChooseRandom
If set, one event, or a sub event set, is chosen randomly from this set.
Definition: EventSet.cs:127
readonly bool AllowAtStart
If the event is not allowed at start, it won't become active until the submarine has moved at least 5...
Definition: EventSet.cs:157
EventSet(ContentXElement element, RandomEventsFile file, EventSet parentSet=null)
Definition: EventSet.cs:341
readonly bool TriggerEventCooldown
Should this event set trigger the event cooldown (during which no new events are created) when it bec...
Definition: EventSet.cs:167
readonly bool PerCave
The set is applied once per each cave in the level. Can be used to ensure there's a consistent amount...
Definition: EventSet.cs:182
readonly bool PerRuin
The set is applied once per each ruin in the level. Can be used to ensure there's a consistent amount...
Definition: EventSet.cs:177
readonly ImmutableArray< Identifier > LocationTypeIdentifiers
If set, the event set can only be chosen in locations of this type.
Definition: EventSet.cs:117
readonly bool IgnoreIntensity
Normally events can only trigger if the intensity of the situation is low enough (e....
Definition: EventSet.cs:172
readonly LevelData.LevelType LevelType
If set, the event set can only be chosen in this type of level (outpost level or a connection between...
Definition: EventSet.cs:107
readonly ImmutableArray< SubEventPrefab > EventPrefabs
Definition: EventSet.cs:298
readonly float ResetTime
If set, the event set can trigger again after this amount of seconds has passed since it last trigger...
Definition: EventSet.cs:220
readonly int ForceAtVisitedNr
Used to force an event set based on how many other outposts have been visited before this (used for c...
Definition: EventSet.cs:230
void CheckLocationTypeErrors()
Definition: EventSet.cs:466
int GetEventCount(Level level)
Definition: EventSet.cs:498
readonly float MinLevelDifficulty
The difficulty of the current level must be equal to or higher than this for this set to be chosen.
Definition: EventSet.cs:93
static readonly PrefabCollection< EventSet > Prefabs
Definition: EventSet.cs:44
readonly ImmutableArray< EventSet > ChildSets
Definition: EventSet.cs:300
readonly float MinIntensity
Definition: EventSet.cs:152
float GetCommonness(Level level)
Definition: EventSet.cs:478
readonly float MinMissionTime
The event set won't become active until the round has lasted at least this many seconds.
Definition: EventSet.cs:149
readonly float DefaultCommonness
The commonness of the event set (i.e. how likely it is for this specific set to be chosen).
Definition: EventSet.cs:214
readonly float MinDistanceTraveled
The event set won't become active until the submarine has travelled at least this far....
Definition: EventSet.cs:144
readonly bool Additive
Additive sets are important to be aware of when creating custom event sets! If an additive set gets c...
Definition: EventSet.cs:209
readonly int ForceAtDiscoveredNr
Used to force an event set based on how many other locations have been discovered before this (used f...
Definition: EventSet.cs:225
readonly ImmutableDictionary< Identifier, float > OverrideCommonness
Definition: EventSet.cs:215
readonly float MaxLevelDifficulty
The difficulty of the current level must be equal to or less than this for this set to be chosen.
Definition: EventSet.cs:97
readonly bool Exhaustible
'Exhaustible' sets won't appear in the same level until after one world step (~10 min,...
Definition: EventSet.cs:139
readonly Identifier RequiredLayer
If set, this layer must be present somewhere in the level.
Definition: EventSet.cs:112
readonly bool IsCampaignSet
If enabled, this set can only be chosen in the campaign mode.
Definition: EventSet.cs:88
static List< EventPrefab > GetAllEventPrefabs()
Definition: EventSet.cs:64
readonly bool CampaignTutorialOnly
If enabled, this set can only occur when the campaign tutorial is enabled (generally used for the tut...
Definition: EventSet.cs:235
static List< string > GetDebugStatistics(int simulatedRoundCount=100, Func< MonsterEvent, bool > filter=null, bool fullLog=false)
Definition: EventSet.cs:512
readonly int SubSetCount
Definition: EventSet.cs:133
readonly bool OncePerLevel
If enabled, events from this set can only occur once in the level.
Definition: EventSet.cs:197
readonly bool DelayWhenCrewAway
Should the event set be delayed if at least half of the crew is away from the submarine?...
Definition: EventSet.cs:202
override void Dispose()
Definition: EventSet.cs:655
static void AddSetEventPrefabsToList(List< EventPrefab > list, EventSet set)
Definition: EventSet.cs:74
readonly bool IgnoreCoolDown
Normally an event (such as a monster spawn) triggers a cooldown during which no new events are create...
Definition: EventSet.cs:162
override string ToString()
Definition: EventSet.cs:650
readonly Identifier BiomeIdentifier
If set, the event set can only be chosen in this biome.
Definition: EventSet.cs:102
readonly Identifier Faction
If set, the event set can only be chosen in locations that belong to this faction.
Definition: EventSet.cs:122
readonly Sprite Sprite
Definition: EventSet.cs:15
override void Dispose()
Definition: EventSet.cs:22
EventSprite(ContentXElement element, RandomEventsFile file)
Definition: EventSet.cs:17
static readonly PrefabCollection< EventSprite > Prefabs
Definition: EventSet.cs:13
static GameSession?? GameSession
Definition: GameMain.cs:88
readonly Dictionary< EventSet, int > FinishedEvents
Definition: LevelData.cs:74
LocationType Type
Definition: Location.cs:91
static readonly PrefabCollection< LocationType > Prefabs
Definition: LocationType.cs:15
readonly Identifier Identifier
Definition: Prefab.cs:34
Sprite(ContentXElement element, string path="", string file="", bool lazyLoad=false, float sourceRectScale=1)
IEnumerable< Identifier > GetMissingIdentifiers()
Definition: EventSet.cs:284
readonly Identifier Faction
Definition: EventSet.cs:275
SubEventPrefab(Either< Identifier[], EventPrefab > prefabOrIdentifiers, float? commonness, float? probability, Identifier factionId)
Definition: EventSet.cs:239
IEnumerable< EventPrefab > EventPrefabs
Definition: EventSet.cs:249
void Deconstruct(out IEnumerable< EventPrefab > eventPrefabs, out float commonness, out float probability)
Definition: EventSet.cs:277
readonly Either< Identifier[], EventPrefab > PrefabOrIdentifier
Definition: EventSet.cs:247