#pragma once #include "CoreMinimal.h" #include "Components/ActorComponent.h" #include "SkillTreeTypes.h" #include "SkillTreeComponent.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSkillPointsChanged, int32, NewSkillPoints); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSkillPurchased, FName, SkillID); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSkillSelectionChanged, int32, TotalCost); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnSkillStateChanged, FName, SkillID); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSelectionError, FName, SkillID, FText, ErrorMessage); UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class UTAD_UI_API USkillTreeComponent : public UActorComponent { GENERATED_BODY() public: USkillTreeComponent(); protected: virtual void BeginPlay() override; // Current skill points available UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Skill Points", SaveGame) int32 AvailableSkillPoints = 0; // Total skill points earned UPROPERTY(BlueprintReadOnly, Category = "Skill Points", SaveGame) int32 TotalSkillPointsEarned = 0; // Data table containing all skill definitions UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Skill Tree") class UDataTable* SkillDataTable = nullptr; // All skills loaded from the data table UPROPERTY(BlueprintReadOnly, Category = "Skill Tree") TMap AllSkills = {}; // Currently purchased skills UPROPERTY(BlueprintReadOnly, Category = "Skill Tree", SaveGame) TArray PurchasedSkills; // Currently selected skills for purchase UPROPERTY(BlueprintReadOnly, Category = "Skill Tree") TArray SelectedSkills; // Cache the total cost of selected skills UPROPERTY(BlueprintReadOnly, Category = "Skill Tree") int32 CurrentSelectionCost; public: // Initialize the skill tree from data table UFUNCTION(BlueprintCallable, Category = "Skill Tree") void InitializeSkillTree(); // Skill Points Management UFUNCTION(BlueprintCallable, Category = "Skill Points") void AddSkillPoints(int32 Amount); UFUNCTION(BlueprintCallable, Category = "Skill Points") void RemoveSkillPoints(int32 Amount); UFUNCTION(BlueprintPure, Category = "Skill Points") int32 GetAvailableSkillPoints() const { return AvailableSkillPoints; } UFUNCTION(BlueprintPure, Category = "Skill Points") int32 GetTotalSkillPointsEarned() const { return TotalSkillPointsEarned; } // Selection Management UFUNCTION(BlueprintCallable, Category = "Skill Selection") bool SelectSkill(FName SkillID); UFUNCTION(BlueprintCallable, Category = "Skill Selection") bool DeselectSkill(FName SkillID); UFUNCTION(BlueprintCallable, Category = "Skill Selection") void ClearSelection(); UFUNCTION(BlueprintCallable, Category = "Skill Selection") bool ConfirmPurchase(); UFUNCTION(BlueprintPure, Category = "Skill Selection") TArray GetSelectedSkills() const { return SelectedSkills; } UFUNCTION(BlueprintPure, Category = "Skill Selection") int32 GetSelectionCost() const { return CurrentSelectionCost; } UFUNCTION(BlueprintPure, Category = "Skill Selection") bool CanAffordSelection() const { return AvailableSkillPoints >= CurrentSelectionCost; } // Skill State Queries UFUNCTION(BlueprintPure, Category = "Skill State") bool IsSkillPurchased(FName SkillID) const; UFUNCTION(BlueprintPure, Category = "Skill State") bool IsSkillSelected(FName SkillID) const; UFUNCTION(BlueprintPure, Category = "Skill State") bool IsSkillAvailable(FName SkillID) const; UFUNCTION(BlueprintPure, Category = "Skill State") bool CanSelectSkill(FName SkillID, FText& OutErrorMessage) const; UFUNCTION(BlueprintPure, Category = "Skill State") ESkillNodeState GetSkillState(FName SkillID) const; // Get skill data UFUNCTION(BlueprintPure, Category = "Skill Data") bool GetSkillNodeData(FName SkillID, FSkillNodeRuntime& OutNodeData) const; UFUNCTION(BlueprintPure, Category = "Skill Data") TArray GetAllSkillNodes() const; // Calculate total bonuses from purchased skills UFUNCTION(BlueprintPure, Category = "Skill Bonuses") float GetTotalHealthBonus() const; UFUNCTION(BlueprintPure, Category = "Skill Bonuses") float GetTotalDamageBonus() const; UFUNCTION(BlueprintPure, Category = "Skill Bonuses") float GetTotalSpeedBonus() const; UFUNCTION(BlueprintPure, Category = "Skill Bonuses") float GetTotalHealthBonusPercent() const; UFUNCTION(BlueprintPure, Category = "Skill Bonuses") float GetTotalDamageBonusPercent() const; UFUNCTION(BlueprintPure, Category = "Skill Bonuses") float GetTotalSpeedBonusPercent() const; // Reset skills (for respec feature) UFUNCTION(BlueprintCallable, Category = "Skill Tree") void ResetAllSkills(); // Events UPROPERTY(BlueprintAssignable, Category = "Skill Events") FOnSkillPointsChanged OnSkillPointsChanged; UPROPERTY(BlueprintAssignable, Category = "Skill Events") FOnSkillPurchased OnSkillPurchased; UPROPERTY(BlueprintAssignable, Category = "Skill Events") FOnSkillSelectionChanged OnSkillSelectionChanged; UPROPERTY(BlueprintAssignable, Category = "Skill Events") FOnSkillStateChanged OnSkillStateChanged; UPROPERTY(BlueprintAssignable, Category = "Skill Events") FOnSelectionError OnSelectionError; private: // Internal helper functions void UpdateSkillStates(); void UpdateSelectionCost(); bool ArePrerequisitesMet(const FSkillNodeData& SkillData, bool bIncludeSelected = false) const; bool HasChildrenPurchased(FName SkillID) const; void ApplySkillEffects(const FSkillNodeData& SkillData); void RemoveSkillEffects(const FSkillNodeData& SkillData); void CascadeDeselectDependents(FName SkillID); };