text: // Created by Manjog Singh
  
  
  #include "SHealthComponent.h"
  #include "Net/UnrealNetwork.h"
  #include "SGameModeBase.h"
  
  // Sets default values for this component's properties
  USHealthComponent::USHealthComponent()
  {
  	DefaultHealth = 100;
  	bIsDead = false;
  
  	TeamNo = 255;
  
  	// SetIsReplicated(true);
  }
  
  
  // Called when the game starts
  void USHealthComponent::BeginPlay()
  {
  	Super::BeginPlay();
  
  	if (GetOwnerRole() == ROLE_Authority)
  	{
  		AActor* MyOwner = GetOwner();
  		if (MyOwner)
  		{
  			MyOwner->OnTakeAnyDamage.AddDynamic(this, &USHealthComponent::HandleTakeAnyDamage);
  		}
  	}
  	Health = DefaultHealth;
  }
  
  void USHealthComponent::OnRep_Health(float OldHealth)
  {
  	float Damage = Health - OldHealth;
  	OnHealthChanged.Broadcast(this, Health, Damage, nullptr, nullptr, nullptr);
  }
  
  void USHealthComponent::HandleTakeAnyDamage(AActor* DamagedActor, float Damage, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
  {
  	if (Damage <= 0.0f || bIsDead)
  	{
  		return;
  	}
  
  	if (DamageCauser != DamagedActor && IsFriendly(DamagedActor, DamageCauser))
  	{
  		return;
  	}
  
  	Health = FMath::Clamp(Health - Damage, 0.0f, DefaultHealth);
  
  	UE_LOG(LogTemp, Log, TEXT("Health changed: %s"), *FString::SanitizeFloat(Health));
  
  	bIsDead = Health <= 0.0f;
  
  	OnHealthChanged.Broadcast(this, Health, Damage, DamageType, InstigatedBy, DamageCauser);
  
  	if (bIsDead)
  	{
  		ASGameModeBase* GM = Cast<ASGameModeBase>(GetWorld()->GetAuthGameMode());
  		if (GM)
  		{
  			GM->OnActorKilled.Broadcast(GetOwner(), DamageCauser, InstigatedBy);
  		}
  	}
  }
  
  bool USHealthComponent::IsFriendly(AActor* ActorA, AActor* ActorB)
  {
  	if (ActorA == nullptr || ActorB == nullptr)
  	{
  		return true;
  	}
  
  	USHealthComponent* HealthCompA = Cast<USHealthComponent>(ActorA->GetComponentByClass(USHealthComponent::StaticClass()));
  	USHealthComponent* HealthCompB = Cast<USHealthComponent>(ActorB->GetComponentByClass(USHealthComponent::StaticClass()));
  
  	if (HealthCompA == nullptr || HealthCompB == nullptr)
  	{
  		return true;
  	}
  
  	return HealthCompA->TeamNo == HealthCompB->TeamNo;
  }
  
  float USHealthComponent::GetHealth() const
  {
  	return Health;
  }
  
  void USHealthComponent::Heal(float HealAmount)
  {
  	if (HealAmount <= 0.0 || Health <= 0.0f)
  	{
  		return;
  	}
  	
  	Health = FMath::Clamp(Health + HealAmount, 0.0f, DefaultHealth);
  
  	UE_LOG(LogTemp, Log, TEXT("Health changed: %s (+ %s)"), *FString::SanitizeFloat(Health), *FString::SanitizeFloat(HealAmount));
  
  	OnHealthChanged.Broadcast(this, Health, - HealAmount, nullptr, nullptr, nullptr);
  
  }
  
  void USHealthComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
  {
  	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
  
  	DOREPLIFETIME(USHealthComponent, Health);
  }