Merge remote-tracking branch 'upstream/master' into ed-23-07-2024-upstream

# Conflicts:
#	.github/PULL_REQUEST_TEMPLATE.md
#	Content.Client/Clothing/ClientClothingSystem.cs
#	Content.Client/Hands/Systems/HandsSystem.cs
#	Content.IntegrationTests/Tests/PostMapInitTest.cs
#	Content.Shared/Hands/Components/HandsComponent.cs
#	Content.Shared/Inventory/InventoryComponent.cs
#	Content.Shared/Storage/StorageComponent.cs
#	Resources/Prototypes/Accents/word_replacements.yml
#	Resources/Prototypes/Entities/Mobs/Player/human.yml
#	Resources/Prototypes/Maps/Pools/default.yml
#	Resources/Prototypes/Maps/fland.yml
#	Resources/Prototypes/Maps/oasis.yml
#	Resources/Prototypes/Maps/packed.yml
#	Resources/Prototypes/Maps/saltern.yml
This commit is contained in:
Ed
2024-07-23 12:24:42 +03:00
494 changed files with 41440 additions and 41010 deletions

View File

@@ -1,5 +1,5 @@
using System.Text.Json;
using Content.Server.Station.Components;
using Content.Shared.Station.Components;
using Robust.Shared.Map;
using Robust.Shared.Map.Components;

View File

@@ -1,11 +1,11 @@
using Content.Server.Bible.Components;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Ghost.Roles.Events;
using Content.Server.Popups;
using Content.Shared.ActionBlocker;
using Content.Shared.Actions;
using Content.Shared.Bible;
using Content.Shared.Damage;
using Content.Shared.Ghost.Roles.Components;
using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Inventory;

View File

@@ -121,21 +121,25 @@ public sealed class InjectorSystem : SharedInjectorSystem
if (!SolutionContainers.TryGetSolution(injector.Owner, injector.Comp.SolutionName, out _, out var solution))
return;
var actualDelay = MathHelper.Max(injector.Comp.Delay, TimeSpan.FromSeconds(1));
float amountToInject;
var actualDelay = injector.Comp.Delay;
FixedPoint2 amountToInject;
if (injector.Comp.ToggleState == InjectorToggleMode.Draw)
{
// additional delay is based on actual volume left to draw in syringe when smaller than transfer amount
amountToInject = Math.Min(injector.Comp.TransferAmount.Float(), (solution.MaxVolume - solution.Volume).Float());
amountToInject = FixedPoint2.Min(injector.Comp.TransferAmount, (solution.MaxVolume - solution.Volume));
}
else
{
// additional delay is based on actual volume left to inject in syringe when smaller than transfer amount
amountToInject = Math.Min(injector.Comp.TransferAmount.Float(), solution.Volume.Float());
amountToInject = FixedPoint2.Min(injector.Comp.TransferAmount, solution.Volume);
}
// Injections take 0.5 seconds longer per 5u of possible space/content
actualDelay += TimeSpan.FromSeconds(amountToInject / 10);
// First 5u(MinimumTransferAmount) doesn't incur delay
actualDelay += injector.Comp.DelayPerVolume * FixedPoint2.Max(0, amountToInject - injector.Comp.MinimumTransferAmount).Double();
// Ensure that minimum delay before incapacitation checks is 1 seconds
actualDelay = MathHelper.Max(actualDelay, TimeSpan.FromSeconds(1));
var isTarget = user != target;

View File

@@ -308,6 +308,12 @@ namespace Content.Server.Connection
return (false, "");
var isAccountAgeInvalid = record.FirstSeenTime.CompareTo(DateTimeOffset.Now - TimeSpan.FromMinutes(maxAccountAgeMinutes)) <= 0;
if (isAccountAgeInvalid)
{
_sawmill.Debug($"Baby jail will deny {userId} for account age {record.FirstSeenTime}"); // Remove on or after 2024-09
}
if (isAccountAgeInvalid && showReason)
{
var locAccountReason = reason != string.Empty
@@ -322,7 +328,12 @@ namespace Content.Server.Connection
}
var overallTime = ( await _db.GetPlayTimes(e.UserId)).Find(p => p.Tracker == PlayTimeTrackingShared.TrackerOverall);
var isTotalPlaytimeInvalid = overallTime == null || overallTime.TimeSpent.TotalMinutes >= maxPlaytimeMinutes;
var isTotalPlaytimeInvalid = overallTime != null && overallTime.TimeSpent.TotalMinutes >= maxPlaytimeMinutes;
if (isTotalPlaytimeInvalid)
{
_sawmill.Debug($"Baby jail will deny {userId} for playtime {overallTime!.TimeSpent}"); // Remove on or after 2024-09
}
if (isTotalPlaytimeInvalid && showReason)
{

View File

@@ -9,6 +9,7 @@ using Content.Shared.Disposal;
using Content.Shared.Interaction;
using Robust.Server.GameObjects;
using Robust.Shared.Player;
using Robust.Shared.Utility;
namespace Content.Server.Disposal.Mailing;
@@ -35,7 +36,7 @@ public sealed class MailingUnitSystem : EntitySystem
SubscribeLocalEvent<MailingUnitComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
SubscribeLocalEvent<MailingUnitComponent, BeforeDisposalFlushEvent>(OnBeforeFlush);
SubscribeLocalEvent<MailingUnitComponent, ConfigurationSystem.ConfigurationUpdatedEvent>(OnConfigurationUpdated);
SubscribeLocalEvent<MailingUnitComponent, ActivateInWorldEvent>(HandleActivate);
SubscribeLocalEvent<MailingUnitComponent, ActivateInWorldEvent>(HandleActivate, before: new[] { typeof(DisposalUnitSystem) });
SubscribeLocalEvent<MailingUnitComponent, DisposalUnitUIStateUpdatedEvent>(OnDisposalUnitUIStateChange);
SubscribeLocalEvent<MailingUnitComponent, TargetSelectedMessage>(OnTargetSelected);
}
@@ -179,7 +180,7 @@ public sealed class MailingUnitSystem : EntitySystem
if (component.DisposalUnitInterfaceState == null)
return;
var state = new MailingUnitBoundUserInterfaceState(component.DisposalUnitInterfaceState, component.Target, component.TargetList, component.Tag);
var state = new MailingUnitBoundUserInterfaceState(component.DisposalUnitInterfaceState, component.Target, component.TargetList.ShallowClone(), component.Tag);
_userInterfaceSystem.SetUiState(uid, MailingUnitUiKey.Key, state);
}

View File

@@ -8,6 +8,7 @@ using Content.Shared.Maps;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Systems;
using Content.Shared.NPC.Systems;
using Content.Shared.Zombies;
@@ -27,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 MobStateSystem _mobState = default!;
private EntityQuery<CarpRiftsConditionComponent> _objQuery;
@@ -91,7 +93,8 @@ public sealed partial class DragonSystem : EntitySystem
}
}
comp.RiftAccumulator += frameTime;
if (!_mobState.IsDead(uid))
comp.RiftAccumulator += frameTime;
// Delete it, naughty dragon!
if (comp.RiftAccumulator >= comp.RiftMaxAccumulator)

View File

@@ -1,8 +0,0 @@
namespace Content.Server.Eye.Blinding
{
[RegisterComponent]
public sealed partial class ActivatableUIRequiresVisionComponent : Component
{
}
}

View File

@@ -1,56 +0,0 @@
using Content.Shared.Eye.Blinding;
using Content.Shared.UserInterface;
using Content.Server.Popups;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Eye.Blinding.Systems;
using Robust.Shared.Player;
using Robust.Server.GameObjects;
using Robust.Shared.Collections;
namespace Content.Server.Eye.Blinding;
public sealed class ActivatableUIRequiresVisionSystem : EntitySystem
{
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ActivatableUIRequiresVisionComponent, ActivatableUIOpenAttemptEvent>(OnOpenAttempt);
SubscribeLocalEvent<BlindableComponent, BlindnessChangedEvent>(OnBlindnessChanged);
}
private void OnOpenAttempt(EntityUid uid, ActivatableUIRequiresVisionComponent component, ActivatableUIOpenAttemptEvent args)
{
if (args.Cancelled)
return;
if (TryComp<BlindableComponent>(args.User, out var blindable) && blindable.IsBlind)
{
_popupSystem.PopupCursor(Loc.GetString("blindness-fail-attempt"), args.User, Shared.Popups.PopupType.MediumCaution);
args.Cancel();
}
}
private void OnBlindnessChanged(EntityUid uid, BlindableComponent component, ref BlindnessChangedEvent args)
{
if (!args.Blind)
return;
var toClose = new ValueList<(EntityUid Entity, Enum Key)>();
foreach (var bui in _userInterfaceSystem.GetActorUis(uid))
{
if (HasComp<ActivatableUIRequiresVisionComponent>(bui.Entity))
{
toClose.Add(bui);
}
}
foreach (var bui in toClose)
{
_userInterfaceSystem.CloseUi(bui.Entity, bui.Key, uid);
}
}
}

View File

@@ -1,63 +0,0 @@
using Content.Shared.StatusEffect;
using Content.Shared.Inventory;
using Content.Shared.Eye.Blinding.Components;
using Content.Shared.Eye.Blinding.Systems;
using Content.Shared.Tools.Components;
using Content.Shared.Item.ItemToggle.Components;
namespace Content.Server.Eye.Blinding.EyeProtection
{
public sealed class EyeProtectionSystem : EntitySystem
{
[Dependency] private readonly StatusEffectsSystem _statusEffectsSystem = default!;
[Dependency] private readonly BlindableSystem _blindingSystem = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RequiresEyeProtectionComponent, ToolUseAttemptEvent>(OnUseAttempt);
SubscribeLocalEvent<RequiresEyeProtectionComponent, ItemToggledEvent>(OnWelderToggled);
SubscribeLocalEvent<EyeProtectionComponent, GetEyeProtectionEvent>(OnGetProtection);
SubscribeLocalEvent<EyeProtectionComponent, InventoryRelayedEvent<GetEyeProtectionEvent>>(OnGetRelayedProtection);
}
private void OnGetRelayedProtection(EntityUid uid, EyeProtectionComponent component,
InventoryRelayedEvent<GetEyeProtectionEvent> args)
{
OnGetProtection(uid, component, args.Args);
}
private void OnGetProtection(EntityUid uid, EyeProtectionComponent component, GetEyeProtectionEvent args)
{
args.Protection += component.ProtectionTime;
}
private void OnUseAttempt(EntityUid uid, RequiresEyeProtectionComponent component, ToolUseAttemptEvent args)
{
if (!component.Toggled)
return;
if (!TryComp<BlindableComponent>(args.User, out var blindable) || blindable.IsBlind)
return;
var ev = new GetEyeProtectionEvent();
RaiseLocalEvent(args.User, ev);
var time = (float) (component.StatusEffectTime - ev.Protection).TotalSeconds;
if (time <= 0)
return;
// Add permanent eye damage if they had zero protection, also somewhat scale their temporary blindness by
// how much damage they already accumulated.
_blindingSystem.AdjustEyeDamage((args.User, blindable), 1);
var statusTimeSpan = TimeSpan.FromSeconds(time * MathF.Sqrt(blindable.EyeDamage));
_statusEffectsSystem.TryAddStatusEffect(args.User, TemporaryBlindnessSystem.BlindingStatusEffect,
statusTimeSpan, false, TemporaryBlindnessSystem.BlindingStatusEffect);
}
private void OnWelderToggled(EntityUid uid, RequiresEyeProtectionComponent component, ItemToggledEvent args)
{
component.Toggled = args.Activated;
}
}
}

View File

@@ -171,7 +171,7 @@ namespace Content.Server.GameTicking
var gridIds = _map.LoadMap(targetMapId, ev.GameMap.MapPath.ToString(), ev.Options);
_metaData.SetEntityName(_mapManager.GetMapEntityId(targetMapId), $"station map - {map.MapName}");
_metaData.SetEntityName(_mapManager.GetMapEntityId(targetMapId), map.MapName);
var gridUids = gridIds.ToList();
RaiseLocalEvent(new PostGameMapLoad(map, targetMapId, gridUids, stationName));

View File

@@ -483,7 +483,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem<NukeopsRuleComponent>
if (!Resolve(ent, ref ent.Comp, false))
return null;
return ent.Comp.MapGrids.Where(e => HasComp<StationMemberComponent>(e) && !HasComp<NukeOpsShuttleComponent>(e)).FirstOrNull();
return ent.Comp.MapGrids.Where(e => !HasComp<NukeOpsShuttleComponent>(e)).FirstOrNull();
}
/// <remarks>

View File

@@ -1,30 +0,0 @@
using Robust.Shared.Prototypes;
namespace Content.Server.Ghost.Roles.Components
{
/// <summary>
/// Allows a ghost to take this role, spawning a new entity.
/// </summary>
[RegisterComponent, EntityCategory("Spawner")]
[Access(typeof(GhostRoleSystem))]
public sealed partial class GhostRoleMobSpawnerComponent : Component
{
[DataField]
public bool DeleteOnSpawn = true;
[DataField]
public int AvailableTakeovers = 1;
[ViewVariables]
public int CurrentTakeovers = 0;
[DataField]
public EntProtoId? Prototype;
/// <summary>
/// If this ghostrole spawner has multiple selectable ghostrole prototypes.
/// </summary>
[DataField]
public List<string> SelectablePrototypes = [];
}
}

View File

@@ -3,7 +3,6 @@ using Content.Server.Administration.Logs;
using Content.Server.EUI;
using Content.Server.Ghost.Roles.Components;
using Content.Server.Ghost.Roles.Events;
using Content.Server.Ghost.Roles.Raffles;
using Content.Shared.Ghost.Roles.Raffles;
using Content.Server.Ghost.Roles.UI;
using Content.Server.Mind.Commands;
@@ -31,6 +30,7 @@ using Robust.Shared.Utility;
using Content.Server.Popups;
using Content.Shared.Verbs;
using Robust.Shared.Collections;
using Content.Shared.Ghost.Roles.Components;
namespace Content.Server.Ghost.Roles
{
@@ -80,6 +80,7 @@ namespace Content.Server.Ghost.Roles
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, TakeGhostRoleEvent>(OnSpawnerTakeRole);
SubscribeLocalEvent<GhostTakeoverAvailableComponent, TakeGhostRoleEvent>(OnTakeoverTakeRole);
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GetVerbsEvent<Verb>>(OnVerb);
SubscribeLocalEvent<GhostRoleMobSpawnerComponent, GhostRoleRadioMessage>(OnGhostRoleRadioMessage);
_playerManager.PlayerStatusChanged += PlayerStatusChanged;
}
@@ -786,6 +787,21 @@ namespace Content.Server.Ghost.Roles
_popupSystem.PopupEntity(msg, uid, userUid.Value);
}
}
public void OnGhostRoleRadioMessage(Entity<GhostRoleMobSpawnerComponent> entity, ref GhostRoleRadioMessage args)
{
if (!_prototype.TryIndex(args.ProtoId, out var ghostRoleProto))
return;
// if the prototype chosen isn't actually part of the selectable options, ignore it
foreach (var selectableProto in entity.Comp.SelectablePrototypes)
{
if (selectableProto == ghostRoleProto.EntityPrototype.Id)
return;
}
SetMode(entity.Owner, ghostRoleProto, ghostRoleProto.Name, entity.Comp);
}
}
[AnyCommand]

View File

@@ -170,7 +170,7 @@ namespace Content.Server.Hands.Systems
private bool HandleThrowItem(ICommonSession? playerSession, EntityCoordinates coordinates, EntityUid entity)
{
if (playerSession?.AttachedEntity is not {Valid: true} player || !Exists(player))
if (playerSession?.AttachedEntity is not {Valid: true} player || !Exists(player) || !coordinates.IsValid(EntityManager))
return false;
return ThrowHeldItem(player, coordinates);

View File

@@ -79,6 +79,9 @@ namespace Content.Server.Kitchen.Components
public Container Storage = default!;
[DataField]
public string ContainerId = "microwave_entity_container";
[DataField, ViewVariables(VVAccess.ReadWrite)]
public int Capacity = 10;

View File

@@ -252,7 +252,7 @@ namespace Content.Server.Kitchen.EntitySystems
private void OnInit(Entity<MicrowaveComponent> ent, ref ComponentInit args)
{
// this really does have to be in ComponentInit
ent.Comp.Storage = _container.EnsureContainer<Container>(ent, "microwave_entity_container");
ent.Comp.Storage = _container.EnsureContainer<Container>(ent, ent.Comp.ContainerId);
}
private void OnMapInit(Entity<MicrowaveComponent> ent, ref MapInitEvent args)
@@ -312,6 +312,9 @@ namespace Content.Server.Kitchen.EntitySystems
private void OnInsertAttempt(Entity<MicrowaveComponent> ent, ref ContainerIsInsertingAttemptEvent args)
{
if (args.Container.ID != ent.Comp.ContainerId)
return;
if (ent.Comp.Broken)
{
args.Cancel();

View File

@@ -3,11 +3,11 @@ using Content.Server.Audio;
using Content.Server.Light.Components;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Examine;
using Content.Shared.Light;
using Content.Shared.Light.Components;
using Content.Shared.Station.Components;
using Robust.Server.GameObjects;
using Color = Robust.Shared.Maths.Color;

View File

@@ -1,4 +1,4 @@
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork;
using Content.Server.DeviceNetwork.Components;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Medical.SuitSensors;

View File

@@ -0,0 +1,11 @@
using Robust.Shared.Prototypes;
namespace Content.Server.NPC.Queries.Queries;
/// <summary>
/// Remove anchored entities from the query
/// </summary>
public sealed partial class RemoveAnchoredFilter : UtilityQueryFilter
{
}

View File

@@ -1,7 +1,6 @@
using Content.Server.NPC.Components;
using Content.Shared.CombatMode;
using Content.Shared.Interaction;
using Content.Shared.Physics;
using Content.Shared.Weapons.Ranged.Components;
using Content.Shared.Weapons.Ranged.Events;
using Robust.Shared.Map;
@@ -134,7 +133,7 @@ public sealed partial class NPCCombatSystem
{
comp.LOSAccumulator += UnoccludedCooldown;
// For consistency with NPC steering.
comp.TargetInLOS = _interaction.InRangeUnobstructed(uid, Transform(comp.Target).Coordinates, distance + 0.1f);
comp.TargetInLOS = _interaction.InRangeUnobstructed(uid, comp.Target, distance + 0.1f);
}
if (!comp.TargetInLOS)

View File

@@ -499,6 +499,26 @@ public sealed class NPCUtilitySystem : EntitySystem
break;
}
case RemoveAnchoredFilter:
{
_entityList.Clear();
foreach (var ent in entities)
{
if (!TryComp(ent, out TransformComponent? xform))
continue;
if (xform.Anchored)
_entityList.Add(ent);
}
foreach (var ent in _entityList)
{
entities.Remove(ent);
}
break;
}
case PuddleFilter:
{
_entityList.Clear();

View File

@@ -211,6 +211,7 @@ public sealed class DrinkSystem : SharedDrinkSystem
target: target,
used: item)
{
BreakOnHandChange = false,
BreakOnMove = forceDrink,
BreakOnDamage = true,
MovementThreshold = 0.01f,

View File

@@ -198,6 +198,7 @@ public sealed class FoodSystem : EntitySystem
target: target,
used: food)
{
BreakOnHandChange = false,
BreakOnMove = forceFeed,
BreakOnDamage = true,
MovementThreshold = 0.01f,

View File

@@ -1,13 +1,12 @@
using Content.Shared.Singularity.Components;
using Robust.Shared.Prototypes;
namespace Content.Server.ParticleAccelerator.Components;
[RegisterComponent]
public sealed partial class ParticleAcceleratorEmitterComponent : Component
{
[DataField("emittedPrototype")]
[ViewVariables(VVAccess.ReadWrite)]
public string EmittedPrototype = "ParticlesProjectile";
[DataField]
public EntProtoId EmittedPrototype = "ParticlesProjectile";
[DataField("emitterType")]
[ViewVariables(VVAccess.ReadWrite)]

View File

@@ -101,6 +101,7 @@ public sealed partial class ParticleAcceleratorSystem
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(player):player} has turned {ToPrettyString(uid)} off");
comp.Enabled = false;
SetStrength(uid, ParticleAcceleratorPowerState.Standby, user, comp);
UpdatePowerDraw(uid, comp);
PowerOff(uid, comp);
UpdateUI(uid, comp);
@@ -174,12 +175,14 @@ public sealed partial class ParticleAcceleratorSystem
var pos = Transform(uid);
if (_timing.CurTime > comp.EffectCooldown)
{
_chat.SendAdminAlert(player, Loc.GetString("particle-accelerator-admin-power-strength-warning",
_chat.SendAdminAlert(player,
Loc.GetString("particle-accelerator-admin-power-strength-warning",
("machine", ToPrettyString(uid)),
("powerState", strength),
("powerState", GetPANumericalLevel(strength)),
("coordinates", pos.Coordinates)));
_audio.PlayGlobal("/Audio/Misc/adminlarm.ogg",
Filter.Empty().AddPlayers(_adminManager.ActiveAdmins), false,
Filter.Empty().AddPlayers(_adminManager.ActiveAdmins),
false,
AudioParams.Default.WithVolume(-8f));
comp.EffectCooldown = _timing.CurTime + comp.CooldownDuration;
}
@@ -230,7 +233,7 @@ public sealed partial class ParticleAcceleratorSystem
powerConsumer.DrawRate = powerDraw;
}
private void UpdateUI(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
public void UpdateUI(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
{
if (!Resolve(uid, ref comp))
return;
@@ -247,7 +250,9 @@ public sealed partial class ParticleAcceleratorSystem
receive = powerConsumer.ReceivedPower;
}
_uiSystem.SetUiState(uid, ParticleAcceleratorControlBoxUiKey.Key, new ParticleAcceleratorUIState(
_uiSystem.SetUiState(uid,
ParticleAcceleratorControlBoxUiKey.Key,
new ParticleAcceleratorUIState(
comp.Assembled,
comp.Enabled,
comp.SelectedStrength,
@@ -396,4 +401,16 @@ public sealed partial class ParticleAcceleratorSystem
UpdateUI(uid, comp);
}
public static int GetPANumericalLevel(ParticleAcceleratorPowerState state)
{
return state switch
{
ParticleAcceleratorPowerState.Level0 => 1,
ParticleAcceleratorPowerState.Level1 => 2,
ParticleAcceleratorPowerState.Level2 => 3,
ParticleAcceleratorPowerState.Level3 => 4,
_ => 0
};
}
}

View File

@@ -1,10 +1,8 @@
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using Content.Server.ParticleAccelerator.Components;
using JetBrains.Annotations;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Events;
using Robust.Shared.Player;
namespace Content.Server.ParticleAccelerator.EntitySystems;
@@ -26,8 +24,6 @@ public sealed partial class ParticleAcceleratorSystem
if (controller.CurrentlyRescanning)
return;
SwitchOff(uid, user, controller);
var partQuery = GetEntityQuery<ParticleAcceleratorPartComponent>();
foreach (var part in AllParts(uid, controller))
{
@@ -45,19 +41,25 @@ public sealed partial class ParticleAcceleratorSystem
var xformQuery = GetEntityQuery<TransformComponent>();
if (!xformQuery.TryGetComponent(uid, out var xform) || !xform.Anchored)
{
SwitchOff(uid, user, controller);
return;
}
var gridUid = xform.GridUid;
if (gridUid == null || gridUid != xform.ParentUid || !TryComp<MapGridComponent>(gridUid, out var grid))
{
SwitchOff(uid, user, controller);
return;
}
// Find fuel chamber first by scanning cardinals.
var fuelQuery = GetEntityQuery<ParticleAcceleratorFuelChamberComponent>();
foreach (var adjacent in _mapSystem.GetCardinalNeighborCells(gridUid.Value, grid, xform.Coordinates))
{
if (fuelQuery.HasComponent(adjacent)
&& partQuery.TryGetComponent(adjacent, out var partState)
&& partState.Master == null)
&& partQuery.TryGetComponent(adjacent, out var partState)
&& partState.Master == null)
{
controller.FuelChamber = adjacent;
break;
@@ -66,7 +68,7 @@ public sealed partial class ParticleAcceleratorSystem
if (controller.FuelChamber == null)
{
UpdateUI(uid, controller);
SwitchOff(uid, user, controller);
return;
}
@@ -93,19 +95,19 @@ public sealed partial class ParticleAcceleratorSystem
var positionForeEmitter = positionFuelChamber + offsetVect * 2;
var positionStarboardEmitter = positionFuelChamber + offsetVect * 2 - orthoOffsetVect;
ScanPart<ParticleAcceleratorEndCapComponent>(gridUid!.Value, positionEndCap, rotation, out controller.EndCap, out var _, grid);
ScanPart<ParticleAcceleratorPowerBoxComponent>(gridUid!.Value, positionPowerBox, rotation, out controller.PowerBox, out var _, grid);
ScanPart<ParticleAcceleratorEndCapComponent>(gridUid.Value, positionEndCap, rotation, out controller.EndCap, out _, grid);
ScanPart<ParticleAcceleratorPowerBoxComponent>(gridUid.Value, positionPowerBox, rotation, out controller.PowerBox, out _, grid);
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionPortEmitter, rotation, out controller.PortEmitter, out var portEmitter, grid)
|| portEmitter!.Type != ParticleAcceleratorEmitterType.Port)
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid.Value, positionPortEmitter, rotation, out controller.PortEmitter, out var portEmitter, grid)
|| portEmitter.Type != ParticleAcceleratorEmitterType.Port)
controller.PortEmitter = null;
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionForeEmitter, rotation, out controller.ForeEmitter, out var foreEmitter, grid)
|| foreEmitter!.Type != ParticleAcceleratorEmitterType.Fore)
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid.Value, positionForeEmitter, rotation, out controller.ForeEmitter, out var foreEmitter, grid)
|| foreEmitter.Type != ParticleAcceleratorEmitterType.Fore)
controller.ForeEmitter = null;
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionStarboardEmitter, rotation, out controller.StarboardEmitter, out var starboardEmitter, grid)
|| starboardEmitter!.Type != ParticleAcceleratorEmitterType.Starboard)
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid.Value, positionStarboardEmitter, rotation, out controller.StarboardEmitter, out var starboardEmitter, grid)
|| starboardEmitter.Type != ParticleAcceleratorEmitterType.Starboard)
controller.StarboardEmitter = null;
controller.Assembled =
@@ -157,19 +159,19 @@ public sealed partial class ParticleAcceleratorSystem
private void OnComponentShutdown(EntityUid uid, ParticleAcceleratorPartComponent comp, ComponentShutdown args)
{
if (EntityManager.EntityExists(comp.Master))
if (Exists(comp.Master))
RescanParts(comp.Master!.Value);
}
private void BodyTypeChanged(EntityUid uid, ParticleAcceleratorPartComponent comp, ref PhysicsBodyTypeChangedEvent args)
{
if (EntityManager.EntityExists(comp.Master))
if (Exists(comp.Master))
RescanParts(comp.Master!.Value);
}
private void OnMoveEvent(EntityUid uid, ParticleAcceleratorPartComponent comp, ref MoveEvent args)
{
if (EntityManager.EntityExists(comp.Master))
if (Exists(comp.Master))
RescanParts(comp.Master!.Value);
}
}

View File

@@ -1,4 +1,5 @@
using Content.Server.ParticleAccelerator.Components;
using Content.Server.ParticleAccelerator.EntitySystems;
using Content.Server.Wires;
using Content.Shared.Singularity.Components;
using Content.Shared.Wires;
@@ -19,12 +20,16 @@ public sealed partial class ParticleAcceleratorKeyboardWireAction : ComponentWir
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.InterfaceDisabled = true;
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
paSystem.UpdateUI(wire.Owner, controller);
return true;
}
public override bool Mend(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.InterfaceDisabled = false;
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
paSystem.UpdateUI(wire.Owner, controller);
return true;
}

View File

@@ -5,7 +5,6 @@ using Content.Server.Wires;
using Content.Shared.Popups;
using Content.Shared.Singularity.Components;
using Content.Shared.Wires;
using Robust.Shared.Player;
namespace Content.Server.ParticleAccelerator.Wires;
@@ -35,6 +34,8 @@ public sealed partial class ParticleAcceleratorLimiterWireAction : ComponentWire
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.MaxStrength = ParticleAcceleratorPowerState.Level3;
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
paSystem.UpdateUI(wire.Owner, controller);
return true;
}
@@ -49,12 +50,14 @@ public sealed partial class ParticleAcceleratorLimiterWireAction : ComponentWire
// Since that blocks SetStrength().
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
paSystem.SetStrength(wire.Owner, controller.MaxStrength, user, controller);
paSystem.UpdateUI(wire.Owner, controller);
return true;
}
public override void Pulse(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
EntityManager.System<PopupSystem>().PopupEntity(
EntityManager.System<PopupSystem>()
.PopupEntity(
Loc.GetString("particle-accelerator-control-box-component-wires-update-limiter-on-pulse"),
user,
PopupType.SmallCaution

View File

@@ -21,12 +21,16 @@ public sealed partial class ParticleAcceleratorStrengthWireAction : ComponentWir
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.StrengthLocked = true;
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
paSystem.UpdateUI(wire.Owner, controller);
return true;
}
public override bool Mend(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.StrengthLocked = false;
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
paSystem.UpdateUI(wire.Owner, controller);
return true;
}

View File

@@ -65,7 +65,7 @@ public sealed partial class ChasingWalkComponent : Component
/// The component that the entity is chasing
/// </summary>
[DataField(required: true)]
public ComponentRegistry ChasingComponent = default!;
public ComponentRegistry ChasingComponent = [];
/// <summary>
/// The maximum radius in which the entity chooses the target component to follow

View File

@@ -61,6 +61,9 @@ public sealed class ChasingWalkSystem : VirtualController
private void ChangeTarget(EntityUid uid, ChasingWalkComponent component)
{
if (component.ChasingComponent.Count <= 0)
return;
//We find our coordinates and calculate the radius of the target search.
var xform = Transform(uid);
var range = component.MaxChaseRadius;

View File

@@ -4,10 +4,10 @@ using Content.Server.NodeContainer.Nodes;
using Content.Server.Power.Components;
using Content.Server.Power.Nodes;
using Content.Server.Power.NodeGroups;
using Content.Server.Station.Components;
using Content.Server.StationEvents.Components;
using Content.Shared.GameTicking.Components;
using Content.Shared.Pinpointer;
using Content.Shared.Station.Components;
using Content.Shared.Power;
using JetBrains.Annotations;
using Robust.Server.GameObjects;

View File

@@ -2,7 +2,7 @@
using Content.Server.Atmos.EntitySystems;
using Content.Server.Chat.Managers;
using Content.Server.GameTicking;
using Content.Server.Station.Components;
using Content.Shared.Station.Components;
using Content.Server.Station.Systems;
using Content.Shared.Database;
using Content.Shared.Maps;

View File

@@ -1,6 +1,6 @@
using Content.Server.Shuttles.Components;
using Content.Server.Shuttles.Events;
using Content.Server.Station.Components;
using Content.Shared.Station.Components;
using Content.Shared.UserInterface;
namespace Content.Server.Shuttles.Systems;

View File

@@ -7,6 +7,7 @@ using Content.Shared.CCVar;
using Content.Shared.Procedural;
using Content.Shared.Salvage;
using Content.Shared.Shuttles.Components;
using Content.Shared.Station.Components;
using Robust.Shared.Collections;
using Robust.Shared.Map;
using Robust.Shared.Random;

View File

@@ -1,16 +0,0 @@
using Content.Server.Station.Systems;
namespace Content.Server.Station.Components;
/// <summary>
/// Indicates that a grid is a member of the given station.
/// </summary>
[RegisterComponent, Access(typeof(StationSystem))]
public sealed partial class StationMemberComponent : Component
{
/// <summary>
/// Station that this grid is a part of.
/// </summary>
[DataField]
public EntityUid Station = EntityUid.Invalid;
}

View File

@@ -5,6 +5,7 @@ using Content.Server.Station.Components;
using Content.Server.Station.Events;
using Content.Shared.CCVar;
using Content.Shared.Station;
using Content.Shared.Station.Components;
using JetBrains.Annotations;
using Robust.Server.GameObjects;
using Robust.Server.Player;

View File

@@ -1,11 +0,0 @@
using Content.Server.StationEvents.Events;
namespace Content.Server.StationEvents.Components;
/// <summary>
/// This is used to keep track of hallucinated entities to remove effects when event ends
/// </summary>
[RegisterComponent, Access(typeof(MassHallucinationsRule))]
public sealed partial class MassHallucinationsComponent : Component
{
}

View File

@@ -1,5 +1,6 @@
using Content.Server.StationEvents.Events;
using Robust.Shared.Audio;
using Robust.Shared.Collections;
namespace Content.Server.StationEvents.Components;
@@ -23,4 +24,7 @@ public sealed partial class MassHallucinationsRuleComponent : Component
[DataField("sounds", required: true)]
public SoundSpecifier Sounds = default!;
[DataField, ViewVariables(VVAccess.ReadOnly)]
public List<EntityUid> AffectedEntities = new();
}

View File

@@ -1,10 +1,9 @@
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Resist;
using Content.Server.Station.Components;
using Content.Server.StationEvents.Components;
using Content.Server.Storage.Components;
using Content.Server.Storage.EntitySystems;
using Content.Shared.Access.Components;
using Content.Shared.Station.Components;
using Content.Shared.GameTicking.Components;
using Content.Shared.Coordinates;

View File

@@ -1,8 +1,8 @@
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Station.Components;
using Content.Server.StationEvents.Components;
using Content.Shared.GameTicking.Components;
using Content.Shared.GameTicking.Components;
using Content.Shared.Station.Components;
using JetBrains.Annotations;
namespace Content.Server.StationEvents.Events;

View File

@@ -1,6 +1,5 @@
using System.Linq;
using Content.Server.Silicons.Laws;
using Content.Server.Station.Components;
using Content.Server.StationEvents.Components;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
@@ -11,6 +10,7 @@ using Content.Shared.Random;
using Content.Shared.Random.Helpers;
using Content.Shared.Silicons.Laws;
using Content.Shared.Silicons.Laws.Components;
using Content.Shared.Station.Components;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;

View File

@@ -2,9 +2,11 @@ using Content.Server.GameTicking.Rules.Components;
using Content.Server.StationEvents.Components;
using Content.Server.Traits.Assorted;
using Content.Shared.GameTicking.Components;
using Content.Shared.Humanoid;
using Content.Shared.Mind.Components;
using Content.Shared.Traits.Assorted;
namespace Content.Server.StationEvents.Events;
public sealed class MassHallucinationsRule : StationEventSystem<MassHallucinationsRuleComponent>
@@ -14,16 +16,17 @@ public sealed class MassHallucinationsRule : StationEventSystem<MassHallucinatio
protected override void Started(EntityUid uid, MassHallucinationsRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
{
base.Started(uid, component, gameRule, args);
var query = EntityQueryEnumerator<MindContainerComponent>();
while (query.MoveNext(out var ent, out _))
var query = EntityQueryEnumerator<MindContainerComponent, HumanoidAppearanceComponent>();
while (query.MoveNext(out var ent, out _, out _))
{
if (!HasComp<ParacusiaComponent>(ent))
if (!EnsureComp<ParacusiaComponent>(ent, out var paracusia))
{
EnsureComp<MassHallucinationsComponent>(ent);
var paracusia = EnsureComp<ParacusiaComponent>(ent);
_paracusia.SetSounds(ent, component.Sounds, paracusia);
_paracusia.SetTime(ent, component.MinTimeBetweenIncidents, component.MaxTimeBetweenIncidents, paracusia);
_paracusia.SetDistance(ent, component.MaxSoundDistance);
component.AffectedEntities.Add(ent);
}
}
}
@@ -31,10 +34,12 @@ public sealed class MassHallucinationsRule : StationEventSystem<MassHallucinatio
protected override void Ended(EntityUid uid, MassHallucinationsRuleComponent component, GameRuleComponent gameRule, GameRuleEndedEvent args)
{
base.Ended(uid, component, gameRule, args);
var query = EntityQueryEnumerator<MassHallucinationsComponent>();
while (query.MoveNext(out var ent, out _))
foreach (var ent in component.AffectedEntities)
{
RemComp<ParacusiaComponent>(ent);
}
component.AffectedEntities.Clear();
}
}

View File

@@ -1,10 +1,9 @@
using System.Threading;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Station.Components;
using Content.Server.StationEvents.Components;
using Content.Shared.GameTicking.Components;
using Content.Shared.Station.Components;
using JetBrains.Annotations;
using Robust.Shared.Audio;
using Robust.Shared.Player;

View File

@@ -1,14 +1,13 @@
using Content.Server.Atmos.Piping.Unary.Components;
using Content.Server.Station.Components;
using Content.Server.Fluids.EntitySystems;
using Content.Server.StationEvents.Components;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.GameTicking.Components;
using Content.Shared.Station.Components;
using JetBrains.Annotations;
using Robust.Shared.Random;
using System.Linq;
using Content.Server.Fluids.EntitySystems;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.StationEvents.Components;
using Content.Shared.GameTicking.Components;
namespace Content.Server.StationEvents.Events;

View File

@@ -1,7 +1,6 @@
using Content.Server.StationEvents.Components;
using Content.Server.GameTicking.Rules.Components;
using Content.Server.Station.Components;
using Content.Shared.GameTicking.Components;
using Content.Shared.Station.Components;
using Content.Shared.Storage;
using Robust.Shared.Map;
using Robust.Shared.Random;

View File

@@ -1,7 +1,6 @@
using System.Linq;
using Content.Server.Explosion.EntitySystems;
using Content.Server.Resist;
using Content.Server.Station.Components;
using Content.Server.Storage.Components;
using Content.Shared.Access;
using Content.Shared.Access.Components;
@@ -9,6 +8,7 @@ using Content.Shared.Coordinates;
using Content.Shared.DoAfter;
using Content.Shared.Lock;
using Content.Shared.Mind.Components;
using Content.Shared.Station.Components;
using Content.Shared.Storage.Components;
using Content.Shared.Storage.EntitySystems;
using Content.Shared.Tools.Systems;

View File

@@ -4,7 +4,7 @@ using Content.Shared.IdentityManagement;
using Content.Shared.Popups;
using Content.Shared.Tag;
using Content.Shared.Weapons.Melee.Events;
using Robust.Shared.Audio;
using Content.Shared.Throwing;
using Robust.Shared.Audio.Systems;
namespace Content.Server.Weapons.Melee.Balloon;
@@ -23,6 +23,7 @@ public sealed class BalloonPopperSystem : EntitySystem
public override void Initialize()
{
SubscribeLocalEvent<BalloonPopperComponent, MeleeHitEvent>(OnMeleeHit);
SubscribeLocalEvent<BalloonPopperComponent, ThrowDoHitEvent>(OnThrowHit);
}
private void OnMeleeHit(EntityUid uid, BalloonPopperComponent component, MeleeHitEvent args)
@@ -40,6 +41,15 @@ public sealed class BalloonPopperSystem : EntitySystem
}
}
private void OnThrowHit(EntityUid uid, BalloonPopperComponent component, ThrowDoHitEvent args)
{
foreach (var held in _hands.EnumerateHeld(args.Target))
{
if (_tag.HasTag(held, component.BalloonTag))
PopBallooon(uid, held, component);
}
}
/// <summary>
/// Pops a target balloon, making a popup and playing a sound.
/// </summary>

View File

@@ -9,7 +9,6 @@ using Content.Server.Inventory;
using Content.Server.Mind;
using Content.Server.Mind.Commands;
using Content.Server.NPC;
using Content.Server.NPC.Components;
using Content.Server.NPC.HTN;
using Content.Server.NPC.Systems;
using Content.Server.Roles;
@@ -24,10 +23,8 @@ using Content.Shared.Humanoid;
using Content.Shared.Interaction.Components;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Systems;
using Content.Shared.NPC.Components;
using Content.Shared.NPC.Systems;
using Content.Shared.Nutrition.AnimalHusbandry;
using Content.Shared.Nutrition.Components;
@@ -38,6 +35,7 @@ using Content.Shared.Zombies;
using Content.Shared.Prying.Components;
using Content.Shared.Traits.Assorted;
using Robust.Shared.Audio.Systems;
using Content.Shared.Ghost.Roles.Components;
namespace Content.Server.Zombies
{