public static SimpleParticleProperties TemporalEffectAtPos(this BlockPos pos, ICoreAPI api) { SimpleParticleProperties p = TemporalEffect; Vec3d posvec = pos.DownCopy().MidPoint(); int r = 53; int g = 221; int b = 172; p.Color = (r << 16) | (g << 8) | (b << 0) | (50 << 24); p.AddPos.Set(0, 0, 0); p.BlueEvolve = null; p.RedEvolve = null; p.GreenEvolve = null; p.MinSize = 0.1f; p.MaxSize = 0.2f; p.SizeEvolve = null; p.OpacityEvolve = EvolvingNatFloat.create(EnumTransformFunction.LINEAR, 100f); double xpos = rndPos.nextFloat(); double ypos = 1.9 + api.World.Rand.NextDouble() * 0.2; double zpos = rndPos.nextFloat(); p.LifeLength = GameMath.Sqrt(xpos * xpos + zpos * zpos) / 10; p.MinPos.Set(posvec.X + xpos, posvec.Y + ypos, posvec.Z + zpos); p.MinVelocity.Set(-(float)xpos, -1 - (float)api.World.Rand.NextDouble() / 2, -(float)zpos); p.MinQuantity = 0.25f; p.AddQuantity = 0; return(p); }
protected override void beforeGenDeposit(IMapChunk mapChunk, BlockPos pos) { ypos = YPosRel.nextFloat(1, DepositRand); pos.Y = (int)ypos; step = (float)mapChunk.MapRegion.OreMapVerticalDistortTop.InnerSize / regionChunkSize; }
public override void GetYMinMax(BlockPos pos, out double miny, out double maxy) { float yposmin = 9999; float yposmax = -9999; for (int i = 0; i < 100; i++) { float ypos = YPosRel.nextFloat(1, DepositRand); yposmin = Math.Min(yposmin, ypos); yposmax = Math.Max(yposmax, ypos); } miny = yposmin; maxy = yposmax; }
public void Generate(IBlockAccessor blockAccessor, LCGRandom rnd, int posX, int posY, int posZ, int firstBlockId) { float quantity = Quantity.nextFloat() + 1; int chunkSize = blockAccessor.ChunkSize; Block[] blocks = getBlocks(firstBlockId); if (blocks.Length == 0) { return; } while (quantity-- > 0) { if (quantity < 1 && rnd.NextDouble() > quantity) { break; } pos.X = posX + (int)OffsetX.nextFloat(); pos.Z = posZ + (int)OffsetZ.nextFloat(); int index = GameMath.Mod((int)BlockCodeIndex.nextFloat(), blocks.Length); IServerChunk chunk = (IServerChunk)blockAccessor.GetChunk(pos.X / chunkSize, 0, pos.Z / chunkSize); if (chunk == null) { break; } int lx = GameMath.Mod(pos.X, chunkSize); int lz = GameMath.Mod(pos.Z, chunkSize); if (Placement == EnumBlockPatchPlacement.Underground) { pos.Y = rnd.NextInt(Math.Max(1, chunk.MapChunk.WorldGenTerrainHeightMap[lz * blockAccessor.ChunkSize + lx] - 1)); } else { pos.Y = chunk.MapChunk.RainHeightMap[lz * blockAccessor.ChunkSize + lx] + 1; if (Math.Abs(pos.Y - posY) > 8 || pos.Y >= blockAccessor.MapSizeY - 1) { continue; } if (Placement == EnumBlockPatchPlacement.UnderWater) { tempPos.Set(pos.X, pos.Y - GameMath.Max(1, MinWaterDepth), pos.Z); Block downBlock = blockAccessor.GetBlock(tempPos); if (downBlock == null || downBlock.LiquidCode != "water") { continue; } } } blocks[index].TryPlaceBlockForWorldGen(blockAccessor, pos, BlockFacing.UP, rnd); } }
protected override void beforeGenDeposit(IMapChunk mapChunk, BlockPos targetPos) { depthf = YPosRel.nextFloat(1, DepositRand); depthi = (int)depthf; targetPos.Y = depthi; step = (float)mapChunk.MapRegion.OreMapVerticalDistortTop.InnerSize / regionChunkSize; }
public override void OnBlockPlaced(ItemStack byItemStack = null) { Block block = Api.World.BlockAccessor.GetBlock(Pos); NatFloat growthDays = NatFloat.create(EnumDistribution.UNIFORM, 6.5f, 1.5f); if (block?.Attributes != null) { growthDays = block.Attributes["growthDays"].AsObject(growthDays); } totalHoursTillGrowth = Api.World.Calendar.TotalHours + growthDays.nextFloat(1, Api.World.Rand) * 24; }
public ResolvedTradeItem Resolve(IWorldAccessor world) { this.Resolve(world, "TradeItem"); return(new ResolvedTradeItem() { Stack = this.ResolvedItemstack, //Name = Name, Price = (int)Math.Max(1, Math.Round(Price.nextFloat(1f, world.Rand))), Stock = Stock == null ? 0 : (int)Math.Round(Stock.nextFloat(1f, world.Rand)), Restock = Restock, SupplyDemand = SupplyDemand }); }
/// <summary> /// Returns an itemstack with random quantity as configured via the Quantity field /// </summary> /// <returns></returns> public ItemStack GetNextItemStack(float dropQuantityMultiplier = 1f) { if (ResolvedItemstack == null) { return(null); } float val = Quantity.nextFloat() * dropQuantityMultiplier; int quantity = (int)val + (((val - (int)val) > random.NextDouble()) ? 1 : 0); if (quantity <= 0) { return(null); } ItemStack cloned = ResolvedItemstack.Clone(); cloned.StackSize = quantity; return(cloned); }
public override void GenDeposit(IBlockAccessor blockAccessor, IServerChunk[] chunks, int originChunkX, int originChunkZ, BlockPos pos, ref Dictionary <BlockPos, DepositVariant> subDepositsToPlace) { IMapChunk heremapchunk = chunks[0].MapChunk; int depositGradeIndex = PlaceBlock.AllowedVariants != null?DepositRand.NextInt(PlaceBlock.AllowedVariants.Length) : 0; int radius = Math.Min(64, (int)Radius.nextFloat(1, DepositRand)); if (radius <= 0) { return; } radius++; bool shouldGenSurfaceDeposit = DepositRand.NextFloat() > 0.35f && SurfaceBlock != null; float tries = RandomTries.nextFloat(1, DepositRand); for (int i = 0; i < tries; i++) { targetPos.Set( pos.X + DepositRand.NextInt(2 * radius + 1) - radius, pos.Y + DepositRand.NextInt(2 * radius + 1) - radius, pos.Z + DepositRand.NextInt(2 * radius + 1) - radius ); int lx = targetPos.X % chunksize; int lz = targetPos.Z % chunksize; if (targetPos.Y <= 1 || targetPos.Y >= worldheight || lx < 0 || lz < 0 || lx >= chunksize || lz >= chunksize) { continue; } int index3d = ((targetPos.Y % chunksize) * chunksize + lz) * chunksize + lx; int blockId = chunks[targetPos.Y / chunksize].Blocks[index3d]; ResolvedDepositBlock resolvedPlaceBlock; if (placeBlockByInBlockId.TryGetValue(blockId, out resolvedPlaceBlock)) { Block placeblock = resolvedPlaceBlock.Blocks[depositGradeIndex]; if (variant.WithBlockCallback) { placeblock.TryPlaceBlockForWorldGen(blockAccessor, targetPos, BlockFacing.UP, DepositRand); } else { chunks[targetPos.Y / chunksize].Blocks[index3d] = placeblock.BlockId; } if (shouldGenSurfaceDeposit) { int surfaceY = heremapchunk.RainHeightMap[lz * chunksize + lx]; int depth = surfaceY - targetPos.Y; float chance = SurfaceBlockChance * Math.Max(0, 1 - depth / 8f); if (surfaceY < worldheight && DepositRand.NextFloat() < chance) { index3d = (((surfaceY + 1) % chunksize) * chunksize + lz) * chunksize + lx; Block belowBlock = Api.World.Blocks[chunks[surfaceY / chunksize].Blocks[((surfaceY % chunksize) * chunksize + lz) * chunksize + lx]]; if (belowBlock.SideSolid[BlockFacing.UP.Index] && chunks[(surfaceY + 1) / chunksize].Blocks[index3d] == 0) { chunks[(surfaceY + 1) / chunksize].Blocks[index3d] = surfaceBlockByInBlockId[blockId].Blocks[0].BlockId; } } } } } }
public float WidthLoss(Random rand) { return(randomWidthLoss != null?randomWidthLoss.nextFloat(1f, rand) : widthloss); }
public override void GenDeposit(IBlockAccessor blockAccessor, IServerChunk[] chunks, int chunkX, int chunkZ, BlockPos depoCenterPos, ref Dictionary <BlockPos, DepositVariant> subDepositsToPlace) { int depositGradeIndex = PlaceBlock.MaxGrade == 0 ? 0 : DepositRand.NextInt(PlaceBlock.MaxGrade); int radius = Math.Min(64, (int)Radius.nextFloat(1, DepositRand)); if (radius <= 0) { return; } // Let's deform that perfect circle a bit (+/- 25%) float deform = GameMath.Clamp(DepositRand.NextFloat() - 0.5f, -0.25f, 0.25f); radiusX = radius - (int)(radius * deform); radiusZ = radius + (int)(radius * deform); int baseX = chunkX * chunksize; int baseZ = chunkZ * chunksize; // No need to caluclate further if this deposit won't be part of this chunk if (depoCenterPos.X + radiusX < baseX - 6 || depoCenterPos.Z + radiusZ < baseZ - 6 || depoCenterPos.X - radiusX >= baseX + chunksize + 6 || depoCenterPos.Z - radiusZ >= baseZ + chunksize + 6) { return; } IMapChunk heremapchunk = chunks[0].MapChunk; beforeGenDeposit(heremapchunk, depoCenterPos); // Ok generate float th = Thickness.nextFloat(1, DepositRand); depoitThickness = (int)th + (DepositRand.NextFloat() < th - (int)th ? 1 : 0); float xRadSqInv = 1f / (radiusX * radiusX); float zRadSqInv = 1f / (radiusZ * radiusZ); bool parentBlockOk = false; ResolvedDepositBlock resolvedPlaceBlock = null; bool shouldGenSurfaceDeposit = DepositRand.NextFloat() <= GenSurfaceBlockChance && SurfaceBlock != null; int lx = GameMath.Mod(depoCenterPos.X, chunksize); int lz = GameMath.Mod(depoCenterPos.Z, chunksize); int distx, distz; // No need to go search far beyond chunk boundaries int minx = baseX - 6; int maxx = baseX + chunksize + 6; int minz = baseZ - 6; int maxz = baseZ + chunksize + 6; minx = GameMath.Clamp(depoCenterPos.X - radiusX, minx, maxx); maxx = GameMath.Clamp(depoCenterPos.X + radiusX, minx, maxx); minz = GameMath.Clamp(depoCenterPos.Z - radiusZ, minz, maxz); maxz = GameMath.Clamp(depoCenterPos.Z + radiusZ, minz, maxz); //int placed = 0; float invChunkAreaSize = 1f / (chunksize * chunksize); double val = 1; for (int posx = minx; posx < maxx; posx++) { targetPos.X = posx; lx = targetPos.X - baseX; distx = posx - depoCenterPos.X; float xSq = distx * distx * xRadSqInv; for (int posz = minz; posz < maxz; posz++) { targetPos.Y = depoCenterPos.Y; targetPos.Z = posz; lz = targetPos.Z - baseZ; distz = posz - depoCenterPos.Z; // Kinda weird mathematically speaking, but seems to work as a means to distort the perfect circleness of deposits ¯\_(ツ)_/¯ // Also not very efficient to use direct perlin noise in here :/ // But after ~10 hours of failing (=weird lines of missing deposit material) with a pre-generated 2d distortion map i give up >.> val = 1 - (radius > 3 ? DistortNoiseGen.Noise(targetPos.X / 3.0, targetPos.Z / 3.0) * 0.2 : 0); double distanceToEdge = val - (xSq + distz * distz * zRadSqInv); if (distanceToEdge < 0 || lx < 0 || lz < 0 || lx >= chunksize || lz >= chunksize) { continue; } loadYPosAndThickness(heremapchunk, lx, lz, targetPos, distanceToEdge); // Some deposits may not appear all over cliffs if (Math.Abs(depoCenterPos.Y - targetPos.Y) > MaxYRoughness) { continue; } for (int y = 0; y < hereThickness; y++) { if (targetPos.Y <= 1 || targetPos.Y >= worldheight) { continue; } int index3d = ((targetPos.Y % chunksize) * chunksize + lz) * chunksize + lx; int blockId = chunks[targetPos.Y / chunksize].Blocks[index3d]; if (!IgnoreParentTestPerBlock || !parentBlockOk) { parentBlockOk = placeBlockByInBlockId.TryGetValue(blockId, out resolvedPlaceBlock); } if (parentBlockOk && resolvedPlaceBlock.Blocks.Length > 0) { int gradeIndex = Math.Min(resolvedPlaceBlock.Blocks.Length - 1, depositGradeIndex); Block placeblock = resolvedPlaceBlock.Blocks[gradeIndex]; if (variant.WithBlockCallback || (WithLastLayerBlockCallback && y == hereThickness - 1)) { placeblock.TryPlaceBlockForWorldGen(blockAccessor, targetPos.Copy(), BlockFacing.UP, rand); } else { chunks[targetPos.Y / chunksize].Blocks[index3d] = placeblock.BlockId; //placed++; } if (variant.ChildDeposits != null) { for (int i = 0; i < variant.ChildDeposits.Length; i++) { float rndVal = DepositRand.NextFloat(); float quantity = variant.ChildDeposits[i].TriesPerChunk * invChunkAreaSize; if (quantity > rndVal) { if (ShouldPlaceAdjustedForOreMap(variant.ChildDeposits[i], targetPos.X, targetPos.Z, quantity, rndVal)) { subDepositsToPlace[targetPos.Copy()] = variant.ChildDeposits[i]; } } } } if (shouldGenSurfaceDeposit) { int surfaceY = heremapchunk.RainHeightMap[lz * chunksize + lx]; int depth = surfaceY - targetPos.Y; float chance = SurfaceBlockChance * Math.Max(0, 1.11f - depth / 9f); if (surfaceY < worldheight && DepositRand.NextFloat() < chance) { Block belowBlock = Api.World.Blocks[chunks[surfaceY / chunksize].Blocks[((surfaceY % chunksize) * chunksize + lz) * chunksize + lx]]; index3d = (((surfaceY + 1) % chunksize) * chunksize + lz) * chunksize + lx; if (belowBlock.SideSolid[BlockFacing.UP.Index] && chunks[(surfaceY + 1) / chunksize].Blocks[index3d] == 0) { chunks[(surfaceY + 1) / chunksize].Blocks[index3d] = surfaceBlockByInBlockId[blockId].Blocks[0].BlockId; } } } } targetPos.Y--; } } } //Console.WriteLine("placed {0} blocks", placed); }
private Vec3d nearbyWaterOrRandomTarget() { int tries = 9; Vec4d bestTarget = null; Vec4d curTarget = new Vec4d(); BlockPos tmpPos = new BlockPos(); if (FailedConsecutivePathfinds > 10) { WanderRangeMul = Math.Max(0.1f, WanderRangeMul * 0.9f); } else { WanderRangeMul = Math.Min(1, WanderRangeMul * 1.1f); if (rand.NextDouble() < 0.05) { WanderRangeMul = Math.Min(1, WanderRangeMul * 1.5f); } } float wRangeMul = WanderRangeMul; double dx, dy, dz; if (rand.NextDouble() < 0.05) { wRangeMul *= 3; } while (tries-- > 0) { dx = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; dy = wanderRangeVertical.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; dz = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; curTarget.X = entity.ServerPos.X + dx; curTarget.Y = entity.ServerPos.Y + dy; curTarget.Z = entity.ServerPos.Z + dz; curTarget.W = 1; Block block; block = entity.World.BlockAccessor.GetBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (!block.IsLiquid()) { curTarget.W = 0; } else { curTarget.W = 1 / Math.Sqrt((dx - 1.0) * (dx - 1.0) + (dz - 1.0) * (dz - 1.0) + 1); //prefer target approx 1 block away } //TODO: reject (or de-weight) targets not in direct line of sight (avoiding terrain) if (bestTarget == null || curTarget.W > bestTarget.W) { bestTarget = new Vec4d(curTarget.X, curTarget.Y, curTarget.Z, curTarget.W); if (curTarget.W >= 1.0) { break; //have a good enough target, no need for further tries } } } if (bestTarget.W > 0) { FailedConsecutivePathfinds = Math.Max(FailedConsecutivePathfinds - 3, 0); return(bestTarget.XYZ); } FailedConsecutivePathfinds++; return(null); }
// Requirements: // - ✔ Try to not move a lot vertically // - ✔ If territorial: Stay close to the spawn point // - ✔ If air habitat: Don't go above maxHeight blocks above surface // - ✔ If land habitat: Don't walk into water, prefer surface // - ~~If cave habitat: Prefer caves~~ // - ✔ If water habitat: Don't walk onto land // - ✔ Try not to fall from very large heights. Try not to fall from any large heights if entity has FallDamage // - ✔ Prefer preferredLightLevel // - ✔ If land habitat: Must be above a block the entity can stand on // - ✔ if failed searches is high, reduce wander range public Vec3d loadNextWanderTarget() { EnumHabitat habitat = entity.Properties.Habitat; bool canFallDamage = entity.Properties.FallDamage; bool territorial = StayCloseToSpawn; int tries = 9; Vec4d bestTarget = null; Vec4d curTarget = new Vec4d(); BlockPos tmpPos = new BlockPos(); if (FailedConsecutivePathfinds > 10) { WanderRangeMul = Math.Max(0.1f, WanderRangeMul * 0.9f); } else { WanderRangeMul = Math.Min(1, WanderRangeMul * 1.1f); if (rand.NextDouble() < 0.05) { WanderRangeMul = Math.Min(1, WanderRangeMul * 1.5f); } } float wRangeMul = WanderRangeMul; double dx, dy, dz; if (rand.NextDouble() < 0.05) { wRangeMul *= 3; } while (tries-- > 0) { dx = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; dy = wanderRangeVertical.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; dz = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; curTarget.X = entity.ServerPos.X + dx; curTarget.Y = entity.ServerPos.Y + dy; curTarget.Z = entity.ServerPos.Z + dz; curTarget.W = 1; if (StayCloseToSpawn) { double distToEdge = curTarget.SquareDistanceTo(SpawnPosition) / (MaxDistanceToSpawn * MaxDistanceToSpawn); // Prefer staying close to spawn curTarget.W = 1 - distToEdge; } Block block; switch (habitat) { case EnumHabitat.Air: int rainMapY = world.BlockAccessor.GetRainMapHeightAt((int)curTarget.X, (int)curTarget.Z); // Don't fly above max height curTarget.Y = Math.Min(curTarget.Y, rainMapY + maxHeight); // Cannot be in water block = entity.World.BlockAccessor.GetBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (block.IsLiquid()) { curTarget.W = 0; } break; case EnumHabitat.Land: curTarget.Y = moveDownToFloor((int)curTarget.X, curTarget.Y, (int)curTarget.Z); // No floor found if (curTarget.Y < 0) { curTarget.W = 0; } else { // Does not like water block = entity.World.BlockAccessor.GetBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (block.IsLiquid()) { curTarget.W /= 2; } // Lets make a straight line plot to see if we would fall off a cliff bool stop = false; bool willFall = false; float angleHor = (float)Math.Atan2(dx, dz) + GameMath.PIHALF; Vec3d target1BlockAhead = curTarget.XYZ.Ahead(1, 0, angleHor); Vec3d startAhead = entity.ServerPos.XYZ.Ahead(1, 0, angleHor); // Otherwise they are forever stuck if they stand over the edge int prevY = (int)startAhead.Y; GameMath.BresenHamPlotLine2d((int)startAhead.X, (int)startAhead.Z, (int)target1BlockAhead.X, (int)target1BlockAhead.Z, (x, z) => { if (stop) { return; } double nowY = moveDownToFloor(x, prevY, z); // Not more than 4 blocks down if (nowY < 0 || prevY - nowY > 4) { willFall = true; stop = true; } // Not more than 2 blocks up if (nowY - prevY > 2) { stop = true; } prevY = (int)nowY; }); if (willFall) { curTarget.W = 0; } } break; case EnumHabitat.Sea: block = entity.World.BlockAccessor.GetBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (!block.IsLiquid()) { curTarget.W = 0; } break; } if (curTarget.W > 0) { // Try to not hug the wall so much for (int i = 0; i < BlockFacing.HORIZONTALS.Length; i++) { BlockFacing face = BlockFacing.HORIZONTALS[i]; block = entity.World.BlockAccessor.GetBlock((int)curTarget.X + face.Normali.X, (int)curTarget.Y, (int)curTarget.Z + face.Normali.Z); if (block.SideSolid[face.Opposite.Index]) { curTarget.W *= 0.5; } } } if (preferredLightLevel != null) { tmpPos.Set((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); int lightdiff = Math.Abs((int)preferredLightLevel - entity.World.BlockAccessor.GetLightLevel(tmpPos, EnumLightLevelType.MaxLight)); curTarget.W /= Math.Max(1, lightdiff); } if (bestTarget == null || curTarget.W > bestTarget.W) { bestTarget = new Vec4d(curTarget.X, curTarget.Y, curTarget.Z, curTarget.W); } } if (bestTarget.W > 0) { //double bla = bestTarget.Y; //bestTarget.Y += 1; //dx = bestTarget.X - entity.ServerPos.X; //dz = bestTarget.Z - entity.ServerPos.Z; //Vec3d sadf = bestTarget.XYZ.Ahead(1, 0, (float)Math.Atan2(dx, dz) + GameMath.PIHALF); /*(entity.Api as ICoreServerAPI).World.HighlightBlocks(world.AllOnlinePlayers[0], 10, new List<BlockPos>() { * new BlockPos((int)bestTarget.X, (int)bestTarget.Y, (int)bestTarget.Z) }, new List<int>() { ColorUtil.ColorFromRgba(0, 255, 0, 80) }, EnumHighlightBlocksMode.Absolute, EnumHighlightShape.Arbitrary); * (entity.Api as ICoreServerAPI).World.HighlightBlocks(world.AllOnlinePlayers[0], 11, new List<BlockPos>() { * new BlockPos((int)sadf.X, (int)sadf.Y, (int)sadf.Z) }, new List<int>() { ColorUtil.ColorFromRgba(0, 255, 255, 180) }, EnumHighlightBlocksMode.Absolute, EnumHighlightShape.Arbitrary);*/ //bestTarget.Y = bla; FailedConsecutivePathfinds = Math.Max(FailedConsecutivePathfinds - 3, 0); return(bestTarget.XYZ); } FailedConsecutivePathfinds++; return(null); }
public override bool ShouldExecute() { if (rand.NextDouble() > wanderChance) { return(false); } List <Vec3d> goodtargets = new List <Vec3d>(); int tries = 9; while (tries-- > 0) { int terrainYPos = entity.World.BlockAccessor.GetTerrainMapheightAt(tmpPos); float dx = wanderRange.nextFloat() * (rand.Next(2) * 2 - 1); float dy = wanderRange.nextFloat() * (rand.Next(2) * 2 - 1); float dz = wanderRange.nextFloat() * (rand.Next(2) * 2 - 1); MainTarget = entity.ServerPos.XYZ.Add(dx, dy, dz); MainTarget.Y = Math.Min(MainTarget.Y, terrainYPos + maxHeight); tmpPos.X = (int)MainTarget.X; tmpPos.Z = (int)MainTarget.Z; if ((entity.Controls.IsClimbing && !entity.Properties.FallDamage) || (entity.Properties.Habitat != EnumHabitat.Land)) { if (entity.Properties.Habitat == EnumHabitat.Sea) { Block block = entity.World.BlockAccessor.GetBlock(tmpPos); return(block.IsLiquid()); } return(true); } else { int yDiff = (int)entity.ServerPos.Y - terrainYPos; double slopeness = yDiff / Math.Max(1, GameMath.Sqrt(MainTarget.HorizontalSquareDistanceTo(entity.ServerPos.XYZ)) - 2); tmpPos.Y = terrainYPos; Block block = entity.World.BlockAccessor.GetBlock(tmpPos); Block belowblock = entity.World.BlockAccessor.GetBlock(tmpPos.X, tmpPos.Y - 1, tmpPos.Z); bool canStep = block.CollisionBoxes == null || block.CollisionBoxes.Max((cuboid) => cuboid.Y2) <= 1f; bool canStand = belowblock.CollisionBoxes != null && belowblock.CollisionBoxes.Length > 0; if (slopeness < 3 && canStand && canStep) { if (preferredLightLevel == null) { return(true); } goodtargets.Add(MainTarget); } } } int smallestdiff = 999; Vec3d bestTarget = null; for (int i = 0; i < goodtargets.Count; i++) { int lightdiff = Math.Abs((int)preferredLightLevel - entity.World.BlockAccessor.GetLightLevel(goodtargets[i].AsBlockPos, EnumLightLevelType.MaxLight)); if (lightdiff < smallestdiff) { smallestdiff = lightdiff; bestTarget = goodtargets[i]; } } if (bestTarget != null) { MainTarget = bestTarget; return(true); } return(false); }
public bool TryGenerate(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos, int climateUpLeft, int climateUpRight, int climateBotLeft, int climateBotRight, DidGenerate didGenerateStructure) { this.climateUpLeft = climateUpLeft; this.climateUpRight = climateUpRight; this.climateBotLeft = climateBotLeft; this.climateBotRight = climateBotRight; float cnt = QuantityStructures.nextFloat(); int minQuantity = (int)cnt; BlockPos schemPos = pos.Copy(); Cuboidi location = new Cuboidi(); rand.InitPositionSeed(pos.X, pos.Z); List <GeneratableStructure> generatables = new List <GeneratableStructure>(); while (cnt-- > 0) { if (cnt < 1 && rand.NextDouble() > cnt) { break; } int tries = 30; while (tries-- > 0) { schemPos.Set(pos); schemPos.Add(rand.NextInt(50) - 25, 0, rand.NextInt(50) - 25); schemPos.Y = blockAccessor.GetTerrainMapheightAt(schemPos); double rndVal = rand.NextDouble() * totalWeight; int i = 0; VillageSchematic schem = null; while (rndVal > 0) { schem = Schematics[i++]; rndVal -= schem.Weight; } BlockSchematicStructure struc = GetGeneratableStructure(schem, blockAccessor, worldForCollectibleResolve, schemPos); if (struc != null) { location.Set(schemPos.X, schemPos.Y, schemPos.Z, schemPos.X + struc.SizeX, schemPos.Y + struc.SizeY, schemPos.Z + struc.SizeZ); bool intersect = false; for (int k = 0; k < generatables.Count; k++) { if (location.IntersectsOrTouches(generatables[k].location)) { intersect = true; break; } } if (!intersect) { generatables.Add(new GeneratableStructure() { struc = struc, pos = schemPos.Copy(), location = location.Clone() }); } break; } } } if (generatables.Count >= minQuantity) { foreach (var val in generatables) { val.struc.PlaceRespectingBlockLayers(blockAccessor, worldForCollectibleResolve, val.pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight, replaceblockids); didGenerateStructure(val.location, val.struc); } } return(true); }
public override void OnPlanted(ICoreAPI api) { vineGrowthQuantity = vineGrowthQuantityGen.nextFloat(1, api.World.Rand); }
public Vec3d loadNextWanderTarget() { int tries = 9; Vec4d bestTarget = null; Vec4d curTarget = new Vec4d(); BlockPos tmpPos = new BlockPos(); if (FailedConsecutivePathfinds > 10) { WanderRangeMul = Math.Max(0.1f, WanderRangeMul * 0.9f); } else { WanderRangeMul = Math.Min(1, WanderRangeMul * 1.1f); if (rand.NextDouble() < 0.05) { WanderRangeMul = Math.Min(1, WanderRangeMul * 1.5f); } } float wRangeMul = WanderRangeMul; double dx, dy, dz; if (rand.NextDouble() < 0.05) { wRangeMul *= 3; } while (tries-- > 0) { dx = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; dy = wanderRangeVertical.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; dz = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul; curTarget.X = entity.ServerPos.X + dx; curTarget.Y = entity.ServerPos.Y + dy; curTarget.Z = entity.ServerPos.Z + dz; curTarget.W = 1; Block block; block = entity.World.BlockAccessor.GetBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); if (!block.IsLiquid()) { curTarget.W = 0; } else { curTarget.W = 1 / (Math.Abs(dy) + 1); //prefer not too much vertical change when underwater } //TODO: reject (or de-weight) targets not in direct line of sight (avoiding terrain) if (preferredLightLevel != null && curTarget.W != 0) { tmpPos.Set((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z); int lightdiff = Math.Abs((int)preferredLightLevel - entity.World.BlockAccessor.GetLightLevel(tmpPos, EnumLightLevelType.MaxLight)); curTarget.W /= Math.Max(1, lightdiff); } if (bestTarget == null || curTarget.W > bestTarget.W) { bestTarget = new Vec4d(curTarget.X, curTarget.Y, curTarget.Z, curTarget.W); if (curTarget.W >= 1.0) { break; //have a good enough target, no need for further tries } } } if (bestTarget.W > 0) { FailedConsecutivePathfinds = Math.Max(FailedConsecutivePathfinds - 3, 0); return(bestTarget.XYZ); } FailedConsecutivePathfinds++; return(null); }
public override void GenDeposit(IBlockAccessor blockAccessor, IServerChunk[] chunks, int chunkX, int chunkZ, BlockPos depoCenterPos, ref Dictionary <BlockPos, DepositVariant> subDepositsToPlace) { int radius = Math.Min(64, (int)Radius.nextFloat(1, DepositRand)); if (radius <= 0) { return; } // Let's deform that perfect circle a bit (+/- 25%) float deform = GameMath.Clamp(DepositRand.NextFloat() - 0.5f, -0.25f, 0.25f); radiusX = radius - (int)(radius * deform); radiusZ = radius + (int)(radius * deform); int baseX = chunkX * chunksize; int baseZ = chunkZ * chunksize; // No need to caluclate further if this deposit won't be part of this chunk if (depoCenterPos.X + radiusX < baseX - 6 || depoCenterPos.Z + radiusZ < baseZ - 6 || depoCenterPos.X - radiusX >= baseX + chunksize + 6 || depoCenterPos.Z - radiusZ >= baseZ + chunksize + 6) { return; } IMapChunk heremapchunk = chunks[0].MapChunk; // Ok generate float th = Thickness.nextFloat(1, DepositRand); float depoitThickness = (int)th + (DepositRand.NextFloat() < th - (int)th ? 1 : 0); float xRadSqInv = 1f / (radiusX * radiusX); float zRadSqInv = 1f / (radiusZ * radiusZ); int lx = GameMath.Mod(depoCenterPos.X, chunksize); int lz = GameMath.Mod(depoCenterPos.Z, chunksize); int distx, distz; // No need to go search far beyond chunk boundaries int minx = baseX - 6; int maxx = baseX + chunksize + 6; int minz = baseZ - 6; int maxz = baseZ + chunksize + 6; minx = GameMath.Clamp(depoCenterPos.X - radiusX, minx, maxx); maxx = GameMath.Clamp(depoCenterPos.X + radiusX, minx, maxx); minz = GameMath.Clamp(depoCenterPos.Z - radiusZ, minz, maxz); maxz = GameMath.Clamp(depoCenterPos.Z + radiusZ, minz, maxz); float invChunkAreaSize = 1f / (chunksize * chunksize); double val = 1; IList <Block> blocktypes = Api.World.Blocks; bool doGravel = DepositRand.NextFloat() > 0.33; for (int posx = minx; posx < maxx; posx++) { targetPos.X = posx; lx = targetPos.X - baseX; distx = posx - depoCenterPos.X; float xSq = distx * distx * xRadSqInv; for (int posz = minz; posz < maxz; posz++) { targetPos.Z = posz; lz = targetPos.Z - baseZ; distz = posz - depoCenterPos.Z; // Kinda weird mathematically speaking, but seems to work as a means to distort the perfect circleness of deposits ¯\_(ツ)_/¯ // Also not very efficient to use direct perlin noise in here :/ // But after ~10 hours of failing (=weird lines of missing deposit material) with a pre-generated 2d distortion map i give up >.> val = 1 - DistortNoiseGen.Noise(targetPos.X / 3.0, targetPos.Z / 3.0) * 1.5 + 0.15; double distanceToEdge = val - (xSq + distz * distz * zRadSqInv); if (distanceToEdge < 0 || lx < 0 || lz < 0 || lx >= chunksize || lz >= chunksize) { continue; } targetPos.Y = heremapchunk.WorldGenTerrainHeightMap[lz * chunksize + lx]; // Some deposits may not appear all over cliffs if (Math.Abs(depoCenterPos.Y - targetPos.Y) > MaxYRoughness) { continue; } int rockblockid = heremapchunk.TopRockIdMap[lz * chunksize + lx]; Block rockblock = blocktypes[rockblockid]; if (!rockblock.Variant.ContainsKey("rock")) { continue; } Block alluvialblock; if (doGravel) { alluvialblock = Api.World.GetBlock(new AssetLocation("gravel-" + rockblock.Variant["rock"])); } else { alluvialblock = Api.World.GetBlock(new AssetLocation("sand-" + rockblock.Variant["rock"])); } for (int y = 0; y < depoitThickness; y++) { if (targetPos.Y <= 1 || targetPos.Y >= worldheight) { continue; } int index3d = ((targetPos.Y % chunksize) * chunksize + lz) * chunksize + lx; int blockId = chunks[targetPos.Y / chunksize].Blocks[index3d]; Block block = blocktypes[blockId]; if (block.BlockMaterial != EnumBlockMaterial.Soil) { continue; } if (alluvialblock != null) { chunks[targetPos.Y / chunksize].Blocks[index3d] = alluvialblock.BlockId; } targetPos.Y--; } } } }
private void OnClientGameTick(float dt) { if (block == null || api?.World == null || !canTeleport || !Activated) { return; } bool playerInside = (api.World.ElapsedMilliseconds > 100 && api.World.ElapsedMilliseconds - lastCollideMsOwnPlayer < 100); SimpleParticleProperties currentParticles = playerInside ? block.insideParticles : block.idleParticles ; if (playerInside) { animUtil.StartAnimation(new AnimationMetaData() { Animation = "idle", Code = "idle", AnimationSpeed = 1, EaseInSpeed = 100, EaseOutSpeed = 100, BlendMode = EnumAnimationBlendMode.Average }); animUtil.StartAnimation(new AnimationMetaData() { Animation = "teleport", Code = "teleport", AnimationSpeed = 1, EaseInSpeed = 8, EaseOutSpeed = 8, BlendMode = EnumAnimationBlendMode.Add }); } else { animUtil.StopAnimation("teleport"); } if (api.World.ElapsedMilliseconds - lastCollideMsOwnPlayer > 3000) { animUtil.StopAnimation("idle"); } //int color = temporalGearStack.Collectible.GetRandomColor(api as ICoreClientAPI, temporalGearStack); - not working o.O int r = 53; int g = 221; int b = 172; currentParticles.color = (r << 16) | (g << 8) | (b << 0) | (50 << 24); currentParticles.addPos.Set(0, 0, 0); currentParticles.BlueEvolve = null; currentParticles.RedEvolve = null; currentParticles.GreenEvolve = null; currentParticles.minSize = 0.1f; currentParticles.maxSize = 0.2f; currentParticles.SizeEvolve = null; currentParticles.OpacityEvolve = EvolvingNatFloat.create(EnumTransformFunction.LINEAR, 100f); double xpos = rndPos.nextFloat(); double ypos = 1.9 + api.World.Rand.NextDouble() * 0.2; double zpos = rndPos.nextFloat(); currentParticles.lifeLength = GameMath.Sqrt(xpos * xpos + zpos * zpos) / 10; currentParticles.minPos.Set(posvec.X + xpos, posvec.Y + ypos, posvec.Z + zpos); currentParticles.minVelocity.Set(-(float)xpos, -1 - (float)api.World.Rand.NextDouble() / 2, -(float)zpos); currentParticles.minQuantity = playerInside ? 2 : 0.25f; currentParticles.addQuantity = 0; api.World.SpawnParticles(currentParticles); }