Add MVP character proxy selection

This commit is contained in:
2026-05-19 10:32:08 -07:00
parent 11a13042b6
commit bc7617b08b
11 changed files with 264 additions and 6 deletions
@@ -12,12 +12,15 @@
#include "AgrarianPersistenceSubsystem.h"
#include "AgrarianShelterActor.h"
#include "AgrarianSurvivalComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "EnhancedInputSubsystems.h"
#include "Engine/LocalPlayer.h"
#include "Engine/SkeletalMesh.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "InputCoreTypes.h"
#include "InputMappingContext.h"
#include "Materials/MaterialInterface.h"
#include "Blueprint/UserWidget.h"
#include "TimerManager.h"
#include "AgrarianGame.h"
@@ -75,6 +78,20 @@ namespace
return false;
}
const TCHAR* GetMvpCharacterProxyMeshPath(const FName ProxyId)
{
return ProxyId == TEXT("female")
? TEXT("/Game/Characters/Mannequins/Meshes/SKM_Quinn_Simple.SKM_Quinn_Simple")
: TEXT("/Game/Characters/Mannequins/Meshes/SKM_Manny_Simple.SKM_Manny_Simple");
}
const TCHAR* GetMvpCharacterProxyMaterialPath(const FName ProxyId)
{
return ProxyId == TEXT("female")
? TEXT("/Game/Agrarian/Characters/Materials/M_AGR_CharacterProxy_Workwear_Female.M_AGR_CharacterProxy_Workwear_Female")
: TEXT("/Game/Agrarian/Characters/Materials/M_AGR_CharacterProxy_Workwear_Male.M_AGR_CharacterProxy_Workwear_Male");
}
}
void AAgrarianGamePlayerController::BeginPlay()
@@ -258,6 +275,30 @@ void AAgrarianGamePlayerController::HandleMvpEscapeInput()
ShowMvpPauseMenu();
}
void AAgrarianGamePlayerController::ApplyMvpCharacterProxyToPawn()
{
AAgrarianGameCharacter* AgrarianCharacter = GetPawn<AAgrarianGameCharacter>();
USkeletalMeshComponent* MeshComponent = AgrarianCharacter ? AgrarianCharacter->GetMesh() : nullptr;
if (!MeshComponent)
{
return;
}
if (USkeletalMesh* ProxyMesh = LoadObject<USkeletalMesh>(nullptr, GetMvpCharacterProxyMeshPath(SelectedMvpCharacterProxyId)))
{
MeshComponent->SetSkeletalMesh(ProxyMesh);
}
if (UMaterialInterface* ProxyMaterial = LoadObject<UMaterialInterface>(nullptr, GetMvpCharacterProxyMaterialPath(SelectedMvpCharacterProxyId)))
{
const int32 MaterialCount = FMath::Max(1, MeshComponent->GetNumMaterials());
for (int32 MaterialIndex = 0; MaterialIndex < MaterialCount; ++MaterialIndex)
{
MeshComponent->SetMaterial(MaterialIndex, ProxyMaterial);
}
}
}
void AAgrarianGamePlayerController::AgrarianGrantItem(FName ItemId, int32 Quantity)
{
if (ItemId == NAME_None || Quantity <= 0)
@@ -498,14 +539,18 @@ void AAgrarianGamePlayerController::AgrarianSelectCharacter(FName Archetype)
if (Archetype == TEXT("male") || Archetype == TEXT("YoungAdultMale"))
{
SelectedMvpCharacterProxyId = TEXT("male");
MvpFrontendWidget->SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultMale);
ApplyMvpCharacterProxyToPawn();
ClientMessage(TEXT("Selected MVP young adult male character archetype."));
return;
}
if (Archetype == TEXT("female") || Archetype == TEXT("YoungAdultFemale"))
{
SelectedMvpCharacterProxyId = TEXT("female");
MvpFrontendWidget->SetSelectedCharacterArchetype(EAgrarianMvpCharacterArchetype::YoungAdultFemale);
ApplyMvpCharacterProxyToPawn();
ClientMessage(TEXT("Selected MVP young adult female character archetype."));
return;
}
@@ -66,6 +66,9 @@ protected:
void HandleMvpConfirmInput();
void HandleMvpBackInput();
void HandleMvpEscapeInput();
void ApplyMvpCharacterProxyToPawn();
FName SelectedMvpCharacterProxyId = TEXT("male");
public:
UFUNCTION(Exec)
@@ -226,6 +226,13 @@ void UAgrarianMvpFrontendWidget::CompleteFrontendFlow()
{
if (APlayerController* PlayerController = GetOwningPlayer())
{
if (ActiveScreen == EAgrarianMvpFrontendScreen::Loading)
{
PlayerController->ConsoleCommand(SelectedCharacterArchetype == EAgrarianMvpCharacterArchetype::YoungAdultFemale
? TEXT("AgrarianSelectCharacter female")
: TEXT("AgrarianSelectCharacter male"));
}
PlayerController->SetInputMode(FInputModeGameOnly());
PlayerController->bShowMouseCursor = false;
PlayerController->SetIgnoreMoveInput(false);
@@ -311,7 +318,7 @@ void UAgrarianMvpFrontendWidget::RebuildFrontendTree()
UVerticalBox* MaleStack = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("MalePioneerStack"));
MaleButton->SetContent(MaleStack);
AddText(MaleStack, FText::FromString(TEXT("Young adult male")), FMath::RoundToInt(21.0f * Scale), true, TextColor, 8.0f * Scale);
AddText(MaleStack, FText::FromString(TEXT("Average proportions, survival baseline, placeholder visual.")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 18.0f * Scale);
AddText(MaleStack, FText::FromString(TEXT("Average build, practical workwear proxy, survival baseline.")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 18.0f * Scale);
AddText(MaleStack, bMaleSelected ? FText::FromString(TEXT("Selected")) : FText::FromString(TEXT("Available")), FMath::RoundToInt(15.0f * Scale), true, bMaleSelected ? AccentColor : MutedTextColor, 0.0f);
if (UHorizontalBoxSlot* MaleSlot = CharacterRow->AddChildToHorizontalBox(MaleButton))
{
@@ -325,7 +332,7 @@ void UAgrarianMvpFrontendWidget::RebuildFrontendTree()
UVerticalBox* FemaleStack = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("FemalePioneerStack"));
FemaleButton->SetContent(FemaleStack);
AddText(FemaleStack, FText::FromString(TEXT("Young adult female")), FMath::RoundToInt(21.0f * Scale), true, TextColor, 8.0f * Scale);
AddText(FemaleStack, FText::FromString(TEXT("Average proportions, survival baseline, placeholder visual.")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 18.0f * Scale);
AddText(FemaleStack, FText::FromString(TEXT("Average build, practical workwear proxy, survival baseline.")), FMath::RoundToInt(15.0f * Scale), false, MutedTextColor, 18.0f * Scale);
AddText(FemaleStack, bFemaleSelected ? FText::FromString(TEXT("Selected")) : FText::FromString(TEXT("Available")), FMath::RoundToInt(15.0f * Scale), true, bFemaleSelected ? AccentColor : MutedTextColor, 0.0f);
if (UHorizontalBoxSlot* FemaleSlot = CharacterRow->AddChildToHorizontalBox(FemaleButton))
{