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