WallmountCondition.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using System.Linq;
  2. using System.Numerics;
  3. using Content.Shared.Physics;
  4. using Content.Shared.Tag;
  5. using JetBrains.Annotations;
  6. using Robust.Shared.Map;
  7. using Robust.Shared.Physics;
  8. using Robust.Shared.Physics.Systems;
  9. using Robust.Shared.Utility;
  10. namespace Content.Shared.Construction.Conditions
  11. {
  12. [UsedImplicitly]
  13. [DataDefinition]
  14. public sealed partial class WallmountCondition : IConstructionCondition
  15. {
  16. public bool Condition(EntityUid user, EntityCoordinates location, Direction direction)
  17. {
  18. var entManager = IoCManager.Resolve<IEntityManager>();
  19. // get blueprint and user position
  20. var transformSystem = entManager.System<SharedTransformSystem>();
  21. var userWorldPosition = transformSystem.GetWorldPosition(user);
  22. var objWorldPosition = location.ToMap(entManager, transformSystem).Position;
  23. // find direction from user to blueprint
  24. var userToObject = (objWorldPosition - userWorldPosition);
  25. // get direction of the grid being placed on as an offset.
  26. var gridRotation = transformSystem.GetWorldRotation(location.EntityId);
  27. var directionWithOffset = gridRotation.RotateVec(direction.ToVec());
  28. // dot product will be positive if user direction and blueprint are co-directed
  29. var dotProd = Vector2.Dot(directionWithOffset.Normalized(), userToObject.Normalized());
  30. if (dotProd > 0)
  31. return false;
  32. // now we need to check that user actually tries to build wallmount on a wall
  33. var physics = entManager.System<SharedPhysicsSystem>();
  34. var rUserToObj = new CollisionRay(userWorldPosition, userToObject.Normalized(), (int) CollisionGroup.Impassable);
  35. var length = userToObject.Length();
  36. var tagSystem = entManager.System<TagSystem>();
  37. var userToObjRaycastResults = physics.IntersectRayWithPredicate(entManager.GetComponent<TransformComponent>(user).MapID, rUserToObj, maxLength: length,
  38. predicate: (e) => !tagSystem.HasTag(e, "Wall"));
  39. var targetWall = userToObjRaycastResults.FirstOrNull();
  40. if (targetWall == null)
  41. return false;
  42. // get this wall entity
  43. // check that we didn't try to build wallmount that facing another adjacent wall
  44. var rAdjWall = new CollisionRay(objWorldPosition, directionWithOffset.Normalized(), (int) CollisionGroup.Impassable);
  45. var adjWallRaycastResults = physics.IntersectRayWithPredicate(entManager.GetComponent<TransformComponent>(user).MapID, rAdjWall, maxLength: 0.5f,
  46. predicate: e => e == targetWall.Value.HitEntity || !tagSystem.HasTag(e, "Wall"));
  47. return !adjWallRaycastResults.Any();
  48. }
  49. public ConstructionGuideEntry GenerateGuideEntry()
  50. {
  51. return new ConstructionGuideEntry()
  52. {
  53. Localization = "construction-step-condition-wallmount",
  54. };
  55. }
  56. }
  57. }