For now, the Player will face Enemies of only one type - Minion. These Minion assets were sourced from the Paragon: Minions Asset Pack from the Epic Games Store. I will be adding more Enemies very soon from the Infinity Blade: Adversaries Asset Pack.
An Enemy’s Collision Volumes are as below:
All such Collision Volumes use the OnComponentBeginOverlap
and OnComponentEndOverlap
functions to perform actions if an overlap occurs.
AgroSphere - If the Character enters this sphere, the Enemy will get agressive and chase the Character. Chasing is done with UE4’s inbuilt MoveToTarget() function, using which the Enemy will follow a path to reach the Character’s location. This functionality only works inside NavMeshBounds Volumes.
CombatSphere - When the Enemy reaches close enough to the Character to make it overlap with the CombatSphere, the Enemy will begin attacking.
Additional functionality added is the ability for the Enemy to turn so that attacks hit the Character i.e. if the Character moves when it is attacking, it will turn so that it can look directly at the Character.
Attack Animations for Enemies are kept together in an Animation Montage. Out of the set of Animations, one is chosen at random.
void AEnemy::Attack()
{
if (Alive() && bHasValidTarget)
{
if (AIController)
{
// As Character is overlapping CombatSphere, there is no need to move
AIController->StopMovement();
SetEnemyMovementStatus(EEnemyMovementStatus::EMS_Attacking);
}
if (!bAttacking)
{
// Turn towards Character
SetInterpToEnemy(true);
bAttacking = true;
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
if (AnimInstance)
{
//Randomly choose between the 4 attack animations
AttackSection = FMath::RandRange(1, 4);
// Append the AttackSection to the FString below
FString AttackName("Attack_");
AttackName.AppendInt(AttackSection);
AnimInstance->Montage_Play(CombatMontage, 1.0f);
AnimInstance->Montage_JumpToSection(FName(*AttackName), CombatMontage);
}
}
}
}
If the CombatCollision overlaps with the Character, a check will be performed to see if the Character was blocking.
If the Character was not blocking, a function InflictDamageOnMain
is called. This function uses UE4’s ApplyDamage() function to decrease the
Character’s health, along with calling functions to emit blood particles and playing hit sounds.
The hit reaction animations are not picked at random, but are related to the AttackSection
shown above AND if the Character is facing the
attacking Enemy. As a result, the appropriate animation plays in reaction to the Enemy’s attack.
InflictDamageOnMain()
void AEnemy::InflictDamageOnMain(AMain* Main, bool bHitFromBehind)
{
// If Character was hit from behind
if (bHitFromBehind)
{
// Play HitFromBehind Animation
Main->Impact(1);
/**
* First 2 Attack Sockets in Main's SocketNames are the names of the Sockets that will be used
* if the Player gets hit by the Enemy facing them. By adding 4, we get the Sockets that will be used if
* the Player gets hit by the Enemy facing their back. Used below to use the appropriate Socket to emit the blood.
*/
AttackSection += 4;
}
// If Character was hit while facing the attacking Enemy
else
{
// Play appropriate Hit Reaction Animation
Main->Impact(AttackSection + 1);
}
// Spawn Blood particles
if (Main->HitParticles)
{
Main->SpawnHitParticles(this);
}
// Play Hit Sound
if (Main->HitSound)
{
UGameplayStatics::PlaySound2D(this, Main->HitSound);
}
// Apply Damage to Main
if (DamageTypeClass)
{
UGameplayStatics::ApplyDamage(Main, Damage, AIController, this, DamageTypeClass);
}
//In case the Player's attack was interrupted
Main->bAttacking = false;
Main->bInterpToEnemy = false;
}
Performed using the Right Mouse Button(RMB). The Character can block attacks using a One-Handed Weapon AND a Shield OR with a Two-Handed Weapon. One-Handed Weapons alone cannot be used for blocking.
The Character can walk while blocking. This is done by using UE4’s Layered Blend per bone
node, done before in the
Crouching post.
Blocking with Shield
Blocking with Two-Handed Weapon
To successfully block an Enemy’s attack, the Character has to be blocking AND has to be facing the attacking Enemy, while also having sufficient Stamina available.
Facing an Enemy means that the Enemy should be inside the Character’s Field of View (taken as 120°).
If the attack was blocked, the Character’s Stamina will reduce by BlockStaminaCost
(declared in the Weapon and Shield classes).
Additionally, if a Two-Handed Weapon was used for blocking, the Character’s Health will decrease by an amount DamageIfBlocked
,
as Weapons cannot block as effectively as Shields.
You can view the code of the project here!
One-Handed Weapon + Shield
Two-Handed Weapon