Compare commits

...

2 Commits

Author SHA1 Message Date
koritsa d840f59bda Added starting wardrobe items hydration 2026-06-01 23:10:11 +03:00
koritsa 0e9832719d Added NPC logic 2026-06-01 22:04:31 +03:00
38 changed files with 170 additions and 43 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,4 +1,4 @@
# Development Plan
# Development Plan
Working document for Naked Desire implementation. Tracks current state vs. the GDD (README.md) and the phased roadmap. Update this file as state changes — code is the source of truth, this file is the navigation chart.
+22 -4
View File
@@ -2,8 +2,12 @@
#include "NPC.h"
#include "BrainComponent.h"
#include "NPCTypeDefinition.h"
#include "NPCAIController.h"
#include "NPCTargetLocation.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
@@ -58,15 +62,26 @@ void ANPC::ActivateFromPool(const FVector& Location, const FRotator& Rotation)
Move->SetComponentTickEnabled(true);
Move->SetMovementMode(MOVE_Walking);
}
OnActivatedFromPool();
if (ANPCAIController* NPCController = Cast<ANPCAIController>(GetController()))
{
NPCController->RunCustomBehaviorTree();
NPCController->GetBlackboardComponent()->SetValueAsBool(TEXT("bHasReacted"), false);
}
}
void ANPC::DeactivateToPool()
{
// Drop any active observation so a pooled-out NPC stops contributing to the player's embarrassment.
if (ANPCAIController* NPCController = Cast<ANPCAIController>(GetController()))
{
NPCController->ClearObservation();
if (UBrainComponent* Brain = NPCController->GetBrainComponent())
{
Brain->StopLogic(TEXT("Moved to pool"));
}
NPCController->ClearFocus(EAIFocusPriority::Default);
}
if (UCharacterMovementComponent* Move = GetCharacterMovement())
{
@@ -74,9 +89,12 @@ void ANPC::DeactivateToPool()
Move->DisableMovement();
Move->SetComponentTickEnabled(false);
}
if (TargetLocationActor)
{
TargetLocationActor->Release(this);
}
SetActorHiddenInGame(true);
SetActorEnableCollision(false);
OnDeactivatedToPool();
}
+3 -5
View File
@@ -7,6 +7,7 @@
#include "NPCType.h"
#include "NPC.generated.h"
class ANPCTargetLocation;
class UNPCTypeDefinition;
UCLASS()
@@ -44,9 +45,6 @@ public:
void DeactivateToPool();
protected:
UFUNCTION(BlueprintImplementableEvent, Category = "NPC")
void OnActivatedFromPool();
UFUNCTION(BlueprintImplementableEvent, Category = "NPC")
void OnDeactivatedToPool();
UPROPERTY(BlueprintReadWrite, Category = "NPC")
TObjectPtr<ANPCTargetLocation> TargetLocationActor;
};
@@ -45,6 +45,11 @@ void ANPCAIController::ClearObservation()
}
}
void ANPCAIController::RunCustomBehaviorTree()
{
RunBehaviorTree(BehaviorTreeAsset);
}
float ANPCAIController::GetObservationWeight() const
{
if (const ANPC* NPC = Cast<ANPC>(GetPawn()))
+1
View File
@@ -27,6 +27,7 @@ public:
// Clears any active observation of the player (used on un-possess and when the NPC is pooled out).
void ClearObservation();
void RunCustomBehaviorTree();
protected:
UFUNCTION()
@@ -0,0 +1,29 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "NPCTargetLocation.h"
#include "NPC.h"
ANPCTargetLocation::ANPCTargetLocation()
{
PrimaryActorTick.bCanEverTick = false;
}
bool ANPCTargetLocation::TryClaim(ANPC* InClaimant)
{
if (Claimant.IsValid() && Claimant.Get() != InClaimant)
return false;
Claimant = InClaimant;
return true;
}
void ANPCTargetLocation::Release(ANPC* Requester)
{
if (!Claimant.IsValid() || Claimant.Get() != Requester)
return;
Claimant = nullptr;
}
@@ -0,0 +1,31 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "NPCTargetLocation.generated.h"
class ANPC;
UCLASS()
class NAKEDDESIRE_API ANPCTargetLocation : public AActor
{
GENERATED_BODY()
public:
ANPCTargetLocation();
UFUNCTION(BlueprintCallable)
bool TryClaim(ANPC* InClaimant);
UFUNCTION(BlueprintPure)
bool IsClaimed() const { return Claimant.IsValid(); }
UFUNCTION(BlueprintCallable)
void Release(ANPC* Requester);
private:
UPROPERTY()
TWeakObjectPtr<ANPC> Claimant = nullptr;
};
+14 -2
View File
@@ -62,15 +62,27 @@ void USaveSubsystem::PopulateStartingData(UGlobalSaveGameData* Save) const
if (!GameInstance || !GameInstance->StartingSaveData)
return;
for (UItemDefinition* Definition : GameInstance->StartingSaveData->EquippedItems)
for (const UItemDefinition* Definition : GameInstance->StartingSaveData->EquippedItems)
{
if (!Definition)
continue;
UItemInstance* Instance = Definition->CreateInstance(Save);
const UItemInstance* Instance = Definition->CreateInstance(Save);
if (!Instance)
continue;
Save->AddEquippedItem(Instance);
}
for (const UItemDefinition* Definition : GameInstance->StartingSaveData->WardrobeItems)
{
if (!Definition)
continue;
const UItemInstance* Instance = Definition->CreateInstance(Save);
if (!Instance)
continue;
Save->AddWardrobeItem(Instance);
}
}