Reorganize Blueprint categories under ASTERION namespace, move bAutoStartBehavior to PersonalityComponent, add user documentation
- Bulk rename Category/ClassGroup strings to ASTERION|PS_AI_ConvAgent|... and ASTERION|PS_AI_Behavior|... (284 occurrences, 24 files) so functions/properties/components group cleanly in Blueprint menus - Move bAutoStartBehavior from AIController to PersonalityComponent so the same AIController class can drive multiple NPC archetypes with per-instance scripted-mode override - Add PowerPoint user documentation for both plugins in Docs/ with generator scripts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,7 +81,12 @@ void APS_AI_Behavior_AIController::OnPossess(APawn* InPawn)
|
||||
|
||||
SetupBlackboard();
|
||||
|
||||
if (bAutoStartBehavior)
|
||||
// Read auto-start from PersonalityComponent (defaults to true if no component)
|
||||
const bool bAutoStart = PersonalityComp
|
||||
? PersonalityComp->bAutoStartBehavior
|
||||
: true;
|
||||
|
||||
if (bAutoStart)
|
||||
{
|
||||
StartBehavior();
|
||||
}
|
||||
@@ -89,7 +94,7 @@ void APS_AI_Behavior_AIController::OnPossess(APawn* InPawn)
|
||||
{
|
||||
// Stay in Scripted state — no BT, no services, controlled externally
|
||||
SetBehaviorState(EPS_AI_Behavior_State::Scripted);
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] bAutoStartBehavior=false — entering Scripted state."),
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] bAutoStartBehavior=false (from Profile) — entering Scripted state."),
|
||||
*GetName());
|
||||
}
|
||||
|
||||
@@ -97,7 +102,7 @@ void APS_AI_Behavior_AIController::OnPossess(APawn* InPawn)
|
||||
TryBindGazeComponent();
|
||||
|
||||
UE_LOG(LogPS_AI_Behavior, Log, TEXT("[%s] Possessed Pawn '%s' — TeamId=%d, AutoStart=%d."),
|
||||
*GetName(), *InPawn->GetName(), TeamId, (int32)bAutoStartBehavior);
|
||||
*GetName(), *InPawn->GetName(), TeamId, (int32)bAutoStart);
|
||||
}
|
||||
|
||||
void APS_AI_Behavior_AIController::OnUnPossess()
|
||||
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
uint8 TeamId = FGenericTeamId::NoTeam;
|
||||
|
||||
/** Set the team ID at runtime. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Team")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Team")
|
||||
void SetTeamId(uint8 NewTeamId);
|
||||
|
||||
// ─── IGenericTeamAgentInterface (inherited from AAIController) ────
|
||||
@@ -59,10 +59,6 @@ public:
|
||||
|
||||
// ─── Configuration ──────────────────────────────────────────────────
|
||||
|
||||
/** If false, the Behavior Tree does NOT start on possess. Call StartBehavior() manually. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Behavior")
|
||||
bool bAutoStartBehavior = true;
|
||||
|
||||
/** Behavior Tree to run. If null, uses the Profile's DefaultBehaviorTree. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Behavior")
|
||||
TObjectPtr<UBehaviorTree> BehaviorTreeAsset;
|
||||
@@ -78,45 +74,45 @@ public:
|
||||
// ─── Gaze Configuration ────────────────────────────────────────────
|
||||
|
||||
/** Detection radius for proximity gaze (cm). NPC glances at nearby actors within this range. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI Behavior|Gaze", meta = (ClampMin = "100.0", ClampMax = "1500.0"))
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_Behavior|Gaze", meta = (ClampMin = "100.0", ClampMax = "1500.0"))
|
||||
float GazeProximityRadius = 400.0f;
|
||||
|
||||
/** Maximum duration (seconds) the NPC looks at a proximity target before releasing. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI Behavior|Gaze", meta = (ClampMin = "0.5", ClampMax = "30.0"))
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_Behavior|Gaze", meta = (ClampMin = "0.5", ClampMax = "30.0"))
|
||||
float GazeMaxDuration = 3.0f;
|
||||
|
||||
/** Cooldown (seconds) before re-targeting the same actor after releasing. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI Behavior|Gaze", meta = (ClampMin = "0.0", ClampMax = "30.0"))
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_Behavior|Gaze", meta = (ClampMin = "0.0", ClampMax = "30.0"))
|
||||
float GazeCooldown = 5.0f;
|
||||
|
||||
/** Enable/disable proximity gaze (NPC glances at nearby actors in Idle/Patrol). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI Behavior|Gaze")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_Behavior|Gaze")
|
||||
bool bEnableProximityGaze = true;
|
||||
|
||||
// ─── Component Access ───────────────────────────────────────────────
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
UPS_AI_Behavior_PerceptionComponent* GetBehaviorPerception() const { return BehaviorPerception; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
UPS_AI_Behavior_PersonalityComponent* GetPersonalityComponent() const { return PersonalityComp; }
|
||||
|
||||
// ─── Blackboard Helpers ─────────────────────────────────────────────
|
||||
|
||||
/** Write the current behavior state to the Blackboard. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Blackboard")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Blackboard")
|
||||
void SetBehaviorState(EPS_AI_Behavior_State NewState);
|
||||
|
||||
/** Read the current behavior state from the Blackboard. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Blackboard")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Blackboard")
|
||||
EPS_AI_Behavior_State GetBehaviorState() const;
|
||||
|
||||
/** Start (or restart) the Behavior Tree. If state is Scripted, transitions to Idle. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void StartBehavior();
|
||||
|
||||
/** Stop the Behavior Tree and enter Scripted state. NPC stays alive and perceptible. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void StopBehavior();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -17,7 +17,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnDamageReceived, float, Damage, A
|
||||
*
|
||||
* Attach to the NPC Pawn alongside PersonalityComponent.
|
||||
*/
|
||||
UCLASS(ClassGroup = "PS AI Behavior", meta = (BlueprintSpawnableComponent, DisplayName = "PS AI Behavior - Combat"))
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_Behavior", meta = (BlueprintSpawnableComponent, DisplayName = "PS AI Behavior - Combat"))
|
||||
class PS_AI_BEHAVIOR_API UPS_AI_Behavior_CombatComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
@@ -52,21 +52,21 @@ public:
|
||||
// ─── Delegates ──────────────────────────────────────────────────────
|
||||
|
||||
/** Fired on ALL machines (server + clients) when an attack is executed. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI Behavior|Combat")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_Behavior|Combat")
|
||||
FOnAttackExecuted OnAttackExecuted;
|
||||
|
||||
/** Fired on server when damage is received. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI Behavior|Combat")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_Behavior|Combat")
|
||||
FOnDamageReceived OnDamageReceived;
|
||||
|
||||
// ─── API ────────────────────────────────────────────────────────────
|
||||
|
||||
/** Whether the NPC can currently attack (cooldown elapsed). Server-only. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Combat")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Combat")
|
||||
bool CanAttack() const;
|
||||
|
||||
/** Whether the target is within attack range. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Combat")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Combat")
|
||||
bool IsInAttackRange(AActor* Target) const;
|
||||
|
||||
/**
|
||||
@@ -74,14 +74,14 @@ public:
|
||||
* cooldown, and multicasts cosmetic event to all clients.
|
||||
* @return True if the attack was executed.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Combat")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Combat")
|
||||
bool ExecuteAttack(AActor* Target);
|
||||
|
||||
/**
|
||||
* Called when this NPC takes damage. Updates threat perception.
|
||||
* Hook this into the owning Actor's OnTakeAnyDamage.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Combat")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Combat")
|
||||
void NotifyDamageReceived(float Damage, AActor* DamageInstigator);
|
||||
|
||||
// ─── Replication ────────────────────────────────────────────────────
|
||||
|
||||
@@ -88,23 +88,23 @@ public:
|
||||
// ─── API ────────────────────────────────────────────────────────────
|
||||
|
||||
/** Can this point be used by the given NPC type? */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Cover")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Cover")
|
||||
bool IsAccessibleTo(EPS_AI_Behavior_NPCType NPCType) const;
|
||||
|
||||
/** Is there room for one more occupant? */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Cover")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Cover")
|
||||
bool HasRoom() const;
|
||||
|
||||
/** Try to claim this point for an NPC. Returns true if successful. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Cover")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Cover")
|
||||
bool Claim(AActor* Occupant);
|
||||
|
||||
/** Release this point (NPC leaves cover). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Cover")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Cover")
|
||||
void Release(AActor* Occupant);
|
||||
|
||||
/** Get the facing direction (forward vector of the actor). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Cover")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Cover")
|
||||
FVector GetCoverDirection() const;
|
||||
|
||||
/**
|
||||
@@ -113,11 +113,11 @@ public:
|
||||
* @param ThreatLocation Where the threat is.
|
||||
* @return Combined score 0.0 to 1.0.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Cover")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Cover")
|
||||
float EvaluateAgainstThreat(const FVector& ThreatLocation) const;
|
||||
|
||||
/** Enable/disable at runtime (e.g. barricade destroyed). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Cover")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Cover")
|
||||
void SetEnabled(bool bNewEnabled);
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
||||
@@ -44,11 +44,11 @@ public:
|
||||
// ─── NPC Type ───────────────────────────────────────────────────────
|
||||
|
||||
/** Get this NPC's type (Civilian, Enemy, Protector). */
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
EPS_AI_Behavior_NPCType GetBehaviorNPCType() const;
|
||||
|
||||
/** Set this NPC's type. Called by gameplay logic or plugin actions. */
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void SetBehaviorNPCType(EPS_AI_Behavior_NPCType NewType);
|
||||
|
||||
// ─── Hostility ──────────────────────────────────────────────────────
|
||||
@@ -58,14 +58,14 @@ public:
|
||||
* An infiltrated Enemy with IsHostile=false appears as Civilian to the perception system.
|
||||
* When SetHostile(true) is called, the NPC reveals itself and TeamId changes.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
bool IsBehaviorHostile() const;
|
||||
|
||||
/**
|
||||
* Set hostility state. Typically called by gameplay scripts or ConvAgent actions.
|
||||
* Implementors should update their TeamId accordingly.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void SetBehaviorHostile(bool bNewHostile);
|
||||
|
||||
// ─── Movement ───────────────────────────────────────────────────────
|
||||
@@ -80,13 +80,13 @@ public:
|
||||
*
|
||||
* @param NewSpeed Desired walk speed in cm/s.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void SetBehaviorMovementSpeed(float NewSpeed);
|
||||
|
||||
/**
|
||||
* Get the Pawn's current movement speed (cm/s).
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
float GetBehaviorMovementSpeed() const;
|
||||
|
||||
/**
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
* @param NewState The new behavioral state.
|
||||
* @param OldState The previous behavioral state.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void OnBehaviorStateChanged(EPS_AI_Behavior_State NewState, EPS_AI_Behavior_State OldState);
|
||||
|
||||
// ─── Target Validation ──────────────────────────────────────────────
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
* @param TargetActor The actor to validate.
|
||||
* @return True if the actor can still be targeted.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
bool IsTargetActorValid(AActor* TargetActor) const;
|
||||
|
||||
// ─── Combat ─────────────────────────────────────────────────────────
|
||||
@@ -125,21 +125,21 @@ public:
|
||||
*
|
||||
* @param Target The actor to attack.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void BehaviorStartAttack(AActor* Target);
|
||||
|
||||
/**
|
||||
* Order the Pawn to stop attacking.
|
||||
* Called when the BT exits the Attack task (state changed, target lost, etc.).
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void BehaviorStopAttack();
|
||||
|
||||
/**
|
||||
* Query whether the Pawn can currently attack the target (has ammo, weapon ready, etc.).
|
||||
* If false, the BT will keep the NPC in combat stance but won't call BehaviorStartAttack.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
bool CanBehaviorAttack(AActor* Target) const;
|
||||
|
||||
// ─── Stance ─────────────────────────────────────────────────────────
|
||||
@@ -151,7 +151,7 @@ public:
|
||||
*
|
||||
* @param bCrouch True = crouch, False = stand up.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
void SetBehaviorCrouch(bool bCrouch);
|
||||
|
||||
// ─── Combat Style ───────────────────────────────────────────────────
|
||||
@@ -162,7 +162,7 @@ public:
|
||||
* Melee NPCs rush the target; Ranged NPCs use cover and maintain distance.
|
||||
* Default: Melee.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
EPS_AI_Behavior_CombatType GetBehaviorCombatType() const;
|
||||
|
||||
// ─── Actor Resolution ──────────────────────────────────────────────
|
||||
@@ -177,6 +177,6 @@ public:
|
||||
*
|
||||
* @return The actor to use as threat source / target.
|
||||
*/
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "PS AI Behavior")
|
||||
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "ASTERION|PS_AI_Behavior")
|
||||
AActor* GetBehaviorThreatActor() const;
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* Automatically added by PS_AI_Behavior_AIController — you don't need to add it manually.
|
||||
*/
|
||||
UCLASS(ClassGroup = "PS AI Behavior", meta = (DisplayName = "PS AI Behavior - Perception"))
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_Behavior", meta = (DisplayName = "PS AI Behavior - Perception"))
|
||||
class PS_AI_BEHAVIOR_API UPS_AI_Behavior_PerceptionComponent : public UAIPerceptionComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
* If empty, uses default [Protector, Player, Civilian].
|
||||
* @return The most threatening actor, or nullptr if none perceived.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Perception")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Perception")
|
||||
AActor* GetHighestThreatActor(const TArray<EPS_AI_Behavior_TargetType>& TargetPriority);
|
||||
|
||||
/** Convenience overload — reads priority from the Pawn's PersonalityProfile. */
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
* 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")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Perception")
|
||||
float CalculateThreatLevel();
|
||||
|
||||
/**
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
* @param OutLocation Filled with the threat location if any threat exists.
|
||||
* @return True if a threat was found.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Perception")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Perception")
|
||||
bool GetThreatLocation(FVector& OutLocation);
|
||||
|
||||
/**
|
||||
@@ -82,7 +82,7 @@ protected:
|
||||
* Uses IsPlayerControlled() for Player, IPS_AI_Behavior interface or
|
||||
* PersonalityComponent for NPC type.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Perception")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Perception")
|
||||
static EPS_AI_Behavior_TargetType ClassifyActor(const AActor* Actor);
|
||||
|
||||
private:
|
||||
|
||||
@@ -22,7 +22,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnBehaviorStateChanged, EPS_AI_Beh
|
||||
*
|
||||
* Attach to the NPC Pawn/Character.
|
||||
*/
|
||||
UCLASS(ClassGroup = "PS AI Behavior", meta = (BlueprintSpawnableComponent, DisplayName = "PS AI Behavior - Personality"))
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_Behavior", meta = (BlueprintSpawnableComponent, DisplayName = "PS AI Behavior - Personality"))
|
||||
class PS_AI_BEHAVIOR_API UPS_AI_Behavior_PersonalityComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
@@ -36,6 +36,14 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Personality")
|
||||
TObjectPtr<UPS_AI_Behavior_PersonalityProfile> Profile;
|
||||
|
||||
/**
|
||||
* If false, the Behavior Tree does NOT start on possess.
|
||||
* Use this for NPCs controlled externally (conversations, cinematics).
|
||||
* Call StartBehavior() on the AIController to activate manually.
|
||||
*/
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Personality")
|
||||
bool bAutoStartBehavior = true;
|
||||
|
||||
/**
|
||||
* Master debug toggle for this NPC.
|
||||
* When enabled, draws floating text above the NPC's head with:
|
||||
@@ -73,7 +81,7 @@ public:
|
||||
// ─── Delegates ──────────────────────────────────────────────────────
|
||||
|
||||
/** Fired when the behavioral state changes (on server AND clients via OnRep). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI Behavior|Personality")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
FOnBehaviorStateChanged OnBehaviorStateChanged;
|
||||
|
||||
// ─── API ────────────────────────────────────────────────────────────
|
||||
@@ -82,7 +90,7 @@ public:
|
||||
* Evaluate the NPC's reaction based on current traits and perceived threat.
|
||||
* Returns the recommended behavioral state. Server-only.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
EPS_AI_Behavior_State EvaluateReaction() const;
|
||||
|
||||
/**
|
||||
@@ -90,23 +98,23 @@ public:
|
||||
* Server-only: state is replicated to clients via OnRep.
|
||||
* @return The new behavioral state.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
EPS_AI_Behavior_State ApplyReaction();
|
||||
|
||||
/** Get a runtime trait value (returns 0.5 if undefined). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
float GetTrait(EPS_AI_Behavior_TraitAxis Axis) const;
|
||||
|
||||
/** Modify a runtime trait by delta, clamped to [0, 1]. Server-only. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
void ModifyTrait(EPS_AI_Behavior_TraitAxis Axis, float Delta);
|
||||
|
||||
/** Force a specific state (e.g. from conversation agent action). Server-only. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
void ForceState(EPS_AI_Behavior_State NewState);
|
||||
|
||||
/** Get the NPC type from the interface or profile. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
EPS_AI_Behavior_NPCType GetNPCType() const;
|
||||
|
||||
/**
|
||||
@@ -114,7 +122,7 @@ public:
|
||||
* Driven by the Combat/Cover cycle timer based on Aggressivity vs Caution.
|
||||
* Used by the IsCoverNeeded BT decorator.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
bool ShouldPreferCover() const { return bPreferCover; }
|
||||
|
||||
// ─── Replication ────────────────────────────────────────────────────
|
||||
|
||||
@@ -160,11 +160,11 @@ public:
|
||||
/**
|
||||
* Get the score for a given trait axis. Returns 0.5 if the axis is not defined.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
float GetTrait(EPS_AI_Behavior_TraitAxis Axis) const;
|
||||
|
||||
/** Get the speed for a given state. Returns DefaultWalkSpeed if state not in SpeedPerState. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Personality")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Personality")
|
||||
float GetSpeedForState(EPS_AI_Behavior_State State) const;
|
||||
|
||||
/** UPrimaryDataAsset interface */
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* Project-wide settings for the PS AI Behavior plugin.
|
||||
* Accessible via Project Settings -> Plugins -> PS AI Behavior.
|
||||
*/
|
||||
UCLASS(config = Game, defaultconfig, meta = (DisplayName = "PS AI Behavior"))
|
||||
UCLASS(config = Game, defaultconfig, meta = (DisplayName = "ASTERION|PS_AI_Behavior"))
|
||||
class PS_AI_BEHAVIOR_API UPS_AI_Behavior_Settings : public UDeveloperSettings
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
@@ -32,7 +32,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSplineEndReached,
|
||||
*
|
||||
* Attach to the NPC Pawn. Works with or without the AI Controller.
|
||||
*/
|
||||
UCLASS(ClassGroup = "PS AI Behavior", meta = (BlueprintSpawnableComponent, DisplayName = "PS AI Behavior - Spline Follower"))
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_Behavior", meta = (BlueprintSpawnableComponent, DisplayName = "PS AI Behavior - Spline Follower"))
|
||||
class PS_AI_BEHAVIOR_API UPS_AI_Behavior_SplineFollowerComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
@@ -109,15 +109,15 @@ public:
|
||||
// ─── Delegates ──────────────────────────────────────────────────────
|
||||
|
||||
/** Fired when approaching a junction. Use to make custom spline selection. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI Behavior|Spline Follower")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
FOnApproachingJunction OnApproachingJunction;
|
||||
|
||||
/** Fired when the NPC switches to a different spline. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI Behavior|Spline Follower")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
FOnSplineChanged OnSplineChanged;
|
||||
|
||||
/** Fired when the NPC reaches the end of a spline (if bReverseAtEnd is false). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI Behavior|Spline Follower")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
FOnSplineEndReached OnSplineEndReached;
|
||||
|
||||
// ─── API ────────────────────────────────────────────────────────────
|
||||
@@ -128,24 +128,24 @@ public:
|
||||
* @param bForward Direction of travel.
|
||||
* @return True if successfully started.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline Follower")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
bool StartFollowing(APS_AI_Behavior_SplinePath* Spline, bool bForward = true);
|
||||
|
||||
/**
|
||||
* Start following the given spline from a specific distance.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline Follower")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
bool StartFollowingAtDistance(APS_AI_Behavior_SplinePath* Spline, float StartDistance, bool bForward = true);
|
||||
|
||||
/** Stop following the current spline. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline Follower")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
void StopFollowing();
|
||||
|
||||
/** Pause/resume without losing state. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline Follower")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
void PauseFollowing();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline Follower")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
void ResumeFollowing();
|
||||
|
||||
/**
|
||||
@@ -154,15 +154,15 @@ public:
|
||||
* @param DistanceOnNew Distance along the new spline to start from.
|
||||
* @param bNewForward Direction on the new spline.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline Follower")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
void SwitchToSpline(APS_AI_Behavior_SplinePath* NewSpline, float DistanceOnNew, bool bNewForward = true);
|
||||
|
||||
/** Get the effective walk speed (considering spline override). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline Follower")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
float GetEffectiveSpeed() const;
|
||||
|
||||
/** Get progress as a 0-1 ratio. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline Follower")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline Follower")
|
||||
float GetProgress() const;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
* Called automatically after world initialization. Can be called again
|
||||
* if splines are added/removed at runtime.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|SplineNetwork")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|SplineNetwork")
|
||||
void RebuildNetwork();
|
||||
|
||||
// ─── Queries ────────────────────────────────────────────────────────
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
* @param OutDistance Distance along the spline to the closest point.
|
||||
* @return True if a spline was found within MaxDistance.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|SplineNetwork")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|SplineNetwork")
|
||||
bool FindClosestSpline(const FVector& WorldLocation,
|
||||
EPS_AI_Behavior_NPCType NPCType, float MaxDistance,
|
||||
APS_AI_Behavior_SplinePath*& OutSpline, float& OutDistance) const;
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
/**
|
||||
* Get all splines of a given category.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|SplineNetwork")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|SplineNetwork")
|
||||
TArray<APS_AI_Behavior_SplinePath*> GetSplinesForCategory(
|
||||
EPS_AI_Behavior_NPCType Category) const;
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
* @param CautionScore Optional: NPC's caution trait (0-1). Higher = prefer quieter paths.
|
||||
* @return The chosen spline (could be the same if staying is best).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|SplineNetwork")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|SplineNetwork")
|
||||
APS_AI_Behavior_SplinePath* ChooseSplineAtJunction(
|
||||
APS_AI_Behavior_SplinePath* CurrentSpline, int32 JunctionIndex,
|
||||
EPS_AI_Behavior_NPCType NPCType,
|
||||
@@ -81,11 +81,11 @@ public:
|
||||
float CautionScore = 0.5f) const;
|
||||
|
||||
/** Total number of splines in the network. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|SplineNetwork")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|SplineNetwork")
|
||||
int32 GetSplineCount() const { return AllSplines.Num(); }
|
||||
|
||||
/** Total number of junctions detected. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|SplineNetwork")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|SplineNetwork")
|
||||
int32 GetJunctionCount() const { return TotalJunctions; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
// ─── API ────────────────────────────────────────────────────────────
|
||||
|
||||
/** Can the given NPC type use this spline? */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline")
|
||||
bool IsAccessibleTo(EPS_AI_Behavior_NPCType NPCType) const;
|
||||
|
||||
/**
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
* @param OutWorldPoint World location of the closest point on the spline.
|
||||
* @return Distance from WorldLocation to the closest spline point.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline")
|
||||
float GetClosestPointOnSpline(const FVector& WorldLocation,
|
||||
float& OutDistance, FVector& OutWorldPoint) const;
|
||||
|
||||
@@ -115,24 +115,24 @@ public:
|
||||
* @param bForward Travel direction (true = increasing distance).
|
||||
* @return Array of upcoming junctions.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline")
|
||||
TArray<FPS_AI_Behavior_SplineJunction> GetUpcomingJunctions(
|
||||
float CurrentDistance, float LookAheadDist, bool bForward) const;
|
||||
|
||||
/** Total spline length. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline")
|
||||
float GetSplineLength() const;
|
||||
|
||||
/** Get world location at a distance along the spline. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline")
|
||||
FVector GetWorldLocationAtDistance(float Distance) const;
|
||||
|
||||
/** Get world rotation at a distance along the spline. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline")
|
||||
FRotator GetWorldRotationAtDistance(float Distance) const;
|
||||
|
||||
/** Get world-space tangent direction at a distance along the spline. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Spline")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Spline")
|
||||
FVector GetWorldDirectionAtDistance(float Distance) const;
|
||||
|
||||
#if WITH_EDITOR
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
* @param Loudness Noise loudness (default 1.0). Scales with HearingRange.
|
||||
* @param MaxRange Override max hearing range (0 = use sense default).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Perception",
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Perception",
|
||||
meta = (WorldContext = "WorldContext", DefaultToSelf = "Shooter"))
|
||||
static void ReportGunfire(UObject* WorldContext, FVector Location,
|
||||
AActor* Shooter, bool bIsEnemyFire = false,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* Enemy (Team 2) — Protectors and Civilians react
|
||||
* Protector (Team 3) — Allied with Civilians, hostile to Enemies
|
||||
*/
|
||||
UCLASS(ClassGroup = "PS AI Behavior", meta = (BlueprintSpawnableComponent,
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_Behavior", meta = (BlueprintSpawnableComponent,
|
||||
DisplayName = "PS AI Behavior Pawn Identity"))
|
||||
class PS_AI_BEHAVIOR_API UPS_AI_Behavior_TeamComponent : public UActorComponent
|
||||
{
|
||||
@@ -31,16 +31,16 @@ public:
|
||||
UPS_AI_Behavior_TeamComponent();
|
||||
|
||||
/** Role of this actor in the behavior system. Determines team affiliation. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI Behavior|Team")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_Behavior|Team")
|
||||
EPS_AI_Behavior_NPCType Role = EPS_AI_Behavior_NPCType::Civilian;
|
||||
|
||||
/** Faction within the same role. Same role + different faction = rivals. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI Behavior|Team",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_Behavior|Team",
|
||||
meta = (ClampMin = "0", ClampMax = "15"))
|
||||
uint8 Faction = 0;
|
||||
|
||||
/** Change role at runtime. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI Behavior|Team")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_Behavior|Team")
|
||||
void SetRole(EPS_AI_Behavior_NPCType NewRole) { Role = NewRole; }
|
||||
|
||||
/** Returns the TeamId derived from the current Role. */
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
* Obtain from https://elevenlabs.io – used to authenticate WebSocket connections.
|
||||
* Keep this secret; do not ship with the key hard-coded in a shipping build.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "PS AI ConvAgent|ElevenLabs API")
|
||||
UPROPERTY(Config, EditAnywhere, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs API")
|
||||
FString API_Key;
|
||||
|
||||
/**
|
||||
@@ -45,18 +45,18 @@ public:
|
||||
* - US: force US servers (api.us.elevenlabs.io).
|
||||
* - EU / India: Enterprise-only data residency endpoints.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "PS AI ConvAgent|ElevenLabs API")
|
||||
UPROPERTY(Config, EditAnywhere, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs API")
|
||||
EPS_AI_ConvAgent_ElevenLabsRegion ServerRegion = EPS_AI_ConvAgent_ElevenLabsRegion::Global;
|
||||
|
||||
/**
|
||||
* Override the ElevenLabs WebSocket URL entirely. Leave empty to use ServerRegion setting.
|
||||
* Example: wss://custom-proxy.example.com/v1/convai/conversation?agent_id=YOUR_ID
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "PS AI ConvAgent|ElevenLabs API")
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs API")
|
||||
FString CustomWebSocketURL;
|
||||
|
||||
/** Log verbose WebSocket messages to the Output Log (useful during development). */
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "PS AI ConvAgent|ElevenLabs API")
|
||||
UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs API")
|
||||
bool bVerboseLogging = false;
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
* Injected at conversation start via dynamic variables — changes take effect
|
||||
* on the next conversation without re-syncing agents.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, Category = "PS AI ConvAgent|Global Prompt",
|
||||
UPROPERTY(Config, EditAnywhere, Category = "ASTERION|PS_AI_ConvAgent|Global Prompt",
|
||||
meta = (MultiLine = "true",
|
||||
ToolTip = "Context prompt shared by all agents.\nDescribe the world, era, common rules.\nChanges take effect on next conversation start (no re-sync needed)."))
|
||||
FString GlobalContextPrompt;
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
* This allows per-instance override without modifying the Skeletal Mesh asset.
|
||||
* @param SkelMeshComp The target Skeletal Mesh Component.
|
||||
* @param AnimBPClass The AnimBlueprint class to use as post-process (nullptr to clear). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|Utilities",
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|Utilities",
|
||||
meta = (DisplayName = "Set Post Process Anim Blueprint"))
|
||||
static void SetPostProcessAnimBlueprint(USkeletalMeshComponent* SkelMeshComp,
|
||||
TSubclassOf<UAnimInstance> AnimBPClass);
|
||||
|
||||
@@ -55,7 +55,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnBodyExpressionChanged,
|
||||
// 4. The component listens to conversation lifecycle + emotion events.
|
||||
// 5. The AnimNode reads GetSnapshot() and blends the upper body pose.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
UCLASS(ClassGroup = "PS AI ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
DisplayName = "PS AI ConvAgent Body Expression")
|
||||
class PS_AI_CONVAGENT_API UPS_AI_ConvAgent_BodyExpressionComponent : public UActorComponent
|
||||
{
|
||||
@@ -68,28 +68,28 @@ public:
|
||||
|
||||
/** Body pose map asset containing body animation lists per emotion.
|
||||
* Create a dedicated PS_AI_ConvAgent_BodyPoseMap asset in the Content Browser. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|BodyExpression",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression",
|
||||
meta = (ToolTip = "Body Pose Map asset with animation lists per emotion.\nRight-click Content Browser > Miscellaneous > PS AI ConvAgent Body Pose Map."))
|
||||
TObjectPtr<UPS_AI_ConvAgent_BodyPoseMap> BodyPoseMap;
|
||||
|
||||
/** Whether body expressions are currently active (read-only).
|
||||
* Managed automatically: activates on conversation connect, deactivates on disconnect. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|BodyExpression")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression")
|
||||
bool bActive = false;
|
||||
|
||||
/** How long (seconds) to blend in/out when conversation starts/ends. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|BodyExpression",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression",
|
||||
meta = (ClampMin = "0.05", ClampMax = "3.0"))
|
||||
float ActivationBlendDuration = 0.5f;
|
||||
|
||||
/** Crossfade duration (seconds) when switching between animations. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|BodyExpression",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression",
|
||||
meta = (ClampMin = "0.1", ClampMax = "3.0",
|
||||
ToolTip = "How long (seconds) to crossfade between animations.\n0.5 = snappy, 1.5 = smooth."))
|
||||
float EmotionBlendDuration = 1.0f;
|
||||
|
||||
/** Overall blend weight for body expressions. 1.0 = full, 0.5 = subtle. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|BodyExpression",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression",
|
||||
meta = (ClampMin = "0.0", ClampMax = "1.0",
|
||||
ToolTip = "Overall blend weight for body expressions.\n1.0 = full, 0.5 = subtle."))
|
||||
float BlendWeight = 1.0f;
|
||||
@@ -97,12 +97,12 @@ public:
|
||||
// ── Debug ────────────────────────────────────────────────────────────────
|
||||
|
||||
/** Enable debug logging for this component. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug")
|
||||
bool bDebug = false;
|
||||
|
||||
/** Verbosity level when bDebug is true.
|
||||
* 0 = minimal extras, 1 = normal debug, 2 = detailed, 3 = per-frame data. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug",
|
||||
meta = (ClampMin = "0", ClampMax = "3", EditCondition = "bDebug"))
|
||||
int32 DebugVerbosity = 1;
|
||||
|
||||
@@ -117,22 +117,22 @@ public:
|
||||
}
|
||||
|
||||
/** Get the active emotion. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|BodyExpression")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression")
|
||||
EPS_AI_ConvAgent_Emotion GetActiveEmotion() const { return ActiveEmotion; }
|
||||
|
||||
/** Get the active emotion intensity. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|BodyExpression")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression")
|
||||
EPS_AI_ConvAgent_EmotionIntensity GetActiveIntensity() const { return ActiveEmotionIntensity; }
|
||||
|
||||
/** True when the agent is currently speaking (body uses N/M/E lists). */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|BodyExpression")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression")
|
||||
bool IsSpeaking() const { return bIsSpeaking; }
|
||||
|
||||
// ── Events ───────────────────────────────────────────────────────────────
|
||||
|
||||
/** Fired when the body expression changes (emotion + intensity).
|
||||
* Only fires when the emotion actually differs from the previous one. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|BodyExpression|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|BodyExpression|Events")
|
||||
FOnBodyExpressionChanged OnBodyExpressionChanged;
|
||||
|
||||
/** Current activation blend alpha (0 = fully inactive, 1 = fully active).
|
||||
|
||||
@@ -91,11 +91,11 @@ struct PS_AI_CONVAGENT_API FPS_AI_ConvAgent_ConversationInfo_ElevenLabs
|
||||
GENERATED_BODY()
|
||||
|
||||
/** Unique ID of this conversation session assigned by ElevenLabs. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
FString ConversationID;
|
||||
|
||||
/** Agent ID that is responding. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
FString AgentID;
|
||||
};
|
||||
|
||||
@@ -108,15 +108,15 @@ struct PS_AI_CONVAGENT_API FPS_AI_ConvAgent_TranscriptSegment_ElevenLabs
|
||||
GENERATED_BODY()
|
||||
|
||||
/** Transcribed text. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
FString Text;
|
||||
|
||||
/** "user" or "agent". */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
FString Speaker;
|
||||
|
||||
/** Whether this is a final transcript or a tentative (in-progress) one. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
bool bIsFinal = false;
|
||||
};
|
||||
|
||||
@@ -155,15 +155,15 @@ struct PS_AI_CONVAGENT_API FPS_AI_ConvAgent_ClientToolCall_ElevenLabs
|
||||
GENERATED_BODY()
|
||||
|
||||
/** Name of the tool the agent wants to invoke (e.g. "set_emotion"). */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
FString ToolName;
|
||||
|
||||
/** Unique ID for this tool invocation — must be echoed back in client_tool_result. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
FString ToolCallId;
|
||||
|
||||
/** Raw JSON parameters as key-value string pairs. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
TMap<FString, FString> Parameters;
|
||||
};
|
||||
|
||||
@@ -177,11 +177,11 @@ struct PS_AI_CONVAGENT_API FPS_AI_ConvAgent_AgentAction_ElevenLabs
|
||||
GENERATED_BODY()
|
||||
|
||||
/** Action identifier sent by the LLM (e.g. "flee", "draw_weapon"). Keep short, snake_case. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
FString Name;
|
||||
|
||||
/** Human-readable description — helps the LLM understand when to use this action. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
FString Description;
|
||||
};
|
||||
|
||||
@@ -210,23 +210,23 @@ struct PS_AI_CONVAGENT_API FPS_AI_ConvAgent_ToolParameter_ElevenLabs
|
||||
|
||||
/** Parameter identifier (snake_case). Must match the name expected by the client code.
|
||||
* Examples: "emotion", "intensity", "action", "target_name" */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "Parameter name (snake_case).\nThe key sent in the tool call JSON."))
|
||||
FString Name;
|
||||
|
||||
/** Data type for this parameter. Maps to JSON Schema "type". */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "Data type: String, Integer, Number, or Boolean."))
|
||||
EPS_AI_ConvAgent_ToolParamType Type = EPS_AI_ConvAgent_ToolParamType::String;
|
||||
|
||||
/** Whether this parameter is required in the tool call. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "If true, the LLM must provide this parameter."))
|
||||
bool bRequired = true;
|
||||
|
||||
/** Description passed to the LLM explaining what this parameter is
|
||||
* and how to extract or determine its value from the conversation. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (MultiLine = "true",
|
||||
ToolTip = "LLM prompt describing this parameter.\nGuides the LLM on what value to provide."))
|
||||
FString Description;
|
||||
@@ -234,7 +234,7 @@ struct PS_AI_CONVAGENT_API FPS_AI_ConvAgent_ToolParameter_ElevenLabs
|
||||
/** Optional predefined values the LLM can choose from.
|
||||
* If empty, the LLM can use any value of the specified type.
|
||||
* Examples: ["joy","sadness","anger"] for emotion, ["low","medium","high"] for intensity. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "Predefined enum values (optional).\nIf set, the LLM must choose from these."))
|
||||
TArray<FString> EnumValues;
|
||||
};
|
||||
|
||||
@@ -139,7 +139,7 @@ DECLARE_MULTICAST_DELEGATE_OneParam(FOnAgentAudioData, const TArray<uint8>& /*PC
|
||||
// 4. React to events (OnAgentTranscript, OnAgentTextResponse, etc.) in Blueprint.
|
||||
// 5. Call EndConversation() when done.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
UCLASS(ClassGroup = "PS AI ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
DisplayName = "PS AI ConvAgent - ElevenLabs Conv")
|
||||
class PS_AI_CONVAGENT_API UPS_AI_ConvAgent_ElevenLabsComponent : public UActorComponent
|
||||
{
|
||||
@@ -153,18 +153,18 @@ public:
|
||||
/** Agent configuration data asset.
|
||||
* When set, the AgentID is resolved from this asset at conversation start.
|
||||
* Create one via Content Browser → right-click → Miscellaneous → PS AI ConvAgent Agent Config. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "Agent configuration data asset.\nOverrides the AgentID string below when set."))
|
||||
TObjectPtr<UPS_AI_ConvAgent_AgentConfig_ElevenLabs> AgentConfig;
|
||||
|
||||
/** ElevenLabs Agent ID used for this conversation. Leave empty to use the default from Project Settings > PS AI ConvAgent - ElevenLabs.
|
||||
* Overridden by AgentConfig if set. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "ElevenLabs Agent ID. Leave empty to use the project default from Project Settings.\nOverridden by AgentConfig if set."))
|
||||
FString AgentID;
|
||||
|
||||
/** How turn-taking is managed between the user and the agent.\n- Server VAD (recommended): ElevenLabs automatically detects when the user stops speaking.\n- Client Controlled: You manually call StartListening/StopListening (push-to-talk with a key). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "Turn-taking mode.\n- Server VAD: ElevenLabs detects end-of-speech automatically (hands-free).\n- Client Controlled: You call StartListening/StopListening manually (push-to-talk)."))
|
||||
EPS_AI_ConvAgent_TurnMode_ElevenLabs TurnMode = EPS_AI_ConvAgent_TurnMode_ElevenLabs::Server;
|
||||
|
||||
@@ -174,38 +174,38 @@ public:
|
||||
* The agent remembers the full conversation context between interactions.
|
||||
* When false (ephemeral), each StartConversation opens a fresh WebSocket session
|
||||
* and EndConversation closes it. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "Keep the WebSocket open across conversation cycles.\n- True: agent remembers the full conversation between interactions.\n- False: each StartConversation opens a new session."))
|
||||
bool bPersistentSession = true;
|
||||
|
||||
/** Automatically open the microphone as soon as the WebSocket connection is established. Only applies in Server VAD mode. In Client (push-to-talk) mode, you must call StartListening manually. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "Auto-open the microphone when the conversation starts.\nOnly applies in Server VAD mode. In push-to-talk mode, call StartListening() manually."))
|
||||
bool bAutoStartListening = true;
|
||||
|
||||
/** How many milliseconds of microphone audio to accumulate before sending a chunk to ElevenLabs. Lower values reduce latency but may degrade voice detection accuracy. Higher values are more reliable but add delay. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs|Latency",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Latency",
|
||||
meta = (ClampMin = "20", ClampMax = "500",
|
||||
ToolTip = "Mic audio chunk duration sent to ElevenLabs.\n- 50-80ms: lower latency, less reliable voice detection.\n- 100ms (default): good balance.\n- 150-250ms: more reliable, higher latency."))
|
||||
int32 MicChunkDurationMs = 100;
|
||||
|
||||
/** Allow the user to interrupt the agent while it is speaking.\n- In Server VAD mode: the microphone stays open during agent speech and the server detects interruptions automatically.\n- In Client (push-to-talk) mode: pressing the talk key while the agent speaks sends an interrupt signal.\n- When disabled: the user must wait for the agent to finish speaking before talking. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ToolTip = "Allow the user to interrupt the agent while it speaks.\n- Server VAD: mic stays open, server detects user voice automatically.\n- Push-to-talk: pressing the talk key interrupts the agent.\n- Disabled: user must wait for the agent to finish."))
|
||||
bool bAllowInterruption = true;
|
||||
|
||||
/** Enable the OnAgentTranscript event, which provides real-time speech-to-text of what the user is saying. Disable if you don't need to display user speech to reduce processing overhead. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fire OnAgentTranscript with real-time speech-to-text of user speech.\nDisable if you don't need to display what the user said."))
|
||||
bool bEnableUserTranscript = true;
|
||||
|
||||
/** Enable the OnAgentTextResponse event, which provides the agent's complete text response once fully generated. Disable if you only need the audio output. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fire OnAgentTextResponse with the agent's complete text once fully generated.\nDisable if you only need the audio output."))
|
||||
bool bEnableAgentTextResponse = true;
|
||||
|
||||
/** Enable the OnAgentPartialResponse event, which streams the agent's text word-by-word as the LLM generates it. Use this for real-time subtitles that appear while the agent speaks, rather than waiting for the full response. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fire OnAgentPartialResponse with streaming text fragments as the LLM generates them.\nIdeal for real-time subtitles. Each event gives one text chunk, not the accumulated text."))
|
||||
bool bEnableAgentPartialResponse = false;
|
||||
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
* When adaptive mode is on, the system starts here and can only decrease
|
||||
* (never increase) as it measures that chunks arrive fast enough.
|
||||
* Set to 0 to disable pre-buffering entirely. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs|Latency",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Latency",
|
||||
meta = (ClampMin = "0", ClampMax = "4000",
|
||||
ToolTip = "Pre-buffer delay (ms) — your safe 'worst case' value.\nAdaptive mode can only decrease from here, never increase.\nSet 0 to disable pre-buffering entirely."))
|
||||
int32 AudioPreBufferMs = 300;
|
||||
@@ -223,13 +223,13 @@ public:
|
||||
* lowers the pre-buffer when TTS chunks arrive fast enough.
|
||||
* The system can only decrease from AudioPreBufferMs — never increase.
|
||||
* Resets to AudioPreBufferMs at the start of each conversation. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs|Latency",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Latency",
|
||||
meta = (EditCondition = "AudioPreBufferMs > 0",
|
||||
ToolTip = "Automatically lower pre-buffer when connection is good.\nCan only decrease, never increase beyond AudioPreBufferMs.\nResets each conversation."))
|
||||
bool bAdaptivePreBuffer = true;
|
||||
|
||||
/** Safety timeout: if the server does not start generating a response within this many seconds after the user stops speaking, fire OnAgentResponseTimeout. Set to 0 to disable. A normal response starts within 0.1-0.8s. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ClampMin = "0.0",
|
||||
ToolTip = "Seconds to wait for a server response after the user stops speaking.\nFires OnAgentResponseTimeout if exceeded. Normal latency is 0.1-0.8s.\nSet to 0 to disable. Default: 10s."))
|
||||
float ResponseTimeoutSeconds = 10.0f;
|
||||
@@ -237,7 +237,7 @@ public:
|
||||
/** Maximum auto-reconnection attempts on unexpected WebSocket disconnect.
|
||||
* Uses exponential backoff (1s, 2s, 4s, ... up to 30s).
|
||||
* Set to 0 to disable auto-reconnection. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs",
|
||||
meta = (ClampMin = "0",
|
||||
ToolTip = "Auto-reconnect attempts on unexpected disconnect.\n0 = disabled. Uses exponential backoff."))
|
||||
int32 MaxReconnectAttempts = 5;
|
||||
@@ -248,7 +248,7 @@ public:
|
||||
* When set, the agent's audio playback will be spatialized in 3D — volume
|
||||
* and panning change based on distance and direction from the listener.
|
||||
* Leave null for non-spatialized (2D) audio (default, same as before). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|ElevenLabs|Audio",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Audio",
|
||||
meta = (ToolTip = "Sound attenuation for 3D spatialized audio.\nLeave null for non-spatialized (2D) playback."))
|
||||
USoundAttenuation* SoundAttenuation = nullptr;
|
||||
|
||||
@@ -256,104 +256,104 @@ public:
|
||||
|
||||
/** Enable debug logging for this component.
|
||||
* When false, only key events (init, errors, state changes) are logged. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug")
|
||||
bool bDebug = false;
|
||||
|
||||
/** Verbosity level when bDebug is true.
|
||||
* 0 = minimal extras, 1 = normal debug, 2 = detailed, 3 = per-frame data. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug",
|
||||
meta = (ClampMin = "0", ClampMax = "3", EditCondition = "bDebug"))
|
||||
int32 DebugVerbosity = 1;
|
||||
|
||||
/** Show a separate latency debug HUD with detailed per-turn timing breakdown.
|
||||
* Independent from bDebug — can be enabled alone via CVar ps.ai.ConvAgent.Debug.Latency. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug")
|
||||
bool bDebugLatency = false;
|
||||
|
||||
// ── Events ────────────────────────────────────────────────────────────────
|
||||
|
||||
/** Fired when the WebSocket connection is established and the conversation session is ready. Provides the ConversationID and AgentID. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the connection to ElevenLabs is established and the conversation is ready to begin."))
|
||||
FOnAgentConnected OnAgentConnected;
|
||||
|
||||
/** Fired when the WebSocket connection is closed (gracefully or due to an error). Provides the status code and reason. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the connection to ElevenLabs is closed. Check StatusCode and Reason for details."))
|
||||
FOnAgentDisconnected OnAgentDisconnected;
|
||||
|
||||
/** Fired on any connection or protocol error. The error message describes what went wrong. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires on connection or protocol errors. The ErrorMessage describes the issue."))
|
||||
FOnAgentError OnAgentError;
|
||||
|
||||
/** Fired with real-time speech-to-text of the user's voice. Includes both tentative (in-progress) and final transcripts. Requires bEnableUserTranscript to be true. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Real-time speech-to-text of the user's voice.\nIncludes tentative and final transcripts. Enable with bEnableUserTranscript."))
|
||||
FOnAgentTranscript OnAgentTranscript;
|
||||
|
||||
/** Fired once when the agent's complete text response is available. This is the full text that corresponds to the audio the agent speaks. Requires bEnableAgentTextResponse to be true. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "The agent's complete text response (matches the spoken audio).\nFires once when the full text is ready. Enable with bEnableAgentTextResponse."))
|
||||
FOnAgentTextResponse OnAgentTextResponse;
|
||||
|
||||
/** Fired repeatedly as the LLM generates text, providing one word/fragment at a time. Use for real-time subtitles. Each call gives a new fragment, NOT the accumulated text. Requires bEnableAgentPartialResponse to be true. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Streaming text fragments as the LLM generates them (word by word).\nIdeal for real-time subtitles. Enable with bEnableAgentPartialResponse."))
|
||||
FOnAgentPartialResponse OnAgentPartialResponse;
|
||||
|
||||
/** Fired when the agent begins playing audio (first audio chunk received). Use this to trigger speech animations or UI indicators. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the agent starts speaking (first audio chunk). Use for lip-sync or UI feedback."))
|
||||
FOnAgentStartedSpeaking OnAgentStartedSpeaking;
|
||||
|
||||
/** Fired when audio playback actually starts — AFTER any pre-buffering delay.
|
||||
* Unlike OnAgentStartedSpeaking (first chunk arrival), this fires when audio is audible.
|
||||
* Use this for body/gesture animations that should be synced with audible speech. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when audio playback actually starts (after pre-buffering).\nSynced with audible speech. Use for body animations."))
|
||||
FOnAudioPlaybackStarted OnAudioPlaybackStarted;
|
||||
|
||||
/** Fired when the agent finishes playing all audio. Use this to re-open the microphone (in Server VAD mode without interruption) or update UI. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the agent finishes speaking. Use to re-open the mic or update UI."))
|
||||
FOnAgentStoppedSpeaking OnAgentStoppedSpeaking;
|
||||
|
||||
/** Fired when the agent's speech is interrupted (either by the user speaking over it, or by a manual InterruptAgent call). The audio playback is automatically stopped. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the agent is interrupted mid-speech. Audio is automatically stopped."))
|
||||
FOnAgentInterrupted OnAgentInterrupted;
|
||||
|
||||
/** Fired when the server starts generating a response (before any audio arrives). Use this for "thinking..." UI feedback. In push-to-talk mode, the microphone is automatically closed when this fires. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the server starts generating (before audio arrives).\nUse for 'thinking...' UI. Mic is auto-closed in push-to-talk mode."))
|
||||
FOnAgentStartedGenerating OnAgentStartedGenerating;
|
||||
|
||||
/** Fired if the server does not start generating a response within ResponseTimeoutSeconds after the user stops speaking. Use this to show a "try again" message or automatically re-open the microphone. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires if the server doesn't respond within ResponseTimeoutSeconds.\nUse to show 'try again' or re-open the mic automatically."))
|
||||
FOnAgentResponseTimeout OnAgentResponseTimeout;
|
||||
|
||||
/** Fired when the agent changes emotion via the "set_emotion" client tool. The emotion is set BEFORE the corresponding audio arrives, giving you time to smoothly blend facial expressions. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the agent sets an emotion (joy, sadness, surprise, fear, anger, disgust).\nDriven by the 'set_emotion' client tool. Arrives before the audio."))
|
||||
FOnAgentEmotionChanged OnAgentEmotionChanged;
|
||||
|
||||
/** Fired when the LLM triggers a perform_action tool call.
|
||||
* ActionName is the identifier from the ActionSet (e.g. "flee", "draw_weapon").
|
||||
* Handle this in Blueprint to play animations, trigger AI behavior, etc. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the agent triggers a physical action.\nActionName matches the Name field from the ActionSet Data Asset."))
|
||||
FOnAgentActionRequested OnAgentActionRequested;
|
||||
|
||||
/** Fired for client tool calls that are NOT automatically handled (i.e. not "set_emotion", not "perform_action"). You must call GetWebSocketProxy()->SendClientToolResult() to respond. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires for custom client tool calls (not set_emotion, not perform_action).\nYou must respond via GetWebSocketProxy()->SendClientToolResult()."))
|
||||
FOnAgentClientToolCall OnAgentClientToolCall;
|
||||
|
||||
/** Fired when the active speaker changes in a multi-player shared conversation.
|
||||
* NewSpeaker is null when no one is speaking (idle timeout). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when the speaking player changes.\nNewSpeaker is null when no one is speaking."))
|
||||
FOnActiveSpeakerChanged OnActiveSpeakerChanged;
|
||||
|
||||
@@ -361,26 +361,26 @@ public:
|
||||
* components back to neutral. The NPC is fully idle and the game can start
|
||||
* the physical action (flee, draw weapon, etc.).
|
||||
* Call ForceEnableConversation() later to allow conversation again. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when all animation components have returned to neutral after ForceDisableConversation().\nThe agent is ready for a game action."))
|
||||
FOnReadyForAction OnReadyForAction;
|
||||
|
||||
/** Fired when this agent starts passively tracking a nearby player (head/eyes gaze). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when this agent starts passively tracking a nearby player.\nTriggered by proximity awareness — the agent is not selected for conversation."))
|
||||
FOnAgentPassiveGazeStarted OnPassiveGazeStarted;
|
||||
|
||||
/** Fired when this agent stops passively tracking a player (left range or selected). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events",
|
||||
meta = (ToolTip = "Fires when this agent stops passively tracking a player.\nThe player left range or selected this agent for active conversation."))
|
||||
FOnAgentPassiveGazeStopped OnPassiveGazeStopped;
|
||||
|
||||
/** The current emotion of the agent, as set by the "set_emotion" client tool. Defaults to Neutral. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_Emotion, BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(ReplicatedUsing = OnRep_Emotion, BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
EPS_AI_ConvAgent_Emotion CurrentEmotion = EPS_AI_ConvAgent_Emotion::Neutral;
|
||||
|
||||
/** The current emotion intensity. Defaults to Medium. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_Emotion, BlueprintReadOnly, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UPROPERTY(ReplicatedUsing = OnRep_Emotion, BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
EPS_AI_ConvAgent_EmotionIntensity CurrentEmotionIntensity = EPS_AI_ConvAgent_EmotionIntensity::Medium;
|
||||
|
||||
// ── Raw audio data (C++ only, used by LipSync component) ────────────────
|
||||
@@ -392,26 +392,26 @@ public:
|
||||
|
||||
/** True when one or more players are in conversation with this NPC.
|
||||
* Replicated to all clients for UI feedback, gaze, LOD, etc. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ConversationState, BlueprintReadOnly, Category = "PS AI ConvAgent|Network")
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ConversationState, BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|Network")
|
||||
bool bNetIsConversing = false;
|
||||
|
||||
/** All player pawns currently in conversation with this NPC.
|
||||
* Multiple players can share the same agent — audio is routed via speaker arbitration.
|
||||
* Replicated to ALL clients for gaze target and LOD distance checks. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ConversationState, BlueprintReadOnly, Category = "PS AI ConvAgent|Network")
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ConversationState, BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|Network")
|
||||
TArray<TObjectPtr<APawn>> NetConnectedPawns;
|
||||
|
||||
/** The player currently speaking (active audio sender). Null if no one is speaking.
|
||||
* Used by GazeComponent for target switching — the NPC looks at whoever is talking.
|
||||
* Replicated to ALL clients so gaze updates everywhere. */
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ActiveSpeaker, BlueprintReadOnly, Category = "PS AI ConvAgent|Network")
|
||||
UPROPERTY(ReplicatedUsing = OnRep_ActiveSpeaker, BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|Network")
|
||||
TObjectPtr<APawn> NetActiveSpeakerPawn = nullptr;
|
||||
|
||||
// ── Multi-player speaker arbitration (server only) ──────────────────────
|
||||
|
||||
/** Minimum seconds of silence from the current speaker before allowing a speaker switch.
|
||||
* Prevents rapid ping-pong switching when both players make brief sounds. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Network|MultiPlayer",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Network|MultiPlayer",
|
||||
meta = (ClampMin = "0.0", ClampMax = "5.0",
|
||||
ToolTip = "Minimum silence from current speaker before switching to another.\nPrevents rapid gaze flip-flop."))
|
||||
float SpeakerSwitchHysteresis = 0.3f;
|
||||
@@ -419,7 +419,7 @@ public:
|
||||
/** Seconds after last speech before the active speaker is cleared.
|
||||
* When cleared, gaze returns to the last speaker position (or closest connected player).
|
||||
* Set to 0 to never clear (last speaker stays active indefinitely). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Network|MultiPlayer",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Network|MultiPlayer",
|
||||
meta = (ClampMin = "0.0",
|
||||
ToolTip = "Seconds of silence before clearing the active speaker.\n0 = last speaker stays active indefinitely."))
|
||||
float SpeakerIdleTimeout = 3.0f;
|
||||
@@ -428,14 +428,14 @@ public:
|
||||
|
||||
/** Distance (cm) beyond which remote clients stop receiving agent audio entirely.
|
||||
* The speaking player always receives full audio regardless of distance. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Network|LOD",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Network|LOD",
|
||||
meta = (ClampMin = "0", ToolTip = "Distance beyond which audio is culled for non-speaking players. 0 = no cull."))
|
||||
float AudioLODCullDistance = 3000.f;
|
||||
|
||||
/** Distance (cm) beyond which remote clients skip lip-sync / emotion processing.
|
||||
* Audio still plays (if within AudioLODCullDistance) but without facial animation.
|
||||
* The speaking player always gets full lip-sync regardless of distance. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Network|LOD",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Network|LOD",
|
||||
meta = (ClampMin = "0", ToolTip = "Distance beyond which lip-sync is skipped for non-speaking players. 0 = no LOD."))
|
||||
float LipSyncLODDistance = 1500.f;
|
||||
|
||||
@@ -514,25 +514,25 @@ public:
|
||||
* Open the WebSocket connection and start the conversation.
|
||||
* If bAutoStartListening is true, microphone capture also starts once connected.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void StartConversation();
|
||||
|
||||
/** Close the WebSocket and stop all audio. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void EndConversation();
|
||||
|
||||
/**
|
||||
* Start capturing microphone audio and streaming it to ElevenLabs.
|
||||
* In Client turn mode, also sends a UserTurnStart signal.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void StartListening();
|
||||
|
||||
/**
|
||||
* Stop capturing microphone audio.
|
||||
* In Client turn mode, also sends a UserTurnEnd signal.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void StopListening();
|
||||
|
||||
/**
|
||||
@@ -540,11 +540,11 @@ public:
|
||||
* The agent will respond with audio and text just as if it heard you speak.
|
||||
* Useful for testing in the Editor or for text-based interaction.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void SendTextMessage(const FString& Text);
|
||||
|
||||
/** Interrupt the agent's current utterance. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void InterruptAgent();
|
||||
|
||||
/**
|
||||
@@ -565,7 +565,7 @@ public:
|
||||
*
|
||||
* @param ActionName The action to perform once neutral (passed through to OnReadyForAction).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void ForceDisableConversation(const FString& ActionName);
|
||||
|
||||
/**
|
||||
@@ -573,7 +573,7 @@ public:
|
||||
* Clears the disabled flag so the InteractionComponent can auto-start
|
||||
* a new conversation on the next tick (if the player is still looking).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void ForceEnableConversation();
|
||||
|
||||
/**
|
||||
@@ -583,7 +583,7 @@ public:
|
||||
* The component must be connected and listening (StartListening called) for audio to be sent.
|
||||
* @param FloatPCM Float32 samples, 16000 Hz mono (same format as MicrophoneCaptureComponent output).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void FeedExternalAudio(const TArray<float>& FloatPCM);
|
||||
|
||||
/** Receive mic audio from a specific player with speaker arbitration.
|
||||
@@ -592,13 +592,13 @@ public:
|
||||
|
||||
// ── State queries ─────────────────────────────────────────────────────────
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
bool IsConnected() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
bool IsListening() const { return bIsListening; }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
bool IsAgentSpeaking() const { return bAgentSpeaking; }
|
||||
|
||||
/** True when the agent is speaking OR the server hasn't confirmed the full response yet.
|
||||
@@ -606,21 +606,21 @@ public:
|
||||
* produce more audio (e.g. during TTS inter-batch gaps). */
|
||||
bool IsAgentSpeakingOrPending() const { return bAgentSpeaking || (bAgentGenerating && !bAgentResponseReceived); }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
const FPS_AI_ConvAgent_ConversationInfo_ElevenLabs& GetConversationInfo() const;
|
||||
|
||||
/** True while conversation is force-disabled (ForceDisableConversation was called).
|
||||
* While disabled, StartConversation and ServerJoinConversation are blocked. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
bool IsConversationDisabled() const { return bConversationDisabledByAction; }
|
||||
|
||||
/** True while audio is being pre-buffered (playback hasn't started yet).
|
||||
* Used by the LipSync component to pause viseme queue consumption. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
bool IsPreBuffering() const { return bPreBuffering; }
|
||||
|
||||
/** Access the underlying WebSocket proxy (advanced use). */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
UPS_AI_ConvAgent_WebSocket_ElevenLabsProxy* GetWebSocketProxy() const { return WebSocketProxy; }
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -35,7 +35,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnExpressionChanged,
|
||||
// 4. Emotion animations crossfade smoothly (configurable duration).
|
||||
// 5. The AnimNode reads GetCurrentEmotionCurves() and injects them into the pose.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
UCLASS(ClassGroup = "PS AI ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
DisplayName = "PS AI ConvAgent Facial Expression")
|
||||
class PS_AI_CONVAGENT_API UPS_AI_ConvAgent_FacialExpressionComponent : public UActorComponent
|
||||
{
|
||||
@@ -48,23 +48,23 @@ public:
|
||||
|
||||
/** Emotion pose map asset containing emotion AnimSequences (Normal / Medium / Extreme per emotion).
|
||||
* Create a dedicated PS_AI_ConvAgent_EmotionPoseMap asset in the Content Browser. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|FacialExpression",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression",
|
||||
meta = (ToolTip = "Dedicated Emotion Pose Map asset.\nRight-click Content Browser → Miscellaneous → PS AI ConvAgent Emotion Pose Map."))
|
||||
TObjectPtr<UPS_AI_ConvAgent_EmotionPoseMap> EmotionPoseMap;
|
||||
|
||||
/** Whether facial expressions are currently active (read-only).
|
||||
* Managed automatically: activates on conversation connect, deactivates on disconnect.
|
||||
* The underlying emotion playback keeps running so reactivation is seamless. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|FacialExpression")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression")
|
||||
bool bActive = true;
|
||||
|
||||
/** How long (seconds) to blend in/out when bActive changes. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|FacialExpression",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression",
|
||||
meta = (ClampMin = "0.05", ClampMax = "3.0"))
|
||||
float ActivationBlendDuration = 0.5f;
|
||||
|
||||
/** Emotion crossfade duration in seconds. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|FacialExpression",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression",
|
||||
meta = (ClampMin = "0.1", ClampMax = "3.0",
|
||||
ToolTip = "How long (seconds) to crossfade between emotions.\n0.5 = snappy, 1.5 = smooth."))
|
||||
float EmotionBlendDuration = 0.5f;
|
||||
@@ -73,12 +73,12 @@ public:
|
||||
|
||||
/** Enable debug logging for this component.
|
||||
* When false, only key events (init, errors, state changes) are logged. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug")
|
||||
bool bDebug = false;
|
||||
|
||||
/** Verbosity level when bDebug is true.
|
||||
* 0 = minimal extras, 1 = normal debug, 2 = detailed, 3 = per-frame data. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug",
|
||||
meta = (ClampMin = "0", ClampMax = "3", EditCondition = "bDebug"))
|
||||
int32 DebugVerbosity = 1;
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
|
||||
/** Get the current emotion curves evaluated from the playing AnimSequence.
|
||||
* Returns a COPY — safe to call from any thread (AnimNode worker thread). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|FacialExpression")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression")
|
||||
TMap<FName, float> GetCurrentEmotionCurves() const
|
||||
{
|
||||
FScopeLock Lock(&EmotionCurveLock);
|
||||
@@ -94,15 +94,15 @@ public:
|
||||
}
|
||||
|
||||
/** Get the active emotion. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|FacialExpression")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression")
|
||||
EPS_AI_ConvAgent_Emotion GetActiveEmotion() const { return ActiveEmotion; }
|
||||
|
||||
/** Get the active emotion intensity. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|FacialExpression")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression")
|
||||
EPS_AI_ConvAgent_EmotionIntensity GetActiveIntensity() const { return ActiveEmotionIntensity; }
|
||||
|
||||
/** Check if a curve name belongs to the mouth area (overridden by lip sync). */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|FacialExpression")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression")
|
||||
static bool IsMouthCurve(const FName& CurveName);
|
||||
|
||||
// ── Events ───────────────────────────────────────────────────────────────
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
* Subscribe in Blueprints to react to expression changes (trigger animations,
|
||||
* particles, sounds, etc.). Only fires when the emotion actually differs
|
||||
* from the previous one. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|FacialExpression|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|FacialExpression|Events")
|
||||
FOnExpressionChanged OnExpressionChanged;
|
||||
|
||||
/** Current activation blend alpha (0 = fully inactive, 1 = fully active).
|
||||
|
||||
@@ -58,7 +58,7 @@ struct PS_AI_CONVAGENT_API FPS_AI_ConvAgent_NeckBoneEntry
|
||||
// 5. Set TargetOffset for actors without a skeleton (e.g. (0,0,160) for
|
||||
// eye-level on a simple actor).
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
UCLASS(ClassGroup = "PS AI ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
DisplayName = "PS AI ConvAgent Gaze")
|
||||
class PS_AI_CONVAGENT_API UPS_AI_ConvAgent_GazeComponent : public UActorComponent
|
||||
{
|
||||
@@ -71,24 +71,24 @@ public:
|
||||
|
||||
/** The actor to look at. Can be any actor (player, prop, etc.).
|
||||
* Set to null to smoothly return to neutral. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ToolTip = "Target actor to look at.\nSet to null to return to neutral."))
|
||||
TObjectPtr<AActor> TargetActor;
|
||||
|
||||
/** When false, all gaze outputs smoothly blend to neutral (passthrough).
|
||||
* The underlying tracking keeps running so reactivation is seamless.
|
||||
* Managed automatically: activates on conversation connect, deactivates on disconnect. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|Gaze")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|Gaze")
|
||||
bool bActive = true;
|
||||
|
||||
/** How long (seconds) to blend in/out when bActive changes. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0.05", ClampMax = "3.0"))
|
||||
float ActivationBlendDuration = 0.5f;
|
||||
|
||||
/** When false, body rotation is frozen — only head and eyes track the target.
|
||||
* Useful to have the agent notice the player (eyes+head) before fully engaging (body). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ToolTip = "Enable body rotation toward the target.\nWhen false, only head and eyes track."))
|
||||
bool bEnableBodyTracking = true;
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
* When enabled, TargetOffset is ignored and the agent looks at the midpoint
|
||||
* between the target pawn's eye bones.
|
||||
* Fallback chain: eye bones → head bone → PawnViewLocation → FallbackEyeHeight. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ToolTip = "Auto-target the pawn's eye bones for eye contact.\nFallback: eye bones > head bone > PawnViewLocation > FallbackEyeHeight."))
|
||||
bool bAutoTargetEyes = true;
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
* AND the target is not a Pawn. For Pawns without skeleton, GetPawnViewLocation()
|
||||
* is used instead (accounts for BaseEyeHeight automatically).
|
||||
* Only applies to non-Pawn actors (props, triggers, etc.). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (EditCondition = "bAutoTargetEyes", ClampMin = "0",
|
||||
ToolTip = "Height offset (cm) for non-Pawn targets without skeleton.\nPawns use BaseEyeHeight automatically.\nOnly used as last-resort fallback for non-Pawn actors."))
|
||||
float FallbackEyeHeight = 160.0f;
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
/** Offset from the target actor's origin to aim at.
|
||||
* Only used when bAutoTargetEyes is false.
|
||||
* E.g. (0,0,160) for eye-level on a simple actor. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (EditCondition = "!bAutoTargetEyes",
|
||||
ToolTip = "Offset from target actor origin.\nE.g. (0,0,160) for eye-level.\nOnly used when Auto Target Eyes is disabled."))
|
||||
FVector TargetOffset = FVector(0.0f, 0.0f, 0.0f);
|
||||
@@ -127,44 +127,44 @@ public:
|
||||
// so small movements around the target don't re-trigger higher layers.
|
||||
|
||||
/** Maximum head yaw rotation in degrees. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0", ClampMax = "90"))
|
||||
float MaxHeadYaw = 40.0f;
|
||||
|
||||
/** Maximum head pitch rotation in degrees. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0", ClampMax = "90"))
|
||||
float MaxHeadPitch = 30.0f;
|
||||
|
||||
/** Maximum horizontal eye angle in degrees. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0", ClampMax = "90"))
|
||||
float MaxEyeHorizontal = 15.0f;
|
||||
|
||||
/** Maximum vertical eye angle in degrees. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0", ClampMax = "90"))
|
||||
float MaxEyeVertical = 10.0f;
|
||||
|
||||
// ── Smoothing speeds ─────────────────────────────────────────────────────
|
||||
|
||||
/** Body rotation interpolation speed (lower = slower, more natural). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0.1", ClampMax = "20"))
|
||||
float BodyInterpSpeed = 4.0f;
|
||||
|
||||
/** Head rotation interpolation speed. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0.1", ClampMax = "20"))
|
||||
float HeadInterpSpeed = 4.0f;
|
||||
|
||||
/** Eye movement interpolation speed (higher = snappier). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0.1", ClampMax = "20"))
|
||||
float EyeInterpSpeed = 5.0f;
|
||||
|
||||
/** Interpolation speed when returning to neutral (TargetActor is null). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0.1", ClampMax = "20"))
|
||||
float ReturnToNeutralSpeed = 3.0f;
|
||||
|
||||
@@ -178,7 +178,7 @@ public:
|
||||
* 1.0 = head always points at target regardless of animation.
|
||||
* 0.0 = gaze is additive on top of animation (old behavior).
|
||||
* Default: 1.0 for conversational AI (always look at who you talk to). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0", ClampMax = "1"))
|
||||
float HeadAnimationCompensation = 0.9f;
|
||||
|
||||
@@ -186,7 +186,7 @@ public:
|
||||
* 1.0 = eyes frozen on gaze target, animation's eye movement removed.
|
||||
* 0.0 = animation's eyes play through, gaze is additive.
|
||||
* Intermediate (e.g. 0.5) = smooth 50/50 blend. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0", ClampMax = "1"))
|
||||
float EyeAnimationCompensation = 0.6f;
|
||||
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
* counter-rotates the gaze to keep the head pointing at the target.
|
||||
* 1.0 = full compensation — head stays locked on target even during bows.
|
||||
* 0.0 = no compensation — head follows body movement naturally. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "0", ClampMax = "1"))
|
||||
float BodyDriftCompensation = 0.8f;
|
||||
|
||||
@@ -204,12 +204,12 @@ public:
|
||||
/** Enable debug logging for this component.
|
||||
* When false, only key events (init, errors, state changes) are logged.
|
||||
* When true, additional diagnostic info is logged based on DebugVerbosity. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug")
|
||||
bool bDebug = false;
|
||||
|
||||
/** Verbosity level when bDebug is true.
|
||||
* 0 = minimal extras, 1 = normal debug, 2 = detailed, 3 = per-frame data. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug",
|
||||
meta = (ClampMin = "0", ClampMax = "3", EditCondition = "bDebug"))
|
||||
int32 DebugVerbosity = 1;
|
||||
|
||||
@@ -217,7 +217,7 @@ public:
|
||||
* Green = head bone → target (desired).
|
||||
* Cyan = computed gaze direction (body yaw + head + eyes).
|
||||
* Useful for verifying that eye contact is accurate. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug",
|
||||
meta = (EditCondition = "bDebug"))
|
||||
bool bDrawDebugGaze = false;
|
||||
|
||||
@@ -228,14 +228,14 @@ public:
|
||||
* 0 = mesh faces +X (default UE convention)
|
||||
* 90 = mesh faces +Y
|
||||
* -90 = mesh faces -Y */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze",
|
||||
meta = (ClampMin = "-180", ClampMax = "180"))
|
||||
float MeshForwardYawOffset = 90.0f;
|
||||
|
||||
// ── Head bone ────────────────────────────────────────────────────────────
|
||||
|
||||
/** Name of the head bone on the skeletal mesh (used for eye origin calculation). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze")
|
||||
FName HeadBoneName = FName(TEXT("head"));
|
||||
|
||||
// ── Neck bone chain ─────────────────────────────────────────────────────
|
||||
@@ -244,7 +244,7 @@ public:
|
||||
* Order: root-to-tip (e.g. neck_01 → neck_02 → head).
|
||||
* Weights should sum to ~1.0.
|
||||
* If empty, falls back to single-bone behavior (HeadBoneName, weight 1.0). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Gaze")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Gaze")
|
||||
TArray<FPS_AI_ConvAgent_NeckBoneEntry> NeckBoneChain;
|
||||
|
||||
// ── Getters (read by AnimNode) ───────────────────────────────────────────
|
||||
@@ -252,7 +252,7 @@ public:
|
||||
/** Get current eye gaze curves (8 ARKit eye look curves).
|
||||
* Returns a COPY scaled by activation alpha — safe to call from any thread.
|
||||
* NOTE: Prefer FillCurrentEyeCurves() for hot paths to avoid per-frame allocation. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|Gaze")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|Gaze")
|
||||
TMap<FName, float> GetCurrentEyeCurves() const
|
||||
{
|
||||
FScopeLock Lock(&GazeDataLock);
|
||||
|
||||
@@ -45,7 +45,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnNoConvAgentInRange);
|
||||
// 4. Mic management is auto-detected (no manual flag needed on agents).
|
||||
// 5. Agents manage their own WebSocket connections independently.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
UCLASS(ClassGroup = "PS AI ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
DisplayName = "PS AI ConvAgent Interaction")
|
||||
class PS_AI_CONVAGENT_API UPS_AI_ConvAgent_InteractionComponent : public UActorComponent
|
||||
{
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
// ── Configuration ─────────────────────────────────────────────────────────
|
||||
|
||||
/** Maximum distance (cm) at which an agent can be selected. Agents beyond this are ignored. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction",
|
||||
meta = (ClampMin = "0",
|
||||
ToolTip = "Max distance in cm to interact with an agent.\nAgents beyond this distance are never selected."))
|
||||
float MaxInteractionDistance = 300.0f;
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
/** Half-angle (degrees) of the view cone used for agent selection.
|
||||
* The cone is centered on the pawn's view direction (camera or control rotation).
|
||||
* Agents outside this cone are not considered unless they are the current sticky selection. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction",
|
||||
meta = (ClampMin = "0", ClampMax = "180",
|
||||
ToolTip = "Half-angle of the view cone (degrees).\nAgents outside this cone are not selected.\n45 = 90-degree total FOV."))
|
||||
float ViewConeHalfAngle = 45.0f;
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
/** Wider half-angle (degrees) used for the currently selected agent.
|
||||
* This provides hysteresis so the player can look slightly away from
|
||||
* the current agent without losing selection (prevents flickering). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction",
|
||||
meta = (ClampMin = "0", ClampMax = "180",
|
||||
ToolTip = "Sticky cone half-angle for the current agent (degrees).\nMust be >= ViewConeHalfAngle for hysteresis to work.\n60 = agent stays selected until 120-degree total cone is exceeded."))
|
||||
float SelectionStickyAngle = 60.0f;
|
||||
@@ -81,14 +81,14 @@ public:
|
||||
/** Height offset (cm) added to the agent's origin for the view cone check.
|
||||
* Agent origins are typically at foot level; this shifts the target point
|
||||
* up to chest/head height so close-range look-at checks don't fail. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction",
|
||||
meta = (ClampMin = "0",
|
||||
ToolTip = "Height offset (cm) above the agent origin for the view cone check.\nPrevents losing selection at close range because the camera looks above the agent's feet.\n150 = roughly chest height for a MetaHuman."))
|
||||
float AgentEyeLevelOffset = 150.0f;
|
||||
|
||||
/** When false, only distance matters for selection (no view cone check).
|
||||
* The closest agent within MaxInteractionDistance is always selected. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction",
|
||||
meta = (ToolTip = "Require the player to look at an agent to select it.\nWhen false, the closest agent within range is always selected."))
|
||||
bool bRequireLookAt = true;
|
||||
|
||||
@@ -97,20 +97,20 @@ public:
|
||||
/** Automatically set/clear the agent's GazeComponent TargetActor
|
||||
* when the agent is selected/deselected. When false, gaze must
|
||||
* be managed from Blueprint (e.g. on conversation start). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Gaze",
|
||||
meta = (ToolTip = "Automatically point the agent's gaze at the pawn on selection.\nDisable for manual control (e.g. set target only when conversation starts)."))
|
||||
bool bAutoManageGaze = true;
|
||||
|
||||
/** Delay (seconds) before setting the agent's gaze target after selection.
|
||||
* 0 = immediate. Useful to let the agent "notice" the player with a beat. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Gaze",
|
||||
meta = (EditCondition = "bAutoManageGaze", ClampMin = "0",
|
||||
ToolTip = "Seconds to wait before the agent looks at the pawn.\n0 = immediate."))
|
||||
float GazeAttachDelay = 0.0f;
|
||||
|
||||
/** Delay (seconds) before clearing the agent's gaze target after deselection.
|
||||
* 0 = immediate. Useful to have the agent keep looking briefly as the player leaves. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Gaze",
|
||||
meta = (EditCondition = "bAutoManageGaze", ClampMin = "0",
|
||||
ToolTip = "Seconds to wait before the agent stops looking at the pawn.\n0 = immediate."))
|
||||
float GazeDetachDelay = 0.0f;
|
||||
@@ -119,20 +119,20 @@ public:
|
||||
* with head+eyes (and optionally body). This creates natural "awareness"
|
||||
* without requiring an active conversation.
|
||||
* Also controls the passive gaze retained after switching conversations. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Gaze",
|
||||
meta = (EditCondition = "bAutoManageGaze",
|
||||
ToolTip = "Agents in range but not selected will passively track the player.\nAlso applies to retained gaze after switching conversations."))
|
||||
bool bAutoPassiveGaze = true;
|
||||
|
||||
/** In passive gaze mode, the agent's head and eyes follow the player. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Gaze",
|
||||
meta = (EditCondition = "bAutoManageGaze && bAutoPassiveGaze",
|
||||
ToolTip = "Enable head+eyes tracking in passive gaze mode."))
|
||||
bool bPassiveGazeHeadEyes = true;
|
||||
|
||||
/** In passive gaze mode, the agent's body also turns toward the player.
|
||||
* When false, only head and eyes track — the body stays in its default animation. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction|Gaze",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Gaze",
|
||||
meta = (EditCondition = "bAutoManageGaze && bAutoPassiveGaze",
|
||||
ToolTip = "Enable body rotation in passive gaze mode.\nWhen false, only head and eyes track."))
|
||||
bool bPassiveGazeBody = false;
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
/** How long (seconds) the player must look at a different agent before switching
|
||||
* during an active conversation. Prevents accidental switches when glancing around.
|
||||
* Only applies when a conversation is active (bNetIsConversing). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction",
|
||||
meta = (ClampMin = "0.0", ClampMax = "5.0",
|
||||
ToolTip = "Seconds the player must look at another agent before switching mid-conversation.\nPrevents accidental switches when glancing around.\n0 = instant switch."))
|
||||
float ConversationSwitchDelay = 1.0f;
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
* via StartConversationWithSelectedAgent() (e.g. on a key press).
|
||||
* Set to false when you have multiple agents in a scene to prevent them
|
||||
* all from greeting the player simultaneously. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction",
|
||||
meta = (ToolTip = "Auto-start the WebSocket when an agent is selected by proximity.\nSet to false to require explicit interaction (call StartConversationWithSelectedAgent).\nUseful with multiple agents to prevent simultaneous greetings."))
|
||||
bool bAutoStartConversation = true;
|
||||
|
||||
@@ -162,48 +162,48 @@ public:
|
||||
/** Automatically call StartListening/StopListening on the agent's
|
||||
* ElevenLabsComponent when selected/deselected. When false, listening
|
||||
* must be managed from Blueprint. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Interaction|Listening",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Listening",
|
||||
meta = (ToolTip = "Automatically open/close the agent's mic turn on selection.\nDisable for manual control (e.g. push-to-talk)."))
|
||||
bool bAutoManageListening = true;
|
||||
|
||||
// ── Debug ────────────────────────────────────────────────────────────────
|
||||
|
||||
/** Enable debug logging for this component. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug")
|
||||
bool bDebug = false;
|
||||
|
||||
/** Verbosity level when bDebug is true.
|
||||
* 0 = selection changes only, 1 = candidate evaluation, 2 = per-frame data. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug",
|
||||
meta = (ClampMin = "0", ClampMax = "3", EditCondition = "bDebug"))
|
||||
int32 DebugVerbosity = 1;
|
||||
|
||||
// ── Events ────────────────────────────────────────────────────────────────
|
||||
|
||||
/** Fired when a new agent enters selection. Use this to set gaze targets, show UI, etc. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|Interaction|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Events",
|
||||
meta = (ToolTip = "Fires when a new agent is selected.\nSet gaze targets, update UI, etc."))
|
||||
FOnConvAgentSelected OnAgentSelected;
|
||||
|
||||
/** Fired when the previously selected agent loses selection. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|Interaction|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Events",
|
||||
meta = (ToolTip = "Fires when the current agent is deselected.\nClear gaze targets, hide UI, etc."))
|
||||
FOnConvAgentDeselected OnAgentDeselected;
|
||||
|
||||
/** Fired when no agent is within range or view cone. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|Interaction|Events",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|Interaction|Events",
|
||||
meta = (ToolTip = "Fires when no agent meets the distance/view criteria."))
|
||||
FOnNoConvAgentInRange OnNoAgentInRange;
|
||||
|
||||
// ── Blueprint API ─────────────────────────────────────────────────────────
|
||||
|
||||
/** Get the currently selected agent (null if none). */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|Interaction")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|Interaction")
|
||||
UPS_AI_ConvAgent_ElevenLabsComponent* GetSelectedAgent() const;
|
||||
|
||||
/** Manually select a specific agent, bypassing distance/view checks.
|
||||
* Pass null to clear the selection. Automatic selection resumes next tick. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|Interaction")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|Interaction")
|
||||
void ForceSelectAgent(UPS_AI_ConvAgent_ElevenLabsComponent* Agent);
|
||||
|
||||
/** Start the WebSocket conversation with the currently selected agent.
|
||||
@@ -211,18 +211,18 @@ public:
|
||||
* interacts (e.g. presses a key, enters a trigger zone).
|
||||
* Does nothing if no agent is selected or the agent is already connected.
|
||||
* Also starts mic capture and listening automatically. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|Interaction")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|Interaction")
|
||||
void StartConversationWithSelectedAgent();
|
||||
|
||||
/** Send a text message to the currently selected agent.
|
||||
* The agent responds with audio and text, just as if it heard the player speak.
|
||||
* Handles network relay automatically (works on both server and client).
|
||||
* Does nothing if no agent is selected or not connected. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|Interaction")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|Interaction")
|
||||
void SendTextToSelectedAgent(const FString& Text);
|
||||
|
||||
/** Clear the current selection. Automatic selection resumes next tick. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|Interaction")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|Interaction")
|
||||
void ClearSelection();
|
||||
|
||||
// ── Network relay RPCs ───────────────────────────────────────────────────
|
||||
|
||||
@@ -29,11 +29,11 @@ public:
|
||||
void UnregisterAgent(UPS_AI_ConvAgent_ElevenLabsComponent* Agent);
|
||||
|
||||
/** Get all currently registered agent components (weak pointers, may contain stale entries that are cleaned on access). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|Interaction")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|Interaction")
|
||||
TArray<UPS_AI_ConvAgent_ElevenLabsComponent*> GetRegisteredAgents() const;
|
||||
|
||||
/** Get the number of registered agents. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|Interaction")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|Interaction")
|
||||
int32 GetNumRegisteredAgents() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -39,7 +39,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnPS_AI_ConvAgent_VisemesReady);
|
||||
* 3. Conversation starts → lip sync works automatically.
|
||||
* 4. (Optional) Bind OnVisemesReady for custom Blueprint handling.
|
||||
*/
|
||||
UCLASS(ClassGroup = "PS AI ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
DisplayName = "PS AI ConvAgent Lip Sync")
|
||||
class PS_AI_CONVAGENT_API UPS_AI_ConvAgent_LipSyncComponent : public UActorComponent
|
||||
{
|
||||
@@ -61,16 +61,16 @@ public:
|
||||
/** Whether lip sync is currently active (read-only).
|
||||
* Managed automatically: activates on conversation connect, deactivates on disconnect.
|
||||
* The underlying audio analysis keeps running so reactivation is seamless. */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|LipSync")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|LipSync")
|
||||
bool bActive = true;
|
||||
|
||||
/** How long (seconds) to blend in/out when bActive changes. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ClampMin = "0.05", ClampMax = "3.0"))
|
||||
float ActivationBlendDuration = 0.5f;
|
||||
|
||||
/** Overall mouth movement intensity multiplier. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ClampMin = "0.0", ClampMax = "3.0",
|
||||
ToolTip = "Lip sync intensity.\n1.0 = normal, higher = more expressive, lower = subtler."))
|
||||
float LipSyncStrength = 1.0f;
|
||||
@@ -78,13 +78,13 @@ public:
|
||||
/** Scales the audio amplitude driving mouth movement.
|
||||
* Lower values produce subtler animation, higher values are more pronounced.
|
||||
* Use this to tone down overly strong lip movement without changing the shape. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ClampMin = "0.5", ClampMax = "1.0",
|
||||
ToolTip = "Audio amplitude scale.\n0.5 = subtle, 0.75 = balanced, 1.0 = full.\nReduces overall mouth movement without affecting viseme shape."))
|
||||
float AmplitudeScale = 1.0f;
|
||||
|
||||
/** How quickly viseme weights interpolate towards new values each frame. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ClampMin = "35.0", ClampMax = "65.0",
|
||||
ToolTip = "Smoothing speed for viseme transitions.\n35 = smooth and soft, 50 = balanced, 65 = sharp and responsive."))
|
||||
float SmoothingSpeed = 50.0f;
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
* When the agent is NOT speaking, lip sync releases all mouth curves so the
|
||||
* FacialExpressionComponent's emotion curves (including mouth) can show through.
|
||||
* When the agent starts speaking, lip sync smoothly takes over mouth curves. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ClampMin = "0.05", ClampMax = "1.0",
|
||||
ToolTip = "Blend duration when speech starts/stops.\nDuring silence, emotion facial curves control the mouth.\nDuring speech, lip sync takes over."))
|
||||
float SpeechBlendDuration = 0.15f;
|
||||
@@ -108,7 +108,7 @@ public:
|
||||
* 0.0 = lip sync completely overrides expression curves (old behavior).
|
||||
* 1.0 = emotion fully additive on expression curves during speech.
|
||||
* 0.5 = balanced blend (recommended). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ClampMin = "0.0", ClampMax = "1.0",
|
||||
ToolTip = "Emotion bleed-through during speech.\n0 = pure lip sync, 0.5 = balanced, 1 = full emotion on expression curves.\nOnly affects expression curves (smile, frown, etc.), not lip shape."))
|
||||
float EmotionExpressionBlend = 0.5f;
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
/** Envelope attack time in milliseconds.
|
||||
* Controls how fast the mouth opens when speech starts or gets louder.
|
||||
* Lower = snappier onset, higher = gentler opening. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ClampMin = "1.0", ClampMax = "50.0",
|
||||
ToolTip = "Envelope attack (ms).\n5 = snappy, 10 = balanced, 25 = gentle.\nHow fast the mouth opens on speech onset."))
|
||||
float EnvelopeAttackMs = 10.0f;
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
/** Envelope release time in milliseconds.
|
||||
* Controls how slowly the mouth closes when speech gets quieter.
|
||||
* Higher = smoother, more natural decay. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ClampMin = "10.0", ClampMax = "200.0",
|
||||
ToolTip = "Envelope release (ms).\n25 = responsive, 50 = balanced, 120 = smooth/cinematic.\nHow slowly the mouth closes between syllables."))
|
||||
float EnvelopeReleaseMs = 50.0f;
|
||||
@@ -135,12 +135,12 @@ public:
|
||||
|
||||
/** Enable debug logging for this component.
|
||||
* When false, only key events (init, errors, state changes) are logged. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug")
|
||||
bool bDebug = false;
|
||||
|
||||
/** Verbosity level when bDebug is true.
|
||||
* 0 = minimal extras, 1 = normal debug, 2 = detailed, 3 = per-frame data. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug",
|
||||
meta = (ClampMin = "0", ClampMax = "3", EditCondition = "bDebug"))
|
||||
int32 DebugVerbosity = 1;
|
||||
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
* When assigned, curve data is extracted at BeginPlay and replaces the
|
||||
* hardcoded ARKit blendshape mapping with artist-crafted poses.
|
||||
* Leave empty to use the built-in ARKit mapping (backward compatible). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ToolTip = "Reusable pose map asset.\nAssign your MHF_* AnimSequences once, reuse on all MetaHumans.\nLeave empty for built-in ARKit mapping."))
|
||||
TObjectPtr<UPS_AI_ConvAgent_LipSyncPoseMap> PoseMap;
|
||||
|
||||
@@ -160,19 +160,19 @@ public:
|
||||
|
||||
/** Fires every tick when viseme data has been updated.
|
||||
* Use GetCurrentVisemes() or GetCurrentBlendshapes() to read values. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|LipSync",
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|LipSync",
|
||||
meta = (ToolTip = "Fires each frame with updated viseme data.\nCall GetCurrentVisemes() or GetCurrentBlendshapes() to read values."))
|
||||
FOnPS_AI_ConvAgent_VisemesReady OnVisemesReady;
|
||||
|
||||
// ── Getters ───────────────────────────────────────────────────────────────
|
||||
|
||||
/** Get current OVR viseme weights (15 values: sil, PP, FF, TH, DD, kk, CH, SS, nn, RR, aa, E, ih, oh, ou). */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|LipSync")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|LipSync")
|
||||
TMap<FName, float> GetCurrentVisemes() const { return SmoothedVisemes; }
|
||||
|
||||
/** Get current ARKit blendshape weights (MetaHuman compatible: jawOpen, mouthFunnel, mouthClose, etc.).
|
||||
* Thread-safe: returns a snapshot updated each tick. Safe to call from anim worker threads. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|LipSync")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|LipSync")
|
||||
TMap<FName, float> GetCurrentBlendshapes() const
|
||||
{
|
||||
FScopeLock Lock(&BlendshapeLock);
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
|
||||
/** True when the agent is currently producing speech audio.
|
||||
* When false, lip sync releases mouth curves to let emotion curves through. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|LipSync")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|LipSync")
|
||||
bool IsSpeaking() const { return bIsSpeaking; }
|
||||
|
||||
/** Current speech blend alpha (0 = silent/emotion mouth, 1 = lip sync mouth).
|
||||
|
||||
@@ -22,7 +22,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnPS_AI_ConvAgent_VoiceActivityChan
|
||||
* Modelled after Convai's ConvaiAudioCaptureComponent but stripped to the
|
||||
* minimal functionality needed for conversational AI agents.
|
||||
*/
|
||||
UCLASS(ClassGroup = "PS AI ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
UCLASS(ClassGroup = "ASTERION|PS_AI_ConvAgent", meta = (BlueprintSpawnableComponent),
|
||||
DisplayName = "PS AI ConvAgent Microphone Capture")
|
||||
class PS_AI_CONVAGENT_API UPS_AI_ConvAgent_MicrophoneCaptureComponent : public UActorComponent
|
||||
{
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
UPS_AI_ConvAgent_MicrophoneCaptureComponent();
|
||||
|
||||
/** Multiplier applied to the microphone input volume before sending to the agent. Increase if the agent has trouble hearing you, decrease if your audio is clipping. Default: 1.0 (no change). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|MicCapture",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|MicCapture",
|
||||
meta = (ClampMin = "0.0", ClampMax = "4.0",
|
||||
ToolTip = "Microphone volume multiplier.\n1.0 = no change. Increase if the agent can't hear you, decrease if audio clips."))
|
||||
float VolumeMultiplier = 1.0f;
|
||||
@@ -52,50 +52,50 @@ public:
|
||||
// ── Local Voice Activity Detection ──────────────────────────────────
|
||||
|
||||
/** RMS threshold above which audio is considered voice. Adjust based on mic sensitivity and environment noise. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Voice Activity",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Voice Activity",
|
||||
meta = (ClampMin = "0.001", ClampMax = "0.2"))
|
||||
float VoiceActivityThreshold = 0.015f;
|
||||
|
||||
/** Time (seconds) RMS must stay above threshold before declaring speech onset. Prevents false triggers from clicks/bumps. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Voice Activity",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Voice Activity",
|
||||
meta = (ClampMin = "0.01", ClampMax = "1.0"))
|
||||
float VoiceOnsetTime = 0.1f;
|
||||
|
||||
/** Time (seconds) RMS must stay below threshold before declaring speech ended. Prevents cutting off between words. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Voice Activity",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Voice Activity",
|
||||
meta = (ClampMin = "0.1", ClampMax = "3.0"))
|
||||
float VoiceSilenceTime = 0.5f;
|
||||
|
||||
/** Whether the user is currently speaking (local VAD, independent of ElevenLabs server). */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "PS AI ConvAgent|Voice Activity")
|
||||
UPROPERTY(BlueprintReadOnly, Category = "ASTERION|PS_AI_ConvAgent|Voice Activity")
|
||||
bool bIsUserSpeaking = false;
|
||||
|
||||
/** Fired when voice activity changes. Use to pause NPC movement, trigger animations, etc. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|Voice Activity")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|Voice Activity")
|
||||
FOnPS_AI_ConvAgent_VoiceActivityChanged OnUserVoiceActivityChanged;
|
||||
|
||||
// ── Debug ────────────────────────────────────────────────────────────────
|
||||
|
||||
/** Enable debug logging for this component.
|
||||
* When false, only key events (init, errors, state changes) are logged. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug")
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug")
|
||||
bool bDebug = false;
|
||||
|
||||
/** Verbosity level when bDebug is true.
|
||||
* 0 = minimal extras, 1 = normal debug, 2 = detailed, 3 = per-frame data. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PS AI ConvAgent|Debug",
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ASTERION|PS_AI_ConvAgent|Debug",
|
||||
meta = (ClampMin = "0", ClampMax = "3", EditCondition = "bDebug"))
|
||||
int32 DebugVerbosity = 1;
|
||||
|
||||
/** Open the default capture device and begin streaming audio. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|MicCapture")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|MicCapture")
|
||||
void StartCapture();
|
||||
|
||||
/** Stop streaming and close the capture device. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|MicCapture")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|MicCapture")
|
||||
void StopCapture();
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|MicCapture")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|MicCapture")
|
||||
bool IsCapturing() const { return bCapturing; }
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -69,31 +69,31 @@ public:
|
||||
// ── Events ────────────────────────────────────────────────────────────────
|
||||
|
||||
/** Called once the WebSocket handshake succeeds and the agent sends its initiation metadata. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_Connected OnConnected;
|
||||
|
||||
/** Called when the WebSocket closes (graceful or remote). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_Disconnected OnDisconnected;
|
||||
|
||||
/** Called on any connection or protocol error. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_Error OnError;
|
||||
|
||||
/** Raw PCM audio coming from the agent — feed this into your audio component. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_AudioReceived OnAudioReceived;
|
||||
|
||||
/** User or agent transcript (may be tentative while the conversation is ongoing). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_Transcript OnTranscript;
|
||||
|
||||
/** Final text response from the agent (complements audio). */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_AgentResponse OnAgentResponse;
|
||||
|
||||
/** The agent was interrupted by new user speech. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_Interrupted OnInterrupted;
|
||||
|
||||
/**
|
||||
@@ -101,15 +101,15 @@ public:
|
||||
* starts generating. Fires well before audio. The component uses this to stop the
|
||||
* microphone if it was restarted before the server finished processing the previous turn.
|
||||
*/
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_ResponseStarted OnAgentResponseStarted;
|
||||
|
||||
/** Fired for every agent_chat_response_part with the streaming text fragment. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_ResponsePart OnAgentResponsePart;
|
||||
|
||||
/** Fired when the agent invokes a client tool. Handle the call and reply with SendClientToolResult. */
|
||||
UPROPERTY(BlueprintAssignable, Category = "PS AI ConvAgent|ElevenLabs|Events")
|
||||
UPROPERTY(BlueprintAssignable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs|Events")
|
||||
FOnPS_AI_ConvAgent_ElevenLabs_ClientToolCall OnClientToolCall;
|
||||
|
||||
// ── Lifecycle ─────────────────────────────────────────────────────────────
|
||||
@@ -121,21 +121,21 @@ public:
|
||||
* @param AgentID ElevenLabs agent ID. Overrides the project-level default when non-empty.
|
||||
* @param APIKey API key. Overrides the project-level default when non-empty.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void Connect(const FString& AgentID = TEXT(""), const FString& APIKey = TEXT(""));
|
||||
|
||||
/**
|
||||
* Gracefully close the WebSocket connection.
|
||||
* OnDisconnected will fire after the server acknowledges.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void Disconnect();
|
||||
|
||||
/** Current connection state. */
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
EPS_AI_ConvAgent_ConnectionState_ElevenLabs GetConnectionState() const { return ConnectionState; }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
bool IsConnected() const { return ConnectionState == EPS_AI_ConvAgent_ConnectionState_ElevenLabs::Connected; }
|
||||
|
||||
// ── Audio sending ─────────────────────────────────────────────────────────
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
*
|
||||
* @param PCMData Raw PCM bytes (16-bit LE, 16kHz, mono).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void SendAudioChunk(const TArray<uint8>& PCMData);
|
||||
|
||||
// ── Turn control (only relevant in Client turn mode) ──────────────────────
|
||||
@@ -158,7 +158,7 @@ public:
|
||||
* Sends a { "type": "user_activity" } message to the server.
|
||||
* Call this periodically while the user is speaking (e.g. every audio chunk).
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void SendUserTurnStart();
|
||||
|
||||
/**
|
||||
@@ -166,7 +166,7 @@ public:
|
||||
* No explicit API message — simply stop sending user_activity.
|
||||
* The server detects silence and hands the turn to the agent.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void SendUserTurnEnd();
|
||||
|
||||
/**
|
||||
@@ -174,11 +174,11 @@ public:
|
||||
* Useful for testing or text-only interaction.
|
||||
* Sends: { "type": "user_message", "text": "..." }
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void SendTextMessage(const FString& Text);
|
||||
|
||||
/** Ask the agent to stop the current utterance. */
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void SendInterrupt();
|
||||
|
||||
/**
|
||||
@@ -189,12 +189,12 @@ public:
|
||||
* @param Result A string result to return to the agent.
|
||||
* @param bIsError True if the tool execution failed.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintCallable, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
void SendClientToolResult(const FString& ToolCallId, const FString& Result, bool bIsError = false);
|
||||
|
||||
// ── Info ──────────────────────────────────────────────────────────────────
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "PS AI ConvAgent|ElevenLabs")
|
||||
UFUNCTION(BlueprintPure, Category = "ASTERION|PS_AI_ConvAgent|ElevenLabs")
|
||||
const FPS_AI_ConvAgent_ConversationInfo_ElevenLabs& GetConversationInfo() const { return ConversationInfo; }
|
||||
|
||||
/** Latest WebSocket round-trip latency reported by the server (ms).
|
||||
|
||||
@@ -21,7 +21,7 @@ FText UAnimGraphNode_PS_AI_ConvAgent_BodyExpression::GetTooltipText() const
|
||||
|
||||
FString UAnimGraphNode_PS_AI_ConvAgent_BodyExpression::GetNodeCategory() const
|
||||
{
|
||||
return TEXT("PS AI ConvAgent");
|
||||
return TEXT("ASTERION|PS_AI_ConvAgent");
|
||||
}
|
||||
|
||||
FLinearColor UAnimGraphNode_PS_AI_ConvAgent_BodyExpression::GetNodeTitleColor() const
|
||||
|
||||
@@ -20,7 +20,7 @@ FText UAnimGraphNode_PS_AI_ConvAgent_FacialExpression::GetTooltipText() const
|
||||
|
||||
FString UAnimGraphNode_PS_AI_ConvAgent_FacialExpression::GetNodeCategory() const
|
||||
{
|
||||
return TEXT("PS AI ConvAgent");
|
||||
return TEXT("ASTERION|PS_AI_ConvAgent");
|
||||
}
|
||||
|
||||
FLinearColor UAnimGraphNode_PS_AI_ConvAgent_FacialExpression::GetNodeTitleColor() const
|
||||
|
||||
@@ -21,7 +21,7 @@ FText UAnimGraphNode_PS_AI_ConvAgent_Gaze::GetTooltipText() const
|
||||
|
||||
FString UAnimGraphNode_PS_AI_ConvAgent_Gaze::GetNodeCategory() const
|
||||
{
|
||||
return TEXT("PS AI ConvAgent");
|
||||
return TEXT("ASTERION|PS_AI_ConvAgent");
|
||||
}
|
||||
|
||||
FLinearColor UAnimGraphNode_PS_AI_ConvAgent_Gaze::GetNodeTitleColor() const
|
||||
|
||||
@@ -20,7 +20,7 @@ FText UAnimGraphNode_PS_AI_ConvAgent_LipSync::GetTooltipText() const
|
||||
|
||||
FString UAnimGraphNode_PS_AI_ConvAgent_LipSync::GetNodeCategory() const
|
||||
{
|
||||
return TEXT("PS AI ConvAgent");
|
||||
return TEXT("ASTERION|PS_AI_ConvAgent");
|
||||
}
|
||||
|
||||
FLinearColor UAnimGraphNode_PS_AI_ConvAgent_LipSync::GetNodeTitleColor() const
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/**
|
||||
* AnimGraph editor node for the PS AI ConvAgent Body Expression AnimNode.
|
||||
*
|
||||
* This node appears in the AnimBP graph editor under the "PS AI ConvAgent" category.
|
||||
* This node appears in the AnimBP graph editor under the "ASTERION|PS_AI_ConvAgent" category.
|
||||
* Place it in the character's Body AnimBP after upstream body animations
|
||||
* (idle, locomotion). It blends emotion-driven body poses onto the upper body
|
||||
* while passing the lower body through unchanged.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/**
|
||||
* AnimGraph editor node for the PS AI ConvAgent Facial Expression AnimNode.
|
||||
*
|
||||
* This node appears in the AnimBP graph editor under the "PS AI ConvAgent" category.
|
||||
* This node appears in the AnimBP graph editor under the "ASTERION|PS_AI_ConvAgent" category.
|
||||
* Place it BEFORE the PS AI ConvAgent Lip Sync node in the MetaHuman Face AnimBP.
|
||||
* It auto-discovers the PS_AI_ConvAgent_FacialExpressionComponent on the owning Actor
|
||||
* and injects CTRL_expressions_* curves for emotion-driven facial expressions.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/**
|
||||
* AnimGraph editor node for the PS AI ConvAgent Gaze AnimNode.
|
||||
*
|
||||
* This node appears in the AnimBP graph editor under the "PS AI ConvAgent" category.
|
||||
* This node appears in the AnimBP graph editor under the "ASTERION|PS_AI_ConvAgent" category.
|
||||
* Place it AFTER the PS AI ConvAgent Facial Expression node and BEFORE the
|
||||
* PS AI ConvAgent Lip Sync node in the MetaHuman Face AnimBP.
|
||||
*
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/**
|
||||
* AnimGraph editor node for the PS AI ConvAgent Lip Sync AnimNode.
|
||||
*
|
||||
* This node appears in the AnimBP graph editor under the "PS AI ConvAgent" category.
|
||||
* This node appears in the AnimBP graph editor under the "ASTERION|PS_AI_ConvAgent" category.
|
||||
* Drop it into your MetaHuman Face AnimBP between the pose source and the
|
||||
* Control Rig node. It auto-discovers the PS_AI_ConvAgent_LipSyncComponent on the
|
||||
* owning Actor and injects CTRL_expressions_* curves for lip sync.
|
||||
|
||||
Reference in New Issue
Block a user