Coordinates Disks & Shuttle FTL Travel (#23240)

* Adds the CentComm Disk and configures it to work with direct-use shuttles

* Added functionality for drone shuttles (i.e. cargo shuttle)

* Adds support for pods, and a disk console object for disks to be inserted into. Also sprites.

* Added the disk to HoP's locker

* Removed leftover logs & comments

* Fix for integration test

* Apply suggestions from code review (formatting & proper DataField)

Co-authored-by: 0x6273 <0x40@keemail.me>

* Fix integration test & changes based on code review

* Includes Disk Cases to contain Coordinate Disks, which are now CDs instead of Floppy Disks

* Check pods & non-evac shuttles for CentCom travel, even in FTL

* Import

* Remove CentCom travel restrictions & pod disk consoles

* Major changes that changes the coordinates disk system to work with salvage expeditions

* Missed CC diskcase removal

* Fix build

* Review suggestions and changes

* Major additional changes after merge

* Minor tag miss

* Integration test fix

* review

---------

Co-authored-by: 0x6273 <0x40@keemail.me>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
SlamBamActionman
2024-04-01 06:50:00 +02:00
committed by GitHub
parent cc35f16839
commit bed9e9ac6a
24 changed files with 217 additions and 23 deletions

View File

@@ -263,9 +263,10 @@ public sealed partial class MapScreen : BoxContainer
while (mapComps.MoveNext(out var mapComp, out var mapXform, out var mapMetadata))
{
if (!_shuttles.CanFTLTo(_shuttleEntity.Value, mapComp.MapId))
if (_console != null && !_shuttles.CanFTLTo(_shuttleEntity.Value, mapComp.MapId, _console.Value))
{
continue;
}
var mapName = mapMetadata.EntityName;
if (string.IsNullOrEmpty(mapName))
@@ -310,7 +311,6 @@ public sealed partial class MapScreen : BoxContainer
};
_mapHeadings.Add(mapComp.MapId, gridContents);
foreach (var grid in _mapManager.GetAllMapGrids(mapComp.MapId))
{
_entManager.TryGetComponent(grid.Owner, out IFFComponent? iffComp);
@@ -327,8 +327,8 @@ public sealed partial class MapScreen : BoxContainer
{
AddMapObject(mapComp.MapId, gridObj);
}
else if (iffComp == null ||
(iffComp.Flags & IFFFlags.Hide) == 0x0)
else if (!_shuttles.IsBeaconMap(_mapManager.GetMapEntityId(mapComp.MapId)) && (iffComp == null ||
(iffComp.Flags & IFFFlags.Hide) == 0x0))
{
_pendingMapObjects.Add((mapComp.MapId, gridObj));
}

View File

@@ -1,10 +1,16 @@
using Content.Shared.Shuttles.Components;
using Content.Shared.Procedural;
using Content.Shared.Salvage.Expeditions;
using Content.Shared.Dataset;
using Robust.Shared.Prototypes;
namespace Content.Server.Salvage;
public sealed partial class SalvageSystem
{
[ValidatePrototypeId<EntityPrototype>]
public const string CoordinatesDisk = "CoordinatesDisk";
private void OnSalvageClaimMessage(EntityUid uid, SalvageExpeditionConsoleComponent component, ClaimSalvageMessage args)
{
var station = _station.GetOwningStation(uid);
@@ -15,11 +21,16 @@ public sealed partial class SalvageSystem
if (!data.Missions.TryGetValue(args.Index, out var missionparams))
return;
SpawnMission(missionparams, station.Value);
var cdUid = Spawn(CoordinatesDisk, Transform(uid).Coordinates);
SpawnMission(missionparams, station.Value, cdUid);
data.ActiveMission = args.Index;
var mission = GetMission(_prototypeManager.Index<SalvageDifficultyPrototype>(missionparams.Difficulty), missionparams.Seed);
data.NextOffer = _timing.CurTime + mission.Duration + TimeSpan.FromSeconds(1);
_labelSystem.Label(cdUid, GetFTLName(_prototypeManager.Index<DatasetPrototype>("names_borer"), missionparams.Seed));
_audio.PlayPvs(component.PrintSound, uid);
UpdateConsoles((station.Value, data));
}

View File

@@ -8,6 +8,7 @@ using Content.Shared.Salvage.Expeditions;
using Robust.Shared.CPUJob.JobQueues;
using Robust.Shared.CPUJob.JobQueues.Queues;
using Robust.Shared.GameStates;
using Robust.Shared.Map;
namespace Content.Server.Salvage;
@@ -148,7 +149,7 @@ public sealed partial class SalvageSystem
return new SalvageExpeditionConsoleState(component.NextOffer, component.Claimed, component.Cooldown, component.ActiveMission, missions);
}
private void SpawnMission(SalvageMissionParams missionParams, EntityUid station)
private void SpawnMission(SalvageMissionParams missionParams, EntityUid station, EntityUid? coordinatesDisk)
{
var cancelToken = new CancellationTokenSource();
var job = new SpawnSalvageMissionJob(
@@ -162,7 +163,9 @@ public sealed partial class SalvageSystem
_biome,
_dungeon,
_metaData,
_transform,
station,
coordinatesDisk,
missionParams,
cancelToken.Token);

View File

@@ -32,6 +32,7 @@ using Robust.Shared.Audio;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Map.Components;
using Robust.Shared.Timing;
using Content.Server.Labels;
namespace Content.Server.Salvage
{
@@ -39,6 +40,7 @@ namespace Content.Server.Salvage
{
[Dependency] private readonly IChatManager _chat = default!;
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
[Dependency] private readonly IEntityManager _entManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ILogManager _logManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
@@ -48,6 +50,7 @@ namespace Content.Server.Salvage
[Dependency] private readonly BiomeSystem _biome = default!;
[Dependency] private readonly DungeonSystem _dungeon = default!;
[Dependency] private readonly GravitySystem _gravity = default!;
[Dependency] private readonly LabelSystem _labelSystem = default!;
[Dependency] private readonly MapLoaderSystem _map = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly RadioSystem _radioSystem = default!;

View File

@@ -33,6 +33,9 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Content.Server.Shuttles.Components;
using Content.Shared.Coordinates;
using Content.Shared.Shuttles.Components;
namespace Content.Server.Salvage;
@@ -46,8 +49,10 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
private readonly BiomeSystem _biome;
private readonly DungeonSystem _dungeon;
private readonly MetaDataSystem _metaData;
private readonly SharedTransformSystem _xforms;
public readonly EntityUid Station;
public readonly EntityUid? CoordinatesDisk;
private readonly SalvageMissionParams _missionParams;
private readonly ISawmill _sawmill;
@@ -63,7 +68,9 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
BiomeSystem biome,
DungeonSystem dungeon,
MetaDataSystem metaData,
SharedTransformSystem xform,
EntityUid station,
EntityUid? coordinatesDisk,
SalvageMissionParams missionParams,
CancellationToken cancellation = default) : base(maxTime, cancellation)
{
@@ -75,7 +82,9 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
_biome = biome;
_dungeon = dungeon;
_metaData = metaData;
_xforms = xform;
Station = station;
CoordinatesDisk = coordinatesDisk;
_missionParams = missionParams;
_sawmill = logManager.GetSawmill("salvage_job");
#if !DEBUG
@@ -94,6 +103,18 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
var random = new Random(_missionParams.Seed);
var destComp = _entManager.AddComponent<FTLDestinationComponent>(mapUid);
destComp.BeaconsOnly = true;
destComp.RequireCoordinateDisk = true;
destComp.Enabled = true;
_metaData.SetEntityName(mapUid, SharedSalvageSystem.GetFTLName(_prototypeManager.Index<DatasetPrototype>("names_borer"), _missionParams.Seed));
_entManager.AddComponent<FTLBeaconComponent>(mapUid);
// Saving the mission mapUid to a CD is made optional, in case one is somehow made in a process without a CD entity
if (CoordinatesDisk.HasValue)
{
var cd = _entManager.EnsureComponent<ShuttleDestinationCoordinatesComponent>(CoordinatesDisk.Value);
cd.Destination = mapUid;
_entManager.Dirty(CoordinatesDisk.Value, cd);
}
// Setup mission configs
// As we go through the config the rating will deplete so we'll go for most important to least important.
@@ -144,11 +165,6 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
expedition.EndTime = _timing.CurTime + mission.Duration;
expedition.MissionParams = _missionParams;
// Don't want consoles to have the incorrect name until refreshed.
var ftlUid = _entManager.CreateEntityUninitialized("FTLPoint", new EntityCoordinates(mapUid, grid.TileSizeHalfVector));
_metaData.SetEntityName(ftlUid, SharedSalvageSystem.GetFTLName(_prototypeManager.Index<DatasetPrototype>("names_borer"), _missionParams.Seed));
_entManager.InitializeAndStartEntity(ftlUid);
var landingPadRadius = 24;
var minDungeonOffset = landingPadRadius + 4;

View File

@@ -9,7 +9,7 @@ namespace Content.Server.Shuttles.Components;
[RegisterComponent, Access(typeof(EmergencyShuttleSystem)), AutoGenerateComponentPause]
public sealed partial class EscapePodComponent : Component
{
[DataField("launchTime", customTypeSerializer:typeof(TimeOffsetSerializer))]
[DataField(customTypeSerializer:typeof(TimeOffsetSerializer))]
[AutoPausedField]
public TimeSpan? LaunchTime;
}

View File

@@ -14,5 +14,11 @@ namespace Content.Server.Shuttles.Components
/// </summary>
[DataField("zoom")]
public Vector2 Zoom = new(1.5f, 1.5f);
/// <summary>
/// Should this console have access to restricted FTL destinations?
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField("whitelistSpecific")]
public List<EntityUid> FTLWhitelist = new List<EntityUid>();
}
}

View File

@@ -44,6 +44,10 @@ public sealed partial class ShuttleConsoleSystem
}
var nCoordinates = new NetCoordinates(GetNetEntity(targetXform.ParentUid), targetXform.LocalPosition);
if (targetXform.ParentUid == EntityUid.Invalid)
{
nCoordinates = new NetCoordinates(GetNetEntity(beaconEnt), targetXform.LocalPosition);
}
// Check target exists
if (!_shuttle.CanFTLBeacon(nCoordinates))
@@ -128,7 +132,7 @@ public sealed partial class ShuttleConsoleSystem
}
// Check shuttle can FTL to this target.
if (!_shuttle.CanFTLTo(shuttleUid.Value, targetMap))
if (!_shuttle.CanFTLTo(shuttleUid.Value, targetMap, ent))
{
return;
}

View File

@@ -1,4 +1,5 @@
using Content.Shared.Salvage.Expeditions.Modifiers;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
@@ -30,7 +31,11 @@ public sealed class SalvageExpeditionConsoleState : BoundUserInterfaceState
[RegisterComponent, NetworkedComponent]
public sealed partial class SalvageExpeditionConsoleComponent : Component
{
/// <summary>
/// The sound made when spawning a coordinates disk
/// </summary>
[DataField]
public SoundSpecifier PrintSound = new SoundPathSpecifier("/Audio/Machines/terminal_insert_disc.ogg");
}
[Serializable, NetSerializable]

View File

@@ -23,4 +23,10 @@ public sealed partial class FTLDestinationComponent : Component
/// </summary>
[DataField, AutoNetworkedField]
public bool BeaconsOnly;
/// <summary>
/// Shuttles must use a corresponding CD to travel to this location.
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public bool RequireCoordinateDisk = false;
}

View File

@@ -9,7 +9,7 @@ namespace Content.Shared.Shuttles.Components
[NetworkedComponent]
public abstract partial class SharedShuttleConsoleComponent : Component
{
public static string DiskSlotName = "disk_slot";
}
[Serializable, NetSerializable]

View File

@@ -0,0 +1,15 @@
namespace Content.Shared.Shuttles.Components;
using Robust.Shared.GameStates;
/// <summary>
/// Enables a shuttle to travel to a destination with an item inserted into its console
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class ShuttleDestinationCoordinatesComponent : Component
{
/// <summary>
/// Uid for entity containing the FTLDestination component
/// </summary>
[ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField]
public EntityUid? Destination;
}

View File

@@ -1,3 +1,4 @@
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Shuttles.BUIStates;
using Content.Shared.Shuttles.Components;
using Content.Shared.Shuttles.UI.MapObjects;
@@ -11,6 +12,7 @@ namespace Content.Shared.Shuttles.Systems;
public abstract partial class SharedShuttleSystem : EntitySystem
{
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly ItemSlotsSystem _itemSlots = default!;
[Dependency] protected readonly SharedMapSystem Maps = default!;
[Dependency] protected readonly SharedTransformSystem XformSystem = default!;
@@ -34,7 +36,7 @@ public abstract partial class SharedShuttleSystem : EntitySystem
/// <summary>
/// Returns whether an entity can FTL to the specified map.
/// </summary>
public bool CanFTLTo(EntityUid shuttleUid, MapId targetMap)
public bool CanFTLTo(EntityUid shuttleUid, MapId targetMap, EntityUid consoleUid)
{
var mapUid = _mapManager.GetMapEntityId(targetMap);
var shuttleMap = _xformQuery.GetComponent(shuttleUid).MapID;
@@ -42,12 +44,42 @@ public abstract partial class SharedShuttleSystem : EntitySystem
if (shuttleMap == targetMap)
return true;
if (!TryComp<FTLDestinationComponent>(mapUid, out var destination) ||
!destination.Enabled)
if (!TryComp<FTLDestinationComponent>(mapUid, out var destination) || !destination.Enabled)
return false;
if (destination.RequireCoordinateDisk)
{
if (!TryComp<ItemSlotsComponent>(consoleUid, out var slot))
{
return false;
}
if (!_itemSlots.TryGetSlot(consoleUid, SharedShuttleConsoleComponent.DiskSlotName, out var itemSlot, component: slot) || !itemSlot.HasItem)
{
return false;
}
if (itemSlot.Item is { Valid: true } disk)
{
ShuttleDestinationCoordinatesComponent? diskCoordinates = null;
if (!Resolve(disk, ref diskCoordinates))
{
return false;
}
var diskCoords = diskCoordinates.Destination;
if (diskCoords == null || !TryComp<FTLDestinationComponent>(diskCoords.Value, out var diskDestination) || diskDestination != destination)
{
return false;
}
}
else
{
return false;
}
}
if (HasComp<FTLMapComponent>(mapUid))
return false;

View File

@@ -0,0 +1,19 @@
- type: entity
name: coordinates disk
parent: BaseItem
id: CoordinatesDisk
description: A disk containing the coordinates to a location in space. Necessary for any FTL-traversing vessel to reach their destination. Fits inside shuttle consoles.
components:
- type: Sprite
sprite: Objects/Misc/cd.rsi
state: icon
- type: StaticPrice
price: 100
- type: Tag
tags:
- CoordinatesDisk
- type: DamageOtherOnHit
damage:
types:
Slash: 1
- type: ShuttleDestinationCoordinates

View File

@@ -0,0 +1,21 @@
- type: entity
name: diskcase
parent: BaseStorageItem
id: DiskCase
description: Case for storing a coordinates disk.
components:
- type: Sprite
sprite: Objects/Misc/diskcases.rsi
state: icon_base
- type: Storage
grid:
- 0,0,0,1
maxItemSize: Normal
whitelist:
tags:
- Document
- CoordinatesDisk
storageOpenSound: /Audio/Machines/screwdriveropen.ogg
storageCloseSound: /Audio/Machines/screwdriverclose.ogg
storageInsertSound: /Audio/Items/crowbar.ogg
storageRemoveSound: /Audio/Items/crowbar.ogg

View File

@@ -63,6 +63,22 @@
color: "#43ccb5"
- type: Rotatable
rotateWhileAnchored: true
- type: ItemSlots
slots:
disk_slot:
name: Disk
insertSound:
path: /Audio/Machines/terminal_insert_disc.ogg
ejectSound:
path: /Audio/Machines/terminal_insert_disc.ogg
whitelist:
components:
- ShuttleDestinationCoordinates
- type: ContainerContainer
containers:
board: !type:Container
ents: []
disk_slot: !type:ContainerSlot {}
- type: entity
parent: BaseComputerShuttle

View File

@@ -418,6 +418,9 @@
- type: Tag
id: ConveyorAssembly
- type: Tag
id: CoordinatesDisk
- type: Tag #Ohioans die happy
id: Corn

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

View File

@@ -0,0 +1,14 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Made by SlamBamActionman",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

View File

@@ -0,0 +1,20 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Made by SlamBamActionman",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon_base"
},
{
"name": "icon_cc"
},
{
"name": "icon_cargo"
}
]
}