fish-station/Content.Shared/_Sunrise/Radials/Systems/SharedRadialSystem.cs
ThereDrD 8efeca7f48
Питомцы (#391)
* init

* port better radials

* change wizden radials to new radials

* minor radial ui refactor

* less redundant values

* cleanup

* minor cleanup + refactor

* rename action + base ghost logic

* ghost actions update

* attack action + better action granting

* add missing translation

* add debug entity for testing

* add radial actions sprites

* micro fixes

* translations for ghost panel

* fix attack action logic

* new pet action sprites

* better attack target action params

* add 2 new stock pets

* add translation string for new pets

* add additional checks for petting + cute effect for successful petting

* add transfer pets to new body logic for cloning and gibbing

* add summary for OnMasterGibbed

* add stock pets to loadout menu

* fix OnMasterGibbed logic and change it to OnMasterShutdown

* add localisation support

* add logic for shutdown pet component

* pets that spawned as loadout automatically linked now

* added new pets

* cleanup

* more pets

* ы

* фиксы

---------

Co-authored-by: SplikZerys <tronezero700@yandex.ru>
Co-authored-by: Vigers Ray <60344369+VigersRay@users.noreply.github.com>
Co-authored-by: Vigers Ray <vigersray@gmail.com>
2025-01-11 07:53:23 +03:00

128 lines
5.4 KiB
C#

using Content.Shared.ActionBlocker;
using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.Inventory.VirtualItem;
using Robust.Shared.Containers;
namespace Content.Shared._Sunrise.Radials.Systems;
public abstract class SharedRadialSystem : EntitySystem
{
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!;
[Dependency] protected readonly SharedContainerSystem ContainerSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeAllEvent<ExecuteRadialEvent>(HandleExecuteRadial);
}
private void HandleExecuteRadial(ExecuteRadialEvent args, EntitySessionEventArgs eventArgs)
{
var user = eventArgs.SenderSession.AttachedEntity;
if (user == null)
return;
if (Deleted(GetEntity(args.Target)) || Deleted(user))
return;
var radials = GetLocalRadials(GetEntity(args.Target), user.Value, args.RequestedRadial.GetType());
if (radials.TryGetValue(args.RequestedRadial, out var radial))
ExecuteRadial(radial, user.Value, GetEntity(args.Target));
}
/// <summary>
/// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This
/// does not request verbs from the server.
/// </summary>
public SortedSet<Radial> GetLocalRadials(EntityUid target, EntityUid user, Type type, bool force = false)
{
return GetLocalRadials(target, user, new HashSet<Type>() { type }, force);
}
/// <summary>
/// Raises a number of events in order to get all verbs of the given type(s) defined in local systems. This
/// does not request verbs from the server.
/// </summary>
public SortedSet<Radial> GetLocalRadials(EntityUid target, EntityUid user, HashSet<Type> types, bool force = false)
{
SortedSet<Radial> radials = new();
// accessibility checks
bool canAccess = false;
if (force || target == user)
canAccess = true;
else if (_interactionSystem.InRangeUnobstructed(user, target))
{
// Note that being in a container does not count as an obstruction for InRangeUnobstructed
// Therefore, we need extra checks to ensure the item is actually accessible:
if (ContainerSystem.IsInSameOrParentContainer(user, target))
canAccess = true;
else
// the item might be in a backpack that the user has open
canAccess = _interactionSystem.CanAccessViaStorage(user, target);
}
// A large number of verbs need to check action blockers. Instead of repeatedly having each system individually
// call ActionBlocker checks, just cache it for the verb request.
var canInteract = force || _actionBlockerSystem.CanInteract(user, target);
EntityUid? @using = null;
if (TryComp(user, out HandsComponent? hands) && (force || _actionBlockerSystem.CanUseHeldEntity(user, target)))
{
@using = hands.ActiveHandEntity;
// Check whether the "Held" entity is a virtual pull entity. If yes, set that as the entity being "Used".
// This allows you to do things like buckle a dragged person onto a surgery table, without click-dragging
// their sprite.
if (TryComp(@using, out VirtualItemComponent? pull))
@using = pull.BlockingEntity;
}
// TODO: fix this garbage and use proper generics or reflection or something else, not this.
if (types.Contains(typeof(InteractionRadial)))
{
var radialEvent = new GetRadialsEvent<InteractionRadial>(user, target, @using, hands, canInteract, canAccess);
RaiseLocalEvent(target, radialEvent, true);
radials.UnionWith(radialEvent.Radials);
}
// generic verbs
if (types.Contains(typeof(Radial)))
{
var radialsEvent = new GetRadialsEvent<Radial>(user, target, @using, hands, canInteract, canAccess);
RaiseLocalEvent(target, radialsEvent, true);
radials.UnionWith(radialsEvent.Radials);
}
return radials;
}
public virtual void ExecuteRadial(Radial radial, EntityUid user, EntityUid target, bool forced = false)
{
// invoke any relevant actions
radial.Act?.Invoke();
// Maybe raise a local event
if (radial.ExecutionEventArgs != null)
{
if (radial.EventTarget.IsValid())
RaiseLocalEvent(radial.EventTarget, radial.ExecutionEventArgs);
else
RaiseLocalEvent(radial.ExecutionEventArgs);
}
if (Deleted(user) || Deleted(target))
return;
// Perform any contact interactions
if (radial.DoContactInteraction ?? (radial.DefaultDoContactInteraction && _interactionSystem.InRangeUnobstructed(user, target)))
_interactionSystem.DoContactInteraction(user, target);
}
}