From 3b9a02b3b10f68ef44e8dcc7e2ba9aebd28ae2b8 Mon Sep 17 00:00:00 2001 From: Cody Larkin Date: Thu, 1 Jan 2026 19:35:48 -0500 Subject: [PATCH] health var updates correctly on client when hit by projectile --- .../PlayerCharacter/Components/DDIHealth.cpp | 6 +-- .../PlayerCharacter/DDICharacter.cpp | 47 ++++++++++++++++++- .../PlayerCharacter/DDICharacter.h | 12 +++++ .../Weapons/Projectiles/ProjectileBase.cpp | 6 +-- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/Source/OpenConflict/PlayerCharacter/Components/DDIHealth.cpp b/Source/OpenConflict/PlayerCharacter/Components/DDIHealth.cpp index b9fa2bd..37b08f5 100644 --- a/Source/OpenConflict/PlayerCharacter/Components/DDIHealth.cpp +++ b/Source/OpenConflict/PlayerCharacter/Components/DDIHealth.cpp @@ -9,6 +9,7 @@ UDDIHealth::UDDIHealth() // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features // off to improve performance if you don't need them. PrimaryComponentTick.bCanEverTick = true; + SetIsReplicatedByDefault(true); MaxHealth = 0; CurrentHealth = 0; ClassName = ClassNames::Scout; @@ -41,7 +42,7 @@ void UDDIHealth::BeginPlay() MaxHealth += seg; CurrentHealth = MaxHealth; - GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Cyan, FString::Printf(TEXT("CurrentHealth: %d"), CurrentHealth)); + GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Emerald, FString::Printf(TEXT("CurrentHealth: %d"), CurrentHealth)); } @@ -81,10 +82,9 @@ void UDDIHealth::Heal() // Called to cause damage void UDDIHealth::TakeDamage(int DamageValue) { - // if (HealTimer.IsValid()) - // HealTimer.Invalidate(); GetWorld()->GetTimerManager().ClearTimer(HealTimer); CurrentHealth -= DamageValue; + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Cyan, FString::Printf(TEXT("Client Hit\nHealth: %d"), CurrentHealth)); } \ No newline at end of file diff --git a/Source/OpenConflict/PlayerCharacter/DDICharacter.cpp b/Source/OpenConflict/PlayerCharacter/DDICharacter.cpp index 28baea2..1220612 100644 --- a/Source/OpenConflict/PlayerCharacter/DDICharacter.cpp +++ b/Source/OpenConflict/PlayerCharacter/DDICharacter.cpp @@ -50,10 +50,55 @@ void ADDICharacter::Tick(float DeltaTime) void ADDICharacter::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) { - + Server_CharacterHit(HitComponent, OtherActor, OtherComp, NormalImpulse, Hit); } void ADDICharacter::TakeDamage(int Damage) { HealthComponent->TakeDamage(Damage); } + +bool ADDICharacter::Server_SpawnProjectile_Validate() +{ + return true; +} +void ADDICharacter::Server_SpawnProjectile_Implementation() +{ + FVector Location = GetActorLocation(); + FRotator Rotation = GetActorRotation(); + FVector Dir = GetActorForwardVector(); + + Location += Dir * 200.f; + if (!ProjectileClass) + { + GEngine->AddOnScreenDebugMessage(1, 10.f, FColor::Emerald, "No Projectile Set"); + return; + } + GetWorld()->SpawnActor(ProjectileClass, Location, Rotation); + + + +} + +void ADDICharacter::Client_CharacterHit_Implementation() +{ + TakeDamage(10); + +} +bool ADDICharacter::Client_CharacterHit_Validate() +{ + return true; +} +void ADDICharacter::Server_CharacterHit_Implementation(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) +{ + if (AProjectileBase* Projectile = Cast(OtherActor)) + { + // if (Cast(Projectile->Owner) == this) + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Emerald, "Damage dealt"); + Client_CharacterHit(); + } +} +bool ADDICharacter::Server_CharacterHit_Validate(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) +{ + return true; +} \ No newline at end of file diff --git a/Source/OpenConflict/PlayerCharacter/DDICharacter.h b/Source/OpenConflict/PlayerCharacter/DDICharacter.h index 62518e9..f257620 100644 --- a/Source/OpenConflict/PlayerCharacter/DDICharacter.h +++ b/Source/OpenConflict/PlayerCharacter/DDICharacter.h @@ -31,12 +31,24 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Health") UDDIHealth* HealthComponent; + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Projectile") + TSubclassOf ProjectileClass; + /*Functions*/ UFUNCTION() void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit); UFUNCTION() void TakeDamage(int Damage); + + UFUNCTION(Server, Reliable, WithValidation, BlueprintCallable) + void Server_SpawnProjectile(); + + UFUNCTION(Client, Reliable, WithValidation, BlueprintCallable) + void Client_CharacterHit(); + + UFUNCTION(Server, Reliable, WithValidation, BlueprintCallable) + void Server_CharacterHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit); /*C++ only declarations*/ private: diff --git a/Source/OpenConflict/Weapons/Projectiles/ProjectileBase.cpp b/Source/OpenConflict/Weapons/Projectiles/ProjectileBase.cpp index c4761ac..e794add 100644 --- a/Source/OpenConflict/Weapons/Projectiles/ProjectileBase.cpp +++ b/Source/OpenConflict/Weapons/Projectiles/ProjectileBase.cpp @@ -46,9 +46,7 @@ void AProjectileBase::Tick(float DeltaTime) void AProjectileBase::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) { - if (ADDICharacter* character = Cast(OtherActor)) - { + // if (ADDICharacter* character = Cast(OtherActor)) Destroy(); - character->TakeDamage(10); - } + } \ No newline at end of file