public void shoot(float delta, bool isPuppet) { if (reloadWeapon) { return; } if (!isPuppet) { return; } // Get bullet ray. RayCast bulletRay = (RayCast)camera.GetNode("bullet_ray"); if (bullets > 0) { bullets -= 1; // Notify bullet update GameState.instance.EmitSignal(nameof(GameState.updateWeapon), weaponName, bullets, ammo); if (camera != null) { // Recoil camera.Rotation = new Vector3( Mathf.Lerp(camera.Rotation.x, (float)GD.RandRange(1, 2), delta), Mathf.Lerp(camera.Rotation.y, (float)GD.RandRange(-1, 1), delta), camera.Rotation.z ); // Shake camera.Set("shakeForce", 0.002); camera.Set("shakeTime", 0.2); } // Audio AudioStreamPlayer3D shoot = ((AudioStreamPlayer3D)audioNode.GetNode("shoot")); shoot.PitchScale = (float)GD.RandRange(0.9, 1.1); shoot.Play(); // Update crosshair crosshair.RectScale = crosshair.RectScale.LinearInterpolate(new Vector2(4, 4), 10 * delta); if (bulletRay.IsColliding()) { // Object collision CollisionObject collisionObject = (CollisionObject)bulletRay.GetCollider(); // Add spark to props. if (collisionObject.IsInGroup("props")) { // Add Spark Particles spark = (Particles)sparkScene.Instance(); ((Node)bulletRay.GetCollider()).AddChild(spark); spark.GlobalTransform = new Transform(spark.GlobalTransform.basis, bulletRay.GetCollisionPoint()); spark.Emitting = true; } // Add Muzzle Particles muzzle = (Particles)muzzleScene.Instance(); barrelNode.AddChild(muzzle); muzzle.Emitting = true; if (collisionObject is KinematicBody) { // Add Blood splatter Particles splatter = (Particles)splatterScene.Instance(); ((Node)bulletRay.GetCollider()).AddChild(splatter); splatter.GlobalTransform = new Transform(splatter.GlobalTransform.basis, bulletRay.GetCollisionPoint()); splatter.Emitting = true; int localDamage = 0; if (collisionObject.IsInGroup("head")) { localDamage = (int)GD.RandRange(damage / 2, damage); } else { localDamage = (int)GD.RandRange(damage / 3, damage / 2); } int colliderId = Convert.ToInt32(collisionObject.Name); // Send damage report. GameState.instance.EmitSignal(nameof(GameState.takeDamage), colliderId, localDamage); return; } else if (collisionObject.IsInGroup("props") || collisionObject.IsInGroup("walls")) { // Apply force to rigid body other than hitbox if (bulletRay.GetCollider() is RigidBody) { int localDamage = (int)GD.RandRange(damage / 1.5f, damage); ((RigidBody)bulletRay.GetCollider()).ApplyCentralImpulse(-bulletRay.GetCollisionNormal() * (localDamage * 0.3f)); } // Apply decal Spatial decal = (Spatial)decalScene.Instance(); ((Node)bulletRay.GetCollider()).AddChild(decal); decal.GlobalTransform = new Transform( decal.GlobalTransform.basis, bulletRay.GetCollisionPoint() ); decal.LookAt(bulletRay.GetCollisionPoint() + bulletRay.GetCollisionNormal(), new Vector3(1, 1, 0)); return; } } } else { AudioStreamPlayer3D empty = ((AudioStreamPlayer3D)audioNode.GetNode("empty")); if (!empty.Playing) { empty.PitchScale = (float)GD.RandRange(0.9, 1.1); empty.Play(); } } }