Example #1
0
        private const int rumbleCount = 50;         // Average the last X block positions to get the position of the rumble
        public void Update(float dt)
        {
            intervalTimer += dt;
            Entity targetEntity = this.Target.Value.Target;

            if (targetEntity != null && targetEntity.Active && this.Index < this.Coords.Length)
            {
                EffectBlockFactory factory = Factory.Get <EffectBlockFactory>();
                Voxel m = targetEntity.Get <Voxel>();

                float interval = 0.03f * this.IntervalMultiplier;

                while (intervalTimer > interval && this.Index < this.Coords.Length)
                {
                    CoordinateEntry entry       = this.Coords[this.Index];
                    Entity          blockEntity = factory.CreateAndBind(main);
                    EffectBlock     effectBlock = blockEntity.Get <EffectBlock>();
                    entry.Coord.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>());
                    effectBlock.CheckAdjacent = false;
                    effectBlock.Offset.Value  = m.GetRelativePosition(entry.Coord);
                    effectBlock.DoScale       = true;

                    effectBlock.StartPosition    = entry.Position + new Vector3(8.0f, 20.0f, 8.0f) * this.BlockLifetime.Value;
                    effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f * this.Index, 0.15f * this.Index, 0);

                    effectBlock.TotalLifetime = this.BlockLifetime;
                    effectBlock.Setup(targetEntity, entry.Coord, entry.Coord.Data.ID);
                    main.Add(blockEntity);

                    this.rumbleSum += entry.Position;
                    int lastIndex = this.Index - rumbleCount;
                    if (lastIndex >= 0)
                    {
                        this.rumbleSum -= this.Coords[lastIndex].Position;
                    }

                    this.Index.Value++;
                    intervalTimer -= interval;
                }
                if (this.Coords.Count > 200)
                {
                    this.RumblePosition.Value = this.rumbleSum / Math.Min(this.Index + 1, rumbleCount);
                    if (!this.rumbling)
                    {
                        AkSoundEngine.PostEvent(AK.EVENTS.PLAY_BLOCK_RUMBLE, this.Entity);
                        this.rumbling = true;
                    }
                }
            }
            else
            {
                this.Delete.Execute();
            }
        }
Example #2
0
        public void Update(float dt)
        {
            intervalTimer += dt;
            Entity targetEntity = this.Target.Value.Target;

            if (targetEntity != null && targetEntity.Active && this.Index < this.Coords.Length)
            {
                float interval = 0.03f * this.IntervalMultiplier;
                while (intervalTimer > interval && this.Index < this.Coords.Length)
                {
                    EffectBlockFactory factory = Factory.Get <EffectBlockFactory>();
                    Voxel m = targetEntity.Get <Voxel>();

                    CoordinateEntry entry       = this.Coords[this.Index];
                    Entity          blockEntity = factory.CreateAndBind(main);
                    EffectBlock     effectBlock = blockEntity.Get <EffectBlock>();
                    entry.Coord.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>());
                    effectBlock.CheckAdjacent = false;
                    effectBlock.Offset.Value  = m.GetRelativePosition(entry.Coord);
                    effectBlock.DoScale       = true;

                    effectBlock.StartPosition    = entry.Position + new Vector3(8.0f, 20.0f, 8.0f) * this.BlockLifetime.Value;
                    effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f * this.Index, 0.15f * this.Index, 0);

                    effectBlock.TotalLifetime = this.BlockLifetime;
                    effectBlock.Setup(targetEntity, entry.Coord, entry.Coord.Data.ID);
                    main.Add(blockEntity);

                    this.Index.Value++;
                    intervalTimer -= interval;
                }
            }
            else
            {
                this.Delete.Execute();
            }
        }
Example #3
0
        public static void Consolidate(Main main, DynamicVoxel voxel, Voxel targetVoxel, Voxel.Coord targetCoord, float interval = 1.0f)
        {
            if (targetVoxel != null)
            {
                // Combine this map with the other one

                Direction x = targetVoxel.GetRelativeDirection(voxel.GetAbsoluteVector(Vector3.Right));
                Direction y = targetVoxel.GetRelativeDirection(voxel.GetAbsoluteVector(Vector3.Up));
                Direction z = targetVoxel.GetRelativeDirection(voxel.GetAbsoluteVector(Vector3.Backward));

                if (x.IsParallel(y))
                {
                    x = y.Cross(z);
                }
                else if (y.IsParallel(z))
                {
                    y = x.Cross(z);
                }

                Voxel.Coord offset = new Voxel.Coord();
                float       closestCoordDistance = float.MaxValue;
                Vector3     closestCoordPosition = targetVoxel.GetAbsolutePosition(targetCoord);
                foreach (Voxel.Coord c in voxel.Chunks.SelectMany(c => c.Boxes).SelectMany(b => b.GetCoords()))
                {
                    float distance = (voxel.GetAbsolutePosition(c) - closestCoordPosition).LengthSquared();
                    if (distance < closestCoordDistance)
                    {
                        closestCoordDistance = distance;
                        offset = c;
                    }
                }
                Vector3 toLevitatingMap = voxel.Transform.Value.Translation - targetVoxel.GetAbsolutePosition(targetCoord);
                offset = offset.Move(voxel.GetRelativeDirection(-toLevitatingMap));

                Quaternion orientation = Quaternion.CreateFromRotationMatrix(voxel.Transform.Value);

                EffectBlockFactory blockFactory = Factory.Get <EffectBlockFactory>();

                int index = 0;
                List <Voxel.Coord> coords = voxel.Chunks.SelectMany(c => c.Boxes).SelectMany(b => b.GetCoords()).ToList();
                Voxel.Coord        camera = voxel.GetCoordinate(main.Camera.Position);
                foreach (Voxel.Coord c in coords.OrderBy(c2 => new Vector3(c2.X - camera.X, c2.Y - camera.Y, c2.Z - camera.Z).LengthSquared()))
                {
                    Voxel.Coord offsetFromCenter = c.Move(-offset.X, -offset.Y, -offset.Z);
                    Voxel.Coord targetCoord2     = new Voxel.Coord();
                    targetCoord2.SetComponent(x, offsetFromCenter.GetComponent(Direction.PositiveX));
                    targetCoord2.SetComponent(y, offsetFromCenter.GetComponent(Direction.PositiveY));
                    targetCoord2.SetComponent(z, offsetFromCenter.GetComponent(Direction.PositiveZ));
                    targetCoord2 = targetCoord2.Move(targetCoord.X, targetCoord.Y, targetCoord.Z);
                    if (targetVoxel[targetCoord2].ID == 0)
                    {
                        Entity blockEntity = blockFactory.CreateAndBind(main);
                        c.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>());
                        EffectBlock effectBlock = blockEntity.Get <EffectBlock>();
                        effectBlock.Offset.Value     = targetVoxel.GetRelativePosition(targetCoord2);
                        effectBlock.DoScale          = false;
                        effectBlock.StartPosition    = voxel.GetAbsolutePosition(c);
                        effectBlock.StartOrientation = orientation;
                        effectBlock.TotalLifetime    = (0.05f + (index * 0.0075f)) * interval;
                        effectBlock.Setup(targetVoxel.Entity, targetCoord2, c.Data.ID);
                        main.Add(blockEntity);
                        index++;
                    }
                }

                // Delete the map
                voxel.Entity.Delete.Execute();
            }
        }
Example #4
0
        public override void Awake()
        {
            base.Awake();

            this.blockFactory = Factory.Get <EffectBlockFactory>();

            this.EnabledWhenPaused = false;

            if (main.EditorEnabled)
            {
                this.BlockQueue.Clear();
            }

            this.particles = ParticleSystem.Get(main, "WhiteShatter");

            for (int i = 0; i < maxSparkLights; i++)
            {
                PointLight light = new PointLight();
                light.Serialize     = false;
                light.Color.Value   = new Vector3(1.0f);
                light.Enabled.Value = false;
                this.Entity.Add(light);
                this.sparkLights.Add(light);
            }

            if (!this.main.EditorEnabled)
            {
                this.Add(new CommandBinding <Voxel, IEnumerable <Voxel.Coord>, Voxel>(Voxel.GlobalCellsFilled, delegate(Voxel map, IEnumerable <Voxel.Coord> coords, Voxel transferredFromMap)
                {
                    foreach (Voxel.Coord c in coords)
                    {
                        Voxel.t id = c.Data.ID;
                        if (id == Voxel.t.Blue || id == Voxel.t.Powered || id == Voxel.t.PoweredSwitch || id == Voxel.t.Infected || id == Voxel.t.Neutral || id == Voxel.t.HardPowered || id == Voxel.t.Hard || id == Voxel.t.HardInfected)
                        {
                            Voxel.Coord newCoord = c;
                            newCoord.Data        = Voxel.States.Empty;
                            int generation;
                            EffectBlock.Entry generationsKey = new EffectBlock.Entry {
                                Voxel = map, Coordinate = newCoord
                            };
                            if (this.generations.TryGetValue(generationsKey, out generation))
                            {
                                this.generations.Remove(generationsKey);
                            }
                            if (!this.isInQueue(map.Entity, newCoord, false))
                            {
                                this.BlockQueue.Add(new ScheduledBlock
                                {
                                    Voxel      = map.Entity,
                                    Coordinate = newCoord,
                                    Time       = propagateDelay,
                                    Generation = generation,
                                });
                            }
                        }
                    }
                }));

                this.Add(new CommandBinding <Voxel, IEnumerable <Voxel.Coord>, Voxel>(Voxel.GlobalCellsEmptied, delegate(Voxel map, IEnumerable <Voxel.Coord> coords, Voxel transferringToNewMap)
                {
                    foreach (Voxel.Coord coord in coords)
                    {
                        Voxel.t id = coord.Data.ID;
                        if (id == Voxel.t.Powered || id == Voxel.t.PoweredSwitch || id == Voxel.t.HardPowered || id == Voxel.t.PermanentPowered)
                        {
                            this.removedPoweredCoords.Add(coord);
                        }
                        if (transferringToNewMap != null)
                        {
                            continue;
                        }

                        if (id == Voxel.t.Critical)                         // Critical. Explodes when destroyed.
                        {
                            Explosion.Explode(main, map, coord);
                        }
                        else if (id == Voxel.t.HardInfected)                         // Infected. Shatter effects.
                        {
                            ParticleSystem shatter = ParticleSystem.Get(main, "InfectedShatter");
                            Vector3 pos            = map.GetAbsolutePosition(coord);
                            AkSoundEngine.PostEvent(AK.EVENTS.PLAY_INFECTED_CRITICAL_SHATTER, pos);
                            for (int i = 0; i < 50; i++)
                            {
                                Vector3 offset = new Vector3((float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f, (float)random.NextDouble() - 0.5f);
                                shatter.AddParticle(pos + offset, offset);
                            }
                        }
                        else if (id == Voxel.t.Powered || id == Voxel.t.Blue || id == Voxel.t.Neutral || id == Voxel.t.Infected || id == Voxel.t.Floater)
                        {
                            int generation;
                            Voxel.Coord c = coord;
                            c.Data        = Voxel.States.Empty;
                            EffectBlock.Entry generationKey = new EffectBlock.Entry {
                                Voxel = map, Coordinate = c
                            };
                            if (this.generations.TryGetValue(generationKey, out generation))
                            {
                                this.generations.Remove(generationKey);
                            }

                            if (id == Voxel.t.Floater)
                            {
                                Entity blockEntity      = this.blockFactory.CreateAndBind(main);
                                EffectBlock effectBlock = blockEntity.Get <EffectBlock>();
                                coord.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>());
                                effectBlock.Delay            = 4.0f;
                                effectBlock.Offset.Value     = map.GetRelativePosition(coord);
                                effectBlock.StartPosition    = map.GetAbsolutePosition(coord) + new Vector3(2.5f, 5.0f, 2.5f);
                                effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(1.0f, 1.0f, 0);
                                effectBlock.TotalLifetime    = 0.5f;
                                effectBlock.Setup(map.Entity, coord, coord.Data.ID);
                                main.Add(blockEntity);
                            }

                            if (generation == 0)
                            {
                                if (!this.isInQueue(map.Entity, coord, true))
                                {
                                    this.BlockQueue.Add(new ScheduledBlock
                                    {
                                        Voxel      = map.Entity,
                                        Coordinate = coord,
                                        Time       = propagateDelay,
                                        Removing   = true,
                                    });
                                }
                            }
                            else if (generation < maxGenerations)
                            {
                                Direction down = map.GetRelativeDirection(Direction.NegativeY);
                                for (int i = 0; i < 6; i++)
                                {
                                    Direction dir        = DirectionExtensions.Directions[i];
                                    Voxel.Coord adjacent = coord.Move(dir);
                                    if (!coords.Contains(adjacent))
                                    {
                                        Voxel.t adjacentID     = map[adjacent].ID;
                                        bool adjacentIsFloater = adjacentID == Voxel.t.Floater;
                                        if (dir != down || adjacentIsFloater)
                                        {
                                            if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Neutral || adjacentID == Voxel.t.Infected || adjacentIsFloater)
                                            {
                                                if (!this.isInQueue(map.Entity, adjacent, true))
                                                {
                                                    this.BlockQueue.Add(new ScheduledBlock
                                                    {
                                                        Voxel      = map.Entity,
                                                        Coordinate = adjacent,
                                                        Time       = propagateDelay,
                                                        Removing   = true,
                                                        Generation = generation + 1,
                                                    });
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else if (id == Voxel.t.White || id == Voxel.t.Glass)                         // Shatter effects.
                        {
                            ParticleSystem shatter = ParticleSystem.Get(main, "WhiteShatter");
                            Vector3 pos            = map.GetAbsolutePosition(coord);
                            for (int i = 0; i < 50; i++)
                            {
                                Vector3 offset = new Vector3((float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f);
                                shatter.AddParticle(pos + offset, offset);
                            }
                            float time = this.main.TotalTime;
                            if (time - this.lastShatterSound > 0.3f)
                            {
                                this.lastShatterSound = time;
                                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_WHITE_SHATTER, pos);
                            }
                        }
                    }

                    if (this.removedPoweredCoords.Count > 0)
                    {
                        IEnumerable <IEnumerable <Voxel.Box> > poweredIslands = map.GetAdjacentIslands(this.removedPoweredCoords, x => x.ID == Voxel.t.Powered || x.ID == Voxel.t.HardPowered, x => x == Voxel.States.PermanentPowered || x == Voxel.States.PoweredSwitch);
                        List <Voxel.Coord> poweredCoords = poweredIslands.SelectMany(x => x).SelectMany(x => x.GetCoords()).ToList();
                        if (poweredCoords.Count > 0)
                        {
                            lock (map.MutationLock)
                            {
                                map.Empty(poweredCoords, true, true, map, false);
                                for (int i = 0; i < poweredCoords.Count; i++)
                                {
                                    Voxel.Coord coord = poweredCoords[i];
                                    if (coord.Data.ID == Voxel.t.HardPowered)
                                    {
                                        map.Fill(coord, Voxel.States.Hard, false);
                                    }
                                    else
                                    {
                                        map.Fill(coord, Voxel.States.Blue, false);
                                    }
                                }
                            }
                            this.toRegenerate.Add(map);
                        }
                        this.removedPoweredCoords.Clear();
                    }
                }));
            }
        }
Example #5
0
        // Function for finding a wall to build for the player
        public Possibility FindWall(Vector3 position, Vector2 direction)
        {
            Voxel shortestMap = null;

            Voxel.Coord shortestPlayerCoord    = new Voxel.Coord();
            Direction   shortestWallDirection  = Direction.None;
            Direction   shortestBuildDirection = Direction.None;
            int         shortestDistance       = searchDistance;

            EffectBlockFactory blockFactory = Factory.Get <EffectBlockFactory>();

            foreach (Voxel map in Voxel.ActivePhysicsVoxels)
            {
                if (!ignoreTypes.Contains(map.Entity.Type))
                {
                    foreach (Direction absoluteWallDir in DirectionExtensions.HorizontalDirections)
                    {
                        Direction relativeWallDir = map.GetRelativeDirection(absoluteWallDir);
                        Vector3   wallVector      = map.GetAbsoluteVector(relativeWallDir.GetVector());
                        float     dot             = Vector2.Dot(direction, Vector2.Normalize(new Vector2(wallVector.X, wallVector.Z)));
                        if (dot > -0.25f && dot < 0.8f)
                        {
                            Voxel.Coord coord = map.GetCoordinate(position).Move(relativeWallDir, 2);
                            foreach (Direction dir in DirectionExtensions.Directions.Where(x => x.IsPerpendicular(relativeWallDir)))
                            {
                                for (int i = 0; i < shortestDistance; i++)
                                {
                                    Voxel.Coord c     = coord.Move(dir, i);
                                    Voxel.State state = map[c];

                                    if (state == Voxel.States.Empty)
                                    {
                                        continue;
                                    }

                                    if (this.canBuild(state) && this.canBuild(map.GetAbsolutePosition(c)))
                                    {
                                        shortestMap            = map;
                                        shortestBuildDirection = dir;
                                        shortestWallDirection  = relativeWallDir;
                                        shortestDistance       = i;
                                        shortestPlayerCoord    = coord;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (shortestMap != null)
            {
                // Found something to build a wall on.
                Direction   dirU       = shortestBuildDirection;
                Direction   dirV       = dirU.Cross(shortestWallDirection);
                Voxel.Coord startCoord = shortestPlayerCoord.Move(dirU, shortestDistance).Move(dirV, additionalWallDistance);
                Voxel.Coord endCoord   = shortestPlayerCoord.Move(dirU, -additionalWallDistance).Move(dirV, -additionalWallDistance).Move(shortestWallDirection);
                return(new Possibility
                {
                    Map = shortestMap,
                    StartCoord = new Voxel.Coord {
                        X = Math.Min(startCoord.X, endCoord.X), Y = Math.Min(startCoord.Y, endCoord.Y), Z = Math.Min(startCoord.Z, endCoord.Z)
                    },
                    EndCoord = new Voxel.Coord {
                        X = Math.Max(startCoord.X, endCoord.X), Y = Math.Max(startCoord.Y, endCoord.Y), Z = Math.Max(startCoord.Z, endCoord.Z)
                    },
                });
            }

            return(null);
        }
Example #6
0
        // Function for finding a platform to build for the player
        public Possibility FindPlatform(Vector3 position)
        {
            int       shortestDistance = searchDistance;
            Direction relativeShortestDirection = Direction.None, absoluteShortestDirection = Direction.None;

            Voxel.Coord shortestCoordinate = new Voxel.Coord();
            Voxel       shortestMap        = null;

            EffectBlockFactory blockFactory = Factory.Get <EffectBlockFactory>();

            foreach (Voxel map in Voxel.ActivePhysicsVoxels)
            {
                if (!ignoreTypes.Contains(map.Entity.Type))
                {
                    List <Matrix> results             = new List <Matrix>();
                    Voxel.Coord   absolutePlayerCoord = map.GetCoordinate(position);
                    bool          inMap = map.GetChunk(absolutePlayerCoord, false) != null;
                    foreach (Direction absoluteDir in platformBuildableDirections)
                    {
                        Voxel.Coord playerCoord = absoluteDir == Direction.NegativeY ? absolutePlayerCoord : map.GetCoordinate(position + new Vector3(0, platformSize / -2.0f, 0));
                        Direction   relativeDir = map.GetRelativeDirection(absoluteDir);
                        if (!inMap && map.GetChunk(playerCoord.Move(relativeDir, searchDistance), false) == null)
                        {
                            continue;
                        }

                        for (int i = 1; i < shortestDistance; i++)
                        {
                            Voxel.Coord coord = playerCoord.Move(relativeDir, i);
                            Voxel.State state = map[coord];

                            if (state == Voxel.States.Empty)
                            {
                                continue;
                            }

                            if (this.canBuild(state) && this.canBuild(map.GetAbsolutePosition(coord)))
                            {
                                shortestDistance          = i;
                                relativeShortestDirection = relativeDir;
                                absoluteShortestDirection = absoluteDir;
                                shortestCoordinate        = playerCoord;
                                shortestMap = map;
                            }
                            break;
                        }
                    }
                }
            }

            if (shortestMap != null && shortestDistance > 1)
            {
                Direction yDir = relativeShortestDirection.IsParallel(Direction.PositiveY) ? Direction.PositiveX : Direction.PositiveY;
                Direction zDir = relativeShortestDirection.Cross(yDir);

                int         initialOffset = absoluteShortestDirection == Direction.NegativeY ? 0 : -2;
                Voxel.Coord startCoord    = shortestCoordinate.Move(relativeShortestDirection, initialOffset).Move(yDir, platformSize / -2).Move(zDir, platformSize / -2);
                Voxel.Coord endCoord      = startCoord.Move(relativeShortestDirection, -initialOffset + shortestDistance).Move(yDir, platformSize).Move(zDir, platformSize);

                return(new Possibility
                {
                    Map = shortestMap,
                    StartCoord = new Voxel.Coord {
                        X = Math.Min(startCoord.X, endCoord.X), Y = Math.Min(startCoord.Y, endCoord.Y), Z = Math.Min(startCoord.Z, endCoord.Z)
                    },
                    EndCoord = new Voxel.Coord {
                        X = Math.Max(startCoord.X, endCoord.X), Y = Math.Max(startCoord.Y, endCoord.Y), Z = Math.Max(startCoord.Z, endCoord.Z)
                    },
                });
            }
            return(null);
        }
Example #7
0
        public void Update(float dt)
        {
            if (this.TimeUntilRebuild > 0)
            {
                if (this.TargetVoxel.Value.Target == null || !this.TargetVoxel.Value.Target.Active)
                {
                    this.Delete.Execute();
                    return;
                }

                float newValue = Math.Max(0.0f, this.TimeUntilRebuild.Value - dt);
                this.TimeUntilRebuild.Value = newValue;
                if (newValue == 0.0f)
                {
                    // Rebuild
                    Entity targetMap = this.TargetVoxel.Value.Target;

                    Voxel m = targetMap.Get <Voxel>();

                    EffectBlockFactory factory = Factory.Get <EffectBlockFactory>();

                    int startIndex = this.Base.BaseBoxes.Sum(x => x.Volume);
                    int index      = startIndex;

                    foreach (Entity.Handle e in this.DynamicVoxels)
                    {
                        Entity dynamicMap          = e.Target;
                        Voxel  dynamicMapComponent = dynamicMap != null && dynamicMap.Active ? dynamicMap.Get <Voxel>() : null;

                        if (dynamicMap == null || !dynamicMap.Active)
                        {
                            continue;
                        }

                        Quaternion orientation = Quaternion.CreateFromRotationMatrix(dynamicMapComponent.Transform.Value);

                        List <Voxel.Coord> coords = new List <Voxel.Coord>();

                        foreach (Voxel.Coord c in dynamicMapComponent.Chunks.SelectMany(x => x.Boxes).SelectMany(x => x.GetCoords()))
                        {
                            if (m[c].ID == 0)
                            {
                                coords.Add(c);
                            }
                        }

                        foreach (Voxel.Coord c in coords.OrderBy(x => (new Vector3(x.X, x.Y, x.Z) - this.Base.Position).LengthSquared()))
                        {
                            Entity blockEntity = factory.CreateAndBind(main);
                            c.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>());
                            EffectBlock effectBlock = blockEntity.Get <EffectBlock>();
                            effectBlock.Offset.Value = m.GetRelativePosition(c);
                            effectBlock.DoScale      = dynamicMapComponent == null;
                            if (dynamicMapComponent != null && dynamicMapComponent[c].ID == c.Data.ID)
                            {
                                effectBlock.StartPosition    = dynamicMapComponent.GetAbsolutePosition(c);
                                effectBlock.StartOrientation = orientation;
                            }
                            else
                            {
                                effectBlock.StartPosition    = m.GetAbsolutePosition(c) + new Vector3(0.25f, 0.5f, 0.25f) * index;
                                effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f * index, 0.15f * index, 0);
                            }
                            effectBlock.TotalLifetime = 0.05f + (index * rebuildTimeMultiplier * RebuildTime);
                            effectBlock.Setup(targetMap, c, c.Data.ID);
                            main.Add(blockEntity);
                            index++;
                        }
                        dynamicMap.Delete.Execute();
                    }
                    this.DynamicVoxels.Clear();

                    if (index > startIndex)                     // We built some stuff. Build the base.
                    {
                        int baseIndex = 0;
                        foreach (Voxel.Coord c in this.Base.BaseBoxes.SelectMany(x => x.GetCoords()))
                        {
                            if (m[c].ID == 0)
                            {
                                Entity      blockEntity = factory.CreateAndBind(main);
                                EffectBlock effectBlock = blockEntity.Get <EffectBlock>();
                                c.Data.ApplyToEffectBlock(blockEntity.Get <ModelInstance>());
                                effectBlock.Offset.Value     = m.GetRelativePosition(c);
                                effectBlock.StartPosition    = m.GetAbsolutePosition(c) + new Vector3(0.25f, 0.5f, 0.25f) * baseIndex;
                                effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f * baseIndex, 0.15f * baseIndex, 0);
                                effectBlock.TotalLifetime    = 0.05f + (baseIndex * rebuildTimeMultiplier * RebuildTime);
                                effectBlock.Setup(targetMap, c, c.Data.ID);
                                main.Add(blockEntity);
                                baseIndex++;
                            }
                        }
                        this.TimeUntilRebuildComplete.Value = 0.05f + (index * rebuildTimeMultiplier * RebuildTime);
                    }
                    else                     // We didn't build anything. Delete ourselves.
                    {
                        this.Delete.Execute();
                    }
                }
            }
            else if (this.TimeUntilRebuildComplete > 0)
            {
                // Rebuilding
                float newValue = Math.Max(0.0f, this.TimeUntilRebuildComplete.Value - dt);
                this.TimeUntilRebuildComplete.Value = newValue;
                if (newValue == 0.0f)
                {
                    // Done rebuilding
                    if (!this.Base.IsValid)
                    {
                        this.Delete.Execute();
                    }
                    else
                    {
                        this.Base.EnableCellEmptyBinding = !main.EditorEnabled;
                        if (this.IsTriggered)
                        {
                            fall();
                        }
                    }
                }
            }
        }