Merge remote-tracking branch 'upstream/stable' into ed-30-04-2025-upstream-sync
# Conflicts: # Content.Client/Parallax/ParallaxControl.cs # Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs # Content.IntegrationTests/Tests/PostMapInitTest.cs # Content.Server/Chat/Managers/ChatManager.cs # Content.Server/Fluids/EntitySystems/PuddleSystem.Evaporation.cs # Content.Server/Labels/Label/LabelSystem.cs # Content.Shared/Actions/SharedActionsSystem.cs # Content.Shared/Fluids/Components/EvaporationComponent.cs # Content.Shared/Labels/EntitySystems/SharedLabelSystem.cs # README.md # Resources/Prototypes/Entities/Mobs/Player/admin_ghost.yml # Resources/Prototypes/Maps/Pools/deathmatch.yml # Resources/Prototypes/Maps/arenas.yml
This commit is contained in:
@@ -57,14 +57,14 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
|
||||
var oldProgress = component.Progress.ShallowClone();
|
||||
component.Progress.Clear();
|
||||
|
||||
var water = solution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents);
|
||||
if (water > FixedPoint2.Zero)
|
||||
var mopReagent = solution.GetTotalPrototypeQuantity(_puddleSystem.GetAbsorbentReagents(solution));
|
||||
if (mopReagent > FixedPoint2.Zero)
|
||||
{
|
||||
component.Progress[solution.GetColorWithOnly(_prototype, PuddleSystem.EvaporationReagents)] = water.Float();
|
||||
component.Progress[solution.GetColorWithOnly(_prototype, _puddleSystem.GetAbsorbentReagents(solution))] = mopReagent.Float();
|
||||
}
|
||||
|
||||
var otherColor = solution.GetColorWithout(_prototype, PuddleSystem.EvaporationReagents);
|
||||
var other = (solution.Volume - water).Float();
|
||||
var otherColor = solution.GetColorWithout(_prototype, _puddleSystem.GetAbsorbentReagents(solution));
|
||||
var other = (solution.Volume - mopReagent).Float();
|
||||
|
||||
if (other > 0f)
|
||||
{
|
||||
@@ -180,7 +180,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
|
||||
}
|
||||
|
||||
// Prioritize transferring non-evaporatives if absorbent has any
|
||||
var contaminants = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, transferAmount, PuddleSystem.EvaporationReagents);
|
||||
var contaminants = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, transferAmount, _puddleSystem.GetAbsorbentReagents(absorbentSoln.Comp.Solution));
|
||||
if (contaminants.Volume > 0)
|
||||
{
|
||||
_solutionContainerSystem.TryAddSolution(refillableSoln, contaminants);
|
||||
@@ -205,7 +205,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
|
||||
Entity<SolutionComponent> absorbentSoln,
|
||||
Entity<SolutionComponent> refillableSoln)
|
||||
{
|
||||
var contaminantsFromAbsorbent = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, component.PickupAmount, PuddleSystem.EvaporationReagents);
|
||||
var contaminantsFromAbsorbent = _solutionContainerSystem.SplitSolutionWithout(absorbentSoln, component.PickupAmount, _puddleSystem.GetAbsorbentReagents(absorbentSoln.Comp.Solution));
|
||||
|
||||
var absorbentSolution = absorbentSoln.Comp.Solution;
|
||||
if (contaminantsFromAbsorbent.Volume == FixedPoint2.Zero && absorbentSolution.AvailableVolume == FixedPoint2.Zero)
|
||||
@@ -222,7 +222,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
|
||||
absorbentSolution.AvailableVolume;
|
||||
|
||||
var refillableSolution = refillableSoln.Comp.Solution;
|
||||
var waterFromRefillable = refillableSolution.SplitSolutionWithOnly(waterPulled, PuddleSystem.EvaporationReagents);
|
||||
var waterFromRefillable = refillableSolution.SplitSolutionWithOnly(waterPulled, _puddleSystem.GetAbsorbentReagents(refillableSoln.Comp.Solution));
|
||||
_solutionContainerSystem.UpdateChemicals(refillableSoln);
|
||||
|
||||
if (waterFromRefillable.Volume == FixedPoint2.Zero && contaminantsFromAbsorbent.Volume == FixedPoint2.Zero)
|
||||
@@ -284,7 +284,7 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
|
||||
|
||||
// Check if we have any evaporative reagents on our absorber to transfer
|
||||
var absorberSolution = absorberSoln.Comp.Solution;
|
||||
var available = absorberSolution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents);
|
||||
var available = absorberSolution.GetTotalPrototypeQuantity(_puddleSystem.GetAbsorbentReagents(absorberSolution));
|
||||
|
||||
// No material
|
||||
if (available == FixedPoint2.Zero)
|
||||
@@ -296,8 +296,8 @@ public sealed class AbsorbentSystem : SharedAbsorbentSystem
|
||||
var transferMax = absorber.PickupAmount;
|
||||
var transferAmount = available > transferMax ? transferMax : available;
|
||||
|
||||
var puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagents);
|
||||
var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, PuddleSystem.EvaporationReagents);
|
||||
var puddleSplit = puddleSolution.SplitSolutionWithout(transferAmount, _puddleSystem.GetAbsorbentReagents(puddleSolution));
|
||||
var absorberSplit = absorberSolution.SplitSolutionWithOnly(puddleSplit.Volume, _puddleSystem.GetAbsorbentReagents(absorberSolution));
|
||||
|
||||
// Do tile reactions first
|
||||
var transform = Transform(target);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Weather;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Content.Shared.Maps;
|
||||
@@ -36,7 +37,7 @@ public sealed partial class PuddleSystem
|
||||
return;
|
||||
}
|
||||
|
||||
if (solution.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero)
|
||||
if (solution.GetTotalPrototypeQuantity(GetEvaporatingReagents(solution)) > FixedPoint2.Zero)
|
||||
{
|
||||
var evaporation = AddComp<EvaporationComponent>(uid);
|
||||
evaporation.NextTick = _timing.CurTime + EvaporationCooldown;
|
||||
@@ -61,14 +62,17 @@ public sealed partial class PuddleSystem
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, puddle.SolutionName, ref puddle.Solution, out var puddleSolution))
|
||||
continue;
|
||||
|
||||
var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds;
|
||||
foreach ((string evaporatingReagent, FixedPoint2 evaporatingSpeed) in GetEvaporationSpeeds(puddleSolution))
|
||||
{
|
||||
var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds * evaporatingSpeed;
|
||||
puddleSolution.SplitSolutionWithOnly(reagentTick, evaporatingReagent);
|
||||
}
|
||||
|
||||
//CP14 Force evaporation
|
||||
if (!evaporation.CP14ForceEvaporation)
|
||||
puddleSolution.SplitSolutionWithOnly(reagentTick, EvaporationReagents);
|
||||
else
|
||||
if (evaporation.CP14ForceEvaporation)
|
||||
{
|
||||
var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds;
|
||||
puddleSolution.SplitSolution(reagentTick);
|
||||
//CP14 end force evaporation
|
||||
}
|
||||
|
||||
// Despawn if we're done
|
||||
if (puddleSolution.Volume == FixedPoint2.Zero)
|
||||
|
||||
@@ -2,11 +2,14 @@ using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Fluids;
|
||||
using Content.Shared.Nutrition.EntitySystems;
|
||||
|
||||
namespace Content.Server.Fluids.EntitySystems;
|
||||
|
||||
public sealed partial class PuddleSystem
|
||||
{
|
||||
[Dependency] private readonly OpenableSystem _openable = default!;
|
||||
|
||||
private void InitializeTransfers()
|
||||
{
|
||||
SubscribeLocalEvent<RefillableSolutionComponent, DragDropDraggedEvent>(OnRefillableDragged);
|
||||
@@ -14,6 +17,12 @@ public sealed partial class PuddleSystem
|
||||
|
||||
private void OnRefillableDragged(Entity<RefillableSolutionComponent> entity, ref DragDropDraggedEvent args)
|
||||
{
|
||||
if (!_actionBlocker.CanComplexInteract(args.User))
|
||||
{
|
||||
_popups.PopupEntity(Loc.GetString("mopping-system-no-hands"), args.User, args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_solutionContainerSystem.TryGetSolution(entity.Owner, entity.Comp.Solution, out var soln, out var solution) || solution.Volume == FixedPoint2.Zero)
|
||||
{
|
||||
_popups.PopupEntity(Loc.GetString("mopping-system-empty", ("used", entity.Owner)), entity, args.User);
|
||||
@@ -26,6 +35,12 @@ public sealed partial class PuddleSystem
|
||||
if (!_solutionContainerSystem.TryGetDumpableSolution((args.Target, dump, null), out var dumpableSoln, out var dumpableSolution))
|
||||
return;
|
||||
|
||||
if (!_solutionContainerSystem.TryGetDrainableSolution(entity.Owner, out _, out _))
|
||||
return;
|
||||
|
||||
if (_openable.IsClosed(entity))
|
||||
return;
|
||||
|
||||
bool success = true;
|
||||
if (dump.Unlimited)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ using Content.Server.Chemistry.TileReactions;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Server.Spreader;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
@@ -40,6 +41,7 @@ namespace Content.Server.Fluids.EntitySystems;
|
||||
/// </summary>
|
||||
public sealed partial class PuddleSystem : SharedPuddleSystem
|
||||
{
|
||||
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly SharedMapSystem _map = default!;
|
||||
@@ -56,6 +58,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
||||
[Dependency] private readonly StepTriggerSystem _stepTrigger = default!;
|
||||
[Dependency] private readonly SpeedModifierContactsSystem _speedModContacts = default!;
|
||||
[Dependency] private readonly TileFrictionController _tile = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
|
||||
[ValidatePrototypeId<ReagentPrototype>]
|
||||
private const string Blood = "Blood";
|
||||
@@ -68,8 +71,6 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
||||
|
||||
private static string[] _standoutReagents = [Blood, Slime, CopperBlood];
|
||||
|
||||
public static readonly float PuddleVolume = 1000;
|
||||
|
||||
// Using local deletion queue instead of the standard queue so that we can easily "undelete" if a puddle
|
||||
// loses & then gains reagents in a single tick.
|
||||
private HashSet<EntityUid> _deletionQueue = [];
|
||||
@@ -91,7 +92,6 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
||||
// Shouldn't need re-anchoring.
|
||||
SubscribeLocalEvent<PuddleComponent, AnchorStateChangedEvent>(OnAnchorChanged);
|
||||
SubscribeLocalEvent<PuddleComponent, SolutionContainerChangedEvent>(OnSolutionUpdate);
|
||||
SubscribeLocalEvent<PuddleComponent, ComponentInit>(OnPuddleInit);
|
||||
SubscribeLocalEvent<PuddleComponent, SpreadNeighborsEvent>(OnPuddleSpread);
|
||||
SubscribeLocalEvent<PuddleComponent, SlipEvent>(OnPuddleSlip);
|
||||
|
||||
@@ -324,11 +324,6 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
||||
TickEvaporation();
|
||||
}
|
||||
|
||||
private void OnPuddleInit(Entity<PuddleComponent> entity, ref ComponentInit args)
|
||||
{
|
||||
_solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName, out _, FixedPoint2.New(PuddleVolume));
|
||||
}
|
||||
|
||||
private void OnSolutionUpdate(Entity<PuddleComponent> entity, ref SolutionContainerChangedEvent args)
|
||||
{
|
||||
if (args.SolutionId != entity.Comp.SolutionName)
|
||||
@@ -341,7 +336,7 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
||||
}
|
||||
|
||||
_deletionQueue.Remove(entity);
|
||||
UpdateSlip(entity, entity.Comp, args.Solution);
|
||||
UpdateSlip((entity, entity.Comp), args.Solution);
|
||||
UpdateSlow(entity, args.Solution);
|
||||
//UpdateEvaporation(entity, args.Solution); //CP14 Force evaporation under sky via YML
|
||||
UpdateAppearance(entity, entity.Comp);
|
||||
@@ -386,62 +381,89 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
||||
_appearance.SetData(uid, PuddleVisuals.SolutionColor, color, appearance);
|
||||
}
|
||||
|
||||
private void UpdateSlip(EntityUid entityUid, PuddleComponent component, Solution solution)
|
||||
private void UpdateSlip(Entity<PuddleComponent> entity, Solution solution)
|
||||
{
|
||||
var isSlippery = false;
|
||||
var isSuperSlippery = false;
|
||||
// The base sprite is currently at 0.3 so we require at least 2nd tier to be slippery or else it's too hard to see.
|
||||
var amountRequired = FixedPoint2.New(component.OverflowVolume.Float() * LowThreshold);
|
||||
var slipperyAmount = FixedPoint2.Zero;
|
||||
if (!TryComp<StepTriggerComponent>(entity, out var comp))
|
||||
return;
|
||||
|
||||
// Utilize the defaults from their relevant systems... this sucks, and is a bandaid
|
||||
var launchForwardsMultiplier = SlipperyComponent.DefaultLaunchForwardsMultiplier;
|
||||
var paralyzeTime = SlipperyComponent.DefaultParalyzeTime;
|
||||
var requiredSlipSpeed = StepTriggerComponent.DefaultRequiredTriggeredSpeed;
|
||||
// This is the base amount of reagent needed before a puddle can be considered slippery. Is defined based on
|
||||
// the sprite threshold for a puddle larger than 5 pixels.
|
||||
var smallPuddleThreshold = FixedPoint2.New(entity.Comp.OverflowVolume.Float() * LowThreshold);
|
||||
|
||||
// Stores how many units of slippery reagents a puddle has
|
||||
var slipperyUnits = FixedPoint2.Zero;
|
||||
// Stores how many units of super slippery reagents a puddle has
|
||||
var superSlipperyUnits = FixedPoint2.Zero;
|
||||
|
||||
// These three values will be averaged later and all start at zero so the calculations work
|
||||
// A cumulative weighted amount of minimum speed to slip values
|
||||
var puddleFriction = FixedPoint2.Zero;
|
||||
// A cumulative weighted amount of minimum speed to slip values
|
||||
var slipStepTrigger = FixedPoint2.Zero;
|
||||
// A cumulative weighted amount of launch multipliers from slippery reagents
|
||||
var launchMult = FixedPoint2.Zero;
|
||||
// A cumulative weighted amount of stun times from slippery reagents
|
||||
var stunTimer = TimeSpan.Zero;
|
||||
|
||||
// Check if the puddle is big enough to slip in to avoid doing unnecessary logic
|
||||
if (solution.Volume <= smallPuddleThreshold)
|
||||
{
|
||||
_stepTrigger.SetActive(entity, false, comp);
|
||||
_tile.SetModifier(entity, TileFrictionController.DefaultFriction);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TryComp<SlipperyComponent>(entity, out var slipComp))
|
||||
return;
|
||||
|
||||
foreach (var (reagent, quantity) in solution.Contents)
|
||||
{
|
||||
var reagentProto = _prototypeManager.Index<ReagentPrototype>(reagent.Prototype);
|
||||
|
||||
if (!reagentProto.Slippery)
|
||||
// Calculate the minimum speed needed to slip in the puddle. Average the overall slip thresholds for all reagents
|
||||
var deltaSlipTrigger = reagentProto.SlipData?.RequiredSlipSpeed ?? entity.Comp.DefaultSlippery;
|
||||
slipStepTrigger += quantity * deltaSlipTrigger;
|
||||
|
||||
// Aggregate Friction based on quantity
|
||||
puddleFriction += reagentProto.Friction * quantity;
|
||||
|
||||
if (reagentProto.SlipData == null)
|
||||
continue;
|
||||
slipperyAmount += quantity;
|
||||
|
||||
if (slipperyAmount <= amountRequired)
|
||||
continue;
|
||||
isSlippery = true;
|
||||
slipperyUnits += quantity;
|
||||
// Aggregate launch speed based on quantity
|
||||
launchMult += reagentProto.SlipData.LaunchForwardsMultiplier * quantity;
|
||||
// Aggregate stun times based on quantity
|
||||
stunTimer += reagentProto.SlipData.ParalyzeTime * (float)quantity;
|
||||
|
||||
foreach (var tileReaction in reagentProto.TileReactions)
|
||||
{
|
||||
if (tileReaction is not SpillTileReaction spillTileReaction)
|
||||
continue;
|
||||
isSuperSlippery = spillTileReaction.SuperSlippery;
|
||||
launchForwardsMultiplier = launchForwardsMultiplier < spillTileReaction.LaunchForwardsMultiplier ? spillTileReaction.LaunchForwardsMultiplier : launchForwardsMultiplier;
|
||||
requiredSlipSpeed = requiredSlipSpeed > spillTileReaction.RequiredSlipSpeed ? spillTileReaction.RequiredSlipSpeed : requiredSlipSpeed;
|
||||
paralyzeTime = paralyzeTime < spillTileReaction.ParalyzeTime ? spillTileReaction.ParalyzeTime : paralyzeTime;
|
||||
}
|
||||
if (reagentProto.SlipData.SuperSlippery)
|
||||
superSlipperyUnits += quantity;
|
||||
}
|
||||
|
||||
if (isSlippery)
|
||||
// Turn on the step trigger if it's slippery
|
||||
_stepTrigger.SetActive(entity, slipperyUnits > smallPuddleThreshold, comp);
|
||||
|
||||
// This is based of the total volume and not just the slippery volume because there is a default
|
||||
// slippery for all reagents even if they aren't technically slippery.
|
||||
slipComp.SlipData.RequiredSlipSpeed = (float)(slipStepTrigger / solution.Volume);
|
||||
_stepTrigger.SetRequiredTriggerSpeed(entity, slipComp.SlipData.RequiredSlipSpeed);
|
||||
|
||||
// Divide these both by only total amount of slippery reagents.
|
||||
// A puddle with 10 units of lube vs a puddle with 10 of lube and 20 catchup should stun and launch forward the same amount.
|
||||
if (slipperyUnits > 0)
|
||||
{
|
||||
var comp = EnsureComp<StepTriggerComponent>(entityUid);
|
||||
_stepTrigger.SetActive(entityUid, true, comp);
|
||||
var friction = EnsureComp<TileFrictionModifierComponent>(entityUid);
|
||||
_tile.SetModifier(entityUid, TileFrictionController.DefaultFriction * 0.5f, friction);
|
||||
|
||||
if (!TryComp<SlipperyComponent>(entityUid, out var slipperyComponent))
|
||||
return;
|
||||
slipperyComponent.SuperSlippery = isSuperSlippery;
|
||||
_stepTrigger.SetRequiredTriggerSpeed(entityUid, requiredSlipSpeed);
|
||||
slipperyComponent.LaunchForwardsMultiplier = launchForwardsMultiplier;
|
||||
slipperyComponent.ParalyzeTime = paralyzeTime;
|
||||
|
||||
}
|
||||
else if (TryComp<StepTriggerComponent>(entityUid, out var comp))
|
||||
{
|
||||
_stepTrigger.SetActive(entityUid, false, comp);
|
||||
RemCompDeferred<TileFrictionModifierComponent>(entityUid);
|
||||
slipComp.SlipData.LaunchForwardsMultiplier = (float)(launchMult/slipperyUnits);
|
||||
slipComp.SlipData.ParalyzeTime = (stunTimer/(float)slipperyUnits);
|
||||
}
|
||||
|
||||
// Only make it super slippery if there is enough super slippery units for its own puddle
|
||||
slipComp.SlipData.SuperSlippery = superSlipperyUnits >= smallPuddleThreshold;
|
||||
|
||||
// Lower tile friction based on how slippery it is, lets items slide across a puddle of lube
|
||||
slipComp.SlipData.SlipFriction = (float)(puddleFriction/solution.Volume);
|
||||
_tile.SetModifier(entity, TileFrictionController.DefaultFriction * slipComp.SlipData.SlipFriction);
|
||||
|
||||
Dirty(entity, slipComp);
|
||||
}
|
||||
|
||||
private void UpdateSlow(EntityUid uid, Solution solution)
|
||||
@@ -626,7 +648,8 @@ public sealed partial class PuddleSystem : SharedPuddleSystem
|
||||
return false;
|
||||
}
|
||||
|
||||
var gridUid = coordinates.GetGridUid(EntityManager);
|
||||
var gridUid = _transform.GetGrid(coordinates);
|
||||
|
||||
if (!TryComp<MapGridComponent>(gridUid, out var mapGrid))
|
||||
{
|
||||
puddleUid = EntityUid.Invalid;
|
||||
|
||||
@@ -3,14 +3,16 @@ using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Server.Gravity;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Fluids;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Timing;
|
||||
using Content.Shared.Vapor;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Numerics;
|
||||
@@ -30,6 +32,9 @@ public sealed class SpraySystem : EntitySystem
|
||||
[Dependency] private readonly VaporSystem _vapor = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _transform = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
private float _gridImpulseMultiplier;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -37,6 +42,7 @@ public sealed class SpraySystem : EntitySystem
|
||||
|
||||
SubscribeLocalEvent<SprayComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
SubscribeLocalEvent<SprayComponent, UserActivateInWorldEvent>(OnActivateInWorld);
|
||||
Subs.CVar(_cfg, CCVars.GridImpulseMultiplier, UpdateGridMassMultiplier, true);
|
||||
}
|
||||
|
||||
private void OnActivateInWorld(Entity<SprayComponent> entity, ref UserActivateInWorldEvent args)
|
||||
@@ -51,6 +57,11 @@ public sealed class SpraySystem : EntitySystem
|
||||
Spray(entity, args.User, targetMapPos);
|
||||
}
|
||||
|
||||
private void UpdateGridMassMultiplier(float value)
|
||||
{
|
||||
_gridImpulseMultiplier = value;
|
||||
}
|
||||
|
||||
private void OnAfterInteract(Entity<SprayComponent> entity, ref AfterInteractEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
@@ -156,7 +167,21 @@ public sealed class SpraySystem : EntitySystem
|
||||
if (TryComp<PhysicsComponent>(user, out var body))
|
||||
{
|
||||
if (_gravity.IsWeightless(user, body))
|
||||
_physics.ApplyLinearImpulse(user, -impulseDirection.Normalized() * entity.Comp.PushbackAmount, body: body);
|
||||
{
|
||||
// push back the player
|
||||
_physics.ApplyLinearImpulse(user, -impulseDirection * entity.Comp.PushbackAmount, body: body);
|
||||
}
|
||||
else
|
||||
{
|
||||
// push back the grid the player is standing on
|
||||
var userTransform = Transform(user);
|
||||
if (userTransform.GridUid == userTransform.ParentUid)
|
||||
{
|
||||
// apply both linear and angular momentum depending on the player position
|
||||
// multiply by a cvar because grid mass is currently extremely small compared to all other masses
|
||||
_physics.ApplyLinearImpulse(userTransform.GridUid.Value, -impulseDirection * _gridImpulseMultiplier * entity.Comp.PushbackAmount, userTransform.LocalPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user