#pragma once #include "CoreMinimal.h" #include "MGameplayActor.h" #include "MConstructableBuilding.generated.h" class UArrowComponent; class UMHealthComponent; class UWidgetComponent; class AMConstructableBuilding; UENUM(BlueprintType) enum class EBuildingState : uint8 { Constructable UMETA(DisplayName = "Constructable"), UnConstructable UMETA(DisplayName = "UnConstructable"), UnderConstruction UMETA(DisplayName = "UnderConstruction"), Constructed UMETA(DisplayName = "Constructed") }; DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnBuildingStateChanged, AMConstructableBuilding*, Building, EBuildingState, NewState, EBuildingState, PreviousState); UCLASS() class MECHDEFENCE_API AMConstructableBuilding : public AMGameplayActor { GENERATED_BODY() public: AMConstructableBuilding(); protected: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) USkeletalMeshComponent* BaseBuildingMesh; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building", meta = (Tooltip = "The colour that will be used to show the building when it is at a valid location and can be constructed")) FLinearColor ConstructableColor; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building", meta = (Tooltip = "The colour that will be used to show the building when it is at a location where it cannot be constructed")) FLinearColor UnConstructableColor; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building", meta = (Tooltip = "The colour that will be used to show the building when it has been placed in the world and is under construction")) FLinearColor UnderConstructionColor; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building", meta = (Tooltip = "The material that will be used on all the meshes of this building while it is in an unconstructed state.")) UMaterialInterface* BuildingDynamicStateMaterial; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building") EBuildingState BuildingState; UPROPERTY(BlueprintReadWrite) TArray DefaultMaterials; UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "Building", meta = (Tooltip = "Dynamically created material that represents the current state of the building")) UMaterialInstanceDynamic* CurrentBuildingStateMaterial; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building", meta = (Tooltip = "List of actor types that will be checked against to determine if the building can be placed at a particular location")) TArray> InvalidActorsFilter; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building", meta = (Tooltip = "List of actor types that required to be overlapping with this building at a particular location if it is to be placed there")) TArray> RequiredOverlappingActorsFilter; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building", meta = (Tooltip = "This shape is used alongside InvalidActors filter to determine whether the building can be placed at its current location or not")) UShapeComponent* PlacementOverlapChecker; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building") UWidgetComponent* StatusIndicatorWidget; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building") UStaticMeshComponent* ArrowMesh; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Building") UMHealthComponent* HealthComponent; UFUNCTION() void HandleMeshComponentEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); UFUNCTION() void HandleMeshComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); UFUNCTION() void SetupHealthIndicator(); virtual void BeginPlay() override; UFUNCTION() void ConstructionCompleted(); FTimerHandle TimerHandle_UnderConstructionTimer; public: virtual void Tick(float DeltaTime) override; UFUNCTION(BlueprintCallable) void SetBuildingState(TEnumAsByte NewState); UFUNCTION(BlueprintImplementableEvent, meta = (Tooltip = "When building state is set, the base class only changes the state of the default mesh. Implement this function in blueprint to add other behaviour")) void BuildingStateSet(const EBuildingState& NewState, const EBuildingState& PreviousState); UFUNCTION(BlueprintCallable) void StartBuildingConstruction(float TimeToConstruct); UFUNCTION(BlueprintCallable, BlueprintNativeEvent) bool IsAtValidLocation(); UFUNCTION(BlueprintCallable) EBuildingState GetBuildingState() const { return BuildingState; }; UFUNCTION(BlueprintCallable, BlueprintNativeEvent) void SetHighlighted(bool Highlighted); UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Events") FOnBuildingStateChanged OnBuildingStateChanged; };