2023-07-08 14:08:32 +10:00
using System.Numerics ;
2022-06-11 18:54:41 -07:00
using Content.Server.Chemistry.Components ;
2021-10-29 13:40:15 +01:00
using Content.Server.Chemistry.Components.SolutionManager ;
2021-09-06 15:49:44 +02:00
using Content.Shared.Chemistry.Components ;
2021-07-21 22:26:09 +10:00
using Content.Shared.Chemistry.Reagent ;
2021-11-03 16:48:03 -07:00
using Content.Shared.FixedPoint ;
2021-07-21 22:26:09 +10:00
using Content.Shared.Physics ;
2022-07-15 12:45:21 +10:00
using Content.Shared.Spawners.Components ;
using Content.Shared.Throwing ;
2021-09-06 15:49:44 +02:00
using Content.Shared.Vapor ;
2020-12-08 11:56:10 +01:00
using JetBrains.Annotations ;
2021-07-21 22:26:09 +10:00
using Robust.Shared.Map ;
2022-11-22 13:12:04 +11:00
using Robust.Shared.Map.Components ;
2022-09-14 17:26:26 +10:00
using Robust.Shared.Physics.Components ;
2021-07-21 22:26:09 +10:00
using Robust.Shared.Physics.Dynamics ;
2022-09-14 17:26:26 +10:00
using Robust.Shared.Physics.Events ;
2023-01-15 15:38:59 +11:00
using Robust.Shared.Physics.Systems ;
2021-07-21 22:26:09 +10:00
using Robust.Shared.Prototypes ;
2020-08-08 14:33:36 +02:00
2021-06-09 22:19:39 +02:00
namespace Content.Server.Chemistry.EntitySystems
2020-08-08 14:33:36 +02:00
{
2020-12-08 11:56:10 +01:00
[UsedImplicitly]
2021-07-21 22:26:09 +10:00
internal sealed class VaporSystem : EntitySystem
2020-08-08 14:33:36 +02:00
{
2021-07-21 22:26:09 +10:00
[Dependency] private readonly IMapManager _mapManager = default ! ;
[Dependency] private readonly IPrototypeManager _protoManager = default ! ;
2023-01-15 15:38:59 +11:00
[Dependency] private readonly SharedPhysicsSystem _physics = default ! ;
2021-09-06 15:49:44 +02:00
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default ! ;
2022-07-15 12:45:21 +10:00
[Dependency] private readonly ThrowingSystem _throwing = default ! ;
2021-07-21 22:26:09 +10:00
private const float ReactTime = 0.125f ;
2023-05-18 01:02:07 +10:00
private ISawmill _sawmill = default ! ;
2021-07-21 22:26:09 +10:00
public override void Initialize ( )
{
base . Initialize ( ) ;
2023-05-18 01:02:07 +10:00
_sawmill = Logger . GetSawmill ( "vapor" ) ;
2021-07-21 22:26:09 +10:00
SubscribeLocalEvent < VaporComponent , StartCollideEvent > ( HandleCollide ) ;
}
2022-09-14 17:26:26 +10:00
private void HandleCollide ( EntityUid uid , VaporComponent component , ref StartCollideEvent args )
2021-07-21 22:26:09 +10:00
{
2021-09-28 13:35:29 +02:00
if ( ! EntityManager . TryGetComponent ( uid , out SolutionContainerManagerComponent ? contents ) ) return ;
2021-07-21 22:26:09 +10:00
2023-01-15 15:38:59 +11:00
foreach ( var value in contents . Solutions . Values )
2021-09-06 15:49:44 +02:00
{
2023-05-09 19:21:26 +12:00
value . DoEntityReaction ( args . OtherEntity , ReactionMethod . Touch ) ;
2021-09-06 15:49:44 +02:00
}
2021-07-21 22:26:09 +10:00
// Check for collision with a impassable object (e.g. wall) and stop
if ( ( args . OtherFixture . CollisionLayer & ( int ) CollisionGroup . Impassable ) ! = 0 & & args . OtherFixture . Hard )
{
2021-09-06 15:49:44 +02:00
EntityManager . QueueDeleteEntity ( uid ) ;
2021-07-21 22:26:09 +10:00
}
}
2022-07-15 12:45:21 +10:00
public void Start ( VaporComponent vapor , TransformComponent vaporXform , Vector2 dir , float speed , MapCoordinates target , float aliveTime , EntityUid ? user = null )
2021-07-21 22:26:09 +10:00
{
vapor . Active = true ;
2022-07-15 12:45:21 +10:00
var despawn = EnsureComp < TimedDespawnComponent > ( vapor . Owner ) ;
despawn . Lifetime = aliveTime ;
2021-07-21 22:26:09 +10:00
// Set Move
2021-12-08 13:00:43 +01:00
if ( EntityManager . TryGetComponent ( vapor . Owner , out PhysicsComponent ? physics ) )
2021-07-21 22:26:09 +10:00
{
2023-01-15 15:38:59 +11:00
_physics . SetLinearDamping ( physics , 0f ) ;
_physics . SetAngularDamping ( physics , 0f ) ;
2022-07-15 12:45:21 +10:00
2023-05-13 09:54:37 +10:00
_throwing . TryThrow ( vapor . Owner , dir , speed , user : user , pushbackRatio : ThrowingSystem . PushbackDefault * 10f ) ;
2022-07-15 12:45:21 +10:00
2023-07-08 14:08:32 +10:00
var distance = ( target . Position - vaporXform . WorldPosition ) . Length ( ) ;
var time = ( distance / physics . LinearVelocity . Length ( ) ) ;
2022-07-15 12:45:21 +10:00
despawn . Lifetime = MathF . Min ( aliveTime , time ) ;
2021-07-21 22:26:09 +10:00
}
}
internal bool TryAddSolution ( VaporComponent vapor , Solution solution )
{
2023-01-12 16:41:40 +13:00
if ( solution . Volume = = 0 )
2021-07-21 22:26:09 +10:00
{
return false ;
}
2022-07-15 12:45:21 +10:00
if ( ! _solutionContainerSystem . TryGetSolution ( vapor . Owner , VaporComponent . SolutionName ,
2021-09-15 12:48:07 +02:00
out var vaporSolution ) )
2021-07-21 22:26:09 +10:00
{
return false ;
}
2021-12-03 15:53:09 +01:00
return _solutionContainerSystem . TryAddSolution ( vapor . Owner , vaporSolution , solution ) ;
2021-07-21 22:26:09 +10:00
}
2020-08-08 14:33:36 +02:00
public override void Update ( float frameTime )
{
2022-07-15 12:45:21 +10:00
foreach ( var ( vaporComp , solution , xform ) in EntityManager
. EntityQuery < VaporComponent , SolutionContainerManagerComponent , TransformComponent > ( ) )
2021-07-21 22:26:09 +10:00
{
2021-09-06 15:49:44 +02:00
foreach ( var ( _ , value ) in solution . Solutions )
{
2022-07-15 12:45:21 +10:00
Update ( frameTime , vaporComp , value , xform ) ;
2021-09-06 15:49:44 +02:00
}
2021-07-21 22:26:09 +10:00
}
}
2022-07-15 12:45:21 +10:00
private void Update ( float frameTime , VaporComponent vapor , Solution contents , TransformComponent xform )
2021-07-21 22:26:09 +10:00
{
if ( ! vapor . Active )
return ;
var entity = vapor . Owner ;
vapor . ReactTimer + = frameTime ;
2022-11-04 10:12:25 +11:00
if ( vapor . ReactTimer > = ReactTime & & TryComp ( xform . GridUid , out MapGridComponent ? gridComp ) )
2021-07-21 22:26:09 +10:00
{
vapor . ReactTimer = 0 ;
2022-11-22 13:12:04 +11:00
var tile = gridComp . GetTileRef ( xform . Coordinates . ToVector2i ( EntityManager , _mapManager ) ) ;
2021-09-06 15:49:44 +02:00
foreach ( var reagentQuantity in contents . Contents . ToArray ( ) )
2021-07-21 22:26:09 +10:00
{
2021-11-03 16:48:03 -07:00
if ( reagentQuantity . Quantity = = FixedPoint2 . Zero ) continue ;
2021-07-21 22:26:09 +10:00
var reagent = _protoManager . Index < ReagentPrototype > ( reagentQuantity . ReagentId ) ;
2023-05-18 01:02:07 +10:00
var reaction =
reagent . ReactionTile ( tile , ( reagentQuantity . Quantity / vapor . TransferAmount ) * 0.25f ) ;
if ( reaction > reagentQuantity . Quantity )
{
_sawmill . Error ( $"Tried to tile react more than we have for reagent {reagentQuantity.ReagentId}. Found {reaction} and we only have {reagentQuantity.Quantity}" ) ;
reaction = reagentQuantity . Quantity ;
}
_solutionContainerSystem . TryRemoveReagent ( vapor . Owner , contents , reagentQuantity . ReagentId , reaction ) ;
2021-07-21 22:26:09 +10:00
}
}
2023-01-12 16:41:40 +13:00
if ( contents . Volume = = 0 )
2020-08-08 14:33:36 +02:00
{
2021-07-21 22:26:09 +10:00
// Delete this
2021-12-08 13:00:43 +01:00
EntityManager . QueueDeleteEntity ( entity ) ;
2020-08-08 14:33:36 +02:00
}
}
}
}