using Content.Shared.Camera;
using Content.Shared.CCVar;
using Content.Shared.Construction.Components;
+using Content.Shared.Construction.EntitySystems;
using Content.Shared.Database;
using Content.Shared.Friction;
using Content.Shared.Projectiles;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Physics.Systems;
+using Robust.Shared.Serialization;
using Robust.Shared.Timing;
namespace Content.Shared.Throwing;
[Dependency] private readonly SharedCameraRecoilSystem _recoil = default!;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
[Dependency] private readonly IConfigurationManager _configManager = default!;
+ [Dependency] private readonly AnchorableSystem _anchorable = default!;
+
+ private EntityQuery<AnchorableComponent> _anchorableQuery;
public override void Initialize()
{
base.Initialize();
+ _anchorableQuery = GetEntityQuery<AnchorableComponent>();
+
Subs.CVar(_configManager, CCVars.TileFrictionModifier, value => _frictionModifier = value, true);
Subs.CVar(_configManager, CCVars.AirFriction, value => _airDamping = value, true);
}
bool animated = true,
bool playSound = true,
bool doSpin = true,
- bool unanchor = false)
+ ThrowingUnanchorStrength unanchor = ThrowingUnanchorStrength.None)
{
var thrownPos = _transform.GetMapCoordinates(uid);
var mapPos = _transform.ToMapCoordinates(coordinates);
/// <param name="friction">friction value used for the distance calculation. If set to null this defaults to the standard tile values</param>
/// <param name="compensateFriction">True will adjust the throw so the item stops at the target coordinates. False means it will land at the target and keep sliding.</param>
/// <param name="doSpin">Whether spin will be applied to the thrown entity.</param>
- /// <param name="unanchor">If true and the thrown entity has <see cref="AnchorableComponent"/>, unanchor the thrown entity</param>
+ /// <param name="unanchor">If set to Unanchorable, if the entity has <see cref="AnchorableComponent"/> and is unanchorable, it will unanchor the thrown entity. If set to All, it will unanchor the entity regardless.</param>
public void TryThrow(EntityUid uid,
Vector2 direction,
float baseThrowSpeed = 10.0f,
bool animated = true,
bool playSound = true,
bool doSpin = true,
- bool unanchor = false)
+ ThrowingUnanchorStrength unanchor = ThrowingUnanchorStrength.None)
{
var physicsQuery = GetEntityQuery<PhysicsComponent>();
if (!physicsQuery.TryGetComponent(uid, out var physics))
/// <param name="friction">friction value used for the distance calculation. If set to null this defaults to the standard tile values</param>
/// <param name="compensateFriction">True will adjust the throw so the item stops at the target coordinates. False means it will land at the target and keep sliding.</param>
/// <param name="doSpin">Whether spin will be applied to the thrown entity.</param>
- /// <param name="unanchor">If true and the thrown entity has <see cref="AnchorableComponent"/>, unanchor the thrown entity</param>
+ /// <param name="unanchor">If set to Unanchorable, if the entity has <see cref="AnchorableComponent"/> and is unanchorable, it will unanchor the thrown entity. If set to All, it will unanchor the entity regardless.</param>
public void TryThrow(EntityUid uid,
Vector2 direction,
PhysicsComponent physics,
bool animated = true,
bool playSound = true,
bool doSpin = true,
- bool unanchor = false)
+ ThrowingUnanchorStrength unanchor = ThrowingUnanchorStrength.None)
{
if (baseThrowSpeed <= 0 || direction == Vector2Helpers.Infinity || direction == Vector2Helpers.NaN || direction == Vector2.Zero || friction < 0)
return;
- if (unanchor && HasComp<AnchorableComponent>(uid))
+ // Unanchor the entity if applicable
+ if (unanchor == ThrowingUnanchorStrength.All ||
+ unanchor == ThrowingUnanchorStrength.Unanchorable &&
+ _anchorableQuery.TryComp(uid, out var anchorableComponent) &&
+ (anchorableComponent.Flags & AnchorableFlags.Unanchorable) != 0)
_transform.Unanchor(uid);
if ((physics.BodyType & (BodyType.Dynamic | BodyType.KinematicController)) == 0x0)
if (pushEv.Push)
_physics.ApplyLinearImpulse(user.Value, -impulseVector / physics.Mass * pushbackRatio * MathF.Min(massLimit, physics.Mass), body: userPhysics);
}
+
+
+}
+
+/// <summary>
+/// If a throwing action should attempt to unanchor anchored entities.
+/// </summary>
+[Serializable, NetSerializable]
+public enum ThrowingUnanchorStrength : byte
+{
+ /// <summary>
+ /// No entites will be unanchored.
+ /// </summary>
+ None,
+ /// <summary>
+ /// Only entities that can be unanchored (e.g. via wrench) will be unanchored.
+ /// </summary>
+ Unanchorable,
+ /// <summary>
+ /// All entities will be unanchored.
+ /// </summary>
+ All,
}