251 lines
8.8 KiB
C#
251 lines
8.8 KiB
C#
using Content.Server.Popups;
|
|
using Content.Server.Power.Components;
|
|
using Content.Server.Power.EntitySystems;
|
|
using Content.Server.Shuttles.Components;
|
|
using Content.Shared.ActionBlocker;
|
|
using Content.Shared.Alert;
|
|
using Content.Shared.Interaction;
|
|
using Content.Shared.Popups;
|
|
using Content.Shared.Shuttles;
|
|
using Content.Shared.Shuttles.Components;
|
|
using Content.Shared.Tag;
|
|
using Content.Shared.Verbs;
|
|
using Robust.Shared.Map;
|
|
using Robust.Shared.Player;
|
|
using Robust.Shared.Utility;
|
|
|
|
namespace Content.Server.Shuttles.EntitySystems
|
|
{
|
|
internal sealed class ShuttleConsoleSystem : SharedShuttleConsoleSystem
|
|
{
|
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
|
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
|
[Dependency] private readonly AlertsSystem _alertsSystem = default!;
|
|
[Dependency] private readonly PopupSystem _popup = default!;
|
|
[Dependency] private readonly TagSystem _tags = default!;
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<ShuttleConsoleComponent, ComponentShutdown>(HandleConsoleShutdown);
|
|
SubscribeLocalEvent<ShuttleConsoleComponent, ActivateInWorldEvent>(HandleConsoleInteract);
|
|
SubscribeLocalEvent<ShuttleConsoleComponent, PowerChangedEvent>(HandlePowerChange);
|
|
SubscribeLocalEvent<ShuttleConsoleComponent, GetVerbsEvent<InteractionVerb>>(OnConsoleInteract);
|
|
|
|
SubscribeLocalEvent<PilotComponent, MoveEvent>(HandlePilotMove);
|
|
}
|
|
|
|
private void OnConsoleInteract(EntityUid uid, ShuttleConsoleComponent component, GetVerbsEvent<InteractionVerb> args)
|
|
{
|
|
if (!args.CanAccess ||
|
|
!args.CanInteract)
|
|
return;
|
|
|
|
var xform = EntityManager.GetComponent<TransformComponent>(uid);
|
|
|
|
// Maybe move mode onto the console instead?
|
|
if (!_mapManager.TryGetGrid(xform.GridEntityId, out var grid) ||
|
|
!EntityManager.TryGetComponent(grid.GridEntityId, out ShuttleComponent? shuttle)) return;
|
|
|
|
InteractionVerb verb = new()
|
|
{
|
|
Text = Loc.GetString("shuttle-mode-toggle"),
|
|
Act = () => ToggleShuttleMode(args.User, component, shuttle),
|
|
Disabled = !xform.Anchored || !this.IsPowered(uid, EntityManager),
|
|
};
|
|
|
|
args.Verbs.Add(verb);
|
|
}
|
|
|
|
private void ToggleShuttleMode(EntityUid user, ShuttleConsoleComponent consoleComponent, ShuttleComponent shuttleComponent, TransformComponent? consoleXform = null)
|
|
{
|
|
// Re-validate
|
|
if (!this.IsPowered(consoleComponent.Owner, EntityManager)) return;
|
|
|
|
if (!Resolve(consoleComponent.Owner, ref consoleXform)) return;
|
|
|
|
if (!consoleXform.Anchored || consoleXform.GridEntityId != EntityManager.GetComponent<TransformComponent>(shuttleComponent.Owner).GridEntityId) return;
|
|
|
|
switch (shuttleComponent.Mode)
|
|
{
|
|
case ShuttleMode.Cruise:
|
|
shuttleComponent.Mode = ShuttleMode.Docking;
|
|
_popup.PopupEntity(Loc.GetString("shuttle-mode-docking"), consoleComponent.Owner, Filter.Entities(user));
|
|
break;
|
|
case ShuttleMode.Docking:
|
|
shuttleComponent.Mode = ShuttleMode.Cruise;
|
|
_popup.PopupEntity(Loc.GetString("shuttle-mode-cruise"), consoleComponent.Owner, Filter.Entities(user));
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
public override void Update(float frameTime)
|
|
{
|
|
base.Update(frameTime);
|
|
|
|
var toRemove = new RemQueue<PilotComponent>();
|
|
|
|
foreach (var comp in EntityManager.EntityQuery<PilotComponent>())
|
|
{
|
|
if (comp.Console == null) continue;
|
|
|
|
if (!_blocker.CanInteract(comp.Owner, comp.Console.Owner))
|
|
{
|
|
toRemove.Add(comp);
|
|
}
|
|
}
|
|
|
|
foreach (var comp in toRemove)
|
|
{
|
|
RemovePilot(comp);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Console requires power to operate.
|
|
/// </summary>
|
|
private void HandlePowerChange(EntityUid uid, ShuttleConsoleComponent component, PowerChangedEvent args)
|
|
{
|
|
if (!args.Powered)
|
|
{
|
|
component.Enabled = false;
|
|
|
|
ClearPilots(component);
|
|
}
|
|
else
|
|
{
|
|
component.Enabled = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// If pilot is moved then we'll stop them from piloting.
|
|
/// </summary>
|
|
private void HandlePilotMove(EntityUid uid, PilotComponent component, ref MoveEvent args)
|
|
{
|
|
if (component.Console == null || component.Position == null)
|
|
{
|
|
DebugTools.Assert(component.Position == null && component.Console == null);
|
|
EntityManager.RemoveComponent<PilotComponent>(uid);
|
|
return;
|
|
}
|
|
|
|
if (args.NewPosition.TryDistance(EntityManager, component.Position.Value, out var distance) &&
|
|
distance < PilotComponent.BreakDistance) return;
|
|
|
|
RemovePilot(component);
|
|
}
|
|
|
|
/// <summary>
|
|
/// For now pilots just interact with the console and can start piloting with wasd.
|
|
/// </summary>
|
|
private void HandleConsoleInteract(EntityUid uid, ShuttleConsoleComponent component, ActivateInWorldEvent args)
|
|
{
|
|
if (!_tags.HasTag(args.User, "CanPilot"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var pilotComponent = EntityManager.EnsureComponent<PilotComponent>(args.User);
|
|
|
|
if (!component.Enabled)
|
|
{
|
|
args.User.PopupMessage($"Console is not powered.");
|
|
return;
|
|
}
|
|
|
|
args.Handled = true;
|
|
var console = pilotComponent.Console;
|
|
|
|
if (console != null)
|
|
{
|
|
RemovePilot(pilotComponent);
|
|
|
|
if (console == component)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
AddPilot(args.User, component);
|
|
}
|
|
|
|
protected override void HandlePilotShutdown(EntityUid uid, PilotComponent component, ComponentShutdown args)
|
|
{
|
|
base.HandlePilotShutdown(uid, component, args);
|
|
RemovePilot(component);
|
|
}
|
|
|
|
private void HandleConsoleShutdown(EntityUid uid, ShuttleConsoleComponent component, ComponentShutdown args)
|
|
{
|
|
ClearPilots(component);
|
|
}
|
|
|
|
public void AddPilot(EntityUid entity, ShuttleConsoleComponent component)
|
|
{
|
|
if (!EntityManager.TryGetComponent(entity, out PilotComponent? pilotComponent) ||
|
|
component.SubscribedPilots.Contains(pilotComponent))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (TryComp<SharedEyeComponent>(entity, out var eye))
|
|
{
|
|
eye.Zoom = component.Zoom;
|
|
}
|
|
|
|
component.SubscribedPilots.Add(pilotComponent);
|
|
|
|
_alertsSystem.ShowAlert(entity, AlertType.PilotingShuttle);
|
|
|
|
entity.PopupMessage(Loc.GetString("shuttle-pilot-start"));
|
|
pilotComponent.Console = component;
|
|
ActionBlockerSystem.UpdateCanMove(entity);
|
|
pilotComponent.Position = EntityManager.GetComponent<TransformComponent>(entity).Coordinates;
|
|
pilotComponent.Dirty();
|
|
}
|
|
|
|
public void RemovePilot(PilotComponent pilotComponent)
|
|
{
|
|
var console = pilotComponent.Console;
|
|
|
|
if (console is not ShuttleConsoleComponent helmsman) return;
|
|
|
|
pilotComponent.Console = null;
|
|
pilotComponent.Position = null;
|
|
|
|
if (TryComp<SharedEyeComponent>(pilotComponent.Owner, out var eye))
|
|
{
|
|
eye.Zoom = new(1.0f, 1.0f);
|
|
}
|
|
|
|
if (!helmsman.SubscribedPilots.Remove(pilotComponent)) return;
|
|
|
|
_alertsSystem.ClearAlert(pilotComponent.Owner, AlertType.PilotingShuttle);
|
|
|
|
pilotComponent.Owner.PopupMessage(Loc.GetString("shuttle-pilot-end"));
|
|
|
|
if (pilotComponent.LifeStage < ComponentLifeStage.Stopping)
|
|
EntityManager.RemoveComponent<PilotComponent>(pilotComponent.Owner);
|
|
}
|
|
|
|
public void RemovePilot(EntityUid entity)
|
|
{
|
|
if (!EntityManager.TryGetComponent(entity, out PilotComponent? pilotComponent)) return;
|
|
|
|
RemovePilot(pilotComponent);
|
|
}
|
|
|
|
public void ClearPilots(ShuttleConsoleComponent component)
|
|
{
|
|
while (component.SubscribedPilots.TryGetValue(0, out var pilot))
|
|
{
|
|
RemovePilot(pilot);
|
|
}
|
|
}
|
|
}
|
|
}
|