Merge branch 'master' into replace-sounds-with-sound-specifier
# Conflicts: # Content.Server/Hands/Components/HandsComponent.cs # Content.Server/Light/Components/ExpendableLightComponent.cs # Content.Shared/Light/Component/SharedExpendableLightComponent.cs
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.Shared.Chemistry.Metabolizable
|
||||
{
|
||||
/// <summary>
|
||||
/// Default metabolism for reagents. Metabolizes the reagent with no effects
|
||||
/// Default metabolization for reagents. Returns the amount of reagents metabolized without applying effects.
|
||||
/// Metabolizes reagents at a constant rate, limited by how much is available. Other classes are derived from
|
||||
/// this class, so that they do not need their own metabolization quantity calculation.
|
||||
/// </summary>
|
||||
[DataDefinition]
|
||||
public class DefaultMetabolizable : IMetabolizable
|
||||
@@ -13,12 +15,22 @@ namespace Content.Shared.Chemistry.Metabolizable
|
||||
/// <summary>
|
||||
/// Rate of metabolism in units / second
|
||||
/// </summary>
|
||||
[DataField("rate")]
|
||||
public double MetabolismRate { get; set; } = 1;
|
||||
[DataField("rate")] public ReagentUnit MetabolismRate { get; set; } = ReagentUnit.New(1);
|
||||
|
||||
ReagentUnit IMetabolizable.Metabolize(IEntity solutionEntity, string reagentId, float tickTime)
|
||||
public virtual ReagentUnit Metabolize(IEntity solutionEntity, string reagentId, float tickTime, ReagentUnit availableReagent)
|
||||
{
|
||||
return ReagentUnit.New(MetabolismRate * tickTime);
|
||||
|
||||
// How much reagent should we metabolize
|
||||
// The default behaviour is to metabolize at a constant rate, independent of the quantity of reagents.
|
||||
var amountMetabolized = MetabolismRate * tickTime;
|
||||
|
||||
// is that much reagent actually available?
|
||||
if (availableReagent < amountMetabolized)
|
||||
{
|
||||
return availableReagent;
|
||||
}
|
||||
|
||||
return amountMetabolized;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.Chemistry.Metabolizable
|
||||
@@ -16,7 +16,8 @@ namespace Content.Shared.Chemistry.Metabolizable
|
||||
/// <param name="solutionEntity">The entity containing the solution.</param>
|
||||
/// <param name="reagentId">The reagent id</param>
|
||||
/// <param name="tickTime">The time since the last metabolism tick in seconds.</param>
|
||||
/// <param name="availableReagent">Reagent available to be metabolized.</param>
|
||||
/// <returns>The amount of reagent to be removed. The metabolizing organ should handle removing the reagent.</returns>
|
||||
ReagentUnit Metabolize(IEntity solutionEntity, string reagentId, float tickTime);
|
||||
ReagentUnit Metabolize(IEntity solutionEntity, string reagentId, float tickTime, ReagentUnit availableReagent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
Ingestion,
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public abstract class ReagentEntityReaction
|
||||
{
|
||||
[ViewVariables]
|
||||
|
||||
50
Content.Shared/Hands/Components/HandVirtualPullComponent.cs
Normal file
50
Content.Shared/Hands/Components/HandVirtualPullComponent.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Hands.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent]
|
||||
public sealed class HandVirtualPullComponent : Component
|
||||
{
|
||||
private EntityUid _pulledEntity;
|
||||
public override string Name => "HandVirtualPull";
|
||||
|
||||
public EntityUid PulledEntity
|
||||
{
|
||||
get => _pulledEntity;
|
||||
set
|
||||
{
|
||||
_pulledEntity = value;
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override ComponentState GetComponentState(ICommonSession player)
|
||||
{
|
||||
return new VirtualPullComponentState(_pulledEntity);
|
||||
}
|
||||
|
||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
||||
{
|
||||
if (curState is not VirtualPullComponentState pullState)
|
||||
return;
|
||||
|
||||
_pulledEntity = pullState.PulledEntity;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class VirtualPullComponentState : ComponentState
|
||||
{
|
||||
public readonly EntityUid PulledEntity;
|
||||
|
||||
public VirtualPullComponentState(EntityUid pulledEntity)
|
||||
{
|
||||
PulledEntity = pulledEntity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,11 +55,11 @@ namespace Content.Shared.Hands.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string? _activeHand;
|
||||
|
||||
[ViewVariables]
|
||||
public IReadOnlyList<IReadOnlyHand> ReadOnlyHands => Hands;
|
||||
protected readonly List<Hand> Hands = new();
|
||||
public readonly List<Hand> Hands = new();
|
||||
|
||||
/// <summary>
|
||||
/// The amount of throw impulse per distance the player is from the throw target.
|
||||
@@ -89,7 +89,10 @@ namespace Content.Shared.Hands.Components
|
||||
|
||||
public virtual void HandsModified()
|
||||
{
|
||||
// todo axe all this for ECS.
|
||||
Dirty();
|
||||
|
||||
Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, new HandsModifiedMessage { Hands = this });
|
||||
}
|
||||
|
||||
public void AddHand(string handName, HandLocation handLocation)
|
||||
@@ -100,7 +103,7 @@ namespace Content.Shared.Hands.Components
|
||||
var container = ContainerHelpers.CreateContainer<ContainerSlot>(Owner, handName);
|
||||
container.OccludesLight = false;
|
||||
|
||||
Hands.Add(new Hand(handName, true, handLocation, container));
|
||||
Hands.Add(new Hand(handName, handLocation, container));
|
||||
|
||||
if (ActiveHand == null)
|
||||
ActiveHand = handName;
|
||||
@@ -125,48 +128,55 @@ namespace Content.Shared.Hands.Components
|
||||
Hands.Remove(hand);
|
||||
|
||||
if (ActiveHand == hand.Name)
|
||||
ActiveHand = ReadOnlyHands.FirstOrDefault()?.Name;
|
||||
ActiveHand = Hands.FirstOrDefault()?.Name;
|
||||
|
||||
HandCountChanged();
|
||||
|
||||
HandsModified();
|
||||
}
|
||||
|
||||
public bool HasHand(string handName)
|
||||
{
|
||||
foreach (var hand in Hands)
|
||||
{
|
||||
if (hand.Name == handName)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Hand? GetHand(string handName)
|
||||
{
|
||||
foreach (var hand in Hands)
|
||||
{
|
||||
if (hand.Name == handName)
|
||||
return hand;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Hand? GetActiveHand()
|
||||
{
|
||||
if (ActiveHand == null)
|
||||
return null;
|
||||
|
||||
return GetHand(ActiveHand);
|
||||
return GetHandOrNull(ActiveHand);
|
||||
}
|
||||
|
||||
protected bool TryGetHand(string handName, [NotNullWhen(true)] out Hand? foundHand)
|
||||
public bool HasHand(string handName)
|
||||
{
|
||||
foundHand = GetHand(handName);
|
||||
return foundHand != null;
|
||||
return TryGetHand(handName, out _);
|
||||
}
|
||||
|
||||
protected bool TryGetActiveHand([NotNullWhen(true)] out Hand? activeHand)
|
||||
public Hand? GetHandOrNull(string handName)
|
||||
{
|
||||
return TryGetHand(handName, out var hand) ? hand : null;
|
||||
}
|
||||
|
||||
public Hand GetHand(string handName)
|
||||
{
|
||||
if (!TryGetHand(handName, out var hand))
|
||||
throw new KeyNotFoundException($"Unable to find hand with name {handName}");
|
||||
|
||||
return hand;
|
||||
}
|
||||
|
||||
public bool TryGetHand(string handName, [NotNullWhen(true)] out Hand? foundHand)
|
||||
{
|
||||
foreach (var hand in Hands)
|
||||
{
|
||||
if (hand.Name == handName)
|
||||
{
|
||||
foundHand = hand;
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
foundHand = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetActiveHand([NotNullWhen(true)] out Hand? activeHand)
|
||||
{
|
||||
activeHand = GetActiveHand();
|
||||
return activeHand != null;
|
||||
@@ -211,7 +221,7 @@ namespace Content.Shared.Hands.Components
|
||||
|
||||
public IEnumerable<IEntity> GetAllHeldEntities()
|
||||
{
|
||||
foreach (var hand in ReadOnlyHands)
|
||||
foreach (var hand in Hands)
|
||||
{
|
||||
if (hand.HeldEntity != null)
|
||||
yield return hand.HeldEntity;
|
||||
@@ -416,7 +426,7 @@ namespace Content.Shared.Hands.Components
|
||||
/// <summary>
|
||||
/// Drops a hands contents to the target location.
|
||||
/// </summary>
|
||||
private void DropHeldEntity(Hand hand, EntityCoordinates targetDropLocation, bool intentionalDrop = true)
|
||||
public void DropHeldEntity(Hand hand, EntityCoordinates targetDropLocation, bool intentionalDrop = true)
|
||||
{
|
||||
var heldEntity = hand.HeldEntity;
|
||||
|
||||
@@ -538,16 +548,7 @@ namespace Content.Shared.Hands.Components
|
||||
|
||||
public bool CanPickupEntityToActiveHand(IEntity entity, bool checkActionBlocker = true)
|
||||
{
|
||||
if (!TryGetActiveHand(out var hand))
|
||||
return false;
|
||||
|
||||
if (checkActionBlocker && !PlayerCanPickup())
|
||||
return false;
|
||||
|
||||
if (!CanInsertEntityIntoHand(hand, entity))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return ActiveHand != null && CanPickupEntity(ActiveHand, entity, checkActionBlocker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -563,10 +564,7 @@ namespace Content.Shared.Hands.Components
|
||||
|
||||
public bool TryPickupEntityToActiveHand(IEntity entity, bool checkActionBlocker = true)
|
||||
{
|
||||
if (!TryGetActiveHand(out var hand))
|
||||
return false;
|
||||
|
||||
return TryPickupEntity(hand, entity, checkActionBlocker);
|
||||
return ActiveHand != null && TryPickupEntity(ActiveHand, entity, checkActionBlocker);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -574,9 +572,6 @@ namespace Content.Shared.Hands.Components
|
||||
/// </summary>
|
||||
protected bool CanInsertEntityIntoHand(Hand hand, IEntity entity)
|
||||
{
|
||||
if (!hand.Enabled)
|
||||
return false;
|
||||
|
||||
var handContainer = hand.Container;
|
||||
if (handContainer == null)
|
||||
return false;
|
||||
@@ -602,7 +597,7 @@ namespace Content.Shared.Hands.Components
|
||||
/// <summary>
|
||||
/// Puts an entity into the player's hand, assumes that the insertion is allowed.
|
||||
/// </summary>
|
||||
private void PutEntityIntoHand(Hand hand, IEntity entity)
|
||||
public void PutEntityIntoHand(Hand hand, IEntity entity)
|
||||
{
|
||||
var handContainer = hand.Container;
|
||||
if (handContainer == null)
|
||||
@@ -658,7 +653,7 @@ namespace Content.Shared.Hands.Components
|
||||
if (newActiveIndex > finalHandIndex)
|
||||
newActiveIndex = 0;
|
||||
|
||||
nextHand = ReadOnlyHands[newActiveIndex].Name;
|
||||
nextHand = Hands[newActiveIndex].Name;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -752,7 +747,7 @@ namespace Content.Shared.Hands.Components
|
||||
Hand? priorityHand = null;
|
||||
|
||||
if (priorityHandName != null)
|
||||
priorityHand = GetHand(priorityHandName);
|
||||
priorityHand = GetHandOrNull(priorityHandName);
|
||||
|
||||
return TryPutInAnyHand(entity, priorityHand, checkActionBlocker);
|
||||
}
|
||||
@@ -793,43 +788,16 @@ namespace Content.Shared.Hands.Components
|
||||
protected virtual void DoActivate(IEntity heldEntity) { }
|
||||
|
||||
protected virtual void HandlePickupAnimation(IEntity entity) { }
|
||||
|
||||
protected void EnableHand(Hand hand)
|
||||
{
|
||||
hand.Enabled = true;
|
||||
Dirty();
|
||||
}
|
||||
|
||||
protected void DisableHand(Hand hand)
|
||||
{
|
||||
hand.Enabled = false;
|
||||
DropHeldEntityToFloor(hand, intentionalDrop: false);
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
public interface IReadOnlyHand
|
||||
public class Hand
|
||||
{
|
||||
[ViewVariables]
|
||||
public string Name { get; }
|
||||
|
||||
public bool Enabled { get; }
|
||||
|
||||
[ViewVariables]
|
||||
public HandLocation Location { get; }
|
||||
|
||||
public abstract IEntity? HeldEntity { get; }
|
||||
}
|
||||
|
||||
public class Hand : IReadOnlyHand
|
||||
{
|
||||
[ViewVariables]
|
||||
public string Name { get; set; }
|
||||
|
||||
[ViewVariables]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[ViewVariables]
|
||||
public HandLocation Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The container used to hold the contents of this hand. Nullable because the client must get the containers via <see cref="ContainerManagerComponent"/>,
|
||||
/// which may not be synced with the server when the client hands are created.
|
||||
@@ -840,37 +808,36 @@ namespace Content.Shared.Hands.Components
|
||||
[ViewVariables]
|
||||
public IEntity? HeldEntity => Container?.ContainedEntities?.FirstOrDefault();
|
||||
|
||||
public Hand(string name, bool enabled, HandLocation location, IContainer? container = null)
|
||||
public bool IsEmpty => HeldEntity == null;
|
||||
|
||||
public Hand(string name, HandLocation location, IContainer? container = null)
|
||||
{
|
||||
Name = name;
|
||||
Enabled = enabled;
|
||||
Location = location;
|
||||
Container = container;
|
||||
}
|
||||
|
||||
public HandState ToHandState()
|
||||
{
|
||||
return new(Name, Location, Enabled);
|
||||
return new(Name, Location);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class HandState
|
||||
public struct HandState
|
||||
{
|
||||
public string Name { get; }
|
||||
public HandLocation Location { get; }
|
||||
public bool Enabled { get; }
|
||||
|
||||
public HandState(string name, HandLocation location, bool enabled)
|
||||
public HandState(string name, HandLocation location)
|
||||
{
|
||||
Name = name;
|
||||
Location = location;
|
||||
Enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class HandsComponentState : ComponentState
|
||||
public sealed class HandsComponentState : ComponentState
|
||||
{
|
||||
public HandState[] Hands { get; }
|
||||
public string? ActiveHand { get; }
|
||||
@@ -886,25 +853,20 @@ namespace Content.Shared.Hands.Components
|
||||
/// A message that calls the use interaction on an item in hand, presumed for now the interaction will occur only on the active hand.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public class UseInHandMsg : ComponentMessage
|
||||
public sealed class UseInHandMsg : EntityEventArgs
|
||||
{
|
||||
public UseInHandMsg()
|
||||
{
|
||||
Directed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A message that calls the activate interaction on the item in the specified hand.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public class ActivateInHandMsg : ComponentMessage
|
||||
public class ActivateInHandMsg : EntityEventArgs
|
||||
{
|
||||
public string HandName { get; }
|
||||
|
||||
public ActivateInHandMsg(string handName)
|
||||
{
|
||||
Directed = true;
|
||||
HandName = handName;
|
||||
}
|
||||
}
|
||||
@@ -913,13 +875,12 @@ namespace Content.Shared.Hands.Components
|
||||
/// Uses the item in the active hand on the item in the specified hand.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public class ClientAttackByInHandMsg : ComponentMessage
|
||||
public class ClientInteractUsingInHandMsg : EntityEventArgs
|
||||
{
|
||||
public string HandName { get; }
|
||||
|
||||
public ClientAttackByInHandMsg(string handName)
|
||||
public ClientInteractUsingInHandMsg(string handName)
|
||||
{
|
||||
Directed = true;
|
||||
HandName = handName;
|
||||
}
|
||||
}
|
||||
@@ -928,28 +889,12 @@ namespace Content.Shared.Hands.Components
|
||||
/// Moves an item from one hand to the active hand.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public class MoveItemFromHandMsg : ComponentMessage
|
||||
public class MoveItemFromHandMsg : EntityEventArgs
|
||||
{
|
||||
public string HandName { get; }
|
||||
|
||||
public MoveItemFromHandMsg(string handName)
|
||||
{
|
||||
Directed = true;
|
||||
HandName = handName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the player's active hand to a specified hand.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public class ClientChangedHandMsg : ComponentMessage
|
||||
{
|
||||
public string HandName { get; }
|
||||
|
||||
public ClientChangedHandMsg(string handName)
|
||||
{
|
||||
Directed = true;
|
||||
HandName = handName;
|
||||
}
|
||||
}
|
||||
@@ -975,7 +920,7 @@ namespace Content.Shared.Hands.Components
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class PickupAnimationMessage : ComponentMessage
|
||||
public class PickupAnimationMessage : EntityEventArgs
|
||||
{
|
||||
public EntityUid EntityUid { get; }
|
||||
public EntityCoordinates InitialPosition { get; }
|
||||
@@ -983,10 +928,15 @@ namespace Content.Shared.Hands.Components
|
||||
|
||||
public PickupAnimationMessage(EntityUid entityUid, Vector2 pickupDirection, EntityCoordinates initialPosition)
|
||||
{
|
||||
Directed = true;
|
||||
EntityUid = entityUid;
|
||||
PickupDirection = pickupDirection;
|
||||
InitialPosition = initialPosition;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public struct HandsModifiedMessage
|
||||
{
|
||||
public SharedHandsComponent Hands;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Content.Shared.Hands.Components;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization;
|
||||
using System;
|
||||
|
||||
@@ -16,11 +15,7 @@ namespace Content.Shared.Hands
|
||||
SubscribeLocalEvent<SharedHandsComponent, EntRemovedFromContainerMessage>(HandleContainerModified);
|
||||
SubscribeLocalEvent<SharedHandsComponent, EntInsertedIntoContainerMessage>(HandleContainerModified);
|
||||
|
||||
SubscribeLocalEvent<RequestSetHandEvent>(HandleSetHand);
|
||||
SubscribeNetworkEvent<RequestSetHandEvent>(HandleSetHand);
|
||||
|
||||
SubscribeLocalEvent<RequestDropHeldEntityEvent>(HandleDrop);
|
||||
SubscribeNetworkEvent<RequestDropHeldEntityEvent>(HandleDrop);
|
||||
SubscribeAllEvent<RequestSetHandEvent>(HandleSetHand);
|
||||
}
|
||||
|
||||
public void DropHandItems(IEntity entity, bool doMobChecks = true)
|
||||
@@ -38,14 +33,16 @@ namespace Content.Shared.Hands
|
||||
|
||||
eventBus.RaiseLocalEvent(uid, msg);
|
||||
|
||||
if (msg.Cancelled) return;
|
||||
if (msg.Cancelled)
|
||||
return;
|
||||
|
||||
if (entity.TryGetContainerMan(out var containerManager))
|
||||
{
|
||||
var parentMsg = new ContainedEntityDropHandItemsAttemptEvent(uid);
|
||||
eventBus.RaiseLocalEvent(containerManager.Owner.Uid, parentMsg);
|
||||
|
||||
if (parentMsg.Cancelled) return;
|
||||
if (parentMsg.Cancelled)
|
||||
return;
|
||||
}
|
||||
|
||||
DropAllItemsInHands(entity, doMobChecks);
|
||||
@@ -55,9 +52,9 @@ namespace Content.Shared.Hands
|
||||
{
|
||||
}
|
||||
|
||||
private void HandleSetHand(RequestSetHandEvent msg, EntitySessionEventArgs eventArgs)
|
||||
private static void HandleSetHand(RequestSetHandEvent msg, EntitySessionEventArgs eventArgs)
|
||||
{
|
||||
var entity = eventArgs.SenderSession?.AttachedEntity;
|
||||
var entity = eventArgs.SenderSession.AttachedEntity;
|
||||
|
||||
if (entity == null || !entity.TryGetComponent(out SharedHandsComponent? hands))
|
||||
return;
|
||||
@@ -65,17 +62,13 @@ namespace Content.Shared.Hands
|
||||
hands.ActiveHand = msg.HandName;
|
||||
}
|
||||
|
||||
private void HandleDrop(RequestDropHeldEntityEvent msg, EntitySessionEventArgs eventArgs)
|
||||
protected virtual void HandleContainerModified(
|
||||
EntityUid uid,
|
||||
SharedHandsComponent component,
|
||||
ContainerModifiedMessage args)
|
||||
{
|
||||
var entity = eventArgs.SenderSession?.AttachedEntity;
|
||||
|
||||
if (entity == null || !entity.TryGetComponent(out SharedHandsComponent? hands))
|
||||
return;
|
||||
|
||||
hands.TryDropHand(msg.HandName, msg.DropTarget);
|
||||
component.Dirty();
|
||||
}
|
||||
|
||||
protected abstract void HandleContainerModified(EntityUid uid, SharedHandsComponent component, ContainerModifiedMessage args);
|
||||
}
|
||||
|
||||
public sealed class ContainedEntityDropHandItemsAttemptEvent : CancellableEntityEventArgs
|
||||
@@ -103,21 +96,4 @@ namespace Content.Shared.Hands
|
||||
HandName = handName;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class RequestDropHeldEntityEvent : EntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// The hand to drop from.
|
||||
/// </summary>
|
||||
public string HandName { get; }
|
||||
|
||||
public EntityCoordinates DropTarget { get; }
|
||||
|
||||
public RequestDropHeldEntityEvent(string handName, EntityCoordinates dropTarget)
|
||||
{
|
||||
HandName = handName;
|
||||
DropTarget = dropTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
Content.Shared/Interaction/BeforeInteract.cs
Normal file
53
Content.Shared/Interaction/BeforeInteract.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Shared.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// Raised directed on the used object when clicking on another object before an interaction is handled.
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public class BeforeInteractEvent : HandledEntityEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity that triggered the interaction.
|
||||
/// </summary>
|
||||
public IEntity User { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Entity that the user used to interact.
|
||||
/// </summary>
|
||||
public IEntity Used { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Entity that was interacted on. This can be null if the attack did not click on an entity.
|
||||
/// </summary>
|
||||
public IEntity? Target { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Location that the user clicked outside of their interaction range.
|
||||
/// </summary>
|
||||
public EntityCoordinates ClickLocation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the click location close enough to reach by the player? This does not check for obstructions, just that the target is within
|
||||
/// reach radius around the user.
|
||||
/// </summary>
|
||||
public bool CanReach { get; }
|
||||
|
||||
public BeforeInteractEvent(
|
||||
IEntity user,
|
||||
IEntity used,
|
||||
IEntity? target,
|
||||
EntityCoordinates clickLocation,
|
||||
bool canReach)
|
||||
{
|
||||
User = user;
|
||||
Used = used;
|
||||
Target = target;
|
||||
ClickLocation = clickLocation;
|
||||
CanReach = canReach;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using JetBrains.Annotations;
|
||||
using Robust.Shared.Analyzers;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.DragDrop
|
||||
namespace Content.Shared.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface gives components behavior when they're dropped by a mob.
|
||||
@@ -1,5 +1,9 @@
|
||||
using System;
|
||||
using Content.Shared.Sound;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Players;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
@@ -9,7 +13,8 @@ namespace Content.Shared.Light.Component
|
||||
[Serializable, NetSerializable]
|
||||
public enum ExpendableLightVisuals
|
||||
{
|
||||
State
|
||||
State,
|
||||
Behavior
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
@@ -21,8 +26,11 @@ namespace Content.Shared.Light.Component
|
||||
Dead
|
||||
}
|
||||
|
||||
[NetworkedComponent]
|
||||
public abstract class SharedExpendableLightComponent: Robust.Shared.GameObjects.Component
|
||||
{
|
||||
public static readonly AudioParams LoopedSoundParams = new(0, 1, "Master", 62.5f, 1, true, 0.3f);
|
||||
|
||||
public sealed override string Name => "ExpendableLight";
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
@@ -66,7 +74,7 @@ namespace Content.Shared.Light.Component
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("loopedSound")]
|
||||
protected string LoopedSound { get; set; } = default!;
|
||||
public string LoopedSound { get; set; } = string.Empty;
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("dieSound")]
|
||||
|
||||
@@ -50,6 +50,8 @@ namespace Content.Shared.Pulling.Components
|
||||
return;
|
||||
}
|
||||
|
||||
var eventBus = Owner.EntityManager.EventBus;
|
||||
|
||||
// New value. Abandon being pulled by any existing object.
|
||||
if (_puller != null)
|
||||
{
|
||||
@@ -64,10 +66,9 @@ namespace Content.Shared.Pulling.Components
|
||||
{
|
||||
var message = new PullStoppedMessage(oldPullerPhysics, _physics);
|
||||
|
||||
oldPuller.SendMessage(null, message);
|
||||
Owner.SendMessage(null, message);
|
||||
eventBus.RaiseLocalEvent(oldPuller.Uid, message, broadcast: false);
|
||||
eventBus.RaiseLocalEvent(Owner.Uid, message);
|
||||
|
||||
oldPuller.EntityManager.EventBus.RaiseEvent(EventSource.Local, message);
|
||||
_physics.WakeBody();
|
||||
}
|
||||
// else-branch warning is handled below
|
||||
@@ -125,14 +126,14 @@ namespace Content.Shared.Pulling.Components
|
||||
|
||||
var pullAttempt = new PullAttemptMessage(pullerPhysics, _physics);
|
||||
|
||||
value.SendMessage(null, pullAttempt);
|
||||
eventBus.RaiseLocalEvent(value.Uid, pullAttempt, broadcast: false);
|
||||
|
||||
if (pullAttempt.Cancelled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Owner.SendMessage(null, pullAttempt);
|
||||
eventBus.RaiseLocalEvent(Owner.Uid, pullAttempt);
|
||||
|
||||
if (pullAttempt.Cancelled)
|
||||
{
|
||||
@@ -147,10 +148,8 @@ namespace Content.Shared.Pulling.Components
|
||||
|
||||
var message = new PullStartedMessage(PullerPhysics, _physics);
|
||||
|
||||
_puller.SendMessage(null, message);
|
||||
Owner.SendMessage(null, message);
|
||||
|
||||
_puller.EntityManager.EventBus.RaiseEvent(EventSource.Local, message);
|
||||
eventBus.RaiseLocalEvent(_puller.Uid, message, broadcast: false);
|
||||
eventBus.RaiseLocalEvent(Owner.Uid, message);
|
||||
|
||||
var union = PullerPhysics.GetWorldAABB().Union(_physics.GetWorldAABB());
|
||||
var length = Math.Max(union.Size.X, union.Size.Y) * 0.75f;
|
||||
@@ -335,29 +334,6 @@ namespace Content.Shared.Pulling.Components
|
||||
Puller = entity;
|
||||
}
|
||||
|
||||
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
||||
{
|
||||
base.HandleMessage(message, component);
|
||||
|
||||
if (message is not PullMessage pullMessage ||
|
||||
pullMessage.Pulled.Owner != Owner)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pulledStatus = Owner.GetComponentOrNull<SharedAlertsComponent>();
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case PullStartedMessage:
|
||||
pulledStatus?.ShowAlert(AlertType.Pulled);
|
||||
break;
|
||||
case PullStoppedMessage:
|
||||
pulledStatus?.ClearAlert(AlertType.Pulled);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRemove()
|
||||
{
|
||||
TryStopPull();
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Content.Shared.Physics.Pull;
|
||||
using Content.Shared.Movement.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Component = Robust.Shared.GameObjects.Component;
|
||||
|
||||
@@ -46,30 +44,5 @@ namespace Content.Shared.Pulling.Components
|
||||
|
||||
base.OnRemove();
|
||||
}
|
||||
|
||||
public override void HandleMessage(ComponentMessage message, IComponent? component)
|
||||
{
|
||||
base.HandleMessage(message, component);
|
||||
|
||||
if (message is not PullMessage pullMessage ||
|
||||
pullMessage.Puller.Owner != Owner)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SharedAlertsComponent? ownerStatus = Owner.GetComponentOrNull<SharedAlertsComponent>();
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case PullStartedMessage msg:
|
||||
Pulling = msg.Pulled.Owner;
|
||||
ownerStatus?.ShowAlert(AlertType.Pulling);
|
||||
break;
|
||||
case PullStoppedMessage _:
|
||||
Pulling = null;
|
||||
ownerStatus?.ClearAlert(AlertType.Pulling);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Shared.Physics.Pull
|
||||
{
|
||||
public class PullMessage : ComponentMessage
|
||||
public class PullMessage : EntityEventArgs
|
||||
{
|
||||
public readonly IPhysBody Puller;
|
||||
public readonly IPhysBody Pulled;
|
||||
44
Content.Shared/Pulling/Systems/SharedPullerSystem.cs
Normal file
44
Content.Shared/Pulling/Systems/SharedPullerSystem.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Physics.Pull;
|
||||
using Content.Shared.Pulling.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Shared.Pulling
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class SharedPullerSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SharedPullerComponent, PullStartedMessage>(PullerHandlePullStarted);
|
||||
SubscribeLocalEvent<SharedPullerComponent, PullStoppedMessage>(PullerHandlePullStopped);
|
||||
}
|
||||
|
||||
private static void PullerHandlePullStarted(
|
||||
EntityUid uid,
|
||||
SharedPullerComponent component,
|
||||
PullStartedMessage args)
|
||||
{
|
||||
if (args.Puller.Owner.Uid != uid)
|
||||
return;
|
||||
|
||||
if (component.Owner.TryGetComponent(out SharedAlertsComponent? alerts))
|
||||
alerts.ShowAlert(AlertType.Pulling);
|
||||
}
|
||||
|
||||
private static void PullerHandlePullStopped(
|
||||
EntityUid uid,
|
||||
SharedPullerComponent component,
|
||||
PullStoppedMessage args)
|
||||
{
|
||||
if (args.Puller.Owner.Uid != uid)
|
||||
return;
|
||||
|
||||
if (component.Owner.TryGetComponent(out SharedAlertsComponent? alerts))
|
||||
alerts.ClearAlert(AlertType.Pulling);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Physics.Pull;
|
||||
@@ -56,12 +57,34 @@ namespace Content.Shared.Pulling
|
||||
SubscribeLocalEvent<MoveEvent>(PullerMoved);
|
||||
SubscribeLocalEvent<EntInsertedIntoContainerMessage>(HandleContainerInsert);
|
||||
|
||||
SubscribeLocalEvent<SharedPullableComponent, PullStartedMessage>(PullableHandlePullStarted);
|
||||
SubscribeLocalEvent<SharedPullableComponent, PullStoppedMessage>(PullableHandlePullStopped);
|
||||
|
||||
CommandBinds.Builder
|
||||
.Bind(ContentKeyFunctions.MovePulledObject, new PointerInputCmdHandler(HandleMovePulledObject))
|
||||
.Bind(ContentKeyFunctions.ReleasePulledObject, InputCmdHandler.FromDelegate(HandleReleasePulledObject))
|
||||
.Register<SharedPullingSystem>();
|
||||
}
|
||||
|
||||
// Raise a "you are being pulled" alert if the pulled entity has alerts.
|
||||
private static void PullableHandlePullStarted(EntityUid uid, SharedPullableComponent component, PullStartedMessage args)
|
||||
{
|
||||
if (args.Pulled.Owner.Uid != uid)
|
||||
return;
|
||||
|
||||
if (component.Owner.TryGetComponent(out SharedAlertsComponent? alerts))
|
||||
alerts.ShowAlert(AlertType.Pulled);
|
||||
}
|
||||
|
||||
private static void PullableHandlePullStopped(EntityUid uid, SharedPullableComponent component, PullStoppedMessage args)
|
||||
{
|
||||
if (args.Pulled.Owner.Uid != uid)
|
||||
return;
|
||||
|
||||
if (component.Owner.TryGetComponent(out SharedAlertsComponent? alerts))
|
||||
alerts.ClearAlert(AlertType.Pulled);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
@@ -1,116 +0,0 @@
|
||||
using System;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.Shared.Sound
|
||||
{
|
||||
[NetworkedComponent()]
|
||||
public class SharedLoopingSoundComponent : Component
|
||||
{
|
||||
public override string Name => "LoopingSound";
|
||||
|
||||
/// <summary>
|
||||
/// Stops all sounds.
|
||||
/// </summary>
|
||||
public virtual void StopAllSounds()
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Stops a certain scheduled sound from playing.
|
||||
/// </summary>
|
||||
public virtual void StopScheduledSound(string filename)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an scheduled sound to be played.
|
||||
/// </summary>
|
||||
public virtual void AddScheduledSound(ScheduledSound scheduledSound)
|
||||
{}
|
||||
|
||||
/// <summary>
|
||||
/// Play an audio file following the entity.
|
||||
/// </summary>
|
||||
/// <param name="filename">The resource path to the OGG Vorbis file to play.</param>
|
||||
public void Play(string filename, AudioParams? audioParams = null)
|
||||
{
|
||||
AddScheduledSound(new ScheduledSound()
|
||||
{
|
||||
Filename = filename,
|
||||
AudioParams = audioParams,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public class ScheduledSoundMessage : ComponentMessage
|
||||
{
|
||||
public ScheduledSound Schedule = new();
|
||||
public ScheduledSoundMessage()
|
||||
{
|
||||
Directed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public class StopSoundScheduleMessage : ComponentMessage
|
||||
{
|
||||
public string Filename = string.Empty;
|
||||
public StopSoundScheduleMessage()
|
||||
{
|
||||
Directed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[NetSerializable, Serializable]
|
||||
public class StopAllSoundsMessage : ComponentMessage
|
||||
{
|
||||
public StopAllSoundsMessage()
|
||||
{
|
||||
Directed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
[DataDefinition]
|
||||
public class ScheduledSound
|
||||
{
|
||||
[DataField("fileName")]
|
||||
public string Filename = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The parameters to play the sound with.
|
||||
/// </summary>
|
||||
[DataField("audioparams")]
|
||||
public AudioParams? AudioParams;
|
||||
|
||||
/// <summary>
|
||||
/// Delay in milliseconds before playing the sound,
|
||||
/// and delay between repetitions if Times is not 0.
|
||||
/// </summary>
|
||||
[DataField("delay")]
|
||||
public uint Delay;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of milliseconds to add to the delay randomly.
|
||||
/// Useful for random ambience noises. Generated value differs from client to client.
|
||||
/// </summary>
|
||||
[DataField("randomdelay")]
|
||||
public uint RandomDelay;
|
||||
|
||||
/// <summary>
|
||||
/// How many times to repeat the sound. If it's 0, it will play the sound once.
|
||||
/// If it's less than 0, it will repeat the sound indefinitely.
|
||||
/// If it's greater than 0, it will play the sound n+1 times.
|
||||
/// </summary>
|
||||
[DataField("times")]
|
||||
public int Times;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the sound will play or not.
|
||||
/// </summary>
|
||||
public bool Play = true;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Content.Shared.Sound
|
||||
{
|
||||
[DataDefinition]
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public abstract class SoundSpecifier
|
||||
{
|
||||
public abstract string GetSound();
|
||||
@@ -15,7 +15,6 @@ namespace Content.Shared.Sound
|
||||
public abstract bool TryGetSound([NotNullWhen(true)] out string? sound);
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public sealed class SoundPathSpecifier : SoundSpecifier
|
||||
{
|
||||
public const string Node = "path";
|
||||
@@ -49,7 +48,6 @@ namespace Content.Shared.Sound
|
||||
}
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public sealed class SoundCollectionSpecifier : SoundSpecifier
|
||||
{
|
||||
public const string Node = "collection";
|
||||
|
||||
Reference in New Issue
Block a user