fish-station/Content.Shared/Shuttles/Systems/SharedShuttleSystem.cs
Vigers Ray d6c0a011b7 Merge remote-tracking branch 'space-wizards/master'
# Conflicts:
#	.github/workflows/publish.yml
#	Content.Client/Clothing/ClientClothingSystem.cs
#	Content.Client/Clothing/Systems/ChameleonClothingSystem.cs
#	Content.Client/Fax/UI/FaxWindow.xaml
#	Content.Client/Ghost/GhostSystem.cs
#	Content.Client/Holiday/HolidaySystem.cs
#	Content.Client/Humanoid/HumanoidAppearanceSystem.cs
#	Content.Client/Lobby/UI/Loadouts/LoadoutWindow.xaml.cs
#	Content.Client/Lobby/UI/LobbyGui.xaml
#	Content.Client/Lobby/UI/LobbyGui.xaml.cs
#	Content.Client/Mech/MechSystem.cs
#	Content.Client/Stealth/StealthSystem.cs
#	Content.Client/Weapons/Ranged/Systems/GunSystem.cs
#	Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs
#	Content.Server/Bed/BedSystem.cs
#	Content.Server/Body/Systems/BodySystem.cs
#	Content.Server/Body/Systems/RespiratorSystem.cs
#	Content.Server/Cargo/Systems/CargoSystem.Orders.cs
#	Content.Server/Communications/CommunicationsConsoleComponent.cs
#	Content.Server/EntityEffects/Effects/AreaReactionEffect.cs
#	Content.Server/EntityEffects/Effects/MakeSentient.cs
#	Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs
#	Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs
#	Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs
#	Content.Server/EntityEffects/Effects/PlantMutateGases.cs
#	Content.Server/Fluids/EntitySystems/AbsorbentSystem.cs
#	Content.Server/GameTicking/GameTicker.Spawning.cs
#	Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs
#	Content.Server/IoC/ServerContentIoC.cs
#	Content.Server/Nutrition/EntitySystems/FoodSystem.cs
#	Content.Server/Power/EntitySystems/PowerNetSystem.cs
#	Content.Server/Preferences/Managers/ServerPreferencesManager.cs
#	Content.Server/RoundEnd/RoundEndSystem.cs
#	Content.Server/Shuttles/Systems/EmergencyShuttleSystem.cs
#	Content.Server/Station/Systems/StationSpawningSystem.cs
#	Content.Server/VoiceMask/VoiceMaskSystem.cs
#	Content.Server/Weapons/Ranged/Systems/GunSystem.cs
#	Content.Shared/Bed/Components/HealOnBuckleComponent.cs
#	Content.Shared/Clothing/EntitySystems/ClothingSystem.cs
#	Content.Shared/EntityEffects/Effects/ExplosionReactionEffect.cs
#	Content.Shared/Inventory/InventorySystem.Relay.cs
#	Content.Shared/Item/ItemToggle/Components/ComponentTogglerComponent.cs
#	Content.Shared/Preferences/HumanoidCharacterProfile.cs
#	Content.Shared/Preferences/Loadouts/RoleLoadout.cs
#	Content.Shared/Weapons/Melee/SharedMeleeWeaponSystem.cs
#	Content.Shared/Wieldable/SharedWieldableSystem.cs
#	Resources/Audio/Machines/attributions.yml
#	Resources/Locale/en-US/_strings/atmos/plaque-component.ftl
#	Resources/Locale/en-US/_strings/chat/chat-channel.ftl
#	Resources/Locale/en-US/_strings/components/screen-component.ftl
#	Resources/Locale/en-US/_strings/inventory/components/slot-block-component.ftl
#	Resources/Locale/en-US/_strings/mass-media/news-discord.ftl
#	Resources/Locale/en-US/_strings/objectives/commands/stripall.ftl
#	Resources/Locale/en-US/_strings/salvage/job-board.ftl
#	Resources/Locale/en-US/_strings/ui/spray-painter-window.ftl
#	Resources/Locale/en-US/_strings/ui/turret-controls.ftl
#	Resources/Maps/_Sunrise/Station/box.yml
#	Resources/Prototypes/Access/misc.yml
#	Resources/Prototypes/Catalog/Fills/Boxes/emergency.yml
#	Resources/Prototypes/Catalog/Fills/Lockers/engineer.yml
#	Resources/Prototypes/Catalog/Fills/Lockers/heads.yml
#	Resources/Prototypes/Catalog/Fills/Lockers/service.yml
#	Resources/Prototypes/Catalog/Fills/Lockers/suit_storage.yml
#	Resources/Prototypes/Entities/Clothing/Head/helmets.yml
#	Resources/Prototypes/Entities/Clothing/Masks/masks.yml
#	Resources/Prototypes/Entities/Clothing/OuterClothing/hardsuits.yml
#	Resources/Prototypes/Entities/Markers/Spawners/mobs.yml
#	Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml
#	Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
#	Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml
#	Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml
#	Resources/Prototypes/Entities/Mobs/Player/dragon.yml
#	Resources/Prototypes/Entities/Mobs/Player/silicon.yml
#	Resources/Prototypes/Entities/Mobs/Species/arachnid.yml
#	Resources/Prototypes/Entities/Mobs/Species/moth.yml
#	Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml
#	Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml
#	Resources/Prototypes/LootTables/suspicion_loot_table.yml
#	Resources/Prototypes/Reagents/Consumable/Drink/drinks.yml
#	Resources/Prototypes/Reagents/medicine.yml
#	Resources/Prototypes/Recipes/Lathes/Packs/science.yml
#	Resources/Prototypes/Recipes/Lathes/medical.yml
#	Resources/Prototypes/SoundCollections/NukeMusic.yml
#	Resources/ServerInfo/Guidebook/Cargo/Salvage.xml
#	Resources/Textures/Clothing/Hands/Gloves/KnuckleDusters/brassknuckleduster.rsi/equipped-OUTERCLOTHING-reptilian.png
#	Resources/Textures/Clothing/OuterClothing/Hardsuits/basic.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/eva.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/eva_emergency.rsi/meta.json
#	Resources/Textures/Clothing/OuterClothing/Suits/eva_prisoner.rsi/meta.json
#	Resources/Textures/Effects/speech.rsi/alien3.png
#	Resources/Textures/Effects/speech.rsi/alienroyal3.png
#	Resources/Textures/Effects/speech.rsi/default3.png
#	Resources/Textures/Effects/speech.rsi/guardian3.png
#	Resources/Textures/Effects/speech.rsi/holo3.png
#	Resources/Textures/Effects/speech.rsi/lawyer3.png
#	Resources/Textures/Effects/speech.rsi/lizard3.png
#	Resources/Textures/Effects/speech.rsi/meta.json
#	Resources/Textures/Effects/speech.rsi/moth3.png
#	Resources/Textures/Effects/speech.rsi/robot3.png
#	Resources/Textures/Effects/speech.rsi/slime3.png
#	Resources/Textures/Effects/speech.rsi/spider3.png
#	Resources/Textures/Effects/speech.rsi/syndibot3.png
#	Resources/Textures/Interface/Misc/job_icons.rsi/meta.json
#	Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json
#	Resources/Textures/Mobs/Species/Reptilian/parts.rsi/head_f.png
#	Resources/Textures/Mobs/Species/Reptilian/parts.rsi/head_m.png
#	Resources/Textures/Objects/Misc/id_cards.rsi/meta.json
#	Resources/Textures/Structures/Doors/Airlocks/Glass/external.rsi/emergency_unlit.png
#	Resources/Textures/Structures/Piping/disposal.rsi/meta.json
#	Resources/Textures/Tiles/attributions.yml
#	Resources/Textures/Tiles/steel_dirty.png
#	Resources/migration.yml
#	runclient-Tools.bat
#	runclient.bat
2025-05-27 03:41:41 +03:00

270 lines
8.5 KiB
C#

using Content.Shared._Sunrise.Shuttles;
using Content.Shared.Containers.ItemSlots;
using Content.Shared.Shuttles.BUIStates;
using Content.Shared.Shuttles.Components;
using Content.Shared.Shuttles.UI.MapObjects;
using Content.Shared.Whitelist;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Collision.Shapes;
using Robust.Shared.Physics.Components;
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!;
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
public const float FTLRange = 256f;
public const float FTLBufferRange = 8f;
private EntityQuery<MapGridComponent> _gridQuery;
private EntityQuery<PhysicsComponent> _physicsQuery;
private EntityQuery<TransformComponent> _xformQuery;
private List<Entity<MapGridComponent>> _grids = new();
public override void Initialize()
{
base.Initialize();
_gridQuery = GetEntityQuery<MapGridComponent>();
_physicsQuery = GetEntityQuery<PhysicsComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
}
/// <summary>
/// Returns whether an entity can FTL to the specified map.
/// </summary>
public bool CanFTLTo(EntityUid shuttleUid, MapId targetMap, EntityUid consoleUid)
{
var mapUid = Maps.GetMapOrInvalid(targetMap);
var shuttleMap = _xformQuery.GetComponent(shuttleUid).MapID;
if (shuttleMap == targetMap)
return true;
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;
return _whitelistSystem.IsWhitelistPassOrNull(destination.Whitelist, shuttleUid);
}
/// <summary>
/// Gets the list of map objects relevant for the specified map.
/// </summary>
public IEnumerable<(ShuttleExclusionObject Exclusion, MapCoordinates Coordinates)> GetExclusions(MapId mapId, List<ShuttleExclusionObject> exclusions)
{
foreach (var exc in exclusions)
{
var beaconCoords = XformSystem.ToMapCoordinates(GetCoordinates(exc.Coordinates));
if (beaconCoords.MapId != mapId)
continue;
yield return (exc, beaconCoords);
}
}
/// <summary>
/// Gets the list of map objects relevant for the specified map.
/// </summary>
public IEnumerable<(ShuttleBeaconObject Beacon, MapCoordinates Coordinates)> GetBeacons(MapId mapId, List<ShuttleBeaconObject> beacons)
{
foreach (var beacon in beacons)
{
var beaconCoords = XformSystem.ToMapCoordinates(GetCoordinates(beacon.Coordinates));
if (beaconCoords.MapId != mapId)
continue;
yield return (beacon, beaconCoords);
}
}
public bool CanDraw(EntityUid gridUid, PhysicsComponent? physics = null, IFFComponent? iffComp = null)
{
if (!Resolve(gridUid, ref physics))
return true;
if (physics.BodyType != BodyType.Static && physics.Mass < 10f)
{
return false;
}
if (!Resolve(gridUid, ref iffComp, false))
{
return true;
}
// Hide it entirely.
return (iffComp.Flags & IFFFlags.Hide) == 0x0;
}
public bool IsBeaconMap(EntityUid mapUid)
{
return TryComp(mapUid, out FTLDestinationComponent? ftlDest) && ftlDest.BeaconsOnly;
}
/// <summary>
/// Returns true if a beacon can be FTLd to.
/// </summary>
public bool CanFTLBeacon(NetCoordinates nCoordinates)
{
// Only beacons parented to map supported.
var coordinates = GetCoordinates(nCoordinates);
return HasComp<MapGridComponent>(coordinates.EntityId); // Sunrise-Edit
}
public float GetFTLRange(EntityUid shuttleUid) => FTLRange;
public float GetFTLBufferRange(EntityUid shuttleUid, MapGridComponent? grid = null)
{
if (!_gridQuery.Resolve(shuttleUid, ref grid))
return 0f;
var localAABB = grid.LocalAABB;
var maxExtent = localAABB.MaxDimension / 2f;
var range = maxExtent + FTLBufferRange;
return range;
}
/// <summary>
/// Returns true if the spot is free to be FTLd to (not close to any objects and in range).
/// </summary>
public bool FTLFree(EntityUid shuttleUid, EntityCoordinates coordinates, Angle angle, List<ShuttleExclusionObject>? exclusionZones)
{
if (!_physicsQuery.TryGetComponent(shuttleUid, out var shuttlePhysics) ||
!_xformQuery.TryGetComponent(shuttleUid, out var shuttleXform))
{
return false;
}
// Just checks if any grids inside of a buffer range at the target position.
_grids.Clear();
var mapCoordinates = XformSystem.ToMapCoordinates(coordinates);
var ourPos = Maps.GetGridPosition((shuttleUid, shuttlePhysics, shuttleXform));
// This is the already adjusted position
var targetPosition = mapCoordinates.Position;
// Check range even if it's cross-map.
if ((targetPosition - ourPos).Length() > FTLRange)
{
return false;
}
// Sunrise-Start
// Запрет летать по планете туда сюда
if (shuttleXform.MapID == mapCoordinates.MapId)
return false;
// Sunrise-End
// Check exclusion zones.
// This needs to be passed in manually due to PVS.
if (exclusionZones != null)
{
foreach (var exclusion in exclusionZones)
{
var exclusionCoords = XformSystem.ToMapCoordinates(GetCoordinates(exclusion.Coordinates));
if (exclusionCoords.MapId != mapCoordinates.MapId)
continue;
if ((mapCoordinates.Position - exclusionCoords.Position).Length() <= exclusion.Range)
return false;
}
}
var ourFTLBuffer = GetFTLBufferRange(shuttleUid);
var circle = new PhysShapeCircle(ourFTLBuffer + FTLBufferRange, targetPosition);
_mapManager.FindGridsIntersecting(mapCoordinates.MapId, circle, Robust.Shared.Physics.Transform.Empty,
ref _grids, includeMap: false);
// If any grids in range that aren't us then can't FTL.
foreach (var grid in _grids)
{
if (grid.Owner == shuttleUid)
continue;
// Sunrise-Start
if (HasComp<IgnoreFtlCheckComponent>(grid))
continue;
// Sunrise-End
return false;
}
return true;
}
}
[Flags]
public enum FTLState : byte
{
Invalid = 0,
/// <summary>
/// A dummy state for presentation
/// </summary>
Available = 1 << 0,
/// <summary>
/// Sound played and launch started
/// </summary>
Starting = 1 << 1,
/// <summary>
/// When they're on the FTL map
/// </summary>
Travelling = 1 << 2,
/// <summary>
/// Approaching destination, play effects or whatever,
/// </summary>
Arriving = 1 << 3,
Cooldown = 1 << 4,
}