Merge physics rewrite
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.Interfaces.GameObjects.Components.Movement;
|
using Content.Server.Interfaces.GameObjects.Components.Movement;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using Robust.Server.AI;
|
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));
|
var ray = new CollisionRay(myTransform.WorldPosition, dir.Normalized, (int)(CollisionGroup.MobImpassable | CollisionGroup.Impassable));
|
||||||
|
|
||||||
// cast the ray
|
// 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
|
// add to visible list
|
||||||
if (result.HitEntity == entity)
|
if (result.HitEntity == entity)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Movement;
|
using Content.Server.GameObjects.Components.Movement;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Server.Interfaces.Chat;
|
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 dir = new Vector2(Random01(ref rngState) * 2 - 1, Random01(ref rngState) *2 -1).Normalized;
|
||||||
var ray = new CollisionRay(entWorldPos, dir, (int) CollisionGroup.Impassable);
|
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
|
var rayResult = rayResults[0];
|
||||||
_walkTargetPos = entWorldPos + dir * (rayResult.Distance - 0.5f);
|
if (rayResult.Distance > 1) // hit an impassable object
|
||||||
WalkingPositiveEdge();
|
{
|
||||||
return;
|
// set the new position back from the wall a bit
|
||||||
|
_walkTargetPos = entWorldPos + dir * (rayResult.Distance - 0.5f);
|
||||||
|
WalkingPositiveEdge();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else // hit nothing (path clear)
|
||||||
if (!rayResult.DidHitObject) // hit nothing (path clear)
|
|
||||||
{
|
{
|
||||||
_walkTargetPos = dir * MaxWalkDistance;
|
_walkTargetPos = dir * MaxWalkDistance;
|
||||||
WalkingPositiveEdge();
|
WalkingPositiveEdge();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using Content.Server.GameObjects.Components.Access;
|
using Content.Server.GameObjects.Components.Access;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Shared.GameObjects.Components.Doors;
|
using Content.Shared.GameObjects.Components.Doors;
|
||||||
@@ -17,7 +18,7 @@ namespace Content.Server.GameObjects
|
|||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[ComponentReference(typeof(IActivate))]
|
[ComponentReference(typeof(IActivate))]
|
||||||
public class ServerDoorComponent : Component, IActivate
|
public class ServerDoorComponent : Component, IActivate, ICollideBehavior
|
||||||
{
|
{
|
||||||
public override string Name => "Door";
|
public override string Name => "Door";
|
||||||
|
|
||||||
@@ -85,26 +86,16 @@ namespace Content.Server.GameObjects
|
|||||||
ActivateImpl(eventArgs);
|
ActivateImpl(eventArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void HandleMessage(ComponentMessage message, IComponent component)
|
|
||||||
|
void ICollideBehavior.CollideWith(IEntity entity)
|
||||||
{
|
{
|
||||||
base.HandleMessage(message, component);
|
if (State != DoorState.Closed)
|
||||||
|
|
||||||
switch (message)
|
|
||||||
{
|
{
|
||||||
case BumpedEntMsg msg:
|
return;
|
||||||
if (State != DoorState.Closed)
|
}
|
||||||
{
|
if (entity.HasComponent(typeof(SpeciesComponent)))
|
||||||
return;
|
{
|
||||||
}
|
TryOpen(entity);
|
||||||
|
|
||||||
// Only open when bumped by mobs.
|
|
||||||
if (!msg.Entity.HasComponent(typeof(SpeciesComponent)))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TryOpen(msg.Entity);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +146,7 @@ namespace Content.Server.GameObjects
|
|||||||
|
|
||||||
Timer.Spawn(OpenTimeOne, async () =>
|
Timer.Spawn(OpenTimeOne, async () =>
|
||||||
{
|
{
|
||||||
collidableComponent.IsHardCollidable = false;
|
collidableComponent.CanCollide = false;
|
||||||
|
|
||||||
await Timer.Delay(OpenTimeTwo, _cancellationTokenSource.Token);
|
await Timer.Delay(OpenTimeTwo, _cancellationTokenSource.Token);
|
||||||
|
|
||||||
@@ -191,14 +182,14 @@ namespace Content.Server.GameObjects
|
|||||||
|
|
||||||
public bool Close()
|
public bool Close()
|
||||||
{
|
{
|
||||||
if (collidableComponent.TryCollision(Vector2.Zero))
|
if (collidableComponent.IsColliding(Vector2.Zero))
|
||||||
{
|
{
|
||||||
// Do nothing, somebody's in the door.
|
// Do nothing, somebody's in the door.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
State = DoorState.Closing;
|
State = DoorState.Closing;
|
||||||
collidableComponent.IsHardCollidable = true;
|
collidableComponent.CanCollide = true;
|
||||||
OpenTimeCounter = 0;
|
OpenTimeCounter = 0;
|
||||||
SetAppearance(DoorVisualState.Closing);
|
SetAppearance(DoorVisualState.Closing);
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace Content.Server.GameObjects.Components.Fluids
|
|||||||
// Small puddles will evaporate after a set delay
|
// Small puddles will evaporate after a set delay
|
||||||
|
|
||||||
// TODO: 'leaves fluidtracks', probably in a separate component for stuff like gibb chunks?;
|
// 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)
|
// 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
|
// to check for low volumes for evaporation or whatever
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ namespace Content.Server.GameObjects.Components
|
|||||||
{
|
{
|
||||||
if (Owner.TryGetComponent<ICollidableComponent>(out var collidableComponent))
|
if (Owner.TryGetComponent<ICollidableComponent>(out var collidableComponent))
|
||||||
{
|
{
|
||||||
collidableComponent.CollisionEnabled = IsCollidableWhenOpen || !Open;
|
collidableComponent.CanCollide = IsCollidableWhenOpen || !Open;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Owner.TryGetComponent<PlaceableSurfaceComponent>(out var placeableSurfaceComponent))
|
if (Owner.TryGetComponent<PlaceableSurfaceComponent>(out var placeableSurfaceComponent))
|
||||||
@@ -250,7 +250,7 @@ namespace Content.Server.GameObjects.Components
|
|||||||
entity.Transform.WorldPosition = worldPos;
|
entity.Transform.WorldPosition = worldPos;
|
||||||
if (entityCollidableComponent != null)
|
if (entityCollidableComponent != null)
|
||||||
{
|
{
|
||||||
entityCollidableComponent.CollisionEnabled = false;
|
entityCollidableComponent.CanCollide = false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -265,7 +265,7 @@ namespace Content.Server.GameObjects.Components
|
|||||||
{
|
{
|
||||||
if (contained.TryGetComponent<ICollidableComponent>(out var entityCollidableComponent))
|
if (contained.TryGetComponent<ICollidableComponent>(out var entityCollidableComponent))
|
||||||
{
|
{
|
||||||
entityCollidableComponent.CollisionEnabled = true;
|
entityCollidableComponent.CanCollide = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ namespace Content.Server.GameObjects
|
|||||||
|
|
||||||
if (entity.TryGetComponent(out CollidableComponent collidable))
|
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))
|
if (entity.TryGetComponent(out CollidableComponent collidable))
|
||||||
{
|
{
|
||||||
collidable.CollisionEnabled = true;
|
collidable.CanCollide = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
base.OnAdd();
|
base.OnAdd();
|
||||||
if (Owner.TryGetComponent<CollidableComponent>(out var collide))
|
if (Owner.TryGetComponent<CollidableComponent>(out var collide))
|
||||||
{
|
{
|
||||||
collide.IsHardCollidable = false;
|
//collide.IsHardCollidable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_state = PortalState.Pending;
|
_state = PortalState.Pending;
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ namespace Content.Server.GameObjects.Components.Movement
|
|||||||
if (!gridEntity.HasComponent<ICollidableComponent>())
|
if (!gridEntity.HasComponent<ICollidableComponent>())
|
||||||
{
|
{
|
||||||
var collideComp = gridEntity.AddComponent<CollidableComponent>();
|
var collideComp = gridEntity.AddComponent<CollidableComponent>();
|
||||||
collideComp.CollisionEnabled = true;
|
collideComp.CanCollide = true;
|
||||||
collideComp.IsHardCollidable = true;
|
//collideComp.IsHardCollidable = true;
|
||||||
collideComp.PhysicsShapes.Add(new PhysShapeGrid(grid));
|
collideComp.PhysicsShapes.Add(new PhysShapeGrid(grid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,36 +62,32 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applys the damage when our projectile collides with its victim
|
/// Applies the damage when our projectile collides with its victim
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="collidedwith"></param>
|
/// <param name="entity"></param>
|
||||||
void ICollideBehavior.CollideWith(List<IEntity> 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);
|
damage.TakeDamage(damageType, amount, Owner, 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ namespace Content.Server.GameObjects.Components
|
|||||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
|
private bool _shouldCollide = true;
|
||||||
|
|
||||||
public override string Name => "ThrownItem";
|
public override string Name => "ThrownItem";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,32 +27,37 @@ namespace Content.Server.GameObjects.Components
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public IEntity User;
|
public IEntity User;
|
||||||
|
|
||||||
void ICollideBehavior.CollideWith(List<IEntity> 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
|
// Stop colliding with mobs, this mimics not having enough velocity to do damage
|
||||||
// after impacting the first object.
|
// after impacting the first object.
|
||||||
// For realism this should actually be changed when the velocity of the object is less than a threshold.
|
// 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.
|
// 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.PhysicsShapes[0].CollisionMask &= (int)~CollisionGroup.MobImpassable;
|
||||||
body.IsScrapingFloor = true;
|
|
||||||
|
|
||||||
// KYS, your job is finished. Trigger ILand as well.
|
// KYS, your job is finished. Trigger ILand as well.
|
||||||
|
var physics = Owner.GetComponent<PhysicsComponent>();
|
||||||
|
(physics.Controller as ThrowController).StopThrow();
|
||||||
|
physics.RemoveController();
|
||||||
Owner.RemoveComponent<ThrownItemComponent>();
|
Owner.RemoveComponent<ThrownItemComponent>();
|
||||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().LandInteraction(User, Owner, Owner.Transform.GridPosition);
|
_entitySystemManager.GetEntitySystem<InteractionSystem>().LandInteraction(User, Owner, Owner.Transform.GridPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
using Content.Server.GameObjects.EntitySystems;
|
||||||
using Content.Shared.GameObjects;
|
using Content.Shared.GameObjects;
|
||||||
using Content.Shared.GameObjects.Components.Items;
|
using Content.Shared.GameObjects.Components.Items;
|
||||||
@@ -140,7 +141,7 @@ namespace Content.Server.GameObjects.Components.Weapon.Melee
|
|||||||
for (var i = 0; i < increments; i++)
|
for (var i = 0; i < increments; i++)
|
||||||
{
|
{
|
||||||
var castAngle = new Angle(baseAngle + increment * 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)
|
if (res.HitEntity != null)
|
||||||
{
|
{
|
||||||
resSet.Add(res.HitEntity);
|
resSet.Add(res.HitEntity);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Content.Server.GameObjects.Components.Power;
|
using Content.Server.GameObjects.Components.Power;
|
||||||
using Content.Server.GameObjects.Components.Sound;
|
using Content.Server.GameObjects.Components.Sound;
|
||||||
using Content.Server.GameObjects.EntitySystems;
|
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 angle = new Angle(clickLocation.Position - userPosition);
|
||||||
|
|
||||||
var ray = new CollisionRay(userPosition, angle.ToVec(), (int)(CollisionGroup.Impassable | CollisionGroup.MobImpassable));
|
var ray = new CollisionRay(userPosition, angle.ToVec(), (int)(CollisionGroup.Impassable | CollisionGroup.MobImpassable));
|
||||||
var rayCastResults = IoCManager.Resolve<IPhysicsManager>().IntersectRay(user.Transform.MapID, ray, MaxLength, user, ignoreNonHardCollidables: true);
|
var rayCastResults = IoCManager.Resolve<IPhysicsManager>().IntersectRay(user.Transform.MapID, ray, MaxLength, user).ToList();
|
||||||
|
|
||||||
Hit(rayCastResults, energyModifier, user);
|
if (rayCastResults.Count == 1)
|
||||||
AfterEffects(user, rayCastResults, angle, energyModifier);
|
{
|
||||||
|
Hit(rayCastResults[0], energyModifier, user);
|
||||||
|
AfterEffects(user, rayCastResults[0], angle, energyModifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Hit(RayCastResults ray, float damageModifier, IEntity user = null)
|
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)
|
protected virtual void AfterEffects(IEntity user, RayCastResults ray, Angle angle, float energyModifier)
|
||||||
{
|
{
|
||||||
var time = IoCManager.Resolve<IGameTiming>().CurTime;
|
var time = IoCManager.Resolve<IGameTiming>().CurTime;
|
||||||
var dist = ray.DidHitObject ? ray.Distance : MaxLength;
|
var dist = ray.Distance;
|
||||||
var offset = angle.ToVec() * dist / 2;
|
var offset = angle.ToVec() * dist / 2;
|
||||||
var message = new EffectSystemMessage
|
var message = new EffectSystemMessage
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Content.Server.Observer;
|
|||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.GameObjects.Components.Inventory;
|
using Content.Shared.GameObjects.Components.Inventory;
|
||||||
using Content.Shared.Maps;
|
using Content.Shared.Maps;
|
||||||
|
using Content.Shared.Physics;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Server.GameObjects.EntitySystems;
|
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)
|
private void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, PhysicsComponent physics, CollidableComponent collider = null)
|
||||||
{
|
{
|
||||||
bool weightless = false;
|
if (physics.Controller == null)
|
||||||
|
{
|
||||||
|
// Set up controller
|
||||||
|
physics.SetController<MoverController>();
|
||||||
|
}
|
||||||
|
|
||||||
|
var weightless = false;
|
||||||
|
|
||||||
var tile = _mapManager.GetGrid(transform.GridID).GetTileRef(transform.GridPosition).Tile;
|
var tile = _mapManager.GetGrid(transform.GridID).GetTileRef(transform.GridPosition).Tile;
|
||||||
|
|
||||||
@@ -167,27 +174,27 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
&& !entity.HasComponent<ItemComponent>(); // This can't be an item
|
&& !entity.HasComponent<ItemComponent>(); // This can't be an item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!touching)
|
if (!touching)
|
||||||
{
|
{
|
||||||
return;
|
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
|
else
|
||||||
{
|
{
|
||||||
if (weightless)
|
if (weightless)
|
||||||
{
|
{
|
||||||
physics.LinearVelocity = mover.VelocityDir * mover.CurrentPushSpeed;
|
(physics.Controller as MoverController)?.Push(mover.VelocityDir, mover.CurrentPushSpeed);
|
||||||
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
(physics.Controller as MoverController)?.Move(mover.VelocityDir,
|
||||||
physics.LinearVelocity = mover.VelocityDir * (mover.Sprinting ? mover.CurrentSprintSpeed : mover.CurrentWalkSpeed);
|
mover.Sprinting ? mover.CurrentSprintSpeed : mover.CurrentWalkSpeed);
|
||||||
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
transform.LocalRotation = mover.VelocityDir.GetDir().ToAngle();
|
||||||
|
|
||||||
// Handle footsteps.
|
// Handle footsteps.
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace Content.Server.Throw
|
|||||||
|
|
||||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||||
|
|
||||||
colComp.CollisionEnabled = true;
|
colComp.CanCollide = true;
|
||||||
// I can now collide with player, so that i can do damage.
|
// I can now collide with player, so that i can do damage.
|
||||||
|
|
||||||
if (!thrownEnt.TryGetComponent(out ThrownItemComponent projComp))
|
if (!thrownEnt.TryGetComponent(out ThrownItemComponent projComp))
|
||||||
@@ -37,7 +37,7 @@ namespace Content.Server.Throw
|
|||||||
colComp.PhysicsShapes.Add(new PhysShapeAabb());
|
colComp.PhysicsShapes.Add(new PhysShapeAabb());
|
||||||
|
|
||||||
colComp.PhysicsShapes[0].CollisionMask |= (int) (CollisionGroup.MobImpassable | CollisionGroup.Impassable);
|
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));
|
var angle = new Angle(targetLoc.ToMapPos(mapManager) - sourceLoc.ToMapPos(mapManager));
|
||||||
|
|
||||||
@@ -58,20 +58,16 @@ namespace Content.Server.Throw
|
|||||||
if (!thrownEnt.TryGetComponent(out PhysicsComponent physComp))
|
if (!thrownEnt.TryGetComponent(out PhysicsComponent physComp))
|
||||||
physComp = thrownEnt.AddComponent<PhysicsComponent>();
|
physComp = thrownEnt.AddComponent<PhysicsComponent>();
|
||||||
|
|
||||||
// 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<IGameTiming>();
|
var timing = IoCManager.Resolve<IGameTiming>();
|
||||||
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<ThrowController>();
|
||||||
|
(physComp.Controller as ThrowController)?.StartThrow(angle.ToVec() * spd);
|
||||||
|
|
||||||
if (throwSourceEnt != null)
|
if (throwSourceEnt != null && throwSourceEnt.TryGetComponent<PhysicsComponent>(out var physics))
|
||||||
{
|
{
|
||||||
var p = throwSourceEnt.GetComponent<PhysicsComponent>();
|
const float ThrowFactor = 5.0f; // Break Newton's Third Law for better gameplay
|
||||||
var playerAccel = 5 * throwForce / (float) Math.Max(0.001, p.Mass);
|
(physics.Controller as MoverController)?.Push(-angle.ToVec(), spd * ThrowFactor / physics.Mass);
|
||||||
p.LinearVelocity = Angle.FromDegrees(angle.Degrees + 180).ToVec()
|
|
||||||
* playerAccel / (1f / timing.TickRate);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using Content.Shared.Physics;
|
using Content.Shared.Physics;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.GameObjects.Systems;
|
using Robust.Shared.GameObjects.Systems;
|
||||||
@@ -48,8 +49,8 @@ namespace Content.Server.GameObjects.EntitySystems
|
|||||||
if (range > 0f && !(dir.LengthSquared <= range * range)) return false;
|
if (range > 0f && !(dir.LengthSquared <= range * range)) return false;
|
||||||
|
|
||||||
var ray = new CollisionRay(coords.Position, dir.Normalized, collisionMask);
|
var ray = new CollisionRay(coords.Position, dir.Normalized, collisionMask);
|
||||||
var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate, true);
|
var rayResults = _physicsManager.IntersectRayWithPredicate(coords.MapId, ray, dir.Length, predicate).ToList();
|
||||||
if(!rayResults.DidHitObject || (insideBlockerValid && rayResults.DidHitObject && (rayResults.HitPos - otherCoords).Length < 1f))
|
if(rayResults.Count == 0 || (insideBlockerValid && rayResults.Count > 0 && (rayResults[0].HitPos - otherCoords).Length < 1f))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (_mapManager.TryFindGridAt(coords, out var mapGrid) && mapGrid != null)
|
if (_mapManager.TryFindGridAt(coords, out var mapGrid) && mapGrid != null)
|
||||||
|
|||||||
61
Content.Shared/Physics/MoverController.cs
Normal file
61
Content.Shared/Physics/MoverController.cs
Normal file
@@ -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<IPhysicsManager>().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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
51
Content.Shared/Physics/ThrowController.cs
Normal file
51
Content.Shared/Physics/ThrowController.cs
Normal file
@@ -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<IPhysicsManager>().IsWeightless(_component.Owner.Transform.GridPosition))
|
||||||
|
{
|
||||||
|
Timer.Spawn((int) (ThrowTime * 1000), StopThrow);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_component.Status = BodyStatus.OnGround;
|
||||||
|
_component.LinearVelocity = Vector2.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThrowController()
|
||||||
|
{
|
||||||
|
ThrowTime = DefaultThrowTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Submodule RobustToolbox updated: 5d3f573f3c...274334c926
Reference in New Issue
Block a user