Client LuaCsForBarotrauma
BackgroundCreatureManager.cs
1 using Microsoft.Xna.Framework;
2 using Microsoft.Xna.Framework.Graphics;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Xml.Linq;
7 
8 namespace Barotrauma
9 {
11  {
12  const int MaxCreatures = 100;
13 
14  const float VisibilityCheckInterval = 1.0f;
15 
16  private float checkVisibleTimer;
17 
18  private readonly List<BackgroundCreaturePrefab> prefabs = new List<BackgroundCreaturePrefab>();
19  private readonly List<BackgroundCreature> creatures = new List<BackgroundCreature>();
20 
21  public BackgroundCreatureManager(IEnumerable<BackgroundCreaturePrefabsFile> files)
22  {
23  foreach(var file in files)
24  {
25  LoadConfig(file.Path);
26  }
27  }
28 
29  public BackgroundCreatureManager(string path)
30  {
31  DebugConsole.AddWarning($"Couldn't find any BackgroundCreaturePrefabs files, falling back to {path}");
32  LoadConfig(ContentPath.FromRaw(null, path));
33  }
34 
35  private void LoadConfig(ContentPath configPath)
36  {
37  try
38  {
39  XDocument doc = XMLExtensions.TryLoadXml(configPath);
40  if (doc == null) { return; }
41  var mainElement = doc.Root.FromPackage(configPath.ContentPackage);
42  if (mainElement.IsOverride())
43  {
44  mainElement = mainElement.FirstElement();
45  prefabs.Clear();
46  DebugConsole.NewMessage($"Overriding all background creatures with '{configPath}'", Color.MediumPurple);
47  }
48  else if (prefabs.Any())
49  {
50  DebugConsole.NewMessage($"Loading additional background creatures from file '{configPath}'");
51  }
52 
53  foreach (var element in mainElement.Elements())
54  {
55  prefabs.Add(new BackgroundCreaturePrefab(element));
56  };
57  }
58  catch (Exception e)
59  {
60  DebugConsole.ThrowError(String.Format("Failed to load BackgroundCreatures from {0}", configPath), e);
61  }
62  }
63 
64  public void SpawnCreatures(Level level, int count, Vector2? position = null)
65  {
66  creatures.Clear();
67 
68  if (prefabs.Count == 0) { return; }
69 
70  count = Math.Min(count, MaxCreatures);
71 
72  List<BackgroundCreaturePrefab> availablePrefabs = new List<BackgroundCreaturePrefab>(prefabs);
73 
74  for (int i = 0; i < count; i++)
75  {
76  Vector2 pos = Vector2.Zero;
77  if (position == null)
78  {
79  var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine == null);
80  if (wayPoints.Any())
81  {
82  WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, Rand.RandSync.ClientOnly)];
83  pos = new Vector2(wp.Rect.X, wp.Rect.Y);
84  pos += Rand.Vector(200.0f, Rand.RandSync.ClientOnly);
85  }
86  else
87  {
88  pos = Rand.Vector(2000.0f, Rand.RandSync.ClientOnly);
89  }
90  }
91  else
92  {
93  pos = (Vector2)position;
94  }
95 
96  var prefab = ToolBox.SelectWeightedRandom(availablePrefabs, availablePrefabs.Select(p => p.GetCommonness(level.GenerationParams)).ToList(), Rand.RandSync.ClientOnly);
97  if (prefab == null) { break; }
98 
99  int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax + 1, Rand.RandSync.ClientOnly);
100  List<BackgroundCreature> swarmMembers = new List<BackgroundCreature>();
101  for (int n = 0; n < amount; n++)
102  {
103  var creature = new BackgroundCreature(prefab, pos + Rand.Vector(Rand.Range(0.0f, prefab.SwarmRadius, Rand.RandSync.ClientOnly), Rand.RandSync.ClientOnly));
104  creatures.Add(creature);
105  swarmMembers.Add(creature);
106  }
107  if (amount > 1)
108  {
109  new Swarm(swarmMembers, prefab.SwarmRadius, prefab.SwarmCohesion);
110  }
111  if (creatures.Count(c => c.Prefab == prefab) > prefab.MaxCount)
112  {
113  availablePrefabs.Remove(prefab);
114  if (availablePrefabs.Count <= 0) { break; }
115  }
116  }
117  }
118 
119  public void Clear()
120  {
121  creatures.Clear();
122  }
123 
124  public void Update(float deltaTime, Camera cam)
125  {
126  if (checkVisibleTimer < 0.0f)
127  {
128  int margin = 500;
129  foreach (BackgroundCreature creature in creatures)
130  {
131  Rectangle extents = creature.GetExtents(cam);
132  bool wasVisible = creature.Visible;
133  creature.Visible =
134  extents.Right >= cam.WorldView.X - margin &&
135  extents.X <= cam.WorldView.Right + margin &&
136  extents.Bottom >= cam.WorldView.Y - cam.WorldView.Height - margin &&
137  extents.Y <= cam.WorldView.Y + margin;
138  }
139 
140  checkVisibleTimer = VisibilityCheckInterval;
141  }
142  else
143  {
144  checkVisibleTimer -= deltaTime;
145  }
146 
147  foreach (BackgroundCreature creature in creatures)
148  {
149  if (!creature.Visible) { continue; }
150  creature.Update(deltaTime);
151  }
152  }
153 
154  public void Draw(SpriteBatch spriteBatch, Camera cam)
155  {
156  foreach (BackgroundCreature creature in creatures)
157  {
158  if (!creature.Visible) { continue; }
159  creature.Draw(spriteBatch, cam);
160  }
161  }
162 
163  public void DrawLights(SpriteBatch spriteBatch, Camera cam)
164  {
165  foreach (BackgroundCreature creature in creatures)
166  {
167  if (!creature.Visible) { continue; }
168  creature.DrawLightSprite(spriteBatch, cam);
169  }
170  }
171  }
172 }
void Draw(SpriteBatch spriteBatch, Camera cam)
void DrawLightSprite(SpriteBatch spriteBatch, Camera cam)
Rectangle GetExtents(Camera cam)
void DrawLights(SpriteBatch spriteBatch, Camera cam)
BackgroundCreatureManager(IEnumerable< BackgroundCreaturePrefabsFile > files)
void Draw(SpriteBatch spriteBatch, Camera cam)
void SpawnCreatures(Level level, int count, Vector2? position=null)
void Update(float deltaTime, Camera cam)
Rectangle WorldView
Definition: Camera.cs:123
readonly? ContentPackage ContentPackage
Definition: ContentPath.cs:21
static ContentPath FromRaw(string? rawValue)