Merge remote-tracking branch 'space-station-14/master'
This commit is contained in:
@@ -24,6 +24,14 @@ public sealed partial class AdvertiseComponent : Component
|
||||
[DataField]
|
||||
public int MaximumWait { get; private set; } = 10 * 60;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the delay before the first advertisement (at MapInit) will ignore <see cref="MinimumWait"/>
|
||||
/// and instead be rolled between 0 and <see cref="MaximumWait"/>. This only applies to the initial delay;
|
||||
/// <see cref="MinimumWait"/> will be respected after that.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool Prewarm = true;
|
||||
|
||||
/// <summary>
|
||||
/// The identifier for the advertisements pack prototype.
|
||||
/// </summary>
|
||||
|
||||
@@ -37,13 +37,14 @@ public sealed class AdvertiseSystem : EntitySystem
|
||||
|
||||
private void OnMapInit(EntityUid uid, AdvertiseComponent advert, MapInitEvent args)
|
||||
{
|
||||
RandomizeNextAdvertTime(advert);
|
||||
var prewarm = advert.Prewarm;
|
||||
RandomizeNextAdvertTime(advert, prewarm);
|
||||
_nextCheckTime = MathHelper.Min(advert.NextAdvertisementTime, _nextCheckTime);
|
||||
}
|
||||
|
||||
private void RandomizeNextAdvertTime(AdvertiseComponent advert)
|
||||
private void RandomizeNextAdvertTime(AdvertiseComponent advert, bool prewarm = false)
|
||||
{
|
||||
var minDuration = Math.Max(1, advert.MinimumWait);
|
||||
var minDuration = prewarm ? 0 : Math.Max(1, advert.MinimumWait);
|
||||
var maxDuration = Math.Max(minDuration, advert.MaximumWait);
|
||||
var waitDuration = TimeSpan.FromSeconds(_random.Next(minDuration, maxDuration));
|
||||
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Server.GameTicking;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Server.Inventory;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Station.Components;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Server.StationRecords;
|
||||
using Content.Server.StationRecords.Systems;
|
||||
using Content.Shared.StationRecords;
|
||||
using Content.Shared.UserInterface;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.Bed.Cryostorage;
|
||||
@@ -32,6 +37,7 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly AudioSystem _audio = default!;
|
||||
[Dependency] private readonly AccessReaderSystem _accessReader = default!;
|
||||
[Dependency] private readonly ChatSystem _chatSystem = default!;
|
||||
[Dependency] private readonly ClimbSystem _climb = default!;
|
||||
[Dependency] private readonly ContainerSystem _container = default!;
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
@@ -40,6 +46,7 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
[Dependency] private readonly StationJobsSystem _stationJobs = default!;
|
||||
[Dependency] private readonly StationRecordsSystem _stationRecords = default!;
|
||||
[Dependency] private readonly TransformSystem _transform = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||
|
||||
@@ -163,26 +170,30 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
|
||||
{
|
||||
var comp = ent.Comp;
|
||||
var cryostorageEnt = ent.Comp.Cryostorage;
|
||||
|
||||
var station = _station.GetOwningStation(ent);
|
||||
var name = Name(ent.Owner);
|
||||
|
||||
if (!TryComp<CryostorageComponent>(cryostorageEnt, out var cryostorageComponent))
|
||||
return;
|
||||
|
||||
// if we have a session, we use that to add back in all the job slots the player had.
|
||||
if (userId != null)
|
||||
{
|
||||
foreach (var station in _station.GetStationsSet())
|
||||
foreach (var uniqueStation in _station.GetStationsSet())
|
||||
{
|
||||
if (!TryComp<StationJobsComponent>(station, out var stationJobs))
|
||||
if (!TryComp<StationJobsComponent>(uniqueStation, out var stationJobs))
|
||||
continue;
|
||||
|
||||
if (!_stationJobs.TryGetPlayerJobs(station, userId.Value, out var jobs, stationJobs))
|
||||
if (!_stationJobs.TryGetPlayerJobs(uniqueStation, userId.Value, out var jobs, stationJobs))
|
||||
continue;
|
||||
|
||||
foreach (var job in jobs)
|
||||
{
|
||||
_stationJobs.TryAdjustJobSlot(station, job, 1, clamp: true);
|
||||
_stationJobs.TryAdjustJobSlot(uniqueStation, job, 1, clamp: true);
|
||||
}
|
||||
|
||||
_stationJobs.TryRemovePlayerJobs(station, userId.Value, stationJobs);
|
||||
_stationJobs.TryRemovePlayerJobs(uniqueStation, userId.Value, stationJobs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,12 +214,33 @@ public sealed class CryostorageSystem : SharedCryostorageSystem
|
||||
_gameTicker.OnGhostAttempt(mind.Value, false);
|
||||
}
|
||||
}
|
||||
|
||||
comp.AllowReEnteringBody = false;
|
||||
_transform.SetParent(ent, PausedMap.Value);
|
||||
cryostorageComponent.StoredPlayers.Add(ent);
|
||||
Dirty(ent, comp);
|
||||
UpdateCryostorageUIState((cryostorageEnt.Value, cryostorageComponent));
|
||||
AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(ent):player} was entered into cryostorage inside of {ToPrettyString(cryostorageEnt.Value)}");
|
||||
|
||||
if (!TryComp<StationRecordsComponent>(station, out var stationRecords))
|
||||
return;
|
||||
|
||||
var key = new StationRecordKey(_stationRecords.GetRecordByName(station.Value, name) ?? default(uint), station.Value);
|
||||
var jobName = "Unknown";
|
||||
|
||||
if (_stationRecords.TryGetRecord<GeneralStationRecord>(key, out var entry, stationRecords))
|
||||
jobName = entry.JobTitle;
|
||||
|
||||
_stationRecords.RemoveRecord(key, stationRecords);
|
||||
|
||||
_chatSystem.DispatchStationAnnouncement(station.Value,
|
||||
Loc.GetString(
|
||||
"earlyleave-cryo-announcement",
|
||||
("character", name),
|
||||
("job", CultureInfo.CurrentCulture.TextInfo.ToTitleCase(jobName))
|
||||
), Loc.GetString("earlyleave-cryo-sender"),
|
||||
playDefaultSound: false
|
||||
);
|
||||
}
|
||||
|
||||
private void HandleCryostorageReconnection(Entity<CryostorageContainedComponent> entity)
|
||||
|
||||
@@ -159,7 +159,6 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
if (!_botany.TryGetSeed(seeds, out var seed))
|
||||
return;
|
||||
|
||||
float? seedHealth = seeds.HealthOverride;
|
||||
var name = Loc.GetString(seed.Name);
|
||||
var noun = Loc.GetString(seed.Noun);
|
||||
_popup.PopupCursor(Loc.GetString("plant-holder-component-plant-success-message",
|
||||
@@ -169,9 +168,9 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
component.Seed = seed;
|
||||
component.Dead = false;
|
||||
component.Age = 1;
|
||||
if (seedHealth is float realSeedHealth)
|
||||
if (seeds.HealthOverride != null)
|
||||
{
|
||||
component.Health = realSeedHealth;
|
||||
component.Health = seeds.HealthOverride.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -288,8 +287,18 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
}
|
||||
|
||||
component.Health -= (_random.Next(3, 5) * 10);
|
||||
|
||||
float? healthOverride;
|
||||
if (component.Harvest)
|
||||
{
|
||||
healthOverride = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
healthOverride = component.Health;
|
||||
}
|
||||
component.Seed.Unique = false;
|
||||
var seed = _botany.SpawnSeedPacket(component.Seed, Transform(args.User).Coordinates, args.User, component.Health);
|
||||
var seed = _botany.SpawnSeedPacket(component.Seed, Transform(args.User).Coordinates, args.User, healthOverride);
|
||||
_randomHelper.RandomOffset(seed, 0.25f);
|
||||
var displayName = Loc.GetString(component.Seed.DisplayName);
|
||||
_popup.PopupCursor(Loc.GetString("plant-holder-component-take-sample-message",
|
||||
|
||||
@@ -9,7 +9,6 @@ using Content.Shared.Damage.Systems;
|
||||
using Content.Shared.Explosion;
|
||||
using Content.Shared.Hands.Components;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Input;
|
||||
using Content.Shared.Inventory.VirtualItem;
|
||||
using Content.Shared.Movement.Pulling.Components;
|
||||
@@ -17,8 +16,6 @@ using Content.Shared.Movement.Pulling.Events;
|
||||
using Content.Shared.Movement.Pulling.Systems;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Throwing;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Map;
|
||||
@@ -160,7 +157,7 @@ namespace Content.Server.Hands.Systems
|
||||
continue;
|
||||
}
|
||||
|
||||
QueueDel(hand.HeldEntity.Value);
|
||||
TryDrop(args.PullerUid, hand, handsComp: component);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Shared.Damage;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server.ImmovableRod;
|
||||
@@ -36,4 +37,16 @@ public sealed partial class ImmovableRodComponent : Component
|
||||
/// </summary>
|
||||
[DataField("destroyTiles")]
|
||||
public bool DestroyTiles = true;
|
||||
|
||||
/// <summary>
|
||||
/// If true, this will gib & delete bodies
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool ShouldGib = true;
|
||||
|
||||
/// <summary>
|
||||
/// Damage done, if not gibbing
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public DamageSpecifier? Damage;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Polymorph.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
@@ -22,6 +23,8 @@ public sealed class ImmovableRodSystem : EntitySystem
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly DamageableSystem _damageable = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
@@ -64,11 +67,11 @@ public sealed class ImmovableRodSystem : EntitySystem
|
||||
var vel = component.DirectionOverride.Degrees switch
|
||||
{
|
||||
0f => _random.NextVector2(component.MinSpeed, component.MaxSpeed),
|
||||
_ => xform.WorldRotation.RotateVec(component.DirectionOverride.ToVec()) * _random.NextFloat(component.MinSpeed, component.MaxSpeed)
|
||||
_ => _transform.GetWorldRotation(uid).RotateVec(component.DirectionOverride.ToVec()) * _random.NextFloat(component.MinSpeed, component.MaxSpeed)
|
||||
};
|
||||
|
||||
_physics.ApplyLinearImpulse(uid, vel, body: phys);
|
||||
xform.LocalRotation = (vel - xform.WorldPosition).ToWorldAngle() + MathHelper.PiOver2;
|
||||
xform.LocalRotation = (vel - _transform.GetWorldPosition(uid)).ToWorldAngle() + MathHelper.PiOver2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,12 +97,28 @@ public sealed class ImmovableRodSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
// gib em
|
||||
// dont delete/hurt self if polymoprhed into a rod
|
||||
if (TryComp<PolymorphedEntityComponent>(uid, out var polymorphed))
|
||||
{
|
||||
if (polymorphed.Parent == ent)
|
||||
return;
|
||||
}
|
||||
|
||||
// gib or damage em
|
||||
if (TryComp<BodyComponent>(ent, out var body))
|
||||
{
|
||||
component.MobCount++;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("immovable-rod-penetrated-mob", ("rod", uid), ("mob", ent)), uid, PopupType.LargeCaution);
|
||||
|
||||
if (!component.ShouldGib)
|
||||
{
|
||||
if (component.Damage == null)
|
||||
return;
|
||||
|
||||
_damageable.TryChangeDamage(ent, component.Damage, ignoreResistances: true);
|
||||
return;
|
||||
}
|
||||
|
||||
_bodySystem.GibBody(ent, body: body);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -118,10 +118,12 @@ public sealed partial class PolymorphSystem : EntitySystem
|
||||
|
||||
private void OnPolymorphActionEvent(Entity<PolymorphableComponent> ent, ref PolymorphActionEvent args)
|
||||
{
|
||||
if (!_proto.TryIndex(args.ProtoId, out var prototype))
|
||||
if (!_proto.TryIndex(args.ProtoId, out var prototype) || args.Handled)
|
||||
return;
|
||||
|
||||
PolymorphEntity(ent, prototype.Configuration);
|
||||
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnRevertPolymorphActionEvent(Entity<PolymorphedEntityComponent> ent,
|
||||
|
||||
@@ -66,11 +66,16 @@ public sealed class TegNodeGroup : BaseNodeGroup
|
||||
|
||||
public override void LoadNodes(List<Node> groupNodes)
|
||||
{
|
||||
DebugTools.Assert(groupNodes.Count <= 3, "The TEG has at most 3 parts");
|
||||
DebugTools.Assert(_entityManager != null);
|
||||
|
||||
base.LoadNodes(groupNodes);
|
||||
|
||||
if (groupNodes.Count > 3)
|
||||
{
|
||||
// Somehow got more TEG parts. Probably shenanigans. Bail.
|
||||
return;
|
||||
}
|
||||
|
||||
Generator = groupNodes.OfType<TegNodeGenerator>().SingleOrDefault();
|
||||
if (Generator != null)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,6 @@ using Content.Server.PDA.Ringer;
|
||||
using Content.Server.Stack;
|
||||
using Content.Server.Store.Components;
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
@@ -99,13 +98,13 @@ public sealed partial class StoreSystem
|
||||
}
|
||||
|
||||
//dictionary for all currencies, including 0 values for currencies on the whitelist
|
||||
Dictionary<string, FixedPoint2> allCurrency = new();
|
||||
Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2> allCurrency = new();
|
||||
foreach (var supported in component.CurrencyWhitelist)
|
||||
{
|
||||
allCurrency.Add(supported, FixedPoint2.Zero);
|
||||
|
||||
if (component.Balance.ContainsKey(supported))
|
||||
allCurrency[supported] = component.Balance[supported];
|
||||
if (component.Balance.TryGetValue(supported, out var value))
|
||||
allCurrency[supported] = value;
|
||||
}
|
||||
|
||||
// TODO: if multiple users are supposed to be able to interact with a single BUI & see different
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Ensnaring;
|
||||
using Content.Shared.CombatMode;
|
||||
@@ -20,7 +21,6 @@ using Content.Shared.Verbs;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Strip
|
||||
{
|
||||
@@ -111,7 +111,7 @@ namespace Content.Server.Strip
|
||||
if (TryComp<CombatModeComponent>(user, out var mode) && mode.IsInCombatMode && !openInCombat)
|
||||
return;
|
||||
|
||||
if (TryComp<ActorComponent>(user, out var actor))
|
||||
if (TryComp<ActorComponent>(user, out var actor) && HasComp<StrippingComponent>(user))
|
||||
{
|
||||
if (_userInterfaceSystem.SessionHasOpenUi(strippable, StrippingUiKey.Key, actor.PlayerSession))
|
||||
return;
|
||||
|
||||
@@ -93,6 +93,9 @@ public sealed partial class ActivatableUISystem : EntitySystem
|
||||
if (component.InHandsOnly)
|
||||
return;
|
||||
|
||||
if (component.AllowedItems != null)
|
||||
return;
|
||||
|
||||
args.Handled = InteractUI(args.User, uid, component);
|
||||
}
|
||||
|
||||
@@ -104,6 +107,9 @@ public sealed partial class ActivatableUISystem : EntitySystem
|
||||
if (component.RightClickOnly)
|
||||
return;
|
||||
|
||||
if (component.AllowedItems != null)
|
||||
return;
|
||||
|
||||
args.Handled = InteractUI(args.User, uid, component);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Content.Server.Salvage;
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||
using Content.Shared.Clothing;
|
||||
@@ -42,7 +42,7 @@ public sealed class ArtifactMagnetTriggerSystem : EntitySystem
|
||||
if (!magXform.Coordinates.TryDistance(EntityManager, xform.Coordinates, out var distance))
|
||||
continue;
|
||||
|
||||
if (distance > trigger.Range)
|
||||
if (distance > trigger.MagbootRange)
|
||||
continue;
|
||||
|
||||
_toActivate.Add(artifactUid);
|
||||
|
||||
Reference in New Issue
Block a user