Compare commits

...

10 Commits

Author SHA1 Message Date
Sir Warock 4c691d4ab8
Merge 1754917204 into c3c6a6abd9 2026-05-10 11:43:49 +00:00
Delta-V bot c3c6a6abd9 Automatic changelog update 2026-05-10 13:35:34 +02:00
Stxcking 6f0ad0c181
New: Wallmount Water Dispenser (#5792)
Everything
2026-05-10 13:35:15 +02:00
github-actions[bot] 7abc7a7b66
Update Credits (#5794)
Co-authored-by: DeltaV-Bot <github@deltav.gay>
2026-05-10 04:28:06 +02:00
Delta-V bot 7dc4c5f3fc Automatic changelog update 2026-05-10 01:04:45 +02:00
Cepelinas1 0400ffa8e3
Customizable sec belt/webbing inventory (#5701)
* first

* fix

* spacing

Signed-off-by: Cepelinas1 <kakelis01@gmail.com>

* forgot ftl

---------

Signed-off-by: Cepelinas1 <kakelis01@gmail.com>
2026-05-09 19:04:25 -04:00
Sir Warock 1754917204 Give DeltaV Variants Waypointers 2026-05-05 21:53:42 +02:00
Sir Warock ed737e7c3d Fix 2026-05-04 21:59:33 +02:00
pre-commit-ci[bot] 3138b508c7 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2026-05-03 21:20:43 +00:00
Sir Warock 1f94d1e9ba OneCommitOps
Co-Authored-By: beck-thompson <107373427+beck-thompson@users.noreply.github.com>
2026-05-03 23:16:12 +02:00
67 changed files with 1536 additions and 44 deletions

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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;

View File

@ -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.

View File

@ -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);
}
}
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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");
}

View File

@ -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!;
}

View File

@ -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!;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,
}

View File

@ -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;
}

View File

@ -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

File diff suppressed because one or more lines are too long

View File

@ -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

View File

@ -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}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -48,3 +48,4 @@
- type: NpcFactionMember
factions:
- Dragon # prevent shitter carp from destroying rifts
- type: WaypointerTrackable # DeltaV - Added Waypointers

View File

@ -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

View File

@ -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

View File

@ -44,6 +44,7 @@
- GroupSpeciesBreathToolSecurity
- SecurityFirearm # DeltaV - loadouts
- SecurityFirearmAmmo # DeltaV - loadouts
- SecurityUtility
# Wildcards
- type: roleLoadout

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -52,6 +52,7 @@
- type: ToggleableClothing
clothingPrototype: ClothingHeadHelmetHardsuitCombatOfficer
# Medical Combat Hardsuits
- type: entity
parent: ClothingOuterHardsuitCombatStandard

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1023 B

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 B