Ejemplo n.º 1
0
        void IUpdateableComponent.Update(float dt)
        {
            if (this.main.Paused)
            {
                return;
            }

            bool newUnderwater = this.Fluid.BoundingBox.Contains(this.main.Camera.Position) != ContainmentType.Disjoint;

            if (newUnderwater != this.underwater)
            {
                AkSoundEngine.SetState(AK.STATES.WATER.GROUP, newUnderwater ? AK.STATES.WATER.STATE.UNDERWATER : AK.STATES.WATER.STATE.NORMAL);
            }
            this.underwater = newUnderwater;

            int drawOrder = this.CannotSuspendByDistance && newUnderwater ? 10 : -15;

            if (this.DrawOrder != drawOrder)
            {
                this.DrawOrder.Value = drawOrder;
            }

            Water.BigWaterShader.Value = this.CannotSuspendByDistance && !newUnderwater;

            float waterHeight = this.Position.Value.Y;

            float time = this.main.TotalTime;

            lock (this.Fluid.NotifyEntries)
            {
                foreach (BEPUphysics.BroadPhaseEntries.MobileCollidables.EntityCollidable collidable in this.Fluid.NotifyEntries)
                {
                    if (collidable.Entity == null)
                    {
                        continue;
                    }

                    float speed = collidable.Entity.LinearVelocity.Length();

                    if (speed > 9.0f)
                    {
                        float volume = Math.Min(speed * collidable.Entity.Mass * speedMassVolumeCoefficient, 1.0f);
                        if (volume > 0.1f && !this.submerged.ContainsKey(collidable))
                        {
                            uint temp = AkSoundEngine.RegisterTemp(collidable.Entity.Position);
                            if (collidable.Entity.Mass > 40.0f)
                            {
                                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_WATER_SPLASH_HEAVY, temp);
                            }
                            else
                            {
                                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_WATER_SPLASH, temp);
                            }
                            AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_WATER_SPLASH_VOLUME, volume, temp);
                            AkSoundEngine.UnregisterTemp(temp);
                        }
                    }

                    if (speed > 5.0f)
                    {
                        collidable.UpdateBoundingBox();
                        BoundingBox boundingBox       = collidable.BoundingBox;
                        Vector3     diff              = boundingBox.Max - boundingBox.Min;
                        Vector3[]   particlePositions = new Vector3[5 * (int)(diff.X * diff.Z)];

                        Voxel v             = collidable.Tag as Voxel;
                        int   particleIndex = 0;
                        for (int i = 0; i < particlePositions.Length; i++)
                        {
                            Vector3 pos = particlePositions[particleIndex] = new Vector3
                                                                             (
                                boundingBox.Min.X + ((float)this.random.NextDouble() * diff.X),
                                waterHeight,
                                boundingBox.Min.Z + ((float)this.random.NextDouble() * diff.Z)
                                                                             );
                            if (v == null || v[pos] != Voxel.States.Empty)
                            {
                                particleIndex++;
                            }
                        }

                        ParticleEmitter.Emit(this.main, "Splash", particlePositions.Take(particleIndex));

                        ParticleEmitter.Emit(this.main, "BigSplash", particlePositions.Take(particleIndex / 5));
                    }

                    this.submerged[collidable] = time;
                }
                this.Fluid.NotifyEntries.Clear();
            }

            foreach (KeyValuePair <BEPUphysics.BroadPhaseEntries.MobileCollidables.EntityCollidable, float> p in this.submerged.ToList())
            {
                if (time - p.Value > 0.1f)
                {
                    if (p.Key.Entity != null)
                    {
                        float speed = p.Key.Entity.LinearVelocity.Y;
                        if (speed > 2.0f)
                        {
                            float volume = Math.Min(speed * p.Key.Entity.Mass * speedMassVolumeCoefficient, 1.0f);
                            if (volume > 0.1f)
                            {
                                uint temp = AkSoundEngine.RegisterTemp(p.Key.Entity.Position);
                                AkSoundEngine.PostEvent(AK.EVENTS.PLAY_WATER_SPLASH_OUT, temp);
                                AkSoundEngine.SetRTPCValue(AK.GAME_PARAMETERS.SFX_WATER_SPLASH_VOLUME, volume, temp);
                                AkSoundEngine.UnregisterTemp(temp);
                            }
                        }
                    }
                    this.submerged.Remove(p.Key);
                }
            }
        }
Ejemplo n.º 2
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;
                }
            }
        }
Ejemplo n.º 3
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;
            }));
        }