DO I need to call this function on a server?
I have a SHealthComponent (which handles the incoming damage) and ExplosiveBarrel – owns the SHealthComponent and add explosion effects
ExplosiveBarrel.h
[SPOILER]
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "SExplosiveBarrel.generated.h"
class UStaticMeshComponent;
class UParticleSystem;
class USHealthComponent;
class URadialForceComponent;
class UMaterialInterface;
UCLASS()
class COOPGAME_API ASExplosiveBarrel : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ASExplosiveBarrel();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UPROPERTY(VisibleAnywhere, Category = "Components")
UStaticMeshComponent* MeshComp;
UPROPERTY(VisibleAnywhere, Category = "Components")
USHealthComponent* HealthComp;
UPROPERTY(VisibleAnywhere, Category = "Components")
URadialForceComponent* RadialForceComp;
UPROPERTY(EditDefaultsOnly, Category = "FX")
UParticleSystem* ExplosionEffect;
UPROPERTY(EditDefaultsOnly, Category = "FX")
float ExplostionImpulse;
UPROPERTY(EditDefaultsOnly, Category = "FX")
UMaterialInterface* ExplodedMaterial;
UFUNCTION()
void OnHealthChanched(USHealthComponent* OwningHealthComponent, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser);
// NotifyRep
UPROPERTY(ReplicatedUsing = OnRep_Exploded)
bool bIsExploded;
UFUNCTION()
void OnRep_Exploded();
virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const override;
public:
};
[/SPOILER]
ExplosiveBarrel.cpp
[SPOILER]
// Fill out your copyright notice in the Description page of Project Settings.
#include "Public/SExplosiveBarrel.h"
#include "PhysicsEngine/RadialForceComponent.h"
#include "Public/Components/SHealthComponent.h"
#include "Kismet/GameplayStatics.h"
#include "Net/UnrealNetwork.h"
// Sets default values
ASExplosiveBarrel::ASExplosiveBarrel()
{
HealthComp = CreateDefaultSubobject<USHealthComponent>(TEXT("HealthComp"));
MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
MeshComp->SetSimulatePhysics(true);
MeshComp->SetCollisionObjectType(ECC_PhysicsBody);
RootComponent = MeshComp;
RadialForceComp = CreateDefaultSubobject<URadialForceComponent>(TEXT("RadialForceComp"));
RadialForceComp->Radius = 300.0;
RadialForceComp->bIgnoreOwningActor = true; // ignore self
RadialForceComp->bAutoActivate = false; // to prevent auto adding force instead use FireImpulse()
RadialForceComp->bImpulseVelChange = true; // will ignore mass of objects
RadialForceComp->ImpulseStrength = 400;
RadialForceComp->SetupAttachment(RootComponent);
bIsExploded = false;
ExplostionImpulse = 400.0f;
HealthComp->OnHealthChanged.AddDynamic(this, &ASExplosiveBarrel::OnHealthChanched);
SetReplicates(true);
SetReplicateMovement(true);
}
// Called when the game starts or when spawned
void ASExplosiveBarrel::BeginPlay()
{
Super::BeginPlay();
}
// full func runs on the server(because OnHealthChanched is ShealthComponent`s function which is called only from server
void ASExplosiveBarrel::OnHealthChanched(USHealthComponent* OwningHealthComponent, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
{
if (bIsExploded) {
return;
}
if (Health == 0.0f) {
bIsExploded = true;
// UPROPERTY(ReplicatedUsing = OnRep_Exploded) bool bIsExploded;
// so on the variable change, this function will be called
***// DO I need to call this func on a server?***
*** //OnRep_Exploded();
// DO I need to call this func on a server?***
//Because this is already works w/o it. So I think I do not need it, because of **UPROPERTY(ReplicatedUsing = OnRep_Exploded) bool bIsExploded;**
FVector BoostIntensity = FVector::UpVector * ExplostionImpulse;
MeshComp->AddImpulse(BoostIntensity, NAME_None, true);
// Blast away nearby objects
RadialForceComp->FireImpulse();
}
}
// this will be called on client
void ASExplosiveBarrel::OnRep_Exploded()
{
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosionEffect, GetActorLocation());
MeshComp->SetMaterial(0, ExplodedMaterial);
}
void ASExplosiveBarrel::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ASExplosiveBarrel, bIsExploded);
}
[/SPOILER]
SHealthComponent.h
[SPOILER]
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "SHealthComponent.generated.h"
// ** on Health changed event
// ** delta(triangle) - difference, change in quantity; e.g. delta Y = "change in y" or "how much Y changes"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_SixParams(FOnHeaalthChangedSignature, USHealthComponent*, HealthComponent, float, Health, float, HealthDelta, const class UDamageType*, DamageType, class AController*, InstigatedBy, AActor*, DamageCauser);
// our OWN little category ClassGroup=(COOP) - YOU CAN SEE IT when selecting a component from a dropdown menu
UCLASS( ClassGroup=(COOP), meta=(BlueprintSpawnableComponent) )
class COOPGAME_API USHealthComponent : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
USHealthComponent();
protected:
// Called when the game starts
virtual void BeginPlay() override;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "HealthComponent")
float DefaultHealth;
UPROPERTY(Replicated, EditAnywhere, BlueprintReadWrite, Category = "HealthComponent")
float Health;
UFUNCTION()
void HandleTakeAnyDamage(AActor* DamagedActor, float Damage, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser);
virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const override;
public:
UPROPERTY(BlueprintAssignable, Category = "Events")
FOnHeaalthChangedSignature OnHealthChanged;
float GetCurrentHealth();
};
[/SPOILER]
SHealthComponent.cpp
[SPOILER]
// Fill out your copyright notice in the Description page of Project Settings.
#include "Public/Components/SHealthComponent.h"
#include "Net/UnrealNetwork.h"
USHealthComponent::USHealthComponent()
{
DefaultHealth= 100.0f;
SetIsReplicated(true);
}
void USHealthComponent::BeginPlay()
{
Super::BeginPlay();
if(GetOwnerRole() == ROLE_Authority) {
AActor* MyOwner = GetOwner();
if (!MyOwner) {
return;
}
MyOwner->OnTakeAnyDamage.AddDynamic(this, &USHealthComponent::HandleTakeAnyDamage);
}
Health = DefaultHealth;
}
void USHealthComponent::HandleTakeAnyDamage(AActor* DamagedActor, float Damage, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
{
if (Damage <= 0.0f) {
return;
}
Health = FMath::Clamp(Health - Damage, 0.0f, DefaultHealth);
UE_LOG(LogTemp, Log, TEXT("Health Changed to: %s"), *FString::SanitizeFloat(Health));
OnHealthChanged.Broadcast(this, Health, Damage, DamageType, InstigatedBy, DamageCauser);
}
float USHealthComponent::GetCurrentHealth()
{
return Health;
}
void USHealthComponent::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(USHealthComponent, Health);
}
[/SPOILER]