Compare commits

...

3 Commits

Author SHA1 Message Date
893a0743dd 重构旧的采集系统和掉落系统 #3
Task和Ability系统初步接入,Task系统实现移动
2025-11-02 15:51:28 +08:00
39b100acff 优化角色生成位置 #2
同时也将地图扩大为128 * 128
2025-10-30 23:11:08 +08:00
239425c47d UI框架调整,主界面重做 #16
初步调整
2025-10-28 23:51:17 +08:00
77 changed files with 1099 additions and 41 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,85 @@
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 List<UBusyWidgetSatietyBar> SatietyBars = new();
protected List<UBusyWidgetHealthBar> HealthBars = new();
protected UBusyRoleStateController? UIController;
public override void Construct()
{
base.Construct();
for (int i = 0; i < 5; ++i)
{
if (GetWidget($"WBP_SatietyBar_{i}") is UBusyWidgetSatietyBar Bar)
{
SatietyBars.Add(Bar);
}
if (GetWidget("WBP_HealthBar") is UBusyWidgetHealthBar HpBar)
{
HealthBars.Add(HpBar);
}
}
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);
foreach (UBusyWidgetSatietyBar Bar in SatietyBars)
{
Bar.SetSatietyConfig(CurSatiety, MaxSatiety);
}
}
public override void Destruct()
{
base.Destruct();
UIController.OnAttributeChangeDelegate -= OnAttributeChanged;
}
public void SetSatiety(float Satiety)
{
foreach(UBusyWidgetSatietyBar Bar in SatietyBars)
{
Bar.OnSatietyChanged(Satiety);
}
}
[UFunction()]
protected void OnAttributeChanged(FName AttributeName, float NewValue, float OldValue)
{
if (AttributeName == "Hunger")
{
SetSatiety(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

@ -2,6 +2,7 @@
#include "Camera/CameraComponent.h"
#include "Data/BusyPawnConfig.h"
#include "GameFramework/SpringArmComponent.h"
#include "Level/RoleTask/BusyTaskSubSystem.h"
ABusyPlayerRole::ABusyPlayerRole()
@ -45,3 +46,51 @@ void ABusyPlayerRole::InitPawnAttributes(const struct FBusyPawnBaseConfig& Confi
// }
}
void ABusyPlayerRole::AddTask(UBusyRoleTaskBase* RoleTask)
{
if (RoleTask)
{
RoleTasks.Enqueue(RoleTask);
}
ProcessTasks();
}
void ABusyPlayerRole::ProcessTasks()
{
const auto PeekPtr = RoleTasks.Peek();
if (PeekPtr == nullptr)
{
// 已经没有任务了开启一个6s的回家定时器
if (GoBackTimerHandle.IsValid())
{
return;
}
GetWorldTimerManager().SetTimer(GoBackTimerHandle, [this]()
{
if (UBusyTaskSubSystem* SubSystem = UBusyTaskSubSystem::Get(this))
{
AddTask(SubSystem->CreateGoBackTask());
}
}, 6.0, false);
return;
}
GetWorldTimerManager().ClearTimer(GoBackTimerHandle); // 有任务的情况,清掉回家的定时器
const TWeakObjectPtr<UBusyRoleTaskBase>& Task = *PeekPtr;
if (!Task.Get()) // Task无效pop掉再指向一次
{
RoleTasks.Pop();
ProcessTasks();
return;
}
if (Task->IsActive()) // 正在激活, 直接返回
{
return;
}
Task->Activate(this, FOnBusyRoleTaskFinished::CreateLambda([this](bool bIsCancel)
{
RoleTasks.Pop();
ProcessTasks();
}));
}

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

@ -109,6 +109,7 @@ void UBusyPawnMovement::MoveTick(const float DeltaTime)
if (NewLocation.Equals(CurrentLocation))
{
BusyMoveState = EBusyMoveState::None;
OnMoveFinished.Broadcast();
}
else
{

View File

@ -4,6 +4,7 @@
#include "EnhancedInput/Public/EnhancedInputSubsystems.h"
#include "Level/LevelPlayerState.h"
#include "EnhancedInput/Public/EnhancedInputComponent.h"
#include "Level/RoleTask/BusyTaskSubSystem.h"
inline static void BindEnhancedInputAction(UEnhancedInputComponent* EnhancedInput, const UInputAction* Action, UObject* Target, const FName& Callback)
@ -181,6 +182,20 @@ void ALevelPlayerController::OnSwitchRole(const FInputActionValue& Value)
}
}
void ALevelPlayerController::OnMove(const FInputActionValue& Value)
{
if (ABusyPlayerRole* ControlledRole = GetControlledRole())
{
if (UBusyTaskSubSystem* SubSystem = UBusyTaskSubSystem::Get(this))
{
if (FVector2D CursorPosition; GetCursorPosition(CursorPosition))
{
ControlledRole->AddTask(SubSystem->CreateMoveTask(CursorPosition));
}
}
}
}
void ALevelPlayerController::OnRoleSkillTriggered(FGameplayTag GameplayTag)
{
AActor* ControlledRole = GetControlledRole();

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,29 @@
#include "Level/RoleTask/BusyRoleMoveTask.h"
#include "Level/Actor/BusyPlayerRole.h"
void UBusyRoleMoveTask::Activate(ABusyPlayerRole* Owner, const FOnBusyRoleTaskFinished& Delegate)
{
UBusyRoleTaskBase::Activate(Owner, Delegate);
Owner->MovementComponent->MoveTo(TargetLocation);
Owner->MovementComponent->OnMoveFinished.AddDynamic(this, &ThisClass::OnMoveFinished);
}
void UBusyRoleMoveTask::Cancel()
{
UBusyRoleTaskBase::Cancel();
}
void UBusyRoleMoveTask::SetTargetLocation(const FVector2D& NewLocation)
{
TargetLocation = NewLocation;
}
void UBusyRoleMoveTask::OnMoveFinished()
{
if (OnFinishedDelegate.IsBound())
{
OnFinishedDelegate.Execute(false);
}
TaskOwner->MovementComponent->OnMoveFinished.RemoveDynamic(this, &ThisClass::OnMoveFinished);
bIsActive = false;
}

View File

@ -0,0 +1 @@
#include "Level/RoleTask/BusyRolePickTask.h"

View File

@ -0,0 +1,57 @@
#include "Level/RoleTask/BusyTaskSubSystem.h"
#include "Level/RoleTask/BusyRoleMoveTask.h"
bool UBusyRoleTaskBase::IsActive() const
{
return bIsActive;
}
void UBusyRoleTaskBase::Activate(ABusyPlayerRole* Owner, const FOnBusyRoleTaskFinished& Delegate)
{
TaskOwner = Owner;
bIsActive = true;
OnFinishedDelegate = Delegate;
}
void UBusyRoleTaskBase::Cancel()
{
bIsActive = false;
if (OnFinishedDelegate.IsBound())
{
OnFinishedDelegate.Execute(true);
}
}
UBusyTaskSubSystem* UBusyTaskSubSystem::Get(const UObject* Object)
{
const UWorld* World = Object->GetWorld();
return World->GetSubsystem<UBusyTaskSubSystem>();
}
UBusyRoleTaskBase* UBusyTaskSubSystem::CreatePickTask(const ABusyStaticResource* Resource)
{
return nullptr;
}
UBusyRoleTaskBase* UBusyTaskSubSystem::CreateMoveTask(const FVector2D& TargetPosition)
{
UBusyRoleMoveTask* Task = NewObject<UBusyRoleMoveTask>();
Task->SetTargetLocation(TargetPosition);
return Task;
}
UBusyRoleTaskBase* UBusyTaskSubSystem::CreateGoBackTask()
{
return nullptr;
}
UBusyRoleTaskBase* UBusyTaskSubSystem::CreateBuildTask(const FName& BuildingID, const FVector2D& TargetPosition)
{
return nullptr;
}
UBusyRoleTaskBase* UBusyTaskSubSystem::CreateDismantleTask(const FName& BuildingID, const FVector2D& TargetPosition)
{
return nullptr;
}

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

@ -11,6 +11,8 @@ GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
class UBusyRoleTaskBase;
UCLASS(Blueprintable, BlueprintType)
class UBusyPlayerRoleAttributeSet: public UBusyPawnAttributeSet
{
@ -45,11 +47,18 @@ public:
virtual void BeginPlay() override;
virtual void InitPawnAttributes(const struct FBusyPawnBaseConfig& Config)override;
virtual void OnMoveDirectionChanged_Implementation(const FVector2D& InDirection) override {}
public:
UFUNCTION(BlueprintCallable)
void AddTask(UBusyRoleTaskBase* RoleTask);
protected:
void ProcessTasks();
protected:
/*--------------------相机相关--------------------------*/
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
@ -57,4 +66,9 @@ protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
TObjectPtr<class UCameraComponent> CameraComponent;
protected:
FTimerHandle GoBackTimerHandle;
TQueue<TWeakObjectPtr<UBusyRoleTaskBase>> RoleTasks;
};

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

@ -34,6 +34,7 @@ enum class EBusyMoveState: uint8
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FBusyMoveFinishedSignature);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FBusyMoveDirectionChanged, FVector2D, Direction);
@ -107,6 +108,9 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
FBusyMoveDirectionChanged MoveDirectionChangedDelegate;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Movement")
FBusyMoveFinishedSignature OnMoveFinished;
protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Movement")
EBusyMoveState BusyMoveState = EBusyMoveState::None;

View File

@ -97,6 +97,9 @@ public:
UFUNCTION()
void OnSwitchRole(const FInputActionValue& Value);
UFUNCTION()
void OnMove(const FInputActionValue& Value);
UFUNCTION()
void OnRoleSkillTriggered(FGameplayTag GameplayTag);

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,22 @@
#pragma once
#include "Level/RoleTask/BusyTaskSubSystem.h"
#include "BusyRoleMoveTask.generated.h"
UCLASS()
class UBusyRoleMoveTask : public UBusyRoleTaskBase
{
GENERATED_BODY()
public:
virtual void Activate(ABusyPlayerRole* Owner, const FOnBusyRoleTaskFinished& Delegate) override;
virtual void Cancel() override;
public:
void SetTargetLocation(const FVector2D& NewLocation);
private:
UFUNCTION()
void OnMoveFinished();
private:
FVector2D TargetLocation = FVector2D();
};

View File

@ -0,0 +1,7 @@
#pragma once
class BusyRolePickTask
{
public:
};

View File

@ -0,0 +1,69 @@
#pragma once
#include "Level/Actor/BusyPlayerRole.h"
#include "BusyTaskSubSystem.generated.h"
class ABusyStaticResource;
DECLARE_DELEGATE_OneParam(FOnBusyRoleTaskFinished, bool);
enum EBusyRoleTaskType
{
Unknown = 0,
MoveTask = 1,
GobackTask = 2,
PickTask = 3,
BuildTask = 4,
DismantleTask = 5,
};
UCLASS()
class UBusyRoleTaskBase : public UObject
{
GENERATED_BODY()
public:
bool IsActive() const;
virtual void Activate(ABusyPlayerRole* Owner, const FOnBusyRoleTaskFinished &Delegate);
virtual void Cancel();
protected:
bool bIsActive;
EBusyRoleTaskType TaskType;
TWeakObjectPtr<ABusyPlayerRole> TaskOwner;
FOnBusyRoleTaskFinished OnFinishedDelegate;
};
UCLASS(BlueprintType)
class UBusyTaskSubSystem : public UWorldSubsystem
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static UBusyTaskSubSystem* Get(const UObject* Object);
public:
UFUNCTION(BlueprintCallable)
UBusyRoleTaskBase* CreatePickTask(const ABusyStaticResource* Resource);
UFUNCTION(BlueprintCallable)
UBusyRoleTaskBase* CreateMoveTask(const FVector2D& TargetPosition);
UFUNCTION(BlueprintCallable)
UBusyRoleTaskBase* CreateGoBackTask();
UFUNCTION(BlueprintCallable)
UBusyRoleTaskBase* CreateBuildTask(const FName& BuildingID, const FVector2D& TargetPosition);
UFUNCTION(BlueprintCallable)
UBusyRoleTaskBase* CreateDismantleTask(const FName& BuildingID, const FVector2D& TargetPosition);
};

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:
};