Пример #1
0
        private void OnClientGameTick(float dt)
        {
            quarterSecAccum += dt;
            if (quarterSecAccum > 0.25f)
            {
                clientClimateCond = capi.World.BlockAccessor.GetClimateAt(plrPos, EnumGetClimateMode.NowValues);
                quarterSecAccum   = 0;

                playerChunkLoaded |= capi.World.BlockAccessor.GetChunkAtBlockPos(plrPos) != null; // To avoid rain for one second right after joining
            }

            simLightning.ClientTick(dt);

            for (int i = 0; i < 4; i++)
            {
                WeatherSimulationRegion sim = WeatherDataAtPlayer.AdjacentSims[i];
                if (sim == dummySim)
                {
                    continue;
                }
                sim.TickEvery25ms(dt);
            }

            simSounds.Update(dt);
            rainOverlaySnap.climateCond = clientClimateCond;
            rainOverlaySnap.SetAmbient(rainOverlayPattern, capi == null ? 0 : capi.Ambient.Base.FogDensity.Value);
        }
Пример #2
0
        /// <summary>
        /// Get the current precipitation as seen by the client at pos
        /// </summary>
        /// <param name="rainOnly">If true, returns 0 if it is currently snowing</param>
        /// <returns></returns>
        public double GetActualRainLevel(BlockPos pos, bool rainOnly = false)
        {
            ClimateCondition conds = clientClimateCond;

            if (conds == null || !playerChunkLoaded)
            {
                return(0.0);
            }
            float precIntensity = conds.Rainfall;

            if (rainOnly)
            {
                // TODO:  Testing whether it is snowing or not on the client is kinda slow - though the WeatherSimulationParticles must already know!

                WeatherDataSnapshot   weatherData = BlendedWeatherData;
                EnumPrecipitationType precType    = weatherData.BlendedPrecType;
                if (precType == EnumPrecipitationType.Auto)
                {
                    precType = conds.Temperature < weatherData.snowThresholdTemp ? EnumPrecipitationType.Snow : EnumPrecipitationType.Rain;
                }
                if (precType == EnumPrecipitationType.Snow)
                {
                    return(0d);
                }
            }

            return(precIntensity);
        }
Пример #3
0
        /// <summary>
        /// Compares the ClimateCondition at the given BlockPos with the requirements of the
        /// BlockLayer associated with the next growth stage block. The low fertility variant
        /// is checked first. If it will grow then it returns true immediately, otherwise it
        /// checks the specific block layer for this variant.
        /// </summary>
        /// <param name="world"></param>
        /// <param name="pos"></param>
        /// <returns>True if the climate is appropriate for growth, false otherwise</returns>
        private bool isAppropriateClimateToGrow(IWorldAccessor world, BlockPos pos)
        {
            ClimateCondition climate = world.BlockAccessor.GetClimateAt(pos);

            return(isAppropriateClimateToGrow(world, pos, getLowFertilityVariant(), climate) ||
                   isAppropriateClimateToGrow(world, pos, getNextGrowthStageCode(), climate));
        }
Пример #4
0
        public override bool ShouldReceiveServerGameTicks(IWorldAccessor world, BlockPos pos, Random offThreadRandom, out object extra)
        {
            extra = null;
            if (!GlobalConstants.MeltingFreezingEnabled)
            {
                return(false);
            }

            if (freezable && offThreadRandom.NextDouble() < 0.6)
            {
                int rainY = world.BlockAccessor.GetRainMapHeightAt(pos);
                if (rainY <= pos.Y)
                {
                    for (int i = 0; i < BlockFacing.HORIZONTALS.Length; i++)
                    {
                        BlockFacing facing = BlockFacing.HORIZONTALS[i];
                        if (world.BlockAccessor.GetBlock(pos.AddCopy(facing)).Replaceable < 6000)
                        {
                            ClimateCondition conds = world.BlockAccessor.GetClimateAt(pos, EnumGetClimateMode.NowValues);
                            if (conds != null && conds.Temperature < -4)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Get the current precipitation as seen by the client at pos
        /// </summary>
        /// <param name="rainOnly">If true, returns 0 if it is currently snowing</param>
        /// <returns></returns>
        public double GetActualRainLevel(BlockPos pos, bool rainOnly = false)
        {
            ClimateCondition conds = clientClimateCond;

            if (conds == null || !playerChunkLoaded)
            {
                return(0.0);
            }
            float precIntensity = conds.Rainfall;

            if (rainOnly)
            {
                WeatherDataSnapshot   weatherData = BlendedWeatherData;
                EnumPrecipitationType precType    = weatherData.BlendedPrecType;
                if (precType == EnumPrecipitationType.Auto)
                {
                    precType = conds.Temperature < weatherData.snowThresholdTemp ? EnumPrecipitationType.Snow : EnumPrecipitationType.Rain;
                }
                if (precType == EnumPrecipitationType.Snow)
                {
                    return(0d);
                }
            }

            return(precIntensity);
        }
Пример #6
0
        public void UpdateText()
        {
            BlockPos         entityPos = capi.World.Player.Entity.Pos.AsBlockPos;
            ClimateCondition climate   = capi.World.BlockAccessor.GetClimateAt(entityPos);

            GameCalendar cal       = (GameCalendar)capi.World.Calendar;
            float        stability = (float)capi.World.Player.Entity.WatchedAttributes.GetDouble("temporalStability", 0.0);

            string hour   = cal.FullHourOfDay < 10 ? "0" + cal.FullHourOfDay : "" + cal.FullHourOfDay;
            int    m      = (int)(60 * (cal.HourOfDay - cal.FullHourOfDay));
            string dot    = m % 2 == 0 ? ":" : " ";
            string minute = m < 10 ? "0" + m : "" + m;

            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.AppendLine("Date: " + cal.DayOfYear + "/" + cal.DaysPerYear + ", " + cal.Year)
            .AppendLine("Time: " + hour + dot + minute)
            .AppendLine("Global Season: " + cal.Season)
            .AppendLine("Local Temperature: " + Math.Round(climate.Temperature, 3))
            .AppendLine("Local Rainfall: " + Math.Round(climate.Rainfall, 3))
            .AppendLine("Local Fertility: " + Math.Round(climate.Fertility, 3))
            .AppendLine("Local Wind Velocity: " + GlobalConstants.CurrentWindSpeedClient.Sanitize())
            .AppendLine("Local Temporal Stability: " + Math.Round(capi.ModLoader.GetModSystem <SystemTemporalStability>().GetTemporalStability(entityPos), 3))
            .AppendLine("Player Temporal Stability: " + Math.Round(stability * 100f, 3) + "%");

            SingleComposer.GetDynamicText("clock").SetNewText(stringBuilder.ToString());
        }
Пример #7
0
        private void TestHarvestable(float dt)
        {
            ClimateCondition conds = Api.World.BlockAccessor.GetClimateAt(Pos, EnumGetClimateMode.NowValues);

            if (conds == null)
            {
                return;
            }

            float temp = conds.Temperature + (roomness > 0 ? 5 : 0);

            actvitiyLevel = GameMath.Clamp(temp / 5f, 0f, 1f);

            // Reset timers during winter
            if (temp <= -10)
            {
                harvestableAtTotalHours = Api.World.Calendar.TotalHours + 24 / 2 * (3 + Api.World.Rand.NextDouble() * 8);
                cooldownUntilTotalHours = Api.World.Calendar.TotalHours + 4 / 2 * 24;
            }

            if (!Harvestable && !isWildHive && Api.World.Calendar.TotalHours > harvestableAtTotalHours && hivePopSize > EnumHivePopSize.Poor)
            {
                Harvestable = true;
                MarkDirty(true);
            }
        }
Пример #8
0
        public bool IsPatchSuitableUnderTree(BlockPatch patch, int mapSizeY, ClimateCondition climate, int y)
        {
            float rainRel = climate.Rainfall;

            if (rainRel < patch.MinRain || rainRel > patch.MaxRain)
            {
                // again faster path without needing to fetch temperature etc
                return(false);
            }

            float temp = climate.Temperature;

            if (temp < patch.MinTemp || temp > patch.MaxTemp)
            {
                // again faster path without needing to fetch sealevel and fertility
                return(false);
            }

            float sealevelDistRel = ((float)y - TerraGenConfig.seaLevel) / ((float)mapSizeY - TerraGenConfig.seaLevel);

            if (sealevelDistRel < patch.MinY || sealevelDistRel > patch.MaxY)
            {
                return(false);
            }

            // finally test fertility (the least common blockpatch criterion)
            float fertilityRel = climate.Fertility;

            return(fertilityRel >= patch.MinFertility && fertilityRel <= patch.MaxFertility);
        }
Пример #9
0
        public virtual void CheckTransition(float dt)
        {
            Block block = Api.World.BlockAccessor.GetBlock(Pos);

            if (block.Attributes == null)
            {
                Api.World.Logger.Error("BETransient exiting at {0} cannot find block attributes. Will stop transient timer", Pos);
                UnregisterGameTickListener(listenerId);
                return;
            }

            // In case this block was imported from another older world. In that case lastCheckAtTotalDays would be a future date.
            lastCheckAtTotalDays = Math.Min(lastCheckAtTotalDays, Api.World.Calendar.TotalDays);


            while (Api.World.Calendar.TotalDays - lastCheckAtTotalDays > 1f / Api.World.Calendar.HoursPerDay)
            {
                lastCheckAtTotalDays += 1f / Api.World.Calendar.HoursPerDay;
                transitionHoursLeft  -= 1f;

                ClimateCondition conds = Api.World.BlockAccessor.GetClimateAt(Pos, EnumGetClimateMode.ForSuppliedDateValues, lastCheckAtTotalDays);
                if (conds == null)
                {
                    return;
                }

                if (props.Condition == EnumTransientCondition.Temperature)
                {
                    if (conds.Temperature < props.WhenBelowTemperature || conds.Temperature > props.WhenAboveTemperature)
                    {
                        tryTransition(props.ConvertTo);
                    }

                    continue;
                }


                bool reset = conds.Temperature < props.ResetBelowTemperature;
                bool stop  = conds.Temperature < props.StopBelowTemperature;

                if (stop || reset)
                {
                    transitionHoursLeft += 1f;

                    if (reset)
                    {
                        transitionHoursLeft = props.InGameHours;
                    }

                    continue;
                }

                if (transitionHoursLeft <= 0)
                {
                    tryTransition(props.ConvertTo);
                    break;
                }
            }
        }
Пример #10
0
 /// <summary>
 /// Should this current track play?
 /// </summary>
 /// <param name="props">Player Properties</param>
 /// <returns>Should we play the current track?</returns>
 public virtual bool ShouldPlay(TrackedPlayerProperties props, ClimateCondition conds, BlockPos pos)
 {
     if (IsActive)
     {
         return(false);
     }
     return(true);
 }
Пример #11
0
        public override bool ShouldReceiveServerGameTicks(IWorldAccessor world, BlockPos pos, Random offThreadRandom, out object extra)
        {
            extra = null;
            ClimateCondition conds = world.BlockAccessor.GetClimateAt(pos, EnumGetClimateMode.NowValues);

            float chance = GameMath.Clamp((conds.Temperature - 2f) / 20f, 0, 1);

            return(offThreadRandom.NextDouble() < chance);
        }
Пример #12
0
        private void Event_OnGetClimate(ref ClimateCondition climate, BlockPos pos, EnumGetClimateMode mode, double totalDays)
        {
            if (mode == EnumGetClimateMode.WorldGenValues)
            {
                return;
            }

            updateTemperature(ref climate, pos, api.World.Calendar.YearRel, api.World.Calendar.HourOfDay, totalDays);
        }
Пример #13
0
        public void TickEveryInGameHourServer(double nowTotalHours)
        {
            SnowAccumSnapshot latestSnap = new SnowAccumSnapshot()
            {
                TotalHours = nowTotalHours,
                // SumTemperatureByRegionCorner = new API.FloatDataMap3D(snowAccumResolution, snowAccumResolution, snowAccumResolution),
                SnowAccumulationByRegionCorner = new API.FloatDataMap3D(snowAccumResolution, snowAccumResolution, snowAccumResolution)
            };

            // Idea: We don't want to simulate 512x512 blocks at all times, thats a lot of iterations
            // lets try with just the 8 corner points of the region cuboid and lerp
            BlockPos tmpPos  = new BlockPos();
            int      regsize = ws.api.World.BlockAccessor.RegionSize;


            for (int ix = 0; ix < snowAccumResolution; ix++)
            {
                for (int iy = 0; iy < snowAccumResolution; iy++)
                {
                    for (int iz = 0; iz < snowAccumResolution; iz++)
                    {
                        int y = iy == 0 ? ws.api.World.SeaLevel : ws.api.World.BlockAccessor.MapSizeY - 1;

                        tmpPos.Set(
                            regionX * regsize + ix * (regsize - 1),
                            y,
                            regionZ * regsize + iz * (regsize - 1)
                            );

                        ClimateCondition nowcond = ws.api.World.BlockAccessor.GetClimateAt(tmpPos, EnumGetClimateMode.ForSuppliedDateValues, nowTotalHours + 0.5); // Sample from the middle of the hour
                        if (nowcond == null)
                        {
                            return;
                        }

                        //latestSnap.SumTemperatureByRegionCorner.AddValue(ix, iy, iz, nowcond.Temperature);

                        if (nowcond.Temperature > 0)
                        {
                            latestSnap.SnowAccumulationByRegionCorner.AddValue(ix, iy, iz, -nowcond.Temperature / 5f);
                        }
                        else
                        {
                            latestSnap.SnowAccumulationByRegionCorner.AddValue(ix, iy, iz, nowcond.Rainfall / 3f);
                        }
                    }
                }
            }

            lock (lockTest)
            {
                SnowAccumSnapshots.Add(latestSnap);
            }
            latestSnap.Checks++;
        }
Пример #14
0
        public override bool ShouldReceiveServerGameTicks(IWorldAccessor world, BlockPos pos, Random offThreadRandom, out object extra)
        {
            extra = null;
            if (!canMelt)
            {
                return(false);
            }
            ClimateCondition conds = world.BlockAccessor.GetClimateAt(pos, EnumGetClimateMode.NowValues);

            return(conds != null && offThreadRandom.NextDouble() < GameMath.Clamp((conds.Temperature - 0.5f) / (15f - 10f * conds.Rainfall), 0, 1));
        }
Пример #15
0
        private bool Event_OnTrySpawnEntity(ref EntityProperties properties, Vec3d spawnPosition, long herdId)
        {
            if (properties.Code.Path.StartsWithFast("raccoon"))
            {
                for (int i = 0; i < BlockFacing.HORIZONTALS.Length; i++)
                {
                    BlockFacing facing = BlockFacing.HORIZONTALS[i];
                    Vec3i       dir    = facing.Normali;

                    Block block = sapi.World.BlockAccessor.GetBlock((int)spawnPosition.X + dir.X, (int)spawnPosition.Y, (int)spawnPosition.Z + dir.Z);
                    if (block is BlockLog)
                    {
                        return(true);
                    }

                    block = sapi.World.BlockAccessor.GetBlock((int)spawnPosition.X + dir.X + dir.X, (int)spawnPosition.Y, (int)spawnPosition.Z + dir.Z + dir.Z);
                    if (block is BlockLog)
                    {
                        return(true);
                    }

                    block = sapi.World.BlockAccessor.GetBlock((int)spawnPosition.X + dir.X + dir.X, (int)spawnPosition.Y + 1, (int)spawnPosition.Z + dir.Z + dir.Z);
                    if (block is BlockLog)
                    {
                        return(true);
                    }
                }


                return(false);
            }


            if (properties.Code.Path.StartsWithFast("butterfly"))
            {
                ClimateCondition climate = sapi.World.BlockAccessor.GetClimateAt(new BlockPos((int)spawnPosition.X, (int)spawnPosition.Y, (int)spawnPosition.Z), EnumGetClimateMode.NowValues);
                if (climate.Temperature < 10)
                {
                    return(false);
                }
            }

            if (properties.Code.Path.StartsWithFast("sheep") || properties.Code.Path.StartsWithFast("boar"))
            {
                bool harshWinters = sapi.World.Config.GetString("harshWinters").ToBool(true);
                var  month        = sapi.World.Calendar.MonthName;
                if (harshWinters && (month == EnumMonth.December || month == EnumMonth.January || month == EnumMonth.February))
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #16
0
        protected void Event_OnGetClimate(ref ClimateCondition climate, BlockPos pos, EnumGetClimateMode mode = EnumGetClimateMode.WorldGenValues, double totalDays = 0)
        {
            if (mode == EnumGetClimateMode.WorldGenValues)
            {
                return;
            }
            float rainCloudness = GetRainCloudness(climate, pos.X + 0.5, pos.Z + 0.5, totalDays);

            climate.Rainfall         = GameMath.Clamp(rainCloudness - 0.5f, 0, 1);
            climate.RainCloudOverlay = GameMath.Clamp(rainCloudness, 0, 1);
        }
Пример #17
0
        private void Event_OnGetClimate(ref ClimateCondition climate, BlockPos pos, EnumGetClimateMode mode, double totalDays)
        {
            if (mode == EnumGetClimateMode.WorldGenValues)
            {
                return;
            }

            double yearRel   = totalDays / api.World.Calendar.DaysPerYear % 1;
            double hourOfDay = totalDays / api.World.Calendar.HoursPerDay % 1;

            updateTemperature(ref climate, pos, yearRel, hourOfDay, totalDays);
        }
Пример #18
0
        private void updateTemperature(ref ClimateCondition climate, BlockPos pos, double yearRel, double hourOfDay, double totalDays)
        {
            // 1. Global average temperature at this location
            double heretemp = climate.Temperature;

            // 2. season based temperature
            // - Near the equator the variation seems to be only 5-10 degrees
            // - In european cities the per month average temperature seem to vary by about 20 degrees (~ 0 - 20)
            // - Above the arctic circle it seems to vary by up to 60 degrees (~ -39 - 20)

            // -1 for south pole, 0 for equater, 1 for north pole
            double latitude = coreSys.onGetLatitude(pos.Z);
            double seasonalVariationAmplitude = Math.Abs(latitude) * 65;

            heretemp -= seasonalVariationAmplitude / 2;

            // 1 to 0 => january is coldest month
            // 0 to -1 => july is coldest month
            if (latitude > 0)
            {
                double distanceToJanuary = GameMath.Smootherstep(Math.Abs(GameMath.CyclicValueDistance(0.5f, yearRel * 12, 12) / 6f));
                heretemp += seasonalVariationAmplitude * distanceToJanuary;
            }
            else
            {
                double distanceToJuly = GameMath.Smootherstep(Math.Abs(GameMath.CyclicValueDistance(6.5f, yearRel * 12, 12) / 6f));
                heretemp += seasonalVariationAmplitude * distanceToJuly;
            }

            // 3. diurnal temperature variation:
            // https://en.wikipedia.org/wiki/Diurnal_temperature_variation

            // Lets define the variation strength as 5 + rainFall * 10
            double diurnalVariationAmplitude = 20 - climate.Rainfall * 8;

            // variation is then further reduced by the distance from the equator (because at the equator the day/night cycle is most intense, and thus the warming/cooling effects more pronounced)
            diurnalVariationAmplitude *= (0.2 + 0.8 * Math.Abs(latitude));

            // just before sunrise is the coldest time. We have no time zones in VS
            // lets just hardcode 6 am for this for now
            double distanceTo6Am = GameMath.SmoothStep(Math.Abs(GameMath.CyclicValueDistance(6, hourOfDay, 24) / 12f));

            heretemp -= diurnalVariationAmplitude / 2;
            heretemp += distanceTo6Am * diurnalVariationAmplitude;

            // 4. Yearly random noise
            heretemp += YearlyTemperatureNoise.Noise(totalDays, 0) * 3;

            // 5. Daily random noise
            heretemp += DailyTemperatureNoise.Noise(totalDays, 0);

            climate.Temperature = (float)heretemp;
        }
Пример #19
0
        public override bool ShouldReceiveServerGameTicks(IWorldAccessor world, BlockPos pos, Random offThreadRandom, out object extra)
        {
            extra = null;
            if (!GlobalConstants.MeltingFreezingEnabled)
            {
                return(false);
            }
            if (habitat == EnumReedsHabitat.Land)
            {
                return(false);
            }

            if (habitat == EnumReedsHabitat.Ice)  // ice -> water
            {
                ClimateCondition conds = world.BlockAccessor.GetClimateAt(pos, EnumGetClimateMode.NowValues);
                if (conds == null)
                {
                    return(false);
                }

                float chance = GameMath.Clamp((conds.Temperature - 2f) / 20f, 0, 1);
                return(offThreadRandom.NextDouble() < chance);
            }

            // water -> ice

            if (Variant["type"] == "papyrus")
            {
                return(false);                               //TODO: currently we do not have an ice version of Papyrus
            }
            if (offThreadRandom.NextDouble() < 0.6)
            {
                int rainY = world.BlockAccessor.GetRainMapHeightAt(pos);
                if (rainY <= pos.Y)
                {
                    for (int i = 0; i < BlockFacing.HORIZONTALS.Length; i++)
                    {
                        BlockFacing facing = BlockFacing.HORIZONTALS[i];
                        if (world.BlockAccessor.GetBlock(pos.AddCopy(facing)).Replaceable < 6000)
                        {
                            ClimateCondition conds = world.BlockAccessor.GetClimateAt(pos, EnumGetClimateMode.NowValues);
                            if (conds != null && conds.Temperature < -4)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Пример #20
0
        /// <summary>
        /// Should the game play this track?
        /// </summary>
        /// <param name="props">The properties of the current track.</param>
        /// <returns>Do we play this track?</returns>
        public bool ShouldPlay(TrackedPlayerProperties props, ClimateCondition conds, BlockPos pos)
        {
            if (props.sunSlight > 3 || !ShouldPlayCaveMusic)
            {
                return(false);
            }
            if (capi.World.ElapsedMilliseconds < cooldownUntilMs)
            {
                return(false);
            }

            return(true);
        }
        public void SetLerpedPrec(WeatherDataSnapshot left, WeatherDataSnapshot right, float w)
        {
            Ambient.SetLerped(left.Ambient, right.Ambient, w);
            PrecIntensity    = left.PrecIntensity * (1 - w) + right.PrecIntensity * w;
            PrecParticleSize = left.PrecParticleSize * (1 - w) + right.PrecParticleSize * w;

            nowPrecType          = left.nowPrecType;
            BlendedPrecType      = left.BlendedPrecType;
            nearLightningRate    = left.nearLightningRate;
            distantLightningRate = left.distantLightningRate;
            lightningMinTemp     = left.lightningMinTemp;
            climateCond          = left.climateCond;
            curWindSpeed.X       = left.curWindSpeed.X;
            snowThresholdTemp    = left.snowThresholdTemp;
        }
        public void LoadLerp(Vec3d pos, bool useArgValues, float lerpRainCloudOverlay = 0, float lerpRainOverlay = 0, float dt = 1)
        {
            int regSize = api.World.BlockAccessor.RegionSize;

            double regionRelX = (pos.X / regSize) - (int)Math.Round(pos.X / regSize);
            double regionRelZ = (pos.Z / regSize) - (int)Math.Round(pos.Z / regSize);

            LerpTopBot    = GameMath.Smootherstep(regionRelX + 0.5);
            LerpLeftRight = GameMath.Smootherstep(regionRelZ + 0.5);

            rainOverlayData = ws.rainOverlayPattern;
            rainSnapData    = ws.rainOverlaySnap;


            if (hereMapRegion == null)
            {
                this.lerpRainCloudOverlay = 0;
                this.lerpRainOverlay      = 0;
            }
            else
            {
                if (useArgValues)
                {
                    this.lerpRainCloudOverlay = lerpRainCloudOverlay;
                    this.lerpRainOverlay      = lerpRainOverlay;
                }
                else
                {
                    tmpPos.Set((int)pos.X, (int)pos.Y, (int)pos.Z);

                    int noiseSizeClimate = hereMapRegion.ClimateMap.InnerSize;
                    int climate          = 128 | (128 << 8) | (128 << 16);

                    if (noiseSizeClimate > 0)
                    {
                        double posXInRegionClimate = Math.Max(0, (pos.X / regSize - (int)pos.X / regSize) * noiseSizeClimate);
                        double posZInRegionClimate = Math.Max(0, (pos.Z / regSize - (int)pos.Z / regSize) * noiseSizeClimate);
                        climate = hereMapRegion.ClimateMap.GetUnpaddedColorLerped((float)posXInRegionClimate, (float)posZInRegionClimate);
                    }

                    ClimateCondition conds  = ws.GetClimateFast(tmpPos, climate);
                    float            tspeed = Math.Min(1, dt * 10);
                    this.lerpRainCloudOverlay = this.lerpRainCloudOverlay + (conds.RainCloudOverlay - this.lerpRainCloudOverlay) * tspeed;
                    this.lerpRainOverlay      = this.lerpRainOverlay + (conds.Rainfall - this.lerpRainOverlay) * tspeed;
                }
            }
        }
        public float GetRainCloudness(ClimateCondition conds, double posX, double posZ, double totalDays)
        {
            if (OverridePrecipitation != null)
            {
                return((float)OverridePrecipitation + 0.5f);
            }

            float offset = 0;

            if (conds != null)
            {
                offset = GameMath.Clamp((conds.Rainfall - 0.6f) * 2f, -1, 1f);
            }

            float value = getPrecipNoise(posX, posZ, totalDays + RainCloudDaysOffset, offset);

            return(value);
        }
Пример #24
0
        public virtual float GetPerishRate()
        {
            BlockPos sealevelpos = Pos.Copy();

            sealevelpos.Y = Api.World.SeaLevel;

            ClimateCondition cond = Api.World.BlockAccessor.GetClimateAt(sealevelpos);

            if (cond == null)
            {
                return(1);
            }

            float soilTempWeight = 0f;

            if (room.ExitCount == 0)
            {
                soilTempWeight = 0.5f + 0.5f * (1 - GameMath.Clamp((float)room.NonCoolingWallCount / Math.Max(1, room.CoolingWallCount), 0, 1));
            }

            int lightlevel = Api.World.BlockAccessor.GetLightLevel(Pos, EnumLightLevelType.OnlySunLight);

            // light level above 12 makes it additionally warmer, especially when part of a cellar
            float airTemp = cond.Temperature + GameMath.Clamp(lightlevel - 11, 0, 10) * (1f + 5 * soilTempWeight);


            // Lets say deep soil temperature is a constant 5°C
            float cellarTemp = 5;

            // How good of a cellar it is depends on how much rock or soil was used on he cellars walls
            float hereTemp = GameMath.Lerp(airTemp, cellarTemp, soilTempWeight);

            // For fairness lets say if its colder outside, use that temp instead
            hereTemp = Math.Min(hereTemp, airTemp);

            // Some neat curve to turn the temperature into a spoilage rate
            // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJtYXgoMC4xLG1pbigyLjUsM14oeC8xOS0xLjIpKS0wLjEpIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiLTIwIiwiNDAiLCIwIiwiMyJdLCJncmlkIjpbIjIuNSIsIjAuMjUiXX1d
            // max(0.1, min(2.5, 3^(x/15 - 1.2))-0.1)
            float rate = Math.Max(0.1f, Math.Min(2.4f, (float)Math.Pow(3, hereTemp / 19 - 1.2) - 0.1f));

            return(rate);
        }
Пример #25
0
        public override void Initialize(EntityProperties properties, ICoreAPI api, long InChunkIndex3d)
        {
            base.Initialize(properties, api, InChunkIndex3d);

            if (api.Side == EnumAppSide.Client)
            {
                WatchedAttributes.RegisterModifiedListener("windWaveIntensity", () =>
                {
                    (Properties.Client.Renderer as EntityShapeRenderer).WindWaveIntensity = WatchedAttributes.GetDouble("windWaveIntensity");
                });
            }


            ClimateCondition conds = api.World.BlockAccessor.GetClimateAt(Pos.AsBlockPos, EnumGetClimateMode.NowValues);

            if (conds != null && conds.Temperature < 0)
            {
                Die(EnumDespawnReason.Removed);
            }
        }
        private void OnClientGameTick(float dt)
        {
            quarterSecAccum += dt;
            if (quarterSecAccum > 0.25f)
            {
                clientClimateCond = capi.World.BlockAccessor.GetClimateAt(plrPos);
                quarterSecAccum   = 0;
            }

            simLightning.ClientTick(dt);

            for (int i = 0; i < 4; i++)
            {
                WeatherSimulationRegion sim = adjacentSims[i];
                if (sim == dummySim)
                {
                    continue;
                }
                sim.TickEvery25ms(dt);
            }

            simSounds.Update(dt);
        }
        private float GetDistance(ClimateCondition climate, BlockPatch variant)
        {
            float fertDist, rainDist, tempDist, forestDist;

            tempDist = Math.Abs(climate.Temperature * 2 - variant.MaxTemp - variant.MinTemp) / (variant.MaxTemp - variant.MinTemp);
            if (tempDist > 1f)
            {
                return(5f);
            }
            fertDist = Math.Abs(climate.Fertility * 2 - variant.MaxFertility - variant.MinFertility) / (variant.MaxFertility - variant.MinFertility);
            if (fertDist > 1f)
            {
                return(5f);
            }
            rainDist = Math.Abs(climate.Rainfall * 2 - variant.MaxRain - variant.MinRain) / (variant.MaxRain - variant.MinRain);
            if (rainDist > 1.3f)
            {
                return(5f);
            }
            forestDist = Math.Abs((climate.ForestDensity + 0.2f) * 2 - variant.MaxForest - variant.MinForest) / (variant.MaxForest - variant.MinForest);

            return(tempDist * tempDist + fertDist * fertDist + rainDist * rainDist + forestDist * forestDist);
        }
Пример #28
0
        void exportPlotHere(BlockPos pos)
        {
            ClimateCondition cond       = api.World.BlockAccessor.GetClimateAt(pos);
            double           totalhours = 0;// api.World.Calendar.TotalHours;
            double           starttemp  = cond.Temperature;

            double hoursPerday  = api.World.Calendar.HoursPerDay;
            double daysPerYear  = api.World.Calendar.DaysPerYear;
            double daysPerMonth = api.World.Calendar.DaysPerMonth;

            double monthsPerYear = daysPerYear / daysPerMonth;

            List <string> entries = new List <string>();

            for (double plothours = 0; plothours < 24 * 144; plothours += 1)
            {
                cond.Temperature = (float)starttemp;

                double totalDays = totalhours / hoursPerday;
                double year      = totalDays / daysPerYear;
                double yearRel   = year % 1;
                double hourOfDay = totalhours % hoursPerday;
                double month     = yearRel * monthsPerYear;

                updateTemperature(ref cond, pos, yearRel, hourOfDay, totalDays);

                entries.Add(
                    string.Format("{0}.{1}.{2} {3}:00", (int)(totalDays % daysPerMonth) + 1, (int)month + 1, (int)(totalDays / daysPerYear + 1386), (int)hourOfDay)
                    +
                    ";" + cond.Temperature
                    );

                totalhours += 1;
            }

            File.WriteAllText("temperatureplot.csv", string.Join("\r\n", entries));
        }
Пример #29
0
        private void SlowTick(float dt)
        {
            if (entity is EntityPlayer)
            {
                EntityPlayer plr = (EntityPlayer)entity;
                if (entity.World.PlayerByUid(plr.PlayerUID).WorldData.CurrentGameMode == EnumGameMode.Creative)
                {
                    return;
                }
            }

            bool harshWinters = entity.World.Config.GetString("harshWinters").ToBool(true);

            ClimateCondition conds = entity.World.BlockAccessor.GetClimateAt(entity.Pos.AsBlockPos, EnumGetClimateMode.NowValues);

            if (conds == null || conds.Temperature >= 2 || !harshWinters)
            {
                entity.Stats.Remove("hungerrate", "resistcold");
            }
            else
            {
                // 0..1
                float diff = GameMath.Clamp(2 - conds.Temperature, 0, 10);

                Room room = entity.World.Api.ModLoader.GetModSystem <RoomRegistry>().GetRoomForPosition(entity.Pos.AsBlockPos);

                entity.Stats.Set("hungerrate", "resistcold", room.ExitCount == 0 ? diff / 10f : 0, true);
            }


            if (Saturation <= 0)
            {
                // Let's say a fat reserve of 1000 is depleted in 3 ingame days using the default game speed of 1/60th
                // => 72 ingame hours / 60 = 1.2 irl hours = 4320 irl seconds
                // => 1 irl seconds substracts 1/4.32 fat reserves

                //float sprintLoss = sprintCounter / (15f * 6);
                //FatReserves = Math.Max(0, FatReserves - dt / 4.32f - sprintLoss / 4.32f);

                //if (FatReserves <= 0)
                {
                    entity.ReceiveDamage(new DamageSource()
                    {
                        Source = EnumDamageSource.Internal, Type = EnumDamageType.Hunger
                    }, 0.125f);
                }

                sprintCounter = 0;
            }

            /*if (Saturation >= 0.85 * MaxSaturation)
             * {
             *  // Fat recovery is 6 times slower
             *  FatReserves = Math.Min(MaxFatReserves, FatReserves + dt / (6 * 4.32f));
             * }
             *
             * float max = MaxFatReserves;
             * float cur = FatReserves / max;
             *
             * if (cur <= 0.8 || lastFatReserves <= 0.8)
             * {
             *  float diff = cur - lastFatReserves;
             *  if (Math.Abs(diff) >= 0.1)
             *  {
             *      HealthLocked += diff > 0 ? -1 : 1;
             *
             *      if (diff > 0 || Health > 0)
             *      {
             *          entity.ReceiveDamage(new DamageSource() { source = EnumDamageSource.Internal, type = (diff > 0) ? EnumDamageType.Heal : EnumDamageType.Hunger }, 1);
             *      }
             *
             *      lastFatReserves = cur;
             *  }
             * } else
             * {
             *  lastFatReserves = cur;
             * } */
        }
        public float GetPrecipitation(double posX, double posY, double posZ, double totalDays)
        {
            ClimateCondition conds = api.World.BlockAccessor.GetClimateAt(new BlockPos((int)posX, (int)posY, (int)posZ), EnumGetClimateMode.WorldGenValues, totalDays);

            return(Math.Max(0, GetRainCloudness(conds, posX, posZ, totalDays) - 0.5f));
        }