/// <summary> /// Call if this entity is relevant for the pathfinder /// </summary> /// <param name="entity"></param> /// TODO: These 2 methods currently don't account for a bunch of changes (e.g. airlock unpowered, wrenching, etc.) /// TODO: Could probably optimise this slightly more. public void AddEntity(IEntity entity, ICollidableComponent collidableComponent) { // If we're a door if (entity.HasComponent <AirlockComponent>() || entity.HasComponent <ServerDoorComponent>()) { // If we need access to traverse this then add to readers, otherwise no point adding it (except for maybe tile costs in future) // TODO: Check for powered I think (also need an event for when it's depowered // AccessReader calls this whenever opening / closing but it can seem to get called multiple times // Which may or may not be intended? if (entity.TryGetComponent(out AccessReader accessReader) && !_accessReaders.ContainsKey(entity)) { _accessReaders.Add(entity, accessReader); ParentChunk.Dirty(); } return; } DebugTools.Assert((PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) != 0); if (!collidableComponent.Anchored) { _physicsLayers.Add(entity, collidableComponent.CollisionLayer); } else { _blockedCollidables.Add(entity, collidableComponent.CollisionLayer); GenerateMask(); ParentChunk.Dirty(); } }
public void CollidedWith(ICollidableComponent component) { if (component is Asteroid) { Destroyed = true; } }
private void ProcessFriction(ICollidableComponent body, float deltaTime) { if (body.LinearVelocity == Vector2.Zero) { return; } // sliding friction coefficient, and current gravity at current location var(friction, gravity) = GetFriction(body); // friction between the two objects var effectiveFriction = friction * body.Friction; // current acceleration due to friction var fAcceleration = effectiveFriction * gravity; // integrate acceleration var fVelocity = fAcceleration * deltaTime; // Clamp friction because friction can't make you accelerate backwards friction = Math.Min(fVelocity, body.LinearVelocity.Length); // No multiplication/division by mass here since that would be redundant. var frictionVelocityChange = body.LinearVelocity.Normalized * -friction; body.LinearVelocity += frictionVelocityChange; }
private bool IsAroundCollider(ITransformComponent transform, IMoverComponent mover, ICollidableComponent collider) { foreach (var entity in _entityManager.GetEntitiesInRange(transform.Owner, mover.GrabRange, true)) { if (entity == transform.Owner) { continue; // Don't try to push off of yourself! } if (!entity.TryGetComponent <ICollidableComponent>(out var otherCollider)) { continue; } // Don't count pulled entities if (otherCollider.HasController <PullController>()) { continue; } // TODO: Item check. var touching = ((collider.CollisionMask & otherCollider.CollisionLayer) != 0x0 || (otherCollider.CollisionMask & collider.CollisionLayer) != 0x0) && // Ensure collision !entity.HasComponent <IItemComponent>(); // This can't be an item if (touching) { return(true); } } return(false); }
private void UpdatePosition(ICollidableComponent collidable, float frameTime) { var ent = collidable.Entity; if (!collidable.CanMove() || (collidable.LinearVelocity.LengthSquared < Epsilon && MathF.Abs(collidable.AngularVelocity) < Epsilon)) { return; } if (collidable.LinearVelocity != Vector2.Zero) { if (ContainerHelpers.IsInContainer(ent)) { var relayEntityMoveMessage = new RelayMovementEntityMessage(ent); ent.Transform.Parent !.Owner.SendMessage(ent.Transform, relayEntityMoveMessage); // This prevents redundant messages from being sent if solveIterations > 1 and also simulates the entity "colliding" against the locker door when it opens. collidable.LinearVelocity = Vector2.Zero; } } collidable.Owner.Transform.DeferUpdates = true; _deferredUpdates.Add(collidable); collidable.WorldRotation += collidable.AngularVelocity * frameTime; collidable.WorldPosition += collidable.LinearVelocity * frameTime; }
public override void Initialize() { base.Initialize(); _collidableComponent = Owner.GetComponent <ICollidableComponent>(); _doAfterSystem = EntitySystem.Get <DoAfterSystem>(); }
public static bool IsRelevant(IEntity entity, ICollidableComponent collidableComponent) { if (entity.Transform.GridID == GridId.Invalid || (PathfindingSystem.TrackedCollisionLayers & collidableComponent.CollisionLayer) == 0) { return(false); } return(true); }
public float CalculatePenetration(ICollidableComponent target, ICollidableComponent source) { var manifold = target.WorldAABB.Intersect(source.WorldAABB); if (manifold.IsEmpty()) { return(0.0f); } return(manifold.Height > manifold.Width ? manifold.Width : manifold.Height); }
public Manifold(ICollidableComponent A, ICollidableComponent B, [CanBeNull] SharedPhysicsComponent aPhysics, [CanBeNull] SharedPhysicsComponent bPhysics) { var physicsManager = IoCManager.Resolve <IPhysicsManager>(); this.A = A; this.B = B; Normal = physicsManager.CalculateNormal(A, B); APhysics = aPhysics; BPhysics = bPhysics; }
private (float friction, float gravity) GetFriction(ICollidableComponent body) { if (!body.OnGround) { return(0f, 0f); } var location = body.Owner.Transform; var grid = _mapManager.GetGrid(location.GridPosition.GridID); var tile = grid.GetTileRef(location.GridPosition); var tileDef = _tileDefinitionManager[tile.Tile.TypeId]; return(tileDef.Friction, grid.HasGravity ? 9.8f : 0f); }
public void CollidedWith(ICollidableComponent component) { if (component is Fireball) { //GetService<ScoreService>().AddScore(); //GameServices.GetService<SoundService>().PlayExplosion(); Destroyed = true; } else if (component is Asteroid) { } else if (component is Ship) { Destroyed = true; } }
private bool Valid(IEntity user, IEntity?utilizing, [MaybeNullWhen(false)] out ICollidableComponent collidable, bool force = false) { if (!Owner.TryGetComponent(out collidable)) { return(false); } if (!force) { if (utilizing == null || !utilizing.TryGetComponent(out ToolComponent tool) || !tool.UseTool(user, Owner, ToolQuality.Anchoring)) { return(false); } } return(true); }
public void StartPull(ICollidableComponent puller) { DebugTools.AssertNotNull(puller); if (_puller == puller) { return; } _puller = puller; if (ControlledComponent == null) { return; } ControlledComponent.WakeBody(); var message = new PullStartedMessage(this, _puller, ControlledComponent); _puller.Owner.SendMessage(null, message); ControlledComponent.Owner.SendMessage(null, message); }
public Vector2 CalculateNormal(ICollidableComponent target, ICollidableComponent source) { var manifold = target.WorldAABB.Intersect(source.WorldAABB); if (manifold.IsEmpty()) { return(Vector2.Zero); } if (manifold.Height > manifold.Width) { // X is the axis of seperation var leftDist = source.WorldAABB.Right - target.WorldAABB.Left; var rightDist = target.WorldAABB.Right - source.WorldAABB.Left; return(new Vector2(leftDist > rightDist ? 1 : -1, 0)); } else { // Y is the axis of seperation var bottomDist = source.WorldAABB.Top - target.WorldAABB.Bottom; var topDist = target.WorldAABB.Top - source.WorldAABB.Bottom; return(new Vector2(0, bottomDist > topDist ? 1 : -1)); } }
public PullStartedMessage(PullController controller, ICollidableComponent puller, ICollidableComponent pulled) : base(controller, puller, pulled) { }
protected void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, ICollidableComponent collidable) { collidable.EnsureController <MoverController>(); var weightless = !transform.Owner.HasComponent <MovementIgnoreGravityComponent>() && _physicsManager.IsWeightless(transform.GridPosition); if (weightless) { // No gravity: is our entity touching anything? var touching = IsAroundCollider(transform, mover, collidable); if (!touching) { return; } } // TODO: movement check. var(walkDir, sprintDir) = mover.VelocityDir; var combined = walkDir + sprintDir; if (combined.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner) && !weightless) { if (collidable.TryGetController(out MoverController controller)) { controller.StopMoving(); } } else { if (weightless) { if (collidable.TryGetController(out MoverController controller)) { controller.Push(combined, mover.CurrentPushSpeed); } transform.LocalRotation = walkDir.GetDir().ToAngle(); return; } var total = walkDir * mover.CurrentWalkSpeed + sprintDir * mover.CurrentSprintSpeed; { if (collidable.TryGetController(out MoverController controller)) { controller.Move(total, 1); } } transform.LocalRotation = total.GetDir().ToAngle(); HandleFootsteps(mover); } }
protected PullMessage(PullController controller, ICollidableComponent puller, ICollidableComponent pulled) { Controller = controller; Puller = puller; Pulled = pulled; }
private void FindCollisionsFor(ICollidableComponent a, HashSet <(EntityUid, EntityUid)> combinations)