Ejemplo n.º 1
0
        public override void OnGameTick(float deltaTime)
        {
            if (entity.Pos.Y < -30)
            {
                entity.ReceiveDamage(new DamageSource()
                {
                    Source = EnumDamageSource.Void,
                    Type   = EnumDamageType.Gravity
                }, 4);
            }

            secondsSinceLastUpdate += deltaTime;

            if (secondsSinceLastUpdate >= 1)
            {
                secondsSinceLastUpdate = 0;

                if (entity.Alive && Health < MaxHealth)
                {
                    float recoverySpeed = 0.01f;

                    EntityBehaviorHunger ebh = entity.GetBehavior <EntityBehaviorHunger>();

                    if (ebh != null)
                    {
                        EntityPlayer plr = (EntityPlayer)entity;
                        if (plr != null && entity.World.PlayerByUid(plr.PlayerUID).WorldData.CurrentGameMode == EnumGameMode.Creative)
                        {
                            return;
                        }

                        // When below 75% satiety, autoheal starts dropping
                        recoverySpeed = GameMath.Clamp(0.01f * ebh.Saturation / ebh.MaxSaturation * 1 / 0.75f, 0, 0.01f);

                        ebh.ConsumeSaturation(150f * recoverySpeed);
                    }

                    Health = Math.Min(Health + recoverySpeed, MaxHealth);
                }

                int rainy = entity.World.BlockAccessor.GetRainMapHeightAt((int)entity.ServerPos.X, (int)entity.ServerPos.Z);
                if (entity.World.Side == EnumAppSide.Server && entity is EntityPlayer && rainy <= entity.ServerPos.Y)
                {
                    WeatherSystemBase wsys = entity.Api.ModLoader.GetModSystem <WeatherSystemBase>();
                    var state = wsys.GetPrecipitationState(entity.ServerPos.XYZ);

                    if (state != null && state.ParticleSize > 0.6 && state.Type == EnumPrecipitationType.Hail && entity.World.Rand.NextDouble() < state.Level / 2)
                    {
                        entity.ReceiveDamage(new DamageSource()
                        {
                            Source = EnumDamageSource.Weather,
                            Type   = EnumDamageType.BluntAttack
                        }, (float)state.ParticleSize / 15f);
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Consumes a meal
        /// </summary>
        /// <param name="world"></param>
        /// <param name="eatingPlayer"></param>
        /// <param name="contentStacks"></param>
        /// <param name="recipeCode"></param>
        /// <param name="remainingServings"></param>
        /// <returns>Amount of servings left</returns>
        public virtual float Consume(IWorldAccessor world, IPlayer eatingPlayer, ItemSlot inSlot, ItemStack[] contentStacks, float remainingServings, bool mulwithStackSize)
        {
            float[] nmul = GetNutritionHealthMul(null, inSlot, eatingPlayer.Entity);

            FoodNutritionProperties[] multiProps = GetContentNutritionProperties(world, inSlot, contentStacks, eatingPlayer.Entity, mulwithStackSize, nmul[0], nmul[1]);
            if (multiProps == null)
            {
                return(remainingServings);
            }

            float totalHealth        = 0;
            EntityBehaviorHunger ebh = eatingPlayer.Entity.GetBehavior <EntityBehaviorHunger>();
            float satiablePoints     = ebh.MaxSaturation - ebh.Saturation;


            float mealSatpoints = 0;

            for (int i = 0; i < multiProps.Length; i++)
            {
                FoodNutritionProperties nutriProps = multiProps[i];
                if (nutriProps == null)
                {
                    continue;
                }

                mealSatpoints += nutriProps.Satiety;
            }

            float servingsNeeded = GameMath.Clamp(satiablePoints / Math.Max(1, mealSatpoints), 0, 1);
            float servingsToEat  = Math.Min(remainingServings, servingsNeeded);

            // Affect the players body temperature by eating meals with a larger temperature difference
            float temp = inSlot.Itemstack.Collectible.GetTemperature(world, inSlot.Itemstack);
            var   bh   = eatingPlayer.Entity.GetBehavior <EntityBehaviorBodyTemperature>();

            if (bh != null && Math.Abs(temp - bh.CurBodyTemperature) > 10)
            {
                float intensity = Math.Min(1, (temp - bh.CurBodyTemperature) / 30f);
                bh.CurBodyTemperature += GameMath.Clamp(mealSatpoints * servingsToEat / 80f * intensity, 0, 5);
            }


            for (int i = 0; i < multiProps.Length; i++)
            {
                FoodNutritionProperties nutriProps = multiProps[i];
                if (nutriProps == null)
                {
                    continue;
                }

                float mul = servingsToEat;
                float sat = mul * nutriProps.Satiety;

                eatingPlayer.Entity.ReceiveSaturation(sat, nutriProps.FoodCategory, 10 + sat / 70f * 60f, 1f);

                if (nutriProps.EatenStack?.ResolvedItemstack != null)
                {
                    if (eatingPlayer == null || !eatingPlayer.InventoryManager.TryGiveItemstack(nutriProps.EatenStack.ResolvedItemstack.Clone(), true))
                    {
                        world.SpawnItemEntity(nutriProps.EatenStack.ResolvedItemstack.Clone(), eatingPlayer.Entity.SidedPos.XYZ);
                    }
                }

                totalHealth += mul * nutriProps.Health;
            }


            if (totalHealth != 0)
            {
                eatingPlayer.Entity.ReceiveDamage(new DamageSource()
                {
                    Source = EnumDamageSource.Internal,
                    Type   = totalHealth > 0 ? EnumDamageType.Heal : EnumDamageType.Poison
                }, Math.Abs(totalHealth));
            }


            return(Math.Max(0, remainingServings - servingsToEat));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Consumes a meal
        /// </summary>
        /// <param name="world"></param>
        /// <param name="eatingPlayer"></param>
        /// <param name="contentStacks"></param>
        /// <param name="recipeCode"></param>
        /// <param name="remainingServings"></param>
        /// <returns>Amount of servings left</returns>
        public static float Consume(IWorldAccessor world, IPlayer eatingPlayer, ItemSlot inSlot, ItemStack[] contentStacks, float remainingServings, bool mulwithStackSize)
        {
            FoodNutritionProperties[] multiProps = GetContentNutritionProperties(world, inSlot, contentStacks, eatingPlayer.Entity);
            if (multiProps == null)
            {
                return(remainingServings);
            }

            float totalHealth        = 0;
            EntityBehaviorHunger ebh = eatingPlayer.Entity.GetBehavior <EntityBehaviorHunger>();
            float satiablePoints     = ebh.MaxSaturation - ebh.Saturation;


            float mealSatpoints = 0;

            for (int i = 0; i < multiProps.Length; i++)
            {
                FoodNutritionProperties nutriProps = multiProps[i];
                if (nutriProps == null)
                {
                    continue;
                }

                mealSatpoints += nutriProps.Satiety * (mulwithStackSize ? contentStacks[i].StackSize : 1);
            }

            float servingsNeeded = GameMath.Clamp(satiablePoints / Math.Max(1, mealSatpoints), 0, 1);

            float servingsToEat = Math.Min(remainingServings, servingsNeeded);



            for (int i = 0; i < multiProps.Length; i++)
            {
                FoodNutritionProperties nutriProps = multiProps[i];
                if (nutriProps == null)
                {
                    continue;
                }

                float mul = servingsToEat * (mulwithStackSize ? contentStacks[i].StackSize : 1);
                float sat = mul * nutriProps.Satiety;

                eatingPlayer.Entity.ReceiveSaturation(sat, nutriProps.FoodCategory, 10 + sat / 70f * 60f, 1f);

                if (nutriProps.EatenStack?.ResolvedItemstack != null)
                {
                    if (eatingPlayer == null || !eatingPlayer.InventoryManager.TryGiveItemstack(nutriProps.EatenStack.ResolvedItemstack.Clone(), true))
                    {
                        world.SpawnItemEntity(nutriProps.EatenStack.ResolvedItemstack.Clone(), eatingPlayer.Entity.SidedPos.XYZ);
                    }
                }

                totalHealth += mul * nutriProps.Health;
            }


            if (totalHealth != 0)
            {
                eatingPlayer.Entity.ReceiveDamage(new DamageSource()
                {
                    Source = EnumDamageSource.Internal,
                    Type   = totalHealth > 0 ? EnumDamageType.Heal : EnumDamageType.Poison
                }, Math.Abs(totalHealth));
            }

            return(Math.Max(0, remainingServings - servingsToEat));
        }
Ejemplo n.º 4
0
        public override void OnGameTick(float deltaTime)
        {
            entity.World.FrameProfiler.Mark("not-bhhealth");
            if (entity.Pos.Y < -30)
            {
                entity.ReceiveDamage(new DamageSource()
                {
                    Source = EnumDamageSource.Void,
                    Type   = EnumDamageType.Gravity
                }, 4);
            }

            secondsSinceLastUpdate += deltaTime;

            if (secondsSinceLastUpdate >= 1)
            {
                secondsSinceLastUpdate = 0;

                if (entity.Alive)
                {
                    float health    = Health; // higher performance to read this TreeAttribute only once
                    float maxHealth = MaxHealth;
                    if (health < maxHealth)
                    {
                        float recoverySpeed = 0.01f;

                        // Only players have the hunger behavior, and the different nutrient saturations
                        if (entity is EntityPlayer plr)
                        {
                            EntityBehaviorHunger ebh = entity.GetBehavior <EntityBehaviorHunger>();

                            if (ebh != null)
                            {
                                if (entity.World.PlayerByUid(plr.PlayerUID).WorldData.CurrentGameMode == EnumGameMode.Creative)
                                {
                                    return;
                                }

                                // When below 75% satiety, autoheal starts dropping
                                recoverySpeed = GameMath.Clamp(0.01f * ebh.Saturation / ebh.MaxSaturation * 1 / 0.75f, 0, 0.01f);

                                ebh.ConsumeSaturation(150f * recoverySpeed);
                            }
                        }

                        Health = Math.Min(health + recoverySpeed, maxHealth);
                    }
                }

                if (entity is EntityPlayer && entity.World.Side == EnumAppSide.Server)
                {
                    // A costly check every 1s for hail damage, but it applies only to players who are in the open

                    int rainy = entity.World.BlockAccessor.GetRainMapHeightAt((int)entity.ServerPos.X, (int)entity.ServerPos.Z);
                    if (entity.ServerPos.Y >= rainy)
                    {
                        WeatherSystemBase wsys = entity.Api.ModLoader.GetModSystem <WeatherSystemBase>();
                        var state = wsys.GetPrecipitationState(entity.ServerPos.XYZ);

                        if (state != null && state.ParticleSize >= 0.5 && state.Type == EnumPrecipitationType.Hail && entity.World.Rand.NextDouble() < state.Level / 2)
                        {
                            entity.ReceiveDamage(new DamageSource()
                            {
                                Source = EnumDamageSource.Weather,
                                Type   = EnumDamageType.BluntAttack
                            }, (float)state.ParticleSize / 15f);
                        }
                    }
                }
            }
        }