public override async Task Execute() { // Play explosion sound AudioEmitterComponent audioEmitter = Entity.Get <AudioEmitterComponent>(); explosionSound = audioEmitter["Explosion"]; explosionSound.PlayAndForget(); Entity.Transform.UpdateWorldMatrix(); var model = Entity.Get <ModelComponent>(); // Scatter all the Rigidbody parts of the scattered drone model var fracturedRigidBodies = Entity.GetAll <RigidbodyComponent>(); Vector3 explosionCenter = Entity.Transform.WorldMatrix.TranslationVector; Random explosionRandom = new Random(); foreach (var fragment in fracturedRigidBodies) { Vector3 dir = fragment.PhysicsWorldTransform.TranslationVector - explosionCenter; dir.Normalize(); fragment.IsKinematic = false; if (model.Skeleton.Nodes[fragment.BoneIndex].Name != "Drone_D_part_015") { fragment.ApplyTorqueImpulse(-dir * (float)(explosionRandom.NextDouble() * 0.2f)); fragment.ApplyImpulse(dir * (float)(explosionRandom.NextDouble() * 2.5f + 2.5f)); } } await Task.Delay(30000); // Despawn after a while to clean up drone parts SceneSystem.SceneInstance.RootScene.Entities.Remove(Entity); }
private void Reload() { var bulletDelta = 1.0f / BulletPerSeconds; lastBullet = Game.UpdateTime.Total + TimeSpan.FromSeconds(1.5 - bulletDelta); IsReloading = true; OnReload?.Invoke(this); // Play reload sound reloadSound.PlayAndForget(); }
public void Damage(int damage) { bool wasDead = IsDead; // Let's keep the godmode for now //HealthPoints = Math.Max(0, HealthPoints - damage); if (HealthPoints > 0) { Game.VibratorSmooth(controllerIndex, new Vector2(0.50f, 0.45f), new Vector2(0.95f, 0.90f), TimeSpan.FromSeconds(0.5)); // Stop other hit sounds for (int i = 0; i < hitSounds.Length; i++) { hitSounds[i].Stop(); } // Play being hit sound hitSounds[soundIndexGenerator.Next(0, hitSounds.Length - 1)].PlayAndForget(); } else { // Only do this once, when dying if (!wasDead) { // Play dying sound deathSound.PlayAndForget(); Game.VibratorSmooth(controllerIndex, new Vector2(0.90f, 0.99f), new Vector2(0.0f, 0.0f), TimeSpan.FromSeconds(3)); Move(0.0f); //stop any motion stateMachine?.SwitchTo(IdleState); stateMachine?.Exit(); Script.AddTask(async() => { await Game.WaitTime(TimeSpan.FromSeconds(3)); IsAlive = false; }); } } // Fire event OnDamageTaken?.Invoke(this, damage); }
protected override async Task Explode() { var model = Entity.Get <ModelComponent>(); model.Enabled = false; ExplosionParticle.Enabled = true; //stop spawning smoke particles SmokeParticle.ParticleSystem.StopEmitters(); //find what we hit foreach (var collision in sensor.Collisions) { var collider = collision.ColliderA == sensor ? collision.ColliderB : collision.ColliderA; var damagedEntity = Utils.GetDestructible(collider.Entity); if (damagedEntity == null || damagedEntity.IsDead) { continue; } // Don't damage other drones if (damagedEntity is Drone) { continue; } var firstContact = collision.Contacts.First(); var damage = (int)((0.25f + 0.75f * Math.Abs(firstContact.Distance) / AoE) * Damage); damagedEntity.Damage(damage); } explodeSound.PlayAndForget(); // Wait before Destroying the rocket await Task.Delay(2000); }
/// <summary> /// Spawns rockets in a grid /// </summary> protected override async Task Shoot(Entity targetEntity) { // Play shooting animation Drone.Animation.Shoot(); // Wait a bit await Task.Delay(TimeSpan.FromSeconds(AnimationDelay)); List <Projectile> projectiles = new List <Projectile>(); Vector2 stepOffset = new Vector2(1.0f / ArraySize.X, 1.0f / ArraySize.Y) * ArrayExtent; // Generate random spawn position List <Vector2> spawnOffsets = new List <Vector2>(); for (int y = 0; y < ArraySize.Y; y++) { float stepY = (ArraySize.Y == 0) ? 0.0f : (y / (float)(ArraySize.Y - 1) * 2.0f - 1.0f); for (int x = 0; x < ArraySize.X; x++) { float stepX = (ArraySize.X == 0) ? 0.0f : (x / (float)(ArraySize.X - 1) * 2.0f - 1.0f); Vector2 spawnOffset = new Vector2((stepOffset.X * stepX), (stepOffset.Y * stepY)); spawnOffsets.Add(spawnOffset); } } // Spawn in random order while (spawnOffsets.Count > 0) { // Recalculate directions and start position since drone might have moved var position = ProjectileSpawnPoint.Transform.WorldMatrix.TranslationVector; Vector3 up = Drone.Entity.Transform.WorldMatrix.Up; Vector3 aimDirection = Drone.HeadDirection; Vector3 right = Vector3.Normalize(Vector3.Cross(up, aimDirection)); // Retrieve spawn position for this missile based on the offsets int targetPositionIndex = random.Next(0, spawnOffsets.Count - 1); Vector2 spawnOffset = spawnOffsets[targetPositionIndex]; Vector3 spawnPosition = position + spawnOffset.X * right + spawnOffset.Y * up; spawnPosition += aimDirection * ((float)random.NextDouble() - 0.5f) * 0.1f; spawnOffsets.RemoveAt(targetPositionIndex); // Spawn rocket var projectileEntity = ProjectilePrefab.Instantiate().Single(); var projectile = projectileEntity.Get <Projectile>(); projectile.Owner = Drone.Entity; projectiles.Add(projectile); projectileEntity.Transform.Position = spawnPosition; projectileEntity.Transform.Rotation = Quaternion.BetweenDirections(Vector3.UnitZ, Drone.HeadDirection); // Random Pitch/Roll (relative to shooting direction) Vector2 randomDeviation = new Vector2((float)random.NextDouble(), (float)random.NextDouble()); randomDeviation.X = randomDeviation.X * SpreadAngle.Radians; // Pitch randomDeviation.Y *= MathUtil.TwoPi; // Roll projectileEntity.Transform.Rotation = projectileEntity.Transform.Rotation * Quaternion.RotationAxis(right, randomDeviation.X) * Quaternion.RotationAxis(aimDirection, randomDeviation.Y); var rocket = (projectile as RocketProjectile); if (targetEntity != null) { rocket?.SetTarget(targetEntity.Transform.WorldMatrix.TranslationVector); } else { rocket?.SetTarget(position + aimDirection * ShootingRange); } Drone.SceneSystem.SceneInstance.RootScene.Entities.Add(projectile.Entity); // Set initial direction Vector3 initialRocketDirection = Vector3.Transform(Vector3.UnitZ, projectileEntity.Transform.Rotation); projectile.SetDirection(initialRocketDirection); shootSound.PlayAndForget(); await Task.Delay(2 + random.Next(0, 8)); } }