@@ -5,7 +5,6 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using System;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Projectiles
|
||||
{
|
||||
@@ -37,9 +36,9 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
_solutionContainer = Owner.EnsureComponent<SolutionContainerComponent>();
|
||||
}
|
||||
|
||||
void ICollideBehavior.CollideWith(IPhysBody ourBody, IPhysBody otherBody)
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
{
|
||||
if (!otherBody.Entity.TryGetComponent<BloodstreamComponent>(out var bloodstream))
|
||||
if (!entity.TryGetComponent<BloodstreamComponent>(out var bloodstream))
|
||||
return;
|
||||
|
||||
var solution = _solutionContainer.Solution;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Server.GameObjects.Components.Explosion;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Projectiles
|
||||
{
|
||||
@@ -16,12 +15,18 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
Owner.EnsureComponent<ExplosiveComponent>();
|
||||
}
|
||||
|
||||
void ICollideBehavior.CollideWith(IPhysBody ourBody, IPhysBody otherBody)
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
{
|
||||
if (Owner.TryGetComponent(out ExplosiveComponent explosive))
|
||||
{
|
||||
explosive.Explosion();
|
||||
}
|
||||
}
|
||||
|
||||
// Projectile should handle the deleting
|
||||
void ICollideBehavior.PostCollide(int collisionCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Server.GameObjects.Components.Weapon;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Projectiles
|
||||
@@ -32,15 +31,20 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
Owner.EnsureComponent<ProjectileComponent>();
|
||||
}
|
||||
|
||||
void ICollideBehavior.CollideWith(IPhysBody ourBody, IPhysBody otherBody)
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
{
|
||||
if (_flashed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FlashableComponent.FlashAreaHelper(Owner, _range, _duration);
|
||||
_flashed = true;
|
||||
}
|
||||
|
||||
// Projectile should handle the deleting
|
||||
void ICollideBehavior.PostCollide(int collisionCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ using Content.Shared.GameObjects.Components.Damage;
|
||||
using Content.Shared.GameObjects.Components.Projectiles;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -13,7 +12,7 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Content.Server.GameObjects.Components.Projectiles
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class ProjectileComponent : SharedProjectileComponent, ICollideBehavior, IPostCollide
|
||||
public class ProjectileComponent : SharedProjectileComponent, ICollideBehavior
|
||||
{
|
||||
protected override EntityUid Shooter => _shooter;
|
||||
|
||||
@@ -28,14 +27,15 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
set => _damages = value;
|
||||
}
|
||||
|
||||
private bool _damagedEntity = false;
|
||||
|
||||
public bool DeleteOnCollide => _deleteOnCollide;
|
||||
private bool _deleteOnCollide;
|
||||
|
||||
// Get that juicy FPS hit sound
|
||||
private string _soundHit;
|
||||
private string _soundHitSpecies;
|
||||
|
||||
private bool _damagedEntity;
|
||||
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
@@ -58,27 +58,39 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
Dirty();
|
||||
}
|
||||
|
||||
private bool _internalDeleteOnCollide;
|
||||
|
||||
/// <summary>
|
||||
/// Applies the damage when our projectile collides with its victim
|
||||
/// Applies the damage when our projectile collides with its victim
|
||||
/// </summary>
|
||||
void ICollideBehavior.CollideWith(IPhysBody ourBody, IPhysBody otherBody)
|
||||
/// <param name="entity"></param>
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
{
|
||||
// This is so entities that shouldn't get a collision are ignored.
|
||||
if (!otherBody.Hard || _damagedEntity)
|
||||
if (_damagedEntity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (otherBody.Entity.TryGetComponent(out IDamageableComponent damage) && _soundHitSpecies != null)
|
||||
// This is so entities that shouldn't get a collision are ignored.
|
||||
if (entity.TryGetComponent(out IPhysicsComponent otherPhysics) && otherPhysics.Hard == false)
|
||||
{
|
||||
EntitySystem.Get<AudioSystem>().PlayAtCoords(_soundHitSpecies, otherBody.Entity.Transform.Coordinates);
|
||||
_internalDeleteOnCollide = false;
|
||||
return;
|
||||
}
|
||||
else if (_soundHit != null)
|
||||
else
|
||||
{
|
||||
EntitySystem.Get<AudioSystem>().PlayAtCoords(_soundHit, otherBody.Entity.Transform.Coordinates);
|
||||
_internalDeleteOnCollide = true;
|
||||
}
|
||||
|
||||
if (damage != null)
|
||||
if (_soundHitSpecies != null && entity.HasComponent<IDamageableComponent>())
|
||||
{
|
||||
EntitySystem.Get<AudioSystem>().PlayAtCoords(_soundHitSpecies, entity.Transform.Coordinates);
|
||||
} else if (_soundHit != null)
|
||||
{
|
||||
EntitySystem.Get<AudioSystem>().PlayAtCoords(_soundHit, entity.Transform.Coordinates);
|
||||
}
|
||||
|
||||
if (entity.TryGetComponent(out IDamageableComponent damage))
|
||||
{
|
||||
Owner.EntityManager.TryGetEntity(_shooter, out var shooter);
|
||||
|
||||
@@ -90,17 +102,17 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
_damagedEntity = true;
|
||||
}
|
||||
|
||||
// Damaging it can delete it
|
||||
if (!otherBody.Entity.Deleted && otherBody.Entity.TryGetComponent(out CameraRecoilComponent recoilComponent))
|
||||
if (!entity.Deleted && entity.TryGetComponent(out CameraRecoilComponent recoilComponent)
|
||||
&& Owner.TryGetComponent(out IPhysicsComponent ownPhysics))
|
||||
{
|
||||
var direction = ourBody.LinearVelocity.Normalized;
|
||||
var direction = ownPhysics.LinearVelocity.Normalized;
|
||||
recoilComponent.Kick(direction);
|
||||
}
|
||||
}
|
||||
|
||||
void IPostCollide.PostCollide(IPhysBody ourBody, IPhysBody otherBody)
|
||||
void ICollideBehavior.PostCollide(int collideCount)
|
||||
{
|
||||
if (_damagedEntity) Owner.Delete();
|
||||
if (collideCount > 0 && DeleteOnCollide && _internalDeleteOnCollide) Owner.Delete();
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState(ICommonSession player)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Projectiles
|
||||
@@ -33,14 +32,16 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
Owner.EnsureComponentWarn(out ProjectileComponent _);
|
||||
}
|
||||
|
||||
void ICollideBehavior.CollideWith(IPhysBody ourBody, IPhysBody otherBody)
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
{
|
||||
if (otherBody.Entity.TryGetComponent(out StunnableComponent stunnableComponent))
|
||||
if (entity.TryGetComponent(out StunnableComponent stunnableComponent))
|
||||
{
|
||||
stunnableComponent.Stun(_stunAmount);
|
||||
stunnableComponent.Knockdown(_knockdownAmount);
|
||||
stunnableComponent.Slowdown(_slowdownAmount);
|
||||
}
|
||||
}
|
||||
|
||||
void ICollideBehavior.PostCollide(int collidedCount) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
using Content.Server.GameObjects.EntitySystems.Click;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Projectiles
|
||||
{
|
||||
[RegisterComponent]
|
||||
internal class ThrownItemComponent : ProjectileComponent, ICollideBehavior
|
||||
{
|
||||
public const float DefaultThrowTime = 0.25f;
|
||||
|
||||
private bool _shouldCollide = true;
|
||||
private bool _shouldStop = false;
|
||||
|
||||
public override string Name => "ThrownItem";
|
||||
public override uint? NetID => ContentNetIDs.THROWN_ITEM;
|
||||
|
||||
/// <summary>
|
||||
/// User who threw the item.
|
||||
/// </summary>
|
||||
public IEntity User { get; set; }
|
||||
|
||||
void ICollideBehavior.CollideWith(IEntity entity)
|
||||
{
|
||||
if (!_shouldCollide || entity.Deleted) return;
|
||||
if (entity.TryGetComponent(out PhysicsComponent collid))
|
||||
{
|
||||
if (!collid.Hard) // ignore non hard
|
||||
return;
|
||||
|
||||
_shouldStop = true; // hit something hard => stop after this collision
|
||||
|
||||
// Raise an event.
|
||||
EntitySystem.Get<InteractionSystem>().ThrowCollideInteraction(User, Owner, entity, Owner.Transform.Coordinates);
|
||||
}
|
||||
|
||||
// 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 (!Owner.Deleted && Owner.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1)
|
||||
{
|
||||
_shouldCollide = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void StopThrow()
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Owner.TryGetComponent(out IPhysicsComponent body) && body.PhysicsShapes.Count >= 1)
|
||||
{
|
||||
body.PhysicsShapes[0].CollisionMask &= (int) ~CollisionGroup.ThrownItem;
|
||||
|
||||
if (body.TryGetController(out ThrownController controller))
|
||||
{
|
||||
controller.LinearVelocity = Vector2.Zero;
|
||||
}
|
||||
|
||||
body.Status = BodyStatus.OnGround;
|
||||
|
||||
Owner.RemoveComponent<ThrownItemComponent>();
|
||||
EntitySystem.Get<InteractionSystem>().LandInteraction(User, Owner, Owner.Transform.Coordinates);
|
||||
}
|
||||
}
|
||||
|
||||
void ICollideBehavior.PostCollide(int collideCount)
|
||||
{
|
||||
if (_shouldStop && collideCount > 0)
|
||||
{
|
||||
StopThrow();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartThrow(Vector2 direction, float speed)
|
||||
{
|
||||
var comp = Owner.GetComponent<IPhysicsComponent>();
|
||||
comp.Status = BodyStatus.InAir;
|
||||
|
||||
var controller = comp.EnsureController<ThrownController>();
|
||||
controller.Push(direction, speed);
|
||||
|
||||
EntitySystem.Get<AudioSystem>()
|
||||
.PlayFromEntity("/Audio/Effects/toss.ogg", Owner);
|
||||
|
||||
StartStopTimer();
|
||||
}
|
||||
|
||||
private void StartStopTimer()
|
||||
{
|
||||
Owner.SpawnTimer((int) (DefaultThrowTime * 1000), MaybeStopThrow);
|
||||
}
|
||||
|
||||
private void MaybeStopThrow()
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IoCManager.Resolve<IPhysicsManager>().IsWeightless(Owner.Transform.Coordinates))
|
||||
{
|
||||
StartStopTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
StopThrow();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user