* Revert "Make handheld explosives affect tiles (#2806)"
This reverts commit 005e142949.
* Fixes tiles being destroyed under walls by an explosion
* Extra imports removed
* Handles explosion in space and different grids
This handle explosions across different grids, and tiles are still protected if there is an entity airtight and currently blocking air on top of them that survived the explosion.
* Some bug fixes
- The way tiles were being protected was silly.
- Big explosions cause a lot of objects to trigger multiple events and at the same time they are destroyed.
- Explosions spawning inside containers like closets work now.
* Range bug fixes
* Explosive
The explosion works even if the entity exploding is inside multiple 'layers' of containers like.
bomb -> survival box -> tool box -> closet
* Explosions are different now
Explosion can't jump over walls now.
Explosions work like rays now, if an explosion breaks a wall it can scatter inside the room.
If entities are behind impassable entities that survive the blast they are left unscathed.
* Little fix
* Remove the extra lookup of tiles
* Another small change
* Restore the second lookup
I thought this was extra, but this protects the tile under it if there is an Impassable entity on top. None wants anchored girders on top of lattice/space
* Changing order of conditions
IsBlockedTurf is cheaper to run than InRangeUnobstructed.
* Yep
130 lines
4.2 KiB
C#
130 lines
4.2 KiB
C#
using Content.Server.GameObjects.EntitySystems.Click;
|
|
using Content.Shared.Damage;
|
|
using Content.Shared.GameObjects;
|
|
using Content.Shared.GameObjects.Components.Damage;
|
|
using Content.Shared.Physics;
|
|
using Robust.Server.GameObjects.EntitySystems;
|
|
using Robust.Shared.GameObjects;
|
|
using Robust.Shared.GameObjects.Components;
|
|
using Robust.Shared.GameObjects.Components.Timers;
|
|
using Robust.Shared.GameObjects.Systems;
|
|
using Robust.Shared.Interfaces.GameObjects;
|
|
using Robust.Shared.Interfaces.Physics;
|
|
using Robust.Shared.IoC;
|
|
using Robust.Shared.Maths;
|
|
using Robust.Shared.Timers;
|
|
|
|
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);
|
|
}
|
|
if (entity.TryGetComponent(out IDamageableComponent damage))
|
|
{
|
|
damage.ChangeDamage(DamageType.Blunt, 10, false, Owner);
|
|
}
|
|
|
|
// 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.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();
|
|
}
|
|
}
|
|
}
|