# Projectiles & Targeting

### Jump to section...

* [Projectile Targeting](#projectile-targeting)
* [Projectile Classes](#projectile-classes)

## Projectile Targeting

{% hint style="info" %}
Note that in order to keep the snippets within the line character limit, the code snippets below are intentionally written without worrying about const correctness.
{% endhint %}

Projectiles should fire from the character's hand towards the nearest valid target under the player's reticle. Calculating the projectile's spawn parameters takes some simple 3D math, described below.

![Projectiles should fire from the character's hand to the nearest valid target under player reticle](https://112794710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoURZQKJhQVbJ4EduVl8M%2Fuploads%2FYPjRBtheEqjAsZDieeNg%2Fimage.png?alt=media\&token=c6d69a69-51ad-415b-aa5d-28690ed16e9a)

To aim the projectile in this way, we spawn the projectile at the character's hand, facing in the direction of the target.

The `SpawnLocation` is easy to get, since our Character model is set up with a hand socket. We can retrieve the hand location simply by calling `GetSocketLocation()` on the Character mesh with the name of the hand socket.

`ProjectileRotation` is harder to calculate, and will take some work:

#### Calculating the Projectile Rotation

We need to calculate the world space rotation needed to "look at" the target (such that when the projectile moves forward, it is moving directly towards the target). Luckily, Unreal provides a convenient way to get this world space rotation, provided a vector pointing in the direction you want to look at:

`FRotationMatrix::MakeFromX(FVector XAxis).Rotator()`

First, this creates a rotation matrix from an X-Axis, then creates a rotator representation of this matrix. All that's left is to calculate the X-Axis that looks from the hand location, in the direction of the target. We can easily compute that by subtracting the two locations, giving us the final result:&#x20;

`FRotationMatrix::MakeFromX(TargetLocation - HandLocation).Rotator();`

But wait! Something is still missing! We know how to generate the rotation, but still need to calculate the target location...

#### Calculating the Projectile Target

To find this target, we perform a line trace from the player's camera into the world where the player is looking:

```cpp
FVector TraceStart = CameraComp->GetComponentLocation();
FVector ControlRotation = Character->GetControlRotation().Vector();
FVector TraceEnd = TraceStart + (ControlRotation * MaxAttackTraceDistance)
```

We also need to configure the line trace to only collide with objects we consider attack targets:

```cpp
FCollisionObjectQueryParams ObjectQueryParams;
ObjectQueryParams.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldDynamic);
ObjectQueryParams.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic);
ObjectQueryParams.AddObjectTypesToQuery(ECollisionChannel::ECC_Pawn);
	
FCollisionQueryParams CollisionQueryParams;
CollisionQueryParams.AddIgnoredActor(Character);
```

Then we perform the trace, setting the target to the first object hit, or `MaxAttackTraceDistance` away if nothing was found (e.g. the player was aiming into the sky).

```cpp
FHitResult Hit;
bool bBlockingHit = GetWorld()->LineTraceSingleByObjectType(
	Hit, TraceStart, TraceEnd, ObjectQueryParams, CollisionQueryParams);

FVector ProjectileTargetLocation = bBlockingHit ? Hit.Location : TraceEnd;
```

### Full Solution

**See full solution on GitHub:** [TAction\_ProjectileAttack.cpp](https://github.com/Juwce/ActionRoguelike/blob/main/Source/ActionRoguelike/Private/TAction_ProjectileAttack.cpp) // [TAction\_ProjectileAttack.h](https://github.com/Juwce/ActionRoguelike/blob/main/Source/ActionRoguelike/Public/TAction_ProjectileAttack.h)

## Projectile Classes

{% hint style="info" %}
Functionality for projectiles are implemented in C++. Unreal's Blueprints / UI is only used to assign assets and fine-tune gameplay parameters (damage values, delays, etc.).
{% endhint %}

### Projectile Base Class

A projectile base class `TProjectileBase` handles the basic setup of a projectile.

* Can collide with the environment, exploding upon impact
* Provides the following virtual functions:
  * `OnActorHit()` - callback when projectile hits the environment (blocking collision)
  * `Explode()` - play cosmetic effects and destroy self. Triggered by `OnActorHit()` by default
* Contains the basic components shared by all projectiles:
  * `USphereComponent` - Sphere primitive used for collision detection
  * `UProjectileMovementComponent` - Handle velocity, acceleration, curvature, etc.
  * `UParticleSystemComponent` - Projectile and explosion VFX
  * `UAudioComponent` - Projectile and explosion sounds

**See it on GitHub:** [TProjectileBase.cpp](https://github.com/Juwce/ActionRoguelike/blob/main/Source/ActionRoguelike/Private/TProjectileBase.cpp) // [TProjectileBase.h](https://github.com/Juwce/ActionRoguelike/blob/main/Source/ActionRoguelike/Public/TProjectileBase.h)

### Magic Projectile

![This magic projectile deals an initial burst of damage, then applies the 'burning' effect to actors it hits.](https://112794710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoURZQKJhQVbJ4EduVl8M%2Fuploads%2FVdmjqaV09yHl1BvqvR8g%2F7505745748a13757e9c0878c487a267f.gif?alt=media\&token=9e5056c8-76dc-4fb9-a64a-ea0f1b9e9b2b)

Magic projectiles are the most basic attack a player can perform, dealing damage, applying debuffs, and more. They extend the projectile base class with the following functionality:

Gameplay:

* Deals damage upon overlap (if overlapped object implements health)
* Can apply buffs/debuffs on overlap (if overlapped object implements actions)
* Can be parried / reflected (if overlapped object has parry tag)

Cosmetic:

* Applies camera shake around impact point

**See it on GitHub:** [TProjectile\_Magic.cpp](https://github.com/Juwce/ActionRoguelike/blob/main/Source/ActionRoguelike/Private/TProjectile_Magic.cpp) // [TProjectile\_Magic.h](https://github.com/Juwce/ActionRoguelike/blob/main/Source/ActionRoguelike/Public/TProjectile_Magic.h)

### Dash Projectile

![Left: Player uses dash ability three times. Right: Shows it from the perspective of another player (via networked multiplayer).](https://112794710-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoURZQKJhQVbJ4EduVl8M%2Fuploads%2FxieHY88jwRdxLkwgMTiJ%2F92463d2527cfe3d2acb9ca4a842edb2f.gif?alt=media\&token=836b3462-670f-474f-9914-01804ab0ff08)

Dash projectiles fly forward, exploding on impact or after a set duration expires, whichever comes first. Upon exploding, there is a short delay before the player is teleported to the explosion's impact point. They extend the projectile base class with the following functionality:

Gameplay:

* Explodes on impact or after a set duration, teleporting player to impact location after a short delay
* Configurable delay between spawn and explosion, and explosion and teleport

**See it on GitHub:** [TProjectile\_Dash.cpp](https://github.com/Juwce/ActionRoguelike/blob/main/Source/ActionRoguelike/Private/TProjectile_Dash.cpp) // [TProjectile\_Dash.h](https://github.com/Juwce/ActionRoguelike/blob/main/Source/ActionRoguelike/Public/TProjectile_Dash.h)
