/// <summary> /// Raised directed at a victim when someone has force fed them a drink. /// </summary> private void OnDrink(EntityUid uid, SharedBodyComponent body, DrinkEvent args) { if (args.Drink.Deleted) { return; } args.Drink.CancelToken = null; var transferAmount = FixedPoint2.Min(args.Drink.TransferAmount, args.DrinkSolution.DrainAvailable); var drained = _solutionContainerSystem.Drain(args.Drink.Owner, args.DrinkSolution, transferAmount); var forceDrink = uid != args.User; if (!_bodySystem.TryGetComponentsOnMechanisms <StomachComponent>(uid, out var stomachs, body)) { _popupSystem.PopupEntity( forceDrink ? Loc.GetString("drink-component-try-use-drink-cannot-drink-other") : Loc.GetString("drink-component-try-use-drink-had-enough"), uid, Filter.Entities(args.User)); if (EntityManager.HasComponent <RefillableSolutionComponent>(uid)) { _spillableSystem.SpillAt(args.User, drained, "PuddleSmear"); return; } _solutionContainerSystem.Refill(uid, args.DrinkSolution, drained); return; } var firstStomach = stomachs.FirstOrNull( stomach => _stomachSystem.CanTransferSolution((stomach.Comp).Owner, drained)); // 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)); _spillableSystem.SpillAt(uid, drained, "PuddleSmear"); return; } if (forceDrink) { 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)); } else { _popupSystem.PopupEntity( Loc.GetString("drink-component-try-use-drink-success-slurp"), args.User, Filter.Pvs(args.User)); } SoundSystem.Play(Filter.Pvs(uid), args.Drink.UseSound.GetSound(), uid, AudioParams.Default.WithVolume(-2f)); drained.DoEntityReaction(uid, ReactionMethod.Ingestion); _stomachSystem.TryTransferSolution(firstStomach.Value.Comp.Owner, drained, firstStomach.Value.Comp); }
public PuddleComponent?SpillAt(TileRef tileRef, Solution solution, string prototype, bool overflow = true, bool sound = true, bool noTileReact = false, bool combine = true) { if (solution.TotalVolume <= 0) { return(null); } // If space return early, let that spill go out into the void if (tileRef.Tile.IsEmpty) { return(null); } var gridId = tileRef.GridIndex; if (!_mapManager.TryGetGrid(gridId, out var mapGrid)) { return(null); // Let's not spill to invalid grids. } if (!noTileReact) { // First, do all tile reactions foreach (var(reagentId, quantity) in solution.Contents) { var proto = _prototypeManager.Index <ReagentPrototype>(reagentId); proto.ReactionTile(tileRef, quantity); } } // Tile reactions used up everything. if (solution.CurrentVolume == FixedPoint2.Zero) { return(null); } // Get normalized co-ordinate for spill location and spill it in the centre // TODO: Does SnapGrid or something else already do this? var spillGridCoords = mapGrid.GridTileToWorld(tileRef.GridIndices); var spillEntities = _entityLookup.GetEntitiesIntersecting(mapGrid.ParentMapId, spillGridCoords.Position).ToArray(); foreach (var spillEntity in spillEntities) { if (_solutionContainerSystem.TryGetRefillableSolution(spillEntity, out var solutionContainerComponent)) { _solutionContainerSystem.Refill(spillEntity, solutionContainerComponent, solution.SplitSolution(FixedPoint2.Min( solutionContainerComponent.AvailableVolume, solutionContainerComponent.MaxSpillRefill)) ); } } if (combine) { foreach (var spillEntity in spillEntities) { if (!EntityManager.TryGetComponent(spillEntity, out PuddleComponent? puddleComponent)) { continue; } if (!overflow && _puddleSystem.WouldOverflow(puddleComponent.Owner, solution, puddleComponent)) { return(null); } if (!_puddleSystem.TryAddSolution(puddleComponent.Owner, solution, sound)) { continue; } return(puddleComponent); } } var puddleEnt = EntityManager.SpawnEntity(prototype, spillGridCoords); var newPuddleComponent = EntityManager.GetComponent <PuddleComponent>(puddleEnt); _puddleSystem.TryAddSolution(newPuddleComponent.Owner, solution, sound); return(newPuddleComponent); }
/// <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) { if (!Resolve(uid, ref drink)) { return(false); } // if currently being used to force-feed, cancel that action. if (drink.CancelToken != null) { drink.CancelToken.Cancel(); drink.CancelToken = null; return(true); } if (!drink.Opened) { _popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-not-open", ("owner", Name: EntityManager.GetComponent <MetaDataComponent>(drink.Owner).EntityName)), uid, Filter.Entities(userUid)); return(true); } if (!EntityManager.TryGetComponent(userUid, out SharedBodyComponent? body)) { return(false); } if (!_solutionContainerSystem.TryGetDrainableSolution((drink).Owner, out var drinkSolution) || drinkSolution.DrainAvailable <= 0) { _popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-is-empty", ("entity", Name: EntityManager.GetComponent <MetaDataComponent>(drink.Owner).EntityName)), uid, Filter.Entities(userUid)); return(true); } 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); } if (_foodSystem.IsMouthBlocked(userUid, userUid)) { return(true); } var transferAmount = FixedPoint2.Min(drink.TransferAmount, drinkSolution.DrainAvailable); var drain = _solutionContainerSystem.Drain(uid, drinkSolution, transferAmount); var firstStomach = stomachs.FirstOrNull( stomach => _stomachSystem.CanTransferSolution((stomach.Comp).Owner, drain)); // 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"), userUid, Filter.Entities(userUid)); if (EntityManager.HasComponent <RefillableSolutionComponent>(uid)) { _spillableSystem.SpillAt(userUid, drain, "PuddleSmear"); return(true); } _solutionContainerSystem.Refill(uid, drinkSolution, drain); return(true); } SoundSystem.Play(Filter.Pvs(userUid), drink.UseSound.GetSound(), userUid, AudioParams.Default.WithVolume(-2f)); _popupSystem.PopupEntity(Loc.GetString("drink-component-try-use-drink-success-slurp"), userUid, Filter.Pvs(userUid)); drain.DoEntityReaction(userUid, ReactionMethod.Ingestion); _stomachSystem.TryTransferSolution((firstStomach.Value.Comp).Owner, drain, firstStomach.Value.Comp); return(true); }