CogAbility: Fix cheats not correctly saved when connected to a server

CogSample: Projectile progress
This commit is contained in:
Arnaud Jamin
2023-10-31 23:50:41 -04:00
parent f876862d12
commit 7e8ba3e092
8 changed files with 78 additions and 19 deletions
+4 -1
View File
@@ -1,3 +1,6 @@
---,1.000000
MaxStamina,1000.000000
StaminaRegen,10.000000
StaminaRegen,2.000000
MaxHealth,1000.000000
HealthRegen,0.100000
BaseDamage,100.000000
1 --- 1.000000
2 MaxStamina 1000.000000
3 StaminaRegen 10.000000 2.000000
4 MaxHealth 1000.000000
5 HealthRegen 0.100000
6 BaseDamage 100.000000
@@ -98,13 +98,22 @@ void FCogAbilityWindow_Cheats::TryReapplyCheats()
TArray<AActor*> Targets { LocalPawn };
for (const FString& AppliedCheatName : Config->AppliedCheats)
for (int32 i = Config->AppliedCheats.Num() - 1; i >= 0; i--)
{
const FString& AppliedCheatName = Config->AppliedCheats[i];
if (const FCogAbilityCheat* Cheat = Asset->PersistentEffects.FindByPredicate(
[AppliedCheatName](const FCogAbilityCheat& Cheat) { return Cheat.Name == AppliedCheatName; }))
{
Replicator->ApplyCheat(LocalPawn, Targets, *Cheat);
}
else
{
//-----------------------------------------------------
// This cheat doesn't exist anymore. We can remove it.
//-----------------------------------------------------
Config->AppliedCheats.RemoveAt(i);
}
}
bHasReappliedCheats = true;
@@ -166,30 +175,33 @@ void FCogAbilityWindow_Cheats::RenderContent()
ImGui::TableNextRow();
ImGui::TableNextColumn();
bool bHasChanged = false;
int Index = 0;
for (const FCogAbilityCheat& CheatEffect : Asset->PersistentEffects)
{
ImGui::PushID(Index);
bHasChanged |= AddCheat(ControlledActor, SelectedActor, CheatEffect, true);
AddCheat(ControlledActor, SelectedActor, CheatEffect, true);
ImGui::PopID();
Index++;
}
//----------------------------------------------------------------
// When a persistent cheat has been changed, update the applied
// cheats string array to be saved in the config later
//----------------------------------------------------------------
if (bHasChanged && SelectedActor == ControlledActor)
//----------------------------------------------------------------------------
// Update the config of applied cheat to reapply them on the next launch.
// We do not updated them only when the the user input is pressed because
// the state of the cheat is lagging when connected to a server.
// So we check if the array should be updated all the time.
//----------------------------------------------------------------------------
if (SelectedActor == ControlledActor)
{
Config->AppliedCheats.Empty();
for (const FCogAbilityCheat& CheatEffect : Asset->PersistentEffects)
{
if (ACogAbilityReplicator::IsCheatActive(SelectedActor, CheatEffect))
{
Config->AppliedCheats.Add(CheatEffect.Name);
Config->AppliedCheats.AddUnique(CheatEffect.Name);
}
else
{
Config->AppliedCheats.Remove(CheatEffect.Name);
}
}
}
+17 -1
View File
@@ -4,6 +4,7 @@
#include "CogSampleDefines.h"
#include "CogSampleCharacter.h"
#include "CogSampleLogCategories.h"
#include "CogSampleProjectileComponent.h"
#include "CogSampleTargetAcquisition.h"
#include "GameFramework/PlayerState.h"
#include "Net/UnrealNetwork.h"
@@ -205,7 +206,14 @@ void ACogSamplePlayerController::Server_SetTarget_Implementation(AActor* Value)
}
//--------------------------------------------------------------------------------------------------------------------------
const ACogSamplePlayerController* ACogSamplePlayerController::GetFirstLocalPlayerController(UObject* WorldContextObject)
const ACogSamplePlayerController* ACogSamplePlayerController::GetFirstLocalPlayerControllerConst(UObject* WorldContextObject)
{
const ACogSamplePlayerController* PlayerController = GetFirstLocalPlayerController(WorldContextObject);
return PlayerController;
}
//--------------------------------------------------------------------------------------------------------------------------
ACogSamplePlayerController* ACogSamplePlayerController::GetFirstLocalPlayerController(UObject* WorldContextObject)
{
UWorld* const World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull);
if (World == nullptr)
@@ -231,3 +239,11 @@ float ACogSamplePlayerController::GetClientLag() const
return HalfPingInSeconds;
}
//--------------------------------------------------------------------------------------------------------------------------
void ACogSamplePlayerController::Server_ProjectileHit_Implementation(UCogSampleProjectileComponent* Projectile, const FHitResult& HitResult)
{
if (Projectile != nullptr)
{
Projectile->Server_Hit(HitResult);
}
}
+9 -1
View File
@@ -25,7 +25,9 @@ class ACogSamplePlayerController
public:
static const ACogSamplePlayerController* GetFirstLocalPlayerController(UObject* WorldContextObject);
static const ACogSamplePlayerController* GetFirstLocalPlayerControllerConst(UObject* WorldContextObject);
static ACogSamplePlayerController* GetFirstLocalPlayerController(UObject* WorldContextObject);
ACogSamplePlayerController();
@@ -67,6 +69,12 @@ public:
UPROPERTY()
TArray<UCogSampleSpawnPredictionComponent*> SpawnPredictions;
//----------------------------------------------------------------------------------------------------------------------
// Projectile Hit
//----------------------------------------------------------------------------------------------------------------------
UFUNCTION(Reliable, Server)
void Server_ProjectileHit(UCogSampleProjectileComponent* Projectile, const FHitResult& HitResult);
private:
//----------------------------------------------------------------------------------------------------------------------
@@ -52,6 +52,8 @@
//
// One client could be made responsible to detect hits received by a specific NPC.
//
//--------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------
UCogSampleProjectileComponent::UCogSampleProjectileComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
@@ -81,6 +83,7 @@ void UCogSampleProjectileComponent::BeginPlay()
Creator = UCogSampleFunctionLibrary_Gameplay::GetCreator(GetOwner());
SpawnPrediction = GetOwner()->FindComponentByClass<UCogSampleSpawnPredictionComponent>();
LocalPlayerController = ACogSamplePlayerController::GetFirstLocalPlayerController(this);
COG_LOG_OBJECT(LogCogProjectile, ELogVerbosity::Verbose, Creator.Get(), TEXT("Projectile:%s | Role:%s | IsActive:%d"), *GetNameSafe(GetOwner()), *GetRoleName(), IsActive());
@@ -107,6 +110,12 @@ void UCogSampleProjectileComponent::BeginPlay()
}
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::Activate(bool bReset)
{
@@ -146,9 +155,9 @@ void UCogSampleProjectileComponent::Activate(bool bReset)
//--------------------------------------------------------------------------
if (GetOwner()->GetLocalRole() != ROLE_Authority)
{
if (const ACogSamplePlayerController* Controller = ACogSamplePlayerController::GetFirstLocalPlayerController(this))
if (LocalPlayerController != nullptr)
{
Catchup(Controller->GetClientLag());
Catchup(LocalPlayerController->GetClientLag());
}
}
@@ -510,6 +519,13 @@ void UCogSampleProjectileComponent::Hit_Implementation(const FHitResult& HitResu
DrawDebugHitResult(HitResult);
#endif //ENABLE_COG
if (LocalPlayerController == nullptr)
{
return;
}
LocalPlayerController->Server_ProjectileHit(this, HitResult);
Server_Hit(HitResult);
}
@@ -525,7 +541,7 @@ FString UCogSampleProjectileComponent::GetRoleName() const
}
//--------------------------------------------------------------------------------------------------------------------------
void UCogSampleProjectileComponent::Server_Hit_Implementation(const FHitResult& HitResult)
void UCogSampleProjectileComponent::Server_Hit(const FHitResult& HitResult)
{
COG_LOG_OBJECT(LogCogProjectile, ELogVerbosity::Verbose, Creator.Get(), TEXT("Projectile:%s | Role:%s | Other:%s | Comp:%s | Bone:%s"),
*GetNameSafe(GetOwner()),
@@ -53,12 +53,15 @@ public:
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction);
virtual void Activate(bool bReset) override;
virtual void StopSimulating(const FHitResult& HitResult) override;
virtual void Server_Hit(const FHitResult& Hit);
UFUNCTION(BlueprintCallable)
void ClearHitActors();
@@ -79,8 +82,6 @@ protected:
virtual void TryHit(const FHitResult& Hit);
UFUNCTION(Server, Reliable)
virtual void Server_Hit(const FHitResult& Hit);
UFUNCTION()
virtual void OnCollisionOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool IsFromSweep, const FHitResult& SweepHit);
@@ -129,6 +130,9 @@ protected:
UPROPERTY(Replicated)
FVector ServerSpawnVelocity = FVector::ZeroVector;
UPROPERTY()
TWeakObjectPtr<ACogSamplePlayerController> LocalPlayerController = nullptr;
/** Re-entrancy guard */
bool IsAlreadyProcessingAnOverlap = false;