Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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);
        }
        private void OnFeed(EntityUid uid, SharedBodyComponent body, FeedEvent args)
        {
            if (args.Food.Deleted)
            {
                return;
            }

            args.Food.CancelToken = null;

            if (!_bodySystem.TryGetComponentsOnMechanisms <StomachComponent>(uid, out var stomachs, body))
            {
                return;
            }

            var transferAmount = args.Food.TransferAmount != null
                ? FixedPoint2.Min((FixedPoint2)args.Food.TransferAmount, args.FoodSolution.CurrentVolume)
                : args.FoodSolution.CurrentVolume;

            var split        = _solutionContainerSystem.SplitSolution((args.Food).Owner, args.FoodSolution, transferAmount);
            var firstStomach = stomachs.FirstOrNull(
                stomach => _stomachSystem.CanTransferSolution((stomach.Comp).Owner, split));

            var forceFeed = uid != args.User;

            // No stomach so just popup a message that they can't eat.
            if (firstStomach == null)
            {
                _solutionContainerSystem.TryAddSolution(uid, args.FoodSolution, split);
                _popupSystem.PopupEntity(
                    forceFeed ?
                    Loc.GetString("food-system-you-cannot-eat-any-more-other") :
                    Loc.GetString("food-system-you-cannot-eat-any-more")
                    , uid, Filter.Entities(args.User));
                return;
            }

            split.DoEntityReaction(uid, ReactionMethod.Ingestion);
            _stomachSystem.TryTransferSolution(firstStomach.Value.Comp.Owner, split, firstStomach.Value.Comp);

            if (forceFeed)
            {
                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("food-system-force-feed-success", ("user", userName)),
                                         uid, Filter.Entities(uid));

                _popupSystem.PopupEntity(Loc.GetString("food-system-force-feed-success-user", ("target", targetName)),
                                         args.User, Filter.Entities(args.User));
            }
            else
            {
                _popupSystem.PopupEntity(Loc.GetString(args.Food.EatMessage, ("food", args.Food.Owner)), args.User, Filter.Entities(args.User));
            }

            SoundSystem.Play(Filter.Pvs(uid), args.Food.UseSound.GetSound(), uid, AudioParams.Default.WithVolume(-1f));

            // Try to break all used utensils
            foreach (var utensil in args.Utensils)
            {
                _utensilSystem.TryBreak((utensil).Owner, args.User);
            }

            if (args.Food.UsesRemaining > 0)
            {
                return;
            }

            if (string.IsNullOrEmpty(args.Food.TrashPrototype))
            {
                EntityManager.QueueDeleteEntity(args.Food.Owner);
            }
            else
            {
                DeleteAndSpawnTrash(args.Food, args.User);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Tries to eat some food
        /// </summary>
        /// <param name="uid">Food entity.</param>
        /// <param name="user">Feeding initiator.</param>
        /// <returns>True if an interaction occurred (i.e., food was consumed, or a pop-up message was created)</returns>
        public bool TryUseFood(EntityUid uid, EntityUid user, FoodComponent?food = null)
        {
            if (!Resolve(uid, ref food))
            {
                return(false);
            }

            // if currently being used to force-feed, cancel that action.
            if (food.CancelToken != null)
            {
                food.CancelToken.Cancel();
                food.CancelToken = null;
                return(true);
            }

            if (uid == user ||                                                                                  //Suppresses self-eating
                EntityManager.TryGetComponent <MobStateComponent>(uid, out var mobState) && mobState.IsAlive()) // Suppresses eating alive mobs
            {
                return(false);
            }

            if (!_solutionContainerSystem.TryGetSolution(uid, food.SolutionName, out var solution))
            {
                return(false);
            }

            if (food.UsesRemaining <= 0)
            {
                _popupSystem.PopupEntity(Loc.GetString("food-system-try-use-food-is-empty", ("entity", uid)), user, Filter.Entities(user));
                DeleteAndSpawnTrash(food, user);
                return(true);
            }

            if (!EntityManager.TryGetComponent(user, out SharedBodyComponent ? body) ||
                !_bodySystem.TryGetComponentsOnMechanisms <StomachComponent>(user, out var stomachs, body))
            {
                return(false);
            }

            if (IsMouthBlocked(user, user))
            {
                return(true);
            }

            var usedUtensils = new List <UtensilComponent>();

            if (!TryGetRequiredUtensils(user, food, out var utensils))
            {
                return(true);
            }

            if (!user.InRangeUnobstructed(uid, popup: true))
            {
                return(true);
            }

            var transferAmount = food.TransferAmount != null?FixedPoint2.Min((FixedPoint2)food.TransferAmount, solution.CurrentVolume) : solution.CurrentVolume;

            var split        = _solutionContainerSystem.SplitSolution(uid, solution, transferAmount);
            var firstStomach = stomachs.FirstOrNull(
                stomach => _stomachSystem.CanTransferSolution((stomach.Comp).Owner, split));

            if (firstStomach == null)
            {
                _solutionContainerSystem.TryAddSolution(uid, solution, split);
                _popupSystem.PopupEntity(Loc.GetString("food-system-you-cannot-eat-any-more"), user, Filter.Entities(user));
                return(true);
            }

            // TODO: Account for partial transfer.
            split.DoEntityReaction(user, ReactionMethod.Ingestion);
            _stomachSystem.TryTransferSolution((firstStomach.Value.Comp).Owner, split, firstStomach.Value.Comp);

            SoundSystem.Play(Filter.Pvs(user), food.UseSound.GetSound(), user, AudioParams.Default.WithVolume(-1f));
            _popupSystem.PopupEntity(Loc.GetString(food.EatMessage, ("food", food.Owner)), user, Filter.Entities(user));

            // Try to break all used utensils
            foreach (var utensil in usedUtensils)
            {
                _utensilSystem.TryBreak((utensil).Owner, user);
            }

            if (food.UsesRemaining > 0)
            {
                return(true);
            }

            if (string.IsNullOrEmpty(food.TrashPrototype))
            {
                EntityManager.QueueDeleteEntity((food).Owner);
            }
            else
            {
                DeleteAndSpawnTrash(food, user);
            }

            return(true);
        }