This commit is contained in:
2026-05-17 22:44:49 +03:00
commit 26fedadcd8
9071 changed files with 44364 additions and 0 deletions
@@ -0,0 +1,27 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "GoalRestriction.h"
void UGoalRestriction::Init(ANakedDesireCharacter* PlayerCharacter)
{
IsSuccess = false;
Player = PlayerCharacter;
OnUpdate.Broadcast(this);
}
void UGoalRestriction::Complete()
{
Complete(true);
}
void UGoalRestriction::Complete(const bool Value)
{
IsSuccess = Value;
OnUpdate.Broadcast(this);
}
FText UGoalRestriction::GetDescription() const
{
return FText::GetEmpty();
}
@@ -0,0 +1,44 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "GoalRestriction.generated.h"
class ANakedDesireCharacter;
class UGoalRestriction;
DECLARE_MULTICAST_DELEGATE_OneParam(FMissionRestrictionUpdateSignature, UGoalRestriction*);
/**
*
*/
UCLASS(EditInlineNew, BlueprintType)
class NAKEDDESIRE_API UGoalRestriction : public UObject
{
GENERATED_BODY()
public:
FMissionRestrictionUpdateSignature OnUpdate;
UFUNCTION(BlueprintPure)
bool GetIsSuccess() const
{
return IsSuccess;
}
virtual void Init(ANakedDesireCharacter* PlayerCharacter);
virtual void Complete();
virtual void Complete(bool Value);
virtual void Stop() {};
UFUNCTION(BlueprintPure)
virtual FText GetDescription() const;
protected:
UPROPERTY()
ANakedDesireCharacter* Player = nullptr;
bool IsSuccess = false;
};
@@ -0,0 +1,65 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "FlashGoal.h"
#include "NakedDesire/NPC/NPCAIController.h"
#include "NakedDesire/Player/NakedDesireCharacter.h"
#define LOCTEXT_NAMESPACE "Missions.Goals.Flash"
const FText GoalsFlashSingle = LOCTEXT("Description.Single", "Flash someone {BodyPart} once");
const FText GoalsFlashMultiple = LOCTEXT("Description.Multiple", "Flash {BodyPart} to {PeopleCount} people");
#undef LOCTEXT_NAMESPACE
void UFlashGoal::Init(ANakedDesireCharacter* PlayerCharacter)
{
Super::Init(PlayerCharacter);
PlayerNoticedHandle = PlayerCharacter->OnNoticed.AddUObject(this, &UFlashGoal::OnPlayerNoticed);
}
void UFlashGoal::Complete()
{
Super::Complete();
Player->OnNoticed.Remove(PlayerNoticedHandle);
}
FText UFlashGoal::GetDescription() const
{
const FText BodyTypeString = UPrivateBodyPartType::GetString(BodyType);
if (RequiredFlashCount == 1)
{
return FText::Format(GoalsFlashSingle,
FFormatNamedArguments
{
{TEXT("BodyPart"), BodyTypeString}
});
}
return FText::Format(GoalsFlashMultiple,
FFormatNamedArguments
{
{TEXT("BodyPart"), BodyTypeString},
{TEXT("PeopleCount"), RequiredFlashCount}
});
}
void UFlashGoal::OnPlayerNoticed(ANPCAIController* NPC)
{
if (IsCompleted || !CheckRestrictions())
{
return;
}
if (!NoticedActors.Contains(NPC))
{
NoticedActors.Add(NPC);
}
if (NoticedActors.Num() >= RequiredFlashCount)
{
Complete();
}
}
@@ -0,0 +1,37 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "NakedDesire/MissionBuilder/MissionGoal.h"
#include "NakedDesire/Player/PrivateBodyPartType.h"
#include "FlashGoal.generated.h"
class ANPCAIController;
/**
*
*/
UCLASS(EditInlineNew)
class NAKEDDESIRE_API UFlashGoal : public UMissionGoal
{
GENERATED_BODY()
UPROPERTY(EditDefaultsOnly, meta = (ClampMin = 1))
int RequiredFlashCount = 1;
UPROPERTY(EditDefaultsOnly)
EPrivateBodyPartType BodyType;
FDelegateHandle PlayerNoticedHandle;
UPROPERTY()
TSet<AActor*> NoticedActors;
public:
virtual void Init(ANakedDesireCharacter* PlayerCharacter) override;
virtual void Complete() override;
virtual FText GetDescription() const override;
private:
void OnPlayerNoticed(ANPCAIController* NPC);
};
@@ -0,0 +1,42 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "MinTimeGoal.h"
#define LOCTEXT_NAMESPACE "Missions.Goals.MinTime"
const FText GoalsMinTimeDescription = LOCTEXT("Description", "Do following at least {MinTime} seconds");
#undef LOCTEXT_NAMESPACE
FText UMinTimeGoal::GetDescription() const
{
return FText::Format(GoalsMinTimeDescription,
FFormatNamedArguments
{
{TEXT("MinTime"), MinTime}
});
}
void UMinTimeGoal::OnRestrictionUpdated(UGoalRestriction* Restriction)
{
Super::OnRestrictionUpdated(Restriction);
if (CheckRestrictions())
{
if (!TimerHandle.IsValid())
{
GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &UMinTimeGoal::TimeIsUp, MinTime, false);
}
}
else
{
if (TimerHandle.IsValid())
{
GetWorld()->GetTimerManager().ClearTimer(TimerHandle);
}
}
}
void UMinTimeGoal::TimeIsUp()
{
Complete();
}
@@ -0,0 +1,30 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "../MissionGoal.h"
#include "MinTimeGoal.generated.h"
/**
*
*/
UCLASS(EditInlineNew)
class NAKEDDESIRE_API UMinTimeGoal : public UMissionGoal
{
GENERATED_BODY()
public:
virtual FText GetDescription() const override;
protected:
virtual void OnRestrictionUpdated(UGoalRestriction* Restriction) override;
private:
UPROPERTY(EditDefaultsOnly)
float MinTime = 3.f;
FTimerHandle TimerHandle;
void TimeIsUp();
};
@@ -0,0 +1,63 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "Mission.h"
#include "MissionGoal.h"
void UMission::Init(ANakedDesireCharacter* PlayerCharacter)
{
Player = PlayerCharacter;
for (const auto& Goal : Goals)
{
Goal->Init(Player);
auto Handle = Goal->OnUpdate.AddUObject(this, &UMission::OnGoalUpdated);
GoalUpdateHandles.Add(Handle);
}
}
void UMission::OnGoalUpdated(UMissionGoal* MissionGoal)
{
if (IsCompleted)
{
return;
}
if (CheckGoals())
{
Complete();
}
}
void UMission::Complete()
{
IsCompleted = true;
for (const auto& Goal : Goals)
{
for (const auto& Handle : GoalUpdateHandles)
{
Goal->OnUpdate.Remove(Handle);
}
}
OnComplete.Broadcast(this);
}
bool UMission::CheckGoals()
{
if (IsCompleted)
{
return true;
}
for (const auto& Goal : Goals)
{
if (!Goal->GetIsCompleted() || !Goal->CheckRestrictions())
{
return false;
}
}
return true;
}
@@ -0,0 +1,67 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "Mission.generated.h"
DECLARE_MULTICAST_DELEGATE_OneParam(FMissionCompleteSignature, class UMission*);
class UMissionGoal;
class ANakedDesireCharacter;
class UGoalRestriction;
/**
*
*/
UCLASS(EditInlineNew, BlueprintType)
class NAKEDDESIRE_API UMission : public UObject
{
GENERATED_BODY()
UPROPERTY(EditDefaultsOnly, Instanced)
TArray<UMissionGoal*> Goals;
UPROPERTY(EditDefaultsOnly)
int MoneyReward = 0;
bool IsCompleted = false;
TArray<FDelegateHandle> GoalUpdateHandles;
public:
FMissionCompleteSignature OnComplete;
void Init(ANakedDesireCharacter* PlayerCharacter);
UFUNCTION(BlueprintPure)
int GetMoneyReward() const
{
return MoneyReward;
}
UFUNCTION(BlueprintPure)
TArray<UMissionGoal*> GetGoals() const
{
return Goals;
}
UFUNCTION(BlueprintPure)
bool GetIsCompleted() const
{
return IsCompleted;
}
protected:
UPROPERTY()
ANakedDesireCharacter* Player = nullptr;
private:
UFUNCTION()
void OnGoalUpdated(UMissionGoal* MissionGoal);
void Complete();
bool CheckGoals();
};
@@ -0,0 +1,70 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "MissionGoal.h"
#include "GoalRestriction.h"
void UMissionGoal::Init(ANakedDesireCharacter* PlayerCharacter)
{
Player = PlayerCharacter;
for (const auto& Elem : Restrictions)
{
Elem->Init(Player);
auto Handle = Elem->OnUpdate.AddUObject(this, &UMissionGoal::OnRestrictionUpdated);
RestrictionUpdateHandles.Add(Handle);
}
}
void UMissionGoal::Complete()
{
if (!CheckRestrictions())
{
return;
}
IsCompleted = true;
for (const auto& Restriction : Restrictions)
{
Restriction->Stop();
for (const auto& Handle : RestrictionUpdateHandles)
{
Restriction->OnUpdate.Remove(Handle);
}
}
OnUpdate.Broadcast(this);
}
bool UMissionGoal::CheckRestrictions()
{
if (IsCompleted)
{
return true;
}
for (const auto& Restriction : Restrictions)
{
if (!Restriction->GetIsSuccess())
{
return false;
}
}
return true;
}
FText UMissionGoal::GetDescription() const
{
return FText::GetEmpty();
}
void UMissionGoal::OnRestrictionUpdated(UGoalRestriction* Restriction)
{
if (IsCompleted)
{
return;
}
OnUpdate.Broadcast(this);
}
@@ -0,0 +1,58 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "MissionGoal.generated.h"
class ANakedDesireCharacter;
class UMissionGoal;
class UGoalRestriction;
DECLARE_MULTICAST_DELEGATE_OneParam(FGoalUpdateSignature, UMissionGoal*);
/**
*
*/
UCLASS(EditInlineNew, BlueprintType)
class NAKEDDESIRE_API UMissionGoal : public UObject
{
GENERATED_BODY()
UPROPERTY(EditDefaultsOnly, Instanced)
TArray<UGoalRestriction*> Restrictions;
TArray<FDelegateHandle> RestrictionUpdateHandles;
public:
virtual void Init(ANakedDesireCharacter* PlayerCharacter);
virtual void Complete();
UFUNCTION(BlueprintPure)
bool GetIsCompleted() const
{
return IsCompleted;
}
UFUNCTION(BlueprintPure)
TArray<UGoalRestriction*> GetRestrictions() const
{
return Restrictions;
}
FGoalUpdateSignature OnUpdate;
bool CheckRestrictions();
UFUNCTION(BlueprintPure)
virtual FText GetDescription() const;
protected:
UPROPERTY()
ANakedDesireCharacter* Player = nullptr;
virtual void OnRestrictionUpdated(UGoalRestriction* Restriction);
bool IsCompleted = false;
};
@@ -0,0 +1,4 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "MissionsConfig.h"
@@ -0,0 +1,34 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "MissionsConfig.generated.h"
class UMission;
USTRUCT()
struct NAKEDDESIRE_API FMissionsConfigItem
{
GENERATED_BODY()
UPROPERTY(EditDefaultsOnly, Instanced)
TArray<UMission*> Missions;
};
/**
*
*/
UCLASS()
class NAKEDDESIRE_API UMissionsConfig : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditDefaultsOnly)
TArray<FMissionsConfigItem> DailyMissions;
UPROPERTY(EditDefaultsOnly)
TArray<FMissionsConfigItem> WeeklyMissions;
};
@@ -0,0 +1,69 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "MissionsManager.h"
#include "Mission.h"
#include "NakedDesire/Player/NakedDesireCharacter.h"
UMissionsManager::UMissionsManager()
{
PrimaryComponentTick.bCanEverTick = false;
}
void UMissionsManager::BeginPlay()
{
Super::BeginPlay();
Player = Cast<ANakedDesireCharacter>(GetOwner());
UE_LOG(LogTemp, Warning, TEXT("Player is NULL %s"), Player == nullptr ? TEXT("True") : TEXT("False"));
for (const auto& Mission : AvailableMissions)
{
Mission->Init(Player);
Mission->OnComplete.AddUObject(this, &UMissionsManager::CompleteMission);
}
}
void UMissionsManager::CompleteMission(UMission* Mission)
{
CompletedMissions.Add(Mission);
AvailableMissions.Remove(Mission);
OnMissionCompleted.Broadcast(Mission);
}
void UMissionsManager::CollectRewards()
{
if (CompletedMissions.IsEmpty())
{
return;
}
int TotalReward = 0;
for (const UMission* Mission : CompletedMissions)
{
TotalReward += Mission->GetMoneyReward();
}
Player->Money += TotalReward;
CompletedMissions.Empty();
OnRewardsCollected.Broadcast(TotalReward);
}
void UMissionsManager::RefreshDailyMissions(const TArray<UMission*>& NewMissions)
{
for (auto Mission : AvailableMissions)
{
Mission->OnComplete.RemoveAll(this);
AvailableMissions.Remove(Mission);
}
AvailableMissions.Append(NewMissions);
for (auto Mission : AvailableMissions)
{
Mission->Init(Player);
Mission->OnComplete.AddUObject(this, &UMissionsManager::CompleteMission);
}
}
@@ -0,0 +1,49 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "MissionsManager.generated.h"
class UMission;
class ANakedDesireCharacter;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMissionCompletedSignature, UMission*, Mission);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRewardsCollected, int, Reward);
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class NAKEDDESIRE_API UMissionsManager : public UActorComponent
{
GENERATED_BODY()
UPROPERTY()
ANakedDesireCharacter* Player = nullptr;
public:
UMissionsManager();
UPROPERTY(EditDefaultsOnly, Instanced, BlueprintReadOnly)
TArray<UMission*> AvailableMissions;
UPROPERTY(BlueprintReadWrite)
TArray<UMission*> CompletedMissions;
UPROPERTY(BlueprintAssignable)
FOnMissionCompletedSignature OnMissionCompleted;
UPROPERTY(BlueprintAssignable)
FOnRewardsCollected OnRewardsCollected;
void CompleteMission(UMission* Mission);
UFUNCTION(BlueprintCallable)
void CollectRewards();
UFUNCTION()
void RefreshDailyMissions(const TArray<UMission*>& NewMissions);
protected:
virtual void BeginPlay() override;
};
@@ -0,0 +1,110 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "EquipClothingRestriction.h"
#include "NakedDesire/Clothing/ClothingItem.h"
#include "NakedDesire/Clothing/ClothingItemData.h"
#include "NakedDesire/Clothing/ClothingManager.h"
#include "NakedDesire/Player/NakedDesireCharacter.h"
#define LOCTEXT_NAMESPACE "Missions.Restriction.EquipClothing"
const FText RestrictionEquipClothingDescriptionSingle = LOCTEXT("Description.Single", "Equip {ItemName}");
const FText RestrictionEquipClothingDescriptionMultiple = LOCTEXT("Description.Multiple", "Equip one of: {ItemNames}");
#undef LOCTEXT_NAMESPACE
void UEquipClothingRestriction::Init(ANakedDesireCharacter* PlayerCharacter)
{
Super::Init(PlayerCharacter);
if (!ClothingEquippedDelegateHandle.IsValid())
{
Player->ClothingManager->OnClothingEquip.AddUniqueDynamic(this, &UEquipClothingRestriction::OnClothingEquipped);
}
if (!ClothingUnequippedDelegateHandle.IsValid())
{
Player->ClothingManager->OnClothingUnequip.AddUniqueDynamic(this, &UEquipClothingRestriction::OnClothingUnequipped);
}
CheckClothing();
}
void UEquipClothingRestriction::Stop()
{
Super::Stop();
Player->ClothingManager->OnClothingEquip.Remove(this, TEXT("OnClothingEquipped"));
Player->ClothingManager->OnClothingUnequip.Remove(this, TEXT("OnClothingUnequipped"));
}
FText UEquipClothingRestriction::GetDescription() const
{
if (ClothingItems.Num() == 1 && ClothingItems[0])
{
return FText::Format(RestrictionEquipClothingDescriptionSingle,
FFormatNamedArguments
{
{TEXT("ItemName"), ClothingItems[0]->Name}
});
}
FString Items = TEXT("");
for (const auto& Item : ClothingItems)
{
if (Item)
{
Items += Item->Name.ToString() + ", ";
}
}
return FText::Format(RestrictionEquipClothingDescriptionMultiple,
FFormatNamedArguments
{
{TEXT("ItemNames"), FText::FromString(Items)}
});
}
void UEquipClothingRestriction::OnClothingEquipped(const UClothingItemData* ClothingData)
{
const bool IsTargetClothing = ClothingItems.FindByPredicate([&ClothingData](const UClothingItem* Item)
{
return Item && Item->Name.EqualTo(ClothingData->Info->Name);
}) != nullptr;
if (IsTargetClothing)
{
Complete();
}
}
void UEquipClothingRestriction::OnClothingUnequipped(const UClothingItemData* ClothingData)
{
const bool IsTargetClothing = ClothingItems.FindByPredicate([&ClothingData](const UClothingItem* Item)
{
return Item && Item->Name.EqualTo(ClothingData->Info->Name);
}) != nullptr;
if (IsTargetClothing)
{
Init(Player);
}
}
void UEquipClothingRestriction::CheckClothing()
{
for (const FClothingSlotData& ClothingSlot : Player->ClothingManager->ClothingSlots)
{
if (!ClothingSlot.ClothingData)
{
continue;
}
const bool IsTargetClothing = ClothingItems.FindByPredicate([&ClothingSlot](const UClothingItem* Item)
{
return Item && Item->Name.EqualTo(ClothingSlot.ClothingData->Info->Name);
}) != nullptr;
if (IsTargetClothing)
{
Complete();
return;
}
}
}
@@ -0,0 +1,39 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "NakedDesire/MissionBuilder/GoalRestriction.h"
#include "EquipClothingRestriction.generated.h"
class UClothingItem;
class UClothingItemData;
/**
*
*/
UCLASS(EditInlineNew)
class NAKEDDESIRE_API UEquipClothingRestriction : public UGoalRestriction
{
GENERATED_BODY()
UPROPERTY(EditDefaultsOnly, meta = (ToolTip =
"One of provided clothing items should be equipped by player. If multiple clothing items required provide multiple restrictions"))
TArray<UClothingItem*> ClothingItems;
public:
virtual void Init(ANakedDesireCharacter* PlayerCharacter) override;
virtual void Stop() override;
virtual FText GetDescription() const override;
private:
FDelegateHandle ClothingEquippedDelegateHandle;
FDelegateHandle ClothingUnequippedDelegateHandle;
UFUNCTION()
void OnClothingEquipped(const UClothingItemData* ClothingData);
UFUNCTION()
void OnClothingUnequipped(const UClothingItemData* ClothingData);
void CheckClothing();
};
@@ -0,0 +1,81 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "ExposeBodyPartRestriction.h"
#include "NakedDesire/Clothing/ClothingItemData.h"
#include "NakedDesire/Player/NakedDesireCharacter.h"
#include "NakedDesire/Clothing/ClothingManager.h"
#define LOCTEXT_NAMESPACE "Missions.Restrictions.ExposeBodyPart"
const FText RestrictionsExposeBodyPartDescription = LOCTEXT("Description", "Expose {BodyPart}");
#undef LOCTEXT_NAMESPACE
void UExposeBodyPartRestriction::Init(ANakedDesireCharacter* PlayerCharacter)
{
Super::Init(PlayerCharacter);
PlayerCharacter->ClothingManager->OnClothingEquip.AddUniqueDynamic(this, &UExposeBodyPartRestriction::EquipClothing);
PlayerCharacter->ClothingManager->OnClothingUnequip.AddUniqueDynamic(this, &UExposeBodyPartRestriction::UnequipClothing);
CheckClothing();
}
void UExposeBodyPartRestriction::Stop()
{
Super::Stop();
Player->ClothingManager->OnClothingEquip.Remove(this, TEXT("ClothingEquip"));
Player->ClothingManager->OnClothingUnequip.Remove(this, TEXT("ClothingUnequip"));
}
FText UExposeBodyPartRestriction::GetDescription() const
{
FText Part = UPrivateBodyPartType::GetString(BodyPart);
return FText::Format(RestrictionsExposeBodyPartDescription,
FFormatNamedArguments
{
{TEXT("BodyPart"), Part}
});
}
void UExposeBodyPartRestriction::EquipClothing(const UClothingItemData* ClothingData)
{
if (IsSuccess && ClothingData->Info->CoveredBodyParts.Contains(BodyPart))
{
Init(Player);
}
}
void UExposeBodyPartRestriction::UnequipClothing(const UClothingItemData* ClothingData)
{
if (IsSuccess)
{
return;
}
CheckClothing();
}
void UExposeBodyPartRestriction::CheckClothing()
{
if (!Player || !Player->ClothingManager || Player->ClothingManager->ClothingSlots.IsEmpty())
{
return;
}
const FClothingSlotData* TargetClothingItem = Player->ClothingManager->ClothingSlots.FindByPredicate([this](const FClothingSlotData& ClothingSlot)
{
if (ClothingSlot.ClothingData)
{
return ClothingSlot.ClothingData->Info->CoveredBodyParts.Contains(BodyPart);
}
return false;
});
if (!TargetClothingItem)
{
Complete();
}
}
@@ -0,0 +1,38 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "NakedDesire/Player/PrivateBodyPartType.h"
#include "NakedDesire/MissionBuilder/GoalRestriction.h"
#include "ExposeBodyPartRestriction.generated.h"
class UClothingItemData;
/**
*
*/
UCLASS(EditInlineNew)
class NAKEDDESIRE_API UExposeBodyPartRestriction : public UGoalRestriction
{
GENERATED_BODY()
FDelegateHandle EquipClothingHandle;
FDelegateHandle UnequipClothingHandle;
UPROPERTY(EditDefaultsOnly)
EPrivateBodyPartType BodyPart;
protected:
virtual void Init(ANakedDesireCharacter* PlayerCharacter) override;
virtual void Stop() override;
virtual FText GetDescription() const override;
private:
UFUNCTION()
void EquipClothing(const UClothingItemData* ClothingData);
UFUNCTION()
void UnequipClothing(const UClothingItemData* ClothingData);
void CheckClothing();
};
@@ -0,0 +1,51 @@
// © 2025 Naked People Team. All Rights Reserved.
#include "LocationRestriction.h"
#include "NakedDesire/Locations/LocationData.h"
#include "NakedDesire/Player/NakedDesireCharacter.h"
#define LOCTEXT_NAMESPACE "Missions.Restrictions.Location"
const FText RestrictionsLocationDescription = LOCTEXT("Description", "Visit {LocationName}");
#undef LOCTEXT_NAMESPACE
void ULocationRestriction::Init(ANakedDesireCharacter* PlayerCharacter)
{
Super::Init(PlayerCharacter);
AreaEnterHandle = PlayerCharacter->OnAreaEnter.AddUObject(this, &ULocationRestriction::OnAreaEnter);
AreaExitHandle = PlayerCharacter->OnAreaExit.AddUObject(this, &ULocationRestriction::OnAreaExit);
}
void ULocationRestriction::Stop()
{
Super::Stop();
Player->OnAreaEnter.Remove(AreaEnterHandle);
Player->OnAreaExit.Remove(AreaExitHandle);
}
FText ULocationRestriction::GetDescription() const
{
return FText::Format(RestrictionsLocationDescription,
FFormatNamedArguments
{
{TEXT("LocationName"), TargetLocation->Name}
});
}
void ULocationRestriction::OnAreaEnter(ULocationData* LocationData)
{
if (!IsSuccess && LocationData->Tag.MatchesTag(TargetLocation->Tag))
{
Complete();
}
}
void ULocationRestriction::OnAreaExit(ULocationData* LocationData)
{
if (IsSuccess && LocationData->Tag.MatchesTag(TargetLocation->Tag))
{
Init(Player);
}
}
@@ -0,0 +1,32 @@
// © 2025 Naked People Team. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "NakedDesire/MissionBuilder/GoalRestriction.h"
#include "LocationRestriction.generated.h"
class ULocationData;
/**
*
*/
UCLASS()
class NAKEDDESIRE_API ULocationRestriction : public UGoalRestriction
{
GENERATED_BODY()
FDelegateHandle AreaEnterHandle;
FDelegateHandle AreaExitHandle;
UPROPERTY(EditDefaultsOnly)
ULocationData* TargetLocation;
protected:
virtual void Init(ANakedDesireCharacter* PlayerCharacter) override;
virtual void Stop() override;
virtual FText GetDescription() const override;
private:
void OnAreaEnter(ULocationData* LocationData);
void OnAreaExit(ULocationData* LocationData);
};