2021-11-11 16:10:57 -07:00
using Content.Server.Body.Components ;
using Content.Server.Body.Systems ;
2021-10-29 13:40:15 +01:00
using Content.Server.Chemistry.Components.SolutionManager ;
using Content.Server.Chemistry.EntitySystems ;
2021-11-29 16:27:15 +13:00
using Content.Server.DoAfter ;
2021-10-03 06:56:29 +02:00
using Content.Server.Fluids.Components ;
2021-12-05 04:18:30 +01:00
using Content.Server.Fluids.EntitySystems ;
2021-09-12 16:22:58 +10:00
using Content.Server.Nutrition.Components ;
2021-11-09 11:28:27 +01:00
using Content.Server.Popups ;
2021-11-29 16:27:15 +13:00
using Content.Shared.ActionBlocker ;
using Content.Shared.Administration.Logs ;
2021-11-02 11:40:55 +11:00
using Content.Shared.Body.Components ;
2021-11-29 16:27:15 +13:00
using Content.Shared.Chemistry.Components ;
2021-11-02 11:40:55 +11:00
using Content.Shared.Chemistry.Reagent ;
2021-11-29 16:27:15 +13:00
using Content.Shared.Database ;
2021-11-02 11:40:55 +11:00
using Content.Shared.Examine ;
2021-11-03 16:48:03 -07:00
using Content.Shared.FixedPoint ;
2021-12-07 19:19:26 +13:00
using Content.Shared.Hands ;
2021-11-02 11:40:55 +11:00
using Content.Shared.Interaction ;
using Content.Shared.Interaction.Helpers ;
2021-10-03 06:56:29 +02:00
using Content.Shared.Nutrition.Components ;
2021-11-02 11:40:55 +11:00
using Content.Shared.Popups ;
2021-09-12 16:22:58 +10:00
using Content.Shared.Throwing ;
2021-09-06 15:49:44 +02:00
using JetBrains.Annotations ;
2021-09-12 16:22:58 +10:00
using Robust.Shared.Audio ;
2021-09-06 15:49:44 +02:00
using Robust.Shared.GameObjects ;
using Robust.Shared.IoC ;
2021-11-02 11:40:55 +11:00
using Robust.Shared.Localization ;
2021-09-12 16:22:58 +10:00
using Robust.Shared.Player ;
using Robust.Shared.Random ;
2021-11-30 18:25:02 -07:00
using Robust.Shared.Utility ;
2021-09-06 15:49:44 +02:00
namespace Content.Server.Nutrition.EntitySystems
{
[UsedImplicitly]
public class DrinkSystem : EntitySystem
{
2021-12-03 03:51:05 +13:00
[Dependency] private readonly FoodSystem _foodSystem = default ! ;
2021-09-12 16:22:58 +10:00
[Dependency] private readonly IRobustRandom _random = default ! ;
2021-09-06 15:49:44 +02:00
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default ! ;
2021-11-09 11:28:27 +01:00
[Dependency] private readonly PopupSystem _popupSystem = default ! ;
2021-11-11 16:10:57 -07:00
[Dependency] private readonly BodySystem _bodySystem = default ! ;
[Dependency] private readonly StomachSystem _stomachSystem = default ! ;
2021-11-29 16:27:15 +13:00
[Dependency] private readonly DoAfterSystem _doAfterSystem = default ! ;
[Dependency] private readonly SharedAdminLogSystem _logSystem = default ! ;
[Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default ! ;
2021-12-05 04:18:30 +01:00
[Dependency] private readonly SpillableSystem _spillableSystem = default ! ;
2021-09-06 15:49:44 +02:00
public override void Initialize ( )
{
base . Initialize ( ) ;
SubscribeLocalEvent < DrinkComponent , SolutionChangedEvent > ( OnSolutionChange ) ;
SubscribeLocalEvent < DrinkComponent , ComponentInit > ( OnDrinkInit ) ;
2021-09-12 16:22:58 +10:00
SubscribeLocalEvent < DrinkComponent , LandEvent > ( HandleLand ) ;
2021-11-02 11:40:55 +11:00
SubscribeLocalEvent < DrinkComponent , UseInHandEvent > ( OnUse ) ;
2021-12-07 19:19:26 +13:00
SubscribeLocalEvent < DrinkComponent , HandDeselectedEvent > ( OnDrinkDeselected ) ;
2021-11-02 11:40:55 +11:00
SubscribeLocalEvent < DrinkComponent , AfterInteractEvent > ( AfterInteract ) ;
SubscribeLocalEvent < DrinkComponent , ExaminedEvent > ( OnExamined ) ;
2021-11-29 16:27:15 +13:00
SubscribeLocalEvent < SharedBodyComponent , ForceDrinkEvent > ( OnForceDrink ) ;
SubscribeLocalEvent < ForceDrinkCancelledEvent > ( OnForceDrinkCancelled ) ;
2021-11-02 11:40:55 +11:00
}
2021-12-07 19:19:26 +13:00
/// <summary>
/// If the user is currently forcing someone do drink, this cancels the attempt if they swap hands or
/// otherwise loose the item. Prevents force-feeding dual-wielding.
/// </summary>
private void OnDrinkDeselected ( EntityUid uid , DrinkComponent component , HandDeselectedEvent args )
{
if ( component . CancelToken ! = null )
{
component . CancelToken . Cancel ( ) ;
component . CancelToken = null ;
}
}
2021-11-02 11:40:55 +11:00
public bool IsEmpty ( EntityUid uid , DrinkComponent ? component = null )
{
if ( ! Resolve ( uid , ref component ) )
return true ;
return _solutionContainerSystem . DrainAvailable ( uid ) < = 0 ;
}
private void OnExamined ( EntityUid uid , DrinkComponent component , ExaminedEvent args )
{
if ( ! component . Opened | | ! args . IsInDetailsRange )
{
return ;
}
var color = IsEmpty ( uid , component ) ? "gray" : "yellow" ;
var openedText =
Loc . GetString ( IsEmpty ( uid , component ) ? "drink-component-on-examine-is-empty" : "drink-component-on-examine-is-opened" ) ;
2021-11-04 23:16:28 -05:00
args . Message . AddMarkup ( $"\n{Loc.GetString(" drink - component - on - examine - details - text ", (" colorName ", color), (" text ", openedText))}" ) ;
2021-11-02 11:40:55 +11:00
}
private void SetOpen ( EntityUid uid , bool opened = false , DrinkComponent ? component = null )
{
if ( ! Resolve ( uid , ref component ) )
return ;
if ( opened = = component . Opened )
return ;
component . Opened = opened ;
if ( ! _solutionContainerSystem . TryGetSolution ( uid , component . SolutionName , out _ ) )
{
return ;
}
if ( EntityManager . TryGetComponent < AppearanceComponent > ( uid , out var appearance ) )
{
appearance . SetData ( DrinkCanStateVisual . Opened , opened ) ;
}
if ( opened )
{
EntityManager . EnsureComponent < RefillableSolutionComponent > ( uid ) . Solution = component . SolutionName ;
EntityManager . EnsureComponent < DrainableSolutionComponent > ( uid ) . Solution = component . SolutionName ;
}
else
{
EntityManager . RemoveComponent < RefillableSolutionComponent > ( uid ) ;
EntityManager . RemoveComponent < DrainableSolutionComponent > ( uid ) ;
}
}
private void AfterInteract ( EntityUid uid , DrinkComponent component , AfterInteractEvent args )
{
2021-12-06 14:00:39 +01:00
if ( args . Handled | | args . Target = = null )
2021-11-02 11:40:55 +11:00
return ;
2021-12-05 18:09:01 +01:00
if ( ! _actionBlockerSystem . CanInteract ( args . User ) | | ! _actionBlockerSystem . CanUse ( args . User ) )
2021-11-02 11:40:55 +11:00
return ;
2021-12-05 18:09:01 +01:00
if ( ! args . User . InRangeUnobstructed ( uid , popup : true ) )
2021-11-29 16:27:15 +13:00
{
2021-11-02 11:40:55 +11:00
args . Handled = true ;
2021-11-29 16:27:15 +13:00
return ;
}
2021-12-05 18:09:01 +01:00
if ( args . User = = args . Target )
2021-11-29 16:27:15 +13:00
{
2021-12-05 18:09:01 +01:00
args . Handled = TryUseDrink ( uid , args . User ) ;
2021-11-29 16:27:15 +13:00
return ;
}
2021-12-05 18:09:01 +01:00
if ( ! args . User . InRangeUnobstructed ( args . Target . Value , popup : true ) )
2021-11-29 16:27:15 +13:00
{
args . Handled = true ;
return ;
}
if ( args . User = = args . Target )
2021-12-05 18:09:01 +01:00
args . Handled = TryUseDrink ( uid , args . User , component ) ;
2021-11-29 16:27:15 +13:00
else
2021-12-05 18:09:01 +01:00
args . Handled = TryForceDrink ( uid , args . User , args . Target . Value , component ) ;
2021-11-02 11:40:55 +11:00
}
private void OnUse ( EntityUid uid , DrinkComponent component , UseInHandEvent args )
{
if ( args . Handled ) return ;
2021-11-29 16:27:15 +13:00
2021-12-05 18:09:01 +01:00
if ( ! _actionBlockerSystem . CanInteract ( args . User ) | | ! _actionBlockerSystem . CanUse ( args . User ) )
2021-11-29 16:27:15 +13:00
return ;
2021-12-05 18:09:01 +01:00
if ( ! args . User . InRangeUnobstructed ( uid , popup : true ) )
2021-11-29 16:27:15 +13:00
{
args . Handled = true ;
return ;
}
2021-11-02 11:40:55 +11:00
if ( ! component . Opened )
{
//Do the opening stuff like playing the sounds.
SoundSystem . Play ( Filter . Pvs ( args . User ) , component . OpenSounds . GetSound ( ) , args . User , AudioParams . Default ) ;
SetOpen ( uid , true , component ) ;
return ;
}
if ( _solutionContainerSystem . DrainAvailable ( uid ) < = 0 )
{
2021-12-05 18:09:01 +01:00
args . User . PopupMessage ( Loc . GetString ( "drink-component-on-use-is-empty" , ( "owner" , uid ) ) ) ;
2021-11-02 11:40:55 +11:00
return ;
}
2021-12-05 18:09:01 +01:00
args . Handled = TryUseDrink ( uid , args . User , component ) ;
2021-09-12 16:22:58 +10:00
}
private void HandleLand ( EntityUid uid , DrinkComponent component , LandEvent args )
{
if ( component . Pressurized & &
! component . Opened & &
_random . Prob ( 0.25f ) & &
_solutionContainerSystem . TryGetDrainableSolution ( uid , out var interactions ) )
{
component . Opened = true ;
2021-10-03 06:56:29 +02:00
UpdateAppearance ( component ) ;
2021-09-12 16:22:58 +10:00
var solution = _solutionContainerSystem . Drain ( uid , interactions , interactions . DrainAvailable ) ;
2021-12-07 17:48:49 +01:00
_spillableSystem . SpillAt ( uid , solution , "PuddleSmear" ) ;
2021-09-12 16:22:58 +10:00
2021-12-05 18:09:01 +01:00
SoundSystem . Play ( Filter . Pvs ( uid ) , component . BurstSound . GetSound ( ) , uid , AudioParams . Default . WithVolume ( - 4 ) ) ;
2021-09-12 16:22:58 +10:00
}
2021-09-06 15:49:44 +02:00
}
private void OnDrinkInit ( EntityUid uid , DrinkComponent component , ComponentInit args )
{
2021-11-02 11:40:55 +11:00
SetOpen ( uid , component . DefaultToOpened , component ) ;
2021-09-06 15:49:44 +02:00
2021-11-02 11:40:55 +11:00
if ( EntityManager . TryGetComponent ( uid , out DrainableSolutionComponent ? existingDrainable ) )
2021-09-06 15:49:44 +02:00
{
// Beakers have Drink component but they should use the existing Drainable
component . SolutionName = existingDrainable . Solution ;
}
else
{
2021-11-02 11:40:55 +11:00
_solutionContainerSystem . EnsureSolution ( uid , component . SolutionName ) ;
2021-09-06 15:49:44 +02:00
}
2021-10-03 06:56:29 +02:00
UpdateAppearance ( component ) ;
2021-09-06 15:49:44 +02:00
}
private void OnSolutionChange ( EntityUid uid , DrinkComponent component , SolutionChangedEvent args )
{
2021-10-03 06:56:29 +02:00
UpdateAppearance ( component ) ;
}
public void UpdateAppearance ( DrinkComponent component )
{
2021-12-07 22:22:34 +11:00
if ( ! EntityManager . TryGetComponent ( ( component ) . Owner , out AppearanceComponent ? appearance ) | |
! EntityManager . HasComponent < SolutionContainerManagerComponent > ( ( component ) . Owner ) )
2021-10-03 06:56:29 +02:00
{
return ;
}
2021-12-07 22:22:34 +11:00
var drainAvailable = _solutionContainerSystem . DrainAvailable ( ( component ) . Owner ) ;
2021-10-03 06:56:29 +02:00
appearance . SetData ( FoodVisuals . Visual , drainAvailable . Float ( ) ) ;
appearance . SetData ( DrinkCanStateVisual . Opened , component . Opened ) ;
2021-09-06 15:49:44 +02:00
}
2021-11-02 11:40:55 +11:00
2021-11-29 16:27:15 +13:00
/// <summary>
/// Attempt to drink some of a drink. Returns true if any interaction took place, including generation of
/// pop-up messages.
/// </summary>
private bool TryUseDrink ( EntityUid uid , EntityUid userUid , DrinkComponent ? drink = null )
2021-11-02 11:40:55 +11:00
{
2021-11-29 16:27:15 +13:00
if ( ! Resolve ( uid , ref drink ) )
2021-11-02 11:40:55 +11:00
return false ;
2021-12-07 19:19:26 +13:00
// if currently being used to force-feed, cancel that action.
if ( drink . CancelToken ! = null )
{
drink . CancelToken . Cancel ( ) ;
drink . CancelToken = null ;
return true ;
}
2021-11-29 16:27:15 +13:00
if ( ! drink . Opened )
2021-11-02 11:40:55 +11:00
{
2021-11-29 16:27:15 +13:00
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-not-open" ,
2022-01-09 20:10:36 -08:00
( "owner" , EntityManager . GetComponent < MetaDataComponent > ( drink . Owner ) . EntityName ) ) , uid , Filter . Entities ( userUid ) ) ;
2021-11-29 16:27:15 +13:00
return true ;
2021-11-02 11:40:55 +11:00
}
2021-11-29 16:27:15 +13:00
if ( ! EntityManager . TryGetComponent ( userUid , out SharedBodyComponent ? body ) )
2021-11-02 11:40:55 +11:00
return false ;
2021-12-07 22:22:34 +11:00
if ( ! _solutionContainerSystem . TryGetDrainableSolution ( ( drink ) . Owner , out var drinkSolution ) | |
2021-11-29 16:27:15 +13:00
drinkSolution . DrainAvailable < = 0 )
2021-11-02 11:40:55 +11:00
{
2021-11-29 16:27:15 +13:00
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-is-empty" ,
2022-01-09 20:10:36 -08:00
( "entity" , EntityManager . GetComponent < MetaDataComponent > ( drink . Owner ) . EntityName ) ) , uid , Filter . Entities ( userUid ) ) ;
2021-11-29 16:27:15 +13:00
return true ;
2021-11-02 11:40:55 +11:00
}
2021-11-29 16:27:15 +13:00
if ( ! _bodySystem . TryGetComponentsOnMechanisms < StomachComponent > ( userUid , out var stomachs , body ) )
{
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-cannot-drink" ) ,
userUid , Filter . Entities ( userUid ) ) ;
return true ;
}
2021-11-02 11:40:55 +11:00
2021-12-05 07:56:27 +13:00
if ( _foodSystem . IsMouthBlocked ( userUid , userUid ) )
2021-12-03 03:51:05 +13:00
return true ;
2021-11-29 16:27:15 +13:00
var transferAmount = FixedPoint2 . Min ( drink . TransferAmount , drinkSolution . DrainAvailable ) ;
var drain = _solutionContainerSystem . Drain ( uid , drinkSolution , transferAmount ) ;
2021-11-30 18:25:02 -07:00
var firstStomach = stomachs . FirstOrNull (
2021-12-07 22:22:34 +11:00
stomach = > _stomachSystem . CanTransferSolution ( ( stomach . Comp ) . Owner , drain ) ) ;
2021-11-02 11:40:55 +11:00
// All stomach are full or can't handle whatever solution we have.
if ( firstStomach = = null )
{
2021-11-29 16:27:15 +13:00
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-had-enough" ) ,
userUid , Filter . Entities ( userUid ) ) ;
2021-11-02 11:40:55 +11:00
if ( EntityManager . HasComponent < RefillableSolutionComponent > ( uid ) )
{
2021-12-05 04:18:30 +01:00
_spillableSystem . SpillAt ( userUid , drain , "PuddleSmear" ) ;
2021-11-29 16:27:15 +13:00
return true ;
2021-11-02 11:40:55 +11:00
}
2021-11-29 16:27:15 +13:00
_solutionContainerSystem . Refill ( uid , drinkSolution , drain ) ;
return true ;
2021-11-02 11:40:55 +11:00
}
2021-11-29 16:27:15 +13:00
SoundSystem . Play ( Filter . Pvs ( userUid ) , drink . UseSound . GetSound ( ) , userUid ,
AudioParams . Default . WithVolume ( - 2f ) ) ;
2021-11-02 11:40:55 +11:00
2021-11-29 16:27:15 +13:00
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-success-slurp" ) , userUid ,
Filter . Pvs ( userUid ) ) ;
2021-11-02 11:40:55 +11:00
2021-11-29 16:27:15 +13:00
drain . DoEntityReaction ( userUid , ReactionMethod . Ingestion ) ;
2021-12-07 22:22:34 +11:00
_stomachSystem . TryTransferSolution ( ( firstStomach . Value . Comp ) . Owner , drain , firstStomach . Value . Comp ) ;
2021-11-02 11:40:55 +11:00
return true ;
}
2021-11-29 16:27:15 +13:00
/// <summary>
/// Attempt to force someone else to drink some of a drink. Returns true if any interaction took place,
/// including generation of pop-up messages.
/// </summary>
private bool TryForceDrink ( EntityUid uid , EntityUid userUid , EntityUid targetUid ,
DrinkComponent ? drink = null )
{
if ( ! Resolve ( uid , ref drink ) )
return false ;
// cannot stack do-afters
2021-12-07 19:19:26 +13:00
if ( drink . CancelToken ! = null )
{
drink . CancelToken . Cancel ( ) ;
drink . CancelToken = null ;
return true ;
}
2021-11-29 16:27:15 +13:00
if ( ! EntityManager . HasComponent < SharedBodyComponent > ( targetUid ) )
return false ;
if ( ! drink . Opened )
{
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-not-open" ,
2022-01-09 20:10:36 -08:00
( "owner" , EntityManager . GetComponent < MetaDataComponent > ( drink . Owner ) . EntityName ) ) , uid , Filter . Entities ( userUid ) ) ;
2021-11-29 16:27:15 +13:00
return true ;
}
if ( ! _solutionContainerSystem . TryGetDrainableSolution ( uid , out var drinkSolution ) | |
drinkSolution . DrainAvailable < = 0 )
{
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-is-empty" ,
2022-01-09 20:10:36 -08:00
( "entity" , EntityManager . GetComponent < MetaDataComponent > ( drink . Owner ) . EntityName ) ) , uid , Filter . Entities ( userUid ) ) ;
2021-11-29 16:27:15 +13:00
return true ;
}
2021-12-05 07:56:27 +13:00
if ( _foodSystem . IsMouthBlocked ( targetUid , userUid ) )
2021-12-03 03:51:05 +13:00
return true ;
2021-11-29 16:27:15 +13:00
EntityManager . TryGetComponent ( userUid , out MetaDataComponent ? meta ) ;
var userName = meta ? . EntityName ? ? string . Empty ;
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-force-feed" , ( "user" , userName ) ) ,
userUid , Filter . Entities ( targetUid ) ) ;
2021-12-07 19:19:26 +13:00
drink . CancelToken = new ( ) ;
_doAfterSystem . DoAfter ( new DoAfterEventArgs ( userUid , drink . ForceFeedDelay , drink . CancelToken . Token , targetUid )
2021-11-29 16:27:15 +13:00
{
BreakOnUserMove = true ,
BreakOnDamage = true ,
BreakOnStun = true ,
BreakOnTargetMove = true ,
MovementThreshold = 1.0f ,
TargetFinishedEvent = new ForceDrinkEvent ( userUid , drink , drinkSolution ) ,
2021-12-07 19:19:26 +13:00
BroadcastCancelledEvent = new ForceDrinkCancelledEvent ( drink ) ,
2021-11-29 16:27:15 +13:00
} ) ;
// logging
2021-12-14 00:22:58 +13:00
_logSystem . Add ( LogType . ForceFeed , LogImpact . Medium , $"{ToPrettyString(userUid):user} is forcing {ToPrettyString(targetUid):target} to drink {ToPrettyString(uid):drink} {SolutionContainerSystem.ToPrettyString(drinkSolution):solution}" ) ;
2021-11-29 16:27:15 +13:00
return true ;
}
/// <summary>
/// Raised directed at a victim when someone has force fed them a drink.
/// </summary>
private void OnForceDrink ( EntityUid uid , SharedBodyComponent body , ForceDrinkEvent args )
{
2021-12-07 19:19:26 +13:00
if ( args . Drink . Deleted )
return ;
args . Drink . CancelToken = null ;
2021-11-29 16:27:15 +13:00
var transferAmount = FixedPoint2 . Min ( args . Drink . TransferAmount , args . DrinkSolution . DrainAvailable ) ;
2021-12-07 22:22:34 +11:00
var drained = _solutionContainerSystem . Drain ( ( args . Drink ) . Owner , args . DrinkSolution , transferAmount ) ;
2021-11-29 16:27:15 +13:00
if ( ! _bodySystem . TryGetComponentsOnMechanisms < StomachComponent > ( uid , out var stomachs , body ) )
{
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-cannot-drink-other" ) ,
uid , Filter . Entities ( args . User ) ) ;
2021-12-05 04:18:30 +01:00
_spillableSystem . SpillAt ( uid , drained , "PuddleSmear" ) ;
2021-11-29 16:27:15 +13:00
return ;
}
2021-11-30 18:25:02 -07:00
var firstStomach = stomachs . FirstOrNull (
2021-12-07 22:22:34 +11:00
stomach = > _stomachSystem . CanTransferSolution ( ( stomach . Comp ) . Owner , drained ) ) ;
2021-11-29 16:27:15 +13:00
// All stomach are full or can't handle whatever solution we have.
if ( firstStomach = = null )
{
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-had-enough-other" ) ,
uid , Filter . Entities ( args . User ) ) ;
2021-12-05 04:18:30 +01:00
_spillableSystem . SpillAt ( uid , drained , "PuddleSmear" ) ;
2021-11-29 16:27:15 +13:00
return ;
}
EntityManager . TryGetComponent ( uid , out MetaDataComponent ? targetMeta ) ;
var targetName = targetMeta ? . EntityName ? ? string . Empty ;
EntityManager . TryGetComponent ( args . User , out MetaDataComponent ? userMeta ) ;
var userName = userMeta ? . EntityName ? ? string . Empty ;
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-force-feed-success" , ( "user" , userName ) ) ,
uid , Filter . Entities ( uid ) ) ;
_popupSystem . PopupEntity ( Loc . GetString ( "drink-component-force-feed-success-user" , ( "target" , targetName ) ) ,
args . User , Filter . Entities ( args . User ) ) ;
SoundSystem . Play ( Filter . Pvs ( uid ) , args . Drink . UseSound . GetSound ( ) , uid , AudioParams . Default . WithVolume ( - 2f ) ) ;
drained . DoEntityReaction ( uid , ReactionMethod . Ingestion ) ;
2021-12-07 22:22:34 +11:00
_stomachSystem . TryTransferSolution ( ( firstStomach . Value . Comp ) . Owner , drained , firstStomach . Value . Comp ) ;
2021-11-29 16:27:15 +13:00
}
private void OnForceDrinkCancelled ( ForceDrinkCancelledEvent args )
{
2021-12-07 19:19:26 +13:00
args . Drink . CancelToken = null ;
2021-11-29 16:27:15 +13:00
}
2021-09-06 15:49:44 +02:00
}
}