diff --git a/Content.Client/GameObjects/Components/Chemistry/InjectorComponent.cs b/Content.Client/GameObjects/Components/Chemistry/InjectorComponent.cs index 359dbeb282..6556989340 100644 --- a/Content.Client/GameObjects/Components/Chemistry/InjectorComponent.cs +++ b/Content.Client/GameObjects/Components/Chemistry/InjectorComponent.cs @@ -30,7 +30,7 @@ namespace Content.Client.GameObjects.Components.Chemistry //Handle net updates public override void HandleComponentState(ComponentState curState, ComponentState nextState) { - var cast = (InjectorComponentState) curState; + var cast = (InjectorComponentState) curState; if (cast != null) { CurrentVolume = cast.CurrentVolume; @@ -64,7 +64,7 @@ namespace Content.Client.GameObjects.Components.Chemistry { return; } - + _parent._uiUpdateNeeded = false; //Update current volume and injector state diff --git a/Content.Server/AI/AimShootLifeProcessor.cs b/Content.Server/AI/AimShootLifeProcessor.cs index 159b0f79b5..52f7b06d57 100644 --- a/Content.Server/AI/AimShootLifeProcessor.cs +++ b/Content.Server/AI/AimShootLifeProcessor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Content.Server.Interfaces.GameObjects.Components.Movement; using Content.Shared.Physics; using Robust.Server.AI; @@ -114,7 +115,7 @@ namespace Content.Server.AI var ray = new CollisionRay(myTransform.WorldPosition, dir.Normalized, (int)(CollisionGroup.MobImpassable | CollisionGroup.Impassable)); // cast the ray - var result = _physMan.IntersectRay(myTransform.MapID, ray, maxRayLen, SelfEntity); + var result = _physMan.IntersectRay(myTransform.MapID, ray, maxRayLen, SelfEntity).First(); // add to visible list if (result.HitEntity == entity) diff --git a/Content.Server/AI/WanderProcessor.cs b/Content.Server/AI/WanderProcessor.cs index 1889ce9ac2..bcd7b3579c 100644 --- a/Content.Server/AI/WanderProcessor.cs +++ b/Content.Server/AI/WanderProcessor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Content.Server.GameObjects.Components.Movement; using Content.Server.GameObjects.EntitySystems; using Content.Server.Interfaces.Chat; @@ -127,17 +128,20 @@ namespace Content.Server.AI { var dir = new Vector2(Random01(ref rngState) * 2 - 1, Random01(ref rngState) *2 -1).Normalized; var ray = new CollisionRay(entWorldPos, dir, (int) CollisionGroup.Impassable); - var rayResult = _physMan.IntersectRay(SelfEntity.Transform.MapID, ray, MaxWalkDistance, SelfEntity); + var rayResults = _physMan.IntersectRay(SelfEntity.Transform.MapID, ray, MaxWalkDistance, SelfEntity).ToList(); - if (rayResult.DidHitObject && rayResult.Distance > 1) // hit an impassable object + if (rayResults.Count == 1) { - // set the new position back from the wall a bit - _walkTargetPos = entWorldPos + dir * (rayResult.Distance - 0.5f); - WalkingPositiveEdge(); - return; + var rayResult = rayResults[0]; + if (rayResult.Distance > 1) // hit an impassable object + { + // set the new position back from the wall a bit + _walkTargetPos = entWorldPos + dir * (rayResult.Distance - 0.5f); + WalkingPositiveEdge(); + return; + } } - - if (!rayResult.DidHitObject) // hit nothing (path clear) + else // hit nothing (path clear) { _walkTargetPos = dir * MaxWalkDistance; WalkingPositiveEdge(); diff --git a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs index 443c0fae96..3e496bf08a 100644 --- a/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs +++ b/Content.Server/GameObjects/Components/Doors/ServerDoorComponent.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.EntitySystems; using Content.Shared.GameObjects.Components.Doors; @@ -17,7 +18,7 @@ namespace Content.Server.GameObjects { [RegisterComponent] [ComponentReference(typeof(IActivate))] - public class ServerDoorComponent : Component, IActivate + public class ServerDoorComponent : Component, IActivate, ICollideBehavior { public override string Name => "Door"; @@ -85,26 +86,16 @@ namespace Content.Server.GameObjects ActivateImpl(eventArgs); } - public override void HandleMessage(ComponentMessage message, IComponent component) + + void ICollideBehavior.CollideWith(IEntity entity) { - base.HandleMessage(message, component); - - switch (message) + if (State != DoorState.Closed) { - case BumpedEntMsg msg: - if (State != DoorState.Closed) - { - return; - } - - // Only open when bumped by mobs. - if (!msg.Entity.HasComponent(typeof(SpeciesComponent))) - { - return; - } - - TryOpen(msg.Entity); - break; + return; + } + if (entity.HasComponent(typeof(SpeciesComponent))) + { + TryOpen(entity); } } @@ -155,7 +146,7 @@ namespace Content.Server.GameObjects Timer.Spawn(OpenTimeOne, async () => { - collidableComponent.IsHardCollidable = false; + collidableComponent.CanCollide = false; await Timer.Delay(OpenTimeTwo, _cancellationTokenSource.Token); @@ -191,14 +182,14 @@ namespace Content.Server.GameObjects public bool Close() { - if (collidableComponent.TryCollision(Vector2.Zero)) + if (collidableComponent.IsColliding(Vector2.Zero)) { // Do nothing, somebody's in the door. return false; } State = DoorState.Closing; - collidableComponent.IsHardCollidable = true; + collidableComponent.CanCollide = true; OpenTimeCounter = 0; SetAppearance(DoorVisualState.Closing); diff --git a/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs b/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs index ebc8d8b3be..020f833e6e 100644 --- a/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs +++ b/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs @@ -34,7 +34,7 @@ namespace Content.Server.GameObjects.Components.Fluids // Small puddles will evaporate after a set delay // TODO: 'leaves fluidtracks', probably in a separate component for stuff like gibb chunks?; - // TODO: Add stuff like slipping -> probably in a separate component (for stuff like bananas) and using BumpEntMsg + // TODO: Add stuff like slipping -> probably in a separate component (for stuff like bananas) // based on behaviour (e.g. someone being punched vs slashed with a sword would have different blood sprite) // to check for low volumes for evaporation or whatever diff --git a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs index 89243c45c7..f49c590dc5 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs @@ -190,7 +190,7 @@ namespace Content.Server.GameObjects.Components { if (Owner.TryGetComponent(out var collidableComponent)) { - collidableComponent.CollisionEnabled = IsCollidableWhenOpen || !Open; + collidableComponent.CanCollide = IsCollidableWhenOpen || !Open; } if (Owner.TryGetComponent(out var placeableSurfaceComponent)) @@ -250,7 +250,7 @@ namespace Content.Server.GameObjects.Components entity.Transform.WorldPosition = worldPos; if (entityCollidableComponent != null) { - entityCollidableComponent.CollisionEnabled = false; + entityCollidableComponent.CanCollide = false; } return true; } @@ -265,7 +265,7 @@ namespace Content.Server.GameObjects.Components { if (contained.TryGetComponent(out var entityCollidableComponent)) { - entityCollidableComponent.CollisionEnabled = true; + entityCollidableComponent.CanCollide = true; } } } diff --git a/Content.Server/GameObjects/Components/Mobs/DamageStates.cs b/Content.Server/GameObjects/Components/Mobs/DamageStates.cs index 74ce8cf13e..0fff5a9ef3 100644 --- a/Content.Server/GameObjects/Components/Mobs/DamageStates.cs +++ b/Content.Server/GameObjects/Components/Mobs/DamageStates.cs @@ -195,7 +195,7 @@ namespace Content.Server.GameObjects if (entity.TryGetComponent(out CollidableComponent collidable)) { - collidable.CollisionEnabled = false; + collidable.CanCollide = false; } } @@ -205,7 +205,7 @@ namespace Content.Server.GameObjects if (entity.TryGetComponent(out CollidableComponent collidable)) { - collidable.CollisionEnabled = true; + collidable.CanCollide = true; } } diff --git a/Content.Server/GameObjects/Components/Movement/ServerPortalComponent.cs b/Content.Server/GameObjects/Components/Movement/ServerPortalComponent.cs index 6538363143..582d0e04b9 100644 --- a/Content.Server/GameObjects/Components/Movement/ServerPortalComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ServerPortalComponent.cs @@ -63,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Movement base.OnAdd(); if (Owner.TryGetComponent(out var collide)) { - collide.IsHardCollidable = false; + //collide.IsHardCollidable = false; } _state = PortalState.Pending; diff --git a/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs b/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs index ebbcae52ea..643a92ff4d 100644 --- a/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ShuttleControllerComponent.cs @@ -65,8 +65,8 @@ namespace Content.Server.GameObjects.Components.Movement if (!gridEntity.HasComponent()) { var collideComp = gridEntity.AddComponent(); - collideComp.CollisionEnabled = true; - collideComp.IsHardCollidable = true; + collideComp.CanCollide = true; + //collideComp.IsHardCollidable = true; collideComp.PhysicsShapes.Add(new PhysShapeGrid(grid)); } diff --git a/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs index b2b3ca923e..0d2d309368 100644 --- a/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/ProjectileComponent.cs @@ -62,36 +62,32 @@ namespace Content.Server.GameObjects.Components.Projectiles } /// - /// Applys the damage when our projectile collides with its victim + /// Applies the damage when our projectile collides with its victim /// - /// - void ICollideBehavior.CollideWith(List collidedwith) + /// + void ICollideBehavior.CollideWith(IEntity entity) { - foreach (var entity in collidedwith) + if (entity.TryGetComponent(out DamageableComponent damage)) { - if (entity.TryGetComponent(out DamageableComponent damage)) + Owner.EntityManager.TryGetEntity(Shooter, out var shooter); + + foreach (var (damageType, amount) in _damages) { - Owner.EntityManager.TryGetEntity(Shooter, out var shooter); - - foreach (var (damageType, amount) in _damages) - { - - damage.TakeDamage(damageType, amount, Owner, shooter); - } - } - - if (!entity.Deleted && entity.TryGetComponent(out CameraRecoilComponent recoilComponent) - && Owner.TryGetComponent(out PhysicsComponent physicsComponent)) - { - var direction = physicsComponent.LinearVelocity.Normalized; - recoilComponent.Kick(direction); + damage.TakeDamage(damageType, amount, Owner, shooter); } } - if (collidedwith.Count > 0) + if (!entity.Deleted && entity.TryGetComponent(out CameraRecoilComponent recoilComponent) + && Owner.TryGetComponent(out PhysicsComponent physicsComponent)) { - Owner.Delete(); + var direction = physicsComponent.LinearVelocity.Normalized; + recoilComponent.Kick(direction); } } + + void ICollideBehavior.PostCollide(int collideCount) + { + if (collideCount > 0) Owner.Delete(); + } } } diff --git a/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs b/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs index cbc63c3231..c4f09636e1 100644 --- a/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs +++ b/Content.Server/GameObjects/Components/Projectiles/ThrownItemComponent.cs @@ -18,6 +18,8 @@ namespace Content.Server.GameObjects.Components [Dependency] private readonly IEntitySystemManager _entitySystemManager; #pragma warning restore 649 + private bool _shouldCollide = true; + public override string Name => "ThrownItem"; /// @@ -25,32 +27,37 @@ namespace Content.Server.GameObjects.Components /// public IEntity User; - void ICollideBehavior.CollideWith(List collidedwith) + void ICollideBehavior.CollideWith(IEntity entity) { - foreach (var entity in collidedwith) + if (!_shouldCollide) return; + if (entity.TryGetComponent(out DamageableComponent damage)) { - if (entity.TryGetComponent(out DamageableComponent damage)) - { - damage.TakeDamage(DamageType.Brute, 10, Owner, User); - } + damage.TakeDamage(DamageType.Brute, 10, Owner, User); } - // Stop colliding with mobs, this mimics not having enough velocity to do damage // after impacting the first object. // For realism this should actually be changed when the velocity of the object is less than a threshold. // This would allow ricochets off walls, and weird gravity effects from slowing the object. - if (collidedwith.Count > 0 && Owner.TryGetComponent(out CollidableComponent body) && body.PhysicsShapes.Count >= 1) + if (Owner.TryGetComponent(out CollidableComponent body) && body.PhysicsShapes.Count >= 1) + { + _shouldCollide = false; + } + } + + public void PostCollide(int collideCount) + { + + if (collideCount > 0 && Owner.TryGetComponent(out CollidableComponent body) && body.PhysicsShapes.Count >= 1) { body.PhysicsShapes[0].CollisionMask &= (int)~CollisionGroup.MobImpassable; - body.IsScrapingFloor = true; // KYS, your job is finished. Trigger ILand as well. + var physics = Owner.GetComponent(); + (physics.Controller as ThrowController).StopThrow(); + physics.RemoveController(); Owner.RemoveComponent(); _entitySystemManager.GetEntitySystem().LandInteraction(User, Owner, Owner.Transform.GridPosition); } - - - } } } diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs index c2f24bb97f..2760463a1e 100644 --- a/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Melee/MeleeWeaponComponent.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Content.Server.GameObjects.EntitySystems; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Items; @@ -140,7 +141,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee for (var i = 0; i < increments; i++) { var castAngle = new Angle(baseAngle + increment * i); - var res = _physicsManager.IntersectRay(mapId, new CollisionRay(position, castAngle.ToVec(), 23), _range, ignore, ignoreNonHardCollidables: true); + var res = _physicsManager.IntersectRay(mapId, new CollisionRay(position, castAngle.ToVec(), 23), _range, ignore).First(); if (res.HitEntity != null) { resSet.Add(res.HitEntity); diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs index 3fd4dd5d1e..a725d53ef9 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Hitscan/HitscanWeaponComponent.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Content.Server.GameObjects.Components.Power; using Content.Server.GameObjects.Components.Sound; using Content.Server.GameObjects.EntitySystems; @@ -90,10 +91,13 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Hitscan var angle = new Angle(clickLocation.Position - userPosition); var ray = new CollisionRay(userPosition, angle.ToVec(), (int)(CollisionGroup.Impassable | CollisionGroup.MobImpassable)); - var rayCastResults = IoCManager.Resolve().IntersectRay(user.Transform.MapID, ray, MaxLength, user, ignoreNonHardCollidables: true); + var rayCastResults = IoCManager.Resolve().IntersectRay(user.Transform.MapID, ray, MaxLength, user).ToList(); - Hit(rayCastResults, energyModifier, user); - AfterEffects(user, rayCastResults, angle, energyModifier); + if (rayCastResults.Count == 1) + { + Hit(rayCastResults[0], energyModifier, user); + AfterEffects(user, rayCastResults[0], angle, energyModifier); + } } protected virtual void Hit(RayCastResults ray, float damageModifier, IEntity user = null) @@ -109,7 +113,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Hitscan protected virtual void AfterEffects(IEntity user, RayCastResults ray, Angle angle, float energyModifier) { var time = IoCManager.Resolve().CurTime; - var dist = ray.DidHitObject ? ray.Distance : MaxLength; + var dist = ray.Distance; var offset = angle.ToVec() * dist / 2; var message = new EffectSystemMessage { diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BaseProjectileWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BaseProjectileWeaponComponent.cs index 3090ebdcfc..44b257cf80 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BaseProjectileWeaponComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Projectile/BaseProjectileWeaponComponent.cs @@ -42,7 +42,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Ranged.Projectile { var angle = GetAngleFromClickLocation(source, coord); FireAtAngle(source, angle, projectileType, spreadStdDev, projectilesFired, evenSpreadAngle, velocity); - } + } /// /// Fires projectile in the direction of an angle. diff --git a/Content.Server/GameObjects/EntitySystems/MoverSystem.cs b/Content.Server/GameObjects/EntitySystems/MoverSystem.cs index bdb05b95ce..133ea5df1f 100644 --- a/Content.Server/GameObjects/EntitySystems/MoverSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/MoverSystem.cs @@ -9,6 +9,7 @@ using Content.Server.Observer; using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.Maps; +using Content.Shared.Physics; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.GameObjects.EntitySystems; @@ -148,7 +149,13 @@ namespace Content.Server.GameObjects.EntitySystems private void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, PhysicsComponent physics, CollidableComponent collider = null) { - bool weightless = false; + if (physics.Controller == null) + { + // Set up controller + physics.SetController(); + } + + var weightless = false; var tile = _mapManager.GetGrid(transform.GridID).GetTileRef(transform.GridPosition).Tile; @@ -167,27 +174,27 @@ namespace Content.Server.GameObjects.EntitySystems && !entity.HasComponent(); // This can't be an item } } + if (!touching) { return; } } - if (mover.VelocityDir.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner)) - { - if (physics.LinearVelocity != Vector2.Zero) - physics.LinearVelocity = Vector2.Zero; + if (mover.VelocityDir.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner) && !weightless) + { + (physics.Controller as MoverController)?.StopMoving(); } else { if (weightless) { - physics.LinearVelocity = mover.VelocityDir * mover.CurrentPushSpeed; + (physics.Controller as MoverController)?.Push(mover.VelocityDir, mover.CurrentPushSpeed); transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle(); return; } - - physics.LinearVelocity = mover.VelocityDir * (mover.Sprinting ? mover.CurrentSprintSpeed : mover.CurrentWalkSpeed); + (physics.Controller as MoverController)?.Move(mover.VelocityDir, + mover.Sprinting ? mover.CurrentSprintSpeed : mover.CurrentWalkSpeed); transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle(); // Handle footsteps. diff --git a/Content.Server/Throw/ThrowHelper.cs b/Content.Server/Throw/ThrowHelper.cs index 77484fa656..8cdf31050a 100644 --- a/Content.Server/Throw/ThrowHelper.cs +++ b/Content.Server/Throw/ThrowHelper.cs @@ -26,7 +26,7 @@ namespace Content.Server.Throw var mapManager = IoCManager.Resolve(); - colComp.CollisionEnabled = true; + colComp.CanCollide = true; // I can now collide with player, so that i can do damage. if (!thrownEnt.TryGetComponent(out ThrownItemComponent projComp)) @@ -37,7 +37,7 @@ namespace Content.Server.Throw colComp.PhysicsShapes.Add(new PhysShapeAabb()); colComp.PhysicsShapes[0].CollisionMask |= (int) (CollisionGroup.MobImpassable | CollisionGroup.Impassable); - colComp.IsScrapingFloor = false; + colComp.Status = BodyStatus.InAir; } var angle = new Angle(targetLoc.ToMapPos(mapManager) - sourceLoc.ToMapPos(mapManager)); @@ -58,20 +58,16 @@ namespace Content.Server.Throw if (!thrownEnt.TryGetComponent(out PhysicsComponent physComp)) physComp = thrownEnt.AddComponent(); - // TODO: Move this into PhysicsSystem, we need an ApplyForce function. - var a = throwForce / (float) Math.Max(0.001, physComp.Mass); // a = f / m - var timing = IoCManager.Resolve(); - var spd = a / (1f / timing.TickRate); // acceleration is applied in 1 tick instead of 1 second, scale appropriately + var spd = throwForce / (1f / timing.TickRate); // acceleration is applied in 1 tick instead of 1 second, scale appropriately - physComp.LinearVelocity = angle.ToVec() * spd; + physComp.SetController(); + (physComp.Controller as ThrowController)?.StartThrow(angle.ToVec() * spd); - if (throwSourceEnt != null) + if (throwSourceEnt != null && throwSourceEnt.TryGetComponent(out var physics)) { - var p = throwSourceEnt.GetComponent(); - var playerAccel = 5 * throwForce / (float) Math.Max(0.001, p.Mass); - p.LinearVelocity = Angle.FromDegrees(angle.Degrees + 180).ToVec() - * playerAccel / (1f / timing.TickRate); + const float ThrowFactor = 5.0f; // Break Newton's Third Law for better gameplay + (physics.Controller as MoverController)?.Push(-angle.ToVec(), spd * ThrowFactor / physics.Mass); } } } diff --git a/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs index aa2f88c01a..47a613a91c 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedInteractionSystem.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Content.Shared.Physics; using JetBrains.Annotations; using Robust.Shared.GameObjects.Systems; @@ -48,8 +49,8 @@ namespace Content.Server.GameObjects.EntitySystems if (range > 0f && !(dir.LengthSquared <= range * range)) return false; var ray = new CollisionRay(coords.Position, dir.Normalized, collisionMask); - var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate, true); - if(!rayResults.DidHitObject || (insideBlockerValid && rayResults.DidHitObject && (rayResults.HitPos - otherCoords).Length < 1f)) + var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate).ToList(); + if(rayResults.Count == 0 || (insideBlockerValid && rayResults.Count > 0 && (rayResults[0].HitPos - otherCoords).Length < 1f)) { if (_mapManager.TryFindGridAt(coords, out var mapGrid) && mapGrid != null) diff --git a/Content.Shared/Physics/MoverController.cs b/Content.Shared/Physics/MoverController.cs new file mode 100644 index 0000000000..72159f632b --- /dev/null +++ b/Content.Shared/Physics/MoverController.cs @@ -0,0 +1,61 @@ +using System; +using Robust.Shared.Interfaces.Physics; +using Robust.Shared.IoC; +using Robust.Shared.Maths; +using Robust.Shared.Physics; + +namespace Content.Shared.Physics +{ + public class MoverController: VirtualController + { + private Vector2 _velocity; + private SharedPhysicsComponent _component = null; + + public Vector2 Velocity + { + get => _velocity; + set => _velocity = value; + } + + public override SharedPhysicsComponent ControlledComponent + { + set => _component = value; + } + + public MoverController() + { + _velocity = Vector2.Zero; + } + + public void Move(Vector2 velocityDirection, float speed) + { + if (IoCManager.Resolve().IsWeightless(_component.Owner.Transform.GridPosition)) return; + Push(velocityDirection, speed); + } + + public void Push(Vector2 velocityDirection, float speed) + { + Velocity = velocityDirection * speed; + } + + public void StopMoving() + { + Velocity = Vector2.Zero; + } + + public override void UpdateBeforeProcessing() + { + base.UpdateBeforeProcessing(); + + if (Velocity == Vector2.Zero) + { + // Try to stop movement + _component.LinearVelocity = Vector2.Zero; + } + else + { + _component.LinearVelocity = Velocity; + } + } + } +} diff --git a/Content.Shared/Physics/ThrowController.cs b/Content.Shared/Physics/ThrowController.cs new file mode 100644 index 0000000000..910afff257 --- /dev/null +++ b/Content.Shared/Physics/ThrowController.cs @@ -0,0 +1,51 @@ +using Robust.Shared.Interfaces.Physics; +using Robust.Shared.IoC; +using Robust.Shared.Maths; +using Robust.Shared.Physics; +using Robust.Shared.Timers; + +namespace Content.Shared.Physics +{ + public class ThrowController: VirtualController + { + private float _throwTime; + private SharedPhysicsComponent _component; + + private const float DefaultThrowTime = 0.25f; + + public float ThrowTime + { + get => _throwTime; + set => _throwTime = value; + } + + public override SharedPhysicsComponent ControlledComponent + { + set => _component = value; + } + + public void StartThrow(Vector2 initialImpulse) + { + _component.Momentum = initialImpulse; + _component.Status = BodyStatus.InAir; + Timer.Spawn((int) (ThrowTime * 1000), StopThrow); + } + + public void StopThrow() + { + if (_component == null) return; + if (IoCManager.Resolve().IsWeightless(_component.Owner.Transform.GridPosition)) + { + Timer.Spawn((int) (ThrowTime * 1000), StopThrow); + return; + } + _component.Status = BodyStatus.OnGround; + _component.LinearVelocity = Vector2.Zero; + } + + public ThrowController() + { + ThrowTime = DefaultThrowTime; + } + } +} diff --git a/RobustToolbox b/RobustToolbox index 5d3f573f3c..274334c926 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 5d3f573f3c0dce859d22247d05f1f106075e8645 +Subproject commit 274334c9268dac012f7269cfc592c28ce9ab80c6