From 909583a1bbb5614b8f032093a54d5ca9128c214f Mon Sep 17 00:00:00 2001 From: "j.foucher" Date: Thu, 26 Mar 2026 08:41:42 +0100 Subject: [PATCH] Fix PS_AI_Behavior compilation errors for UE 5.5 - Remove NavigationSystem from .uplugin Plugins (it's a module, not a plugin) - Fix UInterface naming: IPS_AI_Behavior -> IPS_AI_Behavior_Interface (UHT requirement) - Fix TWeakObjectPtr TArray not Blueprint-compatible (remove BlueprintReadOnly) - Fix UseBlackboard TObjectPtr ref: use raw pointer intermediary - Fix FEdMode::HandleClick signature: FInputClick -> FViewportClick (UE 5.5) - Fix SplineNetwork: use OnWorldBeginPlay(UWorld&) override instead of delegate - Fix PerceptionComponent: remove const from methods calling non-const GetActorsPerception - Fix EQS SetScore: use 5-arg float overload (Score, FilterMin, FilterMax) - Fix BTTask_FindCover: add missing Definitions.h include, fix const World - Fix BTTask_FollowSpline: replace AddWeakLambda with polling in TickTask - Fix CoverPoint: initialize Color before switch, add default case - Export LogPS_AI_Behavior with PS_AI_BEHAVIOR_API for cross-module visibility - Remove unused variables (WorldOrigin, WorldDirection) Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Plugins/PS_AI_Behavior/PLAN.md | 511 ++++++++++++++++++ .../PS_AI_Behavior/PS_AI_Behavior.uplugin | 7 +- .../BT/PS_AI_Behavior_BTTask_FindCover.cpp | 2 +- .../BT/PS_AI_Behavior_BTTask_FollowSpline.cpp | 32 +- ...S_AI_Behavior_EQSGenerator_CoverPoints.cpp | 2 +- .../PS_AI_Behavior_EQSTest_CoverQuality.cpp | 4 +- .../Private/PS_AI_Behavior_AIController.cpp | 12 +- .../Private/PS_AI_Behavior_CoverPoint.cpp | 4 +- .../PS_AI_Behavior_PerceptionComponent.cpp | 12 +- .../PS_AI_Behavior_PersonalityComponent.cpp | 8 +- ...PS_AI_Behavior_SplineFollowerComponent.cpp | 1 + .../Private/PS_AI_Behavior_SplineNetwork.cpp | 13 +- .../BT/PS_AI_Behavior_BTTask_FindCover.h | 1 + .../Public/PS_AI_Behavior_CoverPoint.h | 2 +- .../Public/PS_AI_Behavior_Definitions.h | 2 +- .../Public/PS_AI_Behavior_Interface.h | 2 +- .../PS_AI_Behavior_PerceptionComponent.h | 8 +- .../Public/PS_AI_Behavior_SplineNetwork.h | 6 +- .../Private/PS_AI_Behavior_SplineEdMode.cpp | 9 +- .../Public/PS_AI_Behavior_SplineEdMode.h | 2 +- 20 files changed, 564 insertions(+), 76 deletions(-) create mode 100644 Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/PLAN.md diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/PLAN.md b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/PLAN.md new file mode 100644 index 0000000..a7b74e7 --- /dev/null +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/PLAN.md @@ -0,0 +1,511 @@ +# PS_AI_Behavior — Plan d'implémentation V1 + +## Vue d'ensemble +Plugin UE5.5 pour gérer les comportements de NPCs (civils et ennemis) via Behavior Trees, EQS et un système de personnalité à scores. Navigation sur NavMesh, détection d'ennemis, combat basique, fuite, couverture. + +Dépendance optionnelle vers PS_AI_ConvAgent (détectée à l'exécution, pas de link-time dependency). + +--- + +## 1. Structure du plugin + +``` +Plugins/PS_AI_Behavior/ +├── PS_AI_Behavior.uplugin +├── Config/ +│ └── DefaultPS_AI_Behavior.ini +├── Content/ +│ ├── BehaviorTrees/ +│ │ ├── BT_Civilian.uasset (BT civils) +│ │ └── BT_Enemy.uasset (BT ennemis) +│ ├── EQS/ +│ │ ├── EQS_FindCover.uasset (trouver couverture) +│ │ ├── EQS_FindFleePoint.uasset (point de fuite) +│ │ └── EQS_FindPatrolPoint.uasset (point de patrouille) +│ └── Data/ +│ ├── DA_Trait_Coward.uasset (exemple Data Asset) +│ └── DA_Trait_Aggressive.uasset +└── Source/ + ├── PS_AI_Behavior/ (module Runtime) + │ ├── PS_AI_Behavior.Build.cs + │ ├── Public/ + │ │ ├── PS_AI_Behavior.h (module def) + │ │ ├── PS_AI_Behavior_Definitions.h (enums, structs, log category) + │ │ ├── PS_AI_Behavior_Settings.h (Project Settings) + │ │ │ + │ │ ├── PS_AI_Behavior_AIController.h (AIController principal) + │ │ ├── PS_AI_Behavior_PersonalityComponent.h (traits de personnalité) + │ │ ├── PS_AI_Behavior_PerceptionComponent.h (wrapper AIPerception) + │ │ ├── PS_AI_Behavior_CombatComponent.h (état combat) + │ │ ├── PS_AI_Behavior_PersonalityProfile.h (Data Asset profil) + │ │ │ + │ │ ├── BT/ (BT Tasks, Services, Decorators) + │ │ │ ├── PS_AI_Behavior_BTTask_FindCover.h + │ │ │ ├── PS_AI_Behavior_BTTask_FleeFrom.h + │ │ │ ├── PS_AI_Behavior_BTTask_Attack.h + │ │ │ ├── PS_AI_Behavior_BTTask_Patrol.h + │ │ │ ├── PS_AI_Behavior_BTService_UpdateThreat.h + │ │ │ ├── PS_AI_Behavior_BTService_EvaluateReaction.h + │ │ │ └── PS_AI_Behavior_BTDecorator_CheckTrait.h + │ │ │ + │ │ └── EQS/ + │ │ ├── PS_AI_Behavior_EQSContext_Threat.h + │ │ └── PS_AI_Behavior_EQSTest_CoverQuality.h + │ │ + │ └── Private/ + │ ├── PS_AI_Behavior.cpp + │ ├── PS_AI_Behavior_Settings.cpp + │ ├── PS_AI_Behavior_AIController.cpp + │ ├── PS_AI_Behavior_PersonalityComponent.cpp + │ ├── PS_AI_Behavior_PerceptionComponent.cpp + │ ├── PS_AI_Behavior_CombatComponent.cpp + │ ├── PS_AI_Behavior_PersonalityProfile.cpp + │ ├── BT/ + │ │ ├── PS_AI_Behavior_BTTask_FindCover.cpp + │ │ ├── PS_AI_Behavior_BTTask_FleeFrom.cpp + │ │ ├── PS_AI_Behavior_BTTask_Attack.cpp + │ │ ├── PS_AI_Behavior_BTTask_Patrol.cpp + │ │ ├── PS_AI_Behavior_BTService_UpdateThreat.cpp + │ │ ├── PS_AI_Behavior_BTService_EvaluateReaction.cpp + │ │ └── PS_AI_Behavior_BTDecorator_CheckTrait.cpp + │ └── EQS/ + │ ├── PS_AI_Behavior_EQSContext_Threat.cpp + │ └── PS_AI_Behavior_EQSTest_CoverQuality.cpp + │ + └── PS_AI_BehaviorEditor/ (module Editor — futur, pas V1) + ├── PS_AI_BehaviorEditor.Build.cs + └── ... +``` + +--- + +## 2. Classes principales + +### 2.1 Definitions (`PS_AI_Behavior_Definitions.h`) + +```cpp +// Log category +DECLARE_LOG_CATEGORY_EXTERN(LogPS_AI_Behavior, Log, All); + +// Type de NPC +UENUM(BlueprintType) +enum class EPS_AI_Behavior_NPCType : uint8 +{ + Civilian, + Enemy, + Neutral +}; + +// État comportemental haut-niveau +UENUM(BlueprintType) +enum class EPS_AI_Behavior_State : uint8 +{ + Idle, + Patrol, + Alerted, + Combat, + Fleeing, + TakingCover, + Dead +}; + +// Axes de personnalité (scores 0.0 → 1.0) +UENUM(BlueprintType) +enum class EPS_AI_Behavior_TraitAxis : uint8 +{ + Courage, // 0 = lâche, 1 = téméraire + Aggressivity, // 0 = pacifique, 1 = violent + Loyalty, // 0 = égoïste, 1 = dévoué + Caution, // 0 = imprudent, 1 = prudent + Discipline // 0 = indiscipliné, 1 = discipliné +}; + +// Struct pour un trait + valeur +USTRUCT(BlueprintType) +struct FPS_AI_Behavior_TraitScore +{ + GENERATED_BODY() + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(ClampMin=0.0, ClampMax=1.0)) + float Value = 0.5f; +}; +``` + +### 2.2 PersonalityProfile — Data Asset (`PS_AI_Behavior_PersonalityProfile.h`) + +```cpp +UCLASS(BlueprintType) +class PS_AI_BEHAVIOR_API UPS_AI_Behavior_PersonalityProfile : public UPrimaryDataAsset +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Personality") + FText ProfileName; + + // Scores par axe : TMap + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Personality") + TMap TraitScores; + + // Seuils de réaction + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Reaction Thresholds", + meta=(ClampMin=0.0, ClampMax=1.0)) + float FleeThreshold = 0.6f; // Threat level au-delà duquel on fuit (modulé par Courage) + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Reaction Thresholds", + meta=(ClampMin=0.0, ClampMax=1.0)) + float AttackThreshold = 0.4f; // Threat level au-delà duquel on attaque (modulé par Aggressivity) + + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Behavior") + EPS_AI_Behavior_NPCType DefaultNPCType = EPS_AI_Behavior_NPCType::Civilian; + + // Behavior Tree à utiliser (peut être overridé par l'AIController) + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Behavior") + TSoftObjectPtr DefaultBehaviorTree; + + // Helper + float GetTrait(EPS_AI_Behavior_TraitAxis Axis) const; +}; +``` + +### 2.3 PersonalityComponent (`PS_AI_Behavior_PersonalityComponent.h`) + +Attaché au Pawn. Fournit l'accès runtime aux traits, modifie les seuils dynamiquement. + +```cpp +UCLASS(ClassGroup="PS AI Behavior", meta=(BlueprintSpawnableComponent)) +class PS_AI_BEHAVIOR_API UPS_AI_Behavior_PersonalityComponent : public UActorComponent +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Personality") + UPS_AI_Behavior_PersonalityProfile* Profile; + + // Runtime overrides (initialisés depuis Profile au BeginPlay) + UPROPERTY(BlueprintReadWrite, Category="Personality|Runtime") + TMap RuntimeTraits; + + // Threat level perçu (mis à jour par BTService_UpdateThreat) + UPROPERTY(BlueprintReadWrite, Category="Personality|Runtime") + float PerceivedThreatLevel = 0.0f; + + // Décision finale basée sur traits + threat + UFUNCTION(BlueprintCallable, Category="PS AI Behavior|Personality") + EPS_AI_Behavior_State EvaluateReaction() const; + + UFUNCTION(BlueprintCallable, Category="PS AI Behavior|Personality") + float GetTrait(EPS_AI_Behavior_TraitAxis Axis) const; + + UFUNCTION(BlueprintCallable, Category="PS AI Behavior|Personality") + void ModifyTrait(EPS_AI_Behavior_TraitAxis Axis, float Delta); +}; +``` + +**Logique `EvaluateReaction()`** : +``` +EffectiveCourage = RuntimeTraits[Courage] * (1 - PerceivedThreatLevel * 0.5) +if PerceivedThreatLevel > FleeThreshold * (1 + EffectiveCourage) → Fleeing +if PerceivedThreatLevel > AttackThreshold * (1 - Aggressivity) → Combat +if PerceivedThreatLevel > 0.1 → Alerted +else → Idle/Patrol +``` + +### 2.4 AIController (`PS_AI_Behavior_AIController.h`) + +```cpp +UCLASS() +class PS_AI_BEHAVIOR_API APS_AI_Behavior_AIController : public AAIController +{ + GENERATED_BODY() +public: + APS_AI_Behavior_AIController(); + + // Blackboard keys (nom constants) + static const FName BB_State; // EPS_AI_Behavior_State + static const FName BB_ThreatActor; // UObject* + static const FName BB_ThreatLocation; // FVector + static const FName BB_ThreatLevel; // float + static const FName BB_CoverLocation; // FVector + static const FName BB_PatrolIndex; // int32 + static const FName BB_HomeLocation; // FVector + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Behavior") + UBehaviorTree* BehaviorTreeAsset; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Behavior") + UBlackboardData* BlackboardAsset; + + // Patrol waypoints (set par level designer ou spawner) + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Patrol") + TArray PatrolPoints; + +protected: + virtual void OnPossess(APawn* InPawn) override; + virtual void OnUnPossess() override; + + // Auto-détection optionnelle de PS_AI_ConvAgent + void TryBindConversationAgent(); +}; +``` + +**`OnPossess`** : +1. Trouve `PersonalityComponent` sur le Pawn +2. Crée/initialise le Blackboard +3. Lit `DefaultBehaviorTree` du ProfileData (ou utilise `BehaviorTreeAsset`) +4. Lance `RunBehaviorTree()` +5. Appelle `TryBindConversationAgent()` + +**`TryBindConversationAgent()`** : +- Via `FindComponentByClass` (pas de include direct, utilise `FindObject` ou interface) +- Si trouvé : bind OnAgentActionRequested pour injecter des actions dans le BT + +### 2.5 PerceptionComponent (`PS_AI_Behavior_PerceptionComponent.h`) + +Wrapper configuré autour de `UAIPerceptionComponent` : + +```cpp +UCLASS(ClassGroup="PS AI Behavior", meta=(BlueprintSpawnableComponent)) +class PS_AI_BEHAVIOR_API UPS_AI_Behavior_PerceptionComponent : public UAIPerceptionComponent +{ + GENERATED_BODY() +public: + UPS_AI_Behavior_PerceptionComponent(); + + // Pré-configure : Sight (60m, 90° FOV) + Hearing (30m) + Damage + virtual void BeginPlay() override; + + UFUNCTION(BlueprintCallable, Category="PS AI Behavior|Perception") + AActor* GetHighestThreat() const; + + UFUNCTION(BlueprintCallable, Category="PS AI Behavior|Perception") + float CalculateThreatLevel() const; + +protected: + UFUNCTION() + void OnPerceptionUpdated(const TArray& UpdatedActors); +}; +``` + +### 2.6 CombatComponent (`PS_AI_Behavior_CombatComponent.h`) + +Gère l'état combat, les distances, le cooldown d'attaque : + +```cpp +UCLASS(ClassGroup="PS AI Behavior", meta=(BlueprintSpawnableComponent)) +class PS_AI_BEHAVIOR_API UPS_AI_Behavior_CombatComponent : public UActorComponent +{ + GENERATED_BODY() +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Combat") + float AttackRange = 200.0f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Combat") + float AttackCooldown = 1.5f; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Combat") + float AttackDamage = 20.0f; + + UFUNCTION(BlueprintCallable, Category="PS AI Behavior|Combat") + bool CanAttack() const; + + UFUNCTION(BlueprintCallable, Category="PS AI Behavior|Combat") + void ExecuteAttack(AActor* Target); + + UFUNCTION(BlueprintCallable, Category="PS AI Behavior|Combat") + bool IsInAttackRange(AActor* Target) const; +}; +``` + +--- + +## 3. Behavior Tree — Nodes + +### 3.1 Services (tournent en continu) + +**BTService_UpdateThreat** : +- Lit `PerceptionComponent::CalculateThreatLevel()` +- Écrit `BB_ThreatLevel`, `BB_ThreatActor`, `BB_ThreatLocation` +- Met à jour `PersonalityComponent::PerceivedThreatLevel` + +**BTService_EvaluateReaction** : +- Appelle `PersonalityComponent::EvaluateReaction()` +- Écrit `BB_State` dans le Blackboard +- Le BT utilise des decorators pour brancher sur cet état + +### 3.2 Tasks + +**BTTask_Patrol** : +- Lit `BB_PatrolIndex`, navigue vers `PatrolPoints[idx]` +- Au succès, incrémente l'index (cyclique) +- Supporte pause aléatoire aux waypoints + +**BTTask_FleeFrom** : +- Lit `BB_ThreatLocation` +- Utilise EQS `EQS_FindFleePoint` (direction opposée à la menace) +- `MoveTo()` vers le point trouvé + +**BTTask_FindCover** : +- Lance EQS `EQS_FindCover` (scoring : distance menace, line-of-sight block, distance au NPC) +- Navigue vers le meilleur point +- Écrit `BB_CoverLocation` + +**BTTask_Attack** : +- Vérifie `CombatComponent::CanAttack()` +- Si hors range : `MoveTo(Target)` +- Si in range : `CombatComponent::ExecuteAttack(Target)` + +### 3.3 Decorators + +**BTDecorator_CheckTrait** : +- Paramètres : `TraitAxis`, `ComparisonOp` (>, <, ==), `Threshold` +- Lit le trait depuis `PersonalityComponent` +- Exemple : "Exécuter seulement si Courage > 0.5" + +--- + +## 4. EQS + +### EQS_FindCover +- **Generator** : Points sur grille autour du NPC (rayon 15m) +- **Tests** : + - Distance à la menace (préfère mi-distance, pas trop loin) + - Trace visibility (préfère les points non-visibles depuis la menace) + - Distance au NPC (préfère les points proches) + - `EQSTest_CoverQuality` (custom) : raycasts multiples pour évaluer la qualité de couverture + +### EQS_FindFleePoint +- **Generator** : Points sur donut (rayon 10-25m) +- **Tests** : + - Dot product direction (opposé à la menace : score max) + - PathExistence (doit être atteignable sur NavMesh) + - Distance à la menace (préfère loin) + +### EQS_FindPatrolPoint +- **Generator** : Points depuis la liste PatrolPoints de l'AIController +- **Tests** : + - Distance au NPC (préfère le plus proche non-visité) + +### EQSContext_Threat +- Renvoie l'acteur/location de `BB_ThreatActor` / `BB_ThreatLocation` + +--- + +## 5. Intégration optionnelle PS_AI_ConvAgent + +**Mécanisme** : Pas de `#include` direct. L'AIController utilise `FindComponentByClass` avec le nom de classe via UObject reflection : + +```cpp +void APS_AI_Behavior_AIController::TryBindConversationAgent() +{ + // Soft reference — no link-time dependency + UActorComponent* ConvComp = GetPawn()->FindComponentByClass( + LoadClass(nullptr, + TEXT("/Script/PS_AI_ConvAgent.PS_AI_ConvAgent_ElevenLabsComponent"))); + if (ConvComp) + { + // Bind to OnAgentActionRequested via dynamic delegate + // Actions from conversation can inject BT state changes + } +} +``` + +Cela permet : +- Un NPC conversationnel qui reçoit "Fuis !" via ElevenLabs → injecte State=Fleeing dans le BT +- Aucune dépendance de compilation + +--- + +## 6. Build.cs — Dépendances + +```csharp +// PS_AI_Behavior.Build.cs +PublicDependencyModuleNames.AddRange(new string[] { + "Core", "CoreUObject", "Engine", + "AIModule", // AAIController, BehaviorTree, Blackboard + "GameplayTasks", // UGameplayTask (requis par BT tasks) + "NavigationSystem", // NavMesh queries +}); + +PrivateDependencyModuleNames.AddRange(new string[] { + "Settings", // ISettingsModule +}); + +// PAS de dépendance vers PS_AI_ConvAgent +``` + +--- + +## 7. Ordre d'implémentation (étapes) + +### Étape 1 — Squelette plugin +- [ ] Créer la structure de fichiers du plugin +- [ ] `.uplugin`, `Build.cs`, module class +- [ ] `Definitions.h` (enums, structs, log category) +- [ ] `Settings.h/cpp` (settings vides pour l'instant) +- [ ] Ajouter au `.uproject` +- [ ] **Vérification** : compile sans erreur + +### Étape 2 — Personality System +- [ ] `PersonalityProfile` (Data Asset) +- [ ] `PersonalityComponent` avec `EvaluateReaction()` +- [ ] **Vérification** : peut créer un Data Asset dans l'éditeur, lire les traits en BP + +### Étape 3 — AIController + Perception +- [ ] `PS_AI_Behavior_AIController` avec Blackboard setup +- [ ] `PS_AI_Behavior_PerceptionComponent` (sight + hearing) +- [ ] `BlackboardData` asset par défaut +- [ ] **Vérification** : un NPC spawné détecte les acteurs proches + +### Étape 4 — BT Services + Decorators +- [ ] `BTService_UpdateThreat` +- [ ] `BTService_EvaluateReaction` +- [ ] `BTDecorator_CheckTrait` +- [ ] **Vérification** : le Blackboard se met à jour en jeu + +### Étape 5 — BT Tasks (Navigation) +- [ ] `BTTask_Patrol` +- [ ] `BTTask_FleeFrom` +- [ ] `BTTask_FindCover` +- [ ] **Vérification** : NPC patrouille et fuit + +### Étape 6 — Combat +- [ ] `CombatComponent` +- [ ] `BTTask_Attack` +- [ ] **Vérification** : NPC ennemi attaque le joueur + +### Étape 7 — EQS +- [ ] `EQSContext_Threat` +- [ ] `EQSTest_CoverQuality` +- [ ] Assets EQS dans Content/ +- [ ] **Vérification** : NPC trouve des couvertures intelligemment + +### Étape 8 — Intégration ConvAgent (optionnelle) +- [ ] `TryBindConversationAgent()` soft binding +- [ ] Test avec un NPC qui a les deux plugins + +--- + +## 8. Résumé des fichiers à créer + +| # | Fichier | Rôle | +|---|---------|------| +| 1 | `PS_AI_Behavior.uplugin` | Plugin descriptor | +| 2 | `PS_AI_Behavior.Build.cs` | Module dependencies | +| 3 | `PS_AI_Behavior.h / .cpp` | Module class (register settings) | +| 4 | `PS_AI_Behavior_Definitions.h` | Enums, structs, log | +| 5 | `PS_AI_Behavior_Settings.h / .cpp` | Project settings | +| 6 | `PS_AI_Behavior_PersonalityProfile.h / .cpp` | Data Asset | +| 7 | `PS_AI_Behavior_PersonalityComponent.h / .cpp` | Personality runtime | +| 8 | `PS_AI_Behavior_AIController.h / .cpp` | AIController | +| 9 | `PS_AI_Behavior_PerceptionComponent.h / .cpp` | AI Perception | +| 10 | `PS_AI_Behavior_CombatComponent.h / .cpp` | Combat state | +| 11 | `BT/PS_AI_Behavior_BTTask_Patrol.h / .cpp` | Patrol task | +| 12 | `BT/PS_AI_Behavior_BTTask_FleeFrom.h / .cpp` | Flee task | +| 13 | `BT/PS_AI_Behavior_BTTask_FindCover.h / .cpp` | Cover task | +| 14 | `BT/PS_AI_Behavior_BTTask_Attack.h / .cpp` | Attack task | +| 15 | `BT/PS_AI_Behavior_BTService_UpdateThreat.h / .cpp` | Threat service | +| 16 | `BT/PS_AI_Behavior_BTService_EvaluateReaction.h / .cpp` | Reaction service | +| 17 | `BT/PS_AI_Behavior_BTDecorator_CheckTrait.h / .cpp` | Trait decorator | +| 18 | `EQS/PS_AI_Behavior_EQSContext_Threat.h / .cpp` | EQS context | +| 19 | `EQS/PS_AI_Behavior_EQSTest_CoverQuality.h / .cpp` | EQS test | + +**Total : ~38 fichiers C++ (19 paires h/cpp) + 1 .uplugin + 1 .Build.cs** diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/PS_AI_Behavior.uplugin b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/PS_AI_Behavior.uplugin index 7c6942b..ec7690b 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/PS_AI_Behavior.uplugin +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/PS_AI_Behavior.uplugin @@ -30,10 +30,5 @@ ] } ], - "Plugins": [ - { - "Name": "NavigationSystem", - "Enabled": true - } - ] + "Plugins": [] } diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/BT/PS_AI_Behavior_BTTask_FindCover.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/BT/PS_AI_Behavior_BTTask_FindCover.cpp index 2cce071..87fe617 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/BT/PS_AI_Behavior_BTTask_FindCover.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/BT/PS_AI_Behavior_BTTask_FindCover.cpp @@ -28,7 +28,7 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_FindCover::ExecuteTask( UBlackboardComponent* BB = OwnerComp.GetBlackboardComponent(); if (!BB) return EBTNodeResult::Failed; - const UWorld* World = GetWorld(); + UWorld* World = GetWorld(); if (!World) return EBTNodeResult::Failed; const FVector NpcLoc = AIC->GetPawn()->GetActorLocation(); diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/BT/PS_AI_Behavior_BTTask_FollowSpline.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/BT/PS_AI_Behavior_BTTask_FollowSpline.cpp index 0d306a3..e2403aa 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/BT/PS_AI_Behavior_BTTask_FollowSpline.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/BT/PS_AI_Behavior_BTTask_FollowSpline.cpp @@ -42,18 +42,11 @@ EBTNodeResult::Type UPS_AI_Behavior_BTTask_FollowSpline::ExecuteTask( Follower->ResumeFollowing(); } - // Listen for end-of-spline + // Initialize memory — TickTask will poll bIsFollowing to detect end-of-spline FFollowMemory* Memory = reinterpret_cast(NodeMemory); Memory->Elapsed = 0.0f; Memory->bEndReached = false; - // Bind to end delegate - Follower->OnSplineEndReached.AddWeakLambda(this, - [Memory](APS_AI_Behavior_SplinePath* /*Spline*/) - { - Memory->bEndReached = true; - }); - return EBTNodeResult::InProgress; } @@ -62,11 +55,17 @@ void UPS_AI_Behavior_BTTask_FollowSpline::TickTask( { FFollowMemory* Memory = reinterpret_cast(NodeMemory); - // Check if spline end was reached - if (Memory->bEndReached) + // Check if spline end was reached (poll bIsFollowing — set to false by SplineFollowerComponent) + AAIController* AICCheck = OwnerComp.GetAIOwner(); + if (AICCheck && AICCheck->GetPawn()) { - FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); - return; + UPS_AI_Behavior_SplineFollowerComponent* FollowerCheck = + AICCheck->GetPawn()->FindComponentByClass(); + if (FollowerCheck && !FollowerCheck->bIsFollowing) + { + FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); + return; + } } // Time limit check @@ -91,20 +90,13 @@ void UPS_AI_Behavior_BTTask_FollowSpline::TickTask( } } - // Verify follower is still active + // Verify pawn is still valid AAIController* AIC = OwnerComp.GetAIOwner(); if (!AIC || !AIC->GetPawn()) { FinishLatentTask(OwnerComp, EBTNodeResult::Failed); return; } - - UPS_AI_Behavior_SplineFollowerComponent* Follower = - AIC->GetPawn()->FindComponentByClass(); - if (!Follower || !Follower->bIsFollowing) - { - FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded); - } } EBTNodeResult::Type UPS_AI_Behavior_BTTask_FollowSpline::AbortTask( diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/EQS/PS_AI_Behavior_EQSGenerator_CoverPoints.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/EQS/PS_AI_Behavior_EQSGenerator_CoverPoints.cpp index 7cc8142..09e1ecb 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/EQS/PS_AI_Behavior_EQSGenerator_CoverPoints.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/EQS/PS_AI_Behavior_EQSGenerator_CoverPoints.cpp @@ -34,7 +34,7 @@ void UPS_AI_Behavior_EQSGenerator_CoverPoints::GenerateItems(FEnvQueryInstance& { if (QuerierPawn->Implements()) { - NPCType = IPS_AI_Behavior::Execute_GetBehaviorNPCType(const_cast(QuerierPawn)); + NPCType = IPS_AI_Behavior_Interface::Execute_GetBehaviorNPCType(const_cast(QuerierPawn)); } else if (const auto* PC = QuerierPawn->FindComponentByClass()) { diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/EQS/PS_AI_Behavior_EQSTest_CoverQuality.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/EQS/PS_AI_Behavior_EQSTest_CoverQuality.cpp index b7aea3c..ca35b60 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/EQS/PS_AI_Behavior_EQSTest_CoverQuality.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/EQS/PS_AI_Behavior_EQSTest_CoverQuality.cpp @@ -71,8 +71,8 @@ void UPS_AI_Behavior_EQSTest_CoverQuality::RunTest(FEnvQueryInstance& QueryInsta } // Score: ratio of blocked traces (0.0 = fully exposed, 1.0 = fully covered) - const float Score = BlockedCount / TraceHeights.Num(); - It.SetScore(TestPurpose, FilterType, Score); + const float Score = BlockedCount / static_cast(TraceHeights.Num()); + It.SetScore(TestPurpose, FilterType, Score, 0.0f, 1.0f); } } diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_AIController.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_AIController.cpp index 54a7782..29cad55 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_AIController.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_AIController.cpp @@ -47,10 +47,10 @@ void APS_AI_Behavior_AIController::OnPossess(APawn* InPawn) if (InPawn->Implements()) { // Use the interface — the host project controls the storage - NPCType = IPS_AI_Behavior::Execute_GetBehaviorNPCType(InPawn); + NPCType = IPS_AI_Behavior_Interface::Execute_GetBehaviorNPCType(InPawn); // Also check if the interface provides a specific TeamId - const uint8 InterfaceTeamId = IPS_AI_Behavior::Execute_GetBehaviorTeamId(InPawn); + const uint8 InterfaceTeamId = IPS_AI_Behavior_Interface::Execute_GetBehaviorTeamId(InPawn); if (InterfaceTeamId != FGenericTeamId::NoTeam) { TeamId = InterfaceTeamId; @@ -73,7 +73,7 @@ void APS_AI_Behavior_AIController::OnPossess(APawn* InPawn) case EPS_AI_Behavior_NPCType::Enemy: // Check if infiltrated (hostile=false → disguised as civilian) if (InPawn->Implements() && - !IPS_AI_Behavior::Execute_IsBehaviorHostile(InPawn)) + !IPS_AI_Behavior_Interface::Execute_IsBehaviorHostile(InPawn)) { TeamId = 1; // Disguised as Civilian } @@ -187,7 +187,9 @@ void APS_AI_Behavior_AIController::SetupBlackboard() BlackboardAsset->Keys.Add(SplineProgressEntry); } - UseBlackboard(BlackboardAsset, Blackboard); + UBlackboardComponent* RawBBComp = nullptr; + UseBlackboard(BlackboardAsset, RawBBComp); + Blackboard = RawBBComp; // Initialize home location to pawn's spawn position if (Blackboard && GetPawn()) @@ -280,7 +282,7 @@ ETeamAttitude::Type APS_AI_Behavior_AIController::GetTeamAttitudeTowards(const A // Check via IPS_AI_Behavior interface else if (OtherPawn->Implements()) { - OtherTeam = IPS_AI_Behavior::Execute_GetBehaviorTeamId(const_cast(OtherPawn)); + OtherTeam = IPS_AI_Behavior_Interface::Execute_GetBehaviorTeamId(const_cast(OtherPawn)); } } diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_CoverPoint.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_CoverPoint.cpp index 6ed3c6f..8bd7b4a 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_CoverPoint.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_CoverPoint.cpp @@ -163,7 +163,7 @@ void APS_AI_Behavior_CoverPoint::UpdateVisualization() #if WITH_EDITORONLY_DATA if (!ArrowComp) return; - FLinearColor Color; + FLinearColor Color = FLinearColor::White; switch (PointType) { case EPS_AI_Behavior_CoverPointType::Cover: @@ -172,6 +172,8 @@ void APS_AI_Behavior_CoverPoint::UpdateVisualization() case EPS_AI_Behavior_CoverPointType::HidingSpot: Color = FLinearColor(1.0f, 0.85f, 0.0f); // Yellow break; + default: + break; } if (!bEnabled) diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_PerceptionComponent.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_PerceptionComponent.cpp index 818ef11..4d8952d 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_PerceptionComponent.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_PerceptionComponent.cpp @@ -87,7 +87,7 @@ EPS_AI_Behavior_TargetType UPS_AI_Behavior_PerceptionComponent::ClassifyActor(co if (Actor->Implements()) { const EPS_AI_Behavior_NPCType NPCType = - IPS_AI_Behavior::Execute_GetBehaviorNPCType(const_cast(Actor)); + IPS_AI_Behavior_Interface::Execute_GetBehaviorNPCType(const_cast(Actor)); switch (NPCType) { @@ -118,7 +118,7 @@ EPS_AI_Behavior_TargetType UPS_AI_Behavior_PerceptionComponent::ClassifyActor(co // ─── Target Selection ─────────────────────────────────────────────────────── -AActor* UPS_AI_Behavior_PerceptionComponent::GetHighestThreatActor() const +AActor* UPS_AI_Behavior_PerceptionComponent::GetHighestThreatActor() { // Get priority from PersonalityProfile if available TArray Priority; @@ -146,7 +146,7 @@ AActor* UPS_AI_Behavior_PerceptionComponent::GetHighestThreatActor() const } AActor* UPS_AI_Behavior_PerceptionComponent::GetHighestThreatActor( - const TArray& TargetPriority) const + const TArray& TargetPriority) { // Gather all perceived actors from all senses TArray PerceivedActors; @@ -241,7 +241,7 @@ AActor* UPS_AI_Behavior_PerceptionComponent::GetHighestThreatActor( return BestThreat; } -float UPS_AI_Behavior_PerceptionComponent::CalculateThreatLevel() const +float UPS_AI_Behavior_PerceptionComponent::CalculateThreatLevel() { const AActor* Owner = GetOwner(); if (!Owner) return 0.0f; @@ -252,7 +252,7 @@ float UPS_AI_Behavior_PerceptionComponent::CalculateThreatLevel() const TArray PerceivedActors; GetCurrentlyPerceivedActors(nullptr, PerceivedActors); // All senses - for (const AActor* Actor : PerceivedActors) + for (AActor* Actor : PerceivedActors) { if (!Actor) continue; @@ -293,7 +293,7 @@ float UPS_AI_Behavior_PerceptionComponent::CalculateThreatLevel() const return FMath::Min(TotalThreat, 2.0f); } -bool UPS_AI_Behavior_PerceptionComponent::GetThreatLocation(FVector& OutLocation) const +bool UPS_AI_Behavior_PerceptionComponent::GetThreatLocation(FVector& OutLocation) { AActor* Threat = GetHighestThreatActor(); if (Threat) diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_PersonalityComponent.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_PersonalityComponent.cpp index 37090ba..774bb29 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_PersonalityComponent.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_PersonalityComponent.cpp @@ -151,7 +151,7 @@ void UPS_AI_Behavior_PersonalityComponent::OnRep_CurrentState(EPS_AI_Behavior_St AActor* Owner = GetOwner(); if (Owner && Owner->Implements()) { - IPS_AI_Behavior::Execute_OnBehaviorStateChanged(Owner, CurrentState, OldState); + IPS_AI_Behavior_Interface::Execute_OnBehaviorStateChanged(Owner, CurrentState, OldState); } } @@ -168,10 +168,10 @@ void UPS_AI_Behavior_PersonalityComponent::HandleStateChanged( if (Owner->Implements()) { float NewSpeed = Profile ? Profile->GetSpeedForState(NewState) : 150.0f; - IPS_AI_Behavior::Execute_SetBehaviorMovementSpeed(Owner, NewSpeed); + IPS_AI_Behavior_Interface::Execute_SetBehaviorMovementSpeed(Owner, NewSpeed); // 3. Notify the Pawn of the state change - IPS_AI_Behavior::Execute_OnBehaviorStateChanged(Owner, NewState, OldState); + IPS_AI_Behavior_Interface::Execute_OnBehaviorStateChanged(Owner, NewState, OldState); } } @@ -181,7 +181,7 @@ EPS_AI_Behavior_NPCType UPS_AI_Behavior_PersonalityComponent::GetNPCType() const AActor* Owner = GetOwner(); if (Owner && Owner->Implements()) { - return IPS_AI_Behavior::Execute_GetBehaviorNPCType(Owner); + return IPS_AI_Behavior_Interface::Execute_GetBehaviorNPCType(Owner); } // Fallback: read from PersonalityProfile diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_SplineFollowerComponent.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_SplineFollowerComponent.cpp index aaa6cb9..440c4d3 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_SplineFollowerComponent.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_SplineFollowerComponent.cpp @@ -4,6 +4,7 @@ #include "PS_AI_Behavior_SplinePath.h" #include "PS_AI_Behavior_SplineNetwork.h" #include "PS_AI_Behavior_PersonalityComponent.h" +#include "Components/SplineComponent.h" #include "GameFramework/Character.h" #include "GameFramework/CharacterMovementComponent.h" #include "Net/UnrealNetwork.h" diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_SplineNetwork.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_SplineNetwork.cpp index beb9c60..9f710f3 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_SplineNetwork.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Private/PS_AI_Behavior_SplineNetwork.cpp @@ -11,22 +11,10 @@ void UPS_AI_Behavior_SplineNetwork::Initialize(FSubsystemCollectionBase& Collection) { Super::Initialize(Collection); - - UWorld* World = GetWorld(); - if (World) - { - BeginPlayHandle = World->OnWorldBeginPlay.AddUObject(this, &UPS_AI_Behavior_SplineNetwork::OnWorldBeginPlay); - } } void UPS_AI_Behavior_SplineNetwork::Deinitialize() { - UWorld* World = GetWorld(); - if (World && BeginPlayHandle.IsValid()) - { - World->OnWorldBeginPlay.Remove(BeginPlayHandle); - } - AllSplines.Empty(); TotalJunctions = 0; Super::Deinitialize(); @@ -34,6 +22,7 @@ void UPS_AI_Behavior_SplineNetwork::Deinitialize() void UPS_AI_Behavior_SplineNetwork::OnWorldBeginPlay(UWorld& InWorld) { + Super::OnWorldBeginPlay(InWorld); RebuildNetwork(); } diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/BT/PS_AI_Behavior_BTTask_FindCover.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/BT/PS_AI_Behavior_BTTask_FindCover.h index bcf9e45..f0e6064 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/BT/PS_AI_Behavior_BTTask_FindCover.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/BT/PS_AI_Behavior_BTTask_FindCover.h @@ -4,6 +4,7 @@ #include "CoreMinimal.h" #include "BehaviorTree/BTTaskNode.h" +#include "PS_AI_Behavior_Definitions.h" #include "PS_AI_Behavior_BTTask_FindCover.generated.h" class APS_AI_Behavior_CoverPoint; diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_CoverPoint.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_CoverPoint.h index c428f24..c24af98 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_CoverPoint.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_CoverPoint.h @@ -81,7 +81,7 @@ public: // ─── Runtime (server-only) ────────────────────────────────────────── /** Current occupants. Managed by the BT / EQS. */ - UPROPERTY(Transient, BlueprintReadOnly, Category = "Cover Point|Runtime") + UPROPERTY(Transient) TArray> CurrentOccupants; // ─── API ──────────────────────────────────────────────────────────── diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_Definitions.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_Definitions.h index 25ed348..ff50927 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_Definitions.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_Definitions.h @@ -7,7 +7,7 @@ // ─── Log Category ─────────────────────────────────────────────────────────── -DECLARE_LOG_CATEGORY_EXTERN(LogPS_AI_Behavior, Log, All); +PS_AI_BEHAVIOR_API DECLARE_LOG_CATEGORY_EXTERN(LogPS_AI_Behavior, Log, All); // ─── API Macro ────────────────────────────────────────────────────────────── diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_Interface.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_Interface.h index 85c482f..40a5a4f 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_Interface.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_Interface.h @@ -36,7 +36,7 @@ class PS_AI_BEHAVIOR_API UPS_AI_Behavior_Interface : public UInterface GENERATED_BODY() }; -class PS_AI_BEHAVIOR_API IPS_AI_Behavior +class PS_AI_BEHAVIOR_API IPS_AI_Behavior_Interface { GENERATED_BODY() diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_PerceptionComponent.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_PerceptionComponent.h index 191e9e3..6b6cf30 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_PerceptionComponent.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_PerceptionComponent.h @@ -33,17 +33,17 @@ public: * @return The most threatening actor, or nullptr if none perceived. */ UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Perception") - AActor* GetHighestThreatActor(const TArray& TargetPriority) const; + AActor* GetHighestThreatActor(const TArray& TargetPriority); /** Convenience overload — reads priority from the Pawn's PersonalityProfile. */ - AActor* GetHighestThreatActor() const; + AActor* GetHighestThreatActor(); /** * Compute an aggregate threat level from all currently perceived hostile stimuli. * Returns 0.0 (no threat) to 1.0+ (extreme danger). */ UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Perception") - float CalculateThreatLevel() const; + float CalculateThreatLevel(); /** * Get the location of the last known threat stimulus. @@ -51,7 +51,7 @@ public: * @return True if a threat was found. */ UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Perception") - bool GetThreatLocation(FVector& OutLocation) const; + bool GetThreatLocation(FVector& OutLocation); protected: virtual void BeginPlay() override; diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_SplineNetwork.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_SplineNetwork.h index 7c65520..9930383 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_SplineNetwork.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_Behavior/Public/PS_AI_Behavior_SplineNetwork.h @@ -103,8 +103,6 @@ private: void DetectJunctions(APS_AI_Behavior_SplinePath* SplineA, APS_AI_Behavior_SplinePath* SplineB, float Tolerance); - /** World init callback. */ - void OnWorldBeginPlay(UWorld& InWorld); - - FDelegateHandle BeginPlayHandle; + /** UWorldSubsystem override — called when world begins play. */ + virtual void OnWorldBeginPlay(UWorld& InWorld) override; }; diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_BehaviorEditor/Private/PS_AI_Behavior_SplineEdMode.cpp b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_BehaviorEditor/Private/PS_AI_Behavior_SplineEdMode.cpp index c685e1b..087b348 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_BehaviorEditor/Private/PS_AI_Behavior_SplineEdMode.cpp +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_BehaviorEditor/Private/PS_AI_Behavior_SplineEdMode.cpp @@ -54,9 +54,9 @@ void FPS_AI_Behavior_SplineEdMode::Exit() } bool FPS_AI_Behavior_SplineEdMode::HandleClick( - FEditorViewportClient* InViewportClient, HHitProxy* HitProxy, const FInputClick& Click) + FEditorViewportClient* InViewportClient, HHitProxy* HitProxy, const FViewportClick& Click) { - if (Click.Key != EKeys::LeftMouseButton) + if (Click.GetKey() != EKeys::LeftMouseButton) { return false; } @@ -76,9 +76,6 @@ bool FPS_AI_Behavior_SplineEdMode::HandleClick( InViewportClient->EngineShowFlags)); FSceneView* View = InViewportClient->CalcSceneView(&ViewFamily); - const FVector WorldOrigin = View->ViewMatrices.GetViewOrigin(); - FVector WorldDirection; - // Deproject mouse to world FVector2D MousePos(HitX, HitY); FVector RayOrigin, RayDirection; @@ -100,7 +97,7 @@ bool FPS_AI_Behavior_SplineEdMode::HandleClick( FVector ClickLocation = Hit.ImpactPoint; // Ctrl+Click on existing spline → select for extension - if (Click.bControlDown) + if (Click.IsControlDown()) { // Check if we hit a SplinePath AActor* HitActor = Hit.GetActor(); diff --git a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_BehaviorEditor/Public/PS_AI_Behavior_SplineEdMode.h b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_BehaviorEditor/Public/PS_AI_Behavior_SplineEdMode.h index 0910827..20e5c24 100644 --- a/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_BehaviorEditor/Public/PS_AI_Behavior_SplineEdMode.h +++ b/Unreal/PS_AI_Agent/Plugins/PS_AI_Behavior/Source/PS_AI_BehaviorEditor/Public/PS_AI_Behavior_SplineEdMode.h @@ -37,7 +37,7 @@ public: virtual void Exit() override; virtual bool HandleClick(FEditorViewportClient* InViewportClient, - HHitProxy* HitProxy, const FInputClick& Click) override; + HHitProxy* HitProxy, const FViewportClick& Click) override; virtual bool InputKey(FEditorViewportClient* ViewportClient, FViewport* Viewport, FKey Key, EInputEvent Event) override;