Section 15: AI and Behavior Trees - Lecture 310
Retargeting New Montages
This commit is contained in:
parent
a1ec63742e
commit
700f9ab66f
BIN
Content/FXVillesBloodVFXPack/MaterialFunctions/MF_SmoothStep.uasset (Stored with Git LFS)
Normal file
BIN
Content/FXVillesBloodVFXPack/MaterialFunctions/MF_SmoothStep.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/FXVillesBloodVFXPack/Materials/MAT_BloodClip_Master.uasset (Stored with Git LFS)
Normal file
BIN
Content/FXVillesBloodVFXPack/Materials/MAT_BloodClip_Master.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
Binary file not shown.
BIN
Content/FXVillesBloodVFXPack/Materials/MIC_BloodClip_Splat_2x2.uasset (Stored with Git LFS)
Normal file
BIN
Content/FXVillesBloodVFXPack/Materials/MIC_BloodClip_Splat_2x2.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/FXVillesBloodVFXPack/Particles/PS_Blood_Spurt_02.uasset (Stored with Git LFS)
Normal file
BIN
Content/FXVillesBloodVFXPack/Particles/PS_Blood_Spurt_02.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/FXVillesBloodVFXPack/Textures/T_Blood_Reflection.uasset (Stored with Git LFS)
Normal file
BIN
Content/FXVillesBloodVFXPack/Textures/T_Blood_Reflection.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/FXVillesBloodVFXPack/Textures/T_Blood_SubUV_2x2_01.uasset (Stored with Git LFS)
Normal file
BIN
Content/FXVillesBloodVFXPack/Textures/T_Blood_SubUV_2x2_01.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/FXVillesBloodVFXPack/Textures/T_Blood_SubUV_2x2_01_N.uasset (Stored with Git LFS)
Normal file
BIN
Content/FXVillesBloodVFXPack/Textures/T_Blood_SubUV_2x2_01_N.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
Binary file not shown.
BIN
Content/ParagonGrux/Characters/Heroes/Grux/Meshes/Grux_Skeleton.uasset (Stored with Git LFS)
BIN
Content/ParagonGrux/Characters/Heroes/Grux/Meshes/Grux_Skeleton.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/ParagonLtBelica/Characters/Heroes/Belica/Meshes/Belica_Skeleton.uasset (Stored with Git LFS)
BIN
Content/ParagonLtBelica/Characters/Heroes/Belica/Meshes/Belica_Skeleton.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Character/Belica/BelicaAnimBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Character/Belica/BelicaAnimBP.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Character/Belica/BelicaCharacterBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Character/Belica/BelicaCharacterBP.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/_Game/Character/Belica/HitReact/HitReactMontage.uasset (Stored with Git LFS)
Normal file
BIN
Content/_Game/Character/Belica/HitReact/HitReactMontage.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/_Game/Character/Revenant/HitReact/HitReactMontage.uasset (Stored with Git LFS)
Normal file
BIN
Content/_Game/Character/Revenant/HitReact/HitReactMontage.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/_Game/Character/Revenant/HitReact/HitReact_Front.uasset (Stored with Git LFS)
Normal file
BIN
Content/_Game/Character/Revenant/HitReact/HitReact_Front.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/_Game/Character/Revenant/Idle/Idle_Zero_Pose.uasset (Stored with Git LFS)
BIN
Content/_Game/Character/Revenant/Idle/Idle_Zero_Pose.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Character/Revenant/RevenantAnimBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Character/Revenant/RevenantAnimBP.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Character/Revenant/RevenantCharacterBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Character/Revenant/RevenantCharacterBP.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/_Game/Character/TwinBlast/HitReact/HitReactMontage.uasset (Stored with Git LFS)
Normal file
BIN
Content/_Game/Character/TwinBlast/HitReact/HitReactMontage.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/_Game/Character/TwinBlast/HitReact/HitReact_Front.uasset (Stored with Git LFS)
Normal file
BIN
Content/_Game/Character/TwinBlast/HitReact/HitReact_Front.uasset (Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/_Game/Character/TwinBlast/Idle/Idle_Zero_Pose.uasset (Stored with Git LFS)
BIN
Content/_Game/Character/TwinBlast/Idle/Idle_Zero_Pose.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Character/TwinBlast/TwinBlastAnimBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Character/TwinBlast/TwinBlastAnimBP.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Character/TwinBlast/TwinBlastCharacterBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Character/TwinBlast/TwinBlastCharacterBP.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/_Game/Enemies/Animations/EnemyHit.uasset (Stored with Git LFS)
BIN
Content/_Game/Enemies/Animations/EnemyHit.uasset (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/_Game/Enemies/EnemyBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Enemies/EnemyBP.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Enemies/GruxAnimBP.uasset (Stored with Git LFS)
BIN
Content/_Game/Enemies/GruxAnimBP.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/EnemyController/EnemyBehaviorTree.uasset (Stored with Git LFS)
BIN
Content/_Game/EnemyController/EnemyBehaviorTree.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/EnemyController/EnemyBlackboard.uasset (Stored with Git LFS)
BIN
Content/_Game/EnemyController/EnemyBlackboard.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/GameMode/ShooterGameModeBaseBP.uasset (Stored with Git LFS)
BIN
Content/_Game/GameMode/ShooterGameModeBaseBP.uasset (Stored with Git LFS)
Binary file not shown.
BIN
Content/_Game/Maps/DefaultMap.umap (Stored with Git LFS)
BIN
Content/_Game/Maps/DefaultMap.umap (Stored with Git LFS)
Binary file not shown.
|
@ -15,6 +15,7 @@
|
|||
#include "ShooterCharacter.h"
|
||||
#include "Components/BoxComponent.h"
|
||||
#include "Components/CapsuleComponent.h"
|
||||
#include "Engine/SkeletalMeshSocket.h"
|
||||
|
||||
// Sets default values
|
||||
AEnemy::AEnemy() :
|
||||
|
@ -31,7 +32,13 @@ AEnemy::AEnemy() :
|
|||
AttackRFast(TEXT("AttackRFast")),
|
||||
AttackL(TEXT("AttackL")),
|
||||
AttackR(TEXT("AttackR")),
|
||||
BaseDamage(20.f)
|
||||
BaseDamage(20.f),
|
||||
LeftWeaponSocket(TEXT("FX_Trail_L_02")),
|
||||
RightWeaponSocket(TEXT("FX_Trail_R_02")),
|
||||
bCanAttack(true),
|
||||
AttackWaitTime(1.f),
|
||||
bDying(false),
|
||||
DeathTime(4.f)
|
||||
{
|
||||
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
@ -83,11 +90,16 @@ void AEnemy::BeginPlay()
|
|||
// Get the AI Controller
|
||||
EnemyController = Cast<AEnemyController>(GetController());
|
||||
|
||||
if (EnemyController)
|
||||
{
|
||||
EnemyController->GetBlackboardComponent()->SetValueAsBool(TEXT("CanAttack"), true);
|
||||
}
|
||||
|
||||
const FVector WorldPatrolPoint = UKismetMathLibrary::TransformLocation(GetActorTransform(), PatrolPoint);
|
||||
DrawDebugSphere(GetWorld(), WorldPatrolPoint, 25.f, 12, FColor::Red, true);
|
||||
//DrawDebugSphere(GetWorld(), WorldPatrolPoint, 25.f, 12, FColor::Red, true);
|
||||
|
||||
const FVector WorldPatrolPoint2 = UKismetMathLibrary::TransformLocation(GetActorTransform(), PatrolPoint2);
|
||||
DrawDebugSphere(GetWorld(), WorldPatrolPoint2, 25.f, 12, FColor::Blue, true);
|
||||
//DrawDebugSphere(GetWorld(), WorldPatrolPoint2, 25.f, 12, FColor::Blue, true);
|
||||
|
||||
if (EnemyController)
|
||||
{
|
||||
|
@ -105,7 +117,34 @@ void AEnemy::ShowHealthBar_Implementation()
|
|||
|
||||
void AEnemy::Die()
|
||||
{
|
||||
if (bDying) return;
|
||||
bDying = true;
|
||||
|
||||
HideHealthBar();
|
||||
|
||||
if (EnemyController)
|
||||
{
|
||||
EnemyController->GetBlackboardComponent()->SetValueAsBool("Dead", true);
|
||||
EnemyController->StopMovement();
|
||||
}
|
||||
|
||||
if (!DeathMontage) return;
|
||||
|
||||
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
|
||||
if (!AnimInstance) return;
|
||||
|
||||
AnimInstance->Montage_Play(DeathMontage);
|
||||
}
|
||||
|
||||
void AEnemy::FinishDeath()
|
||||
{
|
||||
GetMesh()->bPauseAnims = true;
|
||||
GetWorldTimerManager().SetTimer(DeathTimer, this, &AEnemy::DestroyEnemy, DeathTime);
|
||||
}
|
||||
|
||||
void AEnemy::DestroyEnemy()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void AEnemy::PlayHitMontage(FName Section, float PlayRate)
|
||||
|
@ -188,7 +227,7 @@ void AEnemy::CombatRangeOverlap(UPrimitiveComponent* OverlappedComponent, AActor
|
|||
|
||||
if (!EnemyController) return;
|
||||
EnemyController->GetBlackboardComponent()->SetValueAsBool(TEXT("InAttackRange"), true);
|
||||
UE_LOG(LogTemp, Warning, TEXT("overlap player"));
|
||||
//UE_LOG(LogTemp, Warning, TEXT("overlap player"));
|
||||
}
|
||||
|
||||
void AEnemy::CombatRangeEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
|
@ -201,7 +240,7 @@ void AEnemy::CombatRangeEndOverlap(UPrimitiveComponent* OverlappedComponent, AAc
|
|||
|
||||
if (!EnemyController) return;
|
||||
EnemyController->GetBlackboardComponent()->SetValueAsBool(TEXT("InAttackRange"), false);
|
||||
UE_LOG(LogTemp, Warning, TEXT("end overlap player"));
|
||||
//UE_LOG(LogTemp, Warning, TEXT("end overlap player"));
|
||||
}
|
||||
|
||||
void AEnemy::PlayAttackMontage(FName Section, float PlayRate)
|
||||
|
@ -212,6 +251,12 @@ void AEnemy::PlayAttackMontage(FName Section, float PlayRate)
|
|||
AnimInstance->Montage_Play(AttackMontage, PlayRate);
|
||||
AnimInstance->Montage_JumpToSection(Section, AttackMontage);
|
||||
}
|
||||
bCanAttack = false;
|
||||
GetWorldTimerManager().SetTimer(AttackWaitTimer, this, &AEnemy::ResetCanAttack, AttackWaitTime);
|
||||
if (EnemyController)
|
||||
{
|
||||
EnemyController->GetBlackboardComponent()->SetValueAsBool(TEXT("CanAttack"), false);
|
||||
}
|
||||
}
|
||||
|
||||
FName AEnemy::GetAttackSectionName() const
|
||||
|
@ -231,29 +276,73 @@ FName AEnemy::GetAttackSectionName() const
|
|||
}
|
||||
}
|
||||
|
||||
void AEnemy::DoDamage(AActor* Victim)
|
||||
void AEnemy::DoDamage(AShooterCharacter* Victim)
|
||||
{
|
||||
if (!Victim) return;
|
||||
if (auto const Character = Cast<AShooterCharacter>(Victim))
|
||||
{
|
||||
UGameplayStatics::ApplyDamage(Character, BaseDamage, EnemyController, this, UDamageType::StaticClass());
|
||||
if (USoundCue* MeleeImpactSound = Character->GetMeleeImpactSound())
|
||||
|
||||
UGameplayStatics::ApplyDamage(Victim, BaseDamage, EnemyController, this, UDamageType::StaticClass());
|
||||
if (USoundCue* MeleeImpactSound = Victim->GetMeleeImpactSound())
|
||||
{
|
||||
UGameplayStatics::PlaySoundAtLocation(this, MeleeImpactSound, GetActorLocation());
|
||||
}
|
||||
}
|
||||
|
||||
void AEnemy::SpawnBlood(AShooterCharacter* Victim, FName WeaponSocket)
|
||||
{
|
||||
if (!Victim) return;
|
||||
|
||||
UParticleSystem* Particles = Victim->GetBloodParticles();
|
||||
if (!Particles) return;
|
||||
|
||||
const USkeletalMeshSocket* TipSocket{ GetMesh()->GetSocketByName(WeaponSocket) };
|
||||
if (!TipSocket) return;
|
||||
|
||||
const FTransform SocketTransform{ TipSocket->GetSocketTransform(GetMesh()) };
|
||||
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), Particles, SocketTransform);
|
||||
}
|
||||
|
||||
void AEnemy::StunCharacter(AShooterCharacter* Victim)
|
||||
{
|
||||
if (!Victim) return;
|
||||
|
||||
const float Stun{ FMath::RandRange(0.f,1.f) };
|
||||
|
||||
if (Stun <= Victim->GetStunChance())
|
||||
{
|
||||
Victim->Stun();
|
||||
}
|
||||
}
|
||||
|
||||
void AEnemy::ResetCanAttack()
|
||||
{
|
||||
bCanAttack = true;
|
||||
|
||||
if (!EnemyController) return;
|
||||
EnemyController->GetBlackboardComponent()->SetValueAsBool(TEXT("CanAttack"), true);
|
||||
}
|
||||
|
||||
void AEnemy::OnLeftWeaponOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
|
||||
{
|
||||
DoDamage(OtherActor);
|
||||
auto const Character = Cast<AShooterCharacter>(OtherActor);
|
||||
if (Character)
|
||||
{
|
||||
DoDamage(Character);
|
||||
SpawnBlood(Character, LeftWeaponSocket);
|
||||
StunCharacter(Character);
|
||||
}
|
||||
}
|
||||
|
||||
void AEnemy::OnRightWeaponOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
|
||||
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
|
||||
{
|
||||
DoDamage(OtherActor);
|
||||
auto const Character = Cast<AShooterCharacter>(OtherActor);
|
||||
if (Character)
|
||||
{
|
||||
DoDamage(Character);
|
||||
SpawnBlood(Character, RightWeaponSocket);
|
||||
StunCharacter(Character);
|
||||
}
|
||||
}
|
||||
|
||||
void AEnemy::ActivateLeftWeapon()
|
||||
|
@ -303,6 +392,8 @@ void AEnemy::BulletHit_Implementation(FHitResult HitResult)
|
|||
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ImpactParticles, HitResult.Location, FRotator(0.f), true);
|
||||
}
|
||||
|
||||
if (bDying) return;
|
||||
|
||||
ShowHealthBar();
|
||||
|
||||
// Determine whether bullet hit stuns
|
||||
|
@ -318,6 +409,12 @@ void AEnemy::BulletHit_Implementation(FHitResult HitResult)
|
|||
float AEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator,
|
||||
AActor* DamageCauser)
|
||||
{
|
||||
// Set the Target blackboard key to aggro the character
|
||||
if (EnemyController)
|
||||
{
|
||||
EnemyController->GetBlackboardComponent()->SetValueAsObject(FName("Target"), DamageCauser);
|
||||
}
|
||||
|
||||
float DamageInflicted = DamageAmount;
|
||||
if (Health - DamageAmount <= 0.f)
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@ class UBehaviorTree;
|
|||
class AEnemyController;
|
||||
class USphereComponent;
|
||||
class UBoxComponent;
|
||||
class AShooterCharacter;
|
||||
|
||||
UCLASS()
|
||||
class SHOOTER_API AEnemy : public ACharacter, public IBulletHitInterface
|
||||
|
@ -99,7 +100,18 @@ protected:
|
|||
UFUNCTION(BlueprintCallable)
|
||||
void DeactivateRightWeapon();
|
||||
|
||||
void DoDamage(AActor* Victim);
|
||||
void DoDamage(AShooterCharacter* Victim);
|
||||
void SpawnBlood(AShooterCharacter* Victim, FName WeaponSocket);
|
||||
|
||||
// Attemp to stun character
|
||||
void StunCharacter(AShooterCharacter* Victim);
|
||||
|
||||
void ResetCanAttack();
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void FinishDeath();
|
||||
|
||||
void DestroyEnemy();
|
||||
private:
|
||||
/** Particles to spawn when hit by bullets */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
|
@ -202,6 +214,34 @@ private:
|
|||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
float BaseDamage;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
FName LeftWeaponSocket;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
FName RightWeaponSocket;
|
||||
|
||||
/** True when Enemy can attack */
|
||||
UPROPERTY(VisibleAnywhere, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
bool bCanAttack;
|
||||
|
||||
FTimerHandle AttackWaitTimer;
|
||||
|
||||
/** Min wait time between attacks */
|
||||
UPROPERTY(EditAnywhere, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
float AttackWaitTime;
|
||||
|
||||
/** Death anim montage */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
UAnimMontage* DeathMontage;
|
||||
|
||||
bool bDying;
|
||||
|
||||
FTimerHandle DeathTimer;
|
||||
|
||||
/** Time after death until Destroy */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
float DeathTime;
|
||||
public:
|
||||
// Called every frame
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "BulletHitInterface.h"
|
||||
#include "Enemy.h"
|
||||
#include "PhysicalMaterials/PhysicalMaterial.h"
|
||||
#include "EnemyController.h"
|
||||
#include "BehaviorTree/BlackboardComponent.h"
|
||||
|
||||
// Sets default values
|
||||
AShooterCharacter::AShooterCharacter() :
|
||||
|
@ -79,7 +81,8 @@ AShooterCharacter::AShooterCharacter() :
|
|||
// Icon animation property
|
||||
HighlightedSlot(-1),
|
||||
Health(100.f),
|
||||
MaxHealth(100.f)
|
||||
MaxHealth(100.f),
|
||||
StunChance(.25f)
|
||||
{
|
||||
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
@ -212,7 +215,13 @@ float AShooterCharacter::TakeDamage(float DamageAmount, FDamageEvent const& Dama
|
|||
{
|
||||
DamageInflicted = Health;
|
||||
Health = 0.f;
|
||||
//Die();
|
||||
Die();
|
||||
|
||||
auto EnemyController = Cast<AEnemyController>(EventInstigator);
|
||||
if (EnemyController)
|
||||
{
|
||||
EnemyController->GetBlackboardComponent()->SetValueAsBool(FName("CharacterDead"), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -221,6 +230,26 @@ float AShooterCharacter::TakeDamage(float DamageAmount, FDamageEvent const& Dama
|
|||
return DamageInflicted;
|
||||
}
|
||||
|
||||
void AShooterCharacter::Die()
|
||||
{
|
||||
if (!DeathMontage) return;
|
||||
|
||||
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
|
||||
if (!AnimInstance) return;
|
||||
|
||||
AnimInstance->Montage_Play(DeathMontage);
|
||||
}
|
||||
|
||||
void AShooterCharacter::FinishDeath()
|
||||
{
|
||||
GetMesh()->bPauseAnims = true;
|
||||
APlayerController* PC = UGameplayStatics::GetPlayerController(this, 0);
|
||||
if (PC)
|
||||
{
|
||||
DisableInput(PC);
|
||||
}
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
void AShooterCharacter::Tick(float DeltaTime)
|
||||
{
|
||||
|
@ -309,7 +338,9 @@ void AShooterCharacter::LookUp(float Value)
|
|||
void AShooterCharacter::AimingButtonPressed()
|
||||
{
|
||||
bAimingButtonPressed = true;
|
||||
if (CombatState != ECombatState::ECS_Reloading && CombatState != ECombatState::ECS_Equipping)
|
||||
if (CombatState != ECombatState::ECS_Reloading &&
|
||||
CombatState != ECombatState::ECS_Equipping &&
|
||||
CombatState != ECombatState::ECS_Stunned)
|
||||
{
|
||||
Aim();
|
||||
}
|
||||
|
@ -504,6 +535,16 @@ EPhysicalSurface AShooterCharacter::GetSurfaceType()
|
|||
return UPhysicalMaterial::DetermineSurfaceType(HitResult.PhysMaterial.Get());
|
||||
}
|
||||
|
||||
void AShooterCharacter::EndStun()
|
||||
{
|
||||
CombatState = ECombatState::ECS_Unoccupied;
|
||||
|
||||
if (bAimingButtonPressed)
|
||||
{
|
||||
Aim();
|
||||
}
|
||||
}
|
||||
|
||||
void AShooterCharacter::UnhighlightInventorySlot()
|
||||
{
|
||||
if (HighlightedSlot != -1)
|
||||
|
@ -513,6 +554,19 @@ void AShooterCharacter::UnhighlightInventorySlot()
|
|||
}
|
||||
}
|
||||
|
||||
void AShooterCharacter::Stun()
|
||||
{
|
||||
if (Health <= 0.f) return;
|
||||
if (!HitReactMontage) return;
|
||||
|
||||
UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
|
||||
if (!AnimInstance) return;
|
||||
|
||||
CombatState = ECombatState::ECS_Stunned;
|
||||
|
||||
AnimInstance->Montage_Play(HitReactMontage);
|
||||
}
|
||||
|
||||
int32 AShooterCharacter::GetInterpLocationIndex()
|
||||
{
|
||||
int32 LowestIndex = 1;
|
||||
|
@ -632,6 +686,7 @@ void AShooterCharacter::StartFireTimer()
|
|||
void AShooterCharacter::AutoFireReset()
|
||||
{
|
||||
if (!EquippedWeapon) return;
|
||||
if (CombatState == ECombatState::ECS_Stunned) return;
|
||||
|
||||
CombatState = ECombatState::ECS_Unoccupied;
|
||||
|
||||
|
@ -1135,6 +1190,7 @@ void AShooterCharacter::ReloadWeapon()
|
|||
void AShooterCharacter::FinishReloading()
|
||||
{
|
||||
if (!EquippedWeapon) return;
|
||||
if (CombatState == ECombatState::ECS_Stunned) return;
|
||||
|
||||
CombatState = ECombatState::ECS_Unoccupied;
|
||||
|
||||
|
@ -1175,6 +1231,8 @@ void AShooterCharacter::FinishReloading()
|
|||
|
||||
void AShooterCharacter::FinishEquipping()
|
||||
{
|
||||
if (CombatState == ECombatState::ECS_Stunned) return;
|
||||
|
||||
CombatState = ECombatState::ECS_Unoccupied;
|
||||
|
||||
if (bAimingButtonPressed)
|
||||
|
|
|
@ -25,6 +25,7 @@ enum class ECombatState : uint8
|
|||
ECS_FireTimerInProgress UMETA(DisplayName = "FireTimerInProgress"),
|
||||
ECS_Reloading UMETA(DisplayName = "Reloading"),
|
||||
ECS_Equipping UMETA(DisplayName = "Equipping"),
|
||||
ECS_Stunned UMETA(DisplayName = "Stunned"),
|
||||
|
||||
ECS_MAX UMETA(DisplayName = "DefaultMax")
|
||||
};
|
||||
|
@ -221,6 +222,13 @@ protected:
|
|||
UFUNCTION(BlueprintCallable)
|
||||
EPhysicalSurface GetSurfaceType();
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void EndStun();
|
||||
|
||||
void Die();
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void FinishDeath();
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = true))
|
||||
USpringArmComponent* CameraBoom;
|
||||
|
@ -500,6 +508,22 @@ private:
|
|||
/** Sound made when character gets hit by a melee attack */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
USoundCue* MeleeImpactSound;
|
||||
|
||||
/** Blood splatter particles for melee hit */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
UParticleSystem* BloodParticles;
|
||||
|
||||
/** Hit react anim montage; for when the character is stunned */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
UAnimMontage* HitReactMontage;
|
||||
|
||||
/** Chance of being stunned when hit by an enemy */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
float StunChance;
|
||||
|
||||
/** Character death anim montage */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
|
||||
UAnimMontage* DeathMontage;
|
||||
public:
|
||||
/* Returns CameraBoom SubObject */
|
||||
FORCEINLINE USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
|
||||
|
@ -557,4 +581,8 @@ public:
|
|||
float GetMaxHealth() const { return MaxHealth; }
|
||||
|
||||
FORCEINLINE USoundCue* GetMeleeImpactSound() const { return MeleeImpactSound; }
|
||||
FORCEINLINE UParticleSystem* GetBloodParticles() const { return BloodParticles; }
|
||||
|
||||
void Stun();
|
||||
FORCEINLINE float GetStunChance() const { return StunChance; }
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue