diff --git a/Config/DefaultGameplayTags.ini b/Config/DefaultGameplayTags.ini index e1885d6..017d2ed 100644 --- a/Config/DefaultGameplayTags.ini +++ b/Config/DefaultGameplayTags.ini @@ -8,11 +8,14 @@ FastReplication=False InvalidTagCharacters="\"\'," NumBitsForContainerSize=6 NetIndexFirstBitSegment=16 ++GameplayTagList=(Tag="Ability.Block.UltimatePlaying",DevComment="大招正在释放中") ++GameplayTagList=(Tag="Ability.Flags.Recast",DevComment="可以再次释放技能的标记") +GameplayTagList=(Tag="Ability.Role.AttributeConsume",DevComment="角色属性损耗debuff") +GameplayTagList=(Tag="Ability.Role.EatFood",DevComment="干饭") +GameplayTagList=(Tag="Ability.Role.Pick",DevComment="角色采集物品") +GameplayTagList=(Tag="Ability.Role.Recover",DevComment="角色状态恢复技能") +GameplayTagList=(Tag="Ability.Role.Roll",DevComment="角色无敌翻滚") ++GameplayTagList=(Tag="Ability.Role.Ultimate",DevComment="角色大招") +GameplayTagList=(Tag="Buff.Indispersible.HungerConsume",DevComment="饥饿值消耗,不可被驱散") +GameplayTagList=(Tag="Buff.RoleConsume.Health",DevComment="角色因饥饿掉血的debuff") +GameplayTagList=(Tag="Buff.RoleConsume.Hunger",DevComment="角色每秒钟的饥饿消耗") @@ -25,6 +28,8 @@ NetIndexFirstBitSegment=16 +GameplayTagList=(Tag="CookProcess.Diced",DevComment="切丁") +GameplayTagList=(Tag="CookProcess.Mashed",DevComment="切泥") +GameplayTagList=(Tag="CookProcess.Sliced",DevComment="切片操作") ++GameplayTagList=(Tag="Effect.Duration",DevComment="效果的持续时长") ++GameplayTagList=(Tag="Effect.Factor",DevComment="效果的乘法系数") +GameplayTagList=(Tag="GameItem.Building",DevComment="建筑物") +GameplayTagList=(Tag="GameItem.Food",DevComment="游戏内的可食用物品") +GameplayTagList=(Tag="Ingredient",DevComment="烹饪食材") diff --git a/Content/Blueprint/Level/GameMode/BP_BusyLevelPlayerController.uasset b/Content/Blueprint/Level/GameMode/BP_BusyLevelPlayerController.uasset index b55e2a4..ed262c6 100644 Binary files a/Content/Blueprint/Level/GameMode/BP_BusyLevelPlayerController.uasset and b/Content/Blueprint/Level/GameMode/BP_BusyLevelPlayerController.uasset differ diff --git a/Content/Blueprint/Level/GameMode/BP_BusyLevelPlayerState.uasset b/Content/Blueprint/Level/GameMode/BP_BusyLevelPlayerState.uasset index 275078b..66b284b 100644 Binary files a/Content/Blueprint/Level/GameMode/BP_BusyLevelPlayerState.uasset and b/Content/Blueprint/Level/GameMode/BP_BusyLevelPlayerState.uasset differ diff --git a/Content/Data/Input/Level/IMC_PlayerInputContext.uasset b/Content/Data/Input/Level/IMC_PlayerInputContext.uasset index 384d22c..b510dc7 100644 Binary files a/Content/Data/Input/Level/IMC_PlayerInputContext.uasset and b/Content/Data/Input/Level/IMC_PlayerInputContext.uasset differ diff --git a/Content/Data/Level/LevelRoleBaseConfig.uasset b/Content/Data/Level/LevelRoleBaseConfig.uasset index e70f4bb..8c0ee63 100644 Binary files a/Content/Data/Level/LevelRoleBaseConfig.uasset and b/Content/Data/Level/LevelRoleBaseConfig.uasset differ diff --git a/Content/Gas/Ability/Role/Fox/GA_FoxUltimate.uasset b/Content/Gas/Ability/Role/Fox/GA_FoxUltimate.uasset new file mode 100644 index 0000000..7459cdf Binary files /dev/null and b/Content/Gas/Ability/Role/Fox/GA_FoxUltimate.uasset differ diff --git a/Content/Gas/Effects/Role/Fox/GE_Accelerate.uasset b/Content/Gas/Effects/Role/Fox/GE_Accelerate.uasset new file mode 100644 index 0000000..c75672a Binary files /dev/null and b/Content/Gas/Effects/Role/Fox/GE_Accelerate.uasset differ diff --git a/Content/Gas/Effects/Role/Fox/GE_UltimateRecast.uasset b/Content/Gas/Effects/Role/Fox/GE_UltimateRecast.uasset new file mode 100644 index 0000000..ab983e2 Binary files /dev/null and b/Content/Gas/Effects/Role/Fox/GE_UltimateRecast.uasset differ diff --git a/Content/Lua/@types/BusyGameplayLibrary.d.lua b/Content/Lua/@types/BusyGameplayLibrary.d.lua index 6d7ddee..15f0fe0 100644 --- a/Content/Lua/@types/BusyGameplayLibrary.d.lua +++ b/Content/Lua/@types/BusyGameplayLibrary.d.lua @@ -1,3 +1,4 @@ --- @class BusyGameplayLibrary --- @field K2_GetWorld fun(obj:table):table +--- @field RequestGameplayTag fun(TagName:string):GameplayTag local BusyGameplayLibrary = {} \ No newline at end of file diff --git a/Content/Lua/@types/UE.d.lua b/Content/Lua/@types/UE.d.lua index 9b37218..faa53ab 100644 --- a/Content/Lua/@types/UE.d.lua +++ b/Content/Lua/@types/UE.d.lua @@ -29,7 +29,14 @@ KismetSystemLibrary = { } +--- @class GameplayTag +local GameplayTag + --- @class GameplayStatics --- @field GetPlayerController fun(uobj:table,idx:number):table --- @field GetGameState fun(uobj:table):table local GameplayStatics + +--- @class AbilitySystemBlueprintLibrary +--- @field AssignTagSetByCallerMagnitude fun(SpecHandle:table, DataTag:GameplayTag, Magnitude:number) +local AbilitySystemBlueprintLibrary diff --git a/Content/Lua/Gas/Ability/Common/MoveAbility.lua b/Content/Lua/Gas/Ability/Common/MoveAbility.lua new file mode 100644 index 0000000..72d69ca --- /dev/null +++ b/Content/Lua/Gas/Ability/Common/MoveAbility.lua @@ -0,0 +1,4 @@ +local MoveAbility = {} + + +return Class(nil, nil, MoveAbility) \ No newline at end of file diff --git a/Content/Lua/Gas/Ability/Role/Fox/FoxUltimate.lua b/Content/Lua/Gas/Ability/Role/Fox/FoxUltimate.lua new file mode 100644 index 0000000..0d4d74b --- /dev/null +++ b/Content/Lua/Gas/Ability/Role/Fox/FoxUltimate.lua @@ -0,0 +1,153 @@ +local GameplayStatics = import("GameplayStatics") +local AbilitySystemBlueprintLibrary = import("AbilitySystemBlueprintLibrary") +local BusyGameplayLibrary = import("BusyGameplayLibrary") + +--- @class FoxUltimate +--- @field RecastWindow number +local FoxUltimate = {} + + +function FoxUltimate:ctor() + self.ultimate_phase = 1 -- 大招阶段 + self.active_recast_handle = nil + self.active_accelerate_handle = nil +end + + +function FoxUltimate:K2_ActivateAbilityFromEvent(EventData) + print("FoxUltimate:K2_ActivateAbilityFromEvent", self.ultimate_phase) + + local owner = self:GetOwningActorFromActorInfo() + self.movement = owner.MovementComponent + self.animation = owner.SpineAnimationComponent + self.asc = AbilitySystemBlueprintLibrary.GetAbilitySystemComponent(owner) + self.recast_tag = BusyGameplayLibrary.RequestGameplayTag("Ability.Flags.Recast") + + local asc = self.asc + + if self.ultimate_phase == 1 or asc:HasMatchingGameplayTag(self.recast_tag) then + print("triggered") + self:TriggerUltimate(asc) + else + self:K2_EndAbility() + end + + +end + +function FoxUltimate:TriggerUltimate(asc) + if self.ultimate_phase == 1 then + -- 第一次释放大招,添加一个可以再次释放的Tag + local _, recast_effect = self:GetAbilityEffectSpecHandle("Recast", asc, 1, nil) + self.active_recast_handle = asc:BP_ApplyGameplayEffectSpecToSelf(recast_effect) + elseif self.ultimate_phase == 2 then + -- 第二次激活,移除可重复释放的tag + self.asc:RemoveActiveGameplayEffect(self.active_recast_handle, -1) + local _, recast_effect = self:GetAbilityEffectSpecHandle("Recast", asc, 1, nil) + self.active_recast_handle = asc:BP_ApplyGameplayEffectSpecToSelf(recast_effect) + elseif self.ultimate_phase == 3 then + self.asc:RemoveActiveGameplayEffect(self.active_recast_handle, -1) + end + + -- 播放动画,并监听动画完成的事件 + self:PlayAnimation() +end + + +function FoxUltimate:GetAnimationName(direction) + local animation_name_prefix + if direction.X >= 0 then + animation_name_prefix = "Ultimate/Right/" + else + animation_name_prefix = "Ultimate/Left/" + end + + if self.ultimate_phase == 1 then + return animation_name_prefix .. "UltimateStage1" + elseif self.ultimate_phase == 2 then + return animation_name_prefix .. "UltimateStage2" + elseif self.ultimate_phase == 3 then + return animation_name_prefix .. "UltimateStage3" + end + return nil +end + + +function FoxUltimate:K2_OnEndAbility(bWasCancelled) + print("FoxUltimate:K2_OnEndAbility") +end + + +function FoxUltimate:GetSprintSpeedFactor() + if self.ultimate_phase == 1 then + return 2.5 + elseif self.ultimate_phase == 2 then + return 2.8 + elseif self.ultimate_phase == 3 then + return 3.0 + end +end + +function FoxUltimate:PlayAnimation() + + local animation = self.animation + local PC = GameplayStatics.GetPlayerController(self, 0) + + local result, ability_direction = PC:GetCursorDirection(nil) -- 获取技能的朝向 + if not result then + print("FoxUltimate:TriggerPrimaryPhase can't find direction") + return + end + local anim_name = self:GetAnimationName(ability_direction) -- 获取技能动画名称 + if not anim_name then + print("FoxUltimate:TriggerPrimaryPhase can't get animation", self.ultimate_phase) + return + end + + local anim_entry = animation:SetAnimation(0, anim_name, false) + anim_entry.AnimationComplete:Add(function(entry) self:OnAnimationComplete(entry) end) + anim_entry.AnimationEvent:Add(function(entry, event) self:OnAnimationEvent(entry, event) end) + + local anim_total_time = anim_entry:GetAnimationEnd() -- 获取技能动画时长 + + -- 附加加速buff + self:MakeAccelerate(self:GetSprintSpeedFactor(), anim_total_time) + self.movement:ActivateSprint(ability_direction, anim_total_time) +end + + +function FoxUltimate:MakeAccelerate(speed_factor, total_time) + local _, accelerate_effect = self:GetAbilityEffectSpecHandle("Accelerate", self.asc, 1, nil) + AbilitySystemBlueprintLibrary.AssignTagSetByCallerMagnitude( + accelerate_effect, + BusyGameplayLibrary.RequestGameplayTag("Effect.Factor"), + speed_factor + ) + + AbilitySystemBlueprintLibrary.AssignTagSetByCallerMagnitude( + accelerate_effect, + BusyGameplayLibrary.RequestGameplayTag("Effect.Duration"), + total_time + ) + return self.asc:BP_ApplyGameplayEffectSpecToSelf(accelerate_effect) +end + + +function FoxUltimate:OnAnimationComplete(entry) + self.ultimate_phase = self.ultimate_phase + 1 + entry.AnimationComplete:Clear() + entry.AnimationEvent:Clear() + self:K2_EndAbility() +end + +function FoxUltimate:OnAnimationEvent(entry, event) + if event.Name == "OnSpeedChange" then + self.active_accelerate_handle = self:MakeAccelerate(8.0, 0.5) + elseif event.Name == "OnSpeedReset" then + self.asc:RemoveActiveGameplayEffect(self.active_accelerate_handle, -1) + end +end + + + +return Class(nil, nil, FoxUltimate) \ No newline at end of file diff --git a/Content/Lua/Gas/Ability/Role/Rabbit/RabbitUltimate.lua b/Content/Lua/Gas/Ability/Role/Rabbit/RabbitUltimate.lua new file mode 100644 index 0000000..baad620 --- /dev/null +++ b/Content/Lua/Gas/Ability/Role/Rabbit/RabbitUltimate.lua @@ -0,0 +1,4 @@ +local RabbitUltimate = {} + + +return Class(nil, nil, RabbitUltimate) \ No newline at end of file diff --git a/Content/Resource/Spine/Role/Fox/Fox.uasset b/Content/Resource/Spine/Role/Fox/Fox.uasset index 8372f7d..2e01784 100644 Binary files a/Content/Resource/Spine/Role/Fox/Fox.uasset and b/Content/Resource/Spine/Role/Fox/Fox.uasset differ diff --git a/Content/Resource/Spine/Role/Fox/FoxData.uasset b/Content/Resource/Spine/Role/Fox/FoxData.uasset index bff54a5..7bf38b4 100644 Binary files a/Content/Resource/Spine/Role/Fox/FoxData.uasset and b/Content/Resource/Spine/Role/Fox/FoxData.uasset differ diff --git a/Content/Resource/Spine/Role/Fox/Textures/Fox.uasset b/Content/Resource/Spine/Role/Fox/Textures/Fox.uasset index ffb672b..8e2127c 100644 Binary files a/Content/Resource/Spine/Role/Fox/Textures/Fox.uasset and b/Content/Resource/Spine/Role/Fox/Textures/Fox.uasset differ diff --git a/Source/BusyRabbit/Private/BusyGameplayLibrary.cpp b/Source/BusyRabbit/Private/BusyGameplayLibrary.cpp index a7f138d..d712702 100644 --- a/Source/BusyRabbit/Private/BusyGameplayLibrary.cpp +++ b/Source/BusyRabbit/Private/BusyGameplayLibrary.cpp @@ -78,3 +78,20 @@ bool UBusyGameplayLibrary::GetItemDescription(const FName& RowName, FBusyItemDes bool UBusyGameplayLibrary::GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData){ return GetTableConfig(TEXT("CookMaterialStateConfig"), RowName, RowData); } + +FGameplayTag UBusyGameplayLibrary::RequestGameplayTag(const FName& TagName) +{ + return FGameplayTag::RequestGameplayTag(TagName); +} + +#pragma optimize("",off) +FGameplayTagContainer UBusyGameplayLibrary::RequestGameplayTags(const TArray& TagNames) +{ + TArray GameplayTags; + for (const FName& TagName : TagNames) + { + GameplayTags.Add(FGameplayTag::RequestGameplayTag(TagName)); + } + return FGameplayTagContainer::CreateFromArray(GameplayTags); +} +#pragma optimize("",on) diff --git a/Source/BusyRabbit/Private/CppBindings/AbilitySystemComponentBinding.cpp b/Source/BusyRabbit/Private/CppBindings/AbilitySystemComponentBinding.cpp new file mode 100644 index 0000000..2601650 --- /dev/null +++ b/Source/BusyRabbit/Private/CppBindings/AbilitySystemComponentBinding.cpp @@ -0,0 +1,27 @@ +#include "LuaCppBinding.h" +#include "AbilitySystemComponent.h" +#include "GameplayTagContainer.h" +using slua::lua_State, slua::LuaObject, slua::LuaStruct; +using namespace slua; + + +#pragma optimize( "", off ) + + +bool HasMatchingGameplayTag(const UAbilitySystemComponent& Asc, const FName& TagName) +{ + // return Asc.HasMatchingGameplayTag(FGameplayTag::RequestGameplayTag(TagName)); + return true; +} + + +extern void RegisterAbilitySystemComponentExtension() { + REG_EXTENSION_METHOD_LAMBDA(UAbilitySystemComponent, "AHasMatchingGameplayTag", false, + [](UAbilitySystemComponent* ASC, const FName& Tag) -> bool { + return true; + } + ); +} + +#pragma optimize( "", on) + diff --git a/Source/BusyRabbit/Private/CppBindings/DataTableBindings.cpp b/Source/BusyRabbit/Private/CppBindings/DataTableBindings.cpp index 63fbf44..5752890 100644 --- a/Source/BusyRabbit/Private/CppBindings/DataTableBindings.cpp +++ b/Source/BusyRabbit/Private/CppBindings/DataTableBindings.cpp @@ -1,30 +1,6 @@ #include "LuaCppBinding.h" - using namespace slua; -//static int LuaBinding_FindRow(lua_State* L) { -// UDataTable* DataTable = LuaObject::checkUD(L, 1); -// FName RowName = LuaObject::checkValue(L, 2); -// -// UScriptStruct* RowStruct = (UScriptStruct*)DataTable->GetRowStruct(); -// -// uint8* RowData = DataTable->FindRowUnchecked(RowName); -// -// if (RowData && RowStruct) { -// // LuaStruct װ -// uint32 size = RowStruct->GetStructureSize() ? RowStruct->GetStructureSize() : 1; -// uint8* buf = (uint8*)FMemory::Malloc(size); -// RowStruct->InitializeStruct(buf); -// RowStruct->CopyScriptStruct(buf, RowData); -// -// LuaStruct* ls = new LuaStruct(); -// ls->Init(buf, size, RowStruct, false); -// return LuaObject::push(L, ls); -// } -// else { -// return LuaObject::pushNil(L); -// } -//} static int LuaBinding_FindRow(lua_State* L) { UDataTable* DataTable = LuaObject::checkUD(L, 1); @@ -37,24 +13,13 @@ static int LuaBinding_FindRow(lua_State* L) { LuaStruct* luaStruct = new LuaStruct(); luaStruct->Init((uint8*)TableRow, rowStruct->GetStructureSize(), (UScriptStruct*)rowStruct, true); - LuaObject::addLink(L, TableRow); // ȷ + LuaObject::addLink(L, TableRow); //auto ret = LuaObject::push(L, luaStruct); return LuaObject::pushReference(L, luaStruct, TableRow); } -//FTableRowBase* tableRow = DataTable->FindRow(RowName, TEXT("")); -// -//UScriptStruct* rowStruct = DataTable->GetRowStruct(); -// -//LuaStruct* luaStruct = new LuaStruct(); -//luaStruct->Init((uint8*)tableRow, rowStruct->GetStructureSize(), rowStruct, true); -// -//int ret = LuaObject::push(L, luaStruct); - - - extern void RegisterDataTableExtension() { REG_EXTENSION_METHOD_IMP(UDataTable, "FindRow", { return LuaBinding_FindRow(L); }); } diff --git a/Source/BusyRabbit/Private/Gas/BusyGameAbility.cpp b/Source/BusyRabbit/Private/Gas/BusyGameAbility.cpp new file mode 100644 index 0000000..d1ec3f0 --- /dev/null +++ b/Source/BusyRabbit/Private/Gas/BusyGameAbility.cpp @@ -0,0 +1,33 @@ +#include "Gas/BusyGameAbility.h" +#include "AbilitySystemBlueprintLibrary.h" +#include "AbilitySystemComponent.h" + +UBusyGameAbility::UBusyGameAbility() +{ + bHasBlueprintActivateFromEvent = true; +} + +FString UBusyGameAbility::GetLuaFilePath_Implementation()const +{ + return LuaFilePath; +} + +bool UBusyGameAbility::GetAbilityEffectSpecHandle(const FName& EffectName, const UAbilitySystemComponent* Asc, const int32 Level, + FGameplayEffectSpecHandle& Handle) const +{ + // 1. 查找对应的GameplayEffectClass + const TSubclassOf *EffectClass = AbilityEffects.Find(EffectName); + if (!EffectClass) return false; + + // 2. 创建并设置GameplayEffect上下文 + FGameplayEffectContextHandle EffectContextHandle = Asc->MakeEffectContext(); + + // 3. 将当前对象设置为效果来源 + EffectContextHandle.AddSourceObject(this); + + // 4. 创建GameplayEffectSpecHandle + Handle = Asc->MakeOutgoingSpec(*EffectClass, 1.f, EffectContextHandle); // 这里的1.f是等级 + + return Handle.IsValid(); +} + diff --git a/Source/BusyRabbit/Private/Level/Actor/BusyPawnBase.cpp b/Source/BusyRabbit/Private/Level/Actor/BusyPawnBase.cpp index c238cd2..a871dad 100644 --- a/Source/BusyRabbit/Private/Level/Actor/BusyPawnBase.cpp +++ b/Source/BusyRabbit/Private/Level/Actor/BusyPawnBase.cpp @@ -1,8 +1,12 @@ #include "Level/Actor/BusyPawnBase.h" + +#include "BusyGameplayLibrary.h" #include "Components/SphereComponent.h" #include "SpineSkeletonRendererComponent.h" #include "SpineSkeletonAnimationComponent.h" +#include "Gas/BusyGameAbility.h" #include "Level/Actor/Components/BusyPawnMovement.h" +#include "Tables/BusyPawnConfig.h" DEFINE_LOG_CATEGORY(LogBusyPawn) @@ -30,38 +34,46 @@ void ABusyPawnBase::BeginPlay() { Super::BeginPlay(); - // for (UClass* AbilityClass : Row->DefaultAbilities) { - // if (AbilityClass) { - // AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(AbilityClass)); - // } - // } + if (const UDataTable* DataTable = UBusyGameplayLibrary::GetGameDataTable("LevelRoleBaseConfig")) + { + const FBusyPawnBaseConfig* Config = DataTable->FindRow( + PawnName, FString::Printf(TEXT("ABusyPawnBase::BeginPlay Find %s in LevelRoleBaseConfig"), *PawnName.ToString()) + ); + if (Config) + { + InitPawnAbilities(*+Config); + InitPawnAttributes(*Config); + } + } } float ABusyPawnBase::GetSpeed_Implementation()const { - if (Attribute) + if (Attributes) { - return Attribute->GetMoveSpeed(); + return Attributes->GetMoveSpeed(); } return 0.f; } -void ABusyPawnBase::InitMoveSpeed(const float MoveSpeed)const +void ABusyPawnBase::InitPawnAttributes(const FBusyPawnBaseConfig& Config) { - if (Attribute) + if (Attributes) { - Attribute->InitMoveSpeed(MoveSpeed); + Attributes->InitHealth(Config.Health); + Attributes->InitMaxHealth(Config.Health); + Attributes->InitMoveSpeed(Config.MoveSpeed); + Attributes->InitDamage(Config.Damage); + Attributes->InitDefense(Config.Defense); } } -void ABusyPawnBase::InitHealth(const float Health, const float MaxHealth) const +void ABusyPawnBase::InitPawnAbilities(const FBusyPawnBaseConfig& Config)const { - if (Attribute) + for (const TSubclassOf& Ability : Config.DefaultAbilities) { - Attribute->InitHealth(Health); - Attribute->InitMaxHealth(MaxHealth); + AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(Ability)); } } - diff --git a/Source/BusyRabbit/Private/Level/Actor/BusyPlayerRole.cpp b/Source/BusyRabbit/Private/Level/Actor/BusyPlayerRole.cpp index 07bec3d..dfad955 100644 --- a/Source/BusyRabbit/Private/Level/Actor/BusyPlayerRole.cpp +++ b/Source/BusyRabbit/Private/Level/Actor/BusyPlayerRole.cpp @@ -19,46 +19,31 @@ ABusyPlayerRole::ABusyPlayerRole() SpringArmComponent->SetRelativeRotation(FRotator(0, -90.0, 0.0)); - Attribute = CreateDefaultSubobject(TEXT("Attribute")); - - InitMoveSpeed(200); - InitHealth(100, 100); + Attributes = CreateDefaultSubobject(TEXT("Attribute")); } void ABusyPlayerRole::BeginPlay() { Super::BeginPlay(); - InitRoleAttributes(); } -bool ABusyPlayerRole::InitRoleAttributes() +void ABusyPlayerRole::InitPawnAttributes(const struct FBusyPawnBaseConfig& Config) { - if (!PawnName.IsValid()) return false; - const UDataTable* ConfigTable = UBusyGameplayLibrary::GetGameDataTable(TEXT("LevelRoleBaseConfig")); - if (!ConfigTable) - { - UE_LOG(LogBusyPawn, Log, TEXT("ABusyPlayerRole::InitRoleAttributes Can't find config table: LevelRoleBaseConfig")) - return false; - } - - const FBusyRoleBaseConfig* Result = ConfigTable->FindRow( - PawnName, - *FString::Printf(TEXT("ABusyPlayerRole::InitRoleAttributes, PawnName: %ls"), *PawnName.ToString()) - ); - if (Result) - { - UBusyPlayerRoleAttributeSet* RoleAttributes = Cast(Attribute); - RoleAttributes->InitHealth(Result->Health); - RoleAttributes->InitMaxHealth(Result->Health); - RoleAttributes->InitMoveSpeed(Result->MoveSpeed); - - RoleAttributes->InitHunger(Result->Hunger); - RoleAttributes->InitMaxHunger(Result->Hunger); - RoleAttributes->InitHungerConsume(Result->HungerConsume); + Super::InitPawnAttributes(Config); + UBusyPlayerRoleAttributeSet* RoleAttributes = Cast(Attributes); - RoleAttributes->InitDamage(Result->Damage); - RoleAttributes->InitDefense(Result->Defense); - return true; + if (RoleAttributes && Config.StaticStruct() == FBusyRoleBaseConfig::StaticStruct()) + { + const FBusyRoleBaseConfig* RoleConfig = static_cast(&Config); + RoleAttributes->InitHunger(RoleConfig->Hunger); + RoleAttributes->InitMaxHunger(RoleConfig->Hunger); + RoleAttributes->InitHungerConsume(RoleConfig->HungerConsume); + } + else + { + UE_LOG(LogBusyPawn, Warning, TEXT("ABusyPlayerRole::InitPawnAttributes Failed, RoleAttribute: %p, ConfigName: %s"), + RoleAttributes, *Config.StaticStruct()->GetFName().ToString() + ); } - return false; } + diff --git a/Source/BusyRabbit/Private/Level/Actor/Components/BusyPawnMovement.cpp b/Source/BusyRabbit/Private/Level/Actor/Components/BusyPawnMovement.cpp index 87a8aeb..2cdcd2d 100644 --- a/Source/BusyRabbit/Private/Level/Actor/Components/BusyPawnMovement.cpp +++ b/Source/BusyRabbit/Private/Level/Actor/Components/BusyPawnMovement.cpp @@ -24,6 +24,22 @@ void UBusyPawnMovement::SprintTo(const float Distance, const float SpeedRate) } } +void UBusyPawnMovement::ActivateSprint(const FVector2D& Direction, const float TotalTime) +{ + SprintSpeed = 0.f; + SprintDirection = Direction; + SprintTotalTime = SprintRemainTime = TotalTime; + BusyMoveState = EBusyMoveState::Sprint; +} + +void UBusyPawnMovement::ActivateSprintWithSpeed(const FVector2D& Direction, const float TotalTime, const float Speed) +{ + SprintSpeed = Speed; + SprintDirection = Direction; + SprintTotalTime = SprintRemainTime = TotalTime; + BusyMoveState = EBusyMoveState::Sprint; +} + FVector2D UBusyPawnMovement::GetMoveDirection()const { if (AActor *Owner = GetOwner()) @@ -119,14 +135,24 @@ void UBusyPawnMovement::SprintTick(const float DeltaTime) const FVector CurrentLocation = Owner->GetActorLocation(); const FVector2D CurrentLocation2D = FVector2D(CurrentLocation); - const float MoveDistance = DeltaTime * Movable->Execute_GetSpeed(Owner) * SprintSpeedRate; - const FVector2D NewLocation = CurrentLocation2D + ForwardDirection * MoveDistance; + float SprintDeltaTime = DeltaTime; + if (SprintRemainTime <= DeltaTime) + { + SprintDeltaTime = SprintRemainTime; + SprintRemainTime = 0.f; + } + else + { + SprintRemainTime -= DeltaTime; + } + const float MoveDistance = SprintDeltaTime * (SprintSpeed == 0.f ? Movable->Execute_GetSpeed(Owner) : SprintSpeed); + const FVector2D NewLocation = CurrentLocation2D + SprintDirection * MoveDistance; Owner->SetActorLocation(FVector(NewLocation, CurrentLocation.Z), true); - if (FVector2D::Distance(NewLocation, SprintStartLocation) >= SprintDistance) + if (SprintRemainTime == 0.f) { - BusyMoveState = EBusyMoveState::None; // 这里不对,需要栈来做 + BusyMoveState = EBusyMoveState::None; } } diff --git a/Source/BusyRabbit/Private/Level/LevelPlayerController.cpp b/Source/BusyRabbit/Private/Level/LevelPlayerController.cpp index 9019da8..3dca737 100644 --- a/Source/BusyRabbit/Private/Level/LevelPlayerController.cpp +++ b/Source/BusyRabbit/Private/Level/LevelPlayerController.cpp @@ -1,5 +1,6 @@ #include "Level/LevelPlayerController.h" #include "Level/Actor/BusyPlayerRole.h" +#include "AbilitySystemBlueprintLibrary.h" #include "EnhancedInput/Public/EnhancedInputSubsystems.h" #include "Level/LevelPlayerState.h" #include "EnhancedInput/Public/EnhancedInputComponent.h" @@ -52,6 +53,14 @@ void ALevelPlayerController::SetupInputComponent() BindEnhancedInputAction(EnhancedInput, PrimarySkillAction, this, "OnPrimarySkill"); BindEnhancedInputAction(EnhancedInput, UltimateSkillAction, this, "OnUltimateSkill"); BindEnhancedInputAction(EnhancedInput, SwitchRoleAction, this, "OnSwitchRole"); + + for (const FBusySkillActionConfig& ActionConfig : RoleSkillActions) + { + EnhancedInput->BindAction(ActionConfig.InputAction, ETriggerEvent::Triggered, this, + &ALevelPlayerController::OnRoleSkillTriggered, + ActionConfig.ActionTag + ); + } } void ALevelPlayerController::Tick(float DeltaTime) @@ -107,6 +116,20 @@ bool ALevelPlayerController::GetCursorPosition(FVector2D& Position) const return false; } +bool ALevelPlayerController::GetCursorDirection(FVector2D& Direction) const +{ + const AActor *ControlledRole = GetControlledRole(); + if (!ControlledRole) return false; + + if (FVector2D CursorPosition; GetCursorPosition(CursorPosition)) + { + FVector2D &&RoleLocation = FVector2D(ControlledRole->GetActorLocation()); + Direction = (CursorPosition - RoleLocation).GetSafeNormal(); + return true; + } + return false; +} + void ALevelPlayerController::GetCursorHitResult(TArray& Results) const { } @@ -192,3 +215,14 @@ void ALevelPlayerController::OnSwitchRole(const FInputActionValue& Value) SwitchControlledRole(ControlledRole); } } + +void ALevelPlayerController::OnRoleSkillTriggered(FGameplayTag GameplayTag) +{ + AActor* ControlledRole = GetControlledRole(); + if (!ControlledRole) return; + if (UAbilitySystemComponent* Asc = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(ControlledRole)) + { + FGameplayEventData EventData = FGameplayEventData(); + Asc->HandleGameplayEvent(GameplayTag, &EventData); + } +} diff --git a/Source/BusyRabbit/Public/BusyGameplayLibrary.h b/Source/BusyRabbit/Public/BusyGameplayLibrary.h index f8ec65a..373874b 100644 --- a/Source/BusyRabbit/Public/BusyGameplayLibrary.h +++ b/Source/BusyRabbit/Public/BusyGameplayLibrary.h @@ -53,4 +53,12 @@ public: UFUNCTION(BlueprintPure) static bool GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData); +public: + UFUNCTION(BlueprintPure) + static FGameplayTag RequestGameplayTag(const FName& TagName); + + UFUNCTION(BlueprintCallable) + static FGameplayTagContainer RequestGameplayTags(const TArray& TagNames); + + }; diff --git a/Source/BusyRabbit/Public/Gas/BusyGameAbility.h b/Source/BusyRabbit/Public/Gas/BusyGameAbility.h new file mode 100644 index 0000000..875dc31 --- /dev/null +++ b/Source/BusyRabbit/Public/Gas/BusyGameAbility.h @@ -0,0 +1,30 @@ +#pragma once +#include "slua.h" +#include "Abilities/GameplayAbility.h" +#include "BusyGameAbility.generated.h" + + + +UCLASS(Blueprintable, BlueprintType) +class UBusyGameAbility : public UGameplayAbility, public ILuaOverriderInterface +{ + GENERATED_BODY() +public: + + UBusyGameAbility(); + + virtual FString GetLuaFilePath_Implementation()const override; + + +public: + UFUNCTION(BlueprintCallable) + bool GetAbilityEffectSpecHandle(const FName& EffectName, const UAbilitySystemComponent* Asc, const int32 Level, FGameplayEffectSpecHandle& Handle)const; + + +public: + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + FString LuaFilePath; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, DisplayName="技能效果") + TMap> AbilityEffects; +}; diff --git a/Source/BusyRabbit/Public/Level/Actor/BusyPawnBase.h b/Source/BusyRabbit/Public/Level/Actor/BusyPawnBase.h index 162b9fb..32041dc 100644 --- a/Source/BusyRabbit/Public/Level/Actor/BusyPawnBase.h +++ b/Source/BusyRabbit/Public/Level/Actor/BusyPawnBase.h @@ -6,6 +6,7 @@ class USphereComponent; +struct FBusyPawnBaseConfig; class USpineBoneFollowerComponent; class USpineSkeletonRendererComponent; class USpineSkeletonAnimationComponent; @@ -63,14 +64,9 @@ public: virtual float GetSpeed_Implementation()const override; public: - virtual bool InitRoleAttributes() { return false; } + virtual void InitPawnAttributes(const FBusyPawnBaseConfig& Config); + virtual void InitPawnAbilities(const FBusyPawnBaseConfig& Config) const; -protected: - UFUNCTION(BlueprintCallable) - void InitMoveSpeed(const float MoveSpeed)const; - - UFUNCTION(BlueprintCallable) - void InitHealth(const float Health, const float MaxHealth)const; protected: UPROPERTY(EditDefaultsOnly) @@ -111,7 +107,7 @@ public: protected: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) - TObjectPtr Attribute = nullptr; + TObjectPtr Attributes = nullptr; protected: diff --git a/Source/BusyRabbit/Public/Level/Actor/BusyPlayerRole.h b/Source/BusyRabbit/Public/Level/Actor/BusyPlayerRole.h index 5152007..0cbed04 100644 --- a/Source/BusyRabbit/Public/Level/Actor/BusyPlayerRole.h +++ b/Source/BusyRabbit/Public/Level/Actor/BusyPlayerRole.h @@ -46,7 +46,8 @@ public: virtual void BeginPlay() override; - virtual bool InitRoleAttributes()override; + virtual void InitPawnAttributes(const struct FBusyPawnBaseConfig& Config)override; + protected: diff --git a/Source/BusyRabbit/Public/Level/Actor/Components/BusyAbilitySystemComponent.h b/Source/BusyRabbit/Public/Level/Actor/Components/BusyAbilitySystemComponent.h index 6d0cb43..fe57bc1 100644 --- a/Source/BusyRabbit/Public/Level/Actor/Components/BusyAbilitySystemComponent.h +++ b/Source/BusyRabbit/Public/Level/Actor/Components/BusyAbilitySystemComponent.h @@ -9,7 +9,7 @@ class UBusyAbilitySystemComponent : public UAbilitySystemComponent, public ILuaO { GENERATED_BODY() public: - virtual FString GetLuaFilePath_Implementation() const override; + virtual FString GetLuaFilePath_Implementation() const override; protected: diff --git a/Source/BusyRabbit/Public/Level/Actor/Components/BusyPawnMovement.h b/Source/BusyRabbit/Public/Level/Actor/Components/BusyPawnMovement.h index 91bb497..7c0a910 100644 --- a/Source/BusyRabbit/Public/Level/Actor/Components/BusyPawnMovement.h +++ b/Source/BusyRabbit/Public/Level/Actor/Components/BusyPawnMovement.h @@ -54,6 +54,23 @@ public: UFUNCTION(BlueprintCallable) void SprintTo(const float Distance, const float SpeedRate); + /** + * 以角色自身的速度向某个方向进行冲刺,受角色速度变化的影响 + * @param Direction 冲刺方向 + * @param TotalTime 冲刺的时间(s) + */ + UFUNCTION(BlueprintCallable) + void ActivateSprint(const FVector2D &Direction, const float TotalTime); + + /** + * 以指定速度向某个方向冲刺,无视角色速度 + * @param Direction + * @param TotalTime + * @param Speed + */ + UFUNCTION(BlueprintCallable) + void ActivateSprintWithSpeed(const FVector2D &Direction, const float TotalTime, const float Speed); + /** * 获取当前移动的方向 * @return 返回朝向的单位向量,如果没动返回(0,0) @@ -97,10 +114,17 @@ protected: UPROPERTY(EditAnywhere, BlueprintReadOnly) FVector2D ForwardDirection; + +// 冲刺相关 +protected: - - -protected: // 冲刺相关 + + FVector2D SprintDirection; // 冲刺的方向 + float SprintTotalTime; // 冲刺总时长 + float SprintRemainTime; // 冲刺的剩余时间 + float SprintSpeed; // 指定的冲刺速度, 为0表示使用自己的速度 + + float SprintSpeedRate = 1.f; float SprintDistance = 100.f; FVector2D SprintStartLocation; diff --git a/Source/BusyRabbit/Public/Level/LevelPlayerController.h b/Source/BusyRabbit/Public/Level/LevelPlayerController.h index e805fe4..7859247 100644 --- a/Source/BusyRabbit/Public/Level/LevelPlayerController.h +++ b/Source/BusyRabbit/Public/Level/LevelPlayerController.h @@ -1,16 +1,18 @@ #pragma once #include "LuaPlayerController.h" +#include "GameplayTagContainer.h" +#include "InputAction.h" #include "LevelPlayerController.generated.h" + UINTERFACE(MinimalAPI, Blueprintable) class UBusyControllable: public UInterface { GENERATED_BODY() }; - class IBusyControllable { GENERATED_BODY() @@ -29,8 +31,22 @@ public: }; -struct FInputActionValue; class ABusyPlayerRole; +struct FInputActionValue; + + +USTRUCT(BlueprintType) +struct FBusySkillActionConfig +{ + GENERATED_BODY() + UPROPERTY(EditAnywhere, BlueprintReadOnly) + FGameplayTag ActionTag; + UPROPERTY(EditAnywhere, BlueprintReadOnly) + UInputAction* InputAction; +}; + + + UCLASS() class ALevelPlayerController : public ALuaPlayerController @@ -48,6 +64,14 @@ public: UFUNCTION(BlueprintCallable, Category = "Controller") bool GetCursorPosition(FVector2D& Position) const; + /** + * 获取光标相对于所控制的人物的方向 + * @param Direction + * @return false -> 获取失败, 没有角色或者鼠标不在游戏内 + */ + UFUNCTION(BlueprintCallable, Category = "Controller") + bool GetCursorDirection(FVector2D& Direction) const; + UFUNCTION(BlueprintCallable, Category = "Controller") ABusyPlayerRole* GetControlledRole() const; @@ -88,6 +112,10 @@ public: // 输入相关 UPROPERTY(EditDefaultsOnly, Category = "Input") TObjectPtr SwitchRoleAction; // 切换控制的角色 + + UPROPERTY(EditDefaultsOnly, Category = "Input") + TArray RoleSkillActions; + public: UFUNCTION() void OnMove(const FInputActionValue& Value)const; @@ -104,6 +132,9 @@ public: UFUNCTION() void OnSwitchRole(const FInputActionValue& Value); + UFUNCTION() + void OnRoleSkillTriggered(FGameplayTag GameplayTag); + protected: UPROPERTY()