Compare commits

3 Commits

Author SHA1 Message Date
39b100acff 优化角色生成位置 #2
同时也将地图扩大为128 * 128
2025-10-30 23:11:08 +08:00
239425c47d UI框架调整,主界面重做 #16
初步调整
2025-10-28 23:51:17 +08:00
60596f2772 Merge pull request 'CSharpMigrate' (#15) from CSharpMigrate into main
Reviewed-on: #15
2025-10-26 21:51:42 +08:00
57 changed files with 797 additions and 40 deletions

View File

@ -15,8 +15,8 @@ ManualIPAddress=
[/Script/EngineSettings.GameMapsSettings]
GlobalDefaultGameMode=/Game/Blueprint/Bp_BusyGameMode.Bp_BusyGameMode_C
GameInstanceClass=/Script/BusyRabbit.BusyGameInstance
EditorStartupMap=/Game/Level/HomeLand.HomeLand
GameDefaultMap=/Game/Level/HomeLand.HomeLand
EditorStartupMap=/Game/Level/FalconPlain.FalconPlain
GameDefaultMap=/Game/Level/FalconPlain.FalconPlain
[/Script/Engine.RendererSettings]
r.Mobile.AntiAliasing=0

View File

@ -1,3 +1,4 @@
;METADATA=(Diff=true, UseCommands=true)
[/Script/GameplayTags.GameplayTagsSettings]
ImportTagsFromConfig=True
WarnOnInvalidTags=True
@ -57,6 +58,9 @@ NetIndexFirstBitSegment=16
+GameplayTagList=(Tag="Ingredient.Vegetable.Carrot",DevComment="胡萝卜")
+GameplayTagList=(Tag="Recover.Role.Health",DevComment="回复生命值")
+GameplayTagList=(Tag="Recover.Role.Hunger",DevComment="恢复饥饿值")
+GameplayTagList=(Tag="Resource",DevComment="资源")
+GameplayTagList=(Tag="Resource.Building",DevComment="建筑物")
+GameplayTagList=(Tag="Resource.Building.Campsite",DevComment="营地")
+GameplayTagList=(Tag="Status.Role.Invincible",DevComment="不掉血标签")
+GameplayTagList=(Tag="Terrain.Desert",DevComment="荒漠地形")
+GameplayTagList=(Tag="Terrain.Forest",DevComment="森林")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/UI/Level/bar.uasset Normal file

Binary file not shown.

Binary file not shown.

View File

@ -19,7 +19,7 @@
"**/bin": true,
"**/obj": true
},
"dotnet.defaultSolution": "Script/${workspaceFolderBasename}.sln",
"dotnet.defaultSolution": "Script/ManagedBusyRabbit/ManagedBusyRabbit.sln",
"omnisharp.enableRoslynAnalyzers": true,
"omnisharp.enableEditorConfigSupport": true,
"csharp.suppressDotnetRestoreNotification": false

View File

@ -47,9 +47,6 @@ public class UFoxUltimate : UBusyGameAbility
ASC = AbilitySystemLibrary.GetAbilitySystemComponent(Owner) as UBusyAbilitySystemComponent;
if (FoxData == null || ASC == null) return false;
PrintString("asdafdasdf");
if (bIsEventBinded) return true;
TDelegate<GameplayTagAddOrRemoveDelegate> Delegate = new TDelegate<GameplayTagAddOrRemoveDelegate>();
Delegate.BindUFunction(this, "OnGamePlayTagAddOrRemove");

View File

@ -0,0 +1,29 @@
using UnrealSharp.Engine;
using UnrealSharp.Attributes;
using UnrealSharp.BusyRabbit;
using UnrealSharp;
using UnrealSharp.UMG;
namespace Level.GameSettings;
[UClass]
public class ABusyLevelHud : APW_UIFrameworkHud
{
[UProperty(PropertyFlags.EditDefaultsOnly)]
public TSubclassOf<UPW_WidgetPanel> WidgetClass { set; get; }
protected override void BeginPlay()
{
base.BeginPlay();
}
protected override void OnResourceLoaded()
{
var widget = CreateWidget(WidgetClass);
UIManager.PushWidgetPanel(widget);
}
}

View File

@ -1,5 +1,7 @@
using UnrealSharp;
using UnrealSharp.Attributes;
using UnrealSharp.BusyRabbit;
using UnrealSharp.CoreUObject;
using UnrealSharp.Engine;
namespace Level.GameSettings;
@ -11,7 +13,17 @@ public class ABusyLevelPlayerState : ALevelPlayerState
{
base.BeginPlay();
APlayerController pc = UGameplayStatics.GetPlayerController(0);
var role = CreateRoleRoster(pc) as APawn;
pc.Possess(role);
UGameplayStatics.GetAllActorsWithTag("Resource.Building.Campsite", out IList<AActor> FoundActors);
FVector SpawnLocation = new FVector(0, 0, 10);
if (FoundActors.Count > 0)
{
SpawnLocation = FoundActors[0].ActorLocation;
}
if(CreateRoleRoster(pc) is APawn Role)
{
pc.Possess(Role);
Role.SetActorLocation(SpawnLocation);
}
}
}

View File

@ -38,10 +38,7 @@ public class ABusyFoxRole : ABusyPlayerRole
protected override void EndPlay(EEndPlayReason endPlayReason)
{
base.EndPlay(endPlayReason);
PrintString("haha1");
MovementComponent.MoveDirectionChangedDelegate.Remove(OnRoleMoveDirectionChanged);
PrintString("haha2");
}
[UFunction()]

View File

@ -0,0 +1,76 @@
using UnrealSharp.Engine;
using UnrealSharp.Attributes;
using UnrealSharp.BusyRabbit;
using UnrealSharp.GameplayAbilities;
using UnrealSharp;
using UnrealSharp.CoreUObject;
namespace UI.Level.Controllers;
[UMultiDelegate]
public delegate void OnUIAttributeChange(FName AttributeName, float NewValue, float OldValue);
[UClass]
public class UBusyRoleStateController : UPW_UIController
{
[UProperty()]
public TMulticastDelegate<OnUIAttributeChange> OnAttributeChangeDelegate { get; set; }
protected override void OnUIControllerInitialized()
{
if (UGameplayStatics.GetPlayerController(0) is ALevelPlayerController PC)
{
ABusyPlayerRole Role = PC.ControlledRole;
if (AbilitySystemLibrary.GetAbilitySystemComponent(Role) is UBusyAbilitySystemComponent ASC)
{
RegisterAttributeListener(ASC, "Health");
RegisterAttributeListener(ASC, "Hunger");
}
}
}
public float GetControlledAttribute(FName AttributeName)
{
if (UGameplayStatics.GetPlayerController(0) is ALevelPlayerController PC)
{
ABusyPlayerRole Role = PC.ControlledRole;
if (AbilitySystemLibrary.GetAbilitySystemComponent(Role) is UBusyAbilitySystemComponent ASC)
{
FGameplayAttribute Attribute = UBusyAscLibrary.GetAttribute(Role.Attributes, AttributeName);
return ASC.GetGameplayAttributeValue(Attribute, out bool IsFound);
}
}
return 0;
}
public float GetRoleAttribute(ABusyPawnBase Pawn, FName Attribute)
{
return 0;
}
protected void RegisterAttributeListener(UBusyAbilitySystemComponent ASC, FName AttributeName)
{
TDelegate<OnBusyAttributeChange> Delegate = new TDelegate<OnBusyAttributeChange>();
Delegate.BindUFunction(this, "OnAttributeChange");
ASC.BindEventToAttributeChange(typeof(UBusyPlayerRoleAttributeSet), AttributeName, Delegate);
}
[UFunction()]
protected void OnAttributeChange(FName AttributeName, float NewValue, float OldValue)
{
OnAttributeChangeDelegate.Invoke(AttributeName, NewValue, OldValue);
}
protected override void OnUIControllerDestroy()
{
base.OnUIControllerDestroy();
}
}

View File

@ -0,0 +1,71 @@
using UnrealSharp.Attributes;
using UnrealSharp.BusyRabbit;
using UnrealSharp.UMG;
namespace UI.Level.StateBar;
[UClass]
public class UBusyWidgetHealthBar : UPW_MinimalWidget
{
[UProperty(PropertyFlags.EditAnywhere)]
public float Percent { get; set; }
[UProperty(PropertyFlags.EditAnywhere)]
public float Test { get; set; }
protected UProgressBar? HpBarHurt { get { return GetWidget("HpBarHurt") as UProgressBar; } }
protected UProgressBar? HpBarHealth { get { return GetWidget("HpBarHealth") as UProgressBar; } }
protected UProgressBar? HpBarNormal { get { return GetWidget("HpBarNormal") as UProgressBar; } }
protected USizeBox ? SizeboxMain { get { return GetWidget("SizeboxMain") as USizeBox; } }
[UProperty(PropertyFlags.EditAnywhere)]
public float MaxHp { get; set; }
[UProperty(PropertyFlags.EditAnywhere)]
public float CurHp { get; set; }
[UProperty(PropertyFlags.EditAnywhere)]
public float Width { get; set; }
[UProperty(PropertyFlags.EditAnywhere)]
public float Height { get; set; }
protected float LastHp = 200;
public override void PreConstruct(bool isDesignTime)
{
SetHpConfig(CurHp, MaxHp);
RefreshHealthBarDisplay();
}
public override void Construct()
{
base.Construct();
SetHpConfig(180, 200);
}
public void SetHpConfig(float CurHp, float MaxHp)
{
LastHp = CurHp;
this.CurHp = CurHp;
this.MaxHp = MaxHp;
RefreshHealthBarDisplay();
}
protected void RefreshHealthBarDisplay()
{
if (HpBarHealth == null || HpBarHurt == null || HpBarNormal == null || SizeboxMain == null)
{
return;
}
HpBarHurt.Visibility = ESlateVisibility.Collapsed;
HpBarHealth.Visibility = ESlateVisibility.Collapsed;
HpBarNormal.Percent = MaxHp != 0 ? (CurHp / MaxHp) : 0;
SizeboxMain.WidthOverride = Width;
SizeboxMain.HeightOverride = Height;
}
}

View File

@ -0,0 +1,36 @@
using UnrealSharp.Engine;
using UnrealSharp.Attributes;
using UnrealSharp.BusyRabbit;
using UnrealSharp.UMG;
namespace UI.Level.StateBar;
[UClass]
public class UBusyWidgetSatietyBar : UPW_MinimalWidget
{
protected UProgressBar? SatietyBar { get { return GetWidget("SatietyBar") as UProgressBar; } }
protected float CurrSatiety;
protected float MaxSatiety;
public void SetSatietyConfig(float CurrSatiety, float MaxSatiety)
{
this.MaxSatiety = MaxSatiety;
this.CurrSatiety = CurrSatiety;
RefreshDisplay();
}
public void OnSatietyChanged(float CurSatiety)
{
this.CurrSatiety = CurSatiety;
RefreshDisplay();
}
public void RefreshDisplay()
{
float Percent = MaxSatiety > 0 ? CurrSatiety / MaxSatiety : 0;
if (SatietyBar != null)
{
SatietyBar.Percent = Percent;
}
}
}

View File

@ -0,0 +1,55 @@
using UnrealSharp.Engine;
using UI.Level.Controllers;
using UnrealSharp.Attributes;
using UnrealSharp.BusyRabbit;
using UnrealSharp;
namespace UI.Level.StateBar;
[UClass]
public class UBusyWidgetStateBar : UPW_MinimalWidget
{
protected UBusyWidgetHealthBar? WBP_HealthBar { get { return GetWidget("WBP_HealthBar") as UBusyWidgetHealthBar; } }
protected UBusyWidgetSatietyBar? WBP_SatietyBar { get { return GetWidget("WBP_SatietyBar") as UBusyWidgetSatietyBar; } }
protected UBusyRoleStateController? UIController;
public override void Construct()
{
base.Construct();
WBP_SatietyBar.SetSatietyConfig(100, 200);
UIController = UUIFunctionLibrary.GetUIController(this, "RoleState") as UBusyRoleStateController;
InitRoleAttribute();
UIController.OnAttributeChangeDelegate += OnAttributeChanged;
}
public void InitRoleAttribute()
{
float CurHealth = UIController.GetControlledAttribute("Health");
float MaxHealth = UIController.GetControlledAttribute("MaxHealth");
float CurSatiety = UIController.GetControlledAttribute("Hunger");
float MaxSatiety = UIController.GetControlledAttribute("MaxHunger");
WBP_HealthBar.SetHpConfig(CurHealth, MaxHealth);
WBP_SatietyBar.SetSatietyConfig(CurSatiety, MaxSatiety);
}
public override void Destruct()
{
base.Destruct();
UIController.OnAttributeChangeDelegate -= OnAttributeChanged;
}
[UFunction()]
protected void OnAttributeChanged(FName AttributeName, float NewValue, float OldValue)
{
if (AttributeName == "Hunger")
{
WBP_SatietyBar.OnSatietyChanged(NewValue);
}
}
}

View File

@ -4,6 +4,7 @@
#include "AbilitySystemGlobals.h"
#include "GameplayEffectTypes.h"
#include "Gas/BusyGameAbility.h"
#include "Level/Actor/BusyPawnBase.h"
UBusyAbilityDataAssetBase* UBusyAscLibrary::GetAbilityDataAssetByEffect(const FGameplayEffectSpec& Spec)
{
@ -28,3 +29,12 @@ FGameplayEffectSpecHandle UBusyAscLibrary::MakeGameplayEffectSpecHandle(const UA
FGameplayEffectSpec* NewSpec = new FGameplayEffectSpec(Effect, ContextHandle, Level);
return FGameplayEffectSpecHandle(NewSpec);
}
FGameplayAttribute UBusyAscLibrary::GetAttribute(const UBusyPawnAttributeSet* AttributeSet, const FName& AttributeName)
{
if (FProperty* Prop = FindFieldChecked<FProperty>(AttributeSet->GetClass(), AttributeName))
{
return Prop;
}
return nullptr;
}

View File

@ -0,0 +1,19 @@
#include "BlueprintLibrary/UIFunctionLibrary.h"
#include "UIFramework/UIFrameworkHud.h"
UPW_UIController* UUIFunctionLibrary::GetUIController(const UObject* Object, const FName& Name)
{
if (Object == nullptr) return nullptr;
const UWorld* World = Object->GetWorld();
if (World == nullptr) return nullptr;
const APlayerController* PC = World->GetFirstPlayerController();
if (PC == nullptr) return nullptr;
if (APW_UIFrameworkHud* Hud = Cast<APW_UIFrameworkHud>(PC->GetHUD()))
{
return Hud->GetUIController(Name);
}
return nullptr;
}

View File

@ -1,6 +1,8 @@
#include "Level/Actor/BusyStaticResource.h"
#include "SpineSkeletonRendererComponent.h"
#include "SpineSkeletonAnimationComponent.h"
#include "BusyGameplayLibrary.h"
#include "Data/BusyResourceConfig.h"
ABusyStaticResource::ABusyStaticResource()
{
@ -21,4 +23,19 @@ void ABusyStaticResource::BeginPlay()
Super::BeginPlay();
SpineAnimationComponent->SetSkin("default");
SpineAnimationComponent->SetAnimation(0, "idle", true);
if (ResourceName.IsNone()) return;
const UDataTable* ResourceTable = UBusyGameplayLibrary::GetGameDataTable("ResourceConfig");
if (!ResourceTable) return;
FBusyResourceConfig* Config = ResourceTable->FindRow<FBusyResourceConfig>(
ResourceName, *FString::Printf(TEXT("ABusyStaticResource::BeginPlay Find Config: %s"), *ResourceName.ToString())
);
if (Config == nullptr) return;
for (const FGameplayTag& Tag : Config->GameplayTags)
{
Tags.AddUnique(Tag.GetTagName());
}
}

View File

@ -1 +1,16 @@
#include "Level/Actor/Components/BusyAbilitySystemComponent.h"
void UBusyAbilitySystemComponent::BindEventToAttributeChange(const UClass* AttributeSetClass, const FName& AttributeName, FOnBusyAttributeChange Delegate)
{
FProperty* Prop = FindFieldChecked<FProperty>(AttributeSetClass, AttributeName);
if (Prop == nullptr)
{
return;
}
FOnGameplayAttributeValueChange &OnAttributeChange = GetGameplayAttributeValueChangeDelegate(Prop);
OnAttributeChange.AddLambda([AttributeName, Delegate](const FOnAttributeChangeData& Data)
{
Delegate.ExecuteIfBound(AttributeName, Data.NewValue, Data.OldValue);
});
}

View File

@ -113,7 +113,7 @@ void UStaticResourceLayerComponent::GenerateResourcePoints(TArray<FVector2D>& Ou
const IGameMapInterface * MapInterface = Cast<IGameMapInterface>(Owner);
if (!MapInterface) return;
float MapWidth, MapHeight;
int32 MapWidth, MapHeight;
MapInterface->Execute_GetMapSize(Owner, MapWidth, MapHeight);
const UMitchellBestCandidate *PointCreator = NewObject<UMitchellBestCandidate>();

View File

@ -171,11 +171,25 @@ UTerrainLayerComponent::UTerrainLayerComponent()
void UTerrainLayerComponent::BeginPlay()
{
Super::BeginPlay();
AActor* Owner = GetOwner();
if (IGameMapInterface* GameMap = Cast<IGameMapInterface>(Owner))
{
GameMap->Execute_GetMapSize(Owner, MapWidth, MapHeight);
TileSetSize = GameMap->Execute_GetMapFieldSize(Owner);
}
else
{
MapWidth = MapHeight = 32;
TileSetSize = 128;
}
SetupTerrainActors();
TArray<int32> Priority;
TArray<FGameplayTag> TerrainData;
TArray<FGameplayTag> TerrainTypes;
for (auto TileSetConfig : TileSetConfigs)
{
TerrainTypes.Add(TileSetConfig.Key);

View File

@ -11,7 +11,7 @@ AGameMapActor::AGameMapActor()
this->RootComponent = SceneComp;
}
void AGameMapActor::GetMapSize_Implementation(float& OutWidth, float& OutHeight)
void AGameMapActor::GetMapSize_Implementation(int32& OutWidth, int32& OutHeight)
{
OutWidth = MapWidth;
OutHeight = MapHeight;
@ -22,7 +22,7 @@ FGameplayTag AGameMapActor::GetTerrainAt_Implementation(const float X, const flo
return TerrainLayer->GetTerrainAt(X, Y);
}
float AGameMapActor::GetMapFieldSize_Implementation()
int32 AGameMapActor::GetMapFieldSize_Implementation()
{
return MapFieldSize;
}

View File

@ -0,0 +1,6 @@
#include "UIFramework/MinimalWidget.h"
UWidget* UPW_MinimalWidget::GetWidget(const FName& Name)const
{
return GetWidgetFromName(Name);
}

View File

@ -0,0 +1,22 @@
#include "UIFramework/RootWidget.h"
#include "Blueprint/WidgetTree.h"
#include "UIFramework/WidgetPanel.h"
#include "Components/Overlay.h"
#include "Components/OverlaySlot.h"
bool UPW_RootWidget::PushWidget(UPW_WidgetPanel* Widget)const
{
if (UOverlaySlot* OverlaySlot = Cast<UOverlaySlot>(MainOverlay->AddChild(Widget)))
{
OverlaySlot->SetHorizontalAlignment(HAlign_Fill);
OverlaySlot->SetVerticalAlignment(VAlign_Fill);
return true;
}
return false;
}
bool UPW_RootWidget::RemoveWidget(UPW_WidgetPanel* Widget)const
{
return MainOverlay->RemoveChild(Widget);
}

View File

@ -0,0 +1,21 @@
#include "UIFramework/UIController.h"
void UPW_UIController::InitUIController(APW_UIFrameworkHud* UIHud)
{
Hud = UIHud;
OnUIControllerInitialized();
}
void UPW_UIController::DestroyUIController()
{
OnUIControllerDestroy();
}
void UPW_UIController::OnUIControllerInitialized_Implementation()
{
}
void UPW_UIController::OnUIControllerDestroy_Implementation()
{
}

View File

@ -0,0 +1,83 @@
#include "UIFramework/UIFrameworkHud.h"
#include "UIFramework/RootWidget.h"
#include "UIFramework/UIController.h"
DEFINE_LOG_CATEGORY(LogUIHud)
APW_UIFrameworkHud::APW_UIFrameworkHud()
{
UIManager = CreateDefaultSubobject<UPW_UIManager>(TEXT("UIManager"));
}
void APW_UIFrameworkHud::BeginPlay()
{
if (RootWidgetClass)
{
UPW_RootWidget* Root = NewObject<UPW_RootWidget>(this, RootWidgetClass, FName("RootWidget"));
UIManager->AttachUIDisplay(Root);
}
for (const TPair Pair : UIControllerClasses)
{
TSoftClassPtr<UPW_UIController> ControllerClass = Pair.Value;
if (ControllerClass.IsNull()) continue;
auto Delegate = FLoadSoftObjectPathAsyncDelegate::CreateLambda([this, Pair](const FSoftObjectPath& Path, UObject* Object)
{
if (const UClass* UIControllerClass = Cast<UClass>(Object))
{
if (UPW_UIController* NewController = NewObject<UPW_UIController>(this, UIControllerClass))
{
UIControllers.Add(Pair.Key, NewController);
NewController->InitUIController(this);
}
}
TryNotifyResourceLoaded();
});
if (ControllerClass.LoadAsync(Delegate) == -1)
{
UE_LOG(LogUIHud, Error, TEXT("APW_UIFrameworkHud::BeginPlay can't load class: %s"), *ControllerClass.GetAssetName());
}
}
Super::BeginPlay();
}
void APW_UIFrameworkHud::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
UIManager->DetachUIDisplay();
for (const TPair Pair: UIControllers)
{
if (UPW_UIController* Controller = Pair.Value)
{
Controller->DestroyUIController();
}
}
UIControllers.Empty();
Super::EndPlay(EndPlayReason);
}
UPW_UIController* APW_UIFrameworkHud::GetUIController(const FName& Name)
{
if (UPW_UIController** ControllerPtr = UIControllers.Find(Name))
{
return *ControllerPtr;
}
return nullptr;
}
void APW_UIFrameworkHud::TryNotifyResourceLoaded()
{
if (UIControllers.Num() == UIControllerClasses.Num())
{
OnResourceLoaded();
}
}
void APW_UIFrameworkHud::OnResourceLoaded_Implementation()
{
}

View File

@ -0,0 +1,60 @@
#include "UIFramework/UIManager.h"
#include "Blueprint/UserWidget.h"
#include "UIFramework/RootWidget.h"
#include "UIFramework/UIFrameworkHud.h"
bool UPW_UIManager::AttachUIDisplay(UPW_RootWidget* InRootWidget)
{
if (InRootWidget)
{
RootWidget = InRootWidget;
InRootWidget->AddToViewport();
return true;
}
return false;
}
void UPW_UIManager::DetachUIDisplay()const
{
if (RootWidget.Get() != nullptr)
{
RootWidget->RemoveFromParent();
}
}
void UPW_UIManager::SetRootWidget(UPW_RootWidget* NewRootWidget)
{
RootWidget = NewRootWidget;
}
UPW_UIManager* UPW_UIManager::Get(UWorld* World)
{
if (World == nullptr) return nullptr;
const APlayerController* PC = World->GetFirstPlayerController();
if (PC == nullptr) return nullptr;
if (const APW_UIFrameworkHud * Hud = Cast<APW_UIFrameworkHud>(PC->GetHUD()))
{
return Hud->GetUIManager();
}
return nullptr;
}
bool UPW_UIManager::PushWidgetPanel(UPW_WidgetPanel* Panel)
{
if (RootWidget.Get() == nullptr) return false;
if (WidgetPanelStack.Contains(Panel))
{
WidgetPanelStack.Remove(Panel);
}
WidgetPanelStack.Push(Panel);
RootWidget->PushWidget(Panel);
return true;
}
void UPW_UIManager::PopWidgetPanel(UPW_WidgetPanel* Panel)
{
}

View File

@ -0,0 +1 @@
#include "UIFramework/WidgetPanel.h"

View File

@ -5,6 +5,7 @@
class UGameplayEffect;
struct FGameplayEffectSpec;
class UBusyPawnAttributeSet;
class UBusyAbilityDataAssetBase;
UCLASS()
@ -20,4 +21,8 @@ public:
UFUNCTION(BlueprintCallable)
static FGameplayEffectSpecHandle MakeGameplayEffectSpecHandle(const UAbilitySystemComponent* Asc, const UGameplayEffect* Effect, const float Level);
UFUNCTION(BlueprintCallable)
static FGameplayAttribute GetAttribute(const UBusyPawnAttributeSet* AttributeSet, const FName& AttributeName);
};

View File

@ -0,0 +1,15 @@
#pragma once
#include "UIFunctionLibrary.generated.h"
class UPW_UIController;
UCLASS(BlueprintType)
class UUIFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "UIFunctionLibrary")
static UPW_UIController* GetUIController(const UObject* Object, const FName& Name);
};

View File

@ -18,7 +18,7 @@ class BUSYRABBIT_API UBusyGameplayLibrary : public UBlueprintFunctionLibrary
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
UFUNCTION(BlueprintPure)
static UDataTable* GetGameDataTable(const FString& TableName);
UFUNCTION(BlueprintCallable)

View File

@ -70,7 +70,7 @@ public:
*
*/
UCLASS()
class BUSYRABBIT_API UPW_UserWidget : public UPW_SimpleWidget{
class BUSYRABBIT_API UPW_UserWidget : public UUserWidget{
GENERATED_BODY()
public:
// UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, DisplayName="是否全局唯一")

View File

@ -0,0 +1,15 @@
#pragma once
#include "GameplayTagContainer.h"
#include "BusyResourceConfig.generated.h"
USTRUCT(BlueprintType)
struct FBusyResourceConfig : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, DisplayName="备注")
FString Desc;
UPROPERTY(EditAnywhere, DisplayName="物品标签")
FGameplayTagContainer GameplayTags;
};

View File

@ -12,7 +12,7 @@ class UBusyPawnMovementComponent;
DECLARE_DYNAMIC_DELEGATE_TwoParams(FGameplayTagAddOrRemoveDelegate, const FGameplayTag&, Tag, const int32, Value);
#define MY_ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
#define BUSY_ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
@ -27,28 +27,29 @@ class UBusyPawnAttributeSet : public UAttributeSet
GENERATED_BODY()
public:
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData Health;
MY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, Health);
BUSY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, Health);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData MaxHealth;
MY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, MaxHealth);
BUSY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, MaxHealth);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData MoveSpeed;
MY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, MoveSpeed);
BUSY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, MoveSpeed);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData Damage;
MY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, Damage);
BUSY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, Damage);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes")
FGameplayAttributeData Defense;
MY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, Defense);
BUSY_ATTRIBUTE_ACCESSORS(UBusyPawnAttributeSet, Defense);
};
#undef MY_ATTRIBUTE_ACCESSORS
#undef BUSY_ATTRIBUTE_ACCESSORS
UCLASS()
@ -103,7 +104,7 @@ public:
FName PawnName;
protected:
public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TObjectPtr<UBusyPawnAttributeSet> Attributes = nullptr;

View File

@ -29,4 +29,8 @@ public:
TObjectPtr<USpineSkeletonAnimationComponent> SpineAnimationComponent;
/*-------------------------------------------------------------------*/
protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
FName ResourceName;
};

View File

@ -2,9 +2,13 @@
#include "AbilitySystemComponent.h"
#include "BusyAbilitySystemComponent.generated.h"
DECLARE_DYNAMIC_DELEGATE_ThreeParams(FOnBusyAttributeChange, const FName&, AttributeName, float, NewValue, float, OldValue);
UCLASS()
class UBusyAbilitySystemComponent : public UAbilitySystemComponent
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable)
void BindEventToAttributeChange(const UClass* AttributeSetClass, const FName& AttributeName, FOnBusyAttributeChange Delegate);
};

View File

@ -62,14 +62,9 @@ protected:
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MapWidth = 32;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MapHeight = 32;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 TileSetSize = 128;
int32 MapWidth = 32; // 用Owner的Width覆盖
int32 MapHeight = 32; // 用Owner的Height覆盖
int32 TileSetSize = 128; // 用Owner的Size覆盖
UPROPERTY(EditAnywhere, BlueprintReadOnly)
TMap<FGameplayTag, TObjectPtr<UPaperTileSet>> TileSetConfigs;

View File

@ -18,10 +18,10 @@ class IGameMapInterface
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
void GetMapSize(float &OutX, float &OutY);
void GetMapSize(int32 &OutX, int32 &OutY);
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
float GetMapFieldSize();
int32 GetMapFieldSize();
UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
FGameplayTag GetTerrainAt(const float X, const float Y);
@ -37,9 +37,9 @@ public:
AGameMapActor();
public:
virtual void GetMapSize_Implementation(float& OutWidth, float& OutHeight) override;
virtual void GetMapSize_Implementation(int32& OutWidth, int32& OutHeight) override;
virtual FGameplayTag GetTerrainAt_Implementation(const float X, const float Y) override;
virtual float GetMapFieldSize_Implementation() override;
virtual int32 GetMapFieldSize_Implementation() override;
public:
virtual void BeginPlay() override;
@ -58,11 +58,11 @@ public:
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly)
float MapWidth = 32;
int32 MapWidth = 32;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
float MapHeight = 32;
int32 MapHeight = 32;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
float MapFieldSize = 128;
int32 MapFieldSize = 128;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)

View File

@ -0,0 +1,17 @@
#pragma once
#include "Blueprint/UserWidget.h"
#include "MinimalWidget.generated.h"
UCLASS(Blueprintable, BlueprintType)
class UPW_MinimalWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Widget")
UWidget* GetWidget(const FName& Name)const;
};

View File

@ -0,0 +1,24 @@
#pragma once
#include "Blueprint/UserWidget.h"
#include "RootWidget.generated.h"
class UOverlay;
class UPW_WidgetPanel;
UCLASS()
class UPW_RootWidget : public UUserWidget
{
GENERATED_BODY()
public:
bool PushWidget(UPW_WidgetPanel* Widget)const;
bool RemoveWidget(UPW_WidgetPanel* Widget)const;
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Widget", meta=(BindWidget))
TObjectPtr<UOverlay> MainOverlay;
};

View File

@ -0,0 +1,30 @@
#pragma once
#include "UIController.generated.h"
class APW_UIFrameworkHud;
UCLASS(Blueprintable, BlueprintType)
class UPW_UIController : public UObject
{
GENERATED_BODY()
public:
void InitUIController(APW_UIFrameworkHud* UIHud);
void DestroyUIController();
protected:
UFUNCTION(BlueprintNativeEvent)
void OnUIControllerInitialized();
UFUNCTION(BlueprintNativeEvent)
void OnUIControllerDestroy();
protected:
UPROPERTY()
TObjectPtr<APW_UIFrameworkHud> Hud;
UPROPERTY()
TObjectPtr<APlayerController> PC;
};

View File

@ -0,0 +1,55 @@
#pragma once
#include "GameFramework/HUD.h"
#include "UIFramework/UIManager.h"
#include "UIFrameworkHud.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(LogUIHud, Log, All);
class UPW_UIController;
UCLASS(Blueprintable, BlueprintType)
class APW_UIFrameworkHud : public AHUD
{
GENERATED_BODY()
public:
APW_UIFrameworkHud();
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
public:
UPW_UIController* GetUIController(const FName& Name);
public:
UPW_UIManager* GetUIManager()const {return UIManager.Get();}
protected:
void TryNotifyResourceLoaded();
protected:
UFUNCTION(BlueprintNativeEvent)
void OnResourceLoaded();
protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
TSubclassOf<UPW_RootWidget> RootWidgetClass;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
TMap<FName, TSoftClassPtr<UPW_UIController>> UIControllerClasses;
protected:
UPROPERTY()
TObjectPtr<UPW_UIManager> UIManager;
UPROPERTY()
TMap<FName, UPW_UIController*> UIControllers;
};

View File

@ -0,0 +1,34 @@
#pragma once
#include "UIManager.generated.h"
class UPW_RootWidget;
class UPW_WidgetPanel;
UCLASS(BlueprintType)
class UPW_UIManager : public UObject
{
GENERATED_BODY()
public:
bool AttachUIDisplay(UPW_RootWidget* InRootWidget);
void DetachUIDisplay()const;
void SetRootWidget(UPW_RootWidget* NewRootWidget);
public:
UFUNCTION(BlueprintCallable)
static UPW_UIManager* Get(UWorld* World);
UFUNCTION(BlueprintCallable)
bool PushWidgetPanel(UPW_WidgetPanel* Panel);
UFUNCTION(BlueprintCallable)
void PopWidgetPanel(UPW_WidgetPanel* Panel);
protected:
UPROPERTY()
TArray<UPW_WidgetPanel*> WidgetPanelStack;
UPROPERTY()
TObjectPtr<UPW_RootWidget> RootWidget;
};

View File

@ -0,0 +1,13 @@
#pragma once
#include "UIFramework/MinimalWidget.h"
#include "WidgetPanel.generated.h"
UCLASS(BlueprintType, Blueprintable)
class UPW_WidgetPanel : public UPW_MinimalWidget
{
GENERATED_BODY()
public:
};