Files
OldThink/Content.Server/_White/Cult/Items/Systems/TorchCultistsProviderSystem.cs
2024-03-30 11:33:13 +07:00

278 lines
9.0 KiB
C#

using Content.Server.Atmos.EntitySystems;
using Content.Server.Popups;
using Content.Server.Station.Systems;
using Content.Server.Station.Components;
using Content.Server._White.Cult.Items.Components;
using Content.Shared._White.Cult.Components;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Item;
using Content.Shared.Mind.Components;
using Content.Shared.Physics;
using Content.Shared._White.Cult.Items;
using Content.Shared.Movement.Pulling.Systems;
using Robust.Server.GameObjects;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Timing;
namespace Content.Server._White.Cult.Items.Systems;
public sealed class TorchCultistsProviderSystem : EntitySystem
{
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedTransformSystem _xform = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly SharedPointLightSystem _pointLight = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly PullingSystem _pulling = default!;
[Dependency] private readonly MapSystem _map = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<TorchCultistsProviderComponent, AfterInteractEvent>(OnInteract);
SubscribeLocalEvent<TorchCultistsProviderComponent, TorchWindowItemSelectedMessage>(OnCultistSelected);
SubscribeLocalEvent<TorchCultistsProviderComponent, ComponentInit>(OnInit);
}
private void OnInit(EntityUid uid, TorchCultistsProviderComponent component, ComponentInit args)
{
UpdateAppearance(uid, component);
}
private void OnInteract(EntityUid uid, TorchCultistsProviderComponent comp, AfterInteractEvent args)
{
if (!args.Target.HasValue)
{
return;
}
if (!_interactionSystem.InRangeUnobstructed(args.User, args.Target.Value))
{
return;
}
if (!TryComp<TorchCultistsProviderComponent>(uid, out var provider))
return;
if (!HasComp<CultistComponent>(args.User))
{
_hands.TryDrop(args.User);
_popup.PopupEntity(Loc.GetString("cult-torch-not-cultist"), args.User, args.User);
return;
}
if (!provider.Active || provider.UsesLeft <= 0)
{
_popup.PopupEntity(Loc.GetString("cult-torch-drained"), args.User, args.User);
return;
}
if (provider.NextUse > _timing.CurTime)
{
_popup.PopupEntity(Loc.GetString("cult-torch-cooldown"), args.User, args.User);
return;
}
if (HasComp<MindContainerComponent>(args.Target))
{
TeleportToRandomLocation(uid, args, comp);
return;
}
if (!HasComp<ItemComponent>(args.Target))
{
return;
}
var ui = _ui.GetUiOrNull(uid, comp.UserInterfaceKey);
if (ui == null)
return;
provider.ItemSelected = args.Target;
var cultistsQuery = EntityQueryEnumerator<CultistComponent>();
var list = new Dictionary<string, string>();
while (cultistsQuery.MoveNext(out var cultistUid, out _))
{
if (!TryComp<MetaDataComponent>(cultistUid, out var meta))
return;
if (cultistUid == args.User)
continue;
list.Add(cultistUid.ToString(), meta.EntityName);
}
if (list.Count == 0)
{
_popup.PopupEntity(Loc.GetString("cult-torch-cultists-not-found"), args.User, args.User);
return;
}
_ui.SetUiState(ui, new TorchWindowBUIState(list));
if (!TryComp<ActorComponent>(args.User, out var actorComponent))
return;
_ui.ToggleUi(ui, actorComponent.PlayerSession);
}
private void OnCultistSelected(
EntityUid uid,
TorchCultistsProviderComponent component,
TorchWindowItemSelectedMessage args)
{
var entityUid = args.Session.AttachedEntity;
var cultistsQuery = EntityQueryEnumerator<CultistComponent>();
while (cultistsQuery.MoveNext(out var cultistUid, out _))
{
if (cultistUid.ToString() == args.EntUid)
entityUid = cultistUid;
}
if (entityUid == args.Session.AttachedEntity && entityUid != null)
{
_popup.PopupEntity(Loc.GetString("cult-torch-no-cultist"), entityUid.Value, entityUid.Value);
return;
}
if (component.ItemSelected != null)
{
var item = component.ItemSelected.Value;
if (!TryComp<TransformComponent>(entityUid, out var xForm))
return;
_xform.SetCoordinates(item, xForm.Coordinates);
_hands.PickupOrDrop(entityUid, item);
}
UpdateUsesCount(uid, args.Session.AttachedEntity, component);
}
private void UpdateAppearance(EntityUid uid, TorchCultistsProviderComponent component)
{
AppearanceComponent? appearance = null;
if (!Resolve(uid, ref appearance, false))
return;
_appearance.SetData(uid, VoidTorchVisuals.Activated, component.Active, appearance);
}
private void TeleportToRandomLocation(EntityUid torch, InteractEvent args, TorchCultistsProviderComponent component)
{
if (!args.Target.HasValue)
{
return;
}
if (_pulling.TryGetPulledEntity(args.User, out var pulled) || pulled != args.Target.Value)
{
return;
}
var ownerTransform = Transform(args.User);
if (_station.GetStationInMap(ownerTransform.MapID) is not { } station ||
!TryComp<StationDataComponent>(station, out var stationData) ||
_station.GetLargestGrid(stationData) is not { } grid)
{
if (ownerTransform.GridUid == null)
return;
grid = ownerTransform.GridUid.Value;
}
if (!TryComp<MapGridComponent>(grid, out var mapGrid))
{
return;
}
var gridTransform = Transform(grid);
var gridBounds = mapGrid.LocalAABB.Scale(0.7f); // чтобы не заспавнить на самом краю станции
var targetCoords = gridTransform.Coordinates;
for (var i = 0; i < 25; i++)
{
var randomX = _random.Next((int) gridBounds.Left, (int) gridBounds.Right);
var randomY = _random.Next((int) gridBounds.Bottom, (int) gridBounds.Top);
var tile = new Vector2i(randomX, randomY);
// no air-blocked areas.
if (_atmosphere.IsTileSpace(grid, gridTransform.MapUid, tile) ||
_atmosphere.IsTileAirBlocked(grid, tile, mapGridComp: mapGrid))
{
continue;
}
// don't spawn inside of solid objects
var physQuery = GetEntityQuery<PhysicsComponent>();
var valid = true;
foreach (var ent in _map.GetAnchoredEntities(grid, mapGrid, tile))
{
if (!physQuery.TryGetComponent(ent, out var body))
continue;
if (body.BodyType != BodyType.Static ||
!body.Hard ||
(body.CollisionLayer & (int) CollisionGroup.LargeMobMask) == 0)
continue;
valid = false;
break;
}
if (!valid)
continue;
targetCoords = _map.GridTileToLocal(grid, mapGrid, tile);
break;
}
_xform.SetCoordinates(args.User, targetCoords);
_xform.SetCoordinates(args.Target.Value, targetCoords);
UpdateUsesCount(torch, args.User, component);
}
private void UpdateUsesCount(EntityUid torch, EntityUid? user, TorchCultistsProviderComponent component)
{
component.ItemSelected = null;
component.NextUse = _timing.CurTime + component.Cooldown;
component.UsesLeft--;
if (user.HasValue)
{
_popup.PopupEntity(Loc.GetString("cult-torch-item-send"), user.Value);
}
if (component.UsesLeft <= 0)
{
component.Active = false;
UpdateAppearance(torch, component);
if (!TryComp<PointLightComponent>(torch, out var light))
return;
_pointLight.SetEnabled(torch, false, light);
}
}
}