Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaClient/ClientSource/Map/Levels/BackgroundCreatures/BackgroundCreatureManager.cs
2026-06-16 15:35:36 +03:00

131 lines
4.7 KiB
C#

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Barotrauma
{
class BackgroundCreatureManager
{
const int MaxCreatures = 100;
const float VisibilityCheckInterval = 1.0f;
private float checkVisibleTimer;
private readonly List<BackgroundCreature> creatures = [];
private readonly List<BackgroundCreature> visibleCreatures = [];
public IEnumerable<BackgroundCreature> VisibleCreatures => visibleCreatures;
public void SpawnCreatures(Level level, int count, Vector2? position = null)
{
creatures.Clear();
List<BackgroundCreaturePrefab> availablePrefabs = new List<BackgroundCreaturePrefab>(BackgroundCreaturePrefab.Prefabs.OrderBy(p => p.Identifier.Value));
if (availablePrefabs.Count == 0) { return; }
count = Math.Min(count, MaxCreatures);
for (int i = 0; i < count; i++)
{
Vector2 pos = Vector2.Zero;
if (position == null)
{
var wayPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine == null);
if (wayPoints.Any())
{
WayPoint wp = wayPoints[Rand.Int(wayPoints.Count, Rand.RandSync.ClientOnly)];
pos = new Vector2(wp.Rect.X, wp.Rect.Y);
pos += Rand.Vector(200.0f, Rand.RandSync.ClientOnly);
}
else
{
pos = Rand.Vector(2000.0f, Rand.RandSync.ClientOnly);
}
}
else
{
pos = (Vector2)position;
}
var prefab = ToolBox.SelectWeightedRandom(availablePrefabs, availablePrefabs.Select(p => p.GetCommonness(level?.LevelData)).ToList(), Rand.RandSync.ClientOnly);
if (prefab == null) { break; }
int amount = Rand.Range(prefab.SwarmMin, prefab.SwarmMax + 1, Rand.RandSync.ClientOnly);
List<BackgroundCreature> swarmMembers = new List<BackgroundCreature>();
for (int n = 0; n < amount; n++)
{
var creature = new BackgroundCreature(prefab, pos + Rand.Vector(Rand.Range(0.0f, prefab.SwarmRadius, Rand.RandSync.ClientOnly), Rand.RandSync.ClientOnly));
creatures.Add(creature);
swarmMembers.Add(creature);
}
if (amount > 1)
{
new Swarm(swarmMembers, prefab.SwarmRadius, prefab.SwarmCohesion);
}
if (creatures.Count(c => c.Prefab == prefab) > prefab.MaxCount)
{
availablePrefabs.Remove(prefab);
if (availablePrefabs.Count <= 0) { break; }
}
}
}
public void Clear()
{
creatures.Clear();
}
public void Update(float deltaTime, Camera cam)
{
if (checkVisibleTimer < 0.0f)
{
visibleCreatures.Clear();
int margin = 500;
foreach (BackgroundCreature creature in creatures)
{
Rectangle extents = creature.GetExtents(cam);
creature.Visible =
extents.Right >= cam.WorldView.X - margin &&
extents.X <= cam.WorldView.Right + margin &&
extents.Bottom >= cam.WorldView.Y - cam.WorldView.Height - margin &&
extents.Y <= cam.WorldView.Y + margin;
if (creature.Visible)
{
//insertion sort according to depth
int i = 0;
while (i < visibleCreatures.Count)
{
if (visibleCreatures[i].Depth < creature.Depth) { break; }
i++;
}
visibleCreatures.Insert(i, creature);
}
}
checkVisibleTimer = VisibilityCheckInterval;
}
else
{
checkVisibleTimer -= deltaTime;
}
foreach (BackgroundCreature creature in visibleCreatures)
{
creature.Update(deltaTime);
}
}
public void DrawLights(SpriteBatch spriteBatch, Camera cam)
{
foreach (BackgroundCreature creature in visibleCreatures)
{
creature.DrawLightSprite(spriteBatch, cam);
}
}
}
}