UE5.1.1C++ starts from 0 (10. Homework 3)

The amount of homework this time may be a bit larger than the previous ones. Let me sort out the homework list for this time:

  1. The flying sound of magic bullets and the sound of explosion
  2. Adds a shiny effect to the player when hit, the same kind as the cube
  3. Add a health max variable, replace the health node in the widget with the health max node, and set an upper and lower limit for health, the upper limit is health max, and the lower limit is 0
  4. Set an animation for the damage display widget we just created, and play it when it is hit. At the same time, the damage display cannot be written to death, and it is represented by a variable
  5. Create a new health potion, which can restore health. After recovering once, it cannot be used again within 10 seconds, and can be used again after 10 seconds. Ignore player interaction when player is full health
  6. Add a particle effect to the player’s hand (I didn’t understand this, I didn’t write it)
  7. Add a shake camera effect

There are a total of 7 assignments, and the amount can be said to be very large. . . But still do it one by one.

1. The flying sound and explosion effect of the magic bullet:

I wrote this function into SFatherMagicProjectile

SFatherMagicProjectile.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SFatherMagicProjectile.generated.h"

UCLASS()
class ACTIONROGUELIKE_API ASFatherMagicProjectile : public AActor
{<!-- -->
GENERATED_BODY()

public:
UPROPERTY (Edit Anywhere)
class USphereComponent * SphereComp;

UPROPERTY (Edit Anywhere)
class UProjectileMovementComponent * MovementComp;

UPROPERTY (Edit Anywhere)
class UParticleSystemComponent * ParticleComp;
\t
    //A sound component
UPROPERTY (Edit Anywhere)
class UAudioComponent * AudioComp;
\t
    //Explosion
UPROPERTY (Edit Anywhere)
class USoundBase * Sound;
\t
public:
// Sets default values for this actor's properties
ASFatherMagicProjectile();

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;

public:
// Called every frame
virtual void Tick(float DeltaTime) override;

UFUNCTION()
virtual void OnComponentHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, FHitResult Hit);

UFUNCTION()
void OnComponentOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & amp; SweepResult);
};

SFatherMagicProjectile.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "SFatherMagicProjectile.h"
#include "Components/SphereComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Particles/ParticleSystemComponent.h"
#include "SAttributeComponent.h"
#include "Components/AudioComponent.h"
#include "Kismet/GameplayStatics.h"

// Sets default values
ASFatherMagicProjectile::ASFatherMagicProjectile()
{<!-- -->
 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;

FScriptDelegate OnHit;
OnHit.BindUFunction(this, STATIC_FUNCTION_FNAME(TEXT("ASFatherMagicProjectile::OnComponentHit")));

FScriptDelegateOnOverlap;
OnOverlap.BindUFunction(this, STATIC_FUNCTION_FNAME(TEXT("ASFatherMagicProjectile::OnComponentOverlap")));

SphereComp = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere Comp"));
SphereComp->SetCollisionProfileName("Projectile");
SphereComp->SetSphereRadius(10.0f, true);
SphereComp->OnComponentHit.Add(OnHit);
SphereComp->OnComponentBeginOverlap. Add(OnOverlap);
RootComponent = SphereComp;

MovementComp = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("Movement Comp"));
MovementComp->InitialSpeed = 1000.0f;
MovementComp->bRotationFollowsVelocity = true;
MovementComp->bInitialVelocityInLocalSpace = true;
MovementComp->ProjectileGravityScale = 0.0f;

ParticleComp = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("Particle Comp"));
ParticleComp->SetupAttachment(SphereComp);

AudioComp = CreateDefaultSubobject<UAudioComponent>(TEXT("Audio Comp"));
\t
}

// Called when the game starts or when spawned
void ASFatherMagicProjectile::BeginPlay()
{<!-- -->
Super::BeginPlay();

APawn* Instigator_01 = AActor::GetInstigator();

SphereComp->IgnoreActorWhenMoving(Instigator_01, true);

    //play flight sound
AudioComp->Play(0.0f);
\t
}

// Called every frame
void ASFatherMagicProjectile::Tick(float DeltaTime)
{<!-- -->
Super::Tick(DeltaTime);

}

void ASFatherMagicProjectile::OnComponentHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, FHitResult Hit)
{<!-- -->
APawn* Instigator_01 = AActor::GetInstigator();

if (Instigator_01!=OtherActor)
{<!-- -->
        //play the explosion sound
UGameplayStatics::PlaySoundAtLocation(GetWorld(),Sound , this->GetActorLocation(), 1.0f, 1.0f);
GetWorld()->DestroyActor(this);
DrawDebugSphere(GetWorld(), Hit. ImpactPoint, 10.0f, 16, FColor::Red, false, 2.0f, 0U, 1.0f);
\t\t
}
}

void ASFatherMagicProjectile::OnComponentOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & amp; SweepResult)
{<!-- -->
APawn* Instigator_01 = AActor::GetInstigator();

if (OtherActor)
{<!-- -->
USAttributeComponent* AttributeComp = Cast<USAttributeComponent>(OtherActor->GetComponentByClass(USAttributeComponent::StaticClass()));
if (AttributeComp)
{<!-- -->
if (Instigator_01 != OtherActor)
{<!-- -->
UGameplayStatics::Play
AtLocation(GetWorld(), Sound, this->GetActorLocation(), 1.0f, 1.0f);
AttributeComp->ApplyHealthChange(-20.0f);
GetWorld()->DestroyActor(this);
}
}

}
}




2. Add a shiny effect to the player, the same as the cube

This first has to modify the material of our Gideon

Please add a picture description

Use the MatLayerBlend_Emissive function, and then connect our MF_HitFlash, and then change the code of the player character

SCharacter.cpp

void ASCharacter::OnHealthChanged(AActor* InstigatorActor, USAttributeComponent* OwningComp, float NewHealth, float Delta)
{<!-- -->
    //This function has been changed. The first point is that only damage will trigger the shining effect, and it does not need to trigger this effect when adding blood
if (NewHealth<0.0f)
{<!-- -->
this->GetMesh()->SetScalarParameterValueOnMaterials("TimeToHit", GetWorld()->TimeSeconds);
if (Delta<0.0f)
{<!-- -->
APlayerController* PC = Cast<APlayerController>(GetController());
DisableInput(PC);
}
}
\t
}

3. Add a health max variable, replace the health node in the widget with the health max node, and set an upper and lower limit for health, the upper limit is health max, and the lower limit is 0

This is quite simple, change as follows

SAttributeComponent.cpp

bool USAttributeComponent::ApplyHealthChange(float Delta)
{<!-- -->
\t
    //Using the Clamp function, the change of Health is displayed in the first parameter of the Clamp function
Health = FMath::Clamp(Health + Delta, 0, HealthMax);


OnHealthChanged. Broadcast(nullptr, this, Health, Delta);
return true;
}

4. Set an animation for the widget we just created to display the damage, and play it when it is hit. At the same time, the damage display cannot be written to death, and it is represented by a variable

Please add a picture description

Cube blueprint changes

Please add picture description
As for how to play the animation, it depends on everyone’s design. There are thousands of people and faces here.

5. Create a new health potion, which can restore health. After recovering once, it cannot be used again within 10 seconds, and can be used again after 10 seconds. Ignore player interaction when player is full health

This has not encountered any major problems. The example of this is our box that can be opened and closed.

SHealBottle.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SGameplayInterface.h"
#include "SHealBottle.generated.h"

UCLASS()
class ACTIONROGUELIKE_API ASHealBottle : public AActor, public ISGameplayInterface
{<!-- -->
GENERATED_BODY()

void Interact_Implementation(APawn* InstigatorPawn) override;

UPROPERTY (VisibleAnywhere)
class UStaticMeshComponent* MeshComp;

private:
UFUNCTION()
void RefreshBottle();

private:
bool CanHeal;
\t
FTimerHandle Timer;

public:
// Sets default values for this actor's properties
ASHealBottle();

protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;

public:
// Called every frame
virtual void Tick(float DeltaTime) override;

};

SHealBottle.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "SHealBottle.h"
#include "Components/StaticMeshComponent.h"
#include "SAttributeComponent.h"

//Implementation of the interface function
void ASHealBottle::Interact_Implementation(APawn* InstigatorPawn)
{<!-- -->
ASCharacter* InstigatorCharacter_01 = Cast<ASCharacter>(InstigatorPawn);
USAttributeComponent* attributeComp_01 = InstigatorCharacter_01->AttributeComp;
if (attributeComp_01->GetHealth()>=100||!CanHeal)
{<!-- -->
return;
}
attributeComp_01->ApplyHealthChange(10.0f);
CanHeal = false;
MeshComp->SetVisibility(false);
    //disappear for 10 seconds
GetWorldTimerManager().SetTimer(Timer,this, &ASHealBottle::RefreshBottle, 10.0f);
}

void ASHealBottle::RefreshBottle()
{<!-- -->
CanHeal = true;
MeshComp->SetVisibility(true);
}

// Sets default values
ASHealBottle::ASHealBottle()
{<!-- -->
 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;

MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh Comp"));

CanHeal = true;

}

// Called when the game starts or when spawned
void ASHealBottle::BeginPlay()
{<!-- -->
Super::BeginPlay();
\t
}

// Called every frame
void ASHealBottle::Tick(float DeltaTime)
{<!-- -->
Super::Tick(DeltaTime);

}


7. Add an effect of shaking the camera

SCharacter.cpp

void ASCharacter::PrimaryAttack()
{<!-- -->
\t
    // get the controller
APlayerController* pc = Cast<APlayerController>(GetController());
//Play the vibration of the camera
pc->ClientStartCameraShake(CameraShakeComp);

GetWorldTimerManager().SetTimer(TimerHandle_PrimaryAttack, this, &ASCharacter::PrimaryAttack_TimeElasped, 0.2f);
\t
}