// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "Logging/LogMacros.h" #include "AgrarianGameCharacter.generated.h" class USpringArmComponent; class UCameraComponent; class UInputAction; class UAgrarianBuildingPlacementComponent; class UAgrarianCraftingComponent; class UAgrarianInventoryComponent; class UAgrarianSurvivalComponent; class UAudioComponent; class USoundBase; struct FInputActionValue; DECLARE_LOG_CATEGORY_EXTERN(LogTemplateCharacter, Log, All); /** * A simple player-controllable third person character * Implements a controllable orbiting camera */ UCLASS(abstract) class AAgrarianGameCharacter : public ACharacter { GENERATED_BODY() /** Camera boom positioning the camera behind the character */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components", meta = (AllowPrivateAccess = "true")) USpringArmComponent* CameraBoom; /** Follow camera */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components", meta = (AllowPrivateAccess = "true")) UCameraComponent* FollowCamera; /** Replicated survival state for hunger, thirst, stamina, health, temperature, and injury. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components", meta = (AllowPrivateAccess = "true")) UAgrarianSurvivalComponent* SurvivalComponent; /** Replicated inventory used by gathering, primitive crafting, and early economy prototypes. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components", meta = (AllowPrivateAccess = "true")) UAgrarianInventoryComponent* InventoryComponent; /** Primitive crafting component for MVP recipes and future knowledge progression. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components", meta = (AllowPrivateAccess = "true")) UAgrarianCraftingComponent* CraftingComponent; /** Server-authoritative primitive building placement component. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components", meta = (AllowPrivateAccess = "true")) UAgrarianBuildingPlacementComponent* BuildingPlacementComponent; /** Local placeholder footstep playback point; silent until sound assets are assigned. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components", meta = (AllowPrivateAccess = "true")) UAudioComponent* FootstepAudioComponent; protected: /** Jump Input Action */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* JumpAction; /** Move Input Action */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* MoveAction; /** Look Input Action */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* LookAction; /** Mouse Look Input Action */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* MouseLookAction; /** Interact Input Action */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* InteractAction; /** Hold to sprint while stamina allows it. */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* SprintAction; /** Toggle crouch movement stance. */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* CrouchAction; /** Toggle prone movement stance. */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* ProneAction; /** Toggle between third-person and first-person camera views. */ UPROPERTY(EditAnywhere, Category="Input") UInputAction* ToggleCameraAction; /** How far the player can interact with MVP objects. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Interaction", meta = (ClampMin = "100")) float InteractionDistance = 450.0f; /** Actor currently under the local interaction trace. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Interaction", meta = (AllowPrivateAccess = "true")) TObjectPtr FocusedInteractableActor = nullptr; /** Prompt text for the currently focused interactable. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Interaction", meta = (AllowPrivateAccess = "true")) FText InteractionPromptText; /** Baseline movement speed before sprint, skill, injury, load, and terrain modifiers. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement", meta = (ClampMin = "0")) float WalkSpeed = 140.0f; /** Short-burst movement speed used by the first sprinting pass. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement", meta = (ClampMin = "0")) float SprintSpeed = 550.0f; /** Stamina spent each second while sprinting and moving. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement", meta = (ClampMin = "0")) float SprintStaminaCostPerSecond = 28.0f; /** Minimum stamina required to start or continue sprinting. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement", meta = (ClampMin = "0", ClampMax = "100")) float MinSprintStamina = 5.0f; /** Movement multiplier while crouched. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement|Stance", meta = (ClampMin = "0.1", ClampMax = "1")) float CrouchSpeedMultiplier = 0.55f; /** Movement multiplier while prone. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement|Stance", meta = (ClampMin = "0.05", ClampMax = "1")) float ProneSpeedMultiplier = 0.25f; /** Age hook used by movement until full lifecycle/aging systems own it. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing = OnRep_MovementModifierState, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0")) float AgeYears = 25.0f; /** General physical condition scalar reserved for care, illness, sleep, and long-term state. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing = OnRep_MovementModifierState, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0.25", ClampMax = "1.25")) float PhysicalConditionMultiplier = 1.0f; /** Strength scalar that mainly offsets carried-weight penalties. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing = OnRep_MovementModifierState, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0.25", ClampMax = "2.0")) float StrengthMultiplier = 1.0f; /** Endurance scalar that improves stamina efficiency and movement resilience. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing = OnRep_MovementModifierState, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0.25", ClampMax = "2.0")) float EnduranceMultiplier = 1.0f; /** Comfort carry capacity before speed penalties, in item-weight units. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0")) float ComfortableCarryWeight = 25.0f; /** Severe carry capacity where movement is heavily reduced, in item-weight units. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0")) float HeavyCarryWeight = 60.0f; /** Terrain hook for later surface/volume systems. Values below one slow the character. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing = OnRep_MovementModifierState, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0.25", ClampMax = "1.25")) float TerrainMovementMultiplier = 1.0f; /** Placeholder walk footstep cue, intended for final surface-aware audio replacement later. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Audio|Footsteps") TObjectPtr WalkFootstepSound; /** Placeholder sprint footstep cue. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Audio|Footsteps") TObjectPtr SprintFootstepSound; /** Placeholder crouch footstep cue. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Audio|Footsteps") TObjectPtr CrouchFootstepSound; /** Placeholder prone shuffle cue. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Audio|Footsteps") TObjectPtr ProneFootstepSound; /** Normal walking step cadence before sprint/crouch/prone modifiers. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Audio|Footsteps", meta = (ClampMin = "0.1")) float WalkFootstepIntervalSeconds = 0.58f; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Audio|Footsteps", meta = (ClampMin = "0.1")) float SprintFootstepIntervalSeconds = 0.34f; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Audio|Footsteps", meta = (ClampMin = "0.1")) float CrouchFootstepIntervalSeconds = 0.86f; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Audio|Footsteps", meta = (ClampMin = "0.1")) float ProneFootstepIntervalSeconds = 1.15f; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Audio|Footsteps", meta = (AllowPrivateAccess = "true")) float FootstepIntervalAccumulatorSeconds = 0.0f; /** Third-person spring arm distance used when returning from first person. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Camera", meta = (ClampMin = "0")) float ThirdPersonCameraDistance = 400.0f; /** Local first-person camera offset relative to the capsule root. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Camera") FVector FirstPersonCameraOffset = FVector(0.0f, 0.0f, 72.0f); /** True when this local character is using the optional first-person view. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Camera", meta = (AllowPrivateAccess = "true")) bool bFirstPersonCamera = false; /** Replicated player intent to sprint; actual sprinting also depends on stamina and alive state. */ UPROPERTY(ReplicatedUsing = OnRep_SprintState, VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Movement", meta = (AllowPrivateAccess = "true")) bool bWantsToSprint = false; /** Replicated prone stance for low crawl movement. */ UPROPERTY(ReplicatedUsing = OnRep_ProneState, VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Movement|Stance", meta = (AllowPrivateAccess = "true")) bool bIsProne = false; public: /** Constructor */ AAgrarianGameCharacter(); protected: virtual void Tick(float DeltaSeconds) override; virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; /** Initialize input action bindings */ virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; protected: /** Called for movement input */ void Move(const FInputActionValue& Value); /** Called for looking input */ void Look(const FInputActionValue& Value); /** Called for interaction input */ void Interact(); /** Called when sprint input is pressed. */ void StartSprint(); /** Called when sprint input is released. */ void StopSprint(); /** Called when crouch input is pressed. */ void ToggleCrouchStance(); /** Called when prone input is pressed. */ void ToggleProneStance(); /** Called for camera perspective toggle input */ void ToggleCameraPerspective(); /** Applies local camera presentation state. */ void SetFirstPersonCamera(bool bEnableFirstPerson); /** Applies the requested sprint intent locally and, when needed, on the server. */ void SetWantsToSprint(bool bNewWantsToSprint); /** Returns true when the character has enough survival state to sprint. */ bool CanSprint() const; /** Applies current walk or sprint speed to character movement. */ void ApplyMovementSpeed(); /** Calculates the current multiplier from survival, carried weight, terrain, and placeholder traits. */ float CalculateMovementSpeedMultiplier() const; float CalculateAgeMovementMultiplier() const; float CalculateSurvivalMovementMultiplier() const; float CalculateCarryWeightMovementMultiplier() const; float CalculateStanceMovementMultiplier() const; void UpdateFootstepAudio(float DeltaSeconds); USoundBase* GetCurrentFootstepSound() const; float GetCurrentFootstepIntervalSeconds() const; UFUNCTION() void OnRep_SprintState(); UFUNCTION() void OnRep_ProneState(); UFUNCTION() void OnRep_MovementModifierState(); public: /** Handles move inputs from either controls or UI interfaces */ UFUNCTION(BlueprintCallable, Category="Input") virtual void DoMove(float Right, float Forward); /** Handles look inputs from either controls or UI interfaces */ UFUNCTION(BlueprintCallable, Category="Input") virtual void DoLook(float Yaw, float Pitch); /** Handles jump pressed inputs from either controls or UI interfaces */ UFUNCTION(BlueprintCallable, Category="Input") virtual void DoJumpStart(); /** Handles jump pressed inputs from either controls or UI interfaces */ UFUNCTION(BlueprintCallable, Category="Input") virtual void DoJumpEnd(); /** Attempts to interact with the object in front of the player. */ UFUNCTION(BlueprintCallable, Category="Agrarian|Interaction") virtual void TryInteract(); /** Returns true when the local interaction trace has a usable target. */ UFUNCTION(BlueprintPure, Category="Agrarian|Interaction") bool HasInteractionPrompt() const; /** Returns the current local interaction prompt text. */ UFUNCTION(BlueprintPure, Category="Agrarian|Interaction") FText GetInteractionPromptText() const { return InteractionPromptText; } /** Returns the actor currently under the local interaction trace, if any. */ UFUNCTION(BlueprintPure, Category="Agrarian|Interaction") AActor* GetFocusedInteractableActor() const { return FocusedInteractableActor; } /** Returns true when this local character is using first-person camera presentation. */ UFUNCTION(BlueprintPure, Category="Agrarian|Camera") bool IsFirstPersonCamera() const { return bFirstPersonCamera; } /** Returns true when sprint intent and current stamina allow sprinting. */ UFUNCTION(BlueprintPure, Category="Agrarian|Movement") bool IsSprinting() const; UFUNCTION(BlueprintPure, Category="Agrarian|Movement|Stance") bool IsProne() const { return bIsProne; } UFUNCTION(BlueprintCallable, Category="Agrarian|Movement|Stance") void SetProne(bool bNewProne); UFUNCTION(BlueprintPure, Category="Agrarian|Movement") float GetCurrentCarryWeight() const; UFUNCTION(BlueprintPure, Category="Agrarian|Movement") float GetCurrentMovementSpeedMultiplier() const; UFUNCTION(BlueprintPure, Category="Agrarian|Movement|Modifiers") float GetAgeYears() const { return AgeYears; } UFUNCTION(BlueprintPure, Category="Agrarian|Movement|Modifiers") float GetPhysicalConditionMultiplier() const { return PhysicalConditionMultiplier; } UFUNCTION(BlueprintPure, Category="Agrarian|Movement|Modifiers") float GetStrengthMultiplier() const { return StrengthMultiplier; } UFUNCTION(BlueprintPure, Category="Agrarian|Movement|Modifiers") float GetEnduranceMultiplier() const { return EnduranceMultiplier; } UFUNCTION(BlueprintPure, Category="Agrarian|Movement|Modifiers") float GetTerrainMovementMultiplier() const { return TerrainMovementMultiplier; } UFUNCTION(BlueprintCallable, Category="Agrarian|Movement") void SetTerrainMovementMultiplier(float NewTerrainMovementMultiplier); /** Server-authoritative interaction entry point. */ UFUNCTION(Server, Reliable) void ServerInteract(AActor* TargetActor); /** Server-authoritative sprint intent update. */ UFUNCTION(Server, Reliable) void ServerSetWantsToSprint(bool bNewWantsToSprint); /** Server-authoritative prone stance update. */ UFUNCTION(Server, Reliable) void ServerSetProne(bool bNewProne); /** Server-authoritative terrain movement modifier update. */ UFUNCTION(Server, Reliable) void ServerSetTerrainMovementMultiplier(float NewTerrainMovementMultiplier); /** Refreshes local interactable focus and prompt text. */ void UpdateInteractionPrompt(); /** Finds a valid interactable in front of this character. */ AActor* FindFocusedInteractable(FText* OutPromptText = nullptr) const; public: /** Returns CameraBoom subobject **/ FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; } /** Returns FollowCamera subobject **/ FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; } /** Returns SurvivalComponent subobject **/ FORCEINLINE UAgrarianSurvivalComponent* GetSurvivalComponent() const { return SurvivalComponent; } /** Returns InventoryComponent subobject **/ FORCEINLINE UAgrarianInventoryComponent* GetInventoryComponent() const { return InventoryComponent; } /** Returns CraftingComponent subobject **/ FORCEINLINE UAgrarianCraftingComponent* GetCraftingComponent() const { return CraftingComponent; } /** Returns BuildingPlacementComponent subobject **/ FORCEINLINE UAgrarianBuildingPlacementComponent* GetBuildingPlacementComponent() const { return BuildingPlacementComponent; } };