Merge remote-tracking branch 'upstream/master' into ed-03-10-2024-upstream

# Conflicts:
#	Resources/Prototypes/Entities/Mobs/Customization/Markings/human_hair.yml
This commit is contained in:
Ed
2024-10-03 17:34:08 +03:00
284 changed files with 3117 additions and 1387 deletions

View File

@@ -1,5 +1,4 @@
using Content.Server.DoAfter;
using Content.Server.Fluids.Components;
using Content.Server.Popups;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Audio;
@@ -13,9 +12,7 @@ using Content.Shared.Fluids.Components;
using Content.Shared.Interaction;
using Content.Shared.Tag;
using Content.Shared.Verbs;
using Robust.Server.GameObjects;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Collections;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;
@@ -32,19 +29,27 @@ public sealed class DrainSystem : SharedDrainSystem
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
private readonly HashSet<Entity<PuddleComponent>> _puddles = new();
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<DrainComponent, MapInitEvent>(OnDrainMapInit);
SubscribeLocalEvent<DrainComponent, GetVerbsEvent<Verb>>(AddEmptyVerb);
SubscribeLocalEvent<DrainComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<DrainComponent, AfterInteractUsingEvent>(OnInteract);
SubscribeLocalEvent<DrainComponent, DrainDoAfterEvent>(OnDoAfter);
}
private void OnDrainMapInit(Entity<DrainComponent> ent, ref MapInitEvent args)
{
// Randomise puddle drains so roundstart ones don't all dump at the same time.
ent.Comp.Accumulator = _random.NextFloat(ent.Comp.DrainFrequency);
}
private void AddEmptyVerb(Entity<DrainComponent> entity, ref GetVerbsEvent<Verb> args)
{
if (!args.CanAccess || !args.CanInteract || args.Using == null)
@@ -118,9 +123,6 @@ public sealed class DrainSystem : SharedDrainSystem
{
base.Update(frameTime);
var managerQuery = GetEntityQuery<SolutionContainerManagerComponent>();
var xformQuery = GetEntityQuery<TransformComponent>();
var puddleQuery = GetEntityQuery<PuddleComponent>();
var puddles = new ValueList<(Entity<PuddleComponent> Entity, string Solution)>();
var query = EntityQueryEnumerator<DrainComponent>();
while (query.MoveNext(out var uid, out var drain))
@@ -158,22 +160,10 @@ public sealed class DrainSystem : SharedDrainSystem
// This will ensure that UnitsPerSecond is per second...
var amount = drain.UnitsPerSecond * drain.DrainFrequency;
if (!xformQuery.TryGetComponent(uid, out var xform))
continue;
_puddles.Clear();
_lookup.GetEntitiesInRange(Transform(uid).Coordinates, drain.Range, _puddles);
puddles.Clear();
foreach (var entity in _lookup.GetEntitiesInRange(_transform.GetMapCoordinates(uid, xform), drain.Range))
{
// No InRangeUnobstructed because there's no collision group that fits right now
// and these are placed by mappers and not buildable/movable so shouldnt really be a problem...
if (puddleQuery.TryGetComponent(entity, out var puddle))
{
puddles.Add(((entity, puddle), puddle.SolutionName));
}
}
if (puddles.Count == 0)
if (_puddles.Count == 0)
{
_ambientSoundSystem.SetAmbience(uid, false);
continue;
@@ -181,13 +171,13 @@ public sealed class DrainSystem : SharedDrainSystem
_ambientSoundSystem.SetAmbience(uid, true);
amount /= puddles.Count;
amount /= _puddles.Count;
foreach (var (puddle, solution) in puddles)
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, solution, ref puddle.Comp.Solution, out var puddleSolution))
if (!_solutionContainerSystem.ResolveSolution(puddle.Owner, puddle.Comp.SolutionName, ref puddle.Comp.Solution, out var puddleSolution))
{
EntityManager.QueueDeleteEntity(puddle);
continue;

View File

@@ -14,6 +14,7 @@ using Robust.Shared.Audio.Systems;
using Robust.Shared.Physics.Components;
using Robust.Shared.Prototypes;
using System.Numerics;
using Robust.Shared.Map;
namespace Content.Server.Fluids.EntitySystems;
@@ -35,6 +36,19 @@ public sealed class SpraySystem : EntitySystem
base.Initialize();
SubscribeLocalEvent<SprayComponent, AfterInteractEvent>(OnAfterInteract);
SubscribeLocalEvent<SprayComponent, UserActivateInWorldEvent>(OnActivateInWorld);
}
private void OnActivateInWorld(Entity<SprayComponent> entity, ref UserActivateInWorldEvent args)
{
if (args.Handled)
return;
args.Handled = true;
var targetMapPos = _transform.GetMapCoordinates(GetEntityQuery<TransformComponent>().GetComponent(args.Target));
Spray(entity, args.User, targetMapPos);
}
private void OnAfterInteract(Entity<SprayComponent> entity, ref AfterInteractEvent args)
@@ -44,29 +58,36 @@ public sealed class SpraySystem : EntitySystem
args.Handled = true;
var clickPos = _transform.ToMapCoordinates(args.ClickLocation);
Spray(entity, args.User, clickPos);
}
public void Spray(Entity<SprayComponent> entity, EntityUid user, MapCoordinates mapcoord)
{
if (!_solutionContainer.TryGetSolution(entity.Owner, SprayComponent.SolutionName, out var soln, out var solution))
return;
var ev = new SprayAttemptEvent(args.User);
var ev = new SprayAttemptEvent(user);
RaiseLocalEvent(entity, ref ev);
if (ev.Cancelled)
return;
if (!TryComp<UseDelayComponent>(entity, out var useDelay)
|| _useDelay.IsDelayed((entity, useDelay)))
if (TryComp<UseDelayComponent>(entity, out var useDelay)
&& _useDelay.IsDelayed((entity, useDelay)))
return;
if (solution.Volume <= 0)
{
_popupSystem.PopupEntity(Loc.GetString("spray-component-is-empty-message"), entity.Owner, args.User);
_popupSystem.PopupEntity(Loc.GetString("spray-component-is-empty-message"), entity.Owner, user);
return;
}
var xformQuery = GetEntityQuery<TransformComponent>();
var userXform = xformQuery.GetComponent(args.User);
var userXform = xformQuery.GetComponent(user);
var userMapPos = _transform.GetMapCoordinates(userXform);
var clickMapPos = args.ClickLocation.ToMap(EntityManager, _transform);
var clickMapPos = mapcoord;
var diffPos = clickMapPos.Position - userMapPos.Position;
if (diffPos == Vector2.Zero || diffPos == Vector2Helpers.NaN)
@@ -88,8 +109,6 @@ public sealed class SpraySystem : EntitySystem
var amount = Math.Max(Math.Min((solution.Volume / entity.Comp.TransferAmount).Int(), entity.Comp.VaporAmount), 1);
var spread = entity.Comp.VaporSpread / amount;
// TODO: Just use usedelay homie.
var cooldownTime = 0f;
for (var i = 0; i < amount; i++)
{
@@ -131,20 +150,19 @@ public sealed class SpraySystem : EntitySystem
// impulse direction is defined in world-coordinates, not local coordinates
var impulseDirection = rotation.ToVec();
var time = diffLength / entity.Comp.SprayVelocity;
cooldownTime = MathF.Max(time, cooldownTime);
_vapor.Start(ent, vaporXform, impulseDirection * diffLength, entity.Comp.SprayVelocity, target, time, args.User);
_vapor.Start(ent, vaporXform, impulseDirection * diffLength, entity.Comp.SprayVelocity, target, time, user);
if (TryComp<PhysicsComponent>(args.User, out var body))
if (TryComp<PhysicsComponent>(user, out var body))
{
if (_gravity.IsWeightless(args.User, body))
_physics.ApplyLinearImpulse(args.User, -impulseDirection.Normalized() * entity.Comp.PushbackAmount, body: body);
if (_gravity.IsWeightless(user, body))
_physics.ApplyLinearImpulse(user, -impulseDirection.Normalized() * entity.Comp.PushbackAmount, body: body);
}
}
_audio.PlayPvs(entity.Comp.SpraySound, entity, entity.Comp.SpraySound.Params.WithVariation(0.125f));
_useDelay.SetLength(entity.Owner, TimeSpan.FromSeconds(cooldownTime));
_useDelay.TryResetDelay((entity, useDelay));
if (useDelay != null)
_useDelay.TryResetDelay((entity, useDelay));
}
}