2021-11-11 16:10:57 -07:00
using Content.Server.Body.Components ;
using Content.Server.Body.Systems ;
2024-06-30 05:43:43 +02:00
using Content.Server.EntityEffects.Effects ;
2021-12-05 04:18:30 +01:00
using Content.Server.Fluids.EntitySystems ;
2023-03-31 07:49:25 +03:00
using Content.Server.Forensics ;
2023-09-23 03:10:04 +01:00
using Content.Server.Inventory ;
2021-11-09 11:28:27 +01:00
using Content.Server.Popups ;
2021-11-29 16:27:15 +13:00
using Content.Shared.Administration.Logs ;
2021-11-02 11:40:55 +11:00
using Content.Shared.Body.Components ;
2023-02-24 19:01:25 -05:00
using Content.Shared.Chemistry ;
2023-04-10 15:37:03 +10:00
using Content.Shared.Chemistry.Components ;
2023-10-14 09:45:28 -07:00
using Content.Shared.Chemistry.Components.SolutionManager ;
using Content.Shared.Chemistry.EntitySystems ;
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 ;
2023-02-24 19:01:25 -05:00
using Content.Shared.DoAfter ;
2024-06-30 05:43:43 +02:00
using Content.Shared.EntityEffects ;
2021-11-03 16:48:03 -07:00
using Content.Shared.FixedPoint ;
2024-07-09 16:12:40 -07:00
using Content.Shared.Hands.EntitySystems ;
2022-07-10 18:36:53 -07:00
using Content.Shared.IdentityManagement ;
2021-11-02 11:40:55 +11:00
using Content.Shared.Interaction ;
2022-03-13 01:33:23 +13:00
using Content.Shared.Interaction.Events ;
2023-01-13 16:57:10 -08:00
using Content.Shared.Mobs.Systems ;
2023-04-03 13:13:48 +12:00
using Content.Shared.Nutrition ;
2021-10-03 06:56:29 +02:00
using Content.Shared.Nutrition.Components ;
2024-04-01 06:27:39 +00:00
using Content.Shared.Nutrition.EntitySystems ;
2022-04-23 19:38:21 -04:00
using Content.Shared.Verbs ;
2021-09-12 16:22:58 +10:00
using Robust.Shared.Audio ;
2023-11-27 22:12:34 +11:00
using Robust.Shared.Audio.Systems ;
2021-09-12 16:22:58 +10:00
using Robust.Shared.Player ;
2023-07-25 21:32:10 +00:00
using Robust.Shared.Prototypes ;
2021-11-30 18:25:02 -07:00
using Robust.Shared.Utility ;
2021-09-06 15:49:44 +02:00
2023-07-25 21:32:10 +00:00
namespace Content.Server.Nutrition.EntitySystems ;
2024-04-17 21:49:58 -04:00
public sealed class DrinkSystem : SharedDrinkSystem
2021-09-06 15:49:44 +02:00
{
2023-07-25 21:32:10 +00:00
[Dependency] private readonly BodySystem _body = default ! ;
[Dependency] private readonly FlavorProfileSystem _flavorProfile = default ! ;
2023-09-23 03:10:04 +01:00
[Dependency] private readonly FoodSystem _food = default ! ;
2023-07-25 21:32:10 +00:00
[Dependency] private readonly IPrototypeManager _proto = default ! ;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default ! ;
2023-09-23 03:10:04 +01:00
[Dependency] private readonly MobStateSystem _mobState = default ! ;
[Dependency] private readonly OpenableSystem _openable = default ! ;
2023-07-25 21:32:10 +00:00
[Dependency] private readonly PopupSystem _popup = default ! ;
2023-09-23 03:10:04 +01:00
[Dependency] private readonly PuddleSystem _puddle = default ! ;
2023-07-25 21:32:10 +00:00
[Dependency] private readonly ReactiveSystem _reaction = default ! ;
[Dependency] private readonly SharedAppearanceSystem _appearance = default ! ;
[Dependency] private readonly SharedAudioSystem _audio = default ! ;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default ! ;
2024-07-09 16:12:40 -07:00
[Dependency] private readonly SharedHandsSystem _hands = default ! ;
2023-07-25 21:32:10 +00:00
[Dependency] private readonly SharedInteractionSystem _interaction = default ! ;
2024-09-02 06:26:04 -05:00
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default ! ;
2023-07-25 21:32:10 +00:00
[Dependency] private readonly StomachSystem _stomach = default ! ;
2023-12-15 04:52:55 -05:00
[Dependency] private readonly ForensicsSystem _forensics = default ! ;
2023-07-25 21:32:10 +00:00
public override void Initialize ( )
2021-09-06 15:49:44 +02:00
{
2023-07-25 21:32:10 +00:00
base . Initialize ( ) ;
// TODO add InteractNoHandEvent for entities like mice.
2023-12-29 04:47:43 -08:00
SubscribeLocalEvent < DrinkComponent , SolutionContainerChangedEvent > ( OnSolutionChange ) ;
2023-07-25 21:32:10 +00:00
SubscribeLocalEvent < DrinkComponent , ComponentInit > ( OnDrinkInit ) ;
2023-09-23 03:10:04 +01:00
// run before inventory so for bucket it always tries to drink before equipping (when empty)
// run after openable so its always open -> drink
2024-04-17 21:49:58 -04:00
SubscribeLocalEvent < DrinkComponent , UseInHandEvent > ( OnUse , before : [ typeof ( ServerInventorySystem ) ] , after : [ typeof ( OpenableSystem ) ] ) ;
2023-07-25 21:32:10 +00:00
SubscribeLocalEvent < DrinkComponent , AfterInteractEvent > ( AfterInteract ) ;
SubscribeLocalEvent < DrinkComponent , GetVerbsEvent < AlternativeVerb > > ( AddDrinkVerb ) ;
SubscribeLocalEvent < DrinkComponent , ConsumeDoAfterEvent > ( OnDoAfter ) ;
}
/// <summary>
/// Get the total hydration factor contained in a drink's solution.
/// </summary>
public float TotalHydration ( EntityUid uid , DrinkComponent ? comp = null )
{
if ( ! Resolve ( uid , ref comp ) )
return 0f ;
2021-11-02 11:40:55 +11:00
2023-12-29 04:47:43 -08:00
if ( ! _solutionContainer . TryGetSolution ( uid , comp . Solution , out _ , out var solution ) )
2023-07-25 21:32:10 +00:00
return 0f ;
var total = 0f ;
foreach ( var quantity in solution . Contents )
2021-11-02 11:40:55 +11:00
{
2023-09-05 09:55:10 +12:00
var reagent = _proto . Index < ReagentPrototype > ( quantity . Reagent . Prototype ) ;
2023-07-25 21:32:10 +00:00
if ( reagent . Metabolisms = = null )
continue ;
2021-11-02 11:40:55 +11:00
2023-12-24 23:12:22 -05:00
foreach ( var entry in reagent . Metabolisms . Values )
2022-06-21 22:02:24 -04:00
{
2023-07-25 21:32:10 +00:00
foreach ( var effect in entry . Effects )
2022-06-21 22:02:24 -04:00
{
2023-07-25 21:32:10 +00:00
// ignores any effect conditions, just cares about how much it can hydrate
if ( effect is SatiateThirst thirst )
2022-06-21 22:02:24 -04:00
{
2023-07-25 21:32:10 +00:00
total + = thirst . HydrationFactor * quantity . Quantity . Float ( ) ;
}
2022-06-21 22:02:24 -04:00
}
}
2021-11-02 11:40:55 +11:00
}
2023-07-25 21:32:10 +00:00
return total ;
}
2023-12-29 04:47:43 -08:00
private void AfterInteract ( Entity < DrinkComponent > entity , ref AfterInteractEvent args )
2023-07-25 21:32:10 +00:00
{
if ( args . Handled | | args . Target = = null | | ! args . CanReach )
return ;
2021-11-29 16:27:15 +13:00
2023-12-29 04:47:43 -08:00
args . Handled = TryDrink ( args . User , args . Target . Value , entity . Comp , entity ) ;
2023-07-25 21:32:10 +00:00
}
2021-11-02 11:40:55 +11:00
2023-12-29 04:47:43 -08:00
private void OnUse ( Entity < DrinkComponent > entity , ref UseInHandEvent args )
2023-07-25 21:32:10 +00:00
{
if ( args . Handled )
return ;
2023-12-29 04:47:43 -08:00
args . Handled = TryDrink ( args . User , args . User , entity . Comp , entity ) ;
2023-07-25 21:32:10 +00:00
}
2023-12-29 04:47:43 -08:00
private void OnDrinkInit ( Entity < DrinkComponent > entity , ref ComponentInit args )
2023-07-25 21:32:10 +00:00
{
2023-12-29 04:47:43 -08:00
if ( TryComp < DrainableSolutionComponent > ( entity , out var existingDrainable ) )
2021-09-06 15:49:44 +02:00
{
2023-07-25 21:32:10 +00:00
// Beakers have Drink component but they should use the existing Drainable
2023-12-29 04:47:43 -08:00
entity . Comp . Solution = existingDrainable . Solution ;
2023-07-25 21:32:10 +00:00
}
else
{
2024-09-02 06:26:04 -05:00
_solutionContainer . EnsureSolution ( entity . Owner , entity . Comp . Solution , out _ ) ;
2023-07-25 21:32:10 +00:00
}
2021-09-06 15:49:44 +02:00
2023-12-29 04:47:43 -08:00
UpdateAppearance ( entity , entity . Comp ) ;
2021-09-06 15:49:44 +02:00
2023-12-29 04:47:43 -08:00
if ( TryComp ( entity , out RefillableSolutionComponent ? refillComp ) )
refillComp . Solution = entity . Comp . Solution ;
2022-04-15 23:17:48 +02:00
2023-12-29 04:47:43 -08:00
if ( TryComp ( entity , out DrainableSolutionComponent ? drainComp ) )
drainComp . Solution = entity . Comp . Solution ;
2023-07-25 21:32:10 +00:00
}
2022-08-17 12:47:58 +12:00
2023-12-29 04:47:43 -08:00
private void OnSolutionChange ( Entity < DrinkComponent > entity , ref SolutionContainerChangedEvent args )
2023-07-25 21:32:10 +00:00
{
2023-12-29 04:47:43 -08:00
UpdateAppearance ( entity , entity . Comp ) ;
2023-07-25 21:32:10 +00:00
}
2021-09-06 15:49:44 +02:00
2023-07-25 21:32:10 +00:00
public void UpdateAppearance ( EntityUid uid , DrinkComponent component )
{
if ( ! TryComp < AppearanceComponent > ( uid , out var appearance ) | |
! HasComp < SolutionContainerManagerComponent > ( uid ) )
2021-09-06 15:49:44 +02:00
{
2023-07-25 21:32:10 +00:00
return ;
2021-10-03 06:56:29 +02:00
}
2023-07-25 21:32:10 +00:00
var drainAvailable = DrinkVolume ( uid , component ) ;
_appearance . SetData ( uid , FoodVisuals . Visual , drainAvailable . Float ( ) , appearance ) ;
}
2024-07-09 16:12:40 -07:00
/// <summary>
/// Tries to feed the drink item to the target entity
/// </summary>
2023-07-25 21:32:10 +00:00
private bool TryDrink ( EntityUid user , EntityUid target , DrinkComponent drink , EntityUid item )
{
2023-09-23 03:10:04 +01:00
if ( ! HasComp < BodyComponent > ( target ) )
2023-07-25 21:32:10 +00:00
return false ;
2021-11-02 11:40:55 +11:00
2023-09-23 03:10:04 +01:00
if ( _openable . IsClosed ( item , user ) )
2023-07-25 21:32:10 +00:00
return true ;
2022-04-15 23:17:48 +02:00
2023-12-29 04:47:43 -08:00
if ( ! _solutionContainer . TryGetSolution ( item , drink . Solution , out _ , out var drinkSolution ) | | drinkSolution . Volume < = 0 )
2021-11-02 11:40:55 +11:00
{
2023-09-23 03:10:04 +01:00
if ( drink . IgnoreEmpty )
return false ;
_popup . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-is-empty" , ( "entity" , item ) ) , item , user ) ;
2023-07-25 21:32:10 +00:00
return true ;
}
2021-12-03 03:51:05 +13:00
2023-07-25 21:32:10 +00:00
if ( _food . IsMouthBlocked ( target , user ) )
return true ;
2021-11-29 16:27:15 +13:00
2023-07-25 21:32:10 +00:00
if ( ! _interaction . InRangeUnobstructed ( user , item , popup : true ) )
return true ;
2021-11-29 16:27:15 +13:00
2023-07-25 21:32:10 +00:00
var forceDrink = user ! = target ;
2021-11-29 16:27:15 +13:00
2023-07-25 21:32:10 +00:00
if ( forceDrink )
{
var userName = Identity . Entity ( user , EntityManager ) ;
2022-03-17 12:46:18 +11:00
2023-09-23 03:10:04 +01:00
_popup . PopupEntity ( Loc . GetString ( "drink-component-force-feed" , ( "user" , userName ) ) , user , target ) ;
2022-09-13 19:36:19 -07:00
2023-07-25 21:32:10 +00:00
// logging
2024-09-02 06:26:04 -05:00
_adminLogger . Add ( LogType . ForceFeed , LogImpact . Medium , $"{ToPrettyString(user):user} is forcing {ToPrettyString(target):target} to drink {ToPrettyString(item):drink} {SharedSolutionContainerSystem.ToPrettyString(drinkSolution)}" ) ;
2021-11-29 16:27:15 +13:00
}
2023-07-25 21:32:10 +00:00
else
{
// log voluntary drinking
2024-09-02 06:26:04 -05:00
_adminLogger . Add ( LogType . Ingestion , LogImpact . Low , $"{ToPrettyString(target):target} is drinking {ToPrettyString(item):drink} {SharedSolutionContainerSystem.ToPrettyString(drinkSolution)}" ) ;
2023-07-25 21:32:10 +00:00
}
var flavors = _flavorProfile . GetLocalizedFlavorsMessage ( user , drinkSolution ) ;
2021-11-29 16:27:15 +13:00
2023-09-11 09:42:41 +10:00
var doAfterEventArgs = new DoAfterArgs ( EntityManager ,
2023-07-25 21:32:10 +00:00
user ,
forceDrink ? drink . ForceFeedDelay : drink . Delay ,
2023-12-29 04:47:43 -08:00
new ConsumeDoAfterEvent ( drink . Solution , flavors ) ,
2023-07-25 21:32:10 +00:00
eventTarget : item ,
target : target ,
used : item )
2021-11-29 16:27:15 +13:00
{
2024-07-22 02:17:57 -07:00
BreakOnHandChange = false ,
2024-03-19 12:09:00 +02:00
BreakOnMove = forceDrink ,
2023-07-25 21:32:10 +00:00
BreakOnDamage = true ,
MovementThreshold = 0.01f ,
DistanceThreshold = 1.0f ,
2024-07-09 16:12:40 -07:00
// do-after will stop if item is dropped when trying to feed someone else
// or if the item started out in the user's own hands
NeedHand = forceDrink | | _hands . IsHolding ( user , item ) ,
2023-07-25 21:32:10 +00:00
} ;
_doAfter . TryStartDoAfter ( doAfterEventArgs ) ;
return true ;
}
2023-02-26 00:33:06 -05:00
2023-07-25 21:32:10 +00:00
/// <summary>
/// Raised directed at a victim when someone has force fed them a drink.
/// </summary>
2023-12-29 04:47:43 -08:00
private void OnDoAfter ( Entity < DrinkComponent > entity , ref ConsumeDoAfterEvent args )
2023-07-25 21:32:10 +00:00
{
2023-12-29 04:47:43 -08:00
if ( args . Handled | | args . Cancelled | | entity . Comp . Deleted )
2023-07-25 21:32:10 +00:00
return ;
2023-02-24 19:01:25 -05:00
2023-07-25 21:32:10 +00:00
if ( ! TryComp < BodyComponent > ( args . Target , out var body ) )
return ;
2021-12-07 19:19:26 +13:00
2023-12-29 04:47:43 -08:00
if ( args . Used is null | | ! _solutionContainer . TryGetSolution ( args . Used . Value , args . Solution , out var soln , out var solution ) )
2023-07-25 21:32:10 +00:00
return ;
2023-04-17 19:56:42 +12:00
2024-03-13 23:10:14 -05:00
if ( _openable . IsClosed ( args . Used . Value , args . Target . Value ) )
return ;
2023-07-25 21:32:10 +00:00
// TODO this should really be checked every tick.
if ( _food . IsMouthBlocked ( args . Target . Value ) )
return ;
2023-04-17 19:56:42 +12:00
2023-07-25 21:32:10 +00:00
// TODO this should really be checked every tick.
if ( ! _interaction . InRangeUnobstructed ( args . User , args . Target . Value ) )
return ;
2023-03-09 03:45:19 -05:00
2023-12-29 04:47:43 -08:00
var transferAmount = FixedPoint2 . Min ( entity . Comp . TransferAmount , solution . Volume ) ;
var drained = _solutionContainer . SplitSolution ( soln . Value , transferAmount ) ;
2023-07-25 21:32:10 +00:00
var forceDrink = args . User ! = args . Target ;
2022-02-07 00:37:38 +11:00
2023-07-25 21:32:10 +00:00
args . Handled = true ;
if ( transferAmount < = 0 )
return ;
2021-11-29 16:27:15 +13:00
2024-08-02 00:30:45 -07:00
if ( ! _body . TryGetBodyOrganEntityComps < StomachComponent > ( ( args . Target . Value , body ) , out var stomachs ) )
2023-07-25 21:32:10 +00:00
{
2023-09-23 03:10:04 +01:00
_popup . PopupEntity ( Loc . GetString ( forceDrink ? "drink-component-try-use-drink-cannot-drink-other" : "drink-component-try-use-drink-had-enough" ) , args . Target . Value , args . User ) ;
2022-02-07 00:37:38 +11:00
2023-07-25 21:32:10 +00:00
if ( HasComp < RefillableSolutionComponent > ( args . Target . Value ) )
{
2023-09-23 03:10:04 +01:00
_puddle . TrySpillAt ( args . User , drained , out _ ) ;
2021-11-29 16:27:15 +13:00
return ;
}
2023-12-29 04:47:43 -08:00
_solutionContainer . Refill ( args . Target . Value , soln . Value , drained ) ;
2023-07-25 21:32:10 +00:00
return ;
}
2021-11-29 16:27:15 +13:00
2024-08-02 00:30:45 -07:00
var firstStomach = stomachs . FirstOrNull ( stomach = > _stomach . CanTransferSolution ( stomach . Owner , drained , stomach . Comp1 ) ) ;
2022-07-07 11:21:26 -07:00
2023-07-25 21:32:10 +00:00
//All stomachs are full or can't handle whatever solution we have.
if ( firstStomach = = null )
{
_popup . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-had-enough" ) , args . Target . Value , args . Target . Value ) ;
2021-11-29 16:27:15 +13:00
2023-07-25 21:32:10 +00:00
if ( forceDrink )
{
_popup . PopupEntity ( Loc . GetString ( "drink-component-try-use-drink-had-enough-other" ) , args . Target . Value , args . User ) ;
2023-09-23 03:10:04 +01:00
_puddle . TrySpillAt ( args . Target . Value , drained , out _ ) ;
2021-11-29 16:27:15 +13:00
}
2023-07-25 21:32:10 +00:00
else
2023-12-29 04:47:43 -08:00
_solutionContainer . TryAddSolution ( soln . Value , drained ) ;
2021-11-29 16:27:15 +13:00
2023-07-25 21:32:10 +00:00
return ;
}
Flavor profiles (#10991)
* flavor profiles
TODO: every single flavor! yeah!!!
* adds basic localization, and flavors/lastFlavor values for when you get the flavor profile message
* multiple and single flavor messages
* start on flavor localization, multiple flavors in localized flavors
* flavor prototypes
* a few more flavors, descriptions on what each section of the flavor file should be doing
* localization for flavor profiles in drink/food system
* adds an event that allows a flavor profile list to be transformed base on the user entity
* raises it on the food entity too
* changes a field in flavor, adds some more flavors, starts adding flavor prototypes
* adds basic flavors to several entities, and consumable drinks, renames flavor field to 'flavors'
* changes call ordering in flavorprofile, adds flavor to ignored components server-side
flavor is really just a popup message, and those are all processed server-side
* fixes where food tried to get the flavor of the user instead of the food
* single flavors will now get the localized string
* getting the flavor message now ensures that flavors are deduplicated
* makes flavor processing more strictly unique bu making everything hashsets
* yeah, that could just not have distinctby now
* adds flavorprofile directly to food base instead for generic food taste
* FlavorProfileModificationEvent now passes a hashset of strings and not flavorprototypes
* flavorprofilesystem now broadcasts the flavor profile modification event
* adds more flavors to the flavor profile loc file
* skips a flavor, if the flavor string is null/empty
* adds some more flavors, adds generic medicine flavor to medicinal chemicals
* more food flavors, adds flavors to swallowing
* adds some cocktails to the set of flavor profiles
* regenerates flavor prototypes
* adds flavor type to all flavors, adds whitespace between variants
* adds more flavors, adds flavors to several chemicals and food items
this is the part that took the longest
* changes backup flavor message
* spelling mistake
* more flavors, and flavors on food
* readds all the type fields, whoops
* fixes localization strings for forcefeeding food/drink
* fixes multiple flavor profile
* adds flavor limit for flavors
* makes that fetch the cvardef instead
2022-09-08 16:14:49 -07:00
2023-07-25 21:32:10 +00:00
var flavors = args . FlavorMessage ;
2021-11-29 16:27:15 +13:00
2023-07-25 21:32:10 +00:00
if ( forceDrink )
{
var targetName = Identity . Entity ( args . Target . Value , EntityManager ) ;
var userName = Identity . Entity ( args . User , EntityManager ) ;
2021-11-29 16:27:15 +13:00
2023-07-25 21:32:10 +00:00
_popup . PopupEntity ( Loc . GetString ( "drink-component-force-feed-success" , ( "user" , userName ) , ( "flavors" , flavors ) ) , args . Target . Value , args . Target . Value ) ;
2022-12-02 19:19:44 -06:00
2023-07-25 21:32:10 +00:00
_popup . PopupEntity (
Loc . GetString ( "drink-component-force-feed-success-user" , ( "target" , targetName ) ) ,
args . User , args . User ) ;
2021-11-29 16:27:15 +13:00
2023-07-25 21:32:10 +00:00
// log successful forced drinking
2023-12-29 04:47:43 -08:00
_adminLogger . Add ( LogType . ForceFeed , LogImpact . Medium , $"{ToPrettyString(entity.Owner):user} forced {ToPrettyString(args.User):target} to drink {ToPrettyString(entity.Owner):drink}" ) ;
2023-07-25 21:32:10 +00:00
}
else
{
_popup . PopupEntity (
Loc . GetString ( "drink-component-try-use-drink-success-slurp-taste" , ( "flavors" , flavors ) ) , args . User ,
args . User ) ;
_popup . PopupEntity (
Loc . GetString ( "drink-component-try-use-drink-success-slurp" ) , args . User , Filter . PvsExcept ( args . User ) , true ) ;
// log successful voluntary drinking
2023-12-29 04:47:43 -08:00
_adminLogger . Add ( LogType . Ingestion , LogImpact . Low , $"{ToPrettyString(args.User):target} drank {ToPrettyString(entity.Owner):drink}" ) ;
2023-07-25 21:32:10 +00:00
}
2021-11-29 16:27:15 +13:00
2024-10-17 02:38:02 +01:00
_audio . PlayPvs ( entity . Comp . UseSound , args . Target . Value , AudioParams . Default . WithVolume ( - 2f ) . WithVariation ( 0.25f ) ) ;
2023-03-31 07:49:25 +03:00
2023-07-25 21:32:10 +00:00
_reaction . DoEntityReaction ( args . Target . Value , solution , ReactionMethod . Ingestion ) ;
2024-08-02 00:30:45 -07:00
_stomach . TryTransferSolution ( firstStomach . Value . Owner , drained , firstStomach . Value . Comp1 ) ;
2023-04-15 18:14:26 -04:00
2023-12-29 04:47:43 -08:00
_forensics . TransferDna ( entity , args . Target . Value ) ;
2022-04-23 19:38:21 -04:00
2023-07-25 21:32:10 +00:00
if ( ! forceDrink & & solution . Volume > 0 )
args . Repeat = true ;
}
2022-04-23 19:38:21 -04:00
2023-12-29 04:47:43 -08:00
private void AddDrinkVerb ( Entity < DrinkComponent > entity , ref GetVerbsEvent < AlternativeVerb > ev )
2023-07-25 21:32:10 +00:00
{
2023-12-29 04:47:43 -08:00
if ( entity . Owner = = ev . User | |
2023-07-25 21:32:10 +00:00
! ev . CanInteract | |
! ev . CanAccess | |
2023-09-23 03:10:04 +01:00
! TryComp < BodyComponent > ( ev . User , out var body ) | |
2024-08-02 00:30:45 -07:00
! _body . TryGetBodyOrganEntityComps < StomachComponent > ( ( ev . User , body ) , out var stomachs ) )
2023-07-25 21:32:10 +00:00
return ;
2022-04-23 19:38:21 -04:00
2024-03-31 00:40:22 -04:00
// Make sure the solution exists
if ( ! _solutionContainer . TryGetSolution ( entity . Owner , entity . Comp . Solution , out var solution ) )
return ;
2023-09-23 03:10:04 +01:00
// no drinking from living drinks, have to kill them first.
2023-12-29 04:47:43 -08:00
if ( _mobState . IsAlive ( entity ) )
2023-07-25 21:32:10 +00:00
return ;
2022-06-21 22:02:24 -04:00
2023-12-29 04:47:43 -08:00
var user = ev . User ;
2023-07-25 21:32:10 +00:00
AlternativeVerb verb = new ( )
2022-06-21 22:02:24 -04:00
{
2023-07-25 21:32:10 +00:00
Act = ( ) = >
{
2023-12-29 04:47:43 -08:00
TryDrink ( user , user , entity . Comp , entity ) ;
2023-07-25 21:32:10 +00:00
} ,
2023-12-29 04:47:43 -08:00
Icon = new SpriteSpecifier . Texture ( new ( "/Textures/Interface/VerbIcons/drink.svg.192dpi.png" ) ) ,
2023-07-25 21:32:10 +00:00
Text = Loc . GetString ( "drink-system-verb-drink" ) ,
Priority = 2
} ;
ev . Verbs . Add ( verb ) ;
}
2021-09-06 15:49:44 +02:00
}