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); }
/// <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); }
/// <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)); }
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); }
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()); }
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); } }
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); }
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; } } }
/// <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); }
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); }
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); }
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++; }
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)); }
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); }
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); }
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); }
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; }
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); }
/// <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); }
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); }
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); }
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)); }
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)); }