From 7e8ba3e092094f01d75528cff188ea83e08fcf82 Mon Sep 17 00:00:00 2001 From: Arnaud Jamin Date: Tue, 31 Oct 2023 23:50:41 -0400 Subject: [PATCH] CogAbility: Fix cheats not correctly saved when connected to a server CogSample: Projectile progress --- Config/Game/Hero1_Attributes.csv | 5 ++- .../Attributes/CT_Hero1_Attributes.uasset | Bin 3328 -> 3328 bytes .../E/HA/CXMK7W9FIGA0C2MR0GYXOO.uasset | Bin 6003 -> 5944 bytes .../Private/CogAbilityWindow_Cheats.cpp | 34 ++++++++++++------ .../CogSample/CogSamplePlayerController.cpp | 18 +++++++++- Source/CogSample/CogSamplePlayerController.h | 10 +++++- .../CogSampleProjectileComponent.cpp | 22 ++++++++++-- .../CogSample/CogSampleProjectileComponent.h | 8 +++-- 8 files changed, 78 insertions(+), 19 deletions(-) diff --git a/Config/Game/Hero1_Attributes.csv b/Config/Game/Hero1_Attributes.csv index 991383f..5bfe2f1 100644 --- a/Config/Game/Hero1_Attributes.csv +++ b/Config/Game/Hero1_Attributes.csv @@ -1,3 +1,6 @@ ---,1.000000 MaxStamina,1000.000000 -StaminaRegen,10.000000 +StaminaRegen,2.000000 +MaxHealth,1000.000000 +HealthRegen,0.100000 +BaseDamage,100.000000 diff --git a/Content/Characters/Hero1/Attributes/CT_Hero1_Attributes.uasset b/Content/Characters/Hero1/Attributes/CT_Hero1_Attributes.uasset index d0a59fa86248f28564eaf5ef4c69a21b622a45cc..f6d90ba6ec94f624fde5f605e6c774912543603f 100644 GIT binary patch delta 38 wcmV+>0NMY58h{#*`w$x8e(Hm-wL^kshtwCIs$R1T0sjdE&CJX_vknXL0bbt`hyVZp delta 38 ucmZpWYLJ@nTVP{~zghGBPNK5~WFhR&2FL{_JSxR_BHA)cdEj~Z`pb{>D*c(r)j`w2Kewu@Yqe4nf`%+)BiiQFXl zf8#zOS5M&fMX{EcqU1*eXM2OcxejuC*mz+Q+`{RGqGoTdC4>?@o=})?e1vizkUN&Z zap5`2DKpV07h-)ql1>;G+}kI|hxwNtU#=AgImm7Mfj2&!P?$OHn)+rA^~p_d<;r@= zf+r~X83kt;gjs9SFtc#R9f7M>-9Lzlv>9GWqvikSR+N5Y)xD#%PyJaZ$$tdl(6aH} z(Hggh7K|BBy91d8qv&h*T;`h59d5tN%nir@);(A5fv5g*KHeXtW|3q7_p=2gpXvF% zp4F}boU*HOCtR}Yas=+!RWnaJ%JA9_Yh$#s$)?DnX*RjoE(+>{m`s%6w9}NMaNU{5 z!cUw+g?T3aTuV&kz;dhkA|X+~F-q$SUcLzDT_<1aLF`5%2M^p_)DSOTL-qJ8zN;cK p!JzU=$}`ogQKJkiekeUy^$S_vHyEWvtjW@c703C%UC;=oe*wXLuw?)M delta 1459 zcmbu8&ubGw6vt=Qv?OjL-QDbu#56UD`JpChO|(t5nv_aQPbqrQQw~MMTSX1tA}HR( zhIc6z^dbm?g5;tgsQ*Dk4|?|CQKj0V;Ey+x8QGLA4LFc}Z{GX7@4R`NeO6d6taNCk z^`;iA5<*f6K5(r;p61GHenJLuH>(n&u_*3u1X-Stk7(JCt=06kQ@6?L!pnMR_&K$f zp+y~9g-7&E{1YM-yNk)^A6yaC%V1!(9aA=`7C?95^32kei;eSS`0mXgZPRzv*UX8M zg0R1^GB13$sN}{(ZWFojKDh759roZ3bz@CZ63K4}PHhkV`gcs^fVH*pId?30tt?4&0z*K~t2D9832Z#>~~ zu;k>_*nj3opWM-2F2T1_up*KhC^#uW$f#pVM1#2Dz_MDjikR>RvJL!FNKJf954-7( zS~QP~I+mFc{s!1Xb!9TdHCBe^luIUezo2{8;_hPbma<1{zYk9BvK&$76P7S11ud%{ zc8`l?Re?BgUyD))UhwA!E$S^|!V}9j2z~JGZD)68Vh$dcUN7a(T^NCyWkW(YX%x!( zINi(l*L5=x5eFpUo}Q)qG49|1s#V#@KG}eHh0P{wf2P2lB hCZS?xsfE{#re)2*mJWKZ%H^pIPj%z}1io7He*p+4wPXMQ diff --git a/Plugins/CogAbility/Source/CogAbility/Private/CogAbilityWindow_Cheats.cpp b/Plugins/CogAbility/Source/CogAbility/Private/CogAbilityWindow_Cheats.cpp index ecb5bdb..a28eeae 100644 --- a/Plugins/CogAbility/Source/CogAbility/Private/CogAbilityWindow_Cheats.cpp +++ b/Plugins/CogAbility/Source/CogAbility/Private/CogAbilityWindow_Cheats.cpp @@ -98,13 +98,22 @@ void FCogAbilityWindow_Cheats::TryReapplyCheats() TArray 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); } } } diff --git a/Source/CogSample/CogSamplePlayerController.cpp b/Source/CogSample/CogSamplePlayerController.cpp index 6f46c35..c5e3eb1 100644 --- a/Source/CogSample/CogSamplePlayerController.cpp +++ b/Source/CogSample/CogSamplePlayerController.cpp @@ -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); + } +} \ No newline at end of file diff --git a/Source/CogSample/CogSamplePlayerController.h b/Source/CogSample/CogSamplePlayerController.h index a4be124..b6f54a4 100644 --- a/Source/CogSample/CogSamplePlayerController.h +++ b/Source/CogSample/CogSamplePlayerController.h @@ -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 SpawnPredictions; + //---------------------------------------------------------------------------------------------------------------------- + // Projectile Hit + //---------------------------------------------------------------------------------------------------------------------- + UFUNCTION(Reliable, Server) + void Server_ProjectileHit(UCogSampleProjectileComponent* Projectile, const FHitResult& HitResult); + private: //---------------------------------------------------------------------------------------------------------------------- diff --git a/Source/CogSample/CogSampleProjectileComponent.cpp b/Source/CogSample/CogSampleProjectileComponent.cpp index 7733684..5c21cb4 100644 --- a/Source/CogSample/CogSampleProjectileComponent.cpp +++ b/Source/CogSample/CogSampleProjectileComponent.cpp @@ -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(); + 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()), diff --git a/Source/CogSample/CogSampleProjectileComponent.h b/Source/CogSample/CogSampleProjectileComponent.h index c3a775b..587edc5 100644 --- a/Source/CogSample/CogSampleProjectileComponent.h +++ b/Source/CogSample/CogSampleProjectileComponent.h @@ -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 LocalPlayerController = nullptr; + /** Re-entrancy guard */ bool IsAlreadyProcessingAnOverlap = false;