Fix throwing.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
using Content.Shared.GameObjects.Components.Projectiles;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Projectiles
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class ProjectileComponent : SharedProjectileComponent
|
||||
{
|
||||
protected override EntityUid Shooter => _shooter;
|
||||
private EntityUid _shooter;
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
if (curState is ProjectileComponentState compState)
|
||||
{
|
||||
_shooter = compState.Shooter;
|
||||
IgnoreShooter = compState.IgnoreShooter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Content.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.GameObjects.Components.Projectiles
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class ThrownItemComponent : ProjectileComponent
|
||||
{
|
||||
public override string Name => "ThrownItem";
|
||||
public override uint? NetID => ContentNetIDs.THROWN_ITEM;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,6 @@
|
||||
"Multitool",
|
||||
"Wrench",
|
||||
"Crowbar",
|
||||
"Projectile",
|
||||
"MeleeWeapon",
|
||||
"Storeable",
|
||||
"Dice",
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.GameObjects.Components.Mobs;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.GameObjects.Components.Projectiles;
|
||||
using Robust.Server.GameObjects.EntitySystems;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.GameObjects.Components.Projectiles
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class ProjectileComponent : Component, ICollideSpecial, ICollideBehavior
|
||||
public class ProjectileComponent : SharedProjectileComponent, ICollideBehavior
|
||||
{
|
||||
public override string Name => "Projectile";
|
||||
|
||||
public bool IgnoreShooter = true;
|
||||
protected override EntityUid Shooter => _shooter;
|
||||
|
||||
private EntityUid _shooter = EntityUid.Invalid;
|
||||
|
||||
@@ -56,18 +54,7 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
public void IgnoreEntity(IEntity shooter)
|
||||
{
|
||||
_shooter = shooter.Uid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Special collision override, can be used to give custom behaviors deciding when to collide
|
||||
/// </summary>
|
||||
/// <param name="collidedwith"></param>
|
||||
/// <returns></returns>
|
||||
bool ICollideSpecial.PreventCollide(IPhysBody collidedwith)
|
||||
{
|
||||
if (IgnoreShooter && collidedwith.Owner.Uid == _shooter)
|
||||
return true;
|
||||
return false;
|
||||
Dirty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -106,5 +93,10 @@ namespace Content.Server.GameObjects.Components.Projectiles
|
||||
{
|
||||
if (collideCount > 0 && DeleteOnCollide) Owner.Delete();
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState()
|
||||
{
|
||||
return new ProjectileComponentState(NetID!.Value, _shooter, IgnoreShooter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.GameObjects.Components.Projectiles;
|
||||
using Content.Server.GameObjects.Components.Projectiles;
|
||||
using Content.Server.GameObjects.EntitySystems;
|
||||
using Content.Shared.GameObjects;
|
||||
using Content.Shared.Physics;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
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
|
||||
{
|
||||
[RegisterComponent]
|
||||
internal class ThrownItemComponent : ProjectileComponent, ICollideBehavior
|
||||
{
|
||||
#pragma warning disable 649
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager;
|
||||
#pragma warning restore 649
|
||||
public const float DefaultThrowTime = 0.25f;
|
||||
|
||||
private bool _shouldCollide = true;
|
||||
|
||||
public override string Name => "ThrownItem";
|
||||
public override uint? NetID => ContentNetIDs.THROWN_ITEM;
|
||||
|
||||
/// <summary>
|
||||
/// User who threw the item.
|
||||
@@ -34,6 +35,7 @@ namespace Content.Server.GameObjects.Components
|
||||
{
|
||||
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.
|
||||
@@ -44,20 +46,56 @@ namespace Content.Server.GameObjects.Components
|
||||
}
|
||||
}
|
||||
|
||||
public void PostCollide(int collideCount)
|
||||
private void StopThrow()
|
||||
{
|
||||
|
||||
if (collideCount > 0 && Owner.TryGetComponent(out CollidableComponent body) && body.PhysicsShapes.Count >= 1)
|
||||
if (Owner.TryGetComponent(out CollidableComponent body) && body.PhysicsShapes.Count >= 1)
|
||||
{
|
||||
body.PhysicsShapes[0].CollisionMask &= (int)~CollisionGroup.MobImpassable;
|
||||
body.PhysicsShapes[0].CollisionMask &= (int) ~CollisionGroup.ThrownItem;
|
||||
|
||||
// KYS, your job is finished. Trigger ILand as well.
|
||||
var physics = Owner.GetComponent<PhysicsComponent>();
|
||||
(physics.Controller as ThrowController).StopThrow();
|
||||
physics.RemoveController();
|
||||
physics.LinearVelocity = Vector2.Zero;
|
||||
physics.Status = BodyStatus.OnGround;
|
||||
body.Status = BodyStatus.OnGround;
|
||||
Owner.RemoveComponent<ThrownItemComponent>();
|
||||
_entitySystemManager.GetEntitySystem<InteractionSystem>().LandInteraction(User, Owner, Owner.Transform.GridPosition);
|
||||
EntitySystem.Get<InteractionSystem>().LandInteraction(User, Owner, Owner.Transform.GridPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void ICollideBehavior.PostCollide(int collideCount)
|
||||
{
|
||||
if (collideCount > 0)
|
||||
{
|
||||
StopThrow();
|
||||
}
|
||||
}
|
||||
|
||||
public void StartThrow(Vector2 initialImpulse)
|
||||
{
|
||||
var comp = Owner.GetComponent<PhysicsComponent>();
|
||||
comp.Status = BodyStatus.InAir;
|
||||
comp.Momentum = initialImpulse;
|
||||
StartStopTimer();
|
||||
}
|
||||
|
||||
private void StartStopTimer()
|
||||
{
|
||||
Timer.Spawn((int) (DefaultThrowTime * 1000), MaybeStopThrow);
|
||||
}
|
||||
|
||||
private void MaybeStopThrow()
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IoCManager.Resolve<IPhysicsManager>().IsWeightless(Owner.Transform.GridPosition))
|
||||
{
|
||||
StartStopTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
StopThrow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Content.Server.Throw
|
||||
if (colComp.PhysicsShapes.Count == 0)
|
||||
colComp.PhysicsShapes.Add(new PhysShapeAabb());
|
||||
|
||||
colComp.PhysicsShapes[0].CollisionMask |= (int) (CollisionGroup.MobImpassable | CollisionGroup.Impassable);
|
||||
colComp.PhysicsShapes[0].CollisionMask |= (int) CollisionGroup.ThrownItem;
|
||||
colComp.Status = BodyStatus.InAir;
|
||||
}
|
||||
var angle = new Angle(targetLoc.ToMapPos(mapManager) - sourceLoc.ToMapPos(mapManager));
|
||||
@@ -83,8 +83,7 @@ namespace Content.Server.Throw
|
||||
// scaling is handled elsewhere, this is just multiplying by 60 independent of timing as a fix until elsewhere values are updated
|
||||
var spd = throwForce * 60;
|
||||
|
||||
physComp.SetController<ThrowController>();
|
||||
(physComp.Controller as ThrowController)?.StartThrow(angle.ToVec() * spd);
|
||||
projComp.StartThrow(angle.ToVec() * spd);
|
||||
|
||||
if (throwSourceEnt != null && throwSourceEnt.TryGetComponent<PhysicsComponent>(out var physics)
|
||||
&& physics.Controller is MoverController mover)
|
||||
@@ -135,7 +134,7 @@ namespace Content.Server.Throw
|
||||
|
||||
// Calculate the force necessary to land a throw based on throw duration, mass and distance.
|
||||
var distance = (targetLoc.ToMapPos(mapManager) - sourceLoc.ToMapPos(mapManager)).Length;
|
||||
var throwDuration = ThrowController.DefaultThrowTime;
|
||||
var throwDuration = ThrownItemComponent.DefaultThrowTime;
|
||||
var mass = 1f;
|
||||
if (thrownEnt.TryGetComponent(out PhysicsComponent physicsComponent))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.GameObjects.Components.Projectiles
|
||||
{
|
||||
public abstract class SharedProjectileComponent : Component, ICollideSpecial
|
||||
{
|
||||
private bool _ignoreShooter = true;
|
||||
public override string Name => "Projectile";
|
||||
public override uint? NetID => ContentNetIDs.PROJECTILE;
|
||||
|
||||
protected abstract EntityUid Shooter { get; }
|
||||
|
||||
public bool IgnoreShooter
|
||||
{
|
||||
get => _ignoreShooter;
|
||||
set
|
||||
{
|
||||
_ignoreShooter = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
protected class ProjectileComponentState : ComponentState
|
||||
{
|
||||
public ProjectileComponentState(uint netId, EntityUid shooter, bool ignoreShooter) : base(netId)
|
||||
{
|
||||
Shooter = shooter;
|
||||
IgnoreShooter = ignoreShooter;
|
||||
}
|
||||
|
||||
public EntityUid Shooter { get; }
|
||||
public bool IgnoreShooter { get; }
|
||||
}
|
||||
|
||||
public bool PreventCollide(IPhysBody collidedwith)
|
||||
{
|
||||
return IgnoreShooter && collidedwith.Owner.Uid == Shooter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,6 +56,8 @@
|
||||
public const uint THIRST = 1050;
|
||||
|
||||
public const uint FLASHABLE = 1051;
|
||||
public const uint PROJECTILE = 1052;
|
||||
public const uint THROWN_ITEM = 1053;
|
||||
|
||||
// Net IDs for integration tests.
|
||||
public const uint PREDICTION_TEST = 10001;
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Content.Shared.Physics
|
||||
MapGrid = MapGridHelpers.CollisionGroup, // Map grids, like shuttles. This is the actual grid itself, not the walls or other entities connected to the grid.
|
||||
|
||||
MobMask = Impassable | MobImpassable | VaultImpassable | SmallImpassable,
|
||||
ThrownItem = MobImpassable | Impassable,
|
||||
// 32 possible groups
|
||||
AllMask = -1,
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
using Robust.Shared.GameObjects.Components;
|
||||
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 PhysicsComponent _component;
|
||||
|
||||
public const float DefaultThrowTime = 0.25f;
|
||||
|
||||
public float ThrowTime
|
||||
{
|
||||
get => _throwTime;
|
||||
set => _throwTime = value;
|
||||
}
|
||||
|
||||
public override PhysicsComponent 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 || _component.Owner.Deleted) 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user