Example #1
0
        private void fall()
        {
            if (this.TimeUntilRebuild.Value > 0 || this.TimeUntilRebuildComplete.Value > 0)
            {
                return;
            }

            Entity targetVoxel = this.TargetVoxel.Value.Target;

            if (targetVoxel == null || !targetVoxel.Active)
            {
                return;
            }

            // Disable the cell-emptied notification.
            // This way, we won't think that the base has been destroyed by the player.
            // We are not in fact dying, we're just destroying the base so we can fall over.
            this.Base.EnableCellEmptyBinding = false;

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

            m.Empty(this.Base.BaseBoxes.SelectMany(x => x.GetCoords()));

            m.Regenerate(delegate(List <DynamicVoxel> spawnedMaps)
            {
                if (spawnedMaps.Count == 0)
                {
                    this.Delete.Execute();
                }
                else
                {
                    Vector3 playerPos = PlayerFactory.Instance.Get <Transform>().Position;
                    playerPos        += PlayerFactory.Instance.Get <Player>().Character.LinearVelocity.Value * 0.65f;
                    foreach (DynamicVoxel newMap in spawnedMaps)
                    {
                        Vector3 toPlayer = playerPos - newMap.PhysicsEntity.Position;
                        toPlayer.Normalize();
                        if (Math.Abs(toPlayer.Y) < 0.9f)
                        {
                            toPlayer *= 25.0f * newMap.PhysicsEntity.Mass;

                            Vector3 positionAtPlayerHeight = newMap.PhysicsEntity.Position;
                            Vector3 impulseAtBase          = toPlayer * -0.75f;
                            impulseAtBase.Y          = 0.0f;
                            positionAtPlayerHeight.Y = playerPos.Y;
                            newMap.PhysicsEntity.ApplyImpulse(ref positionAtPlayerHeight, ref impulseAtBase);

                            newMap.PhysicsEntity.ApplyLinearImpulse(ref toPlayer);
                        }
                        newMap.PhysicsEntity.Material.KineticFriction = 1.0f;
                        newMap.PhysicsEntity.Material.StaticFriction  = 1.0f;
                        this.DynamicVoxels.Add(newMap.Entity);
                    }
                }
            });

            this.TimeUntilRebuild.Value = RebuildDelay;
        }
Example #2
0
        private void set()
        {
            Entity voxelEntity = this.AttachedVoxel.Value.Target;

            if (voxelEntity == null)
            {
                return;
            }

            Voxel map = voxelEntity.Get <Voxel>();

            if (map == null)
            {
                return;
            }

            Voxel.State state = Voxel.States.All[this.State];
            if (this.Contiguous)
            {
                lock (map.MutationLock)
                {
                    Voxel.Box b = map.GetBox(this.Coord);
                    if (b != null && b.Type != state)
                    {
                        List <Voxel.Coord> coords = map.GetContiguousByType(new[] { b }).SelectMany(x => x.GetCoords()).Select(x => x.WithData(state)).ToList();
                        map.Empty(coords, true, true, map);
                        map.Fill(coords, true, map);
                        map.Regenerate();
                    }
                }
            }
            else
            {
                lock (map.MutationLock)
                {
                    if (map[this.Coord] != state)
                    {
                        map.Empty(this.Coord, true, true, map);
                        map.Fill(this.Coord, state, true, map);
                        map.Regenerate();
                    }
                }
            }
            this.OnSet.Execute();
        }
Example #3
0
        public override void Awake()
        {
            base.Awake();

            this.Add(new CommandBinding(this.Set, delegate()
            {
                Entity voxelEntity = this.AttachedVoxel.Value.Target;
                if (voxelEntity == null)
                {
                    return;
                }

                Voxel map         = voxelEntity.Get <Voxel>();
                Voxel.State state = Voxel.States.All[this.State];
                if (this.Contiguous)
                {
                    Voxel.Box b = map.GetBox(this.Coord);
                    if (b != null && b.Type != state)
                    {
                        List <Voxel.Coord> coords = map.GetContiguousByType(new[] { b }).SelectMany(x => x.GetCoords()).Select(x => x.WithData(state)).ToList();
                        lock (map.MutationLock)
                        {
                            map.Empty(coords, true, true);
                            map.Fill(coords);
                        }
                        map.Regenerate();
                    }
                }
                else
                {
                    if (map[this.Coord] != state)
                    {
                        lock (map.MutationLock)
                        {
                            map.Empty(this.Coord, true, true);
                            map.Fill(this.Coord, state);
                        }
                        map.Regenerate();
                    }
                }
            }));
        }
Example #4
0
        public override void Bind(Entity entity, Main main, bool creating = false)
        {
            Transform transform = entity.GetOrCreate <Transform>("Transform");

            this.SetMain(entity, main);

            VoxelAttachable attachable = VoxelAttachable.MakeAttachable(entity, main, true, false);

            attachable.Offset.Value  = 1;
            attachable.Enabled.Value = true;

            PowerBlockSocket socket = entity.GetOrCreate <PowerBlockSocket>("PowerBlockSocket");

            socket.Add(new Binding <Voxel.Coord>(socket.Coord, attachable.Coord));
            socket.Add(new Binding <Entity.Handle>(socket.AttachedVoxel, attachable.AttachedVoxel));

            const float maxLightAttenuation = 15.0f;
            PointLight  light = entity.Create <PointLight>();

            light.Attenuation.Value = maxLightAttenuation;
            light.Add(new Binding <Vector3>(light.Position, transform.Position));
            light.Add(new Binding <Vector3, Voxel.t>(light.Color, delegate(Voxel.t t)
            {
                switch (t)
                {
                case Voxel.t.GlowBlue:
                    return(new Vector3(0.8f, 0.9f, 1.2f));

                case Voxel.t.GlowYellow:
                    return(new Vector3(1.2f, 1.2f, 0.8f));

                default:
                    return(Vector3.One);
                }
            }, socket.Type));
            light.Add(new Binding <bool>(light.Enabled, socket.Powered));

            PointLight animationLight = entity.Create <PointLight>();

            animationLight.Add(new Binding <Vector3>(animationLight.Position, light.Position));
            animationLight.Add(new Binding <Vector3>(animationLight.Color, light.Color));
            animationLight.Enabled.Value = false;

            PlayerTrigger trigger = entity.GetOrCreate <PlayerTrigger>("PlayerTrigger");

            trigger.Radius.Value = 7;
            trigger.Add(new Binding <Vector3>(trigger.Position, transform.Position));
            const float minimumChangeTime = 1.5f;
            float       lastChange        = -minimumChangeTime;

            trigger.Add(new CommandBinding(trigger.PlayerEntered, delegate()
            {
                if (main.TotalTime - lastChange > minimumChangeTime)
                {
                    BlockCloud cloud = PlayerFactory.Instance.Get <BlockCloud>();

                    bool changed    = false;
                    Voxel sockVoxel = attachable.AttachedVoxel.Value.Target.Get <Voxel>();
                    if (!socket.Powered && cloud.Type.Value == socket.Type.Value)
                    {
                        // Plug in to the socket
                        List <Voxel.Coord> coords = new List <Voxel.Coord>();
                        Queue <Voxel.Coord> queue = new Queue <Voxel.Coord>();
                        queue.Enqueue(sockVoxel.GetCoordinate(transform.Position));
                        while (queue.Count > 0)
                        {
                            Voxel.Coord c = queue.Dequeue();
                            coords.Add(c);
                            if (coords.Count >= cloud.Blocks.Length)
                            {
                                break;
                            }

                            Voxel.CoordDictionaryCache[c] = true;
                            foreach (Direction adjacentDirection in DirectionExtensions.Directions)
                            {
                                Voxel.Coord adjacentCoord = c.Move(adjacentDirection);
                                if (!Voxel.CoordDictionaryCache.ContainsKey(adjacentCoord))
                                {
                                    Voxel.t adjacentID = sockVoxel[adjacentCoord].ID;
                                    if (adjacentID == Voxel.t.Empty)
                                    {
                                        queue.Enqueue(adjacentCoord);
                                    }
                                }
                            }
                        }
                        Voxel.CoordDictionaryCache.Clear();

                        EffectBlockFactory factory = Factory.Get <EffectBlockFactory>();
                        int i = 0;
                        foreach (Entity block in cloud.Blocks)
                        {
                            Entity effectBlockEntity = factory.CreateAndBind(main);
                            Voxel.States.All[cloud.Type].ApplyToEffectBlock(effectBlockEntity.Get <ModelInstance>());
                            EffectBlock effectBlock      = effectBlockEntity.Get <EffectBlock>();
                            effectBlock.DoScale          = false;
                            Transform blockTransform     = block.Get <Transform>();
                            effectBlock.StartPosition    = blockTransform.Position;
                            effectBlock.StartOrientation = blockTransform.Quaternion;
                            effectBlock.TotalLifetime    = (i + 1) * 0.04f;
                            effectBlock.Setup(sockVoxel.Entity, coords[i], cloud.Type);
                            main.Add(effectBlockEntity);
                            block.Delete.Execute();
                            i++;
                        }
                        cloud.Blocks.Clear();
                        cloud.Type.Value     = Voxel.t.Empty;
                        socket.Powered.Value = true;
                        changed = true;
                    }
                    else if (socket.Powered && cloud.Type.Value == Voxel.t.Empty && !socket.PowerOnOnly)
                    {
                        // Pull blocks out of the socket
                        SceneryBlockFactory factory = Factory.Get <SceneryBlockFactory>();
                        Quaternion quat             = Quaternion.CreateFromRotationMatrix(sockVoxel.Transform);
                        cloud.Type.Value            = socket.Type;
                        List <Voxel.Coord> coords   = sockVoxel.GetContiguousByType(new[] { sockVoxel.GetBox(transform.Position) }).SelectMany(x => x.GetCoords()).ToList();
                        sockVoxel.Empty(coords, true);
                        sockVoxel.Regenerate();
                        ParticleSystem particles = ParticleSystem.Get(main, "WhiteShatter");
                        foreach (Voxel.Coord c in coords)
                        {
                            Vector3 pos = sockVoxel.GetAbsolutePosition(c);
                            for (int j = 0; j < 20; j++)
                            {
                                Vector3 offset = new Vector3((float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f, (float)this.random.NextDouble() - 0.5f);
                                particles.AddParticle(pos + offset, offset);
                            }
                            Entity block                    = factory.CreateAndBind(main);
                            Transform blockTransform        = block.Get <Transform>();
                            blockTransform.Position.Value   = pos;
                            blockTransform.Quaternion.Value = quat;
                            SceneryBlock sceneryBlock       = block.Get <SceneryBlock>();
                            sceneryBlock.Type.Value         = socket.Type;
                            sceneryBlock.Scale.Value        = 0.5f;
                            cloud.Blocks.Add(block);
                            main.Add(block);
                        }
                        socket.Powered.Value = false;
                        changed = true;
                    }

                    if (changed)
                    {
                        lastChange = main.TotalTime;
                        animationLight.Enabled.Value     = true;
                        animationLight.Attenuation.Value = 0.0f;
                        entity.Add(new Animation
                                   (
                                       new Animation.FloatMoveTo(animationLight.Attenuation, maxLightAttenuation, 0.25f),
                                       new Animation.FloatMoveTo(animationLight.Attenuation, 0.0f, 2.0f),
                                       new Animation.Set <bool>(animationLight.Enabled, false)
                                   ));
                    }
                }
            }));

            entity.Add("Type", socket.Type);
            entity.Add("Powered", socket.Powered, new PropertyEntry.EditorData {
                Readonly = true
            });
            entity.Add("PowerOnOnly", socket.PowerOnOnly);
            entity.Add("OnPowerOn", socket.OnPowerOn);
            entity.Add("OnPowerOff", socket.OnPowerOff);
        }
Example #5
0
        public static bool Go(Voxel voxel, Voxel.Coord center, int radius, Action <List <DynamicVoxel> > callback = null)
        {
            if (!voxel[center].Permanent)
            {
                // Break off a chunk of this voxel into a new DynamicMap.

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

                Voxel.Coord ripStart = center.Move(-radius, -radius, -radius);
                Voxel.Coord ripEnd   = center.Move(radius, radius, radius);

                Dictionary <Voxel.Box, bool> permanentBoxes = new Dictionary <Voxel.Box, bool>();
                foreach (Voxel.Coord c in ripStart.CoordinatesBetween(ripEnd))
                {
                    Voxel.Box box = voxel.GetBox(c);
                    if (box != null && box.Type.Permanent)
                    {
                        permanentBoxes[box] = true;
                    }
                }

                foreach (Voxel.Box b in permanentBoxes.Keys)
                {
                    // Top and bottom
                    for (int x = b.X - 1; x <= b.X + b.Width; x++)
                    {
                        for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = x, Y = b.Y + b.Height, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = x, Y = b.Y - 1, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }
                    }

                    // Outer shell
                    for (int y = b.Y; y < b.Y + b.Height; y++)
                    {
                        // Left and right
                        for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = b.X - 1, Y = y, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = b.X + b.Width, Y = y, Z = z
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }

                        // Backward and forward
                        for (int x = b.X; x < b.X + b.Width; x++)
                        {
                            Voxel.Coord coord = new Voxel.Coord {
                                X = x, Y = y, Z = b.Z - 1
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }

                            coord = new Voxel.Coord {
                                X = x, Y = y, Z = b.Z + b.Depth
                            };
                            if (coord.Between(ripStart, ripEnd))
                            {
                                edges.Add(coord);
                            }
                        }
                    }
                }

                if (edges.Contains(center))
                {
                    return(false);
                }

                // Top and bottom
                for (int x = ripStart.X; x <= ripEnd.X; x++)
                {
                    for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = x, Y = ripStart.Y, Z = z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = x, Y = ripEnd.Y, Z = z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }
                }

                // Sides
                for (int y = ripStart.Y + 1; y <= ripEnd.Y - 1; y++)
                {
                    // Left and right
                    for (int z = ripStart.Z; z <= ripEnd.Z; z++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = ripStart.X, Y = y, Z = z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = ripEnd.X, Y = y, Z = z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }

                    // Backward and forward
                    for (int x = ripStart.X; x <= ripEnd.X; x++)
                    {
                        Voxel.Coord c = new Voxel.Coord {
                            X = x, Y = y, Z = ripStart.Z
                        };
                        Voxel.State s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                        c = new Voxel.Coord {
                            X = x, Y = y, Z = ripEnd.Z
                        };
                        s = voxel[c];
                        if (s != Voxel.States.Empty && !s.Permanent)
                        {
                            edges.Add(c);
                        }
                    }
                }

                Propagator p = WorldFactory.Instance.Get <Propagator>();
                foreach (Voxel.Coord c in edges)
                {
                    p.SparksLowPriority(voxel.GetAbsolutePosition(c), Propagator.Spark.Dangerous);
                }

                voxel.Empty(edges);

                voxel.Regenerate(callback);
                return(true);
            }
            return(false);
        }
Example #6
0
        public void Update(float dt)
        {
            float sparkLightFade = sparkLightBrightness * dt / sparkLightFadeTime;

            for (int i = 0; i < activeSparkLights; i++)
            {
                PointLight light = this.sparkLights[i];
                float      a     = light.Color.Value.X - sparkLightFade;
                if (a < 0.0f)
                {
                    light.Enabled.Value = false;
                    PointLight swap = this.sparkLights[activeSparkLights - 1];
                    this.sparkLights[i] = swap;
                    this.sparkLights[activeSparkLights - 1] = light;
                    activeSparkLights--;
                    oldestSparkLight = activeSparkLights;
                }
                else
                {
                    light.Color.Value = new Vector3(a);
                }
            }

            for (int i = 0; i < this.BlockQueue.Length; i++)
            {
                ScheduledBlock entry = this.BlockQueue[i];
                entry.Time -= dt;
                if (entry.Time < 0.0f)
                {
                    this.BlockQueue.RemoveAt(i);
                    i--;

                    Entity mapEntity = entry.Voxel.Target;
                    if (mapEntity != null && mapEntity.Active)
                    {
                        Voxel       map = mapEntity.Get <Voxel>();
                        Voxel.Coord c   = entry.Coordinate;
                        Voxel.t     id  = map[c].ID;

                        bool regenerate = false;

                        if (entry.Removing)
                        {
                            if (entry.Generation == 0 && id == 0)
                            {
                                Direction down = map.GetRelativeDirection(Direction.NegativeY);
                                for (int j = 0; j < 6; j++)
                                {
                                    Direction   dir               = DirectionExtensions.Directions[j];
                                    Voxel.Coord adjacent          = c.Move(dir);
                                    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 = 1,
                                                });
                                            }
                                        }
                                    }
                                }
                            }
                            else if (entry.Generation > 0 && (id == Voxel.t.Blue || id == Voxel.t.Infected || id == Voxel.t.Powered || id == Voxel.t.PermanentPowered || id == Voxel.t.HardPowered || id == Voxel.t.PoweredSwitch || id == Voxel.t.Neutral || id == Voxel.t.Floater))
                            {
                                this.generations[new EffectBlock.Entry {
                                                     Voxel = map, Coordinate = c
                                                 }] = entry.Generation;
                                map.Empty(c);
                                this.SparksLowPriority(map.GetAbsolutePosition(c), Spark.Burn);
                                regenerate = true;
                            }
                        }
                        else if (id == Voxel.t.Blue)
                        {
                            for (int j = 0; j < 6; j++)
                            {
                                Direction   dir        = DirectionExtensions.Directions[j];
                                Voxel.Coord adjacent   = c.Move(dir);
                                Voxel.t     adjacentID = map[adjacent].ID;

                                if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.PermanentPowered || adjacentID == Voxel.t.HardPowered || adjacentID == Voxel.t.PoweredSwitch)
                                {
                                    map.Empty(c, false, true, map);
                                    map.Fill(c, Voxel.States.Powered);
                                    this.SparksLowPriority(map.GetAbsolutePosition(c), Spark.Normal);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations)
                                {
                                    map.Empty(adjacent, false, true, map);
                                    this.generations[new EffectBlock.Entry {
                                                         Voxel = map, Coordinate = adjacent
                                                     }] = entry.Generation + 1;
                                    map.Fill(adjacent, Voxel.States.Blue);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal);
                                    regenerate = true;
                                }
                            }
                        }
                        else if (id == Voxel.t.Neutral)
                        {
                            for (int j = 0; j < 6; j++)
                            {
                                Direction   dir        = DirectionExtensions.Directions[j];
                                Voxel.Coord adjacent   = c.Move(dir);
                                Voxel.t     adjacentID = map[adjacent].ID;
                                if (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Powered)
                                {
                                    map.Empty(adjacent, false, true, map);
                                    map.Fill(adjacent, Voxel.States.Neutral);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.HardInfected)
                                {
                                    map.Empty(adjacent, false, true, map);
                                    map.Fill(adjacent, Voxel.States.Hard);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal);
                                    regenerate = true;
                                }
                            }
                        }
                        else if (id == Voxel.t.Hard)
                        {
                            for (int j = 0; j < 6; j++)
                            {
                                Direction   dir        = DirectionExtensions.Directions[j];
                                Voxel.Coord adjacent   = c.Move(dir);
                                Voxel.t     adjacentID = map[adjacent].ID;
                                if (adjacentID == Voxel.t.HardInfected)
                                {
                                    map.Empty(adjacent, false, true, map);
                                    map.Fill(adjacent, Voxel.States.Hard);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal);
                                    regenerate = true;
                                }
                            }
                        }
                        else if (id == Voxel.t.Powered || id == Voxel.t.PermanentPowered || id == Voxel.t.HardPowered || id == Voxel.t.PoweredSwitch)
                        {
                            for (int j = 0; j < 6; j++)
                            {
                                Direction   dir        = DirectionExtensions.Directions[j];
                                Voxel.Coord adjacent   = c.Move(dir);
                                Voxel.t     adjacentID = map[adjacent].ID;

                                if (id == Voxel.t.Powered && adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations)
                                {
                                    map.Empty(adjacent, false, true, map);
                                    this.generations[new EffectBlock.Entry {
                                                         Voxel = map, Coordinate = adjacent
                                                     }] = entry.Generation + 1;
                                    map.Fill(adjacent, Voxel.States.Powered);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.Blue)
                                {
                                    map.Empty(adjacent, false, true, map);
                                    map.Fill(adjacent, Voxel.States.Powered);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.Switch)
                                {
                                    map.Empty(adjacent, true, true, map);
                                    map.Fill(adjacent, Voxel.States.PoweredSwitch);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.Hard)
                                {
                                    map.Empty(adjacent, true, true, map);
                                    map.Fill(adjacent, Voxel.States.HardPowered);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Normal);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.Critical)
                                {
                                    map.Empty(adjacent);
                                    regenerate = true;
                                }
                            }
                        }
                        else if (id == Voxel.t.Infected || id == Voxel.t.HardInfected)
                        {
                            for (int j = 0; j < 6; j++)
                            {
                                Direction   dir        = DirectionExtensions.Directions[j];
                                Voxel.Coord adjacent   = c.Move(dir);
                                Voxel.t     adjacentID = map[adjacent].ID;
                                if (adjacentID == Voxel.t.Neutral && entry.Generation < maxGenerations)
                                {
                                    map.Empty(adjacent, false, true, map);
                                    this.generations[new EffectBlock.Entry {
                                                         Voxel = map, Coordinate = adjacent
                                                     }] = entry.Generation + 1;
                                    map.Fill(adjacent, Voxel.States.Infected);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Dangerous);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.Hard && entry.Generation < maxGenerations)
                                {
                                    map.Empty(adjacent, false, true, map);
                                    this.generations[new EffectBlock.Entry {
                                                         Voxel = map, Coordinate = adjacent
                                                     }] = entry.Generation + 1;
                                    map.Fill(adjacent, Voxel.States.HardInfected);
                                    this.SparksLowPriority(map.GetAbsolutePosition(adjacent), Spark.Dangerous);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.Critical)
                                {
                                    map.Empty(adjacent);
                                    regenerate = true;
                                }
                            }
                        }

                        if (regenerate)
                        {
                            this.toRegenerate.Add(map);
                        }
                    }
                }
            }
            for (int i = 0; i < this.toRegenerate.Count; i++)
            {
                this.toRegenerate[i].Regenerate();
            }
            this.toRegenerate.Clear();
        }
Example #7
0
        public void Update(float dt)
        {
            if (this.TargetVoxel.Target == null || !this.TargetVoxel.Target.Active)
            {
                this.Delete.Execute();
                return;
            }

            this.Lifetime += dt;

            if (this.Lifetime < this.Delay)
            {
                return;
            }

            float blend = (this.Lifetime - this.Delay) / this.TotalLifetime;

            Voxel m = this.TargetVoxel.Target.Get <Voxel>();

            Matrix finalOrientation = m.Transform;

            finalOrientation.Translation = Vector3.Zero;
            Quaternion finalQuat = Quaternion.CreateFromRotationMatrix(finalOrientation);

            Vector3 finalPosition = m.GetAbsolutePosition(this.Coord);

            if (blend > 1.0f)
            {
                if (this.StateId != Voxel.t.Empty)
                {
                    Voxel.Coord c = this.Coord;

                    bool blue = this.StateId == Voxel.t.Blue;
                    bool foundAdjacentCell = false;
                    bool foundConflict     = false;
                    if (this.CheckAdjacent)
                    {
                        foreach (Direction dir in DirectionExtensions.Directions)
                        {
                            Voxel.Coord adjacent   = c.Move(dir);
                            Voxel.t     adjacentID = m[adjacent].ID;
                            if (adjacentID != Voxel.t.Empty)
                            {
                                if (blue && (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.HardInfected || adjacentID == Voxel.t.Slider || adjacentID == Voxel.t.SliderPowered || adjacentID == Voxel.t.SocketWhite || adjacentID == Voxel.t.SocketBlue || adjacentID == Voxel.t.SocketYellow))
                                {
                                    foundConflict = true;
                                }
                                else
                                {
                                    foundAdjacentCell = true;
                                    if (blue)
                                    {
                                        if (adjacentID == Voxel.t.Reset)
                                        {
                                            this.StateId = Voxel.t.Neutral;
                                            break;
                                        }
                                        else if (adjacentID == Voxel.t.Powered || adjacentID == Voxel.t.PermanentPowered || adjacentID == Voxel.t.PoweredSwitch || adjacentID == Voxel.t.HardPowered)
                                        {
                                            this.StateId = Voxel.t.Powered;
                                            break;
                                        }
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        foundAdjacentCell = true;
                    }

                    if (foundAdjacentCell)
                    {
                        Vector3 absolutePos = m.GetAbsolutePosition(c);

                        if (blue && !Zone.CanBuild(absolutePos))
                        {
                            foundConflict = true;
                        }

                        if (!foundConflict)
                        {
                            bool isDynamic = m.GetType() == typeof(DynamicVoxel);
                            foreach (Voxel m2 in Voxel.ActivePhysicsVoxels)
                            {
                                bool atLeastOneDynamic = isDynamic || m2.GetType() == typeof(DynamicVoxel);
                                if (m2 != m && atLeastOneDynamic && m2[absolutePos].ID != 0)
                                {
                                    foundConflict = true;
                                    break;
                                }
                            }
                        }

                        if (!foundConflict)
                        {
                            Voxel.State state = m[this.Coord];
                            if (state.Permanent || state.Hard || state.ID == this.StateId || (blue && state == Voxel.States.Powered))
                            {
                                foundConflict = true;
                            }
                            else
                            {
                                if (state.ID != 0)
                                {
                                    m.Empty(this.Coord);
                                }
                                m.Fill(this.Coord, Voxel.States.All[this.StateId]);
                                m.Regenerate();
                                if (EffectBlock.random.Next(0, 4) == 0)
                                {
                                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_BLOCK_BUILD, this.Entity);
                                }
                                this.Entity.Delete.Execute();
                                return;
                            }
                        }
                    }

                    // For one reason or another, we can't fill the cell
                    // Animate nicely into oblivion
                    this.StateId = Voxel.t.Empty;
                }
                else
                {
                    // For one reason or another, we can't fill the cell
                    // Animate nicely into oblivion
                    if (blend > 2.0f)
                    {
                        this.Delete.Execute();
                    }
                    else
                    {
                        Matrix result = Matrix.CreateFromQuaternion(finalQuat);
                        float  scale  = 2.0f - blend;
                        result.Right        *= scale;
                        result.Up           *= scale;
                        result.Forward      *= scale;
                        result.Translation   = finalPosition;
                        this.Transform.Value = result;
                    }
                }
            }
            else
            {
                float scale;
                if (this.DoScale)
                {
                    scale = blend;
                }
                else
                {
                    scale = 1.0f;
                }

                float distance = (finalPosition - this.StartPosition).Length() * 0.1f * Math.Max(0.0f, 0.5f - Math.Abs(blend - 0.5f));

                Matrix result = Matrix.CreateFromQuaternion(Quaternion.Lerp(this.StartOrientation, finalQuat, blend));
                result.Right        *= scale;
                result.Up           *= scale;
                result.Forward      *= scale;
                result.Translation   = Vector3.Lerp(this.StartPosition, finalPosition, blend) + new Vector3((float)Math.Sin(blend * Math.PI) * distance);
                this.Transform.Value = result;
            }
        }
Example #8
0
        public override void Awake()
        {
            base.Awake();

            Switch.all.Add(this);

            this.Add(new NotifyBinding(delegate()
            {
                if (this.On)
                {
                    this.OnPowerOn.Execute();
                }
                else
                {
                    this.OnPowerOff.Execute();
                }
            }, this.On));

            this.Add(new CommandBinding(this.OnPowerOff, delegate()
            {
                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_SWITCH_OFF, this.Entity);
            }));

            this.Add(new CommandBinding(this.OnPowerOn, delegate()
            {
                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_SWITCH_ON, this.Entity);
                Voxel map = this.AttachedVoxel.Value.Target.Get <Voxel>();
                List <Voxel.Coord> changes = new List <Voxel.Coord>();
                Stack <Voxel.Box> path     = new Stack <Voxel.Box>();
                Queue <Voxel.Coord> queue  = new Queue <Voxel.Coord>();
                foreach (Switch s in Switch.all)
                {
                    if (s.On && s != this && s.AttachedVoxel.Value.Target == this.AttachedVoxel.Value.Target &&
                        VoxelAStar.Broadphase(map, map.GetBox(this.Coord), s.Coord, canConnect, path, 2000))
                    {
                        Voxel.Coord start = s.Coord;
                        start.Data        = map[start];
                        queue.Enqueue(start);
                        while (queue.Count > 0)
                        {
                            Voxel.Coord c = queue.Dequeue();

                            c.Data = null;                             // Ensure the visited dictionary works correctly
                            Voxel.CoordDictionaryCache[c] = true;

                            Voxel.Coord change = c.Clone();
                            change.Data        = Voxel.States.Switch;
                            changes.Add(change);

                            foreach (Direction adjacentDirection in DirectionExtensions.Directions)
                            {
                                Voxel.Coord adjacentCoord = c.Move(adjacentDirection);
                                if (!Voxel.CoordDictionaryCache.ContainsKey(adjacentCoord))
                                {
                                    Voxel.State adjacentState = map[adjacentCoord];
                                    if (adjacentState == Voxel.States.PoweredSwitch)
                                    {
                                        queue.Enqueue(adjacentCoord);
                                    }
                                    else if ((adjacentState == Voxel.States.Blue || adjacentState == Voxel.States.Powered) &&
                                             path.Contains(map.GetBox(adjacentCoord)))
                                    {
                                        adjacentCoord.Data = Voxel.States.Neutral;
                                        changes.Add(adjacentCoord);
                                    }
                                }
                            }
                        }
                    }
                    path.Clear();
                    queue.Clear();
                }
                Voxel.CoordDictionaryCache.Clear();
                if (changes.Count > 0)
                {
                    lock (map.MutationLock)
                    {
                        map.Empty(changes, true, true, map);
                        map.Fill(changes);
                    }
                    map.Regenerate();
                }
            }));
        }
Example #9
0
        public override void Awake()
        {
            base.Awake();

            Switch.all.Add(this);

            this.Add(new NotifyBinding(delegate()
            {
                if (this.On)
                {
                    this.OnPowerOn.Execute();
                }
                else
                {
                    this.OnPowerOff.Execute();
                }
            }, this.On));

            this.Add(new CommandBinding(this.OnPowerOff, delegate()
            {
                if (this.main.TotalTime > 0.1f)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_SWITCH_OFF, this.Entity);
                }
            }));

            this.Add(new CommandBinding(this.OnPowerOn, delegate()
            {
                if (this.main.TotalTime > 0.1f && this.PowerOnCue != 0)
                {
                    AkSoundEngine.PostEvent(this.PowerOnCue, this.Entity);
                }
                Voxel map = this.AttachedVoxel.Value.Target.Get <Voxel>();

                Switch closestConnectedSwitch          = null;
                Stack <Voxel.Box> closestConnectedPath = null;

                foreach (Switch s in Switch.all)
                {
                    Stack <Voxel.Box> path = new Stack <Voxel.Box>();
                    if (s.On && s != this && s.AttachedVoxel.Value.Target == this.AttachedVoxel.Value.Target &&
                        VoxelAStar.Broadphase(map, map.GetBox(this.Coord), s.Coord, canConnect, path, 2000))
                    {
                        if (closestConnectedPath == null || path.Count < closestConnectedPath.Count)
                        {
                            closestConnectedSwitch = s;
                            closestConnectedPath   = path;
                        }
                    }
                }
                if (closestConnectedSwitch != null)
                {
                    List <Voxel.Coord> changes = new List <Voxel.Coord>();
                    Queue <Voxel.Coord> queue  = new Queue <Voxel.Coord>();
                    Voxel.Coord start          = closestConnectedSwitch.Coord;
                    start.Data = null;
                    queue.Enqueue(start);
                    Voxel.CoordSetCache.Add(start);

                    start.Data = Voxel.States.Switch;
                    changes.Add(start);
                    while (queue.Count > 0)
                    {
                        Voxel.Coord c = queue.Dequeue();

                        foreach (Direction adjacentDirection in DirectionExtensions.Directions)
                        {
                            Voxel.Coord adjacentCoord = c.Move(adjacentDirection);
                            if (!Voxel.CoordSetCache.Contains(adjacentCoord))
                            {
                                Voxel.CoordSetCache.Add(adjacentCoord);
                                Voxel.State adjacentState = map[adjacentCoord];
                                if (adjacentState == Voxel.States.PoweredSwitch)
                                {
                                    queue.Enqueue(adjacentCoord);

                                    adjacentCoord.Data = Voxel.States.Switch;
                                    changes.Add(adjacentCoord);
                                }
                                else if (adjacentState == Voxel.States.Hard)
                                {
                                    queue.Enqueue(adjacentCoord);
                                }
                                else if (adjacentState == Voxel.States.HardPowered)
                                {
                                    queue.Enqueue(adjacentCoord);

                                    adjacentCoord.Data = Voxel.States.Hard;
                                    changes.Add(adjacentCoord);
                                }
                                else if ((adjacentState == Voxel.States.Blue || adjacentState == Voxel.States.Powered) &&
                                         closestConnectedPath.Contains(map.GetBox(adjacentCoord)))
                                {
                                    adjacentCoord.Data = Voxel.States.Neutral;
                                    changes.Add(adjacentCoord);
                                    adjacentCoord.Data = null;
                                }
                            }
                        }
                    }
                    Voxel.CoordSetCache.Clear();
                    if (changes.Count > 0)
                    {
                        lock (map.MutationLock)
                        {
                            map.Empty(changes, true, true, map);
                            map.Fill(changes);
                        }
                        map.Regenerate();
                    }
                }
            }));
        }
Example #10
0
		public static bool Go(Voxel voxel, Voxel.Coord center, int radius, Action<List<DynamicVoxel>> callback = null)
		{
			if (!voxel[center].Permanent)
			{
				// Break off a chunk of this voxel into a new DynamicMap.

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

				Voxel.Coord ripStart = center.Move(-radius, -radius, -radius);
				Voxel.Coord ripEnd = center.Move(radius, radius, radius);

				Dictionary<Voxel.Box, bool> permanentBoxes = new Dictionary<Voxel.Box, bool>();
				foreach (Voxel.Coord c in ripStart.CoordinatesBetween(ripEnd))
				{
					Voxel.Box box = voxel.GetBox(c);
					if (box != null && box.Type.Permanent)
						permanentBoxes[box] = true;
				}

				foreach (Voxel.Box b in permanentBoxes.Keys)
				{
					// Top and bottom
					for (int x = b.X - 1; x <= b.X + b.Width; x++)
					{
						for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
						{
							Voxel.Coord coord = new Voxel.Coord { X = x, Y = b.Y + b.Height, Z = z };
							if (coord.Between(ripStart, ripEnd))
								edges.Add(coord);

							coord = new Voxel.Coord { X = x, Y = b.Y - 1, Z = z };
							if (coord.Between(ripStart, ripEnd))
								edges.Add(coord);
						}
					}

					// Outer shell
					for (int y = b.Y; y < b.Y + b.Height; y++)
					{
						// Left and right
						for (int z = b.Z - 1; z <= b.Z + b.Depth; z++)
						{
							Voxel.Coord coord = new Voxel.Coord { X = b.X - 1, Y = y, Z = z };
							if (coord.Between(ripStart, ripEnd))
								edges.Add(coord);

							coord = new Voxel.Coord { X = b.X + b.Width, Y = y, Z = z };
							if (coord.Between(ripStart, ripEnd))
								edges.Add(coord);
						}

						// Backward and forward
						for (int x = b.X; x < b.X + b.Width; x++)
						{
							Voxel.Coord coord = new Voxel.Coord { X = x, Y = y, Z = b.Z - 1 };
							if (coord.Between(ripStart, ripEnd))
								edges.Add(coord);

							coord = new Voxel.Coord { X = x, Y = y, Z = b.Z + b.Depth };
							if (coord.Between(ripStart, ripEnd))
								edges.Add(coord);
						}
					}
				}

				if (edges.Contains(center))
					return false;

				// Top and bottom
				for (int x = ripStart.X; x <= ripEnd.X; x++)
				{
					for (int z = ripStart.Z; z <= ripEnd.Z; z++)
					{
						Voxel.Coord c = new Voxel.Coord { X = x, Y = ripStart.Y, Z = z };
						Voxel.State s = voxel[c];
						if (s != Voxel.States.Empty && !s.Permanent)
							edges.Add(c);
						c = new Voxel.Coord { X = x, Y = ripEnd.Y, Z = z };
						s = voxel[c];
						if (s != Voxel.States.Empty && !s.Permanent)
							edges.Add(c);
					}
				}

				// Sides
				for (int y = ripStart.Y + 1; y <= ripEnd.Y - 1; y++)
				{
					// Left and right
					for (int z = ripStart.Z; z <= ripEnd.Z; z++)
					{
						Voxel.Coord c = new Voxel.Coord { X = ripStart.X, Y = y, Z = z };
						Voxel.State s = voxel[c];
						if (s != Voxel.States.Empty && !s.Permanent)
							edges.Add(c);
						c = new Voxel.Coord { X = ripEnd.X, Y = y, Z = z };
						s = voxel[c];
						if (s != Voxel.States.Empty && !s.Permanent)
							edges.Add(c);
					}

					// Backward and forward
					for (int x = ripStart.X; x <= ripEnd.X; x++)
					{
						Voxel.Coord c = new Voxel.Coord { X = x, Y = y, Z = ripStart.Z };
						Voxel.State s = voxel[c];
						if (s != Voxel.States.Empty && !s.Permanent)
							edges.Add(c);
						c = new Voxel.Coord { X = x, Y = y, Z = ripEnd.Z };
						s = voxel[c];
						if (s != Voxel.States.Empty && !s.Permanent)
							edges.Add(c);
					}
				}

				Propagator p = WorldFactory.Instance.Get<Propagator>();
				foreach (Voxel.Coord c in edges)
					p.SparksLowPriority(voxel.GetAbsolutePosition(c), Propagator.Spark.Dangerous);

				voxel.Empty(edges);

				voxel.Regenerate(callback);
				return true;
			}
			return false;
		}
Example #11
0
        private void fall()
        {
            if (this.TimeUntilRebuild.Value > 0 || this.TimeUntilRebuildComplete.Value > 0)
            {
                return;
            }

            Entity targetVoxel = this.TargetVoxel.Value.Target;

            if (targetVoxel == null || !targetVoxel.Active)
            {
                return;
            }

            // Disable the cell-emptied notification.
            // This way, we won't think that the base has been destroyed by the player.
            // We are not in fact dying, we're just destroying the base so we can fall over.
            this.Base.EnableCellEmptyBinding = false;

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

            m.Empty(this.Base.BaseBoxes.SelectMany(x => x.GetCoords()));
            Vector3 basePosition = Vector3.Zero;
            int     baseSize     = 0;

            foreach (Voxel.Coord c in this.Base.BaseBoxes.SelectMany(x => x.GetCoords()))
            {
                ParticleSystem shatter = ParticleSystem.Get(main, "InfectedShatter");
                Vector3        pos     = m.GetAbsolutePosition(c);
                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);
                }
                basePosition += pos;
                baseSize++;
            }
            basePosition /= (float)baseSize;
            Sound.PostEvent(AK.EVENTS.PLAY_TOWER_FALL, basePosition);

            m.Regenerate(delegate(List <DynamicVoxel> spawnedMaps)
            {
                if (spawnedMaps.Count == 0)
                {
                    this.Delete.Execute();
                }
                else
                {
                    Vector3 playerPos = PlayerFactory.Instance.Get <Transform>().Position;
                    playerPos        += PlayerFactory.Instance.Get <Player>().Character.LinearVelocity.Value * 0.65f;
                    foreach (DynamicVoxel newMap in spawnedMaps)
                    {
                        newMap.Dangerous.Value = true;
                        Vector3 toPlayer       = playerPos - newMap.PhysicsEntity.Position;
                        toPlayer.Normalize();
                        if (Math.Abs(toPlayer.Y) < 0.9f)
                        {
                            toPlayer *= 25.0f * newMap.PhysicsEntity.Mass;

                            Vector3 positionAtPlayerHeight = newMap.PhysicsEntity.Position;
                            Vector3 impulseAtBase          = toPlayer * -0.75f;
                            impulseAtBase.Y          = 0.0f;
                            positionAtPlayerHeight.Y = playerPos.Y;
                            newMap.PhysicsEntity.ApplyImpulse(ref positionAtPlayerHeight, ref impulseAtBase);

                            newMap.PhysicsEntity.ApplyLinearImpulse(ref toPlayer);
                        }
                        newMap.PhysicsEntity.Material.KineticFriction = 1.0f;
                        newMap.PhysicsEntity.Material.StaticFriction  = 1.0f;
                        this.DynamicVoxels.Add(newMap.Entity);
                    }
                }
            });

            this.TimeUntilRebuild.Value = RebuildDelay;
        }