NearbyTilesPercent.cs 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using Content.Shared.Maps;
  2. using Robust.Shared.Map;
  3. using Robust.Shared.Map.Components;
  4. using Robust.Shared.Physics.Components;
  5. using Robust.Shared.Prototypes;
  6. namespace Content.Shared.Random.Rules;
  7. public sealed partial class NearbyTilesPercentRule : RulesRule
  8. {
  9. /// <summary>
  10. /// If there are anchored entities on the tile do we ignore the tile.
  11. /// </summary>
  12. [DataField]
  13. public bool IgnoreAnchored;
  14. [DataField(required: true)]
  15. public float Percent;
  16. [DataField(required: true)]
  17. public List<ProtoId<ContentTileDefinition>> Tiles = new();
  18. [DataField]
  19. public float Range = 10f;
  20. public override bool Check(EntityManager entManager, EntityUid uid)
  21. {
  22. if (!entManager.TryGetComponent(uid, out TransformComponent? xform) ||
  23. !entManager.TryGetComponent<MapGridComponent>(xform.GridUid, out var grid))
  24. {
  25. return false;
  26. }
  27. var transform = entManager.System<SharedTransformSystem>();
  28. var mapSys = entManager.System<SharedMapSystem>();
  29. var tileDef = IoCManager.Resolve<ITileDefinitionManager>();
  30. var physicsQuery = entManager.GetEntityQuery<PhysicsComponent>();
  31. var tileCount = 0;
  32. var matchingTileCount = 0;
  33. foreach (var tile in mapSys.GetTilesIntersecting(xform.GridUid.Value, grid, new Circle(transform.GetWorldPosition(xform),
  34. Range)))
  35. {
  36. // Only consider collidable anchored (for reasons some subfloor stuff has physics but non-collidable)
  37. if (IgnoreAnchored)
  38. {
  39. var gridEnum = grid.GetAnchoredEntitiesEnumerator(tile.GridIndices);
  40. var found = false;
  41. while (gridEnum.MoveNext(out var ancUid))
  42. {
  43. if (!physicsQuery.TryGetComponent(ancUid, out var physics) ||
  44. !physics.CanCollide)
  45. {
  46. continue;
  47. }
  48. found = true;
  49. break;
  50. }
  51. if (found)
  52. continue;
  53. }
  54. tileCount++;
  55. if (!Tiles.Contains(tileDef[tile.Tile.TypeId].ID))
  56. continue;
  57. matchingTileCount++;
  58. }
  59. if (tileCount == 0 || matchingTileCount / (float) tileCount < Percent)
  60. return Inverted;
  61. return !Inverted;
  62. }
  63. }