예제 #1
0
        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);
        }
예제 #2
0
        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;
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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;
        }
예제 #6
0
        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;
        }
예제 #7
0
        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
            });
        }
예제 #8
0
        /// <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);
        }
예제 #9
0
        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;
                            }
                        }
                    }
                }
            }
        }
예제 #10
0
 public float WidthLoss(Random rand)
 {
     return(randomWidthLoss != null?randomWidthLoss.nextFloat(1f, rand) : widthloss);
 }
예제 #11
0
        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);
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
0
 public override void OnPlanted(ICoreAPI api)
 {
     vineGrowthQuantity = vineGrowthQuantityGen.nextFloat(1, api.World.Rand);
 }
예제 #17
0
        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);
        }
예제 #18
0
        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--;
                    }
                }
            }
        }
예제 #19
0
        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);
        }