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); } } }
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; } } }
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; })); }