Пример #1
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            base.Update(gameTime, chunks, camera);

            Storm.InitializeStatics();
            BoundingBox box = chunks.Bounds;

            box.Expand(10.0f);

            if (GlobalTransform.Translation.X < box.Min.X ||
                GlobalTransform.Translation.X > box.Max.X ||
                GlobalTransform.Translation.Z < box.Min.Z ||
                GlobalTransform.Translation.Z > box.Max.Z)
            {
                Die();
            }


            bool generateRainDrop = MathFunctions.RandEvent(Raininess * 0.75f);

            if (generateRainDrop)
            {
                for (int i = 0; i < MaxRainDrops; i++)
                {
                    if (!RainDrops[i].IsAlive)
                    {
                        RainDrops[i].IsAlive = true;
                        if (RainDrops[i].Particle != null)
                        {
                            RainDrops[i].Particle.LifeRemaining = 60.0f;
                            RainDrops[i].Particle.TimeAlive     = 0.0f;
                        }
                        RainDrops[i].Pos = MathFunctions.RandVector3Box(BoundingBox.Expand(5));
                        RainDrops[i].Pos = new Vector3(RainDrops[i].Pos.X, BoundingBox.Min.Y - 1, RainDrops[i].Pos.Z);
                        RainDrops[i].Vel = Vector3.Down * Storm.Properties[TypeofStorm].RainSpeed + Velocity;
                        break;
                    }
                }
            }

            bool generateLightning = LightningChance > 0.0f && MathFunctions.RandEvent((float)(LightningChance * 0.001f));

            if (generateLightning)
            {
                var below = VoxelHelpers.FindFirstVoxelBelowIncludingWater(new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(new Vector3(Position.X, Math.Min(World.WorldSizeInVoxels.Y - 1, Position.Y), Position.Z))));
                if (below.IsValid && !below.IsEmpty)
                {
                    var above = VoxelHelpers.GetVoxelAbove(below);
                    if (above.IsValid)
                    {
                        EntityFactory.CreateEntity <Fire>("Fire", above.GetBoundingBox().Center());
                        List <Vector3> lightningStrikes = new List <Vector3>();
                        List <Color>   colors           = new List <Color>();
                        var            c = above.GetBoundingBox().Center();
                        for (float t = 0; t < 1.0f; t += 0.25f)
                        {
                            var p = c * t + Position * (1.0f - t);
                            lightningStrikes.Add(p + MathFunctions.RandVector3Box(-5, 5, 0, 0.1f, -5, 5));
                            colors.Add(Color.White);
                        }
                        lightningStrikes.Add(c);
                        colors.Add(Color.White);
                        Drawer3D.DrawLineList(lightningStrikes, colors, 0.3f);
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_gui_rain_storm_alert, MathFunctions.Rand(0.001f, 0.05f), MathFunctions.Rand(0.5f, 1.0f));
                        SoundManager.PlaySound(ContentPaths.Audio.Oscar.sfx_trap_destroyed, c, false, 1.0f, MathFunctions.Rand(-0.5f, 0.5f));
                        World.ParticleManager.Trigger("explode", c, Color.White, 10);
                    }
                }
            }

            Storm.StormProperties stormProperties = Storm.Properties[TypeofStorm];
            var rainEmitter = World.ParticleManager.Effects[stormProperties.RainEffect];
            var hitEmitter  = World.ParticleManager.Effects[stormProperties.HitEffect];

            for (int i = 0; i < MaxRainDrops; i++)
            {
                if (!RainDrops[i].IsAlive)
                {
                    continue;
                }

                RainDrops[i].Pos += RainDrops[i].Vel * DwarfTime.Dt;

                if (stormProperties.RainRandom > 0)
                {
                    RainDrops[i].Vel.X += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt;
                    RainDrops[i].Vel.Z += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt;
                }

                if (RainDrops[i].Pos.Y < 0)
                {
                    RainDrops[i].IsAlive = false;
                }

                if (!RainDrops[i].IsAlive && RainDrops[i].Particle != null)
                {
                    RainDrops[i].Particle.LifeRemaining = -1;
                }
                else if (RainDrops[i].IsAlive && RainDrops[i].Particle == null)
                {
                    RainDrops[i].Particle = rainEmitter.Emitters[0].CreateParticle(RainDrops[i].Pos,
                                                                                   RainDrops[i].Vel, Color.White);
                }
                else if (RainDrops[i].IsAlive && RainDrops[i].Particle != null)
                {
                    RainDrops[i].Particle.Position = RainDrops[i].Pos;
                    RainDrops[i].Particle.Velocity = RainDrops[i].Vel;
                }

                var test = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(RainDrops[i].Pos));
                if (!test.IsValid || (test.IsEmpty && test.LiquidLevel == 0))
                {
                    continue;
                }

                RainDrops[i].IsAlive = false;

                var hitBodies = World.EnumerateIntersectingObjects(new BoundingBox(RainDrops[i].Pos - Vector3.One, RainDrops[i].Pos + Vector3.One));

                foreach (var body in hitBodies)
                {
                    if (body.Parent != Manager.RootComponent)
                    {
                        continue;
                    }

                    var flames = body.GetRoot().GetComponent <Flammable>();
                    if (flames != null)
                    {
                        flames.Heat *= 0.25f;
                    }

                    var seeds = body.GetRoot().GetComponent <Seedling>();
                    if (seeds != null)
                    {
                        if (TypeofStorm == StormType.RainStorm)
                        {
                            seeds.GrowthTime += MathFunctions.Rand(1.0f, 12.0f);
                        }
                        else if (MathFunctions.RandEvent(0.01f))
                        {
                            seeds.GetRoot().Die();
                        }
                    }
                }
                hitEmitter.Trigger(1, RainDrops[i].Pos + Vector3.UnitY * 0.5f, Color.White);

                //if (!MathFunctions.RandEvent(0.1f)) continue;

                var above = test.IsEmpty ? test : VoxelHelpers.GetVoxelAbove(test);

                if (!above.IsValid || !above.IsEmpty)
                {
                    continue;
                }
                if (TypeofStorm == StormType.RainStorm &&
                    (above.LiquidLevel < WaterManager.maxWaterLevel && (above.LiquidType == LiquidType.Water)))
                {
                    above.LiquidLevel = (byte)Math.Min(WaterManager.maxWaterLevel, above.LiquidLevel + WaterManager.rainFallAmount);
                    above.LiquidType  = stormProperties.LiquidToCreate;
                }
                else if (TypeofStorm == StormType.SnowStorm && above.IsEmpty && above.LiquidLevel == 0)
                {
                    if (test.GrassType == 0)
                    {
                        test.GrassType  = Library.GetGrassType("snow").ID;
                        test.GrassDecay = Library.GetGrassType("snow").InitialDecayValue;
                    }
                    else
                    {
                        var existingGrass = Library.GetGrassType((byte)test.GrassType);
                        if (!String.IsNullOrEmpty(existingGrass.BecomeWhenSnowedOn))
                        {
                            var newGrass = Library.GetGrassType(existingGrass.BecomeWhenSnowedOn);
                            test.GrassType  = newGrass.ID;
                            test.GrassDecay = newGrass.InitialDecayValue;
                        }
                    }
                }
            }

            Matrix tf = LocalTransform;

            tf.Translation += Velocity * DwarfTime.Dt;
            LocalTransform  = tf;
        }
Пример #2
0
        /// <summary> gets the list of actions that the creature can take from a given voxel. </summary>
        public IEnumerable <MoveAction> GetMoveActions(MoveState state, List <GameComponent> teleportObjects, MoveActionTempStorage Storage)
        {
            if (Parent == null)
            {
                yield break;
            }

            if (!state.Voxel.IsValid)
            {
                yield break;
            }

            if (Creature == null)
            {
                yield break;
            }

            if (Storage == null)
            {
                Storage = new MoveActionTempStorage();
            }

            GetNeighborhood(state.Voxel.Chunk.Manager, state.Voxel, Storage.Neighborhood);

            bool inWater          = (Storage.Neighborhood[1, 1, 1].IsValid && Storage.Neighborhood[1, 1, 1].LiquidLevel > WaterManager.inWaterThreshold);
            bool standingOnGround = (Storage.Neighborhood[1, 0, 1].IsValid && !Storage.Neighborhood[1, 0, 1].IsEmpty);
            bool topCovered       = (Storage.Neighborhood[1, 2, 1].IsValid && !Storage.Neighborhood[1, 2, 1].IsEmpty);
            bool hasNeighbors     = HasNeighbors(Storage.Neighborhood);
            bool isRiding         = state.VehicleType != VehicleTypes.None;

            var neighborHoodBounds = new BoundingBox(Storage.Neighborhood[0, 0, 0].GetBoundingBox().Min, Storage.Neighborhood[2, 2, 2].GetBoundingBox().Max);

            Storage.NeighborObjects.Clear();
            Parent.World.EnumerateIntersectingObjects(neighborHoodBounds, Storage.NeighborObjects);

            if (Can(MoveType.Teleport))
            {
                foreach (var obj in teleportObjects)
                {
                    if ((obj.Position - state.Voxel.WorldPosition).LengthSquared() < TeleportDistanceSquared)
                    {
                        yield return new MoveAction()
                               {
                                   InteractObject   = obj,
                                   MoveType         = MoveType.Teleport,
                                   SourceVoxel      = state.Voxel,
                                   DestinationState = new MoveState()
                                   {
                                       Voxel = new VoxelHandle(state.Voxel.Chunk.Manager, GlobalVoxelCoordinate.FromVector3(obj.Position))
                                   },
                                   CostMultiplier = 1.0f
                               }
                    }
                }
            }
            ;

            var successors = EnumerateSuccessors(state, state.Voxel, Storage, inWater, standingOnGround, topCovered, hasNeighbors);

            // Now, validate each move action that the creature might take.
            foreach (MoveAction v in successors)
            {
#if DEBUG
                if (!v.DestinationVoxel.IsValid)
                {
                    throw new InvalidOperationException();
                }
#endif

                var n = v.DestinationVoxel.IsValid ? v.DestinationVoxel : Storage.Neighborhood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z];
                if (n.IsValid && (v.MoveType == MoveType.Dig || isRiding || n.IsEmpty || n.LiquidLevel > 0))
                {
                    // Do one final check to see if there is an object blocking the motion.
                    bool blockedByObject = false;
                    if (state.VehicleType == VehicleTypes.None)
                    {
                        var objectsAtNeighbor = Storage.NeighborObjects.Where(o => o.GetBoundingBox().Intersects(n.GetBoundingBox()));

                        // If there is an object blocking the motion, determine if it can be passed through.

                        foreach (var body in objectsAtNeighbor)
                        {
                            var door = body as Door;
                            // ** Doors are in the octtree, pretty sure this was always pointless -- var door = body.GetRoot().EnumerateAll().OfType<Door>().FirstOrDefault();
                            // If there is an enemy door blocking movement, we can destroy it to get through.
                            if (door != null)
                            {
                                if (
                                    Creature.World.Overworld.GetPolitics(door.TeamFaction.ParentFaction, Creature.Faction.ParentFaction)
                                    .GetCurrentRelationship() ==
                                    Relationship.Hateful)
                                {
                                    if (Can(MoveType.DestroyObject))
                                    {
                                        yield return(new MoveAction
                                        {
                                            Diff = v.Diff,
                                            MoveType = MoveType.DestroyObject,
                                            InteractObject = door,
                                            DestinationVoxel = n,
                                            SourceState = state,
                                            CostMultiplier = 1.0f // Todo: Multiply by toughness of object?
                                        });
                                    }
                                    blockedByObject = true;
                                }
                            }
                        }
                    }

                    // If no object blocked us, we can move freely as normal.
                    if (!blockedByObject && n.LiquidType != LiquidType.Lava)
                    {
                        var newAction = v;
                        newAction.SourceState      = state;
                        newAction.DestinationVoxel = n;
                        yield return(newAction);
                    }
                }
            }
        }
Пример #3
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            var body = Parent as GameComponent;

            global::System.Diagnostics.Debug.Assert(body != null);

            Vector3 targetVelocity = TargetPosition - body.GlobalTransform.Translation;

            if (targetVelocity.LengthSquared() > 0.0001f)
            {
                targetVelocity.Normalize();
                targetVelocity *= MaxVelocity;
            }

            Matrix m = body.LocalTransform;

            m.Translation      += targetVelocity * (float)gameTime.ElapsedGameTime.TotalSeconds;
            body.LocalTransform = m;

            body.HasMoved = true;

            switch (State)
            {
            case BalloonState.DeliveringGoods:
            {
                var voxel = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(body.GlobalTransform.Translation));

                if (voxel.IsValid)
                {
                    var surfaceVoxel = VoxelHelpers.FindFirstVoxelBelow(voxel);
                    var height       = surfaceVoxel.Coordinate.Y + 1;

                    TargetPosition = new Vector3(body.GlobalTransform.Translation.X, height + 5, body.GlobalTransform.Translation.Z);

                    Vector3 diff = body.GlobalTransform.Translation - TargetPosition;

                    if (diff.LengthSquared() < 2)
                    {
                        State = BalloonState.Waiting;
                    }
                }
                else
                {
                    State = BalloonState.Leaving;
                }
            }
            break;

            case BalloonState.Leaving:
                TargetPosition = Vector3.UnitY * 100 + body.GlobalTransform.Translation;

                if (body.GlobalTransform.Translation.Y > World.WorldSizeInVoxels.Y + 2)
                {
                    Die();
                }

                break;

            case BalloonState.Waiting:
                TargetPosition = body.GlobalTransform.Translation;
                if (!WaitTimer.HasTriggered)
                {
                    var voxel = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(body.GlobalTransform.Translation));

                    if (voxel.IsValid)
                    {
                        var surfaceVoxel = VoxelHelpers.FindFirstVoxelBelow(voxel);
                        var height       = surfaceVoxel.Coordinate.Y + 6;

                        TargetPosition = new Vector3(body.GlobalTransform.Translation.X, height + 0.5f * (float)Math.Sin(DwarfTime.LastTime.TotalGameTime.TotalSeconds), body.GlobalTransform.Translation.Z);
                    }
                    WaitTimer.Update(DwarfTime.LastTime);
                    break;
                }
                if (!shipmentGiven)
                {
                    shipmentGiven = true;
                }
                else
                {
                    State = BalloonState.Leaving;
                }


                break;
            }
        }
Пример #4
0
 public static IEnumerable <GlobalVoxelCoordinate> EnumerateCube(
     GlobalVoxelCoordinate Coordinate)
 {
     return(EnumerateNeighbors(Cube, Coordinate));
 }
Пример #5
0
 public static IEnumerable <GlobalVoxelCoordinate> EnumerateVertexNeighbors2D(
     GlobalVoxelCoordinate Coordinate, VoxelVertex Vertex)
 {
     return(EnumerateNeighbors(VertexNeighbors2D[(int)Vertex], Coordinate));
 }
Пример #6
0
        private List <VoxelHandle> SpiralVoxels()
        {
            // Process voxels into a neat grid.
            if (Voxels.Count == 0)
            {
                throw new InvalidOperationException();
            }

            var bounds    = this.GetBoundingBox();
            var voxelGrid = new VoxelHandle[(int)(bounds.Max.X - bounds.Min.X), (int)(bounds.Max.Z - bounds.Min.Z)];

            foreach (var voxel in Voxels)
            {
                voxelGrid[(int)(voxel.Coordinate.X - bounds.Min.X), (int)(voxel.Coordinate.Z - bounds.Min.Z)] = voxel;
            }

            // if any invalid voxels in grid, go ahead and abort.
            foreach (var voxel in voxelGrid)
            {
                if (!voxel.IsValid)
                {
                    return(Voxels);
                }
            }

            // Find center voxel. Actually want to round UP - or - spiral in positive direction?
            var center_c  = GlobalVoxelCoordinate.FromVector3(bounds.Center());
            var current_v = Voxels.FirstOrDefault(v => v.Coordinate == center_c);

            if (!current_v.IsValid)
            {
                return(Voxels);
            }

            var direction = Direction.East;

            var results = new List <VoxelHandle>();

            results.Add(current_v);

            // Starting at center, spiral around, starting to the right.

            while (true)
            {
                var next_voxel = Voxels.FirstOrDefault(v => v.Coordinate == current_v.Coordinate + GetDirectionOffset(direction));
                if (next_voxel.IsValid)
                {
                    results.Add(next_voxel);
                    current_v = next_voxel;

                    var possible_turn  = TurnRight(direction);
                    var possible_ahead = Voxels.FirstOrDefault(v => v.Coordinate == current_v.Coordinate + GetDirectionOffset(possible_turn));
                    if (possible_ahead.IsValid && !results.Any(v => v.Coordinate == possible_ahead.Coordinate))
                    {
                        direction = possible_turn;
                    }
                }
                else
                {
                    break;
                }
            }

            // Recover any voxels we missed.
            foreach (var voxel in Voxels)
            {
                if (!results.Any(v => v.Coordinate == voxel.Coordinate))
                {
                    results.Add(voxel);
                }
            }

            return(results);

            // For each voxel - step one in the current direction and return.
            //      If we've hit an edge - try and turn.
            //      If the next direction is unvisited - turn
        }
Пример #7
0
 public static IEnumerable <GlobalVoxelCoordinate> EnumerateManhattanNeighbors2D_Z(GlobalVoxelCoordinate Coordinate)
 {
     return(EnumerateNeighbors(ManhattanNeighbors2D.Select(n => new GlobalVoxelOffset(n.X, -n.Z, 0)), Coordinate));
 }
Пример #8
0
        public bool IsCameraUnderwater()
        {
            var handle = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Camera.Position + Vector3.Up));

            return(handle.IsValid && handle.LiquidLevel > 0 && handle.Coordinate.Y <= (PersistentSettings.MaxViewingLevel >= World.WorldSizeInVoxels.Y ? 1000.0f : PersistentSettings.MaxViewingLevel + 0.25f));
        }
Пример #9
0
 public void ChangeCameraMode(OrbitCamera.ControlType type)
 {
     Camera.Control = type;
     if (type == OrbitCamera.ControlType.Walk)
     {
         SetMaxViewingLevel(World.WorldSizeInVoxels.Y);
         var below = VoxelHelpers.FindFirstVoxelBelowIncludingWater(new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(new Vector3(Camera.Position.X, World.WorldSizeInVoxels.Y - 1, Camera.Position.Z))));
         Camera.Position = below.WorldPosition + Vector3.One * 0.5f + Vector3.Up;
     }
 }
Пример #10
0
        /// <summary>
        /// Rasterizes the line, producing a list of GlobalVoxelCoordinates's that intersect
        /// the line segment.
        /// </summary>
        /// <param name="Start">The start.</param>
        /// <param name="End">The end.</param>
        /// <returns></returns>
        public static IEnumerable <GlobalVoxelCoordinate> FastVoxelTraversal(Vector3 Start, Vector3 End)
        {
            if (L1(Start, End) < 1e-12 || HasNan(Start) || HasNan(End))
            {
                yield break;
            }

            // From "A Fast DestinationVoxel Traversal Algorithm for Ray Tracing"
            // by John Amanatides and Andrew Woo, 1987
            // <http://www.cse.yorku.ca/~amana/research/grid.pdf>
            // <http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.3443>
            // Extensions to the described algorithm:
            //   • Imposed a distance limit.

            // The foundation of this algorithm is a parameterized representation of
            // the provided ray,
            //                    origin + t * direction,
            // except that t is not actually stored; rather, at any given point in the
            // traversal, we keep track of the *greater* t values which we would have
            // if we took a step sufficient to cross a cube boundary along that axis
            // (i.e. change the integer part of the coordinate) in the variables
            // tMaxX, tMaxY, and tMaxZ.

            Vector3 direction    = End - Start;
            var     cutoffLength = direction.LengthSquared() * 1.01f;

            direction.Normalize();

            // Direction to increment x,y,z when stepping.
            var stepX = Math.Sign(direction.X);
            var stepY = Math.Sign(direction.Y);
            var stepZ = Math.Sign(direction.Z);

            // See description above. The initial values depend on the fractional
            // part of the origin.
            var tMaxX = IntBound(Start.X, direction.X);
            var tMaxY = IntBound(Start.Y, direction.Y);
            var tMaxZ = IntBound(Start.Z, direction.Z);

            // The change in t when taking a step (always positive).
            var tDeltaX = stepX / direction.X;
            var tDeltaY = stepY / direction.Y;
            var tDeltaZ = stepZ / direction.Z;

            var endX = FloorInt(End.X);
            var endY = FloorInt(End.Y);
            var endZ = FloorInt(End.Z);

            while (true)
            {
                var r = GlobalVoxelCoordinate.FromVector3(Start);
                yield return(r);

                if (r.X == endX && r.Y == endY && r.Z == endZ)
                {
                    yield break;
                }
                if ((End - Start).LengthSquared() > cutoffLength)
                {
                    yield break;
                }

                // tMaxX stores the t-value at which we cross a cube boundary along the
                // X axis, and similarly for Y and Z. Therefore, choosing the least tMax
                // chooses the closest cube boundary. Only the first case of the four
                // has been commented in detail.
                if (tMaxX < tMaxY)
                {
                    if (tMaxX < tMaxZ)
                    {
                        // Update which cube we are now in.
                        Start.X += stepX;
                        // Adjust tMaxX to the next X-oriented boundary crossing.
                        tMaxX += tDeltaX;
                    }
                    else
                    {
                        Start.Z += stepZ;
                        tMaxZ   += tDeltaZ;
                    }
                }
                else
                {
                    if (tMaxY < tMaxZ)
                    {
                        Start.Y += stepY;
                        tMaxY   += tDeltaY;
                    }
                    else
                    {
                        // Identical to the second case, repeated for simplicity in
                        // the conditionals.
                        Start.Z += stepZ;
                        tMaxZ   += tDeltaZ;
                    }
                }
            }
        }
Пример #11
0
        /// <summary> gets the list of actions that the creature can take from a given voxel. </summary>
        public IEnumerable <MoveAction> GetMoveActions(MoveState state, OctTreeNode OctTree)
        {
            if (Parent == null)
            {
                yield break;
            }

            var voxel = state.Voxel;

            if (!voxel.IsValid)
            {
                yield break;
            }
            var creature = Creature;

            if (creature == null)
            {
                yield break;
            }

            var  neighborHood     = GetNeighborhood(voxel.Chunk.Manager.ChunkData, voxel);
            bool inWater          = (neighborHood[1, 1, 1].IsValid && neighborHood[1, 1, 1].LiquidLevel > WaterManager.inWaterThreshold);
            bool standingOnGround = (neighborHood[1, 0, 1].IsValid && !neighborHood[1, 0, 1].IsEmpty);
            bool topCovered       = (neighborHood[1, 2, 1].IsValid && !neighborHood[1, 2, 1].IsEmpty);
            bool hasNeighbors     = HasNeighbors(neighborHood);
            bool isRiding         = state.VehicleState.IsRidingVehicle;

            var neighborHoodBounds = new BoundingBox(neighborHood[0, 0, 0].GetBoundingBox().Min, neighborHood[2, 2, 2].GetBoundingBox().Max);
            var neighborObjects    = new HashSet <Body>();

            OctTree.EnumerateItems(neighborHoodBounds, neighborObjects);
            var successors = EnumerateSuccessors(state, voxel, neighborHood, inWater, standingOnGround, topCovered, hasNeighbors, isRiding, neighborObjects);

            if (Can(MoveType.Teleport))
            {
                var teleportObjects = Parent.Faction.OwnedObjects.Where(obj => obj.Active && obj.Tags.Contains("Teleporter"));
                foreach (var obj in teleportObjects)
                {
                    if ((obj.Position - state.Voxel.WorldPosition).LengthSquared() < TeleportDistanceSquared)
                    {
                        yield return(new MoveAction()
                        {
                            InteractObject = obj,
                            MoveType = MoveType.Teleport,
                            SourceVoxel = voxel,
                            DestinationState = new MoveState()
                            {
                                Voxel = new VoxelHandle(voxel.Chunk.Manager.ChunkData, GlobalVoxelCoordinate.FromVector3(obj.Position))
                            }
                        });
                    }
                }
            }
            // Now, validate each move action that the creature might take.
            foreach (MoveAction v in successors)
            {
                var n = v.DestinationVoxel.IsValid ? v.DestinationVoxel : neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z];
                if (n.IsValid && (v.MoveType == MoveType.Dig || isRiding || n.IsEmpty || n.LiquidLevel > 0))
                {
                    // Do one final check to see if there is an object blocking the motion.
                    bool blockedByObject = false;
                    if (!isRiding)
                    {
                        var objectsAtNeighbor = neighborObjects.Where(o => o.GetBoundingBox().Intersects(n.GetBoundingBox()));

                        // If there is an object blocking the motion, determine if it can be passed through.

                        foreach (var body in objectsAtNeighbor)
                        {
                            var door = body as Door;
                            // ** Doors are in the octtree, pretty sure this was always pointless -- var door = body.GetRoot().EnumerateAll().OfType<Door>().FirstOrDefault();
                            // If there is an enemy door blocking movement, we can destroy it to get through.
                            if (door != null)
                            {
                                if (
                                    creature.World.Diplomacy.GetPolitics(door.TeamFaction, creature.Faction)
                                    .GetCurrentRelationship() ==
                                    Relationship.Hateful)
                                {
                                    if (Can(MoveType.DestroyObject))
                                    {
                                        yield return(new MoveAction
                                        {
                                            Diff = v.Diff,
                                            MoveType = MoveType.DestroyObject,
                                            InteractObject = door,
                                            DestinationVoxel = n,
                                            SourceState = state
                                        });
                                    }
                                    blockedByObject = true;
                                }
                            }
                        }
                    }

                    // If no object blocked us, we can move freely as normal.
                    if (!blockedByObject && n.LiquidType != LiquidType.Lava)
                    {
                        MoveAction newAction = v;
                        newAction.SourceState      = state;
                        newAction.DestinationVoxel = n;
                        yield return(newAction);
                    }
                }
            }
        }
Пример #12
0
        override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            base.Update(gameTime, chunks, camera);

            Storm.InitializeStatics();
            BoundingBox box = chunks.Bounds;

            box.Expand(10.0f);

            if (GlobalTransform.Translation.X < box.Min.X ||
                GlobalTransform.Translation.X > box.Max.X ||
                GlobalTransform.Translation.Z < box.Min.Z ||
                GlobalTransform.Translation.Z > box.Max.Z)
            {
                Die();
            }


            bool generateRainDrop = MathFunctions.RandEvent(Raininess * 0.75f);

            if (generateRainDrop)
            {
                for (int i = 0; i < MaxRainDrops; i++)
                {
                    if (!RainDrops[i].IsAlive)
                    {
                        RainDrops[i].IsAlive = true;
                        RainDrops[i].Pos     = MathFunctions.RandVector3Box(BoundingBox.Expand(5));
                        RainDrops[i].Pos     = new Vector3(RainDrops[i].Pos.X, BoundingBox.Min.Y - 1, RainDrops[i].Pos.Z);
                        RainDrops[i].Vel     = Vector3.Down * Storm.Properties[TypeofStorm].RainSpeed + Velocity;
                        break;
                    }
                }
            }

            Storm.StormProperties stormProperties = Storm.Properties[TypeofStorm];
            var rainEmitter = World.ParticleManager.Effects[stormProperties.RainEffect];
            var hitEmitter  = World.ParticleManager.Effects[stormProperties.HitEffect];

            for (int i = 0; i < MaxRainDrops; i++)
            {
                if (!RainDrops[i].IsAlive)
                {
                    continue;
                }

                RainDrops[i].Pos += RainDrops[i].Vel * DwarfTime.Dt;

                if (stormProperties.RainRandom > 0)
                {
                    RainDrops[i].Vel.X += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt;
                    RainDrops[i].Vel.Z += MathFunctions.Rand(-1, 1) * stormProperties.RainRandom * DwarfTime.Dt;
                }

                if (RainDrops[i].Pos.Y < 0)
                {
                    RainDrops[i].IsAlive = false;
                }

                if (!RainDrops[i].IsAlive && RainDrops[i].Particle != null)
                {
                    RainDrops[i].Particle.LifeRemaining = -1;
                    RainDrops[i].Particle = null;
                }
                else if (RainDrops[i].IsAlive && RainDrops[i].Particle == null)
                {
                    RainDrops[i].Particle = rainEmitter.Emitters[0].CreateParticle(RainDrops[i].Pos,
                                                                                   RainDrops[i].Vel, Color.White);
                }
                else if (RainDrops[i].IsAlive && RainDrops[i].Particle != null)
                {
                    RainDrops[i].Particle.Position = RainDrops[i].Pos;
                    RainDrops[i].Particle.Velocity = RainDrops[i].Vel;
                }

                var test = new VoxelHandle(chunks.ChunkData,
                                           GlobalVoxelCoordinate.FromVector3(RainDrops[i].Pos));
                if (!test.IsValid || test.IsEmpty || test.LiquidLevel > 0)
                {
                    continue;
                }

                RainDrops[i].IsAlive = false;
                hitEmitter.Trigger(1, RainDrops[i].Pos + Vector3.UnitY * 0.5f, Color.White);

                //if (!MathFunctions.RandEvent(0.1f)) continue;

                var above = test.IsEmpty ? test : VoxelHelpers.GetVoxelAbove(test);

                if (!above.IsValid || !above.IsEmpty)
                {
                    continue;
                }
                if (TypeofStorm == StormType.RainStorm &&
                    (above.LiquidLevel < WaterManager.maxWaterLevel && (above.LiquidType == LiquidType.Water)))
                {
                    above.LiquidLevel = (byte)Math.Min(WaterManager.maxWaterLevel, above.LiquidLevel + WaterManager.rainFallAmount);
                    above.LiquidType  = stormProperties.LiquidToCreate;
                }
                else if (TypeofStorm == StormType.SnowStorm && above.IsEmpty && above.LiquidLevel == 0)
                {
                    if (test.GrassType == 0)
                    {
                        test.GrassType  = GrassLibrary.GetGrassType("snow").ID;
                        test.GrassDecay = GrassLibrary.GetGrassType("snow").InitialDecayValue;
                    }
                    else
                    {
                        var existingGrass = GrassLibrary.GetGrassType((byte)test.GrassType);
                        if (!String.IsNullOrEmpty(existingGrass.BecomeWhenSnowedOn))
                        {
                            var newGrass = GrassLibrary.GetGrassType(existingGrass.BecomeWhenSnowedOn);
                            test.GrassType  = newGrass.ID;
                            test.GrassDecay = newGrass.InitialDecayValue;
                        }
                    }
                }
            }

            Matrix tf = LocalTransform;

            tf.Translation += Velocity * DwarfTime.Dt;
            LocalTransform  = tf;
        }
Пример #13
0
        /// <summary>
        /// Snaps the supplied coordinate into valid world space. Returns nearest valid voxel to the point.
        /// </summary>
        /// <param name="chunks"></param>
        /// <param name="pos"></param>
        /// <returns></returns>
        public static VoxelHandle FindValidVoxelNear(ChunkManager chunks, Microsoft.Xna.Framework.Vector3 pos)
        {
            var clampedPos = MathFunctions.Clamp(pos, chunks.Bounds) + Microsoft.Xna.Framework.Vector3.Down * 0.05f;

            return(chunks.CreateVoxelHandle(GlobalVoxelCoordinate.FromVector3(clampedPos)));
        }
Пример #14
0
        public override void Update(DwarfTime Time, ChunkManager Chunks, Camera Camera)
        {
            if (Active)
            {
                ParticleTimer.Update(Time);
                if (ParticleTimer.HasTriggered)
                {
                    float       t          = (float)Time.TotalGameTime.TotalSeconds * 0.5f;
                    Vector3     pos        = new Vector3((float)Math.Sin(t) * TeleportDistance, 0, (float)Math.Cos(t) * TeleportDistance) + Position;
                    VoxelHandle voxelBelow = VoxelHelpers.FindFirstVoxelBelow(new VoxelHandle(World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(pos)));

                    if (voxelBelow.IsValid)
                    {
                        World.ParticleManager.Trigger("green_flame", voxelBelow.WorldPosition + Vector3.Up * 1.5f, Color.White, 1);
                    }
                }
            }
            base.Update(Time, Chunks, Camera);
        }
Пример #15
0
        public void Sense()
        {
            if (Name == "turret-sensor")
            {
                var x = 5;
            }

            if (!Active)
            {
                return;
            }

            if (Creature != null)
            {
                Allies = Creature.Faction;
            }

            // Don't sense enemies if we're inside the ground??
            var currentVoxel = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Position));

            if (!(currentVoxel.IsValid && currentVoxel.IsEmpty))
            {
                return;
            }

            var sensed = new List <CreatureAI>();

            var myRoot = GetRoot();

            foreach (var body in Manager.World.EnumerateIntersectingObjects(BoundingBox, b => !Object.ReferenceEquals(b, myRoot) && b.IsRoot()))
            {
                if (body.GetComponent <Flammable>().HasValue(out var flames) && flames.IsOnFire)
                {
                    if (GetRoot().GetComponent <CreatureAI>().HasValue(out var myAI))
                    {
                        var task = new FleeEntityTask(body, 5)
                        {
                            Priority        = TaskPriority.Urgent,
                            AutoRetry       = false,
                            ReassignOnDeath = false
                        };

                        if (!myAI.HasTaskWithName(task))
                        {
                            myAI.AssignTask(task);
                        }

                        continue;
                    }
                }

                if (body.GetComponent <CreatureAI>().HasValue(out var minion))
                {
                    if (!minion.Active)
                    {
                        continue;
                    }

                    if (!DetectCloaked && minion.Creature.IsCloaked)
                    {
                        continue;
                    }

                    else if (DetectCloaked && minion.Creature.IsCloaked)
                    {
                        minion.Creature.IsCloaked = false;
                    }

                    if (World.Overworld.GetPolitics(Allies.ParentFaction, minion.Faction.ParentFaction).GetCurrentRelationship() != Relationship.Hateful)
                    {
                        continue;
                    }

                    if (!VoxelHelpers.DoesRayHitSolidVoxel(Manager.World.ChunkManager, Position, minion.Position))
                    {
                        sensed.Add(minion);
                    }
                }
            }

            if (sensed != null && sensed.Count > 0 && OnEnemySensed != null)
            {
                OnEnemySensed.Invoke(sensed);
            }
        }
Пример #16
0
        public IEnumerable <Status> TeleportFunction()
        {
            GameComponent closestItem = Creature.AI.Blackboard.GetData <GameComponent>(ObjectName);

            if (closestItem != null)
            {
                var location = TeleportOffset + closestItem.BoundingBox.Center();
                if (CheckForOcclusion)
                {
                    VoxelHandle voxAt       = new VoxelHandle(Agent.World.ChunkManager, GlobalVoxelCoordinate.FromVector3(location));
                    bool        gotLocation = false;
                    if (!voxAt.IsValid || !voxAt.IsEmpty)
                    {
                        // If we can't go to the preferred location, just try any free neighbor.
                        voxAt = new VoxelHandle(Agent.World.ChunkManager, GlobalVoxelCoordinate.FromVector3(closestItem.BoundingBox.Center()));
                        foreach (var neighbor in VoxelHelpers.EnumerateManhattanNeighbors2D(voxAt.Coordinate))
                        {
                            VoxelHandle newVox = new VoxelHandle(Agent.World.ChunkManager, neighbor);

                            if (newVox.IsValid && newVox.IsEmpty)
                            {
                                location    = newVox.WorldPosition + new Vector3(0.5f, Agent.Physics.BoundingBox.Extents().Y, 0.5f);
                                gotLocation = true;
                                break;
                            }
                        }

                        // If there's no free neighbor, just teleport directly to the object.
                        if (!gotLocation)
                        {
                            location = closestItem.BoundingBox.Center();
                        }
                    }
                }
                TeleportAct act = new TeleportAct(Creature.AI)
                {
                    Location = location
                };
                act.Initialize();
                foreach (Act.Status status in act.Run())
                {
                    yield return(status);
                }
            }

            yield return(Status.Fail);
        }
Пример #17
0
        /// <summary> Animate the PlayState Camera to look at this creature </summary>
        public void ZoomToMe()
        {
            Manager.World.Renderer.Camera.ZoomTo(Position + Vector3.Up * 8.0f);

            var above = VoxelHelpers.FindFirstVoxelAbove(new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(Position)));

            if (above.IsValid)
            {
                World.Renderer.SetMaxViewingLevel(above.Coordinate.Y);
            }
            else
            {
                World.Renderer.SetMaxViewingLevel(World.WorldSizeInVoxels.Y);
            }
        }
Пример #18
0
        public static Act.Status SetTarget(string voxelOutName, string entityName, Creature creature)
        {
            Body target = creature.AI.Blackboard.GetData <Body>(entityName);

            if (target == null)
            {
                return(Status.Fail);
            }
            else
            {
                var targetPosition = target.BoundingBox.Center();
                targetPosition = MathFunctions.Clamp(targetPosition, target.World.ChunkManager.Bounds.Expand(-1));
                var voxelUnder = VoxelHelpers.FindFirstVoxelBelowIncludeWater(new VoxelHandle(
                                                                                  creature.World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(targetPosition)));

                if (voxelUnder.IsValid)
                {
                    if (!voxelUnder.IsEmpty)
                    {
                        voxelUnder = VoxelHelpers.GetVoxelAbove(voxelUnder);
                    }
                    creature.AI.Blackboard.SetData(voxelOutName, voxelUnder);
                    return(Status.Success);
                }
                else
                {
                    return(Status.Fail);
                }
            }
        }
Пример #19
0
        public void Update(ParticleManager manager, DwarfTime gameTime, ChunkManager chunks, Camera camera)
        {
            ParticleEmitter._camera = camera;

            List <Particle> toRemove = new List <Particle>();

            TriggerTimer.Update(gameTime);
            if (TriggerTimer.HasTriggered && Data.ParticlesPerFrame > 0)
            {
                Trigger(Data.ParticlesPerFrame, Vector3.Zero, new Color(255, 255, 0));
            }


            bool particlePhysics = GameSettings.Default.ParticlePhysics;

            foreach (Particle p in Particles)
            {
                float vel = p.Velocity.LengthSquared();
                if (Data.EmitsLight && p.Scale > 0.1f)
                {
                    DynamicLight.TempLights.Add(new DynamicLight(10.0f, 255.0f, false)
                    {
                        Position = p.Position
                    });
                }
                p.Position += p.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds;

                if (Data.RotatesWithVelocity)
                {
                    Vector3 cameraVel   = camera.Project(p.Velocity + camera.Position);
                    float   projectionX = cameraVel.X;
                    float   projectionY = cameraVel.Y;

                    p.Angle = (float)Math.Atan2(projectionY, projectionX);
                }
                else
                {
                    p.Angle += (float)(p.AngularVelocity * gameTime.ElapsedGameTime.TotalSeconds);
                }
                if (!Data.Sleeps || vel > 0.01f)
                {
                    p.Velocity += Data.ConstantAccel * (float)gameTime.ElapsedGameTime.TotalSeconds;
                }
                p.Velocity        *= Data.LinearDamping;
                p.AngularVelocity *= Data.AngularDamping;


                if (!Data.UseManualControl)
                {
                    p.LifeRemaining -= Data.ParticleDecay * (float)gameTime.ElapsedGameTime.TotalSeconds;
                }
                else if (p.TimeAlive > 60)
                {
                    p.LifeRemaining = 0;
                }

                p.Scale += Data.GrowthSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;

                p.Scale = Math.Max(p.Scale, 0.0f);

                var v = new VoxelHandle(chunks.ChunkData,
                                        GlobalVoxelCoordinate.FromVector3(p.Position));

                if (Data.HasLighting)
                {
                    if (v.IsValid)
                    {
                        p.LightRamp = new Color(v.Sunlight ? 255 : 0, 255, 0);
                    }
                }
                else
                {
                    p.LightRamp = new Color(255, 255, 0);
                }

                if (Data.CollidesWorld && particlePhysics && vel > 0.2f)
                {
                    if (v.IsValid && !v.IsEmpty)
                    {
                        BoundingBox     b       = new BoundingBox(p.Position - Vector3.One * p.Scale * 0.5f, p.Position + Vector3.One * p.Scale * 0.5f);
                        BoundingBox     vBox    = v.GetBoundingBox();
                        Physics.Contact contact = new Physics.Contact();
                        if (Physics.TestStaticAABBAABB(b, vBox, ref contact))
                        {
                            p.Position += contact.NEnter * contact.Penetration;
                            Vector3 newVelocity = Vector3.Reflect(p.Velocity, -contact.NEnter);
                            p.Velocity         = newVelocity * Data.Damping;
                            p.AngularVelocity *= 0.5f;
                            if (Data.Sleeps)
                            {
                                p.Velocity        = Vector3.Zero;
                                p.AngularVelocity = 0.0f;
                                vel = 0.0f;
                            }
                            if (!String.IsNullOrEmpty(Data.SpatterType))
                            {
                                var above = VoxelHelpers.GetVoxelAbove(v);
                                if (!above.IsValid || above.IsEmpty)
                                {
                                    float x = MathFunctions.Clamp(p.Position.X, vBox.Min.X + 0.1f, vBox.Max.X - 0.1f);
                                    float z = MathFunctions.Clamp(p.Position.Z, vBox.Min.Z + 0.1f, vBox.Max.Z - 0.1f);
                                    manager.Create(Data.SpatterType,
                                                   VertexNoise.Warp(new Vector3(x, v.RampType == RampType.None ? v.WorldPosition.Y + 1.02f : v.WorldPosition.Y + 0.6f, z)), Vector3.Zero, Color.White, Vector3.Up);
                                }
                                else
                                {
                                    manager.Create(Data.SpatterType, p.Position - contact.NEnter * contact.Penetration * 0.95f, Vector3.Zero, Color.White, contact.NEnter);
                                }
                                p.LifeRemaining = -1.0f;
                            }
                        }
                    }
                }

                if (p.LifeRemaining < 0)
                {
                    if (p.InstanceData != null)
                    {
                        p.InstanceData.ShouldDraw = false;
                        p.InstanceData.Transform  = Matrix.CreateTranslation(camera.Position + new Vector3(-1000, -1000, -1000));
                        Sprites[p.Frame].Remove(p.InstanceData);
                    }

                    toRemove.Add(p);
                }

                else if (p.InstanceData != null)
                {
                    p.TimeAlive += (float)gameTime.ElapsedGameTime.TotalSeconds + MathFunctions.Rand() * 0.01f;
                    int prevFrame = p.Frame;
                    int newFrame  = AnimPlayer.GetFrame(p.TimeAlive);
                    if (vel < 0.2f && Data.Sleeps)
                    {
                        newFrame = prevFrame;
                    }
                    if (newFrame != prevFrame)
                    {
                        p.Frame = newFrame;
                        if (Sprites.Count > 0)
                        {
                            Sprites[prevFrame].Remove(p.InstanceData);
                            Sprites[newFrame].Add(p.InstanceData);
                        }
                        if (/*!Data.Animation.Loops && */ p.Frame == Data.Animation.Frames.Count - 1)
                        {
                            p.LifeRemaining *= 0.1f;
                        }
                    }
                    p.InstanceData.ShouldDraw = true;
                    p.InstanceData.Transform  = MatrixFromParticle(Data, p);
                    p.InstanceData.LightRamp  = p.LightRamp;
                }
            }

            foreach (Particle p in toRemove)
            {
                Particles.Remove(p);
            }


            foreach (var sprites in Sprites)
            {
                sprites.Update(gameTime, camera, GameState.Game.GraphicsDevice, chunks.World.Master.MaxViewingLevel);
            }
        }
Пример #20
0
        public List <Body> GenerateRandomSpawn(int numCreatures, Vector3 position)
        {
            if (Race.CreatureTypes.Count == 0)
            {
                return(new List <Body>());
            }

            List <Body> toReturn = new List <Body>();

            for (int i = 0; i < numCreatures; i++)
            {
                string  creature = Race.CreatureTypes[MathFunctions.Random.Next(Race.CreatureTypes.Count)];
                Vector3 offset   = MathFunctions.RandVector3Cube() * 2;

                var voxelUnder = VoxelHelpers.FindFirstVoxelBelowIncludeWater(new VoxelHandle(
                                                                                  World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(position + offset)));
                if (voxelUnder.IsValid)
                {
                    var body = EntityFactory.CreateEntity <Body>(creature, voxelUnder.WorldPosition + new Vector3(0.5f, 1, 0.5f));
                    var ai   = body.EnumerateAll().OfType <CreatureAI>().FirstOrDefault();

                    if (ai != null)
                    {
                        ai.Faction.Minions.Remove(ai);

                        Minions.Add(ai);
                        ai.Faction         = this;
                        ai.Creature.Allies = Name;
                    }

                    toReturn.Add(body);
                }
            }

            return(toReturn);
        }
Пример #21
0
 public static IEnumerable <GlobalVoxelCoordinate> EnumerateAllNeighbors(
     GlobalVoxelCoordinate Coordinate)
 {
     return(EnumerateNeighbors(AllNeighbors, Coordinate));
 }
Пример #22
0
        public VoxelChunk GenerateChunk(Vector3 origin, WorldManager World)
        {
            float      waterHeight = SeaLevel + 1.0f / VoxelConstants.ChunkSizeY;
            VoxelChunk c           = new VoxelChunk(Manager, origin, GlobalVoxelCoordinate.FromVector3(origin).GetGlobalChunkCoordinate());

            for (int x = 0; x < VoxelConstants.ChunkSizeX; x++)
            {
                for (int z = 0; z < VoxelConstants.ChunkSizeZ; z++)
                {
                    Vector2 v = new Vector2(x + origin.X, z + origin.Z) / WorldScale;

                    var biome = Overworld.Map[(int)MathFunctions.Clamp(v.X, 0, Overworld.Map.GetLength(0) - 1), (int)MathFunctions.Clamp(v.Y, 0, Overworld.Map.GetLength(1) - 1)].Biome;

                    BiomeData biomeData = BiomeLibrary.Biomes[biome];

                    Vector2 pos         = new Vector2(x + origin.X, z + origin.Z) / WorldScale;
                    float   hNorm       = Overworld.LinearInterpolate(pos, Overworld.Map, Overworld.ScalarFieldType.Height);
                    float   h           = MathFunctions.Clamp(hNorm * VoxelConstants.ChunkSizeY, 0.0f, VoxelConstants.ChunkSizeY - 2);
                    int     stoneHeight = (int)(MathFunctions.Clamp((int)(h - (biomeData.SoilLayer.Depth + (Math.Sin(v.X) + Math.Cos(v.Y)))), 1, h));

                    int currentSubsurfaceLayer = 0;
                    int depthWithinSubsurface  = 0;
                    for (int y = VoxelConstants.ChunkSizeY - 1; y >= 0; y--)
                    {
                        var voxel = new VoxelHandle(c, new LocalVoxelCoordinate(x, y, z));

                        if (y == 0)
                        {
                            voxel.RawSetType(VoxelLibrary.GetVoxelType("Bedrock"));
                            voxel.Health = 255; // ?
                            continue;
                        }

                        if (y <= stoneHeight && stoneHeight > 1)
                        {
                            voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SubsurfaceLayers[currentSubsurfaceLayer].VoxelType));
                            depthWithinSubsurface++;
                            if (depthWithinSubsurface > biomeData.SubsurfaceLayers[currentSubsurfaceLayer].Depth)
                            {
                                depthWithinSubsurface = 0;
                                currentSubsurfaceLayer++;
                                if (currentSubsurfaceLayer > biomeData.SubsurfaceLayers.Count - 1)
                                {
                                    currentSubsurfaceLayer = biomeData.SubsurfaceLayers.Count - 1;
                                }
                            }
                        }

                        else if ((y == (int)h || y == stoneHeight) && hNorm > waterHeight)
                        {
                            if (biomeData.ClumpGrass &&
                                NoiseGenerator.Noise(pos.X / biomeData.ClumpSize, 0, pos.Y / biomeData.ClumpSize) >
                                biomeData.ClumpTreshold)
                            {
                                voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));
                                if (!String.IsNullOrEmpty(biomeData.GrassDecal))
                                {
                                    var decal = GrassLibrary.GetGrassType(biomeData.GrassDecal);
                                    voxel.RawSetGrass(decal.ID);
                                }
                            }
                            else if (!biomeData.ClumpGrass)
                            {
                                voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));
                                if (!String.IsNullOrEmpty(biomeData.GrassDecal))
                                {
                                    var decal = GrassLibrary.GetGrassType(biomeData.GrassDecal);
                                    voxel.RawSetGrass(decal.ID);
                                }
                            }
                            else
                            {
                                voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));
                            }
                        }
                        else if (y > h && y > 0)
                        {
                            voxel.RawSetType(VoxelLibrary.emptyType);
                        }
                        else if (hNorm <= waterHeight)
                        {
                            voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.ShoreVoxel));
                        }
                        else
                        {
                            voxel.RawSetType(VoxelLibrary.GetVoxelType(biomeData.SoilLayer.VoxelType));
                        }
                    }
                }
            }

            GenerateWater(c);
            GenerateLava(c);

            UpdateSunlight(c, 255);
            return(c);
        }
Пример #23
0
 public static IEnumerable <GlobalVoxelCoordinate> EnumerateManhattanCube(
     GlobalVoxelCoordinate Coordinate)
 {
     return(EnumerateNeighbors(ManhattanCubeNeighbors, Coordinate));
 }
Пример #24
0
 internal VoxelHandle(GlobalVoxelCoordinate Coordinate)
 {
     this.Coordinate   = Coordinate;
     this._cache_Chunk = null;
     this._cache_Index = 0;
 }
Пример #25
0
        public bool IsCameraUnderwater()
        {
            var handle = new VoxelHandle(ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(Camera.Position));

            return(handle.IsValid && handle.WaterCell.WaterLevel > 0);
        }
Пример #26
0
 public VoxelHandle(VoxelChunk Chunk, LocalVoxelCoordinate Coordinate)
 {
     this.Coordinate   = Chunk.ID + Coordinate;
     this._cache_Chunk = Chunk;
     this._cache_Index = VoxelConstants.DataIndexOf(Coordinate);
 }
Пример #27
0
        public static bool IsValidPlacement(
            VoxelHandle Location,
            CraftItem CraftType,
            WorldManager World,
            GameComponent PreviewBody,
            String Verb,
            String PastParticple)
        {
            if (CraftType == null)
            {
                return(false);
            }

            if (!String.IsNullOrEmpty(CraftType.CraftLocation) &&
                World.PlayerFaction.FindNearestItemWithTags(CraftType.CraftLocation, Location.WorldPosition, false, null) == null)
            {
                World.UserInterface.ShowTooltip("Can't " + Verb + ", need " + CraftType.CraftLocation);
                return(false);
            }

            foreach (var req in CraftType.Prerequisites)
            {
                switch (req)
                {
                case CraftItem.CraftPrereq.NearWall:
                {
                    var neighborFound = VoxelHelpers.EnumerateManhattanNeighbors2D(Location.Coordinate)
                                        .Select(c => new VoxelHandle(World.ChunkManager, c))
                                        .Any(v => v.IsValid && !v.IsEmpty);

                    if (!neighborFound)
                    {
                        World.UserInterface.ShowTooltip("Must be " + PastParticple + " next to wall!");
                        return(false);
                    }

                    break;
                }

                case CraftItem.CraftPrereq.OnGround:
                {
                    var below = VoxelHelpers.GetNeighbor(Location, new GlobalVoxelOffset(0, -1, 0));

                    if (!below.IsValid || below.IsEmpty)
                    {
                        World.UserInterface.ShowTooltip("Must be " + PastParticple + " on solid ground!");
                        return(false);
                    }
                    break;
                }
                }
            }

            if (PreviewBody != null)
            {
                // Just check for any intersecting body in octtree.

                var previewBox = PreviewBody.GetRotatedBoundingBox();
                var sensorBox  = previewBox;
                var sensor     = PreviewBody.GetComponent <GenericVoxelListener>();
                if (sensor != null)
                {
                    sensorBox = sensor.GetRotatedBoundingBox();
                }
                if (Debugger.Switches.DrawToolDebugInfo)
                {
                    Drawer3D.DrawBox(sensorBox, Color.Yellow, 0.1f, false);
                }

                foreach (var intersectingObject in World.EnumerateIntersectingObjects(sensorBox, CollisionType.Static))
                {
                    if (Object.ReferenceEquals(intersectingObject, sensor))
                    {
                        continue;
                    }
                    var objectRoot = intersectingObject.GetRoot() as GameComponent;
                    if (objectRoot is WorkPile)
                    {
                        continue;
                    }
                    if (objectRoot == PreviewBody)
                    {
                        continue;
                    }
                    if (objectRoot != null && objectRoot.GetRotatedBoundingBox().Intersects(previewBox))
                    {
                        World.UserInterface.ShowTooltip("Can't " + Verb + " here: intersects " + objectRoot.Name);
                        return(false);
                    }
                }

                bool intersectsWall = VoxelHelpers.EnumerateCoordinatesInBoundingBox
                                          (PreviewBody.GetRotatedBoundingBox().Expand(-0.1f)).Any(
                    v =>
                {
                    var tvh = new VoxelHandle(World.ChunkManager, v);
                    return(tvh.IsValid && !tvh.IsEmpty);
                });
                var  current    = new VoxelHandle(World.ChunkManager, GlobalVoxelCoordinate.FromVector3(PreviewBody.Position));
                bool underwater = current.IsValid && current.LiquidType != LiquidType.None;
                if (underwater)
                {
                    World.UserInterface.ShowTooltip("Can't " + Verb + " here: underwater or in lava.");
                    return(false);
                }
                if (intersectsWall && !CraftType.Prerequisites.Contains(CraftItem.CraftPrereq.NearWall))
                {
                    World.UserInterface.ShowTooltip("Can't " + Verb + " here: intersects wall.");
                    return(false);
                }
            }
            World.UserInterface.ShowTooltip("");
            return(true);
        }
Пример #28
0
        private void Place(VoxelHandle Location)
        {
            var assignments = new List <Task>();

            for (var i = 0; i < PreviewBodies.Count; ++i)
            {
                var body              = PreviewBodies[i];
                var piece             = Pattern.Pieces[i];
                var actualPosition    = new VoxelHandle(Location.Chunk.Manager.ChunkData, Location.Coordinate + new GlobalVoxelOffset(piece.Offset.X, 0, piece.Offset.Y));
                var addNewDesignation = true;

                foreach (var entity in Player.World.CollisionManager.EnumerateIntersectingObjects(actualPosition.GetBoundingBox().Expand(-0.2f), CollisionManager.CollisionType.Static))
                {
                    if (!addNewDesignation)
                    {
                        break;
                    }
                    if (Object.ReferenceEquals(entity, body))
                    {
                        continue;
                    }

                    var possibleCombination = FindPossibleCombination(piece, entity);
                    if (possibleCombination != null)
                    {
                        var combinedPiece = new Rail.JunctionPiece
                        {
                            RailPiece   = possibleCombination.Result,
                            Orientation = Rail.OrientationHelper.Rotate((entity as RailPiece).Piece.Orientation, (int)possibleCombination.ResultRelativeOrientation),
                        };

                        var existingDesignation = Player.Faction.Designations.EnumerateEntityDesignations(DesignationType.Craft).FirstOrDefault(d => Object.ReferenceEquals(d.Body, entity));
                        if (existingDesignation != null)
                        {
                            (entity as RailPiece).UpdatePiece(combinedPiece, actualPosition);
                            (existingDesignation.Tag as CraftDesignation).Progress = 0.0f;
                            body.Delete();
                            addNewDesignation = false;
                        }
                        else
                        {
                            (entity as RailPiece).Die();
                            body.UpdatePiece(combinedPiece, actualPosition);
                        }
                    }
                }

                if (addNewDesignation)
                {
                    var startPos = body.Position + new Vector3(0.0f, -0.3f, 0.0f);
                    var endPos   = body.Position;

                    var designation = new CraftDesignation
                    {
                        Entity              = body,
                        WorkPile            = new WorkPile(Player.World.ComponentManager, startPos),
                        OverrideOrientation = false,
                        Valid                = true,
                        ItemType             = RailCraftItem,
                        SelectedResources    = SelectedResources,
                        Location             = new VoxelHandle(Player.World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(body.Position)),
                        HasResources         = false,
                        ResourcesReservedFor = null,
                        Orientation          = 0.0f,
                        Progress             = 0.0f,
                    };

                    Player.World.ComponentManager.RootComponent.AddChild(designation.WorkPile);
                    designation.WorkPile.AnimationQueue.Add(new EaseMotion(1.1f, Matrix.CreateTranslation(startPos), endPos));
                    Player.World.ParticleManager.Trigger("puff", endPos, Color.White, 10);
                    Player.Faction.Designations.AddEntityDesignation(body, DesignationType.Craft, designation);
                    assignments.Add(new CraftItemTask(designation));
                }
            }

            if (assignments.Count > 0)
            {
                Player.World.Master.TaskManager.AddTasks(assignments);
            }
        }
Пример #29
0
        public void HandlePosessedDwarf()
        {
            KeyboardState keyState = Keyboard.GetState();

            if (SelectedMinions.Count != 1)
            {
                CameraController.FollowAutoTarget = false;
                CameraController.EnableControl    = true;
                foreach (var creature in Faction.Minions)
                {
                    creature.IsPosessed = false;
                }
                return;
            }

            var dwarf = SelectedMinions[0];

            if (!dwarf.IsPosessed)
            {
                CameraController.FollowAutoTarget = false;
                CameraController.EnableControl    = true;
                return;
            }
            CameraController.EnableControl    = false;
            CameraController.AutoTarget       = dwarf.Position;
            CameraController.FollowAutoTarget = true;

            if (dwarf.Velocity.Length() > 0.1)
            {
                var above = VoxelHelpers.FindFirstVoxelAbove(new VoxelHandle(
                                                                 World.ChunkManager.ChunkData, GlobalVoxelCoordinate.FromVector3(dwarf.Position)));

                if (above.IsValid)
                {
                    World.ChunkManager.ChunkData.SetMaxViewingLevel(above.Coordinate.Y, ChunkManager.SliceMode.Y);
                }
                else
                {
                    World.ChunkManager.ChunkData.SetMaxViewingLevel(VoxelConstants.ChunkSizeY,
                                                                    ChunkManager.SliceMode.Y);
                }
            }

            Vector3 forward         = CameraController.GetForwardVector();
            Vector3 right           = CameraController.GetRightVector();
            Vector3 desiredVelocity = Vector3.Zero;
            bool    hadCommand      = false;
            bool    jumpCommand     = false;

            if (keyState.IsKeyDown(ControlSettings.Mappings.Forward) || keyState.IsKeyDown(Keys.Up))
            {
                hadCommand       = true;
                desiredVelocity += forward * 10;
            }

            if (keyState.IsKeyDown(ControlSettings.Mappings.Back) || keyState.IsKeyDown(Keys.Down))
            {
                hadCommand       = true;
                desiredVelocity -= forward * 10;
            }

            if (keyState.IsKeyDown(ControlSettings.Mappings.Right) || keyState.IsKeyDown(Keys.Right))
            {
                hadCommand       = true;
                desiredVelocity += right * 10;
            }

            if (keyState.IsKeyDown(ControlSettings.Mappings.Left) || keyState.IsKeyDown(Keys.Left))
            {
                hadCommand       = true;
                desiredVelocity -= right * 10;
            }

            if (keyState.IsKeyDown(ControlSettings.Mappings.Jump))
            {
                jumpCommand = true;
                hadCommand  = true;
            }

            if (hadCommand)
            {
                if (dwarf.CurrentTask != null)
                {
                    dwarf.CurrentTask.Cancel();
                }
                dwarf.CurrentTask = null;
                dwarf.TryMoveVelocity(desiredVelocity, jumpCommand);
            }
            else if (dwarf.CurrentTask == null)
            {
                if (dwarf.Creature.IsOnGround)
                {
                    if (dwarf.Physics.Velocity.LengthSquared() < 1)
                    {
                        dwarf.Creature.CurrentCharacterMode = DwarfCorp.CharacterMode.Idle;
                    }
                    dwarf.Physics.Velocity = new Vector3(dwarf.Physics.Velocity.X * 0.9f, dwarf.Physics.Velocity.Y,
                                                         dwarf.Physics.Velocity.Z * 0.9f);
                    dwarf.TryMoveVelocity(Vector3.Zero, false);
                }
            }
        }
Пример #30
0
        /// <summary>
        /// Checks the voxels around the creature and reacts to changes in its immediate environment.
        /// For example this function determines when the creature is standing on solid ground.
        /// </summary>
        public void CheckNeighborhood(ChunkManager chunks, float dt)
        {
            var below = new VoxelHandle(chunks.ChunkData,
                                        GlobalVoxelCoordinate.FromVector3(Physics.GlobalTransform.Translation - Vector3.UnitY * 0.8f));
            var above = new VoxelHandle(chunks.ChunkData,
                                        GlobalVoxelCoordinate.FromVector3(Physics.GlobalTransform.Translation + Vector3.UnitY * 0.8f));

            if (above.IsValid)
            {
                IsHeadClear = above.IsEmpty;
            }
            if (below.IsValid && Physics.IsInLiquid)
            {
                IsOnGround = false;
            }
            else if (below.IsValid)
            {
                IsOnGround = !below.IsEmpty;
            }
            else
            {
                IsOnGround = false;
            }

            if (!IsOnGround)
            {
                if (CurrentCharacterMode != CharacterMode.Flying)
                {
                    if (Physics.Velocity.Y > 0.05)
                    {
                        CurrentCharacterMode = CharacterMode.Jumping;
                    }
                    else if (Physics.Velocity.Y < -0.05)
                    {
                        CurrentCharacterMode = CharacterMode.Falling;
                    }
                }

                if (Physics.IsInLiquid)
                {
                    CurrentCharacterMode = CharacterMode.Swimming;
                }
            }

            if (CurrentCharacterMode == CharacterMode.Falling && IsOnGround)
            {
                CurrentCharacterMode = CharacterMode.Idle;
            }

            if (Status.IsAsleep)
            {
                CurrentCharacterMode = CharacterMode.Sleeping;

                if (MathFunctions.RandEvent(0.01f))
                {
                    NoiseMaker.MakeNoise("Sleep", AI.Position, true);
                }
            }
            else if (currentCharacterMode == CharacterMode.Sleeping)
            {
                CurrentCharacterMode = CharacterMode.Idle;
            }

            if (!Status.Energy.IsDissatisfied())
            {
                Status.IsAsleep = false;
            }
        }