// © 2025 Naked People Team. All Rights Reserved. #include "CommissionObjective.h" #include "TimerManager.h" #include "CommissionConstraint.h" #include "NakedDesire/Player/NakedDesireCharacter.h" void UCommissionObjective::Activate(ANakedDesireCharacter* InPlayer) { Player = InPlayer; bSatisfied = false; OnActivate(); for (UCommissionConstraint* Constraint : Constraints) { if (!Constraint) continue; Constraint->OnConstraintChanged.AddUObject(this, &UCommissionObjective::HandleConstraintChanged); Constraint->Activate(Player); } NotifyConditionChanged(); // evaluate the starting state (e.g. already naked on accept) } void UCommissionObjective::Deactivate() { ClearHoldTimer(); for (UCommissionConstraint* Constraint : Constraints) { if (!Constraint) continue; Constraint->OnConstraintChanged.RemoveAll(this); Constraint->Deactivate(); } OnDeactivate(); Player = nullptr; } bool UCommissionObjective::AreConstraintsMet() const { for (const UCommissionConstraint* Constraint : Constraints) { if (Constraint && !Constraint->IsMet()) return false; } return true; } void UCommissionObjective::HandleConstraintChanged() { NotifyConditionChanged(); } void UCommissionObjective::NotifyConditionChanged() { if (bSatisfied || !Player) return; if (IsConditionMet() && AreConstraintsMet()) { if (RequiredHoldSeconds <= 0.0f) { MarkSatisfied(); return; } if (!HoldTimerHandle.IsValid()) { HoldStartTime = Player->GetWorld()->GetTimeSeconds(); Player->GetWorldTimerManager().SetTimer(HoldTimerHandle, this, &UCommissionObjective::OnHoldElapsed, RequiredHoldSeconds, false); } } else { ClearHoldTimer(); } } void UCommissionObjective::OnHoldElapsed() { MarkSatisfied(); } void UCommissionObjective::MarkSatisfied() { if (bSatisfied) return; bSatisfied = true; ClearHoldTimer(); OnStateChanged.Broadcast(this); } void UCommissionObjective::ClearHoldTimer() { if (HoldTimerHandle.IsValid() && Player) Player->GetWorldTimerManager().ClearTimer(HoldTimerHandle); HoldTimerHandle.Invalidate(); HoldStartTime = 0.0f; } FText UCommissionObjective::GetDescription() const { return FText::GetEmpty(); } float UCommissionObjective::GetProgress() const { if (bSatisfied) return 1.0f; if (HoldTimerHandle.IsValid() && Player && RequiredHoldSeconds > 0.0f) { const float Elapsed = Player->GetWorld()->GetTimeSeconds() - HoldStartTime; return FMath::Clamp(Elapsed / RequiredHoldSeconds, 0.0f, 1.0f); } return 0.0f; }