Merge branch 'master' into MagicWands
This commit is contained in:
@@ -16,6 +16,7 @@ public sealed class GasProducerAnomalySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -56,8 +57,11 @@ public sealed class GasProducerAnomalySystem : EntitySystem
|
||||
return;
|
||||
|
||||
var localpos = xform.Coordinates.Position;
|
||||
var tilerefs = grid.GetLocalTilesIntersecting(
|
||||
new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius))).ToArray();
|
||||
var tilerefs = _map.GetLocalTilesIntersecting(
|
||||
xform.GridUid.Value,
|
||||
grid,
|
||||
new Box2(localpos + new Vector2(-radius, -radius), localpos + new Vector2(radius, radius)))
|
||||
.ToArray();
|
||||
|
||||
if (tilerefs.Length == 0)
|
||||
return;
|
||||
|
||||
@@ -102,10 +102,12 @@ public sealed class LogicGateSystem : EntitySystem
|
||||
if (args.Port == comp.InputPortA)
|
||||
{
|
||||
comp.StateA = state;
|
||||
_appearance.SetData(uid, LogicGateVisuals.InputA, state == SignalState.High); //If A == High => Sets input A sprite to True
|
||||
}
|
||||
else if (args.Port == comp.InputPortB)
|
||||
{
|
||||
comp.StateB = state;
|
||||
_appearance.SetData(uid, LogicGateVisuals.InputB, state == SignalState.High); //If B == High => Sets input B sprite to True
|
||||
}
|
||||
|
||||
UpdateOutput(uid, comp);
|
||||
@@ -143,6 +145,8 @@ public sealed class LogicGateSystem : EntitySystem
|
||||
break;
|
||||
}
|
||||
|
||||
_appearance.SetData(uid, LogicGateVisuals.Output, output);
|
||||
|
||||
// only send a payload if it actually changed
|
||||
if (output != comp.LastOutput)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ using JetBrains.Annotations;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Map.Events;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -66,6 +66,42 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, BoundUserInterfaceCheckRangeEvent>(OnUiRangeCheck);
|
||||
|
||||
SubscribeLocalEvent<DeviceListComponent, ComponentRemove>(OnComponentRemoved);
|
||||
|
||||
SubscribeLocalEvent<BeforeSaveEvent>(OnMapSave);
|
||||
}
|
||||
|
||||
private void OnMapSave(BeforeSaveEvent ev)
|
||||
{
|
||||
var enumerator = AllEntityQuery<NetworkConfiguratorComponent>();
|
||||
while (enumerator.MoveNext(out var uid, out var conf))
|
||||
{
|
||||
if (CompOrNull<TransformComponent>(conf.ActiveDeviceList)?.MapUid != ev.Map)
|
||||
continue;
|
||||
|
||||
// The linked device list is (probably) being saved. Make sure that the configurator is also being saved
|
||||
// (i.e., not in the hands of a mapper/ghost). In the future, map saving should raise a separate event
|
||||
// containing a set of all entities that are about to be saved, which would make checking this much easier.
|
||||
// This is a shitty bandaid, and will force close the UI during auto-saves.
|
||||
// TODO Map serialization refactor
|
||||
|
||||
var xform = Transform(uid);
|
||||
if (xform.MapUid == ev.Map && IsSaveable(uid))
|
||||
continue;
|
||||
|
||||
_uiSystem.CloseUi(uid, NetworkConfiguratorUiKey.Configure);
|
||||
DebugTools.AssertNull(conf.ActiveDeviceList);
|
||||
}
|
||||
|
||||
bool IsSaveable(EntityUid uid)
|
||||
{
|
||||
while (uid.IsValid())
|
||||
{
|
||||
if (Prototype(uid)?.MapSavable == false)
|
||||
return false;
|
||||
uid = Transform(uid).ParentUid;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnUiRangeCheck(Entity<NetworkConfiguratorComponent> ent, ref BoundUserInterfaceCheckRangeEvent args)
|
||||
@@ -485,6 +521,9 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
if (!TryComp(targetUid, out DeviceListComponent? list))
|
||||
return;
|
||||
|
||||
if (TryComp(configurator.ActiveDeviceList, out DeviceListComponent? oldList))
|
||||
oldList.Configurators.Remove(configuratorUid);
|
||||
|
||||
list.Configurators.Add(configuratorUid);
|
||||
configurator.ActiveDeviceList = targetUid;
|
||||
Dirty(configuratorUid, configurator);
|
||||
@@ -758,7 +797,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
{
|
||||
if (query.TryGetComponent(device, out var comp))
|
||||
{
|
||||
component.Devices[addr] = device;
|
||||
component.Devices.Add(addr, device);
|
||||
comp.Configurators.Add(uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ public sealed partial class DragonSystem : EntitySystem
|
||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
|
||||
private EntityQuery<CarpRiftsConditionComponent> _objQuery;
|
||||
@@ -156,7 +157,7 @@ public sealed partial class DragonSystem : EntitySystem
|
||||
}
|
||||
|
||||
// cant put a rift on solars
|
||||
foreach (var tile in grid.GetTilesIntersecting(new Circle(_transform.GetWorldPosition(xform), RiftTileRadius), false))
|
||||
foreach (var tile in _map.GetTilesIntersecting(xform.GridUid.Value, grid, new Circle(_transform.GetWorldPosition(xform), RiftTileRadius), false))
|
||||
{
|
||||
if (!tile.IsSpace(_tileDef))
|
||||
continue;
|
||||
|
||||
@@ -121,7 +121,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
|
||||
activated.TimeLeft -= frameTime;
|
||||
if (activated.TimeLeft <= 0 || !IsPowered(uid, electrified, transform))
|
||||
{
|
||||
_appearance.SetData(uid, ElectrifiedVisuals.IsPowered, false);
|
||||
_appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, false);
|
||||
RemComp<ActivatedElectrifiedComponent>(uid);
|
||||
}
|
||||
}
|
||||
@@ -217,7 +217,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
|
||||
return false;
|
||||
|
||||
EnsureComp<ActivatedElectrifiedComponent>(uid);
|
||||
_appearance.SetData(uid, ElectrifiedVisuals.IsPowered, true);
|
||||
_appearance.SetData(uid, ElectrifiedVisuals.ShowSparks, true);
|
||||
|
||||
siemens *= electrified.SiemensCoefficient;
|
||||
if (!DoCommonElectrocutionAttempt(targetUid, uid, ref siemens) || siemens <= 0)
|
||||
@@ -488,15 +488,4 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
|
||||
}
|
||||
_audio.PlayPvs(electrified.ShockNoises, targetUid, AudioParams.Default.WithVolume(electrified.ShockVolume));
|
||||
}
|
||||
|
||||
public void SetElectrifiedWireCut(Entity<ElectrifiedComponent> ent, bool value)
|
||||
{
|
||||
if (ent.Comp.IsWireCut == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ent.Comp.IsWireCut = value;
|
||||
Dirty(ent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,13 +134,6 @@ public sealed class DrainSystem : SharedDrainSystem
|
||||
}
|
||||
drain.Accumulator -= drain.DrainFrequency;
|
||||
|
||||
// Disable ambient sound from emptying manually
|
||||
if (!drain.AutoDrain)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(uid, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!managerQuery.TryGetComponent(uid, out var manager))
|
||||
continue;
|
||||
|
||||
@@ -160,41 +153,44 @@ public sealed class DrainSystem : SharedDrainSystem
|
||||
// This will ensure that UnitsPerSecond is per second...
|
||||
var amount = drain.UnitsPerSecond * drain.DrainFrequency;
|
||||
|
||||
_puddles.Clear();
|
||||
_lookup.GetEntitiesInRange(Transform(uid).Coordinates, drain.Range, _puddles);
|
||||
|
||||
if (_puddles.Count == 0)
|
||||
if (drain.AutoDrain)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(uid, false);
|
||||
continue;
|
||||
}
|
||||
_puddles.Clear();
|
||||
_lookup.GetEntitiesInRange(Transform(uid).Coordinates, drain.Range, _puddles);
|
||||
|
||||
_ambientSoundSystem.SetAmbience(uid, true);
|
||||
|
||||
amount /= _puddles.Count;
|
||||
|
||||
foreach (var puddle in _puddles)
|
||||
{
|
||||
// Queue the solution deletion if it's empty. EvaporationSystem might also do this
|
||||
// but queuedelete should be pretty safe.
|
||||
if (!_solutionContainerSystem.ResolveSolution(puddle.Owner, puddle.Comp.SolutionName, ref puddle.Comp.Solution, out var puddleSolution))
|
||||
if (_puddles.Count == 0)
|
||||
{
|
||||
EntityManager.QueueDeleteEntity(puddle);
|
||||
_ambientSoundSystem.SetAmbience(uid, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Removes the lowest of:
|
||||
// the drain component's units per second adjusted for # of puddles
|
||||
// the puddle's remaining volume (making it cleanly zero)
|
||||
// the drain's remaining volume in its buffer.
|
||||
var transferSolution = _solutionContainerSystem.SplitSolution(puddle.Comp.Solution.Value,
|
||||
FixedPoint2.Min(FixedPoint2.New(amount), puddleSolution.Volume, drainSolution.AvailableVolume));
|
||||
_ambientSoundSystem.SetAmbience(uid, true);
|
||||
|
||||
drainSolution.AddSolution(transferSolution, _prototypeManager);
|
||||
amount /= _puddles.Count;
|
||||
|
||||
if (puddleSolution.Volume <= 0)
|
||||
foreach (var puddle in _puddles)
|
||||
{
|
||||
QueueDel(puddle);
|
||||
// Queue the solution deletion if it's empty. EvaporationSystem might also do this
|
||||
// but queuedelete should be pretty safe.
|
||||
if (!_solutionContainerSystem.ResolveSolution(puddle.Owner, puddle.Comp.SolutionName, ref puddle.Comp.Solution, out var puddleSolution))
|
||||
{
|
||||
EntityManager.QueueDeleteEntity(puddle);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Removes the lowest of:
|
||||
// the drain component's units per second adjusted for # of puddles
|
||||
// the puddle's remaining volume (making it cleanly zero)
|
||||
// the drain's remaining volume in its buffer.
|
||||
var transferSolution = _solutionContainerSystem.SplitSolution(puddle.Comp.Solution.Value,
|
||||
FixedPoint2.Min(FixedPoint2.New(amount), puddleSolution.Volume, drainSolution.AvailableVolume));
|
||||
|
||||
drainSolution.AddSolution(transferSolution, _prototypeManager);
|
||||
|
||||
if (puddleSolution.Volume <= 0)
|
||||
{
|
||||
QueueDel(puddle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public sealed partial class PuddleSystem
|
||||
var tileRef = _maps.GetTileRef(xform.GridUid.Value, mapGrid, xform.Coordinates);
|
||||
var tileDef = (ContentTileDefinition) _tileDefManager[tileRef.Tile.TypeId];
|
||||
|
||||
entity.Comp.CP14ForceEvaporation = tileDef.Weather;
|
||||
entity.Comp.CP14ForceEvaporation = tileDef.SuckReagents;
|
||||
}
|
||||
//CP14 End force evaporation under sky
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Mind;
|
||||
using Robust.Shared.Console;
|
||||
using Content.Server.GameTicking;
|
||||
|
||||
namespace Content.Server.Ghost
|
||||
{
|
||||
@@ -23,6 +25,14 @@ namespace Content.Server.Ghost
|
||||
return;
|
||||
}
|
||||
|
||||
var gameTicker = _entities.System<GameTicker>();
|
||||
if (!gameTicker.PlayerGameStatuses.TryGetValue(player.UserId, out var playerStatus) ||
|
||||
playerStatus is not PlayerGameStatus.JoinedGame)
|
||||
{
|
||||
shell.WriteLine("ghost-command-error-lobby");
|
||||
return;
|
||||
}
|
||||
|
||||
if (player.AttachedEntity is { Valid: true } frozen &&
|
||||
_entities.HasComponent<AdminFrozenComponent>(frozen))
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking;
|
||||
@@ -32,14 +34,13 @@ using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Server.Ghost
|
||||
{
|
||||
public sealed class GhostSystem : SharedGhostSystem
|
||||
{
|
||||
[Dependency] private readonly SharedActionsSystem _actions = default!;
|
||||
[Dependency] private readonly IAdminLogManager _adminLog = default!;
|
||||
[Dependency] private readonly SharedEyeSystem _eye = default!;
|
||||
[Dependency] private readonly FollowerSystem _followerSystem = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
@@ -221,10 +222,15 @@ namespace Content.Server.Ghost
|
||||
_actions.SetCooldown(component.BooActionEntity.Value, start, end);
|
||||
}
|
||||
|
||||
_actions.AddAction(uid, ref component.ToggleGhostHearingActionEntity, component.ToggleGhostHearingAction);
|
||||
//_actions.AddAction(uid, ref component.ToggleGhostHearingActionEntity, component.ToggleGhostHearingAction); //Dont need in CP14
|
||||
_actions.AddAction(uid, ref component.ToggleLightingActionEntity, component.ToggleLightingAction);
|
||||
_actions.AddAction(uid, ref component.ToggleFoVActionEntity, component.ToggleFoVAction);
|
||||
_actions.AddAction(uid, ref component.ToggleGhostsActionEntity, component.ToggleGhostsAction);
|
||||
//CP14
|
||||
_actions.AddAction(uid, ref component.CP14ZLevelUpActionEntity, component.CP14ZLevelUpAction);
|
||||
_actions.AddAction(uid, ref component.CP14ZLevelDownActionEntity, component.CP14ZLevelDownAction);
|
||||
_actions.AddAction(uid, ref component.CP14ToggleRoofActionEntity, component.CP14ToggleRoofAction);
|
||||
//CP14 end
|
||||
}
|
||||
|
||||
private void OnGhostExamine(EntityUid uid, GhostComponent component, ExaminedEvent args)
|
||||
@@ -330,6 +336,8 @@ namespace Content.Server.Ghost
|
||||
|
||||
private void WarpTo(EntityUid uid, EntityUid target)
|
||||
{
|
||||
_adminLog.Add(LogType.GhostWarp, $"{ToPrettyString(uid)} ghost warped to {ToPrettyString(target)}");
|
||||
|
||||
if ((TryComp(target, out WarpPointComponent? warp) && warp.Follow) || HasComp<MobStateComponent>(target))
|
||||
{
|
||||
_followerSystem.StartFollowingEntity(uid, target);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Ghost.Roles.Components;
|
||||
using Content.Server.Ghost.Roles.Raffles;
|
||||
@@ -77,13 +77,13 @@ namespace Content.Server.Ghost.Roles
|
||||
|
||||
if (isProto)
|
||||
{
|
||||
if (!_protoManager.TryIndex<GhostRoleRaffleSettingsPrototype>(args[4], out var proto))
|
||||
if (!_protoManager.TryIndex<GhostRoleRaffleSettingsPrototype>(args[3], out var proto))
|
||||
{
|
||||
var validProtos = string.Join(", ",
|
||||
_protoManager.EnumeratePrototypes<GhostRoleRaffleSettingsPrototype>().Select(p => p.ID)
|
||||
);
|
||||
|
||||
shell.WriteLine($"{args[4]} is not a valid raffle settings prototype. Valid options: {validProtos}");
|
||||
shell.WriteLine($"{args[3]} is not a valid raffle settings prototype. Valid options: {validProtos}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ using Content.Shared.Light;
|
||||
using Content.Shared.Light.Components;
|
||||
using Content.Shared.Rounding;
|
||||
using Content.Shared.Toggleable;
|
||||
using Content.Shared.Verbs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
@@ -46,7 +45,6 @@ namespace Content.Server.Light.EntitySystems
|
||||
SubscribeLocalEvent<HandheldLightComponent, ComponentShutdown>(OnShutdown);
|
||||
|
||||
SubscribeLocalEvent<HandheldLightComponent, ExaminedEvent>(OnExamine);
|
||||
SubscribeLocalEvent<HandheldLightComponent, GetVerbsEvent<ActivationVerb>>(AddToggleLightVerb);
|
||||
|
||||
SubscribeLocalEvent<HandheldLightComponent, ActivateInWorldEvent>(OnActivate);
|
||||
|
||||
@@ -179,25 +177,7 @@ namespace Content.Server.Light.EntitySystems
|
||||
}
|
||||
}
|
||||
|
||||
private void AddToggleLightVerb(Entity<HandheldLightComponent> ent, ref GetVerbsEvent<ActivationVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || !ent.Comp.ToggleOnInteract)
|
||||
return;
|
||||
|
||||
var @event = args;
|
||||
ActivationVerb verb = new()
|
||||
{
|
||||
Text = Loc.GetString("verb-common-toggle-light"),
|
||||
Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/light.svg.192dpi.png")),
|
||||
Act = ent.Comp.Activated
|
||||
? () => TurnOff(ent)
|
||||
: () => TurnOn(@event.User, ent)
|
||||
};
|
||||
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
public bool TurnOff(Entity<HandheldLightComponent> ent, bool makeNoise = true)
|
||||
public override bool TurnOff(Entity<HandheldLightComponent> ent, bool makeNoise = true)
|
||||
{
|
||||
if (!ent.Comp.Activated || !_lights.TryGetLight(ent, out var pointLightComponent))
|
||||
{
|
||||
@@ -211,7 +191,7 @@ namespace Content.Server.Light.EntitySystems
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TurnOn(EntityUid user, Entity<HandheldLightComponent> uid)
|
||||
public override bool TurnOn(EntityUid user, Entity<HandheldLightComponent> uid)
|
||||
{
|
||||
var component = uid.Comp;
|
||||
if (component.Activated || !_lights.TryGetLight(uid, out var pointLightComponent))
|
||||
|
||||
@@ -40,6 +40,7 @@ public sealed class NukeSystem : EntitySystem
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||
[Dependency] private readonly AppearanceSystem _appearance = default!;
|
||||
@@ -190,7 +191,7 @@ public sealed class NukeSystem : EntitySystem
|
||||
|
||||
var worldPos = _transform.GetWorldPosition(xform);
|
||||
|
||||
foreach (var tile in grid.GetTilesIntersecting(new Circle(worldPos, component.RequiredFloorRadius), false))
|
||||
foreach (var tile in _map.GetTilesIntersecting(xform.GridUid.Value, grid, new Circle(worldPos, component.RequiredFloorRadius), false))
|
||||
{
|
||||
if (!tile.IsSpace(_tileDefManager))
|
||||
continue;
|
||||
|
||||
@@ -18,8 +18,11 @@ public sealed partial class CableComponent : Component
|
||||
[DataField]
|
||||
public EntProtoId CableDroppedOnCutPrototype = "CableHVStack1";
|
||||
|
||||
/// <summary>
|
||||
/// The tool quality needed to cut the cable. Setting to null prevents cutting.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public ProtoId<ToolQualityPrototype> CuttingQuality = SharedToolSystem.CutQuality;
|
||||
public ProtoId<ToolQualityPrototype>? CuttingQuality = SharedToolSystem.CutQuality;
|
||||
|
||||
/// <summary>
|
||||
/// Checked by <see cref="CablePlacerComponent"/> to determine if there is
|
||||
|
||||
@@ -35,7 +35,7 @@ public sealed partial class CableSystem
|
||||
var snapPos = grid.TileIndicesFor(args.ClickLocation);
|
||||
var tileDef = (ContentTileDefinition) _tileManager[_map.GetTileRef(gridUid, grid,snapPos).Tile.TypeId];
|
||||
|
||||
if ((!tileDef.IsSubFloor || !tileDef.Sturdy) && placer.Comp.CP14OnlySubfloor) //CP14 if only subfloor
|
||||
if (!tileDef.IsSubFloor || !tileDef.Sturdy)
|
||||
return;
|
||||
|
||||
foreach (var anchored in grid.GetAnchoredEntities(snapPos))
|
||||
|
||||
@@ -35,7 +35,10 @@ public sealed partial class CableSystem : EntitySystem
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent());
|
||||
if (cable.CuttingQuality != null)
|
||||
{
|
||||
args.Handled = _toolSystem.UseTool(args.Used, args.User, uid, cable.CuttingDelay, cable.CuttingQuality, new CableCuttingFinishedEvent());
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCableCut(EntityUid uid, CableComponent cable, DoAfterEvent args)
|
||||
|
||||
@@ -17,7 +17,7 @@ public sealed partial class PowerWireAction : BaseWireAction
|
||||
[DataField("pulseTimeout")]
|
||||
private int _pulseTimeout = 30;
|
||||
|
||||
private ElectrocutionSystem _electrocutionSystem = default!;
|
||||
private ElectrocutionSystem _electrocution = default!;
|
||||
|
||||
public override object StatusKey { get; } = PowerWireActionKey.Status;
|
||||
|
||||
@@ -105,8 +105,8 @@ public sealed partial class PowerWireAction : BaseWireAction
|
||||
&& !EntityManager.TryGetComponent(used, out electrified))
|
||||
return;
|
||||
|
||||
_electrocutionSystem.SetElectrifiedWireCut((used, electrified), setting);
|
||||
electrified.Enabled = setting;
|
||||
_electrocution.SetElectrifiedWireCut((used, electrified), setting);
|
||||
_electrocution.SetElectrified((used, electrified), setting);
|
||||
}
|
||||
|
||||
/// <returns>false if failed, true otherwise, or if the entity cannot be electrified</returns>
|
||||
@@ -120,7 +120,7 @@ public sealed partial class PowerWireAction : BaseWireAction
|
||||
// always set this to true
|
||||
SetElectrified(wire.Owner, true, electrified);
|
||||
|
||||
var electrifiedAttempt = _electrocutionSystem.TryDoElectrifiedAct(wire.Owner, user);
|
||||
var electrifiedAttempt = _electrocution.TryDoElectrifiedAct(wire.Owner, user);
|
||||
|
||||
// if we were electrified, then return false
|
||||
return !electrifiedAttempt;
|
||||
@@ -161,7 +161,7 @@ public sealed partial class PowerWireAction : BaseWireAction
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_electrocutionSystem = EntityManager.System<ElectrocutionSystem>();
|
||||
_electrocution = EntityManager.System<ElectrocutionSystem>();
|
||||
}
|
||||
|
||||
// This should add a wire into the entity's state, whether it be
|
||||
|
||||
@@ -58,7 +58,7 @@ public sealed partial class DungeonJob
|
||||
}
|
||||
}
|
||||
|
||||
if (tile is not null && biomeSystem.TryGetEntity(node, indexedBiome.Layers, tile.Value, seed, _grid, out var entityProto))
|
||||
if (biomeSystem.TryGetEntity(node, indexedBiome.Layers, tile ?? tileRef.Value.Tile, seed, _grid, out var entityProto))
|
||||
{
|
||||
var ent = _entManager.SpawnEntity(entityProto, new EntityCoordinates(_gridUid, node + _grid.TileSizeHalfVector));
|
||||
var xform = xformQuery.Get(ent);
|
||||
|
||||
@@ -20,7 +20,11 @@ public sealed partial class DungeonJob
|
||||
}
|
||||
|
||||
var tileDef = _prototype.Index(tileProto);
|
||||
data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto);
|
||||
if (!data.SpawnGroups.TryGetValue(DungeonDataKey.WallMounts, out var spawnProto))
|
||||
{
|
||||
// caves can have no walls
|
||||
return;
|
||||
}
|
||||
|
||||
var checkedTiles = new HashSet<Vector2i>();
|
||||
var allExterior = new HashSet<Vector2i>(dungeon.CorridorExteriorTiles);
|
||||
|
||||
@@ -45,7 +45,6 @@ public sealed class ProjectileSystem : SharedProjectileSystem
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
|
||||
var otherName = ToPrettyString(target);
|
||||
var direction = args.OurBody.LinearVelocity.Normalized();
|
||||
var modifiedDamage = _damageableSystem.TryChangeDamage(target, ev.Damage, component.IgnoreResistances, origin: component.Shooter);
|
||||
var deleted = Deleted(target);
|
||||
|
||||
@@ -64,7 +63,9 @@ public sealed class ProjectileSystem : SharedProjectileSystem
|
||||
if (!deleted)
|
||||
{
|
||||
_guns.PlayImpactSound(target, modifiedDamage, component.SoundHit, component.ForceSound);
|
||||
_sharedCameraRecoil.KickCamera(target, direction);
|
||||
|
||||
if (!args.OurBody.LinearVelocity.IsLengthZero())
|
||||
_sharedCameraRecoil.KickCamera(target, args.OurBody.LinearVelocity.Normalized());
|
||||
}
|
||||
|
||||
component.DamagedEntity = true;
|
||||
|
||||
@@ -21,6 +21,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
[Dependency] private readonly TurfSystem _turf = default!;
|
||||
[Dependency] private readonly IChatManager _chat = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
@@ -105,7 +106,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem
|
||||
|
||||
var found = false;
|
||||
|
||||
foreach (var tile in grid.GetTilesIntersecting(circle))
|
||||
foreach (var tile in _map.GetTilesIntersecting(entityGridUid.Value, grid, circle))
|
||||
{
|
||||
if (tile.IsSpace(_tileDefinitionManager)
|
||||
|| _turf.IsTileBlocked(tile, CollisionGroup.MobMask)
|
||||
@@ -176,7 +177,7 @@ public sealed class SpecialRespawnSystem : SharedSpecialRespawnSystem
|
||||
var mapTarget = grid.WorldToTile(mapPos);
|
||||
var circle = new Circle(mapPos, 2);
|
||||
|
||||
foreach (var newTileRef in grid.GetTilesIntersecting(circle))
|
||||
foreach (var newTileRef in _map.GetTilesIntersecting(targetGrid, grid, circle))
|
||||
{
|
||||
if (newTileRef.IsSpace(_tileDefinitionManager) || _turf.IsTileBlocked(newTileRef, CollisionGroup.MobMask) || !_atmosphere.IsTileMixtureProbablySafe(targetGrid, targetMap, mapTarget))
|
||||
continue;
|
||||
|
||||
@@ -43,6 +43,7 @@ public sealed partial class RevenantSystem
|
||||
[Dependency] private readonly TileSystem _tile = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
private void InitializeAbilities()
|
||||
{
|
||||
@@ -228,8 +229,12 @@ public sealed partial class RevenantSystem
|
||||
var xform = Transform(uid);
|
||||
if (!TryComp<MapGridComponent>(xform.GridUid, out var map))
|
||||
return;
|
||||
var tiles = map.GetTilesIntersecting(Box2.CenteredAround(_transformSystem.GetWorldPosition(xform),
|
||||
new Vector2(component.DefileRadius * 2, component.DefileRadius))).ToArray();
|
||||
var tiles = _mapSystem.GetTilesIntersecting(
|
||||
xform.GridUid.Value,
|
||||
map,
|
||||
Box2.CenteredAround(_transformSystem.GetWorldPosition(xform),
|
||||
new Vector2(component.DefileRadius * 2, component.DefileRadius)))
|
||||
.ToArray();
|
||||
|
||||
_random.Shuffle(tiles);
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ public sealed class SpawnSalvageMissionJob : Job<bool>
|
||||
|
||||
List<Vector2i> reservedTiles = new();
|
||||
|
||||
foreach (var tile in grid.GetTilesIntersecting(new Circle(Vector2.Zero, landingPadRadius), false))
|
||||
foreach (var tile in _map.GetTilesIntersecting(mapUid, grid, new Circle(Vector2.Zero, landingPadRadius), false))
|
||||
{
|
||||
if (!_biome.TryGetBiomeTile(mapUid, grid, tile.GridIndices, out _))
|
||||
continue;
|
||||
|
||||
@@ -253,12 +253,6 @@ public sealed partial class ShuttleSystem
|
||||
|
||||
if (TryComp<PhysicsComponent>(shuttleUid, out var shuttlePhysics))
|
||||
{
|
||||
// Static physics type is set when station anchor is enabled
|
||||
if (shuttlePhysics.BodyType == BodyType.Static)
|
||||
{
|
||||
reason = Loc.GetString("shuttle-console-static");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Too large to FTL
|
||||
if (FTLMassLimit > 0 && shuttlePhysics.Mass > FTLMassLimit)
|
||||
@@ -1027,6 +1021,7 @@ public sealed partial class ShuttleSystem
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it has the FTLSmashImmuneComponent ignore it.
|
||||
if (_immuneQuery.HasComponent(ent))
|
||||
{
|
||||
continue;
|
||||
|
||||
37
Content.Server/Silicons/Laws/StartIonStormedSystem.cs
Normal file
37
Content.Server/Silicons/Laws/StartIonStormedSystem.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Content.Shared.Silicons.Laws.Components;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Database;
|
||||
|
||||
namespace Content.Server.Silicons.Laws;
|
||||
|
||||
/// <summary>
|
||||
/// This handles running the ion storm event a on specific entity when that entity is spawned in.
|
||||
/// </summary>
|
||||
public sealed class StartIonStormedSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IonStormSystem _ionStorm = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly SiliconLawSystem _siliconLaw = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<StartIonStormedComponent, MapInitEvent>(OnMapInit);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<StartIonStormedComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
if (!TryComp<SiliconLawBoundComponent>(ent.Owner, out var lawBound))
|
||||
return;
|
||||
if (!TryComp<IonStormTargetComponent>(ent.Owner, out var target))
|
||||
return;
|
||||
|
||||
for (int currentIonStorm = 0; currentIonStorm < ent.Comp.IonStormAmount; currentIonStorm++)
|
||||
{
|
||||
_ionStorm.IonStormTarget((ent.Owner, lawBound, target), false);
|
||||
}
|
||||
|
||||
var laws = _siliconLaw.GetLaws(ent.Owner, lawBound);
|
||||
_adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent.Owner):silicon} spawned with ion stormed laws: {laws.LoggingString()}");
|
||||
}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ public sealed class EventHorizonSystem : SharedEventHorizonSystem
|
||||
foreach (var grid in grids)
|
||||
{
|
||||
// TODO: Remover grid.Owner when this iterator returns entityuids as well.
|
||||
AttemptConsumeTiles(uid, grid.Comp.GetTilesIntersecting(circle), grid, grid, eventHorizon);
|
||||
AttemptConsumeTiles(uid, _mapSystem.GetTilesIntersecting(grid.Owner, grid.Comp, circle), grid, grid, eventHorizon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using Content.Server.StationEvents.Events;
|
||||
using Content.Shared.Access;
|
||||
using Content.Shared.Destructible.Thresholds;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.StationEvents.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Greytide Virus event specific configuration
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(GreytideVirusRule))]
|
||||
public sealed partial class GreytideVirusRuleComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Range from which the severity is randomly picked from.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public MinMax SeverityRange = new(1, 3);
|
||||
|
||||
/// <summary>
|
||||
/// Severity corresponding to the number of access groups affected.
|
||||
/// Will pick randomly from the SeverityRange if not specified.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public int? Severity;
|
||||
|
||||
/// <summary>
|
||||
/// Access groups to pick from.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<ProtoId<AccessGroupPrototype>> AccessGroups = new();
|
||||
|
||||
/// <summary>
|
||||
/// Entities with this access level will be ignored.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<ProtoId<AccessLevelPrototype>> Blacklist = new();
|
||||
}
|
||||
@@ -148,20 +148,20 @@ public sealed class EventManagerSystem : EntitySystem
|
||||
return null;
|
||||
}
|
||||
|
||||
var sumOfWeights = 0;
|
||||
var sumOfWeights = 0.0f;
|
||||
|
||||
foreach (var stationEvent in availableEvents.Values)
|
||||
{
|
||||
sumOfWeights += (int) stationEvent.Weight;
|
||||
sumOfWeights += stationEvent.Weight;
|
||||
}
|
||||
|
||||
sumOfWeights = _random.Next(sumOfWeights);
|
||||
sumOfWeights = _random.NextFloat(sumOfWeights);
|
||||
|
||||
foreach (var (proto, stationEvent) in availableEvents)
|
||||
{
|
||||
sumOfWeights -= (int) stationEvent.Weight;
|
||||
sumOfWeights -= stationEvent.Weight;
|
||||
|
||||
if (sumOfWeights <= 0)
|
||||
if (sumOfWeights <= 0.0f)
|
||||
{
|
||||
return proto.ID;
|
||||
}
|
||||
|
||||
96
Content.Server/StationEvents/Events/GreytideVirusRule.cs
Normal file
96
Content.Server/StationEvents/Events/GreytideVirusRule.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using Content.Server.StationEvents.Components;
|
||||
using Content.Shared.Access;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.Doors.Components;
|
||||
using Content.Shared.Doors.Systems;
|
||||
using Content.Shared.Lock;
|
||||
using Content.Shared.GameTicking.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.StationEvents.Events;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Greytide Virus event
|
||||
/// This will open and bolt airlocks and unlock lockers from randomly selected access groups.
|
||||
/// </summary>
|
||||
public sealed class GreytideVirusRule : StationEventSystem<GreytideVirusRuleComponent>
|
||||
{
|
||||
[Dependency] private readonly AccessReaderSystem _access = default!;
|
||||
[Dependency] private readonly SharedDoorSystem _door = default!;
|
||||
[Dependency] private readonly LockSystem _lock = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
protected override void Added(EntityUid uid, GreytideVirusRuleComponent virusComp, GameRuleComponent gameRule, GameRuleAddedEvent args)
|
||||
{
|
||||
if (!TryComp<StationEventComponent>(uid, out var stationEvent))
|
||||
return;
|
||||
|
||||
// pick severity randomly from range if not specified otherwise
|
||||
virusComp.Severity ??= virusComp.SeverityRange.Next(_random);
|
||||
virusComp.Severity = Math.Min(virusComp.Severity.Value, virusComp.AccessGroups.Count);
|
||||
|
||||
stationEvent.StartAnnouncement = Loc.GetString("station-event-greytide-virus-start-announcement", ("severity", virusComp.Severity.Value));
|
||||
base.Added(uid, virusComp, gameRule, args);
|
||||
}
|
||||
protected override void Started(EntityUid uid, GreytideVirusRuleComponent virusComp, GameRuleComponent gameRule, GameRuleStartedEvent args)
|
||||
{
|
||||
base.Started(uid, virusComp, gameRule, args);
|
||||
|
||||
if (virusComp.Severity == null)
|
||||
return;
|
||||
|
||||
// pick random access groups
|
||||
var chosen = _random.GetItems(virusComp.AccessGroups, virusComp.Severity.Value, allowDuplicates: false);
|
||||
|
||||
// combine all the selected access groups
|
||||
var accessIds = new HashSet<ProtoId<AccessLevelPrototype>>();
|
||||
foreach (var group in chosen)
|
||||
{
|
||||
if (_prototype.TryIndex(group, out var proto))
|
||||
accessIds.UnionWith(proto.Tags);
|
||||
}
|
||||
|
||||
var firelockQuery = GetEntityQuery<FirelockComponent>();
|
||||
var accessQuery = GetEntityQuery<AccessReaderComponent>();
|
||||
|
||||
var lockQuery = AllEntityQuery<LockComponent>();
|
||||
while (lockQuery.MoveNext(out var lockUid, out var lockComp))
|
||||
{
|
||||
if (!accessQuery.TryComp(lockUid, out var accessComp))
|
||||
continue;
|
||||
|
||||
// check access
|
||||
// the AreAccessTagsAllowed function is a little weird because it technically has support for certain tags to be locked out of opening something
|
||||
// which might have unintened side effects (see the comments in the function itself)
|
||||
// but no one uses that yet, so it is fine for now
|
||||
if (!_access.AreAccessTagsAllowed(accessIds, accessComp) || _access.AreAccessTagsAllowed(virusComp.Blacklist, accessComp))
|
||||
continue;
|
||||
|
||||
// open lockers
|
||||
_lock.Unlock(lockUid, null, lockComp);
|
||||
}
|
||||
|
||||
var airlockQuery = AllEntityQuery<AirlockComponent, DoorComponent>();
|
||||
while (airlockQuery.MoveNext(out var airlockUid, out var airlockComp, out var doorComp))
|
||||
{
|
||||
// don't space everything
|
||||
if (firelockQuery.HasComp(airlockUid))
|
||||
continue;
|
||||
|
||||
// use the access reader from the door electronics if they exist
|
||||
if (!_access.GetMainAccessReader(airlockUid, out var accessComp))
|
||||
continue;
|
||||
|
||||
// check access
|
||||
if (!_access.AreAccessTagsAllowed(accessIds, accessComp) || _access.AreAccessTagsAllowed(virusComp.Blacklist, accessComp))
|
||||
continue;
|
||||
|
||||
// open and bolt airlocks
|
||||
_door.TryOpenAndBolt(airlockUid, doorComp, airlockComp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ namespace Content.Server.VendingMachines
|
||||
[Dependency] private readonly ThrowingSystem _throwingSystem = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly SpeakOnUIClosedSystem _speakOnUIClosed = default!;
|
||||
[Dependency] private readonly SharedPointLightSystem _light = default!;
|
||||
|
||||
private const float WallVendEjectDistanceFromWall = 1f;
|
||||
|
||||
@@ -334,6 +335,12 @@ namespace Content.Server.VendingMachines
|
||||
finalState = VendingMachineVisualState.Off;
|
||||
}
|
||||
|
||||
if (_light.TryGetLight(uid, out var pointlight))
|
||||
{
|
||||
var lightState = finalState != VendingMachineVisualState.Broken && finalState != VendingMachineVisualState.Off;
|
||||
_light.SetEnabled(uid, lightState, pointlight);
|
||||
}
|
||||
|
||||
_appearanceSystem.SetData(uid, VendingMachineVisuals.VisualState, finalState);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,14 @@ public abstract partial class ComponentWireAction<TComponent> : BaseWireAction w
|
||||
public override bool Cut(EntityUid user, Wire wire)
|
||||
{
|
||||
base.Cut(user, wire);
|
||||
return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) && Cut(user, wire, component);
|
||||
// if the entity doesn't exist, we need to return true otherwise the wire sprite is never updated
|
||||
return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) ? Cut(user, wire, component) : true;
|
||||
}
|
||||
|
||||
public override bool Mend(EntityUid user, Wire wire)
|
||||
{
|
||||
base.Mend(user, wire);
|
||||
return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) && Mend(user, wire, component);
|
||||
return EntityManager.TryGetComponent(wire.Owner, out TComponent? component) ? Mend(user, wire, component) : true;
|
||||
}
|
||||
|
||||
public override void Pulse(EntityUid user, Wire wire)
|
||||
|
||||
@@ -4,7 +4,6 @@ using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Physics;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Random;
|
||||
@@ -17,7 +16,8 @@ public sealed class ThrowArtifactSystem : EntitySystem
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||
[Dependency] private readonly TileSystem _tile = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
@@ -30,7 +30,9 @@ public sealed class ThrowArtifactSystem : EntitySystem
|
||||
var xform = Transform(uid);
|
||||
if (TryComp<MapGridComponent>(xform.GridUid, out var grid))
|
||||
{
|
||||
var tiles = grid.GetTilesIntersecting(
|
||||
var tiles = _mapSystem.GetTilesIntersecting(
|
||||
xform.GridUid.Value,
|
||||
grid,
|
||||
Box2.CenteredAround(_transform.GetWorldPosition(xform), new Vector2(component.Range * 2, component.Range)));
|
||||
|
||||
foreach (var tile in tiles)
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Shuttles.Components;
|
||||
using Content.Server.Shuttles.Events;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared._CP14.Cargo;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
@@ -17,12 +9,6 @@ namespace Content.Server._CP14.Cargo;
|
||||
|
||||
public sealed partial class CP14CargoSystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLog = default!;
|
||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||
[Dependency] private readonly MindSystem _mind = default!;
|
||||
[Dependency] private readonly SharedJobSystem _job = default!;
|
||||
[Dependency] private readonly StationJobsSystem _stationJobs = default!;
|
||||
|
||||
private void InitializeShuttle()
|
||||
{
|
||||
SubscribeLocalEvent<CP14TravelingStoreShipComponent, FTLCompletedEvent>(OnFTLCompleted);
|
||||
@@ -102,10 +88,6 @@ public sealed partial class CP14CargoSystem
|
||||
{
|
||||
station.OnStation = false;
|
||||
|
||||
var b = station.Balance;
|
||||
|
||||
PlayersPurgeJobs(ent);
|
||||
|
||||
SellingThings((ent.Comp.Station, station)); // +balance
|
||||
TopUpBalance((ent.Comp.Station, station)); //+balance
|
||||
BuyToQueue((ent.Comp.Station, station)); //-balance +buyQueue
|
||||
@@ -121,44 +103,4 @@ public sealed partial class CP14CargoSystem
|
||||
|
||||
UpdateAllStores();
|
||||
}
|
||||
|
||||
private void PlayersPurgeJobs(Entity<CP14TravelingStoreShipComponent> ent)
|
||||
{
|
||||
var childrens = Transform(ent).ChildEnumerator;
|
||||
|
||||
HashSet<EntityUid> toDelete = new();
|
||||
while (childrens.MoveNext(out var uid))
|
||||
{
|
||||
if (!_mind.TryGetMind(uid, out var mindId, out var mindComp))
|
||||
continue;
|
||||
|
||||
if (!_job.MindTryGetJob(mindId, out var jobProto))
|
||||
continue;
|
||||
|
||||
_adminLog.Add(LogType.Action,
|
||||
LogImpact.High,
|
||||
$"{ToPrettyString(uid):player} was leave the round on traveling merchant ship");
|
||||
|
||||
_chatSystem.DispatchStationAnnouncement(ent.Comp.Station,
|
||||
Loc.GetString(
|
||||
"cp14-earlyleave-ship-announcement",
|
||||
("character", mindComp.CharacterName ?? "Unknown"),
|
||||
("entity", ent.Owner), // gender things for supporting downstreams with other languages
|
||||
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(Loc.GetString(jobProto.Name)))
|
||||
),
|
||||
Loc.GetString("cp14-ship-sender"),
|
||||
playDefaultSound: false
|
||||
);
|
||||
|
||||
_stationJobs.TryAdjustJobSlot(ent.Comp.Station, jobProto, 1, clamp: true);
|
||||
toDelete.Add(uid);
|
||||
}
|
||||
|
||||
while (toDelete.Count > 0)
|
||||
{
|
||||
var r = toDelete.First();
|
||||
toDelete.Remove(r);
|
||||
QueueDel(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server._CP14.Currency;
|
||||
using Content.Server._CP14.RoundRemoveShuttle;
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Server.Station.Events;
|
||||
using Content.Server.Station.Systems;
|
||||
@@ -102,6 +103,9 @@ public sealed partial class CP14CargoSystem : CP14SharedCargoSystem
|
||||
var member = EnsureComp<StationMemberComponent>(shuttle);
|
||||
member.Station = station;
|
||||
|
||||
var roundRemover = EnsureComp<CP14RoundRemoveShuttleComponent>(shuttle);
|
||||
roundRemover.Station = station;
|
||||
|
||||
station.Comp.NextTravelTime = _timing.CurTime + TimeSpan.FromSeconds(10f);
|
||||
|
||||
AddRoundstartTradingPositions(station);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared._CP14.DayCycle;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
using CP14DayCycleComponent = Content.Shared._CP14.DayCycle.Components.CP14DayCycleComponent;
|
||||
|
||||
@@ -108,9 +108,9 @@ public sealed class CP14SpawnRandomDemiplaneJob : Job<bool>
|
||||
}
|
||||
|
||||
//Setup gravity
|
||||
var gravity = _entManager.EnsureComponent<GravityComponent>(DemiplaneMapUid);
|
||||
var gravity = _entManager.EnsureComponent<GravityComponent>(grid);
|
||||
gravity.Enabled = true;
|
||||
_entManager.Dirty(DemiplaneMapUid, gravity, metadata);
|
||||
_entManager.Dirty(grid, gravity, metadata);
|
||||
|
||||
// Setup default atmos
|
||||
var moles = new float[Atmospherics.AdjustedNumberOfGases];
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Content.Server._CP14.MapDamage;
|
||||
|
||||
/// <summary>
|
||||
/// can take damage from being directly on the map (not on the grid)
|
||||
/// </summary>
|
||||
[RegisterComponent, AutoGenerateComponentPause]
|
||||
public sealed partial class CP14DamageableByMapComponent : Component
|
||||
{
|
||||
[DataField, AutoPausedField]
|
||||
public TimeSpan NextDamageTime = TimeSpan.Zero;
|
||||
|
||||
[DataField]
|
||||
public bool Enabled = false;
|
||||
|
||||
[DataField]
|
||||
public Entity<CP14MapDamageComponent>? CurrentMap;
|
||||
}
|
||||
24
Content.Server/_CP14/MapDamage/CP14MapDamageComponent.cs
Normal file
24
Content.Server/_CP14/MapDamage/CP14MapDamageComponent.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.FixedPoint;
|
||||
|
||||
namespace Content.Server._CP14.MapDamage;
|
||||
|
||||
/// <summary>
|
||||
/// The map deals damage to entities that are on it (not on the grid)
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14MapDamageComponent : Component
|
||||
{
|
||||
//Damage every second
|
||||
[DataField]
|
||||
public DamageSpecifier Damage = new()
|
||||
{
|
||||
DamageDict = new Dictionary<string, FixedPoint2>()
|
||||
{
|
||||
{"Asphyxiation", 10}
|
||||
}
|
||||
};
|
||||
|
||||
[DataField]
|
||||
public float StaminaDamage = 7f;
|
||||
}
|
||||
82
Content.Server/_CP14/MapDamage/CP14MapDamageSystem.cs
Normal file
82
Content.Server/_CP14/MapDamage/CP14MapDamageSystem.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Systems;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._CP14.MapDamage;
|
||||
|
||||
public sealed partial class CP14MapDamageSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly StaminaSystem _stamina = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14DamageableByMapComponent, EntParentChangedMessage>(OnParentChanged);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<CP14DamageableByMapComponent, DamageableComponent, MobStateComponent>();
|
||||
while (query.MoveNext(out var uid, out var damage, out var damageable, out var mobState))
|
||||
{
|
||||
if (!damage.Enabled)
|
||||
continue;
|
||||
|
||||
if (damage.NextDamageTime > _timing.CurTime)
|
||||
continue;
|
||||
|
||||
damage.NextDamageTime = _timing.CurTime + TimeSpan.FromSeconds(2f);
|
||||
|
||||
if (damage.CurrentMap is null)
|
||||
continue;
|
||||
|
||||
if (!_mobState.IsAlive(uid, mobState))
|
||||
continue;
|
||||
|
||||
_damageable.TryChangeDamage(uid, damage.CurrentMap.Value.Comp.Damage, damageable: damageable);
|
||||
_stamina.TakeStaminaDamage(uid, damage.CurrentMap.Value.Comp.StaminaDamage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnParentChanged(Entity<CP14DamageableByMapComponent> ent, ref EntParentChangedMessage args)
|
||||
{
|
||||
DisableDamage(ent);
|
||||
if (args.OldParent == null || TerminatingOrDeleted(ent))
|
||||
return;
|
||||
|
||||
var newParent = _transform.GetParentUid(ent);
|
||||
if (!TryComp<CP14MapDamageComponent>(newParent, out var mapDamage))
|
||||
return;
|
||||
|
||||
EnableDamage(ent, (newParent, mapDamage));
|
||||
}
|
||||
|
||||
private void DisableDamage(Entity<CP14DamageableByMapComponent> ent)
|
||||
{
|
||||
if (!ent.Comp.Enabled)
|
||||
return;
|
||||
|
||||
ent.Comp.Enabled = false;
|
||||
ent.Comp.CurrentMap = null;
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void EnableDamage(Entity<CP14DamageableByMapComponent> ent, Entity<CP14MapDamageComponent> map)
|
||||
{
|
||||
if (ent.Comp.Enabled)
|
||||
return;
|
||||
|
||||
ent.Comp.Enabled = true;
|
||||
ent.Comp.CurrentMap = map;
|
||||
Dirty(ent);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server._CP14.PortalAutoLink;
|
||||
|
||||
/// <summary>
|
||||
/// allows you to automatically link entities to each other, through key matching searches
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(CP14AutoLinkSystem))]
|
||||
public sealed partial class CP14AutoLinkComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// a key that is used to search for another autolinked entity installed in the worlds
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string? AutoLinkKey = "Hello";
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Teleportation.Systems;
|
||||
|
||||
namespace Content.Server._CP14.PortalAutoLink;
|
||||
|
||||
public sealed partial class CP14AutoLinkSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly LinkedEntitySystem _link = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14AutoLinkComponent, MapInitEvent>(OnMapInit);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<CP14AutoLinkComponent> autolink, ref MapInitEvent args)
|
||||
{
|
||||
TryAutoLink(autolink, out var otherLink);
|
||||
}
|
||||
public bool TryAutoLink(Entity<CP14AutoLinkComponent> autolink, out EntityUid? linkedEnt)
|
||||
{
|
||||
linkedEnt = null;
|
||||
|
||||
var query = EntityQueryEnumerator<CP14AutoLinkComponent>();
|
||||
while (query.MoveNext(out var uid, out var otherAutolink))
|
||||
{
|
||||
if (autolink.Comp == otherAutolink)
|
||||
continue;
|
||||
|
||||
if (autolink.Comp.AutoLinkKey == otherAutolink.AutoLinkKey)
|
||||
{
|
||||
if (_link.TryLink(autolink, uid, false))
|
||||
{
|
||||
RemComp<CP14AutoLinkComponent>(uid);
|
||||
RemComp<CP14AutoLinkComponent>(autolink);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Content.Server._CP14.RoundRemoveShuttle;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class CP14RoundRemoveShuttleComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public EntityUid Station;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Mind;
|
||||
using Content.Server.Shuttles.Events;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.IdentityManagement.Components;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.RoundRemoveShuttle;
|
||||
|
||||
public sealed partial class CP14RoundRemoveShuttleSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLog = default!;
|
||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||
[Dependency] private readonly MindSystem _mind = default!;
|
||||
[Dependency] private readonly StationJobsSystem _stationJobs = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14RoundRemoveShuttleComponent, FTLCompletedEvent>(OnFTLComplete);
|
||||
}
|
||||
|
||||
private void OnFTLComplete(Entity<CP14RoundRemoveShuttleComponent> ent, ref FTLCompletedEvent args)
|
||||
{
|
||||
var childrens = Transform(ent).ChildEnumerator;
|
||||
|
||||
HashSet<EntityUid> toDelete = new();
|
||||
while (childrens.MoveNext(out var uid))
|
||||
{
|
||||
if (!_mind.TryGetMind(uid, out _, out var mindComp))
|
||||
continue;
|
||||
|
||||
//Trying return all jobs roles
|
||||
var userId = mindComp.UserId;
|
||||
ProtoId<JobPrototype>? playerJob = null;
|
||||
string? jobName = null;
|
||||
if (userId is not null)
|
||||
{
|
||||
RestoreJobs(ent.Comp.Station, userId.Value, out playerJob);
|
||||
if (_proto.TryIndex(playerJob, out var indexedJob))
|
||||
{
|
||||
jobName = Loc.GetString(indexedJob.Name);
|
||||
}
|
||||
}
|
||||
|
||||
_adminLog.Add(LogType.Action,
|
||||
LogImpact.High,
|
||||
$"{ToPrettyString(uid):player} was leave the round on traveling merchant ship");
|
||||
|
||||
_chatSystem.DispatchStationAnnouncement(ent.Comp.Station,
|
||||
Loc.GetString(
|
||||
_mobState.IsDead(uid) ? "cp14-earlyleave-ship-announcement-dead" : "cp14-earlyleave-ship-announcement",
|
||||
("character", mindComp.CharacterName ?? "Unknown"),
|
||||
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName ?? "Unknown"))
|
||||
),
|
||||
Loc.GetString("cp14-ship-sender"),
|
||||
playDefaultSound: false
|
||||
);
|
||||
toDelete.Add(uid);
|
||||
}
|
||||
|
||||
while (toDelete.Count > 0)
|
||||
{
|
||||
var r = toDelete.First();
|
||||
toDelete.Remove(r);
|
||||
QueueDel(r);
|
||||
}
|
||||
}
|
||||
|
||||
private void RestoreJobs(EntityUid station, NetUserId userId, out ProtoId<JobPrototype>? outJob)
|
||||
{
|
||||
outJob = null;
|
||||
if (!_stationJobs.TryGetPlayerJobs(station, userId, out var jobs))
|
||||
return;
|
||||
|
||||
foreach (var job in jobs)
|
||||
{
|
||||
_stationJobs.TryAdjustJobSlot(station, job, 1, clamp: true);
|
||||
outJob = job;
|
||||
}
|
||||
_stationJobs.TryRemovePlayerJobs(station, userId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System.Linq;
|
||||
using Content.Server._CP14.ZLevels.Components;
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server._CP14.ZLevels.Commands;
|
||||
|
||||
[AdminCommand(AdminFlags.VarEdit)]
|
||||
public sealed class CP14CombineMapsIntoZLevelsCommand : LocalizedCommands
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entities = default!;
|
||||
[Dependency] private readonly IMapManager _map = default!;
|
||||
|
||||
private const string Name = "cp14-combineMapsIntoZLevels";
|
||||
public override string Command => Name;
|
||||
public override string Description => "Connects a number of maps into a common network of z-levels. Does not work if one of the maps is already in the z-level network";
|
||||
public override string Help => $"{Name} <MapId 1> <MapId 2> ... <MapId X> (from ground to sky)";
|
||||
|
||||
public override void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
if (args.Length == 1)
|
||||
{
|
||||
shell.WriteError("Not enough maps to form a network of levels");
|
||||
return;
|
||||
}
|
||||
|
||||
List<MapId> maps = new();
|
||||
foreach (var arg in args)
|
||||
{
|
||||
if (!int.TryParse(arg, out var mapIdInt))
|
||||
{
|
||||
shell.WriteError($"Cannot parse `{arg}` into mapId");
|
||||
return;
|
||||
}
|
||||
|
||||
var mapId = new MapId(mapIdInt);
|
||||
|
||||
if (mapId == MapId.Nullspace)
|
||||
{
|
||||
shell.WriteError($"Cannot parse NullSpace");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_map.MapExists(mapId))
|
||||
{
|
||||
shell.WriteError($"Map {mapId} dont exist");
|
||||
return;
|
||||
}
|
||||
|
||||
//if (!_mapSystem.TryGetMap(mapId, out var mapUid))
|
||||
//{
|
||||
// shell.WriteError($"Map {mapId} dont exist");
|
||||
// return;
|
||||
//}
|
||||
|
||||
if (maps.Contains(mapId))
|
||||
{
|
||||
shell.WriteError($"Duplication maps: {mapId}");
|
||||
return;
|
||||
}
|
||||
|
||||
maps.Add(mapId);
|
||||
}
|
||||
|
||||
//Check maps already in zLevel links
|
||||
var query = _entities.EntityQueryEnumerator<CP14StationZLevelsComponent>();
|
||||
while (query.MoveNext(out var uid, out var zLevelComp))
|
||||
{
|
||||
foreach (var findMap in maps)
|
||||
{
|
||||
if (zLevelComp.LevelEntities.ContainsKey(findMap))
|
||||
{
|
||||
shell.WriteError($"{findMap} already in z-level network! Z-Network Entity: {uid}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Ok, all check passed, we create new z-level network
|
||||
var zLevelEnt = _entities.Spawn();
|
||||
_entities.EnsureComponent<CP14StationZLevelsComponent>(zLevelEnt, out var newZLevelComp);
|
||||
|
||||
var count = 0;
|
||||
foreach (var map in maps)
|
||||
{
|
||||
newZLevelComp.LevelEntities.Add(map, count);
|
||||
count++;
|
||||
}
|
||||
|
||||
shell.WriteLine($"Successfully created z-level network! Z-Network entity: {zLevelEnt}");
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
using Content.Server._CP14.StationDungeonMap.EntitySystems;
|
||||
using Content.Server._CP14.ZLevels.Commands;
|
||||
using Content.Server._CP14.ZLevels.EntitySystems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server._CP14.StationDungeonMap.Components;
|
||||
namespace Content.Server._CP14.ZLevels.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the z-level system by creating a series of linked maps
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(CP14StationZLevelsSystem))]
|
||||
[RegisterComponent, Access(typeof(CP14StationZLevelsSystem), typeof(CP14CombineMapsIntoZLevelsCommand))]
|
||||
public sealed partial class CP14StationZLevelsComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Server._CP14.StationDungeonMap.EntitySystems;
|
||||
using Content.Server._CP14.ZLevels.EntitySystems;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._CP14.StationDungeonMap.Components;
|
||||
namespace Content.Server._CP14.ZLevels.Components;
|
||||
|
||||
/// <summary>
|
||||
/// automatically creates a linked portal at a different relative z-level, and then the component is removed
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared._CP14.ZLevel;
|
||||
using Content.Shared.Ghost;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server._CP14.ZLevels.EntitySystems;
|
||||
|
||||
public sealed partial class CP14StationZLevelsSystem
|
||||
{
|
||||
private void InitActions()
|
||||
{
|
||||
SubscribeLocalEvent<GhostComponent, CP14ZLevelActionUp>(OnZLevelUp);
|
||||
SubscribeLocalEvent<GhostComponent, CP14ZLevelActionDown>(OnZLevelDown);
|
||||
}
|
||||
|
||||
private void OnZLevelDown(Entity<GhostComponent> ent, ref CP14ZLevelActionDown args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
ZLevelMove(ent, -1);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnZLevelUp(Entity<GhostComponent> ent, ref CP14ZLevelActionUp args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
ZLevelMove(ent, 1);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void ZLevelMove(EntityUid ent, int offset)
|
||||
{
|
||||
var xform = Transform(ent);
|
||||
var map = xform.MapUid;
|
||||
|
||||
if (map is null)
|
||||
return;
|
||||
|
||||
var targetMap = GetMapOffset(map.Value, offset);
|
||||
|
||||
if (targetMap is null)
|
||||
return;
|
||||
|
||||
_transform.SetMapCoordinates(ent, new MapCoordinates(_transform.GetWorldPosition(ent), targetMap.Value));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using Content.Server._CP14.ZLevels.Components;
|
||||
using Content.Server.GameTicking.Events;
|
||||
using Content.Shared.Teleportation.Systems;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server._CP14.ZLevels.EntitySystems;
|
||||
|
||||
public sealed partial class CP14StationZLevelsSystem
|
||||
{
|
||||
[Dependency] private readonly LinkedEntitySystem _linkedEntity = default!;
|
||||
private void InitializePortals()
|
||||
{
|
||||
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
|
||||
SubscribeLocalEvent<CP14ZLevelAutoPortalComponent, MapInitEvent>(OnPortalMapInit);
|
||||
}
|
||||
|
||||
private void OnRoundStart(RoundStartingEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CP14ZLevelAutoPortalComponent>();
|
||||
while (query.MoveNext(out var uid, out var portal))
|
||||
{
|
||||
InitPortal((uid, portal));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPortalMapInit(Entity<CP14ZLevelAutoPortalComponent> autoPortal, ref MapInitEvent args)
|
||||
{
|
||||
InitPortal(autoPortal);
|
||||
}
|
||||
|
||||
private void InitPortal(Entity<CP14ZLevelAutoPortalComponent> autoPortal)
|
||||
{
|
||||
var mapId = Transform(autoPortal).MapUid;
|
||||
if (mapId is null)
|
||||
return;
|
||||
|
||||
var offsetMap = GetMapOffset(mapId.Value, autoPortal.Comp.ZLevelOffset);
|
||||
|
||||
if (offsetMap is null)
|
||||
return;
|
||||
|
||||
var currentWorldPos = _transform.GetWorldPosition(autoPortal);
|
||||
var targetMapPos = new MapCoordinates(currentWorldPos, offsetMap.Value);
|
||||
|
||||
var otherSidePortal = Spawn(autoPortal.Comp.OtherSideProto, targetMapPos);
|
||||
|
||||
_transform.SetWorldRotation(otherSidePortal, _transform.GetWorldRotation(autoPortal));
|
||||
if (_linkedEntity.TryLink(autoPortal, otherSidePortal, true))
|
||||
RemComp<CP14ZLevelAutoPortalComponent>(autoPortal);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,14 @@
|
||||
using Content.Server._CP14.StationDungeonMap.Components;
|
||||
using Content.Server.GameTicking.Events;
|
||||
using Content.Server._CP14.ZLevels.Components;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Events;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Maps;
|
||||
using Content.Shared.Station.Components;
|
||||
using Content.Shared.Teleportation.Systems;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Maps;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._CP14.StationDungeonMap.EntitySystems;
|
||||
namespace Content.Server._CP14.ZLevels.EntitySystems;
|
||||
|
||||
public sealed partial class CP14StationZLevelsSystem : EntitySystem
|
||||
{
|
||||
@@ -20,29 +17,18 @@ public sealed partial class CP14StationZLevelsSystem : EntitySystem
|
||||
[Dependency] private readonly MapLoaderSystem _mapLoader = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly TileSystem _tile = default!;
|
||||
[Dependency] private readonly SharedMapSystem _maps = default!;
|
||||
[Dependency] private readonly LinkedEntitySystem _linkedEntity = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
InitializePortals();
|
||||
InitActions();
|
||||
|
||||
SubscribeLocalEvent<CP14ZLevelAutoPortalComponent, MapInitEvent>(OnPortalMapInit);
|
||||
SubscribeLocalEvent<RoundStartingEvent>(OnRoundStart);
|
||||
SubscribeLocalEvent<CP14StationZLevelsComponent, StationPostInitEvent>(OnStationPostInit);
|
||||
}
|
||||
|
||||
private void OnRoundStart(RoundStartingEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CP14ZLevelAutoPortalComponent>();
|
||||
while (query.MoveNext(out var uid, out var portal))
|
||||
{
|
||||
InitPortal((uid, portal));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStationPostInit(Entity<CP14StationZLevelsComponent> ent, ref StationPostInitEvent args)
|
||||
{
|
||||
if (ent.Comp.Initialized)
|
||||
@@ -98,35 +84,10 @@ public sealed partial class CP14StationZLevelsSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPortalMapInit(Entity<CP14ZLevelAutoPortalComponent> autoPortal, ref MapInitEvent args)
|
||||
{
|
||||
InitPortal(autoPortal);
|
||||
}
|
||||
|
||||
private void InitPortal(Entity<CP14ZLevelAutoPortalComponent> autoPortal)
|
||||
{
|
||||
var mapId = Transform(autoPortal).MapUid;
|
||||
if (mapId is null)
|
||||
return;
|
||||
|
||||
var offsetMap = GetMapOffset(mapId.Value, autoPortal.Comp.ZLevelOffset);
|
||||
|
||||
if (offsetMap is null)
|
||||
return;
|
||||
|
||||
var currentWorldPos = _transform.GetWorldPosition(autoPortal);
|
||||
var targetMapPos = new MapCoordinates(currentWorldPos, offsetMap.Value);
|
||||
|
||||
var otherSidePortal = Spawn(autoPortal.Comp.OtherSideProto, targetMapPos);
|
||||
|
||||
if (_linkedEntity.TryLink(autoPortal, otherSidePortal, true))
|
||||
RemComp<CP14ZLevelAutoPortalComponent>(autoPortal);
|
||||
}
|
||||
|
||||
public MapId? GetMapOffset(EntityUid mapUid, int offset)
|
||||
{
|
||||
var query = EntityQueryEnumerator<CP14StationZLevelsComponent, StationDataComponent>();
|
||||
while (query.MoveNext(out var uid, out var zLevel, out _))
|
||||
var query = EntityQueryEnumerator<CP14StationZLevelsComponent>();
|
||||
while (query.MoveNext(out var uid, out var zLevel))
|
||||
{
|
||||
if (!zLevel.LevelEntities.TryGetValue(Transform(mapUid).MapID, out var currentLevel))
|
||||
continue;
|
||||
Reference in New Issue
Block a user