Compare commits
10 Commits
ee4f13248b
...
4c691d4ab8
| Author | SHA1 | Date |
|---|---|---|
|
|
4c691d4ab8 | |
|
|
c3c6a6abd9 | |
|
|
6f0ad0c181 | |
|
|
7abc7a7b66 | |
|
|
7dc4c5f3fc | |
|
|
0400ffa8e3 | |
|
|
1754917204 | |
|
|
ed737e7c3d | |
|
|
3138b508c7 | |
|
|
1f94d1e9ba |
|
|
@ -0,0 +1,86 @@
|
|||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared._DV.Waypointer;
|
||||
using Content.Shared._DV.Waypointer.Components;
|
||||
using Content.Shared._DV.Waypointer.Events;
|
||||
using Content.Shared.Actions.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client._DV.Waypointer;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class WaypointerMenuBoundUserinterface(EntityUid owner, Enum uiKey) : BoundUserInterface(owner, uiKey)
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
private SimpleRadialMenu? _menu;
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
// The owner is the action entity - Not the entity that has the waypointer.
|
||||
if (!EntMan.TryGetComponent<ActionComponent>(Owner, out var actionComp)
|
||||
|| !EntMan.TryGetComponent<ActiveWaypointerComponent>(actionComp.Container, out var waypointer))
|
||||
return;
|
||||
|
||||
var waypointers = CreateButtons(waypointer);
|
||||
|
||||
if (waypointers == null)
|
||||
return;
|
||||
|
||||
_menu = this.CreateWindow<SimpleRadialMenu>();
|
||||
_menu.SetButtons(waypointers);
|
||||
|
||||
_menu.OpenCentered();
|
||||
}
|
||||
|
||||
private IEnumerable<RadialMenuOptionBase>? CreateButtons(ActiveWaypointerComponent waypointer)
|
||||
{
|
||||
if (waypointer.WaypointerProtoIds == null)
|
||||
return null;
|
||||
|
||||
var options = new List<RadialMenuOptionBase>();
|
||||
// We cannot use sprite specifier as we aren't using entities nor do we only need one image.
|
||||
// We need one for disabling and one for enabling - So we have this Frankenstein Monster.
|
||||
var state = waypointer.Active ? "action_icon_off" : "action_icon_on";
|
||||
var sprite = new SpriteSpecifier.Rsi(waypointer.RadialMenuIconPath, state);
|
||||
var toggleWaypointers = new RadialMenuActionOption<bool>(HandleRadialMenuClick, !waypointer.Active)
|
||||
{
|
||||
IconSpecifier = RadialMenuIconSpecifier.With(sprite),
|
||||
ToolTip = Loc.GetString(waypointer.Active ? "waypointer-disable-all" : "waypointer-enable-all"),
|
||||
};
|
||||
options.Add(toggleWaypointers);
|
||||
// This iterates through every waypointer to add them as options.
|
||||
foreach (var pair in waypointer.WaypointerProtoIds)
|
||||
{
|
||||
if (!_prototype.Resolve(pair.Key, out var prototype))
|
||||
continue;
|
||||
// If the waypointer is active, we want to the get sprite for disabling it.
|
||||
var waypointerState = pair.Value ? "disable" : "enable";
|
||||
var waypointerSprite = new SpriteSpecifier.Rsi(prototype.RadialMenuIconPath, waypointerState);
|
||||
var toggleWaypointer = new RadialMenuActionOption<ProtoId<WaypointerPrototype>>(HandleRadialMenuClick, pair.Key)
|
||||
{
|
||||
IconSpecifier = RadialMenuIconSpecifier.With(waypointerSprite),
|
||||
ToolTip = Loc.GetString(pair.Value ? "waypointer-disable" : "waypointer-enable", ("waypointer", prototype.Name)),
|
||||
};
|
||||
options.Add(toggleWaypointer);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private void HandleRadialMenuClick(bool toggleAll)
|
||||
{
|
||||
var message = new WaypointersToggledMessage(toggleAll);
|
||||
SendPredictedMessage(message);
|
||||
}
|
||||
|
||||
private void HandleRadialMenuClick(ProtoId<WaypointerPrototype> waypointer)
|
||||
{
|
||||
var message = new WaypointerStatusChangedMessage(waypointer);
|
||||
SendPredictedMessage(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.Shuttles.Systems;
|
||||
using Content.Client.Station;
|
||||
using Content.Shared._DV.Waypointer;
|
||||
using Content.Shared.CombatMode;
|
||||
using Content.Shared.Shuttles.Components;
|
||||
using Content.Shared.Station.Components;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client._DV.Waypointer;
|
||||
|
||||
/// <summary>
|
||||
/// This Overlay draws the waypointers on the screen.
|
||||
/// </summary>
|
||||
public sealed class WaypointerOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> UnshadedShader = "unshaded";
|
||||
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
|
||||
private readonly SharedCombatModeSystem _combatMode = default!;
|
||||
private readonly SharedPhysicsSystem _physics;
|
||||
private readonly SpriteSystem _sprite;
|
||||
private readonly StationSystem _station;
|
||||
private readonly TransformSystem _transform;
|
||||
private readonly ShaderInstance _unshadedShader;
|
||||
private readonly ShuttleSystem _shuttle;
|
||||
private readonly EntityWhitelistSystem _whitelist;
|
||||
|
||||
// This is used to check if a prototype is tracking the station grid.
|
||||
private readonly string _stationCompName = "StationData";
|
||||
// Caching the Uid for the station grid.
|
||||
private EntityUid? _mainStationGrid;
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||
|
||||
internal WaypointerOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_combatMode = _entity.System<SharedCombatModeSystem>();
|
||||
_physics = _entity.System<SharedPhysicsSystem>();
|
||||
_sprite = _entity.System<SpriteSystem>();
|
||||
_station = _entity.System<StationSystem>();
|
||||
_transform = _entity.System<TransformSystem>();
|
||||
_unshadedShader = _prototype.Index(UnshadedShader).Instance();
|
||||
_shuttle = _entity.System<ShuttleSystem>();
|
||||
_whitelist = _entity.System<EntityWhitelistSystem>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will draw the waypointers on top of the player.
|
||||
/// </summary>
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (_mainStationGrid == null)
|
||||
_mainStationGrid = GetStationGrid();
|
||||
|
||||
var handle = args.WorldHandle;
|
||||
handle.UseShader(_unshadedShader); // Waypointers are unshaded.
|
||||
|
||||
if (_player.LocalEntity == null
|
||||
|| !_entity.TryGetComponent<Shared._DV.Waypointer.Components.ActiveWaypointerComponent>(_player.LocalEntity, out var waypointer)
|
||||
// Check if the Waypointer hashset is null
|
||||
|| waypointer.WaypointerProtoIds == null
|
||||
|| !_entity.TryGetComponent<TransformComponent>(_player.LocalEntity, out var playerXform)
|
||||
|| playerXform.MapID != args.MapId)
|
||||
return;
|
||||
|
||||
var player = _player.LocalEntity.Value;
|
||||
|
||||
foreach (var waypointerPair in waypointer.WaypointerProtoIds)
|
||||
{
|
||||
// The boolean in the dictionary describes if the waypointer is active
|
||||
if (!waypointerPair.Value)
|
||||
continue;
|
||||
|
||||
if (!_prototype.Resolve(waypointerPair.Key, out var prototype)
|
||||
// Check if the waypointer works on grid and combat
|
||||
|| !prototype.WorkOnGrid && playerXform.GridUid != null
|
||||
|| !prototype.WorkInCombat && _combatMode.IsInCombatMode(player))
|
||||
continue;
|
||||
|
||||
var waypointQuery = _entity.CompRegistryQueryEnumerator(prototype.TrackedComponents);
|
||||
while (waypointQuery.MoveNext(out var target))
|
||||
{
|
||||
// Check if the target fails/passes the whitelist/blacklist.
|
||||
if (!_whitelist.CheckBoth(target, blacklist: prototype.Blacklist, whitelist: prototype.Whitelist)
|
||||
// Check if the target has a hidden IFF.
|
||||
|| _shuttle.HasIFFFlag(target, IFFFlags.Hide)
|
||||
// The station grid cannot be tracked directly due to being in nullspace
|
||||
|| CheckForStation(ref target, prototype)
|
||||
// Check if it has the Transform Component
|
||||
|| !_entity.TryGetComponent<TransformComponent>(target, out var targetXform)
|
||||
// Check if the target is even on the same map.
|
||||
|| targetXform.MapID != args.MapId)
|
||||
continue;
|
||||
|
||||
var positionA = _transform.GetWorldPosition(playerXform);
|
||||
var positionAndRotationB = _transform.GetWorldPositionRotation(targetXform);
|
||||
var positionB = positionAndRotationB.WorldPosition;
|
||||
|
||||
float distance;
|
||||
if (_entity.TryGetComponent<MapGridComponent>(target, out var map))
|
||||
{
|
||||
// Grids take a little more work - This calculates the distance to the closest part of the grid.
|
||||
_physics.TryGetDistance(player, target, out distance, playerXform, targetXform);
|
||||
// And then we also want to point towards the center of the grid - Not where the entity actually is.
|
||||
positionB += positionAndRotationB.WorldRotation.RotateVec(map.LocalAABB.Center);
|
||||
}
|
||||
else
|
||||
// Else we simply get the distance through this.
|
||||
distance = (positionA - positionB).Length();
|
||||
|
||||
if (distance > prototype.MaxRange)
|
||||
continue;
|
||||
|
||||
// The NTStationWaypointer has 5 stages and a range of 200. With calculations, it'll check if it's either in:
|
||||
// 0-39, 40-89, 80-119, 120-159, 160-200 range and use the respective waypointer sprite for it.
|
||||
var increments = prototype.MaxRange / prototype.WaypointerStates;
|
||||
var waypointerState = Math.Truncate(distance / increments) + 1;
|
||||
var stateName = "marker" + waypointerState;
|
||||
|
||||
var rsi = new SpriteSpecifier.Rsi(prototype.RsiPath, stateName);
|
||||
var texture = _sprite.Frame0(rsi);
|
||||
|
||||
// This is to draw the Waypointer sprites directly ontop of the entity sprite.
|
||||
var offset = new Vector2(texture.Height * 0.5f, texture.Width * 0.5f) / EyeManager.PixelsPerMeter;
|
||||
|
||||
// This calculates the angle to rotate the waypointer sprite towards the tracked entity.
|
||||
var direction = positionA - positionB;
|
||||
var angle = direction.ToWorldAngle();
|
||||
|
||||
handle.DrawTexture(texture, positionA - offset, angle, prototype.Color);
|
||||
}
|
||||
handle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This checks if the target is the station grid and if it should be tracking that.
|
||||
/// The station grid is a weird exception - Tracking it directly with StationDataComponent does not work.
|
||||
/// It'll result in tracking an Entity in nullspace. The grid itself does NOT have StationDataComponent.
|
||||
/// That also carries the issue of blacklists not working against the station grid, because it doesn't have the components.
|
||||
/// So, we need to check if the station grid is being tracked, or if we wrongly tracked the station grid when we were just tracking ordinary grids.
|
||||
/// </summary>
|
||||
/// <param name="target">The target being tracked</param>
|
||||
/// <param name="prototype">The waypointer prototype</param>
|
||||
/// <returns>
|
||||
/// Returns true if the target is the station grid, otherwise false.
|
||||
/// The parameter target will be changed to the station grid Uid if the prototype is tracking the station grid.
|
||||
/// </returns>
|
||||
private bool CheckForStation(ref EntityUid target, WaypointerPrototype prototype)
|
||||
{
|
||||
// If we are tracking the station via StationDataComponent, we will NEVER get the mainStationGrid.
|
||||
// So if we somehow DID get the station grid, it's because we are tracking something else and it bypassed the blacklist.
|
||||
if (target == _mainStationGrid)
|
||||
return true;
|
||||
|
||||
// If we are supposed to track the station grid, but are tracking the station entity in nullspace, replace it.
|
||||
if (prototype.TrackedComponents.ContainsKey(_stationCompName) && _mainStationGrid.HasValue)
|
||||
target = _mainStationGrid.Value;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the station grid that's on the playable map.
|
||||
/// </summary>
|
||||
/// <returns>The Uid for the station grid.</returns>
|
||||
private EntityUid? GetStationGrid()
|
||||
{
|
||||
var stationQuery = _entity.AllEntityQueryEnumerator<StationDataComponent>();
|
||||
|
||||
if (!stationQuery.MoveNext(out var station, out var comp))
|
||||
return null;
|
||||
|
||||
return _station.GetLargestGrid((station, comp));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
using Content.Shared._DV.Waypointer;
|
||||
using Content.Shared._DV.Waypointer.Components;
|
||||
using Content.Shared._DV.Waypointer.Events;
|
||||
using Content.Shared.Actions.Components;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.Timing;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Client._DV.Waypointer;
|
||||
|
||||
/// <summary>
|
||||
/// The client-side system handles initializing the overlay, as well as removing and adding it depending on game actions.
|
||||
/// </summary>
|
||||
public sealed class WaypointerSystem : SharedWaypointerSystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||
[Dependency] private readonly IClientGameTiming _timing = default!;
|
||||
|
||||
private WaypointerOverlay _waypointerOverlay = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, ComponentInit>(OnAddition);
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, ComponentRemove>(OnRemoval);
|
||||
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, LocalPlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, LocalPlayerDetachedEvent>(OnPlayerDetached);
|
||||
|
||||
_waypointerOverlay = new WaypointerOverlay();
|
||||
}
|
||||
|
||||
private void OnAddition(Entity<ActiveWaypointerComponent> player, ref ComponentInit args)
|
||||
{
|
||||
if (_player.LocalEntity == null || player.Owner != _player.LocalEntity.Value
|
||||
|| _timing.ApplyingState)
|
||||
return;
|
||||
|
||||
_overlay.AddOverlay(_waypointerOverlay);
|
||||
}
|
||||
|
||||
private void OnRemoval(Entity<ActiveWaypointerComponent> player, ref ComponentRemove args)
|
||||
{
|
||||
if (_player.LocalEntity == null || player.Owner != _player.LocalEntity.Value
|
||||
|| _timing.ApplyingState)
|
||||
return;
|
||||
|
||||
_overlay.RemoveOverlay(_waypointerOverlay);
|
||||
}
|
||||
|
||||
protected override void OnWaypointersToggled(Entity<ActionComponent> action, ref WaypointersToggledMessage args)
|
||||
{
|
||||
base.OnWaypointersToggled(action, ref args);
|
||||
|
||||
if (args.IsActive)
|
||||
_overlay.AddOverlay(_waypointerOverlay);
|
||||
else
|
||||
_overlay.RemoveOverlay(_waypointerOverlay);
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(Entity<ActiveWaypointerComponent> player, ref LocalPlayerAttachedEvent args)
|
||||
{
|
||||
if (args.Entity != _player.LocalEntity)
|
||||
return;
|
||||
|
||||
_overlay.AddOverlay(_waypointerOverlay);
|
||||
}
|
||||
|
||||
private void OnPlayerDetached(Entity<ActiveWaypointerComponent> player, ref LocalPlayerDetachedEvent args)
|
||||
{
|
||||
if (args.Entity != _player.LocalEntity)
|
||||
return;
|
||||
|
||||
_overlay.RemoveOverlay(_waypointerOverlay);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
namespace Content.Server.Cargo.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Target for approved orders to spawn at.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class TradeStationComponent : Component
|
||||
{
|
||||
|
||||
}
|
||||
// DeltaV Start - This has been moved to Shared.
|
||||
// namespace Content.Server.Cargo.Components;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Target for approved orders to spawn at.
|
||||
// /// </summary>
|
||||
// [RegisterComponent]
|
||||
// public sealed partial class TradeStationComponent : Component
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// DeltaV End - This has been moved to Shared.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using Content.Shared.Access.Systems;
|
|||
using Content.Shared.Administration.Logs;
|
||||
using Content.Server.Radio.EntitySystems;
|
||||
using Content.Shared.Cargo;
|
||||
using Content.Shared.Cargo.Components; // DeltaV - Waypointers
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Paper;
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
using Content.Server.Shuttles.Systems;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Server.Shuttles.Components;
|
||||
|
||||
/// <summary>
|
||||
/// If added to a grid gets launched when the emergency shuttle launches.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(EmergencyShuttleSystem)), AutoGenerateComponentPause]
|
||||
public sealed partial class EscapePodComponent : Component
|
||||
{
|
||||
[DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
[AutoPausedField]
|
||||
public TimeSpan? LaunchTime;
|
||||
}
|
||||
// DeltaV Start - This has been moved to _DV.Shared.
|
||||
// using Content.Server.Shuttles.Systems;
|
||||
// using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
//
|
||||
// namespace Content.Server.Shuttles.Components;
|
||||
//
|
||||
// /// <summary>
|
||||
// /// If added to a grid gets launched when the emergency shuttle launches.
|
||||
// /// </summary>
|
||||
// [RegisterComponent, Access(typeof(EmergencyShuttleSystem)), AutoGenerateComponentPause]
|
||||
// public sealed partial class EscapePodComponent : Component
|
||||
// {
|
||||
// [DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
// [AutoPausedField]
|
||||
// public TimeSpan? LaunchTime;
|
||||
// }
|
||||
// DeltaV End - This has been moved to _DV.Shared.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
using System.Linq;
|
||||
using Content.Shared._DV.Waypointer;
|
||||
using Content.Shared._DV.Waypointer.Components;
|
||||
using Content.Shared.Whitelist;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameStates;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._DV.Waypointer;
|
||||
|
||||
/// <summary>
|
||||
/// This handles the PVSOverrides for the Waypointer System.
|
||||
/// </summary>
|
||||
public sealed class WaypointerSystem : SharedWaypointerSystem
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
[Dependency] private readonly IPlayerManager _player = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly PvsOverrideSystem _pvsOverride = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, ComponentInit>(OnAddition);
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, ComponentRemove>(OnRemoval);
|
||||
|
||||
SubscribeLocalEvent<WaypointerTrackableComponent, ComponentInit>(OnTrackableInit);
|
||||
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, PlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, PlayerDetachedEvent>(OnPlayerDetached);
|
||||
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, MapUidChangedEvent>(OnMapChanged);
|
||||
}
|
||||
|
||||
private void OnAddition(Entity<ActiveWaypointerComponent> player, ref ComponentInit args)
|
||||
{
|
||||
_actions.AddAction(player, ref player.Comp.ActionEntity, player.Comp.ActionProtoId);
|
||||
}
|
||||
|
||||
private void OnRemoval(Entity<ActiveWaypointerComponent> player, ref ComponentRemove args)
|
||||
{
|
||||
_actions.RemoveAction(player.Owner, player.Comp.ActionEntity);
|
||||
}
|
||||
|
||||
private void OnTrackableInit(Entity<WaypointerTrackableComponent> trackable, ref ComponentInit args)
|
||||
{
|
||||
// This might be a bit confusing, but I think this is the cheapest way to refresh overrides for new trackables.
|
||||
// I'll explain:
|
||||
// This gets all possible waypointers in the game.
|
||||
var waypointers = _prototype.GetInstances<WaypointerPrototype>();
|
||||
// This will hold all waypointers that need their overrides to be refreshed because this trackable spawned.
|
||||
var waypointersToOverride = new HashSet<ProtoId<WaypointerPrototype>>();
|
||||
|
||||
// Now, we iterate through each waypointer
|
||||
foreach (var waypointer in waypointers.Values)
|
||||
{
|
||||
// And then we iterate through each component that the waypointer tracks
|
||||
foreach (var trackedComponent in waypointer.TrackedComponents.Values)
|
||||
{
|
||||
// And then check if the trackable has that tracked component
|
||||
if (!EntityManager.HasComponent(trackable, trackedComponent.Component.GetType())
|
||||
// And of course, check if it passes the whitelist & blacklist.
|
||||
|| !_whitelist.CheckBoth(trackable, blacklist: waypointer.Blacklist, whitelist: waypointer.Whitelist))
|
||||
continue;
|
||||
|
||||
// THEN we add that WAYPOINTER to the list above.
|
||||
waypointersToOverride.Add(new ProtoId<WaypointerPrototype>(waypointer.ID));
|
||||
// If it didn't have that component, then we don't need to refresh the overrides for that one.
|
||||
}
|
||||
}
|
||||
|
||||
// We get this for a check later.
|
||||
var trackXform = Transform(trackable);
|
||||
|
||||
// Now we get every entity that has an active waypointer
|
||||
var waypointerQuery = AllEntityQuery<ActiveWaypointerComponent, ActorComponent>();
|
||||
// We iterate through them
|
||||
while (waypointerQuery.MoveNext(out var player, out var waypointerComp, out var actorComp))
|
||||
{
|
||||
// No need to override if they don't have any waypointers.
|
||||
if (waypointerComp.WaypointerProtoIds == null)
|
||||
continue;
|
||||
|
||||
// Then we iterate through every waypointer they have access to
|
||||
foreach (var waypointer in waypointerComp.WaypointerProtoIds.Keys)
|
||||
{
|
||||
// We check if they have any waypointer that can track the new trackable entity.
|
||||
if (!waypointersToOverride.Contains(waypointer))
|
||||
continue;
|
||||
|
||||
var playerXform = Transform(player);
|
||||
// Now we check if that player is on the same map as the tracked entity.
|
||||
if (trackXform.MapID != playerXform.MapID)
|
||||
continue;
|
||||
|
||||
// Then we finally override that entity for said player.
|
||||
_pvsOverride.AddSessionOverride(trackable, actorComp.PlayerSession);
|
||||
break; // No need to check other waypointers, so we break here to check for the next player.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerAttached(Entity<ActiveWaypointerComponent> player, ref PlayerAttachedEvent args)
|
||||
{
|
||||
if (player.Comp.WaypointerProtoIds == null)
|
||||
return;
|
||||
|
||||
AddOverrides(player, player.Comp.WaypointerProtoIds.Keys.ToHashSet());
|
||||
}
|
||||
|
||||
private void OnPlayerDetached(Entity<ActiveWaypointerComponent> player, ref PlayerDetachedEvent args)
|
||||
{
|
||||
if (player.Comp.WaypointerProtoIds == null)
|
||||
return;
|
||||
|
||||
RemoveOverrides(player, player.Comp.WaypointerProtoIds.Keys.ToHashSet());
|
||||
}
|
||||
|
||||
private void OnMapChanged(Entity<ActiveWaypointerComponent> player, ref MapUidChangedEvent args)
|
||||
{
|
||||
// Since we only override PVS on entities on the same map, if the person switches maps, they'll need new overrides.
|
||||
RefreshOverrides(player);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the Waypointer PVS Overiddes for an entity if they are controlled by a player.
|
||||
/// </summary>
|
||||
/// <param name="player">The entity to have their overrides refreshed.</param>
|
||||
[PublicAPI]
|
||||
public void RefreshOverrides(Entity<ActiveWaypointerComponent> player)
|
||||
{
|
||||
if (player.Comp.WaypointerProtoIds == null)
|
||||
return;
|
||||
|
||||
RemoveOverrides(player, player.Comp.WaypointerProtoIds.Keys.ToHashSet());
|
||||
AddOverrides(player, player.Comp.WaypointerProtoIds.Keys.ToHashSet());
|
||||
}
|
||||
|
||||
protected override void AddOverrides(EntityUid player, HashSet<ProtoId<WaypointerPrototype>> waypointers)
|
||||
{
|
||||
if (!_player.TryGetSessionByEntity(player, out var session))
|
||||
return;
|
||||
|
||||
var playerXform = Transform(player);
|
||||
|
||||
foreach (var waypointerProtoId in waypointers)
|
||||
{
|
||||
if (!_prototype.Resolve(waypointerProtoId, out var prototype))
|
||||
continue;
|
||||
|
||||
var waypointQuery = _entity.CompRegistryQueryEnumerator(prototype.TrackedComponents);
|
||||
while (waypointQuery.MoveNext(out var target))
|
||||
{
|
||||
// Grids somehow already work, so we exclude them. No idea why. But I fear messing with them.
|
||||
if (HasComp<MapGridComponent>(target)
|
||||
// If it doesn't have the trackable component either, it doesn't work.
|
||||
|| HasComp<WaypointerTrackableComponent>(target)
|
||||
// Check if the target fails/passes the whitelist/blacklist.
|
||||
|| _whitelist.CheckBoth(target, whitelist: prototype.Whitelist, blacklist: prototype.Blacklist))
|
||||
continue;
|
||||
|
||||
var targetXform = Transform(target);
|
||||
|
||||
// Check if they're in the same Map. If not, don't override.
|
||||
if (targetXform.MapID == playerXform.MapID)
|
||||
_pvsOverride.AddSessionOverride(target, session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void RemoveOverrides(EntityUid player, HashSet<ProtoId<WaypointerPrototype>> waypointers)
|
||||
{
|
||||
if (!_player.TryGetSessionByEntity(player, out var session))
|
||||
return;
|
||||
|
||||
foreach (var waypointerProtoId in waypointers)
|
||||
{
|
||||
if (!_prototype.Resolve(waypointerProtoId, out var prototype))
|
||||
continue;
|
||||
|
||||
var waypointQuery = _entity.CompRegistryQueryEnumerator(prototype.TrackedComponents);
|
||||
while (waypointQuery.MoveNext(out var target))
|
||||
{
|
||||
// Grids somehow already work, so we exclude them. No idea why. But I fear messing with them.
|
||||
if (HasComp<MapGridComponent>(target))
|
||||
continue;
|
||||
|
||||
_pvsOverride.RemoveSessionOverride(target, session);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using Content.Shared._DV.Overlays;
|
||||
using Content.Shared._DV.Psionics.Events; // DeltaV
|
||||
using Content.Shared._DV.Waypointer.Events; // DeltaV
|
||||
using Content.Shared.Armor;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Chat;
|
||||
|
|
@ -81,12 +82,15 @@ public partial class InventorySystem
|
|||
SubscribeLocalEvent<InventoryComponent, WieldAttemptEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, UnwieldAttemptEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, IngestionAttemptEvent>(RefRelayInventoryEvent);
|
||||
// DeltaV Start - Psionic Events
|
||||
// DeltaV Start
|
||||
// Psionic Events
|
||||
SubscribeLocalEvent<InventoryComponent, DispelledEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, PsionicPowerUseAttemptEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, TargetedByPsionicPowerEvent>(RefRelayInventoryEvent);
|
||||
SubscribeLocalEvent<InventoryComponent, NoosphericFryEvent>(RefRelayInventoryEvent);
|
||||
// DeltaV End - Psionic Events
|
||||
|
||||
SubscribeLocalEvent<InventoryComponent, WaypointerChangedEvent>(RefRelayInventoryEvent);
|
||||
// DeltaV End
|
||||
|
||||
// Eye/vision events
|
||||
SubscribeLocalEvent<InventoryComponent, CanSeeAttemptEvent>(RelayInventoryEvent);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.Cargo.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Target for approved orders to spawn at.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class TradeStationComponent : Component;
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
using Content.Shared.Shuttles.Systems;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.Shuttles.Components;
|
||||
|
||||
/// <summary>
|
||||
/// If added to a grid gets launched when the emergency shuttle launches.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, Access(typeof(SharedEmergencyShuttleSystem)), AutoGenerateComponentPause]
|
||||
public sealed partial class EscapePodComponent : Component
|
||||
{
|
||||
[DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
[AutoPausedField]
|
||||
public TimeSpan? LaunchTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using Content.Shared.Shuttles.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Map.Components;
|
||||
|
||||
namespace Content.Shared.Shuttles.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// This is the DeltaV System for avoiding merge conflicts.
|
||||
/// </summary>
|
||||
public abstract partial class SharedShuttleSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if the GridUid has the specified IFF-Flag.
|
||||
/// </summary>
|
||||
/// <param name="gridUid">The grid whose IFF-Flags are being checked.</param>
|
||||
/// <param name="requiredFlag">The required IFF-Flag.</param>
|
||||
/// <param name="component">The IFF component of the grid.</param>
|
||||
/// <returns>
|
||||
/// Returns true if the grid has the required IFF-Flag, otherwise false.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// Returns false if the Uid is not a grid and the required IFF-Flag is anything but <see cref="IFFFlags.None"/>, otherwise true.
|
||||
/// </remarks>
|
||||
[PublicAPI]
|
||||
public bool HasIFFFlag(EntityUid gridUid, IFFFlags requiredFlag, IFFComponent? component = null)
|
||||
{
|
||||
// Check if it's a grid.
|
||||
if (!HasComp<MapGridComponent>(gridUid))
|
||||
return requiredFlag == IFFFlags.None;
|
||||
|
||||
component ??= EnsureComp<IFFComponent>(gridUid);
|
||||
|
||||
return component.Flags.HasFlag(requiredFlag);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._DV.Waypointer.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This signifies an entity with an active waypointer trying to track something.
|
||||
/// This is NOT a pinpointer.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class ActiveWaypointerComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The actual UID for the action entity. It'll be saved here when the component is initialized.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public EntityUid? ActionEntity;
|
||||
|
||||
/// <summary>
|
||||
/// The prototype ID for the action.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntProtoId ActionProtoId = "ActionManageWaypointers";
|
||||
|
||||
/// <summary>
|
||||
/// The prototype of the waypointer visible for the owner of this component.
|
||||
/// The bool value determines whether the corresponding waypointer is active.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public Dictionary<ProtoId<WaypointerPrototype>, bool>? WaypointerProtoIds;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the waypointer system is enabled or not.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool Active = true;
|
||||
|
||||
/// <summary>
|
||||
/// The resource path for the "Disable/Enable all waypointers" menu option.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ResPath RadialMenuIconPath = new("_DV/Markers/Waypointers/waypointer_action.rsi");
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._DV.Waypointer.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for clothing that enables waypointers for the equipee.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class ClothingShowWaypointerComponent: Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The prototype of the waypointer that this clothing will grant to the wearer.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public HashSet<ProtoId<WaypointerPrototype>> WaypointerProtoIds = default!;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._DV.Waypointer.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for entities that have an innate waypointer.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// Dragons.
|
||||
/// </example>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class InnateWaypointerComponent: Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The prototype of the waypointer that this entity will have.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public HashSet<ProtoId<WaypointerPrototype>> WaypointerProtoIds = default!;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._DV.Waypointer.Components;
|
||||
|
||||
/// <summary>
|
||||
/// This is on entities that ARE NOT GRIDS to be trackable by Waypointers.
|
||||
/// If you want an entity that isn't a grid to be tracked by a waypointer, put this on them.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed partial class WaypointerTrackableComponent : Component;
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
using Content.Shared.Actions;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._DV.Waypointer.Events;
|
||||
|
||||
/// <summary>
|
||||
/// This is a simple action for when someone wants to manage their waypointers.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public sealed partial class ActionManageWaypointersEvent : InstantActionEvent;
|
||||
|
||||
/// <summary>
|
||||
/// This message is sent from the client when the player wants to toggle all waypointers.
|
||||
/// </summary>
|
||||
/// <param name="isActive">Whether the waypointer system is now active or inactive.</param>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class WaypointersToggledMessage(bool isActive) : BoundUserInterfaceMessage
|
||||
{
|
||||
public bool IsActive = isActive;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This message is sent from the client when the player wants to toggle a specific waypointer.
|
||||
/// </summary>
|
||||
/// <param name="waypointer">The waypointer to be toggled.</param>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class WaypointerStatusChangedMessage(ProtoId<WaypointerPrototype> waypointer) : BoundUserInterfaceMessage
|
||||
{
|
||||
public ProtoId<WaypointerPrototype> ToggledWaypointerProtoId = waypointer;
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
using Content.Shared.Inventory;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared._DV.Waypointer.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Whenever a clothing that shows waypointers is equipped.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct WaypointerChangedEvent() : IInventoryRelayEvent
|
||||
{
|
||||
public HashSet<ProtoId<WaypointerPrototype>> Waypointers = [];
|
||||
SlotFlags IInventoryRelayEvent.TargetSlots => SlotFlags.WITHOUT_POCKET;
|
||||
}
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
using System.Linq;
|
||||
using Content.Shared._DV.Waypointer.Components;
|
||||
using Content.Shared._DV.Waypointer.Events;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Actions.Components;
|
||||
using Content.Shared.Clothing;
|
||||
using Content.Shared.Inventory;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared._DV.Waypointer;
|
||||
|
||||
/// <summary>
|
||||
/// This solely handles giving the Waypoint component to equipees. This cannot be done on client, or else it would.
|
||||
/// </summary>
|
||||
public abstract class SharedWaypointerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] protected readonly SharedActionsSystem _actions = default!;
|
||||
[Dependency] private readonly SharedUserInterfaceSystem _ui = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<InnateWaypointerComponent, MapInitEvent>(OnMapInit);
|
||||
|
||||
SubscribeLocalEvent<ActiveWaypointerComponent, ActionManageWaypointersEvent>(OnActionPressed);
|
||||
SubscribeLocalEvent<ActionComponent, WaypointersToggledMessage>(OnWaypointersToggled);
|
||||
SubscribeLocalEvent<ActionComponent, WaypointerStatusChangedMessage>(OnWaypointersStatusChanged);
|
||||
|
||||
SubscribeLocalEvent<ClothingShowWaypointerComponent, ClothingGotEquippedEvent>(OnEquip);
|
||||
SubscribeLocalEvent<ClothingShowWaypointerComponent, ClothingGotUnequippedEvent>(OnUnequip);
|
||||
|
||||
SubscribeLocalEvent<InnateWaypointerComponent, WaypointerChangedEvent>(OnWaypointerChanged);
|
||||
SubscribeLocalEvent<ClothingShowWaypointerComponent, InventoryRelayedEvent<WaypointerChangedEvent>>(OnWaypointerChanged);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<InnateWaypointerComponent> player, ref MapInitEvent args)
|
||||
{
|
||||
SetWaypointerComponent(player);
|
||||
}
|
||||
|
||||
private void OnActionPressed(Entity<ActiveWaypointerComponent> player, ref ActionManageWaypointersEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
// To avoid adding UserInterfaceComponent on the BaseMob, we open the interface on the action entity, not the player.
|
||||
_ui.OpenUi(args.Action.Owner, WaypointerUiKey.Key, player.Owner);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
protected virtual void OnWaypointersToggled(Entity<ActionComponent> action, ref WaypointersToggledMessage args)
|
||||
{
|
||||
// Messages are sent to the action entity - So we need to get the player from the component.
|
||||
if (!TryComp<ActiveWaypointerComponent>(action.Comp.Container, out var waypointer)
|
||||
|| waypointer.WaypointerProtoIds == null)
|
||||
return;
|
||||
|
||||
waypointer.Active = args.IsActive;
|
||||
_actions.SetToggled(action.AsNullable(), args.IsActive);
|
||||
|
||||
Dirty(action.Comp.Container.Value, waypointer);
|
||||
}
|
||||
|
||||
private void OnWaypointersStatusChanged(Entity<ActionComponent> action, ref WaypointerStatusChangedMessage args)
|
||||
{
|
||||
// Messages are sent to the action entity - So we need to get the player from the component.
|
||||
if (!TryComp<ActiveWaypointerComponent>(action.Comp.Container, out var waypointer)
|
||||
|| waypointer.WaypointerProtoIds == null)
|
||||
return;
|
||||
|
||||
waypointer.WaypointerProtoIds[args.ToggledWaypointerProtoId] = !waypointer.WaypointerProtoIds[args.ToggledWaypointerProtoId];
|
||||
|
||||
Dirty(action.Comp.Container.Value, waypointer);
|
||||
}
|
||||
|
||||
private void OnEquip(Entity<ClothingShowWaypointerComponent> clothing, ref ClothingGotEquippedEvent args)
|
||||
{
|
||||
SetWaypointerComponent(args.Wearer);
|
||||
}
|
||||
|
||||
private void OnUnequip(Entity<ClothingShowWaypointerComponent> clothing, ref ClothingGotUnequippedEvent args)
|
||||
{
|
||||
SetWaypointerComponent(args.Wearer);
|
||||
}
|
||||
|
||||
private void OnWaypointerChanged(Entity<InnateWaypointerComponent> clothing, ref WaypointerChangedEvent args)
|
||||
{
|
||||
args.Waypointers.UnionWith(clothing.Comp.WaypointerProtoIds);
|
||||
}
|
||||
|
||||
private void OnWaypointerChanged(Entity<ClothingShowWaypointerComponent> clothing, ref InventoryRelayedEvent<WaypointerChangedEvent> args)
|
||||
{
|
||||
args.Args.Waypointers.UnionWith(clothing.Comp.WaypointerProtoIds);
|
||||
}
|
||||
|
||||
private void SetWaypointerComponent(EntityUid player)
|
||||
{
|
||||
if (_timing.ApplyingState)
|
||||
return;
|
||||
|
||||
var comp = EnsureComp<ActiveWaypointerComponent>(player);
|
||||
// The following is much easier to do with HashSets.
|
||||
HashSet<ProtoId<WaypointerPrototype>>? previousTable = null;
|
||||
HashSet<ProtoId<WaypointerPrototype>>? overridesToRemove = null;
|
||||
if (comp.WaypointerProtoIds != null)
|
||||
{
|
||||
// Store the hashset for comparison later, if not null
|
||||
previousTable = comp.WaypointerProtoIds.Keys.ToHashSet();
|
||||
// The same as above. As an example, these have the values A and B. { A, B }
|
||||
overridesToRemove = comp.WaypointerProtoIds.Keys.ToHashSet();
|
||||
}
|
||||
|
||||
// We raise this on the entity to check for anything that could give the entity a waypointer.
|
||||
var ev = new WaypointerChangedEvent();
|
||||
RaiseLocalEvent(player, ref ev); // For example purposes, this will return { B, C }
|
||||
|
||||
if (overridesToRemove != null)
|
||||
{
|
||||
// Now we remove all the waypointers that the event gathered from the previous hashset.
|
||||
// Removing { B, C } will leave us with { A }, as we don't have the waypointer A anymore.
|
||||
overridesToRemove.ExceptWith(ev.Waypointers);
|
||||
// We remove the overrides for the waypointer A.
|
||||
RemoveOverrides(player, overridesToRemove);
|
||||
}
|
||||
|
||||
if (ev.Waypointers.Count == 0) // Self-Explanatory - If there are no waypointers left, remove the component.
|
||||
{
|
||||
RemComp<ActiveWaypointerComponent>(player);
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to turn it into a dictionary so we can keep track of every waypointer status, not important for overrides.
|
||||
var newDict = ev.Waypointers.ToDictionary(key => key, _ => true);
|
||||
if (comp.WaypointerProtoIds != null)
|
||||
{
|
||||
foreach (var pair in comp.WaypointerProtoIds.Where(pair => newDict.ContainsKey(pair.Key)))
|
||||
{
|
||||
// We set the status of every waypointer that persisted to their original value, not important for overrides.
|
||||
newDict[pair.Key] = pair.Value;
|
||||
}
|
||||
}
|
||||
// Then replace the old dictionary with the new one
|
||||
comp.WaypointerProtoIds = newDict;
|
||||
|
||||
// Here we now remove every waypointer that doesn't need new overrides.
|
||||
// The waypointer B was already overriden, since it's in the earlier hashset { A, B }
|
||||
// So, by removing { A, b} from { B, C }, we get { C }, which is the only new waypointer - thus needing overrides.
|
||||
if (previousTable != null)
|
||||
ev.Waypointers.ExceptWith(previousTable);
|
||||
|
||||
AddOverrides(player, ev.Waypointers);
|
||||
Dirty(player, comp);
|
||||
}
|
||||
|
||||
protected virtual void AddOverrides(EntityUid player, HashSet<ProtoId<WaypointerPrototype>> waypointers)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void RemoveOverrides(EntityUid player, HashSet<ProtoId<WaypointerPrototype>> waypointers)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum WaypointerUiKey : byte
|
||||
{
|
||||
Key,
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
using Content.Shared._DV.Waypointer.Components;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Shared._DV.Waypointer;
|
||||
|
||||
/// <summary>
|
||||
/// This is the prototype for a waypointer.
|
||||
/// This is stored in either <see cref="ActiveWaypointerComponent"/> or <see cref="ClothingShowWaypointerComponent"/>.
|
||||
/// It's responsible for defining what kind of waypointer is shown to the client.
|
||||
/// </summary>
|
||||
[Prototype]
|
||||
public sealed partial class WaypointerPrototype : IPrototype, IInheritingPrototype
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[IdDataField]
|
||||
public string ID { get; private set; } = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
[ParentDataField(typeof(AbstractPrototypeIdArraySerializer<WaypointerPrototype>))]
|
||||
public string[]? Parents { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
[AbstractDataField, NeverPushInheritance]
|
||||
public bool Abstract { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the waypointer prototype.
|
||||
/// This is player facing, so it's different than ID
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public required string Name;
|
||||
|
||||
/// <summary>
|
||||
/// The components that decide which entities will be tracked by this waypointer.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public ComponentRegistry TrackedComponents = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The path to the rsi folder.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
public ResPath RsiPath;
|
||||
|
||||
/// <summary>
|
||||
/// This signifies how many states the waypointer has.
|
||||
/// These are used to show distance to the tracked target.
|
||||
/// Each rsi state needs to be named "marker" + number.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// The NTStationWaypointer has 5 states: marker1, marker2, marker3, marker4, marker5.
|
||||
/// </example>
|
||||
[DataField]
|
||||
public float WaypointerStates = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// The color of the waypointer.
|
||||
/// Only works on properly grey-scaled textures.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Color? Color;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the waypointer is active on grid.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool WorkOnGrid;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the waypointer is active when the entity is in combat.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool WorkInCombat;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum range to where the pinpointer can track something.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int MaxRange = 200;
|
||||
|
||||
/// <summary>
|
||||
/// The whitelist that the entity needs to fulfill to be tracked.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityWhitelist? Whitelist;
|
||||
|
||||
/// <summary>
|
||||
/// The whitelist that the entity needs to fail to be tracked.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityWhitelist? Blacklist;
|
||||
|
||||
/// <summary>
|
||||
/// The RSI path to the icons for the radial menu.
|
||||
/// It requires both an on and off state.
|
||||
/// The off state needs to be named "disable" and the on state "enable
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// For ease of adding more, there is a example cross picture in waypointer_action.rsi.
|
||||
/// You can copy and paste that over new enable icons to make a disable icon.
|
||||
/// </remarks>
|
||||
[DataField(required: true)]
|
||||
public ResPath RadialMenuIconPath;
|
||||
}
|
||||
|
|
@ -1,18 +1,4 @@
|
|||
Entries:
|
||||
- author: turtlemutt
|
||||
changes:
|
||||
- message: Add a new snack to the game, spicy pickle moffs!
|
||||
type: Add
|
||||
id: 1777
|
||||
time: '2025-11-02T05:28:33.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4425
|
||||
- author: SirWarock
|
||||
changes:
|
||||
- message: Rollerbed sprites now don't stack when a patient is buckled to it!
|
||||
type: Add
|
||||
id: 1778
|
||||
time: '2025-11-02T05:44:53.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/4521
|
||||
- author: HTMLSystem
|
||||
changes:
|
||||
- message: Added arachnid and moth sprites for the night vision and thermal goggles
|
||||
|
|
@ -4418,4 +4404,21 @@
|
|||
id: 2277
|
||||
time: '2026-05-09T22:19:48.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5738
|
||||
- author: Cepelinas1
|
||||
changes:
|
||||
- message: "In an effort to save money on tear gas grenade production, Security\
|
||||
\ can now choose up to 4 items for their secbelt in the character loadout under\
|
||||
\ the \u201CUtility\u201D section! Remember to actually choose what you want,\
|
||||
\ unless you want to go in with just a baton and cuffs."
|
||||
type: Add
|
||||
id: 2278
|
||||
time: '2026-05-09T23:04:26.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5701
|
||||
- author: Stxcking
|
||||
changes:
|
||||
- message: Added Water Wall Dispenser
|
||||
type: Add
|
||||
id: 2279
|
||||
time: '2026-05-10T11:35:15.0000000+00:00'
|
||||
url: https://github.com/DeltaV-Station/Delta-v/pull/5792
|
||||
Order: 1
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ loadout-group-all-gun = Security Sidearm
|
|||
loadout-group-security-gun-ammo = Ammunition
|
||||
loadout-group-revolver-ammo = Ammunition
|
||||
loadout-group-all-ammo = Ammunition
|
||||
security-utility = Utility
|
||||
|
||||
# Justice
|
||||
loadout-group-chiefjustice-head = Chief Justice head
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
waypointer-disable-all = Disable waypointer system
|
||||
waypointer-enable-all = Enable waypointer system
|
||||
waypointer-disable = Disable the {$waypointer}
|
||||
waypointer-enable = Enable the {$waypointer}
|
||||
|
|
@ -123,6 +123,11 @@
|
|||
radius: 5
|
||||
energy: 2
|
||||
color: "#00ffff"
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
- type: Tag
|
||||
tags:
|
||||
- CorgiWearable
|
||||
|
|
|
|||
|
|
@ -232,6 +232,13 @@
|
|||
- type: PressureProtection
|
||||
highPressureMultiplier: 0.72
|
||||
lowPressureMultiplier: 1000
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- WreckWaypointer
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
- type: Tag
|
||||
tags:
|
||||
- CorgiWearable
|
||||
|
|
@ -254,6 +261,13 @@
|
|||
- type: PointLight
|
||||
radius: 7
|
||||
energy: 3
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- WreckWaypointer
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
- type: Tag
|
||||
tags:
|
||||
- CorgiWearable
|
||||
|
|
@ -320,6 +334,13 @@
|
|||
- type: PressureProtection
|
||||
highPressureMultiplier: 0.72
|
||||
lowPressureMultiplier: 1000
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- WreckWaypointer
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
- type: Tag
|
||||
tags:
|
||||
- CorgiWearable
|
||||
|
|
@ -371,6 +392,12 @@
|
|||
Slash: 0.9
|
||||
Piercing: 0.9
|
||||
Heat: 0.9
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
- type: Tag
|
||||
tags:
|
||||
- CorgiWearable
|
||||
|
|
@ -425,6 +452,12 @@
|
|||
Slash: 0.9
|
||||
Piercing: 0.9
|
||||
Heat: 0.9
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#Captain's Hardsuit
|
||||
- type: entity
|
||||
|
|
@ -444,6 +477,12 @@
|
|||
tags:
|
||||
- CorgiWearable
|
||||
- WhitelistChameleon
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#Chief Engineer's Hardsuit
|
||||
- type: entity
|
||||
|
|
@ -599,6 +638,12 @@
|
|||
Slash: 0.9
|
||||
Piercing: 0.9
|
||||
Heat: 0.9
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#Luxury Mining Hardsuit
|
||||
- type: entity
|
||||
|
|
@ -618,6 +663,13 @@
|
|||
- type: PointLight
|
||||
radius: 7
|
||||
energy: 3
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- WreckWaypointer
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#ANTAG HARDSUITS
|
||||
#Blood-red Hardsuit
|
||||
|
|
@ -892,6 +944,12 @@
|
|||
Slash: 0.9
|
||||
Piercing: 0.9
|
||||
Heat: 0.9
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#ERT Chaplain Hardsuit
|
||||
- type: entity
|
||||
|
|
@ -914,6 +972,10 @@
|
|||
- type: GuideHelp
|
||||
guides:
|
||||
- Psionics
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions
|
||||
|
||||
#ERT Engineer Hardsuit
|
||||
|
|
@ -938,6 +1000,12 @@
|
|||
Slash: 0.9
|
||||
Piercing: 0.9
|
||||
Heat: 0.9
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#ERT Medical Hardsuit
|
||||
- type: entity
|
||||
|
|
@ -952,6 +1020,12 @@
|
|||
sprite: Clothing/Head/Hardsuits/ERThelmets/ertmedical.rsi
|
||||
- type: PointLight
|
||||
color: "#adffec"
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#ERT Security Hardsuit
|
||||
- type: entity
|
||||
|
|
@ -973,6 +1047,12 @@
|
|||
Slash: 0.9
|
||||
Piercing: 0.9
|
||||
Heat: 0.9
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#ERT Janitor Hardsuit
|
||||
- type: entity
|
||||
|
|
@ -987,6 +1067,12 @@
|
|||
sprite: Clothing/Head/Hardsuits/ERThelmets/ertjanitor.rsi
|
||||
- type: PointLight
|
||||
color: "#cbadff"
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#CBURN Hardsuit
|
||||
- type: entity
|
||||
|
|
@ -1063,6 +1149,12 @@
|
|||
Heat: 0.80
|
||||
Radiation: 0.80
|
||||
Caustic: 0.95
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
# End DeltaV Additions - Add Waypointers
|
||||
|
||||
#MISC. HARDSUITS
|
||||
#Clown Hardsuit
|
||||
|
|
|
|||
|
|
@ -175,6 +175,12 @@
|
|||
speedModifier: 2.5 # fast because dragon strong
|
||||
useSound:
|
||||
path: /Audio/Items/crowbar.ogg
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
- type: InnateWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- DragonRiftWaypointer
|
||||
# Begin DeltaV Additions - Add Waypointers
|
||||
|
||||
- type: entity
|
||||
parent: BaseMobDragon
|
||||
|
|
|
|||
|
|
@ -48,3 +48,4 @@
|
|||
- type: NpcFactionMember
|
||||
factions:
|
||||
- Dragon # prevent shitter carp from destroying rifts
|
||||
- type: WaypointerTrackable # DeltaV - Added Waypointers
|
||||
|
|
|
|||
|
|
@ -86,12 +86,12 @@
|
|||
- type: loadout
|
||||
id: SecurityBelt
|
||||
equipment:
|
||||
belt: ClothingBeltSecurityFilled
|
||||
belt: ClothingBeltSecurityBeltCustom # DeltaV - loadouts
|
||||
|
||||
- type: loadout
|
||||
id: SecurityWebbing
|
||||
equipment:
|
||||
belt: ClothingBeltSecurityWebbingFilled
|
||||
belt: ClothingBeltSecurityWebbingCustom # DeltaV - loadouts
|
||||
|
||||
# Outerclothing
|
||||
- type: loadout
|
||||
|
|
|
|||
|
|
@ -413,6 +413,7 @@
|
|||
- GroupSpeciesBreathToolSecurity
|
||||
- SecurityAllFirearm # DeltaV - loadouts
|
||||
- SecurityAllAmmo # DeltaV - loadouts
|
||||
- SecurityUtility # DeltaV - loadouts
|
||||
|
||||
- type: roleLoadout
|
||||
id: JobWarden
|
||||
|
|
@ -432,6 +433,7 @@
|
|||
- GroupSpeciesBreathToolSecurity
|
||||
- SecurityAllFirearm # DeltaV - loadouts
|
||||
- SecurityAllAmmo # DeltaV - loadouts
|
||||
- SecurityUtility # DeltaV - loadouts
|
||||
|
||||
- type: roleLoadout
|
||||
id: JobSecurityOfficer
|
||||
|
|
@ -452,6 +454,7 @@
|
|||
- GroupSpeciesBreathToolSecurity
|
||||
- SecurityFirearm # DeltaV - loadouts
|
||||
- SecurityFirearmAmmo # DeltaV - loadouts
|
||||
- SecurityUtility # DeltaV - loadouts
|
||||
|
||||
- type: roleLoadout
|
||||
id: JobDetective
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
- GroupSpeciesBreathToolSecurity
|
||||
- SecurityFirearm # DeltaV - loadouts
|
||||
- SecurityFirearmAmmo # DeltaV - loadouts
|
||||
- SecurityUtility
|
||||
|
||||
# Wildcards
|
||||
- type: roleLoadout
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
- type: entity
|
||||
parent: BaseAction
|
||||
id: ActionManageWaypointers
|
||||
name: Manage Waypointers
|
||||
description: Manage the visibility of your waypointers.
|
||||
components:
|
||||
- type: Action
|
||||
toggled: true
|
||||
icon:
|
||||
sprite: _DV/Markers/Waypointers/waypointer_action.rsi
|
||||
state: action_icon_off
|
||||
iconOn:
|
||||
sprite: _DV/Markers/Waypointers/waypointer_action.rsi
|
||||
state: action_icon_on
|
||||
- type: InstantAction
|
||||
event: !type:ActionManageWaypointersEvent
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
enum.WaypointerUiKey.Key:
|
||||
type: WaypointerMenuBoundUserinterface
|
||||
|
|
@ -25,6 +25,30 @@
|
|||
- id: SyringeEphedrine
|
||||
- id: EmergencyMedipen
|
||||
|
||||
- type: entity
|
||||
id: ClothingBeltSecurityBeltCustom
|
||||
parent: ClothingBeltSecurity
|
||||
suffix: Filled
|
||||
components:
|
||||
- type: EntityTableContainerFill
|
||||
containers:
|
||||
storagebase: !type:AllSelector
|
||||
children:
|
||||
- id: Stunbaton
|
||||
- id: Handcuffs
|
||||
|
||||
- type: entity
|
||||
id: ClothingBeltSecurityWebbingCustom
|
||||
parent: ClothingBeltSecurityWebbing
|
||||
suffix: Filled
|
||||
components:
|
||||
- type: EntityTableContainerFill
|
||||
containers:
|
||||
storagebase: !type:AllSelector
|
||||
children:
|
||||
- id: Stunbaton
|
||||
- id: Handcuffs
|
||||
|
||||
- type: entity
|
||||
id: ClothingBeltFoamSheathFilled
|
||||
parent: ClothingBeltFoamSheath
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
sprite: _DV/Clothing/Head/Hardsuits/Combat/officer.rsi
|
||||
- type: Clothing
|
||||
sprite: _DV/Clothing/Head/Hardsuits/Combat/officer.rsi
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
|
||||
# Medical Combat Hardsuits
|
||||
- type: entity
|
||||
|
|
@ -65,6 +69,10 @@
|
|||
sprite: _DV/Clothing/Head/Hardsuits/Combat/corpsman.rsi
|
||||
- type: Clothing
|
||||
sprite: _DV/Clothing/Head/Hardsuits/Combat/corpsman.rsi
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
|
||||
# Riot Combat Hardsuits
|
||||
- type: entity
|
||||
|
|
@ -99,6 +107,10 @@
|
|||
sprite: _DV/Clothing/Head/Hardsuits/Combat/warden.rsi
|
||||
- type: Clothing
|
||||
sprite: _DV/Clothing/Head/Hardsuits/Combat/warden.rsi
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
|
||||
# Advanced Combat Hardsuits
|
||||
- type: entity
|
||||
|
|
@ -135,6 +147,10 @@
|
|||
sprite: _DV/Clothing/Head/Hardsuits/Combat/hos.rsi
|
||||
- type: Clothing
|
||||
sprite: _DV/Clothing/Head/Hardsuits/Combat/hos.rsi
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
|
||||
#Roboneuroticist Helmet
|
||||
- type: entity
|
||||
|
|
@ -189,6 +205,10 @@
|
|||
Slash: 0.9
|
||||
Piercing: 0.9
|
||||
Heat: 0.9
|
||||
- type: ClothingShowWaypointer
|
||||
waypointerProtoIds:
|
||||
- NTStationWaypointer
|
||||
- TradeStationWaypointer
|
||||
|
||||
#ERT Chaplain Hardsuit
|
||||
- type: entity
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
- type: ToggleableClothing
|
||||
clothingPrototype: ClothingHeadHelmetHardsuitCombatOfficer
|
||||
|
||||
|
||||
# Medical Combat Hardsuits
|
||||
- type: entity
|
||||
parent: ClothingOuterHardsuitCombatStandard
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
- type: entity
|
||||
parent: BaseDispenser
|
||||
id: WaterDispenser
|
||||
name: water dispenser
|
||||
description: Wallmount water dispenser.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: _DV/Structures/Wallmounts/walldispenser.rsi
|
||||
layers:
|
||||
- state: waterdispenser
|
||||
- state: fill-1
|
||||
map: ["enum.SolutionContainerLayers.Fill"]
|
||||
visible: false
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 5
|
||||
fillBaseName: fill-
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
tank:
|
||||
maxVol: 5000
|
||||
reagents:
|
||||
- ReagentId: Water
|
||||
Quantity: 5000
|
||||
|
|
@ -145,3 +145,47 @@
|
|||
id: SecurityClothingHandsGlovesFingerless
|
||||
equipment:
|
||||
gloves: ClothingHandsGlovesFingerless
|
||||
|
||||
# SecBelt utility
|
||||
|
||||
- type: loadout
|
||||
id: FlashBangLoadout
|
||||
storage:
|
||||
belt:
|
||||
- GrenadeFlashBang
|
||||
|
||||
- type: loadout
|
||||
id: TearGasLoadout
|
||||
storage:
|
||||
belt:
|
||||
- TearGasGrenade
|
||||
|
||||
- type: loadout
|
||||
id: SecHoloProjectorLoadout
|
||||
storage:
|
||||
belt:
|
||||
- HoloprojectorSecurity
|
||||
|
||||
- type: loadout
|
||||
id: StingerGrenadeLoadout
|
||||
storage:
|
||||
belt:
|
||||
- GrenadeStinger
|
||||
|
||||
- type: loadout
|
||||
id: RadioHandheldSecurityLoadout
|
||||
storage:
|
||||
belt:
|
||||
- RadioHandheldSecurity
|
||||
|
||||
- type: loadout
|
||||
id: HandcuffsLoadout
|
||||
storage:
|
||||
belt:
|
||||
- Handcuffs
|
||||
|
||||
- type: loadout
|
||||
id: SecLiteLoadout
|
||||
storage:
|
||||
belt:
|
||||
- FlashlightSeclite
|
||||
|
|
|
|||
|
|
@ -414,6 +414,21 @@
|
|||
- SecurityFirearmSpeedLoaderSpecialRubber
|
||||
- SecurityFirearmSpeedLoaderSpecial
|
||||
|
||||
## Security utility
|
||||
- type: loadoutGroup
|
||||
id: SecurityUtility
|
||||
name: security-utility
|
||||
minLimit: 0
|
||||
maxLimit: 4
|
||||
loadouts:
|
||||
- FlashBangLoadout
|
||||
- TearGasLoadout
|
||||
- StingerGrenadeLoadout
|
||||
- RadioHandheldSecurityLoadout
|
||||
- SecHoloProjectorLoadout
|
||||
- HandcuffsLoadout
|
||||
- SecLiteLoadout
|
||||
|
||||
## Security Gloves
|
||||
- type: loadoutGroup
|
||||
id: SecurityGloves
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# If you add a new waypointer, you'll need to add the "WaypointerTrackable" component to every entity that you want to be tracked EXCEPT grids.
|
||||
# Why not grids? As Todd Howard would say, they just work.
|
||||
|
||||
- type: waypointer
|
||||
abstract: true
|
||||
id: BaseWaypointer
|
||||
rsiPath: _DV/Markers/Waypointers/waypointer.rsi
|
||||
waypointerStates: 5
|
||||
color: White
|
||||
|
||||
- type: waypointer
|
||||
parent: BaseWaypointer
|
||||
id: NTStationWaypointer
|
||||
name: Station Waypointer
|
||||
trackedComponents:
|
||||
- type: StationData
|
||||
color: Blue
|
||||
radialMenuIconPath: _DV/Markers/Waypointers/station_waypointer.rsi
|
||||
|
||||
- type: waypointer
|
||||
parent: BaseWaypointer
|
||||
id: TradeStationWaypointer
|
||||
name: Trade Station Waypointer
|
||||
trackedComponents:
|
||||
- type: TradeStation
|
||||
color: Green
|
||||
radialMenuIconPath: _DV/Markers/Waypointers/trade_station_waypointer.rsi
|
||||
|
||||
- type: waypointer
|
||||
parent: BaseWaypointer
|
||||
id: WreckWaypointer
|
||||
name: Wreck Waypointer
|
||||
trackedComponents:
|
||||
- type: MapGrid
|
||||
blacklist:
|
||||
components:
|
||||
- StationData
|
||||
- TradeStation
|
||||
- EscapePod
|
||||
color: Orange
|
||||
maxRange: 50
|
||||
radialMenuIconPath: _DV/Markers/Waypointers/wreck_waypointer.rsi
|
||||
|
||||
- type: waypointer
|
||||
parent: BaseWaypointer
|
||||
id: DragonRiftWaypointer
|
||||
name: Rift Waypointer
|
||||
trackedComponents:
|
||||
- type: DragonRift
|
||||
workOnGrid: true
|
||||
color: Red
|
||||
maxRange: 50
|
||||
radialMenuIconPath: _DV/Markers/Waypointers/rift_waypointer.rsi
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1023 B |
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Cross made by SirWarock on Github, the carp rift: https://github.com/tgstation/tgstation/blob/19da0cee1869bad0186d54d6bcd8a55ed30b9db6/icons/obj/carp_rift.dmi",
|
||||
"states": [
|
||||
{
|
||||
"name": "enable"
|
||||
},
|
||||
{
|
||||
"name": "disable"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 440 B |
|
After Width: | Height: | Size: 303 B |
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "SirWarock on Github",
|
||||
"states": [
|
||||
{
|
||||
"name": "enable"
|
||||
},
|
||||
{
|
||||
"name": "disable"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 513 B |
|
After Width: | Height: | Size: 433 B |
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "SirWarock on Github",
|
||||
"states": [
|
||||
{
|
||||
"name": "enable"
|
||||
},
|
||||
{
|
||||
"name": "disable"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 191 B |
|
After Width: | Height: | Size: 178 B |
|
After Width: | Height: | Size: 165 B |
|
After Width: | Height: | Size: 141 B |
|
After Width: | Height: | Size: 128 B |
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 64,
|
||||
"y": 64
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "SirWarock on Github",
|
||||
"states": [
|
||||
{
|
||||
"name": "marker1"
|
||||
},
|
||||
{
|
||||
"name": "marker2"
|
||||
},
|
||||
{
|
||||
"name": "marker3"
|
||||
},
|
||||
{
|
||||
"name": "marker4"
|
||||
},
|
||||
{
|
||||
"name": "marker5"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 162 B |
|
After Width: | Height: | Size: 260 B |
|
After Width: | Height: | Size: 253 B |
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "SirWarock on Github",
|
||||
"states": [
|
||||
{
|
||||
"name": "action_icon_off"
|
||||
},
|
||||
{
|
||||
"name": "action_icon_on"
|
||||
},
|
||||
{
|
||||
"name": "cross"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 513 B |
|
After Width: | Height: | Size: 433 B |
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "SirWarock on Github",
|
||||
"states": [
|
||||
{
|
||||
"name": "enable"
|
||||
},
|
||||
{
|
||||
"name": "disable"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 568 B |
|
After Width: | Height: | Size: 595 B |
|
After Width: | Height: | Size: 599 B |
|
After Width: | Height: | Size: 619 B |
|
After Width: | Height: | Size: 649 B |
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Modifications made by [scrivoy], Dispenser originally taken from paradise at https://github.com/ParadiseSS13/Paradise/commit/846ce475b2258a4336d8895f07f2c0f4053963bc, waterdispenser by @Stxcking (github)",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "waterdispenser"
|
||||
},
|
||||
{
|
||||
"name": "fill-1"
|
||||
},
|
||||
{
|
||||
"name": "fill-2"
|
||||
},
|
||||
{
|
||||
"name": "fill-3"
|
||||
},
|
||||
{
|
||||
"name": "fill-4"
|
||||
},
|
||||
{
|
||||
"name": "fill-5"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 737 B |