diff --git a/Content/ParagonGrux/Characters/Heroes/Grux/Animations/Death_A.uasset b/Content/ParagonGrux/Characters/Heroes/Grux/Animations/Death_A.uasset index 931d6fbb..07b534ad 100644 --- a/Content/ParagonGrux/Characters/Heroes/Grux/Animations/Death_A.uasset +++ b/Content/ParagonGrux/Characters/Heroes/Grux/Animations/Death_A.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1a5f140befef571c84c2f840f8c3bef7564ac1842cd8462456f9fc24bcb8357e -size 157646 +oid sha256:a59daf06b0ca313a7b4c2a682d0a90ec061223843da7d1b1e54ef27d2f78304c +size 351235 diff --git a/Content/ParagonGrux/Characters/Heroes/Grux/Animations/Death_B.uasset b/Content/ParagonGrux/Characters/Heroes/Grux/Animations/Death_B.uasset index e721f15c..718db05e 100644 --- a/Content/ParagonGrux/Characters/Heroes/Grux/Animations/Death_B.uasset +++ b/Content/ParagonGrux/Characters/Heroes/Grux/Animations/Death_B.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a098241c5e8aef011e63b6fadcc0ccfc856cc1be69badc37a0866dd7bc0e2638 -size 156546 +oid sha256:6188364ea8a0b99e2a69986784b6f4bf7369a4efc0d1fc4396091660b27e98ec +size 344296 diff --git a/Content/ParagonGrux/Characters/Heroes/Grux/Meshes/Grux_Skeleton.uasset b/Content/ParagonGrux/Characters/Heroes/Grux/Meshes/Grux_Skeleton.uasset index 784dfeb8..bbddc3da 100644 --- a/Content/ParagonGrux/Characters/Heroes/Grux/Meshes/Grux_Skeleton.uasset +++ b/Content/ParagonGrux/Characters/Heroes/Grux/Meshes/Grux_Skeleton.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:81e3dbe27061a6e13e346034be83649f3762dd317a83a1b04344b9827c1f3a3b -size 45879 +oid sha256:35e50c562a22bd7c597cbbd5095a2cd93b8634f4e36086d8d34d7dc5c1391eb9 +size 67635 diff --git a/Content/_Game/Enemies/Animations/EnemyHit.uasset b/Content/_Game/Enemies/Animations/EnemyHit.uasset new file mode 100644 index 00000000..18231c2a --- /dev/null +++ b/Content/_Game/Enemies/Animations/EnemyHit.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82edd6e694de0e0c0138e74fdfc0e939df9fc757e5a2889e5028289e622cbdd0 +size 12586 diff --git a/Content/_Game/Enemies/EnemyBP.uasset b/Content/_Game/Enemies/EnemyBP.uasset index 6964dac0..045c78f1 100644 --- a/Content/_Game/Enemies/EnemyBP.uasset +++ b/Content/_Game/Enemies/EnemyBP.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c69bcaa51d0fedf6eb2ef4d3b36c738040cb165bffdd84358b5b2a0a4a76137f -size 68665 +oid sha256:9eaa93cacb2579e69bacef3da38814f8ee42fbbf805f3bbe13f976db5858f8c2 +size 98749 diff --git a/Content/_Game/Enemies/GruxAnimBP.uasset b/Content/_Game/Enemies/GruxAnimBP.uasset new file mode 100644 index 00000000..17b7089a --- /dev/null +++ b/Content/_Game/Enemies/GruxAnimBP.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f0ddbf7b7698d913466186eb9c24f643cc590d0800dff2eaf60b04d0ea2909a +size 68548 diff --git a/Content/_Game/HUD/EnemyHealthBarBP.uasset b/Content/_Game/HUD/EnemyHealthBarBP.uasset index b7702508..19b825cb 100644 --- a/Content/_Game/HUD/EnemyHealthBarBP.uasset +++ b/Content/_Game/HUD/EnemyHealthBarBP.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:98fff25891e5908763df890c87a8abd83e9b52ba55cc24d3cebd4cead8ca81dd -size 46748 +oid sha256:7c5c02d4e244564fbb503b7ff2dcd9eb0c45c1c383c396a1bac9ef3c932508ff +size 46652 diff --git a/Content/_Game/HUD/HitNumber.uasset b/Content/_Game/HUD/HitNumber.uasset new file mode 100644 index 00000000..9f299f16 --- /dev/null +++ b/Content/_Game/HUD/HitNumber.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c66dd6cf4e53dd1e53bc7766bacb256e98a45075eb4c1af0e2721e2f6a44decd +size 23347 diff --git a/Content/_Game/Maps/DefaultMap.umap b/Content/_Game/Maps/DefaultMap.umap index 1cc42f88..e7678225 100644 --- a/Content/_Game/Maps/DefaultMap.umap +++ b/Content/_Game/Maps/DefaultMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1bf9ecce6c147370e9b830b9718b3210b0066614b07676814171e53e88b70267 -size 238616 +oid sha256:ecf19f29123f9a34d8d52ca003daa57f96d736d8c53cc6f358b3abe12b54f15d +size 238914 diff --git a/Source/Shooter/Enemy.cpp b/Source/Shooter/Enemy.cpp index a14773eb..9c173d2f 100644 --- a/Source/Shooter/Enemy.cpp +++ b/Source/Shooter/Enemy.cpp @@ -2,6 +2,8 @@ #include "Enemy.h" + +#include "Blueprint/UserWidget.h" #include "Kismet/GameplayStatics.h" #include "Sound/SoundCue.h" #include "Particles/ParticleSystemComponent.h" @@ -10,7 +12,11 @@ AEnemy::AEnemy() : Health(100.f), MaxHealth(100.f), - HealthBarDisplayTime(4.f) + HealthBarDisplayTime(4.f), + HitReactTimeMin(.5f), + HitReactTimeMax(1.f), + bCanHitReact(true), + HitNumberDestroyTime(1.5f) { // 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; @@ -31,6 +37,47 @@ void AEnemy::ShowHealthBar_Implementation() GetWorldTimerManager().SetTimer(HealthBarTimer, this, &AEnemy::HideHealthBar, HealthBarDisplayTime); } +void AEnemy::Die() +{ + HideHealthBar(); +} + +void AEnemy::PlayHitMontage(FName Section, float PlayRate) +{ + if (!bCanHitReact) return; + + if (UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance()) + { + AnimInstance->Montage_Play(HitMontage, PlayRate); + AnimInstance->Montage_JumpToSection(Section, HitMontage); + + bCanHitReact = false; + const float HitReactTime{ FMath::FRandRange(HitReactTimeMin, HitReactTimeMax) }; + GetWorldTimerManager().SetTimer(HitReactTimer, this, &AEnemy::ResetHitReactTimer, HitReactTime); + } +} + +void AEnemy::ResetHitReactTimer() +{ + bCanHitReact = true; +} + +void AEnemy::StoreHitNumber(UUserWidget* HitNumber, FVector Location) +{ + HitNumbers.Add(HitNumber, Location); + + FTimerHandle HitNumberTimer; + FTimerDelegate HitNumberDelegate; + HitNumberDelegate.BindUFunction(this, FName("DestroyHitNumber"), HitNumber); + GetWorldTimerManager().SetTimer(HitNumberTimer, HitNumberDelegate, HitNumberDestroyTime, false); +} + +void AEnemy::DestroyHitNumber(UUserWidget* HitNumber) +{ + HitNumbers.Remove(HitNumber); + HitNumber->RemoveFromParent(); +} + // Called every frame void AEnemy::Tick(float DeltaTime) { @@ -58,6 +105,8 @@ void AEnemy::BulletHit_Implementation(FHitResult HitResult) } ShowHealthBar(); + + PlayHitMontage(FName("HitReactFront")); } float AEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, @@ -68,6 +117,7 @@ float AEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AC { DamageInflicted = Health; Health = 0.f; + Die(); } else { diff --git a/Source/Shooter/Enemy.h b/Source/Shooter/Enemy.h index dc3f17cf..045f9a17 100644 --- a/Source/Shooter/Enemy.h +++ b/Source/Shooter/Enemy.h @@ -9,6 +9,7 @@ class UParticleSystem; class USoundCue; +class UAnimMontage; UCLASS() class SHOOTER_API AEnemy : public ACharacter, public IBulletHitInterface @@ -29,7 +30,18 @@ protected: UFUNCTION(BlueprintImplementableEvent) void HideHealthBar(); - + + void Die(); + + void PlayHitMontage(FName Section, float PlayRate = 1.0f); + + void ResetHitReactTimer(); + + UFUNCTION(BlueprintCallable) + void StoreHitNumber(UUserWidget* HitNumber, FVector Location); + + UFUNCTION() + void DestroyHitNumber(UUserWidget* HitNumber); private: /** Particles to spawn when hit by bullets */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true)) @@ -55,6 +67,28 @@ private: float HealthBarDisplayTime; FTimerHandle HealthBarTimer; + + /** Montage containing Hit and Death animations */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true)) + UAnimMontage* HitMontage; + + FTimerHandle HitReactTimer; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true)) + float HitReactTimeMin; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true)) + float HitReactTimeMax; + + bool bCanHitReact; + + /** Map to store HitNumber widgets and their hit locations */ + UPROPERTY(VisibleAnywhere, Category = Combat, meta = (AllowPrivateAccess = true)) + TMap HitNumbers; + + /** Time before a hit number is removed from the screen */ + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true)) + float HitNumberDestroyTime; public: // Called every frame virtual void Tick(float DeltaTime) override; @@ -67,4 +101,7 @@ public: virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override; FORCEINLINE FString GetHeadBone() const { return HeadBone; } + + UFUNCTION(BlueprintImplementableEvent) + void ShowHitNumber(int32 Damage, FVector HitLocation); }; diff --git a/Source/Shooter/GruxAnimInstance.cpp b/Source/Shooter/GruxAnimInstance.cpp new file mode 100644 index 00000000..4c72b016 --- /dev/null +++ b/Source/Shooter/GruxAnimInstance.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "GruxAnimInstance.h" + diff --git a/Source/Shooter/GruxAnimInstance.h b/Source/Shooter/GruxAnimInstance.h new file mode 100644 index 00000000..38081686 --- /dev/null +++ b/Source/Shooter/GruxAnimInstance.h @@ -0,0 +1,17 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Animation/AnimInstance.h" +#include "GruxAnimInstance.generated.h" + +/** + * + */ +UCLASS() +class SHOOTER_API UGruxAnimInstance : public UAnimInstance +{ + GENERATED_BODY() + +}; diff --git a/Source/Shooter/ShooterCharacter.cpp b/Source/Shooter/ShooterCharacter.cpp index 7115761d..18fa498f 100644 --- a/Source/Shooter/ShooterCharacter.cpp +++ b/Source/Shooter/ShooterCharacter.cpp @@ -688,7 +688,8 @@ void AShooterCharacter::SendBullet() damageToApply, GetController(), this, UDamageType::StaticClass()); - UE_LOG(LogTemp, Warning, TEXT("Hit Component: %s"), *BeamHitResult.BoneName.ToString()); + + HitEnemy->ShowHitNumber(damageToApply, BeamHitResult.Location); } } else