Exemplo n.º 1
0
 private IEnumerable <Voxel.Coord> spreadFromCenter(Voxel.Coord center, Direction dir)
 {
     for (Voxel.Coord z = center.Move(dir, -1); z.GetComponent(dir) > center.GetComponent(dir) - 3; z = z.Move(dir.GetReverse()))
     {
         yield return(z);
     }
     for (Voxel.Coord z = center.Clone(); z.GetComponent(dir) < center.GetComponent(dir) + 3; z = z.Move(dir))
     {
         yield return(z);
     }
 }
Exemplo n.º 2
0
 public override void Awake()
 {
     base.Awake();
     AkGameObjectTracker.Attach(this.Entity, this.Position);
     this.particles         = ParticleSystem.Get(this.main, "Rift");
     this.EnabledInEditMode = false;
     this.EnabledWhenPaused = false;
     this.Add(new CommandBinding(this.Enable, delegate()
     {
         if (this.Coords.Length == 0)
         {
             AkSoundEngine.PostEvent(AK.EVENTS.PLAY_RIFT_OPEN, this.Entity);
             if (PlayerFactory.Instance != null)
             {
                 PlayerFactory.Instance.Get <CameraController>().Shake.Execute(this.Position, 30.0f);
             }
             Entity voxelEntity = this.Voxel.Value.Target;
             if (voxelEntity != null && voxelEntity.Active)
             {
                 Voxel v            = voxelEntity.Get <Voxel>();
                 Voxel.Coord center = this.Coordinate;
                 Vector3 pos        = v.GetRelativePosition(center);
                 int radius         = this.Radius;
                 List <VoxelFill.CoordinateEntry> coords = Rift.coordSortCache;
                 for (Voxel.Coord x = center.Move(Direction.NegativeX, radius); x.X < center.X + radius; x.X++)
                 {
                     for (Voxel.Coord y = x.Move(Direction.NegativeY, radius); y.Y < center.Y + radius; y.Y++)
                     {
                         for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius); z.Z < center.Z + radius; z.Z++)
                         {
                             float distance = (pos - v.GetRelativePosition(z)).Length();
                             if (distance <= radius && v[z] != Components.Voxel.States.Empty)
                             {
                                 coords.Add(new VoxelFill.CoordinateEntry {
                                     Coord = z.Clone(), Distance = distance
                                 });
                             }
                         }
                     }
                 }
                 coords.Sort(new LambdaComparer <VoxelFill.CoordinateEntry>((x, y) => x.Distance.CompareTo(y.Distance)));
                 this.Coords.AddAll(coords.Select(x => x.Coord));
                 coords.Clear();
             }
         }
     }));
     rifts.Add(this);
 }
Exemplo n.º 3
0
 private void go()
 {
     if (this.Coords.Length == 0)
     {
         AkSoundEngine.PostEvent(AK.EVENTS.PLAY_RIFT_OPEN, this.Entity);
         if (PlayerFactory.Instance != null)
         {
             PlayerFactory.Instance.Get <CameraController>().Shake.Execute(this.Position, 30.0f);
         }
         Entity voxelEntity = this.Voxel.Value.Target;
         if (voxelEntity != null && voxelEntity.Active)
         {
             Voxel       v      = voxelEntity.Get <Voxel>();
             Voxel.Coord center = this.Coordinate;
             Vector3     pos    = v.GetRelativePosition(center);
             int         radius = this.Radius;
             List <VoxelFill.CoordinateEntry> coords = Rift.coordSortCache;
             for (Voxel.Coord x = center.Move(Direction.NegativeX, radius); x.X < center.X + radius; x.X++)
             {
                 for (Voxel.Coord y = x.Move(Direction.NegativeY, radius); y.Y < center.Y + radius; y.Y++)
                 {
                     for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius); z.Z < center.Z + radius; z.Z++)
                     {
                         float distance = (pos - v.GetRelativePosition(z)).Length();
                         if (distance <= radius && v[z] != Components.Voxel.States.Empty)
                         {
                             coords.Add(new VoxelFill.CoordinateEntry {
                                 Coord = z.Clone(), Distance = distance
                             });
                         }
                     }
                 }
             }
             if (coords.Count == 0)
             {
                 this.Entity.Delete.Execute();
             }
             else
             {
                 coords.Sort(new LambdaComparer <VoxelFill.CoordinateEntry>((x, y) => x.Distance.CompareTo(y.Distance)));
                 this.Coords.AddAll(coords.Select(x => x.Coord));
                 coords.Clear();
             }
         }
     }
 }
Exemplo n.º 4
0
        private void updatePower()
        {
            Entity v       = this.AttachedVoxel.Value.Target;
            bool   powered = false;

            if (v != null)
            {
                Voxel       voxel = v.Get <Voxel>();
                Voxel.Coord coord = this.Coord;
                for (int i = 0; i < 6; i++)
                {
                    Direction dir = DirectionExtensions.Directions[i];
                    if (voxel[coord.Move(dir)].ID == this.Type)
                    {
                        powered = true;
                        break;
                    }
                }
            }
            this.Powered.Value = powered;
        }
Exemplo n.º 5
0
        public void BuildFloor(Voxel floorMap, Voxel.Coord floorCoordinate, Direction forwardDir, Direction rightDir)
        {
            List <EffectBlockFactory.BlockBuildOrder> buildCoords = new List <EffectBlockFactory.BlockBuildOrder>();

            Voxel.Coord newFloorCoordinate = floorMap.GetCoordinate(this.Position);
            floorCoordinate.SetComponent(rightDir, newFloorCoordinate.GetComponent(rightDir));
            floorCoordinate.SetComponent(forwardDir, newFloorCoordinate.GetComponent(forwardDir));
            Direction upDir = floorMap.GetRelativeDirection(Direction.PositiveY);

            const int radius = 3;

            foreach (Voxel.Coord x in this.spreadFromCenter(floorCoordinate, rightDir))
            {
                if (floorMap[x.Move(upDir)].Hard)
                {
                    break;
                }
                int dx = x.GetComponent(rightDir) - floorCoordinate.GetComponent(rightDir);
                for (Voxel.Coord y = x.Move(forwardDir, -radius); y.GetComponent(forwardDir) < floorCoordinate.GetComponent(forwardDir) + radius; y = y.Move(forwardDir))
                {
                    if (floorMap[y.Move(upDir)].Hard)
                    {
                        break;
                    }
                    int dy = y.GetComponent(forwardDir) - floorCoordinate.GetComponent(forwardDir);
                    if ((float)Math.Sqrt(dx * dx + dy * dy) < radius && floorMap[y].ID == 0)
                    {
                        buildCoords.Add(new EffectBlockFactory.BlockBuildOrder
                        {
                            Voxel      = floorMap,
                            Coordinate = y,
                            State      = Voxel.States.Blue,
                        });
                    }
                }
            }
            Factory.Get <EffectBlockFactory>().Build(this.main, buildCoords, this.Position);
        }
Exemplo n.º 6
0
        // Classic 3D perlin noise
        float noise3d(Vector3 pos)
        {
            Voxel.Coord cell = new Voxel.Coord {
                X = (int)Math.Floor(pos.X) & 255, Y = (int)Math.Floor(pos.Y) & 255, Z = (int)Math.Floor(pos.Z) & 255
            };

            pos.X = pos.X % 256;
            pos.Y = pos.Y % 256;
            pos.Z = pos.Z % 256;
            Vector3 withinCell = pos - new Vector3(cell.X, cell.Y, cell.Z);

            // Calculate contribution of gradients from each cell
            float contribution000 = Vector3.Dot(this.gradientAtCell3d(cell), withinCell);
            float contribution001 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 0, 1)), withinCell - new Vector3(0, 0, 1));
            float contribution010 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 1, 0)), withinCell - new Vector3(0, 1, 0));
            float contribution011 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 1, 1)), withinCell - new Vector3(0, 1, 1));
            float contribution100 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 0, 0)), withinCell - new Vector3(1, 0, 0));
            float contribution101 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 0, 1)), withinCell - new Vector3(1, 0, 1));
            float contribution110 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 1, 0)), withinCell - new Vector3(1, 1, 0));
            float contribution111 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 1, 1)), withinCell - new Vector3(1, 1, 1));

            Vector3 blend = new Vector3(blendCurve(withinCell.X), blendCurve(withinCell.Y), blendCurve(withinCell.Z));

            // Interpolate along X
            float contribution00 = lerp(contribution000, contribution100, blend.X);
            float contribution01 = lerp(contribution001, contribution101, blend.X);
            float contribution10 = lerp(contribution010, contribution110, blend.X);
            float contribution11 = lerp(contribution011, contribution111, blend.X);

            // Interpolate along Y
            float contribution0 = lerp(contribution00, contribution10, blend.Y);
            float contribution1 = lerp(contribution01, contribution11, blend.Y);

            // Interpolate along Z
            return(lerp(contribution0, contribution1, blend.Z));
        }
Exemplo n.º 7
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();
        }
Exemplo n.º 8
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);
        }
Exemplo n.º 9
0
        private static void explode(Main main, Voxel map, Voxel.Coord coord, Vector3 pos, int radius, float physicsRadius)
        {
            float distanceToCamera = (main.Camera.Position.Value - pos).Length();

            // Kaboom
            Sound.PostEvent(distanceToCamera < physicsRadius * 1.5f ? AK.EVENTS.PLAY_EXPLOSION_CLOSE : AK.EVENTS.PLAY_EXPLOSION, pos);

            Entity lightEntity = Factory.Get <PointLightFactory>().CreateAndBind(main);

            lightEntity.Serialize = false;
            PointLight light = lightEntity.Get <PointLight>();

            light.Color.Value       = new Vector3(1.3f, 1.1f, 0.9f);
            light.Attenuation.Value = 20.0f;
            light.Position.Value    = pos;
            lightEntity.Add(new Animation
                            (
                                new Animation.FloatMoveTo(light.Attenuation, 0.0f, 1.0f),
                                new Animation.Execute(light.Delete)
                            ));
            main.Add(lightEntity);

            SmokeFactory smokeFactory = Factory.Get <SmokeFactory>();

            for (int i = 0; i < 5; i++)
            {
                Entity smoke = smokeFactory.CreateAndBind(main);
                smoke.Get <Transform>().Position.Value = pos;
                main.Add(smoke);
            }

            ParticleEmitter.Emit(main, "Smoke", pos, physicsRadius * 0.4f, 250);

            Entity player = PlayerFactory.Instance;

            if (player != null && player.Active)
            {
                player.Get <CameraController>().Shake.Execute(pos, 50.0f);
            }

            const float physicsImpulse         = 70.0f;
            const float minPlayerDamage        = 0.1f;
            const float playerDamageMultiplier = 2.0f;

            // Remove the cells
            BlockFactory blockFactory = Factory.Get <BlockFactory>();

            foreach (Voxel m in Voxel.ActiveVoxels.ToList())
            {
                List <Voxel.Coord> removals = new List <Voxel.Coord>();

                Voxel.Coord c           = m.GetCoordinate(pos);
                Vector3     relativePos = m.GetRelativePosition(c);

                Quaternion quat = m.Entity.Get <Transform>().Quaternion;

                for (Voxel.Coord x = c.Move(Direction.NegativeX, radius - 1); x.X < c.X + radius; x.X++)
                {
                    for (Voxel.Coord y = x.Move(Direction.NegativeY, radius - 1); y.Y < c.Y + radius; y.Y++)
                    {
                        for (Voxel.Coord z = y.Move(Direction.NegativeZ, radius - 1); z.Z < c.Z + radius; z.Z++)
                        {
                            Voxel.State s = m[z];
                            if (s.ID == 0 || s.Permanent)
                            {
                                continue;
                            }

                            Vector3 cellPos = m.GetRelativePosition(z);
                            if ((cellPos - relativePos).Length() < radius - 1)
                            {
                                removals.Add(z);
                                if (random.NextDouble() > 0.5)
                                {
                                    Entity    block          = blockFactory.CreateAndBind(main);
                                    Transform blockTransform = block.Get <Transform>();
                                    blockTransform.Position.Value   = m.GetAbsolutePosition(cellPos);
                                    blockTransform.Quaternion.Value = Quaternion.CreateFromYawPitchRoll(((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI, ((float)random.NextDouble() - 0.5f) * 2.0f * (float)Math.PI);
                                    s.ApplyToBlock(block);
                                    main.Add(block);
                                }
                            }
                        }
                    }
                }
                if (removals.Count > 0)
                {
                    m.Empty(removals);
                    m.Regenerate();
                }
            }

            // Damage the player
            if (player != null && player.Active)
            {
                Vector3 toPlayer = player.Get <Transform>().Position - pos;
                float   d        = toPlayer.Length();
                if (d < physicsRadius)
                {
                    float attenuation = 1.0f;
                    if (d > 0)
                    {
                        Voxel.GlobalRaycast(pos, toPlayer / d, d, delegate(int x, Voxel.t c)
                        {
                            Voxel.State s = Voxel.States.All[c];
                            if (s.Permanent)
                            {
                                attenuation = 0.0f;
                                return(true);
                            }
                            else if (s.Hard)
                            {
                                attenuation -= 0.6f;
                            }
                            else
                            {
                                attenuation -= 0.35f;
                            }
                            return(false);
                        });
                        attenuation = Math.Max(0, attenuation);
                    }
                    player.Get <Agent>().Damage.Execute(attenuation * (minPlayerDamage + (1.0f - (d / physicsRadius)) * playerDamageMultiplier));
                }
            }

            // Apply impulse to dynamic maps
            foreach (Voxel m in Voxel.ActiveVoxels)
            {
                DynamicVoxel dm = m as DynamicVoxel;
                if (dm == null)
                {
                    continue;
                }

                Vector3 toMap         = dm.Transform.Value.Translation - pos;
                float   distanceToMap = toMap.Length();
                toMap /= distanceToMap;

                toMap *= Math.Max(0.0f, 1.0f - (distanceToMap / physicsRadius)) * Math.Min(200.0f, dm.PhysicsEntity.Mass) * physicsImpulse;

                dm.PhysicsEntity.ApplyImpulse(dm.Transform.Value.Translation + new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f), toMap);
            }

            // Apply impulse to physics blocks
            foreach (Entity b in main.Get("Block"))
            {
                PhysicsBlock block         = b.Get <PhysicsBlock>();
                Vector3      fromExplosion = b.Get <Transform>().Position.Value - pos;
                float        distance      = fromExplosion.Length();
                if (distance > 0.0f && distance < physicsRadius)
                {
                    float blend = 1.0f - (distance / physicsRadius);
                    block.Box.LinearVelocity  += fromExplosion * blend * 10.0f / distance;
                    block.Box.AngularVelocity += new Vector3(((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f, ((float)random.NextDouble() - 0.5f) * 2.0f) * blend;
                }
            }
        }
Exemplo n.º 10
0
        public override void Bind(Entity entity, Main main, bool creating = false)
        {
            if (ParticleSystem.Get(main, "SnakeSparks") == null)
            {
                ParticleSystem.Add(main, "SnakeSparks",
                                   new ParticleSystem.ParticleSettings
                {
                    TextureName           = "Particles\\splash",
                    MaxParticles          = 1000,
                    Duration              = TimeSpan.FromSeconds(1.0f),
                    MinHorizontalVelocity = -7.0f,
                    MaxHorizontalVelocity = 7.0f,
                    MinVerticalVelocity   = 0.0f,
                    MaxVerticalVelocity   = 7.0f,
                    Gravity        = new Vector3(0.0f, -10.0f, 0.0f),
                    MinRotateSpeed = -2.0f,
                    MaxRotateSpeed = 2.0f,
                    MinStartSize   = 0.3f,
                    MaxStartSize   = 0.7f,
                    MinEndSize     = 0.0f,
                    MaxEndSize     = 0.0f,
                    BlendState     = Microsoft.Xna.Framework.Graphics.BlendState.AlphaBlend,
                    MinColor       = new Vector4(2.0f, 2.0f, 2.0f, 1.0f),
                    MaxColor       = new Vector4(2.0f, 2.0f, 2.0f, 1.0f),
                });
                ParticleSystem.Add(main, "SnakeSparksRed",
                                   new ParticleSystem.ParticleSettings
                {
                    TextureName           = "Particles\\splash",
                    MaxParticles          = 1000,
                    Duration              = TimeSpan.FromSeconds(1.0f),
                    MinHorizontalVelocity = -7.0f,
                    MaxHorizontalVelocity = 7.0f,
                    MinVerticalVelocity   = 0.0f,
                    MaxVerticalVelocity   = 7.0f,
                    Gravity        = new Vector3(0.0f, -10.0f, 0.0f),
                    MinRotateSpeed = -2.0f,
                    MaxRotateSpeed = 2.0f,
                    MinStartSize   = 0.3f,
                    MaxStartSize   = 0.7f,
                    MinEndSize     = 0.0f,
                    MaxEndSize     = 0.0f,
                    BlendState     = Microsoft.Xna.Framework.Graphics.BlendState.AlphaBlend,
                    MinColor       = new Vector4(1.4f, 0.8f, 0.7f, 1.0f),
                    MaxColor       = new Vector4(1.4f, 0.8f, 0.7f, 1.0f),
                });
                ParticleSystem.Add(main, "SnakeSparksYellow",
                                   new ParticleSystem.ParticleSettings
                {
                    TextureName           = "Particles\\splash",
                    MaxParticles          = 1000,
                    Duration              = TimeSpan.FromSeconds(1.0f),
                    MinHorizontalVelocity = -7.0f,
                    MaxHorizontalVelocity = 7.0f,
                    MinVerticalVelocity   = 0.0f,
                    MaxVerticalVelocity   = 7.0f,
                    Gravity        = new Vector3(0.0f, -10.0f, 0.0f),
                    MinRotateSpeed = -2.0f,
                    MaxRotateSpeed = 2.0f,
                    MinStartSize   = 0.3f,
                    MaxStartSize   = 0.7f,
                    MinEndSize     = 0.0f,
                    MaxEndSize     = 0.0f,
                    BlendState     = Microsoft.Xna.Framework.Graphics.BlendState.AlphaBlend,
                    MinColor       = new Vector4(1.4f, 1.4f, 0.7f, 1.0f),
                    MaxColor       = new Vector4(1.4f, 1.4f, 0.7f, 1.0f),
                });
            }

            Snake snake = entity.GetOrCreate <Snake>("Snake");

            entity.CannotSuspendByDistance = true;
            Transform transform = entity.GetOrCreate <Transform>("Transform");

            AI ai = entity.GetOrCreate <AI>("AI");

            Agent agent = entity.GetOrCreate <Agent>("Agent");

            const float defaultSpeed    = 5.0f;
            const float chaseSpeed      = 18.0f;
            const float closeChaseSpeed = 12.0f;
            const float crushSpeed      = 125.0f;

            VoxelChaseAI chase = entity.GetOrCreate <VoxelChaseAI>("VoxelChaseAI");

            chase.Add(new TwoWayBinding <Vector3>(transform.Position, chase.Position));
            chase.Speed.Value             = defaultSpeed;
            chase.EnablePathfinding.Value = ai.CurrentState.Value == "Chase";
            chase.Filter = delegate(Voxel.State state)
            {
                if (state == Voxel.States.Infected || state == Voxel.States.Neutral || state == Voxel.States.Hard || state == Voxel.States.HardInfected)
                {
                    return(true);
                }
                return(false);
            };
            entity.Add(new CommandBinding(chase.Delete, entity.Delete));

            PointLight positionLight = null;

            if (!main.EditorEnabled)
            {
                positionLight                   = new PointLight();
                positionLight.Serialize         = false;
                positionLight.Color.Value       = new Vector3(1.5f, 0.5f, 0.5f);
                positionLight.Attenuation.Value = 20.0f;
                positionLight.Add(new Binding <bool, string>(positionLight.Enabled, x => x != "Suspended", ai.CurrentState));
                positionLight.Add(new Binding <Vector3, string>(positionLight.Color, delegate(string state)
                {
                    switch (state)
                    {
                    case "Chase":
                    case "Crush":
                        return(new Vector3(1.5f, 0.5f, 0.5f));

                    case "Alert":
                        return(new Vector3(1.5f, 1.5f, 0.5f));

                    default:
                        return(new Vector3(1.0f, 1.0f, 1.0f));
                    }
                }, ai.CurrentState));
                entity.Add("PositionLight", positionLight);
                ParticleEmitter emitter = entity.GetOrCreate <ParticleEmitter>("Particles");
                emitter.Serialize = false;
                emitter.ParticlesPerSecond.Value = 100;
                emitter.Add(new Binding <string>(emitter.ParticleType, delegate(string state)
                {
                    switch (state)
                    {
                    case "Chase":
                    case "Crush":
                        return("SnakeSparksRed");

                    case "Alert":
                        return("SnakeSparksYellow");

                    default:
                        return("SnakeSparks");
                    }
                }, ai.CurrentState));
                emitter.Add(new Binding <Vector3>(emitter.Position, transform.Position));
                emitter.Add(new Binding <bool, string>(emitter.Enabled, x => x != "Suspended", ai.CurrentState));

                positionLight.Add(new Binding <Vector3>(positionLight.Position, transform.Position));
                emitter.Add(new Binding <Vector3>(emitter.Position, transform.Position));
                agent.Add(new Binding <Vector3>(agent.Position, transform.Position));
                Sound.AttachTracker(entity);
            }

            AI.Task checkMap = new AI.Task
            {
                Action = delegate()
                {
                    if (chase.Voxel.Value.Target == null || !chase.Voxel.Value.Target.Active)
                    {
                        entity.Delete.Execute();
                    }
                },
            };

            AI.Task checkOperationalRadius = new AI.Task
            {
                Interval = 2.0f,
                Action   = delegate()
                {
                    bool shouldBeActive = (transform.Position.Value - main.Camera.Position).Length() < snake.OperationalRadius;
                    if (shouldBeActive && ai.CurrentState == "Suspended")
                    {
                        ai.CurrentState.Value = "Idle";
                    }
                    else if (!shouldBeActive && ai.CurrentState != "Suspended")
                    {
                        ai.CurrentState.Value = "Suspended";
                    }
                },
            };

            AI.Task checkTargetAgent = new AI.Task
            {
                Action = delegate()
                {
                    Entity target = ai.TargetAgent.Value.Target;
                    if (target == null || !target.Active)
                    {
                        ai.TargetAgent.Value  = null;
                        ai.CurrentState.Value = "Idle";
                    }
                },
            };

            Func <Voxel, Direction> randomValidDirection = delegate(Voxel m)
            {
                Voxel.Coord c    = chase.Coord;
                Direction[] dirs = new Direction[6];
                Array.Copy(DirectionExtensions.Directions, dirs, 6);

                // Shuffle directions
                int i = 5;
                while (i > 0)
                {
                    int       k    = this.random.Next(i);
                    Direction temp = dirs[i];
                    dirs[i] = dirs[k];
                    dirs[k] = temp;
                    i--;
                }

                foreach (Direction dir in dirs)
                {
                    if (chase.Filter(m[c.Move(dir)]))
                    {
                        return(dir);
                    }
                }
                return(Direction.None);
            };

            Direction currentDir = Direction.None;

            chase.Add(new CommandBinding <Voxel, Voxel.Coord>(chase.Moved, delegate(Voxel m, Voxel.Coord c)
            {
                if (chase.Active)
                {
                    string currentState = ai.CurrentState.Value;
                    Voxel.t id          = m[c].ID;
                    if (id == Voxel.t.Hard)
                    {
                        m.Empty(c);
                        m.Fill(c, Voxel.States.HardInfected);
                        m.Regenerate();
                    }
                    else if (id == Voxel.t.Neutral)
                    {
                        m.Empty(c);
                        m.Fill(c, Voxel.States.Infected);
                        m.Regenerate();
                    }
                    else if (id == Voxel.t.Empty)
                    {
                        m.Fill(c, Voxel.States.Infected);
                        m.Regenerate();
                    }

                    if (currentState == "Idle")
                    {
                        if (currentDir == Direction.None || !chase.Filter(m[chase.Coord.Value.Move(currentDir)]) || this.random.Next(8) == 0)
                        {
                            currentDir = randomValidDirection(m);
                        }
                        chase.Coord.Value = chase.Coord.Value.Move(currentDir);
                    }
                    else if (snake.Path.Length > 0)
                    {
                        chase.Coord.Value = snake.Path[0];
                        snake.Path.RemoveAt(0);
                    }
                }
            }));

            Sound.AttachTracker(entity);
            SoundKiller.Add(entity, AK.EVENTS.STOP_SNAKE);
            ai.Add(new ChangeBinding <string>(ai.CurrentState, delegate(string old, string value)
            {
                if (value == "Suspended" || value == "Alert")
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.STOP_SNAKE, entity);
                }
                else if (old != "Idle" && old != "Chase" && old != "Crush")
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_SNAKE, entity);
                }
            }));

            const float sightDistance   = 50.0f;
            const float hearingDistance = 0.0f;

            ai.Setup
            (
                new AI.AIState
            {
                Name  = "Suspended",
                Tasks = new[] { checkOperationalRadius },
            },
                new AI.AIState
            {
                Name  = "Idle",
                Enter = delegate(AI.AIState previous)
                {
                    Entity voxelEntity = chase.Voxel.Value.Target;
                    if (voxelEntity != null)
                    {
                        Voxel m = voxelEntity.Get <Voxel>();
                        if (currentDir == Direction.None || !chase.Filter(m[chase.Coord.Value.Move(currentDir)]))
                        {
                            currentDir = randomValidDirection(m);
                        }
                        chase.Coord.Value = chase.Coord.Value.Move(currentDir);
                    }
                },
                Tasks = new[]
                {
                    checkMap,
                    checkOperationalRadius,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action   = delegate()
                        {
                            Agent a = Agent.Query(transform.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                            if (a != null)
                            {
                                ai.CurrentState.Value = "Alert";
                            }
                        },
                    },
                },
            },
                new AI.AIState
            {
                Name  = "Alert",
                Enter = delegate(AI.AIState previous)
                {
                    chase.EnableMovement.Value = false;
                },
                Exit = delegate(AI.AIState next)
                {
                    chase.EnableMovement.Value = true;
                },
                Tasks = new[]
                {
                    checkMap,
                    checkOperationalRadius,
                    new AI.Task
                    {
                        Interval = 0.4f,
                        Action   = delegate()
                        {
                            if (ai.TimeInCurrentState > 3.0f)
                            {
                                ai.CurrentState.Value = "Idle";
                            }
                            else
                            {
                                Agent a = Agent.Query(transform.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                                if (a != null)
                                {
                                    ai.TargetAgent.Value  = a.Entity;
                                    ai.CurrentState.Value = "Chase";
                                }
                            }
                        },
                    },
                },
            },
                new AI.AIState
            {
                Name  = "Chase",
                Enter = delegate(AI.AIState previousState)
                {
                    chase.EnablePathfinding.Value = true;
                    chase.Speed.Value             = chaseSpeed;
                },
                Exit = delegate(AI.AIState nextState)
                {
                    chase.EnablePathfinding.Value = false;
                    chase.Speed.Value             = defaultSpeed;
                },
                Tasks = new[]
                {
                    checkMap,
                    checkOperationalRadius,
                    checkTargetAgent,
                    new AI.Task
                    {
                        Interval = 0.07f,
                        Action   = delegate()
                        {
                            Vector3 targetPosition = ai.TargetAgent.Value.Target.Get <Agent>().Position;

                            float targetDistance = (targetPosition - transform.Position).Length();

                            chase.Speed.Value = targetDistance < 15.0f ? closeChaseSpeed : chaseSpeed;

                            if (targetDistance > 50.0f || ai.TimeInCurrentState > 30.0f)                                     // He got away
                            {
                                ai.CurrentState.Value = "Alert";
                            }
                            else if (targetDistance < 4.0f)                                     // We got 'im
                            {
                                // First, make sure we're not near a reset block
                                Voxel v = chase.Voxel.Value.Target.Get <Voxel>();
                                if (VoxelAStar.BroadphaseSearch(v, chase.Coord, 6, x => x.Type == Lemma.Components.Voxel.States.Reset) == null)
                                {
                                    ai.CurrentState.Value = "Crush";
                                }
                            }
                            else
                            {
                                chase.Target.Value = targetPosition;
                            }
                        },
                    },
                },
            },
                new AI.AIState
            {
                Name  = "Crush",
                Enter = delegate(AI.AIState lastState)
                {
                    // Set up cage
                    Voxel.Coord center = chase.Voxel.Value.Target.Get <Voxel>().GetCoordinate(ai.TargetAgent.Value.Target.Get <Agent>().Position);

                    int radius = 1;

                    // Bottom
                    for (int x = center.X - radius; x <= center.X + radius; x++)
                    {
                        for (int z = center.Z - radius; z <= center.Z + radius; z++)
                        {
                            snake.Path.Add(new Voxel.Coord {
                                X = x, Y = center.Y - 4, Z = z
                            });
                        }
                    }

                    // Outer shell
                    radius = 2;
                    for (int y = center.Y - 3; y <= center.Y + 3; y++)
                    {
                        // Left
                        for (int z = center.Z - radius; z <= center.Z + radius; z++)
                        {
                            snake.Path.Add(new Voxel.Coord {
                                X = center.X - radius, Y = y, Z = z
                            });
                        }

                        // Right
                        for (int z = center.Z - radius; z <= center.Z + radius; z++)
                        {
                            snake.Path.Add(new Voxel.Coord {
                                X = center.X + radius, Y = y, Z = z
                            });
                        }

                        // Backward
                        for (int x = center.X - radius; x <= center.X + radius; x++)
                        {
                            snake.Path.Add(new Voxel.Coord {
                                X = x, Y = y, Z = center.Z - radius
                            });
                        }

                        // Forward
                        for (int x = center.X - radius; x <= center.X + radius; x++)
                        {
                            snake.Path.Add(new Voxel.Coord {
                                X = x, Y = y, Z = center.Z + radius
                            });
                        }
                    }

                    // Top
                    for (int x = center.X - radius; x <= center.X + radius; x++)
                    {
                        for (int z = center.Z - radius; z <= center.Z + radius; z++)
                        {
                            snake.Path.Add(new Voxel.Coord {
                                X = x, Y = center.Y + 3, Z = z
                            });
                        }
                    }

                    chase.EnablePathfinding.Value = false;
                    chase.Speed.Value             = crushSpeed;

                    snake.CrushCoordinate.Value = chase.Coord;
                },
                Exit = delegate(AI.AIState nextState)
                {
                    chase.Speed.Value = defaultSpeed;
                    chase.Coord.Value = chase.LastCoord.Value = snake.CrushCoordinate;
                    snake.Path.Clear();
                },
                Tasks = new[]
                {
                    checkMap,
                    checkOperationalRadius,
                    checkTargetAgent,
                    new AI.Task
                    {
                        Interval = 0.01f,
                        Action   = delegate()
                        {
                            Agent a = ai.TargetAgent.Value.Target.Get <Agent>();
                            a.Damage.Execute(0.01f / 1.5f);                                     // seconds to kill
                            if (!a.Active)
                            {
                                ai.CurrentState.Value = "Alert";
                            }
                            else
                            {
                                if ((a.Position - transform.Position.Value).Length() > 5.0f)                                         // They're getting away
                                {
                                    ai.CurrentState.Value = "Chase";
                                }
                            }
                        }
                    }
                },
            }
            );

            this.SetMain(entity, main);

            entity.Add("OperationalRadius", snake.OperationalRadius);
        }
Exemplo n.º 11
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);
        }
Exemplo n.º 12
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);
				lock (voxel.MutationLock)
				{
					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;
				lock (voxel.MutationLock)
					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();
			}
		}
Exemplo n.º 13
0
        public override void Bind(Entity entity, Main main, bool creating = false)
        {
            PointLight light = entity.GetOrCreate <PointLight>("PointLight");

            light.Serialize = false;

            const float defaultLightAttenuation = 15.0f;

            light.Attenuation.Value = defaultLightAttenuation;

            Transform transform = entity.GetOrCreate <Transform>("Transform");

            light.Add(new Binding <Vector3>(light.Position, transform.Position));

            if (!main.EditorEnabled)
            {
                Sound.AttachTracker(entity);
                SoundKiller.Add(entity, AK.EVENTS.STOP_GLOWSQUARE);
                entity.Add(new PostInitialization(delegate()
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_GLOWSQUARE, entity);
                    AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_GLOWSQUARE_PITCH, -1.0f, entity);
                }));
            }

            AI ai = entity.GetOrCreate <AI>("AI");

            ModelAlpha model = entity.GetOrCreate <ModelAlpha>();

            model.Add(new Binding <Matrix>(model.Transform, transform.Matrix));
            model.Filename.Value  = "AlphaModels\\box";
            model.Serialize       = false;
            model.DrawOrder.Value = 15;

            const float defaultModelScale = 1.0f;

            model.Scale.Value = new Vector3(defaultModelScale);

            model.Add(new Binding <Vector3, string>(model.Color, delegate(string state)
            {
                switch (state)
                {
                case "Alert":
                    return(new Vector3(1.5f, 1.5f, 0.5f));

                case "Chase":
                    return(new Vector3(1.5f, 0.5f, 0.5f));

                case "Explode":
                    return(new Vector3(2.0f, 1.0f, 0.5f));

                default:
                    return(new Vector3(1.0f, 1.0f, 1.0f));
                }
            }, ai.CurrentState));

            entity.Add(new Updater
                       (
                           delegate(float dt)
            {
                float source            = 1.0f + ((float)this.random.NextDouble() - 0.5f) * 2.0f * 0.05f;
                model.Scale.Value       = new Vector3(defaultModelScale * source);
                light.Attenuation.Value = defaultLightAttenuation * source;
            }
                       ));

            model.Add(new Binding <bool, string>(model.Enabled, x => x != "Exploding", ai.CurrentState));

            light.Add(new Binding <Vector3>(light.Color, model.Color));

            Agent agent = entity.GetOrCreate <Agent>();

            agent.Add(new Binding <Vector3>(agent.Position, transform.Position));

            RaycastAIMovement movement = entity.GetOrCreate <RaycastAIMovement>("Movement");
            Exploder          exploder = entity.GetOrCreate <Exploder>("Exploder");

            AI.Task checkOperationalRadius = new AI.Task
            {
                Interval = 2.0f,
                Action   = delegate()
                {
                    bool shouldBeActive = (transform.Position.Value - main.Camera.Position).Length() < movement.OperationalRadius;
                    if (shouldBeActive && ai.CurrentState == "Suspended")
                    {
                        ai.CurrentState.Value = "Idle";
                    }
                    else if (!shouldBeActive && ai.CurrentState != "Suspended")
                    {
                        ai.CurrentState.Value = "Suspended";
                    }
                },
            };

            RaycastAI raycastAI = entity.GetOrCreate <RaycastAI>("RaycastAI");

            raycastAI.Add(new TwoWayBinding <Vector3>(transform.Position, raycastAI.Position));
            raycastAI.Add(new Binding <Quaternion>(transform.Quaternion, raycastAI.Orientation));

            AI.Task updatePosition = new AI.Task
            {
                Action = delegate()
                {
                    raycastAI.Update();
                },
            };

            ai.Add(new AI.AIState
            {
                Name  = "Suspended",
                Tasks = new[] { checkOperationalRadius, },
            });

            const float sightDistance   = 40.0f;
            const float hearingDistance = 0.0f;

            ai.Add(new AI.AIState
            {
                Name  = "Idle",
                Enter = delegate(AI.AIState previous)
                {
                    AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_GLOWSQUARE_PITCH, -1.0f, entity);
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    updatePosition,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action   = delegate()
                        {
                            raycastAI.Move(new Vector3(((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f));
                        }
                    },
                    new AI.Task
                    {
                        Interval = 0.5f,
                        Action   = delegate()
                        {
                            Agent a = Agent.Query(transform.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                            if (a != null)
                            {
                                ai.CurrentState.Value = "Alert";
                            }
                        },
                    },
                },
            });

            ai.Add(new AI.AIState
            {
                Name  = "Alert",
                Enter = delegate(AI.AIState previous)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.STOP_GLOWSQUARE, entity);
                },
                Exit = delegate(AI.AIState next)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_GLOWSQUARE, entity);
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    updatePosition,
                    new AI.Task
                    {
                        Interval = 1.0f,
                        Action   = delegate()
                        {
                            if (ai.TimeInCurrentState > 3.0f)
                            {
                                ai.CurrentState.Value = "Idle";
                            }
                            else
                            {
                                Agent a = Agent.Query(transform.Position, sightDistance, hearingDistance, x => x.Entity.Type == "Player");
                                if (a != null)
                                {
                                    ai.TargetAgent.Value  = a.Entity;
                                    ai.CurrentState.Value = "Chase";
                                }
                            }
                        },
                    },
                },
            });

            AI.Task checkTargetAgent = new AI.Task
            {
                Action = delegate()
                {
                    Entity target = ai.TargetAgent.Value.Target;
                    if (target == null || !target.Active)
                    {
                        ai.TargetAgent.Value  = null;
                        ai.CurrentState.Value = "Idle";
                    }
                },
            };

            ai.Add(new AI.AIState
            {
                Name  = "Chase",
                Enter = delegate(AI.AIState previous)
                {
                    AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_GLOWSQUARE_PITCH, 0.0f, entity);
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    checkTargetAgent,
                    new AI.Task
                    {
                        Interval = 0.35f,
                        Action   = delegate()
                        {
                            raycastAI.Move(ai.TargetAgent.Value.Target.Get <Transform>().Position.Value - transform.Position);
                        }
                    },
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            if ((ai.TargetAgent.Value.Target.Get <Transform>().Position.Value - transform.Position).Length() < 10.0f)
                            {
                                ai.CurrentState.Value = "Explode";
                            }
                        }
                    },
                    updatePosition,
                },
            });

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

            ai.Add(new AI.AIState
            {
                Name  = "Explode",
                Enter = delegate(AI.AIState previous)
                {
                    exploder.CoordQueue.Clear();

                    Entity voxelEntity = raycastAI.Voxel.Value.Target;
                    if (voxelEntity == null || !voxelEntity.Active)
                    {
                        ai.CurrentState.Value = "Alert";
                        return;
                    }

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

                    Voxel.Coord c = raycastAI.Coord.Value;

                    Direction toSupport = Direction.None;

                    foreach (Direction dir in DirectionExtensions.Directions)
                    {
                        if (m[raycastAI.Coord.Value.Move(dir)].ID != 0)
                        {
                            toSupport = dir;
                            break;
                        }
                    }

                    if (toSupport == Direction.None)
                    {
                        ai.CurrentState.Value = "Alert";
                        return;
                    }

                    Direction up = toSupport.GetReverse();

                    exploder.ExplosionOriginalCoord.Value = raycastAI.Coord;

                    Direction right;
                    if (up.IsParallel(Direction.PositiveX))
                    {
                        right = Direction.PositiveZ;
                    }
                    else
                    {
                        right = Direction.PositiveX;
                    }
                    Direction forward = up.Cross(right);

                    for (Voxel.Coord y = c.Clone(); y.GetComponent(up) < c.GetComponent(up) + 3; y = y.Move(up))
                    {
                        for (Voxel.Coord x = y.Clone(); x.GetComponent(right) < c.GetComponent(right) + 2; x = x.Move(right))
                        {
                            for (Voxel.Coord z = x.Clone(); z.GetComponent(forward) < c.GetComponent(forward) + 2; z = z.Move(forward))
                            {
                                exploder.CoordQueue.Add(z);
                            }
                        }
                    }
                },
                Exit = delegate(AI.AIState next)
                {
                    exploder.CoordQueue.Clear();
                },
                Tasks = new[]
                {
                    checkOperationalRadius,
                    new AI.Task
                    {
                        Interval = 0.15f,
                        Action   = delegate()
                        {
                            if (exploder.CoordQueue.Length > 0)
                            {
                                raycastAI.MoveTo(exploder.CoordQueue[0]);

                                exploder.CoordQueue.RemoveAt(0);

                                Entity blockEntity = factory.CreateAndBind(main);
                                Voxel.States.Infected.ApplyToEffectBlock(blockEntity.Get <ModelInstance>());

                                Entity mapEntity = raycastAI.Voxel.Value.Target;
                                if (mapEntity != null && mapEntity.Active)
                                {
                                    EffectBlock effectBlock = blockEntity.Get <EffectBlock>();
                                    Voxel m = mapEntity.Get <Voxel>();

                                    effectBlock.Offset.Value = m.GetRelativePosition(raycastAI.Coord);

                                    Vector3 absolutePos = m.GetAbsolutePosition(raycastAI.Coord);

                                    effectBlock.StartPosition    = absolutePos + new Vector3(0.05f, 0.1f, 0.05f);
                                    effectBlock.StartOrientation = Quaternion.CreateFromYawPitchRoll(0.15f, 0.15f, 0);
                                    effectBlock.TotalLifetime    = 0.05f;
                                    effectBlock.Setup(raycastAI.Voxel.Value.Target, raycastAI.Coord, Voxel.t.Infected);
                                    main.Add(blockEntity);
                                }
                            }
                        }
                    },
                    new AI.Task
                    {
                        Action = delegate()
                        {
                            AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_GLOWSQUARE_PITCH, MathHelper.Lerp(0.0f, 1.0f, ai.TimeInCurrentState.Value / 2.0f), entity);
                            if (exploder.CoordQueue.Length == 0)
                            {
                                // Explode
                                ai.CurrentState.Value = "Exploding";
                            }
                        },
                    },
                    updatePosition,
                },
            });

            ai.Add(new AI.AIState
            {
                Name  = "Exploding",
                Enter = delegate(AI.AIState previous)
                {
                    exploder.Exploded.Value = false;
                    AkSoundEngine.PostEvent(AK.EVENTS.STOP_GLOWSQUARE, entity);
                },
                Exit = delegate(AI.AIState next)
                {
                    exploder.Exploded.Value = false;
                    AkSoundEngine.PostEvent(AK.EVENTS.PLAY_GLOWSQUARE, entity);
                },
                Tasks = new[]
                {
                    new AI.Task
                    {
                        Interval = 0.1f,
                        Action   = delegate()
                        {
                            const int radius = 9;

                            float timeInCurrentState = ai.TimeInCurrentState;
                            if (timeInCurrentState > 1.0f && !exploder.Exploded)
                            {
                                Entity mapEntity = raycastAI.Voxel.Value.Target;
                                if (mapEntity != null && mapEntity.Active)
                                {
                                    Explosion.Explode(main, mapEntity.Get <Voxel>(), raycastAI.Coord, radius, 18.0f);
                                }

                                exploder.Exploded.Value = true;
                            }

                            if (timeInCurrentState > 2.0f)
                            {
                                raycastAI.Move(new Vector3(((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f, ((float)this.random.NextDouble() * 2.0f) - 1.0f));
                                ai.CurrentState.Value = "Alert";
                            }
                        },
                    },
                    updatePosition,
                },
            });

            this.SetMain(entity, main);

            entity.Add("OperationalRadius", movement.OperationalRadius);
        }
Exemplo n.º 14
0
        public void Update(float dt)
        {
            State wallRunState = this.CurrentState;

            if (wallRunState != State.None)
            {
                this.Vault.Execute();                      // Try to vault up
                if (this.CurrentState.Value == State.None) // We vaulted
                {
                    return;
                }

                if (!this.WallRunVoxel.Value.Active || this.IsSupported)
                {
                    this.Deactivate();
                    return;
                }

                Voxel voxel = this.WallRunVoxel.Value;
                if (voxel == null || !voxel.Active)
                {
                    this.Deactivate();
                    return;
                }

                Vector3 wallRunVector = voxel.GetAbsoluteVector(this.WallRunDirection.Value.GetVector());
                Vector3 baseVelocity  = voxel.LinearVelocity + Vector3.Cross(voxel.AngularVelocity, this.Position - voxel.Transform.Value.Translation);
                float   wallRunSpeed  = Vector3.Dot(this.LinearVelocity.Value - baseVelocity, wallRunVector);
                Vector3 pos           = this.Position + new Vector3(0, this.Height * -0.5f, 0);

                if (wallRunState == State.Straight)
                {
                    if (wallRunSpeed < 0.0f)
                    {
                        // Start sliding down
                        this.CurrentState.Value = wallRunState = State.Down;
                        AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_SLIDE_LOOP, this.Entity);
                    }
                }
                else if (wallRunState == State.Left || wallRunState == State.Right)
                {
                    if (this.IsSupported || wallRunSpeed < minWallRunSpeed)
                    {
                        // We landed on the ground or we're going too slow to continue wall-running
                        this.Deactivate();
                        return;
                    }
                    else
                    {
                        // Check if we should switch to another wall
                        Vector3 wallVector = voxel.GetAbsoluteVector(this.WallDirection.Value.GetVector());
                        Voxel.GlobalRaycastResult result = Voxel.GlobalRaycast(pos, wallRunVector + wallVector, 2.0f);
                        if (result.Voxel != null && result.Voxel != voxel)
                        {
                            float dot = Vector3.Dot(result.Voxel.GetAbsoluteVector(result.Normal.GetReverse().GetVector()), wallVector);
                            if (dot > 0.7f)
                            {
                                Matrix  matrix        = Matrix.CreateRotationY(this.Rotation);
                                Vector3 forwardVector = -matrix.Forward;
                                this.setup(result.Voxel, result.Normal.GetReverse(), wallRunState, forwardVector, false, true);
                            }
                        }
                    }
                }

                Voxel.Coord coord     = voxel.GetCoordinate(pos);
                Voxel.Coord wallCoord = coord.Move(this.WallDirection, 2);
                Voxel.State wallType  = voxel[wallCoord];

                if (!wallCoord.Equivalent(this.lastWallRunCoord))
                {
                    this.lastWallRunCoord = wallCoord;
                    this.WalkedOn.Execute(voxel, wallCoord, this.WallDirection);
                }

                if (this.EnableEnhancedWallRun &&
                    (wallRunState == State.Left || wallRunState == State.Right) &&
                    Zone.CanBuild(this.Position) &&
                    voxel.Entity.Type != "Bouncer")
                {
                    Direction up = voxel.GetRelativeDirection(Direction.PositiveY);
                    if (up.IsPerpendicular(this.WallDirection))
                    {
                        Direction right = this.WallDirection.Value.Cross(up);

                        List <EffectBlockFactory.BlockBuildOrder> buildCoords = new List <EffectBlockFactory.BlockBuildOrder>();

                        const int radius       = 5;
                        int       upwardRadius = wallRunState == State.Down ? 0 : radius;
                        for (Voxel.Coord x = wallCoord.Move(right, -radius); x.GetComponent(right) < wallCoord.GetComponent(right) + radius; x = x.Move(right))
                        {
                            int dx = x.GetComponent(right) - wallCoord.GetComponent(right);
                            for (Voxel.Coord y = x.Move(up, -radius); y.GetComponent(up) < wallCoord.GetComponent(up) + upwardRadius; y = y.Move(up))
                            {
                                int dy = y.GetComponent(up) - wallCoord.GetComponent(up);
                                if ((float)Math.Sqrt(dx * dx + dy * dy) < radius && voxel[y].ID == 0)
                                {
                                    buildCoords.Add(new EffectBlockFactory.BlockBuildOrder
                                    {
                                        Voxel      = voxel,
                                        Coordinate = y,
                                        State      = Voxel.States.Blue,
                                    });
                                }
                            }
                        }
                        Factory.Get <EffectBlockFactory>().Build(main, buildCoords, this.Position);
                    }
                    else
                    {
                        this.Deactivate();
                        return;
                    }
                }
                else if (wallType.ID == 0 && wallInstantiationTimer == 0.0f)                 // We ran out of wall to walk on
                {
                    this.Deactivate();
                    return;
                }

                wallInstantiationTimer = Math.Max(0.0f, wallInstantiationTimer - dt);

                Vector3 coordPos = voxel.GetAbsolutePosition(coord);

                Vector3 normal = voxel.GetAbsoluteVector(this.WallDirection.Value.GetVector());
                // Equation of a plane
                // normal (dot) point = d
                float d = Vector3.Dot(normal, coordPos) + (wallRunState == State.Down ? 0.3f : 0.4f);

                // Distance along the normal to keep the player glued to the wall
                float snapDistance = d - Vector3.Dot(pos, normal);

                this.Position.Value += normal * snapDistance;

                Vector3 velocity = this.LinearVelocity;

                // Also fix the velocity so we don't jitter away from the wall
                velocity -= Vector3.Dot(velocity, normal) * normal;

                // Slow our descent
                velocity += new Vector3(0, (wallRunState == State.Straight ? 3.0f : 10.0f) * dt, 0);

                this.LinearVelocity.Value = velocity;
            }
        }
Exemplo n.º 15
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);
        }
Exemplo n.º 16
0
		// Classic 3D perlin noise
		float noise3d(Vector3 pos)
		{
			Voxel.Coord cell = new Voxel.Coord { X = (int)Math.Floor(pos.X) & 255, Y = (int)Math.Floor(pos.Y) & 255, Z = (int)Math.Floor(pos.Z) & 255 };
			
			pos.X = pos.X % 256;
			pos.Y = pos.Y % 256;
			pos.Z = pos.Z % 256;
			Vector3 withinCell = pos - new Vector3(cell.X, cell.Y, cell.Z);
			
			// Calculate contribution of gradients from each cell
			float contribution000 = Vector3.Dot(this.gradientAtCell3d(cell), withinCell);
			float contribution001 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 0, 1)), withinCell - new Vector3(0, 0, 1));
			float contribution010 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 1, 0)), withinCell - new Vector3(0, 1, 0));
			float contribution011 = Vector3.Dot(this.gradientAtCell3d(cell.Move(0, 1, 1)), withinCell - new Vector3(0, 1, 1));
			float contribution100 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 0, 0)), withinCell - new Vector3(1, 0, 0));
			float contribution101 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 0, 1)), withinCell - new Vector3(1, 0, 1));
			float contribution110 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 1, 0)), withinCell - new Vector3(1, 1, 0));
			float contribution111 = Vector3.Dot(this.gradientAtCell3d(cell.Move(1, 1, 1)), withinCell - new Vector3(1, 1, 1));
			
			Vector3 blend = new Vector3(blendCurve(withinCell.X), blendCurve(withinCell.Y), blendCurve(withinCell.Z));
			
			// Interpolate along X
			float contribution00 = lerp(contribution000, contribution100, blend.X);
			float contribution01 = lerp(contribution001, contribution101, blend.X);
			float contribution10 = lerp(contribution010, contribution110, blend.X);
			float contribution11 = lerp(contribution011, contribution111, blend.X);
			
			// Interpolate along Y
			float contribution0 = lerp(contribution00, contribution10, blend.Y);
			float contribution1 = lerp(contribution01, contribution11, blend.Y);
			
			// Interpolate along Z
			return lerp(contribution0, contribution1, blend.Z);
		}
Exemplo n.º 17
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);
        }
Exemplo n.º 18
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();
                }
            }));
        }
Exemplo n.º 19
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();
                    }
                }
            }));
        }
Exemplo n.º 20
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();
            }
        }
Exemplo n.º 21
0
        public bool Go(bool checkPossibilities)
        {
            if (this.main.TotalTime - this.LastVaultStarted < vaultCoolDown)
            {
                return(false);
            }

            Matrix rotationMatrix = Matrix.CreateRotationY(this.Rotation);

            foreach (Voxel map in Voxel.ActivePhysicsVoxels)
            {
                Direction   up          = map.GetRelativeDirection(Direction.PositiveY);
                Direction   backward    = map.GetRelativeDirection(rotationMatrix.Forward);
                Direction   right       = up.Cross(backward);
                Vector3     pos         = this.Position + rotationMatrix.Forward * -(this.Radius + 0.95f);
                Voxel.Coord resortCoord = default(Voxel.Coord);
                bool        resort      = false;
                for (int j = 0; j < searchForwardDistance; j++)
                {
                    Voxel.Coord baseCoord = map.GetCoordinate(pos + (rotationMatrix.Forward * -j)).Move(up, searchUpDistance);
                    foreach (int x in new[] { 0, -1, 1 })
                    {
                        Voxel.Coord coord = baseCoord.Move(right, x);
                        for (int i = 0; i < searchDownDistance; i++)
                        {
                            if (map[coord] != Voxel.States.Empty)
                            {
                                CandidateStatus status = checkAdjacent(map, coord, up, backward, right);
                                if (status == CandidateStatus.Bad)
                                {
                                    break;                                     // Conflict
                                }
                                bool conflict = false;
                                // Check other voxels for conflicts
                                foreach (Voxel v in Voxel.ActivePhysicsVoxels)
                                {
                                    if (v != map)
                                    {
                                        Direction up2       = v.GetRelativeDirection(Direction.PositiveY);
                                        Direction backward2 = v.GetRelativeDirection(rotationMatrix.Forward);
                                        Direction right2    = up2.Cross(backward2);

                                        Voxel.Coord coord2 = v.GetCoordinate(map.GetAbsolutePosition(coord));
                                        if (v[coord2] != Voxel.States.Empty ||
                                            checkAdjacent(v, coord2, up2, backward2, right2) != CandidateStatus.Good)
                                        {
                                            conflict = true;
                                            break;
                                        }
                                    }
                                }
                                if (conflict)
                                {
                                    break;
                                }

                                if (status == CandidateStatus.Uneven && !resort)
                                {
                                    resortCoord = coord;
                                    resort      = true;
                                    break;
                                }

                                // Vault
                                this.vault(map, coord.Move(up), false);
                                return(true);
                            }
                            coord = coord.Move(up.GetReverse());
                        }
                    }
                }
                if (resort)
                {
                    this.vault(map, resortCoord.Move(up), true);
                    return(true);
                }
            }

            if (checkPossibilities)
            {
                // Check block possibilities for vaulting
                foreach (BlockPredictor.Possibility possibility in this.Predictor.AllPossibilities)
                {
                    Direction   up        = possibility.Map.GetRelativeDirection(Direction.PositiveY);
                    Direction   right     = possibility.Map.GetRelativeDirection(Vector3.Cross(Vector3.Up, -rotationMatrix.Forward));
                    Vector3     pos       = this.Position + rotationMatrix.Forward * (this.WallRunState == WallRun.State.Straight ? -1.75f : -1.25f);
                    Voxel.Coord baseCoord = possibility.Map.GetCoordinate(pos).Move(up, searchUpDistance);
                    foreach (int x in new[] { 0, -1, 1 })
                    {
                        Voxel.Coord coord = baseCoord.Move(right, x);
                        for (int i = 0; i < searchDownDistance; i++)
                        {
                            Voxel.Coord downCoord = coord.Move(up.GetReverse());
                            if (!coord.Between(possibility.StartCoord, possibility.EndCoord) && downCoord.Between(possibility.StartCoord, possibility.EndCoord))
                            {
                                this.Predictor.InstantiatePossibility(possibility);
                                this.vault(possibility.Map, coord, false);
                                return(true);
                            }
                            coord = coord.Move(up.GetReverse());
                        }
                    }
                }
            }

            return(false);
        }
Exemplo n.º 22
0
        public override void Awake()
        {
            base.Awake();
            this.EnabledWhenPaused = false;
            this.Serialize         = false;

            this.Footstep.Action = delegate()
            {
                if (this.SoundEnabled && this.main.TotalTime - this.lastFootstepSound > footstepSoundInterval)
                {
                    AkSoundEngine.PostEvent(AK.EVENTS.FOOTSTEP_PLAY, this.Entity);
                    this.lastFootstepSound = this.main.TotalTime;
                }
            };

            this.Add(new CommandBinding <Voxel, Voxel.Coord, Direction>(this.WalkedOn, delegate(Voxel map, Voxel.Coord coord, Direction dir)
            {
                Voxel.State state = map[coord];

                if (state != Voxel.States.Empty)
                {
                    AkSoundEngine.SetSwitch(AK.SWITCHES.FOOTSTEP_MATERIAL.GROUP, state.FootstepSwitch, this.Entity);

                    if (this.WallRunState.Value == WallRun.State.None)
                    {
                        if (map.GetAbsoluteDirection(dir) == Direction.NegativeY && !this.IsSwimming)
                        {
                            this.walkedOnCount++;
                            if (this.walkedOnCount >= 2)
                            {
                                // Every few tiles, save off the location for the auto-respawn system
                                coord.Data = null;
                                this.RespawnLocations.Add(new RespawnLocation
                                {
                                    Coordinate       = coord,
                                    Map              = map.Entity,
                                    Rotation         = this.Rotation,
                                    OriginalPosition = map.GetAbsolutePosition(coord),
                                });
                                while (this.RespawnLocations.Length > Spawner.RespawnMemoryLength)
                                {
                                    this.RespawnLocations.RemoveAt(0);
                                }
                                this.walkedOnCount = 0;
                            }
                        }
                    }
                }

                Voxel.t id = state.ID;
                if (id == Voxel.t.Neutral)
                {
                    map.Empty(coord, false, true, map);
                    bool isPowered = false;
                    for (int i = 0; i < 6; i++)
                    {
                        Voxel.Coord adjacentCoord = coord.Move(DirectionExtensions.Directions[i]);
                        Voxel.t adjacentId        = map[coord].ID;
                        if (adjacentId == Voxel.t.Powered || adjacentId == Voxel.t.PermanentPowered || adjacentId == Voxel.t.PoweredSwitch || adjacentId == Voxel.t.HardPowered)
                        {
                            isPowered = true;
                            break;
                        }
                    }
                    map.Fill(coord, isPowered ? Voxel.States.Powered : Voxel.States.Blue);
                    map.Regenerate();
                    WorldFactory.Instance.Get <Propagator>().Sparks(map.GetAbsolutePosition(coord), Propagator.Spark.Normal);
                }
                else if (id == Voxel.t.Reset)
                {
                    bool regenerate = false;

                    Queue <Voxel.Coord> queue = new Queue <Voxel.Coord>();
                    queue.Enqueue(coord);
                    Voxel.CoordSetCache.Add(coord);
                    while (queue.Count > 0)
                    {
                        Voxel.Coord c = queue.Dequeue();
                        for (int i = 0; i < 6; i++)
                        {
                            Voxel.Coord adjacentCoord = c.Move(DirectionExtensions.Directions[i]);
                            if (!Voxel.CoordSetCache.Contains(adjacentCoord))
                            {
                                Voxel.CoordSetCache.Add(adjacentCoord);
                                Voxel.t adjacentID = map[adjacentCoord].ID;
                                if (adjacentID == Voxel.t.Reset || adjacentID == Voxel.t.Hard)
                                {
                                    queue.Enqueue(adjacentCoord);
                                }
                                else if (adjacentID == Voxel.t.Infected || adjacentID == Voxel.t.Blue || adjacentID == Voxel.t.Powered)
                                {
                                    map.Empty(adjacentCoord, false, true, map);
                                    map.Fill(adjacentCoord, Voxel.States.Neutral);
                                    regenerate = true;
                                }
                                else if (adjacentID == Voxel.t.HardPowered || adjacentID == Voxel.t.HardInfected)
                                {
                                    map.Empty(adjacentCoord, false, true, map);
                                    map.Fill(adjacentCoord, Voxel.States.Hard);
                                    regenerate = true;
                                }
                            }
                        }
                    }
                    Voxel.CoordSetCache.Clear();
                    if (regenerate)
                    {
                        map.Regenerate();
                    }
                }

                // Lava. Damage the player character if it steps on lava.
                bool isInfected = id == Voxel.t.Infected || id == Voxel.t.HardInfected;
                if (isInfected)
                {
                    this.Damage.Execute(0.2f);
                }
                else if (id == Voxel.t.Floater)
                {
                    // Floater. Delete the block after a delay.
                    Vector3 pos = map.GetAbsolutePosition(coord);
                    ParticleEmitter.Emit(main, "Smoke", pos, 1.0f, 10);
                    Sound.PostEvent(AK.EVENTS.PLAY_CRUMBLE, pos);
                    WorldFactory.Instance.Add(new Animation
                                              (
                                                  new Animation.Delay(0.5f),
                                                  new Animation.Execute(delegate()
                    {
                        if (map[coord].ID == Voxel.t.Floater)
                        {
                            map.Empty(coord);
                            map.Regenerate();
                        }
                    })
                                              ));
                }

                this.infectedDamage = isInfected;
            }));
        }
Exemplo n.º 23
0
        private void vault(Voxel map, Voxel.Coord coord, bool uneven)
        {
            Vector3 supportLocation = this.FloorPosition;
            Vector3 supportVelocity = this.getSupportVelocity(map);

            float verticalVelocityChange = this.LinearVelocity.Value.Y - supportVelocity.Y;

            if (verticalVelocityChange < Components.FallDamage.DeathVelocity)
            {
                return;                 // Don't even try to grab
            }
            this.FallDamage.Execute(verticalVelocityChange);
            if (!this.Active)             // We died from fall damage
            {
                return;
            }

            AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_VAULT, this.Entity);

            this.DeactivateWallRun.Execute();
            this.CurrentState.Value = State.Straight;

            this.coord = coord;

            Vector3 coordPosition = map.GetAbsolutePosition(coord);

            this.forward = coordPosition - this.Position;
            this.initialVerticalDifference = forward.Y;

            this.isTopOut = this.initialVerticalDifference > 1.75f || verticalVelocityChange < Lemma.Components.FallDamage.DamageVelocity;

            this.forward.Y = 0.0f;

            float horizontalDistanceToCoord = this.forward.Length();

            this.forward /= horizontalDistanceToCoord;

            Vector3 pos = coordPosition + this.forward * (Character.DefaultRadius + 1.0f);

            pos.Y = this.Position.Value.Y;
            this.Position.Value = pos;

            // If there's nothing on the other side of the wall (it's a one-block-wide wall)
            // then vault over it rather than standing on top of it
            this.vaultOver = this.initialVerticalDifference > 0.0f &&
                             map[coordPosition + this.forward].ID == Voxel.t.Empty &&
                             map[coordPosition + this.forward + new Vector3(0, -1, 0)].ID == Voxel.t.Empty &&
                             map[coordPosition + this.forward + new Vector3(0, -2, 0)].ID == Voxel.t.Empty;

            // Grunt if we're going up
            // If we're falling down, don't grunt because we might already be grunting from the fall damage
            // That would just be awkward
            if (this.random.NextDouble() > 0.5 && verticalVelocityChange >= 0 && !this.isTopOut)
            {
                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_PLAYER_GRUNT, this.Entity);
            }

            this.vaultVelocity = supportVelocity + new Vector3(0, this.isTopOut ? topOutVerticalSpeed : mantleVaultVerticalSpeed, 0);

            this.map = map;

            this.LinearVelocity.Value = this.vaultVelocity;
            this.IsSupported.Value    = false;
            this.HasTraction.Value    = false;

            Direction relativeDir       = map.GetRelativeDirection(this.forward);
            Vector3   absoluteDirVector = map.GetAbsoluteVector(relativeDir.GetVector());

            this.Rotation.Value = (float)Math.Atan2(absoluteDirVector.X, absoluteDirVector.Z);
            this.LockRotation.Execute();

            this.EnableWalking.Value = false;
            this.Crouched.Value      = true;
            this.AllowUncrouch.Value = false;

            Session.Recorder.Event(main, "Vault");
            this.model.Stop
            (
                "Mantle",
                "TopOut",
                "Jump",
                "Jump02",
                "Jump03",
                "JumpLeft",
                "JumpRight",
                "JumpBackward"
            );
            this.model.StartClip(this.isTopOut ? "TopOut" : "Mantle", 4, false, AnimatedModel.DefaultBlendTime);

            if (this.vaultOver)
            {
                this.shallowMantle = false;
            }
            else if (!this.isTopOut)
            {
                // We're mantling
                // Determine if this is a shallow mantle or not
                this.shallowMantle = map[coordPosition + this.forward * 1.5f + new Vector3(0, 1, 0)].ID != Voxel.t.Empty ||
                                     map[coordPosition + this.forward * 1.5f + new Vector3(0, 2, 0)].ID != Voxel.t.Empty;
            }

            this.vaultTime            = 0.0f;
            this.moveForwardStartTime = 0.0f;
            this.movingForward        = false;
            this.originalPosition     = this.Position;

            Direction up = map.GetRelativeDirection(Direction.PositiveY);

            // If this is a top-out, we have to make sure the animation lines up perfectly
            if (this.isTopOut)
            {
                this.relativeVaultStartPosition = map.GetRelativePosition(coord.Move(relativeDir, -2)) + up.GetVector() * -3.7f;
            }
            else
            {
                this.relativeVaultStartPosition = Vector3.Transform(this.originalPosition, Matrix.Invert(this.map.Transform));
            }

            if (uneven)
            {
                // We're climbing an uneven surface, we need to uncrouch early if possible
                Direction right = relativeDir.Cross(up);
                this.uncrouchEarly = map[coord.Move(up, 3).Move(right, -1)] == Voxel.States.Empty &&
                                     map[coord.Move(up, 3)] == Voxel.States.Empty &&
                                     map[coord.Move(up, 3).Move(right, 1)] == Voxel.States.Empty;
            }
            else
            {
                this.uncrouchEarly = false;
            }

            this.LastVaultStarted.Value = this.main.TotalTime;
        }
Exemplo n.º 24
0
        public bool Activate(State state, bool checkPossibilities)
        {
            if (!this.EnableWallRun)
            {
                return(false);
            }

            Vector3 playerVelocity = this.LinearVelocity.Value;

            if (playerVelocity.Y < FallDamage.RollingDamageVelocity)
            {
                return(false);
            }

            if (this.IsSwimming)
            {
                if (state == State.Left || state == State.Right)
                {
                    return(false);
                }
            }

            wallInstantiationTimer = 0.0f;

            // Prevent the player from repeatedly wall-running and wall-jumping ad infinitum.
            bool wallRunDelayPassed     = main.TotalTime - this.lastWallRunEnded > wallRunDelay;
            bool wallRunJumpDelayPassed = main.TotalTime - this.LastWallJump > wallRunDelay;

            Matrix matrix = Matrix.CreateRotationY(this.Rotation);

            Vector3 forwardVector = -matrix.Forward;

            Vector3 wallVector;

            switch (state)
            {
            case State.Straight:
                wallVector = forwardVector;
                break;

            case State.Left:
                if (!this.EnableWallRunHorizontal)
                {
                    return(false);
                }
                wallVector = -matrix.Left;
                break;

            case State.Right:
                if (!this.EnableWallRunHorizontal)
                {
                    return(false);
                }
                wallVector = -matrix.Right;
                break;

            default:
                wallVector = Vector3.Zero;
                break;
            }

            Vector3 pos = this.Position + new Vector3(0, this.Height * -0.5f, 0);

            // Attempt to wall-run on an existing map
            bool  addInitialVelocity = false;
            Voxel closestVoxel       = null;

            Voxel.Coord closestCoord    = default(Voxel.Coord);
            const int   maxWallDistance = 4;
            int         closestDistance = maxWallDistance;
            Direction   closestDir      = Direction.None;

            foreach (Voxel voxel in Voxel.ActivePhysicsVoxels)
            {
                Vector3 baseVelocity = voxel.LinearVelocity + Vector3.Cross(voxel.AngularVelocity, this.Position - voxel.Transform.Value.Translation);
                Vector3 v            = Vector3.Normalize(playerVelocity - baseVelocity);
                v.Y = 0.0f;
                if (Vector3.Dot(forwardVector, v) < -0.3f)
                {
                    continue;
                }

                Voxel.Coord coord      = voxel.GetCoordinate(pos);
                Direction   dir        = voxel.GetRelativeDirection(wallVector);
                Direction   up         = voxel.GetRelativeDirection(Direction.PositiveY);
                Direction   forwardDir = voxel.GetRelativeDirection(forwardVector);
                for (int i = 1; i < maxWallDistance; i++)
                {
                    Voxel.Coord wallCoord = coord.Move(dir, i);
                    if (voxel[coord.Move(dir, i - 1)] != Voxel.States.Empty ||
                        voxel[coord.Move(dir, i - 1).Move(up, 1)] != Voxel.States.Empty ||
                        voxel[coord.Move(dir, i - 1).Move(up, 2)] != Voxel.States.Empty ||
                        ((state == State.Left || state == State.Right) &&
                         (voxel[coord.Move(forwardDir).Move(dir, i - 1)] != Voxel.States.Empty ||
                          voxel[coord.Move(forwardDir).Move(dir, i - 1).Move(up, 1)] != Voxel.States.Empty ||
                          voxel[coord.Move(forwardDir).Move(dir, i - 1).Move(up, 2)] != Voxel.States.Empty)))
                    {
                        // Blocked
                        break;
                    }

                    // Need at least two blocks to consider it a wall
                    if (voxel[wallCoord].ID != 0 && voxel[wallCoord.Move(up)].ID != 0)
                    {
                        bool differentWall = voxel != this.LastWallRunMap.Value || dir != this.LastWallDirection.Value;
                        if ((differentWall || wallRunJumpDelayPassed) && i < closestDistance)
                        {
                            closestVoxel       = voxel;
                            closestDistance    = i;
                            closestCoord       = coord;
                            closestDir         = dir;
                            addInitialVelocity = differentWall || wallRunDelayPassed;
                        }
                    }
                    else if (checkPossibilities)
                    {
                        // Check block possibilities
                        List <BlockPredictor.Possibility> mapBlockPossibilities = this.Predictor.GetPossibilities(voxel);
                        if (mapBlockPossibilities != null)
                        {
                            foreach (BlockPredictor.Possibility block in mapBlockPossibilities)
                            {
                                if (wallCoord.Between(block.StartCoord, block.EndCoord))
                                {
                                    this.Predictor.InstantiatePossibility(block);
                                    this.Predictor.ClearPossibilities();
                                    closestVoxel           = voxel;
                                    closestDistance        = i;
                                    closestCoord           = coord;
                                    closestDir             = dir;
                                    addInitialVelocity     = true;
                                    wallInstantiationTimer = 0.25f;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (closestVoxel != null)
            {
                if (!addInitialVelocity && Vector3.Dot(forwardVector, playerVelocity) < minWallRunSpeed)
                {
                    return(false);
                }
                this.Position.Value = closestVoxel.GetAbsolutePosition(closestCoord.Move(closestDir, closestDistance - 2)) + new Vector3(0, this.Height * 0.5f, 0);
                this.setup(closestVoxel, closestDir, state, forwardVector, addInitialVelocity);
                return(true);
            }
            return(false);
        }
Exemplo n.º 25
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;
            }
        }
Exemplo n.º 26
0
 private static CandidateStatus checkAdjacent(Voxel v, Voxel.Coord coord, Direction up, Direction backward, Direction right)
 {
     if (v[coord.Move(backward)] != Voxel.States.Empty ||
         v[coord.Move(up).Move(backward)] != Voxel.States.Empty ||
         v[coord.Move(up, 2).Move(backward)] != Voxel.States.Empty ||
         v[coord.Move(up, 3).Move(backward)] != Voxel.States.Empty ||
         v[coord.Move(up)] != Voxel.States.Empty ||
         v[coord.Move(up, 2)] != Voxel.States.Empty ||
         v[coord.Move(up, 3)] != Voxel.States.Empty)
     {
         return(CandidateStatus.Bad);
     }
     else if (v[coord.Move(right, -1).Move(up)] != Voxel.States.Empty ||
              v[coord.Move(right, -1).Move(up, 2)] != Voxel.States.Empty ||
              v[coord.Move(right, -1).Move(up, 3)] != Voxel.States.Empty ||
              v[coord.Move(right).Move(up)] != Voxel.States.Empty ||
              v[coord.Move(right).Move(up, 2)] != Voxel.States.Empty ||
              v[coord.Move(right).Move(up, 3)] != Voxel.States.Empty)
     {
         return(CandidateStatus.Uneven);
     }
     else
     {
         return(CandidateStatus.Good);
     }
 }
Exemplo n.º 27
0
        public bool BreakWalls(Vector3 forward, Vector3 right)
        {
            BlockFactory blockFactory = Factory.Get <BlockFactory>();
            Vector3      basePos      = this.Position + new Vector3(0, 0.2f + (this.Height * -0.5f) - this.SupportHeight, 0) + forward * -1.0f;
            bool         broke        = false;

            foreach (Voxel map in Voxel.ActivePhysicsVoxels.ToList())
            {
                List <Voxel.Coord> removals      = new List <Voxel.Coord>();
                Quaternion         mapQuaternion = Quaternion.CreateFromRotationMatrix(map.Transform);
                Voxel.Coord        top           = map.GetCoordinate(basePos + new Vector3(0, this.Height + this.SupportHeight + 0.5f, 0));
                Direction          upDir         = map.GetRelativeDirection(Vector3.Up);
                Direction          rightDir      = map.GetRelativeDirection(right);
                Direction          forwardDir    = map.GetRelativeDirection(forward);
                Voxel.Coord        center        = map.GetCoordinate(basePos);
                for (Voxel.Coord y = center.Clone(); y.GetComponent(upDir) <= top.GetComponent(upDir); y = y.Move(upDir))
                {
                    int minZ = center.GetComponent(rightDir) - 10;
                    int maxZ = minZ + 20;
                    foreach (Voxel.Coord x in this.spreadFromCenter(y, rightDir))
                    {
                        Voxel.Coord z = x.Clone();
                        for (int i = 0; i < 4; i++)
                        {
                            Voxel.State state           = map[z];
                            int         zRightDimension = z.GetComponent(rightDir);
                            if (zRightDimension > minZ && zRightDimension < maxZ && state.ID != 0 && !removals.Contains(z))
                            {
                                if (state.Permanent || state.Hard)
                                {
                                    if (zRightDimension >= center.GetComponent(rightDir))
                                    {
                                        maxZ = zRightDimension;
                                    }
                                    else
                                    {
                                        minZ = zRightDimension;
                                    }
                                    break;
                                }
                                else
                                {
                                    broke = true;
                                    removals.Add(z);
                                    Vector3   cellPos        = map.GetAbsolutePosition(z);
                                    Vector3   toCell         = cellPos - basePos;
                                    Entity    block          = blockFactory.CreateAndBind(this.main);
                                    Transform blockTransform = block.Get <Transform>();
                                    blockTransform.Position.Value   = cellPos;
                                    blockTransform.Quaternion.Value = mapQuaternion;
                                    state.ApplyToBlock(block);
                                    toCell += forward * 4.0f;
                                    toCell.Normalize();
                                    PhysicsBlock physicsBlock = block.Get <PhysicsBlock>();
                                    physicsBlock.LinearVelocity.Value  = toCell * 15.0f;
                                    physicsBlock.AngularVelocity.Value = new Vector3(((float)this.random.NextDouble() - 0.5f) * 2.0f, ((float)this.random.NextDouble() - 0.5f) * 2.0f, ((float)this.random.NextDouble() - 0.5f) * 2.0f);
                                    main.Add(block);
                                }
                            }
                            z = z.Move(forwardDir);
                        }
                    }
                }

                if (removals.Count > 0)
                {
                    map.Empty(removals);
                    map.Regenerate();
                }
            }
            return(broke);
        }