// Copyright Epic Games, Inc. All Rights Reserved. #include "LyraControllerComponent_CharacterParts.h" #include "LyraPawnComponent_CharacterParts.h" #include "GameFramework/Controller.h" #include "LyraCosmeticDeveloperSettings.h" #include "GameFramework/CheatManager.h" ////////////////////////////////////////////////////////////////////// ULyraControllerComponent_CharacterParts::ULyraControllerComponent_CharacterParts(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { } void ULyraControllerComponent_CharacterParts::BeginPlay() { Super::BeginPlay(); // Listen for pawn possession changed events if (HasAuthority()) { if (AController* OwningController = GetController()) { OwningController->OnPossessedPawnChanged.AddDynamic(this, &ThisClass::OnPossessedPawnChanged); if (APawn* ControlledPawn = GetPawn()) { OnPossessedPawnChanged(nullptr, ControlledPawn); } } ApplyDeveloperSettings(); } } void ULyraControllerComponent_CharacterParts::EndPlay(const EEndPlayReason::Type EndPlayReason) { RemoveAllCharacterParts(); Super::EndPlay(EndPlayReason); } ULyraPawnComponent_CharacterParts* ULyraControllerComponent_CharacterParts::GetPawnCustomizer() const { if (APawn* ControlledPawn = GetPawn()) { return ControlledPawn->FindComponentByClass(); } return nullptr; } void ULyraControllerComponent_CharacterParts::AddCharacterPart(const FLyraCharacterPart& NewPart) { AddCharacterPartInternal(NewPart, ECharacterPartSource::Natural); } void ULyraControllerComponent_CharacterParts::AddCharacterPartInternal(const FLyraCharacterPart& NewPart, ECharacterPartSource Source) { FLyraControllerCharacterPartEntry& NewEntry = CharacterParts.AddDefaulted_GetRef(); NewEntry.Part = NewPart; NewEntry.Source = Source; if (ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer()) { if (NewEntry.Source != ECharacterPartSource::NaturalSuppressedViaCheat) { NewEntry.Handle = PawnCustomizer->AddCharacterPart(NewPart); } } } void ULyraControllerComponent_CharacterParts::RemoveCharacterPart(const FLyraCharacterPart& PartToRemove) { for (auto EntryIt = CharacterParts.CreateIterator(); EntryIt; ++EntryIt) { if (FLyraCharacterPart::AreEquivalentParts(EntryIt->Part, PartToRemove)) { if (ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer()) { PawnCustomizer->RemoveCharacterPart(EntryIt->Handle); } EntryIt.RemoveCurrent(); break; } } } void ULyraControllerComponent_CharacterParts::RemoveAllCharacterParts() { if (ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer()) { for (FLyraControllerCharacterPartEntry& Entry : CharacterParts) { PawnCustomizer->RemoveCharacterPart(Entry.Handle); } } CharacterParts.Reset(); } void ULyraControllerComponent_CharacterParts::OnPossessedPawnChanged(APawn* OldPawn, APawn* NewPawn) { // Remove from the old pawn if (ULyraPawnComponent_CharacterParts* OldCustomizer = OldPawn ? OldPawn->FindComponentByClass() : nullptr) { for (FLyraControllerCharacterPartEntry& Entry : CharacterParts) { OldCustomizer->RemoveCharacterPart(Entry.Handle); Entry.Handle.Reset(); } } // Apply to the new pawn if (ULyraPawnComponent_CharacterParts* NewCustomizer = NewPawn ? NewPawn->FindComponentByClass() : nullptr) { for (FLyraControllerCharacterPartEntry& Entry : CharacterParts) { ensure(!Entry.Handle.IsValid()); if (Entry.Source != ECharacterPartSource::NaturalSuppressedViaCheat) { Entry.Handle = NewCustomizer->AddCharacterPart(Entry.Part); } } } } void ULyraControllerComponent_CharacterParts::ApplyDeveloperSettings() { #if UE_WITH_CHEAT_MANAGER const ULyraCosmeticDeveloperSettings* Settings = GetDefault(); // Suppress or unsuppress natural parts if needed const bool bSuppressNaturalParts = (Settings->CheatMode == ECosmeticCheatMode::ReplaceParts) && (Settings->CheatCosmeticCharacterParts.Num() > 0); SetSuppressionOnNaturalParts(bSuppressNaturalParts); // Remove anything added by developer settings and re-add it ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer(); for (auto It = CharacterParts.CreateIterator(); It; ++It) { if (It->Source == ECharacterPartSource::AppliedViaDeveloperSettingsCheat) { if (PawnCustomizer != nullptr) { PawnCustomizer->RemoveCharacterPart(It->Handle); } It.RemoveCurrent(); } } // Add new parts for (const FLyraCharacterPart& PartDesc : Settings->CheatCosmeticCharacterParts) { AddCharacterPartInternal(PartDesc, ECharacterPartSource::AppliedViaDeveloperSettingsCheat); } #endif } void ULyraControllerComponent_CharacterParts::AddCheatPart(const FLyraCharacterPart& NewPart, bool bSuppressNaturalParts) { #if UE_WITH_CHEAT_MANAGER SetSuppressionOnNaturalParts(bSuppressNaturalParts); AddCharacterPartInternal(NewPart, ECharacterPartSource::AppliedViaCheatManager); #endif } void ULyraControllerComponent_CharacterParts::ClearCheatParts() { #if UE_WITH_CHEAT_MANAGER ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer(); // Remove anything added by cheat manager cheats for (auto It = CharacterParts.CreateIterator(); It; ++It) { if (It->Source == ECharacterPartSource::AppliedViaCheatManager) { if (PawnCustomizer != nullptr) { PawnCustomizer->RemoveCharacterPart(It->Handle); } It.RemoveCurrent(); } } ApplyDeveloperSettings(); #endif } void ULyraControllerComponent_CharacterParts::SetSuppressionOnNaturalParts(bool bSuppressed) { #if UE_WITH_CHEAT_MANAGER ULyraPawnComponent_CharacterParts* PawnCustomizer = GetPawnCustomizer(); for (FLyraControllerCharacterPartEntry& Entry : CharacterParts) { if ((Entry.Source == ECharacterPartSource::Natural) && bSuppressed) { // Suppress if (PawnCustomizer != nullptr) { PawnCustomizer->RemoveCharacterPart(Entry.Handle); Entry.Handle.Reset(); } Entry.Source = ECharacterPartSource::NaturalSuppressedViaCheat; } else if ((Entry.Source == ECharacterPartSource::NaturalSuppressedViaCheat) && !bSuppressed) { // Unsuppress if (PawnCustomizer != nullptr) { Entry.Handle = PawnCustomizer->AddCharacterPart(Entry.Part); } Entry.Source = ECharacterPartSource::Natural; } } #endif }