mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
Add EntitySpawnVariationPass as an EntityEffect (#44436)
* Initial pass on making graffiti into an entity effect * Refine code to not consider the entire AABB and eligible tiles * Rename to OnMapInit, * Change default values * Add missing summary * Update into using separate function, entitytable
This commit is contained in:
parent
9b14083903
commit
1b7bb5fefc
3 changed files with 132 additions and 0 deletions
|
|
@ -0,0 +1,111 @@
|
|||
using System.Linq;
|
||||
using Content.Shared.EntityTable;
|
||||
using Content.Shared.EntityTable.EntitySelectors;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared.EntityEffects.Effects.VariationPass;
|
||||
|
||||
/// <summary>
|
||||
/// Used for spawning entities randomly dotted around the grid.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="EntityEffectSystem{T,TEffect}"/>
|
||||
public sealed partial class EntitySpawnVariationPassEntityEffectSystem : EntityEffectSystem<MapGridComponent, EntitySpawnVariationPass>
|
||||
{
|
||||
[Dependency] private SharedMapSystem _map = default!;
|
||||
[Dependency] private IRobustRandom _random = default!;
|
||||
[Dependency] private EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private EntityTableSystem _tables = default!;
|
||||
|
||||
protected override void Effect(Entity<MapGridComponent> entity, ref EntityEffectEvent<EntitySpawnVariationPass> args)
|
||||
{
|
||||
var tiles = _map.GetAllTiles(entity, entity).ToList();
|
||||
var totalTiles = tiles.Count();
|
||||
|
||||
var dirtyMod = _random.NextGaussian(args.Effect.TilesPerEntityAverage, args.Effect.TilesPerEntityStdDev);
|
||||
var trashTiles = Math.Max((int) (totalTiles * (1 / dirtyMod)), 0);
|
||||
|
||||
for (var i = 0; i < trashTiles; i++)
|
||||
{
|
||||
if (TryFindRandomTile(entity, tiles, out var coords))
|
||||
{
|
||||
var ents = _tables.GetSpawns(args.Effect.Table, _random);
|
||||
foreach (var spawn in ents)
|
||||
{
|
||||
SpawnAtPosition(spawn, coords);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to find an empty tile 10 times, returns true if successful.
|
||||
private bool TryFindRandomTile(Entity<MapGridComponent> grid,
|
||||
List<TileRef> tiles,
|
||||
out EntityCoordinates targetCoords)
|
||||
{
|
||||
targetCoords = EntityCoordinates.Invalid;
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var tile = _random.Pick(tiles);
|
||||
var tileCoords = tile.GridIndices;
|
||||
|
||||
if (CheckTileEntities(grid, tileCoords))
|
||||
{
|
||||
targetCoords = _map.GridTileToLocal(grid, grid.Comp, tileCoords);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns false if the tile is occupied.
|
||||
private bool CheckTileEntities(Entity<MapGridComponent> grid, Vector2i tileCoords)
|
||||
{
|
||||
var intersectingEntities = new HashSet<EntityUid>();
|
||||
_lookup.GetLocalEntitiesIntersecting(grid, tileCoords, intersectingEntities, -0.05f, LookupFlags.Uncontained);
|
||||
|
||||
foreach (var ent in intersectingEntities)
|
||||
{
|
||||
if (TryComp<FixturesComponent>(ent, out var fixtures))
|
||||
{
|
||||
foreach (var fixture in fixtures.Fixtures.Values)
|
||||
{
|
||||
// Continue if no collision is possible
|
||||
if (!fixture.Hard || fixture.CollisionLayer <= 0 || (fixture.CollisionLayer & (int) CollisionGroup.Impassable) == 0)
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityEffect"/>
|
||||
public sealed partial class EntitySpawnVariationPass : EntityEffectBase<EntitySpawnVariationPass>
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of tiles before we spawn one entity on average.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float TilesPerEntityAverage = 50f;
|
||||
|
||||
/// <summary>
|
||||
/// Standard deviation for the randomness selection.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float TilesPerEntityStdDev = 7f;
|
||||
|
||||
/// <summary>
|
||||
/// Spawn table for each chosen location.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public EntityTableSelector Table = default!;
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
namespace Content.Shared.EntityEffects;
|
||||
|
||||
/// <summary>
|
||||
/// Applies a set of EntityEffects to the entity upon map initialization.
|
||||
/// <remarks>Useful for e.g. station spawning.</remarks>
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class EntityEffectOnMapInitComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Effects that should be applied upon the map being initiated.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public EntityEffect[] Effects { get; set; } = default!;
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ public sealed partial class SharedEntityEffectsSystem : EntitySystem, IEntityEff
|
|||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<ReactiveComponent, ReactionEntityEvent>(OnReactive);
|
||||
SubscribeLocalEvent<EntityEffectOnMapInitComponent, MapInitEvent>(OnMapInit);
|
||||
}
|
||||
|
||||
private void OnReactive(Entity<ReactiveComponent> entity, ref ReactionEntityEvent args)
|
||||
|
|
@ -58,6 +59,11 @@ public sealed partial class SharedEntityEffectsSystem : EntitySystem, IEntityEff
|
|||
}
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<EntityEffectOnMapInitComponent> entity, ref MapInitEvent args)
|
||||
{
|
||||
ApplyEffects(entity, entity.Comp.Effects);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ApplyEffects(EntityUid,EntityEffect[],float,EntityUid?)"/>
|
||||
public void ApplyEffects(EntityUid target, EntityEffect[] effects, FixedPoint2 scale, EntityUid? user = null)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue