Compare commits

...

3 Commits

37 changed files with 520 additions and 136 deletions

View File

@ -8,11 +8,15 @@ FastReplication=False
InvalidTagCharacters="\"\'," InvalidTagCharacters="\"\',"
NumBitsForContainerSize=6 NumBitsForContainerSize=6
NetIndexFirstBitSegment=16 NetIndexFirstBitSegment=16
+GameplayTagList=(Tag="Ability.Block.UltimatePlaying",DevComment="大招正在释放中")
+GameplayTagList=(Tag="Ability.Flags.Cooldown",DevComment="技能冷却")
+GameplayTagList=(Tag="Ability.Flags.Recast",DevComment="可以再次释放技能的标记")
+GameplayTagList=(Tag="Ability.Role.AttributeConsume",DevComment="角色属性损耗debuff") +GameplayTagList=(Tag="Ability.Role.AttributeConsume",DevComment="角色属性损耗debuff")
+GameplayTagList=(Tag="Ability.Role.EatFood",DevComment="干饭") +GameplayTagList=(Tag="Ability.Role.EatFood",DevComment="干饭")
+GameplayTagList=(Tag="Ability.Role.Pick",DevComment="角色采集物品") +GameplayTagList=(Tag="Ability.Role.Pick",DevComment="角色采集物品")
+GameplayTagList=(Tag="Ability.Role.Recover",DevComment="角色状态恢复技能") +GameplayTagList=(Tag="Ability.Role.Recover",DevComment="角色状态恢复技能")
+GameplayTagList=(Tag="Ability.Role.Roll",DevComment="角色无敌翻滚") +GameplayTagList=(Tag="Ability.Role.Roll",DevComment="角色无敌翻滚")
+GameplayTagList=(Tag="Ability.Role.Ultimate",DevComment="角色大招")
+GameplayTagList=(Tag="Buff.Indispersible.HungerConsume",DevComment="饥饿值消耗,不可被驱散") +GameplayTagList=(Tag="Buff.Indispersible.HungerConsume",DevComment="饥饿值消耗,不可被驱散")
+GameplayTagList=(Tag="Buff.RoleConsume.Health",DevComment="角色因饥饿掉血的debuff") +GameplayTagList=(Tag="Buff.RoleConsume.Health",DevComment="角色因饥饿掉血的debuff")
+GameplayTagList=(Tag="Buff.RoleConsume.Hunger",DevComment="角色每秒钟的饥饿消耗") +GameplayTagList=(Tag="Buff.RoleConsume.Hunger",DevComment="角色每秒钟的饥饿消耗")
@ -25,6 +29,8 @@ NetIndexFirstBitSegment=16
+GameplayTagList=(Tag="CookProcess.Diced",DevComment="切丁") +GameplayTagList=(Tag="CookProcess.Diced",DevComment="切丁")
+GameplayTagList=(Tag="CookProcess.Mashed",DevComment="切泥") +GameplayTagList=(Tag="CookProcess.Mashed",DevComment="切泥")
+GameplayTagList=(Tag="CookProcess.Sliced",DevComment="切片操作") +GameplayTagList=(Tag="CookProcess.Sliced",DevComment="切片操作")
+GameplayTagList=(Tag="Effect.Duration",DevComment="效果的持续时长")
+GameplayTagList=(Tag="Effect.Factor",DevComment="效果的乘法系数")
+GameplayTagList=(Tag="GameItem.Building",DevComment="建筑物") +GameplayTagList=(Tag="GameItem.Building",DevComment="建筑物")
+GameplayTagList=(Tag="GameItem.Food",DevComment="游戏内的可食用物品") +GameplayTagList=(Tag="GameItem.Food",DevComment="游戏内的可食用物品")
+GameplayTagList=(Tag="Ingredient",DevComment="烹饪食材") +GameplayTagList=(Tag="Ingredient",DevComment="烹饪食材")

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,3 +1,4 @@
--- @class BusyGameplayLibrary --- @class BusyGameplayLibrary
--- @field K2_GetWorld fun(obj:table):table --- @field K2_GetWorld fun(obj:table):table
--- @field RequestGameplayTag fun(TagName:string):GameplayTag
local BusyGameplayLibrary = {} local BusyGameplayLibrary = {}

View File

@ -29,7 +29,14 @@ KismetSystemLibrary = {
} }
--- @class GameplayTag
local GameplayTag
--- @class GameplayStatics --- @class GameplayStatics
--- @field GetPlayerController fun(uobj:table,idx:number):table --- @field GetPlayerController fun(uobj:table,idx:number):table
--- @field GetGameState fun(uobj:table):table --- @field GetGameState fun(uobj:table):table
local GameplayStatics local GameplayStatics
--- @class AbilitySystemBlueprintLibrary
--- @field AssignTagSetByCallerMagnitude fun(SpecHandle:table, DataTag:GameplayTag, Magnitude:number)
local AbilitySystemBlueprintLibrary

View File

@ -0,0 +1,4 @@
local MoveAbility = {}
return Class(nil, nil, MoveAbility)

View File

@ -0,0 +1,196 @@
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
self.overlap_delegate_handle = nil
self.tag_add_or_remove_delegate = nil
end
function FoxUltimate:K2_ActivateAbilityFromEvent(EventData)
print("FoxUltimate:K2_ActivateAbilityFromEvent", self.ultimate_phase)
if not self:K2_CommitAbilityCost(false) then
return self:K2_EndAbility()
end
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")
self.owner = owner
local asc = self.asc
if self.tag_add_or_remove_delegate == nil then
self.tag_add_or_remove_delegate = slua.createDelegate(function(tag, is_add)
if is_add == 0 and not self.bIsActive then
self.ultimate_phase = 1
self:K2_CommitAbilityCooldown(false, false)
end
end)
owner:BindGameplayTagAddOrRemove(self.recast_tag, self.tag_add_or_remove_delegate)
end
if self.ultimate_phase == 1 or asc:HasMatchingGameplayTag(self.recast_tag) then
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)
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)
local new_phase = self.ultimate_phase + 1
if new_phase > 3 then
self.ultimate_phase = 1
else
self.ultimate_phase = new_phase
end
print("FoxUltimate:OnAnimationComplete", self.ultimate_phase)
if not self.asc:HasMatchingGameplayTag(self.recast_tag) then
self.ultimate_phase = 1
self:K2_CommitAbilityCooldown(false, false)
end
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)
elseif event.Name == "OnDamageBegin" then
local collision = self.owner["TailCollision"]
collision:SetCollisionEnabled(1)
self.overlap_delegate_handle = collision.OnComponentBeginOverlap:Add(function()
if not self.asc:HasMatchingGameplayTag(self.recast_tag) then
local _, recast_effect = self:GetAbilityEffectSpecHandle("Recast", self.asc, 1, nil)
self.active_recast_handle = self.asc:BP_ApplyGameplayEffectSpecToSelf(recast_effect)
end
end)
elseif event.Name == "OnDamageEnd" then
self.owner["TailCollision"]:SetCollisionEnabled(0)
if self.overlap_delegate_handle ~= nil then
self.owner["TailCollision"].OnComponentBeginOverlap:Remove(self.overlap_delegate_handle)
self.overlap_delegate_handle = nil
end
end
end
return Class(nil, nil, FoxUltimate)

View File

@ -0,0 +1,4 @@
local RabbitUltimate = {}
return Class(nil, nil, RabbitUltimate)

View File

@ -8,6 +8,13 @@ end
function LevelFoxRole:ReceiveBeginPlay() function LevelFoxRole:ReceiveBeginPlay()
self["SpineAnimationComponent"]:SetAnimation(0, "Idle/Front", true) self["SpineAnimationComponent"]:SetAnimation(0, "Idle/Front", true)
self.last_animation = "Idle/Front" self.last_animation = "Idle/Front"
self["SpineBoneFollower"].Target = self
self["SpineBoneFollower"].BoneName = "tail"
self["SpineBoneFollower"].UseComponentTransform = true
self["SpineBoneFollower"].UseScale = true
self["TailCollision"]:SetCollisionEnabled(0)
end end
@ -42,32 +49,6 @@ function LevelFoxRole:OnMove(location)
self["MovementComponent"]:MoveTo(location) self["MovementComponent"]:MoveTo(location)
end end
function LevelFoxRole:OnUltimateSkill()
print("LevelFoxRole:OnUltimateSkill")
local sprint_distance = 600
local sprint_speed_rate = 3.8
-- 获取角色朝向
local forward_direction = self["MovementComponent"]:GetForwardDirection()
self["MovementComponent"]:SprintTo(sprint_distance, sprint_speed_rate)
local anim_comp = self["SpineAnimationComponent"]
if forward_direction.X >= 0 then
anim_comp:SetAnimation(0, "Ultimate/Right/UltimateStage1", false)
else
anim_comp:SetAnimation(0, "Ultimate/Left/UltimateStage1", false)
end
local anim_entry = anim_comp:GetCurrent(0)
local anim_total_time = anim_entry:GetAnimationEnd()
local sprint_time = sprint_distance / (self:GetSpeed() * sprint_speed_rate)
anim_comp:SetTimeScale(anim_total_time / sprint_time)
print("hahhh", anim_total_time, sprint_time)
end
return Class(nil, nil, LevelFoxRole) return Class(nil, nil, LevelFoxRole)

View File

@ -78,3 +78,20 @@ bool UBusyGameplayLibrary::GetItemDescription(const FName& RowName, FBusyItemDes
bool UBusyGameplayLibrary::GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData){ bool UBusyGameplayLibrary::GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData){
return GetTableConfig<FBusyCookMaterialStateConfig>(TEXT("CookMaterialStateConfig"), RowName, RowData); return GetTableConfig<FBusyCookMaterialStateConfig>(TEXT("CookMaterialStateConfig"), RowName, RowData);
} }
FGameplayTag UBusyGameplayLibrary::RequestGameplayTag(const FName& TagName)
{
return FGameplayTag::RequestGameplayTag(TagName);
}
#pragma optimize("",off)
FGameplayTagContainer UBusyGameplayLibrary::RequestGameplayTags(const TArray<FName>& TagNames)
{
TArray<FGameplayTag> GameplayTags;
for (const FName& TagName : TagNames)
{
GameplayTags.Add(FGameplayTag::RequestGameplayTag(TagName));
}
return FGameplayTagContainer::CreateFromArray(GameplayTags);
}
#pragma optimize("",on)

View File

@ -0,0 +1,9 @@
#include "LuaCppBinding.h"
using slua::lua_State, slua::LuaObject, slua::LuaStruct;
extern void RegisterAbilitySystemComponentExtension() {
}

View File

@ -1,30 +1,6 @@
#include "LuaCppBinding.h" #include "LuaCppBinding.h"
using namespace slua; using namespace slua;
//static int LuaBinding_FindRow(lua_State* L) {
// UDataTable* DataTable = LuaObject::checkUD<UDataTable>(L, 1);
// FName RowName = LuaObject::checkValue<FName>(L, 2);
//
// UScriptStruct* RowStruct = (UScriptStruct*)DataTable->GetRowStruct();
//
// uint8* RowData = DataTable->FindRowUnchecked(RowName);
//
// if (RowData && RowStruct) {
// // <20><><EFBFBD><EFBFBD> LuaStruct <20><>װ<EFBFBD><D7B0>
// 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) { static int LuaBinding_FindRow(lua_State* L) {
UDataTable* DataTable = LuaObject::checkUD<UDataTable>(L, 1); UDataTable* DataTable = LuaObject::checkUD<UDataTable>(L, 1);
@ -37,24 +13,13 @@ static int LuaBinding_FindRow(lua_State* L) {
LuaStruct* luaStruct = new LuaStruct(); LuaStruct* luaStruct = new LuaStruct();
luaStruct->Init((uint8*)TableRow, rowStruct->GetStructureSize(), (UScriptStruct*)rowStruct, true); luaStruct->Init((uint8*)TableRow, rowStruct->GetStructureSize(), (UScriptStruct*)rowStruct, true);
LuaObject::addLink(L, TableRow); // ȷ<><C8B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> LuaObject::addLink(L, TableRow);
//auto ret = LuaObject::push(L, luaStruct); //auto ret = LuaObject::push(L, luaStruct);
return LuaObject::pushReference<LuaStruct*>(L, luaStruct, TableRow); return LuaObject::pushReference<LuaStruct*>(L, luaStruct, TableRow);
} }
//FTableRowBase* tableRow = DataTable->FindRow<FTableRowBase>(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() { extern void RegisterDataTableExtension() {
REG_EXTENSION_METHOD_IMP(UDataTable, "FindRow", { return LuaBinding_FindRow(L); }); REG_EXTENSION_METHOD_IMP(UDataTable, "FindRow", { return LuaBinding_FindRow(L); });
} }

View File

@ -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<UGameplayEffect> *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();
}

View File

@ -1,8 +1,12 @@
#include "Level/Actor/BusyPawnBase.h" #include "Level/Actor/BusyPawnBase.h"
#include "BusyGameplayLibrary.h"
#include "Components/SphereComponent.h" #include "Components/SphereComponent.h"
#include "SpineSkeletonRendererComponent.h" #include "SpineSkeletonRendererComponent.h"
#include "SpineSkeletonAnimationComponent.h" #include "SpineSkeletonAnimationComponent.h"
#include "Gas/BusyGameAbility.h"
#include "Level/Actor/Components/BusyPawnMovement.h" #include "Level/Actor/Components/BusyPawnMovement.h"
#include "Tables/BusyPawnConfig.h"
DEFINE_LOG_CATEGORY(LogBusyPawn) DEFINE_LOG_CATEGORY(LogBusyPawn)
@ -12,7 +16,6 @@ ABusyPawnBase::ABusyPawnBase()
RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene")); RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
SpineRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SpineRoot")); SpineRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SpineRoot"));
SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
SpineRenderComponent = CreateDefaultSubobject<USpineSkeletonRendererComponent>(TEXT("SpineRenderComponent")); SpineRenderComponent = CreateDefaultSubobject<USpineSkeletonRendererComponent>(TEXT("SpineRenderComponent"));
SpineAnimationComponent = CreateDefaultSubobject<USpineSkeletonAnimationComponent>(TEXT("SpineAnimationComponent")); SpineAnimationComponent = CreateDefaultSubobject<USpineSkeletonAnimationComponent>(TEXT("SpineAnimationComponent"));
AbilitySystemComponent = CreateDefaultSubobject<UBusyAbilitySystemComponent>(TEXT("AbilitySystemComponent")); AbilitySystemComponent = CreateDefaultSubobject<UBusyAbilitySystemComponent>(TEXT("AbilitySystemComponent"));
@ -20,7 +23,6 @@ ABusyPawnBase::ABusyPawnBase()
RootComponent = RootScene; RootComponent = RootScene;
SpineRoot->SetupAttachment(RootScene); SpineRoot->SetupAttachment(RootScene);
SphereComponent->SetupAttachment(SpineRoot);
SpineRenderComponent->SetupAttachment(SpineRoot); SpineRenderComponent->SetupAttachment(SpineRoot);
SpineRoot->SetRelativeRotation(FRotator(0, 0, -90)); SpineRoot->SetRelativeRotation(FRotator(0, 0, -90));
@ -30,38 +32,61 @@ void ABusyPawnBase::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
// for (UClass* AbilityClass : Row->DefaultAbilities) { if (const UDataTable* DataTable = UBusyGameplayLibrary::GetGameDataTable("LevelRoleBaseConfig"))
// if (AbilityClass) { {
// AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(AbilityClass)); const FBusyPawnBaseConfig* Config = DataTable->FindRow<FBusyPawnBaseConfig>(
// } PawnName, FString::Printf(TEXT("ABusyPawnBase::BeginPlay Find %s in LevelRoleBaseConfig"), *PawnName.ToString())
// } );
if (Config)
{
InitPawnAbilities(*+Config);
InitPawnAttributes(*Config);
}
}
} }
float ABusyPawnBase::GetSpeed_Implementation()const float ABusyPawnBase::GetSpeed_Implementation()const
{ {
if (Attribute) if (Attributes)
{ {
return Attribute->GetMoveSpeed(); return Attributes->GetMoveSpeed();
} }
return 0.f; 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<UGameplayAbility>& Ability : Config.DefaultAbilities)
{ {
Attribute->InitHealth(Health); AbilitySystemComponent->GiveAbility(FGameplayAbilitySpec(Ability));
Attribute->InitMaxHealth(MaxHealth);
} }
} }
void ABusyPawnBase::BindGameplayTagAddOrRemove(const FGameplayTag& Tag, FGameplayTagAddOrRemoveDelegate Delegate)const
{
AbilitySystemComponent->RegisterGameplayTagEvent(Tag, EGameplayTagEventType::NewOrRemoved).AddLambda(
[Delegate](const FGameplayTag GameplayTag, const int32 Value)
{
Delegate.ExecuteIfBound(GameplayTag, Value);
}
);
}
void ABusyPawnBase::InitCollision()
{
}

View File

@ -19,46 +19,31 @@ ABusyPlayerRole::ABusyPlayerRole()
SpringArmComponent->SetRelativeRotation(FRotator(0, -90.0, 0.0)); SpringArmComponent->SetRelativeRotation(FRotator(0, -90.0, 0.0));
Attribute = CreateDefaultSubobject<UBusyPlayerRoleAttributeSet>(TEXT("Attribute")); Attributes = CreateDefaultSubobject<UBusyPlayerRoleAttributeSet>(TEXT("Attribute"));
InitMoveSpeed(200);
InitHealth(100, 100);
} }
void ABusyPlayerRole::BeginPlay() void ABusyPlayerRole::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
InitRoleAttributes();
} }
bool ABusyPlayerRole::InitRoleAttributes() void ABusyPlayerRole::InitPawnAttributes(const struct FBusyPawnBaseConfig& Config)
{ {
if (!PawnName.IsValid()) return false; Super::InitPawnAttributes(Config);
const UDataTable* ConfigTable = UBusyGameplayLibrary::GetGameDataTable(TEXT("LevelRoleBaseConfig")); UBusyPlayerRoleAttributeSet* RoleAttributes = Cast<UBusyPlayerRoleAttributeSet>(Attributes);
if (!ConfigTable)
// if (RoleAttributes && Config.StaticStruct() == FBusyRoleBaseConfig::StaticStruct())
{ {
UE_LOG(LogBusyPawn, Log, TEXT("ABusyPlayerRole::InitRoleAttributes Can't find config table: LevelRoleBaseConfig")) const FBusyRoleBaseConfig* RoleConfig = static_cast<const FBusyRoleBaseConfig*>(&Config);
return false; RoleAttributes->InitHunger(RoleConfig->Hunger);
RoleAttributes->InitMaxHunger(RoleConfig->Hunger);
RoleAttributes->InitHungerConsume(RoleConfig->HungerConsume);
} }
// else
const FBusyRoleBaseConfig* Result = ConfigTable->FindRow<FBusyRoleBaseConfig>( // {
PawnName, // UE_LOG(LogBusyPawn, Warning, TEXT("ABusyPlayerRole::InitPawnAttributes Failed, RoleAttribute: %p, ConfigName: %s"),
*FString::Printf(TEXT("ABusyPlayerRole::InitRoleAttributes, PawnName: %ls"), *PawnName.ToString()) // RoleAttributes, *Config.StaticStruct()->GetFName().ToString()
); // );
if (Result) // }
{
UBusyPlayerRoleAttributeSet* RoleAttributes = Cast<UBusyPlayerRoleAttributeSet>(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);
RoleAttributes->InitDamage(Result->Damage);
RoleAttributes->InitDefense(Result->Defense);
return true;
}
return false;
} }

View File

@ -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 FVector2D UBusyPawnMovement::GetMoveDirection()const
{ {
if (AActor *Owner = GetOwner()) if (AActor *Owner = GetOwner())
@ -119,14 +135,24 @@ void UBusyPawnMovement::SprintTick(const float DeltaTime)
const FVector CurrentLocation = Owner->GetActorLocation(); const FVector CurrentLocation = Owner->GetActorLocation();
const FVector2D CurrentLocation2D = FVector2D(CurrentLocation); const FVector2D CurrentLocation2D = FVector2D(CurrentLocation);
const float MoveDistance = DeltaTime * Movable->Execute_GetSpeed(Owner) * SprintSpeedRate; float SprintDeltaTime = DeltaTime;
const FVector2D NewLocation = CurrentLocation2D + ForwardDirection * MoveDistance; 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); Owner->SetActorLocation(FVector(NewLocation, CurrentLocation.Z), true);
if (FVector2D::Distance(NewLocation, SprintStartLocation) >= SprintDistance) if (SprintRemainTime == 0.f)
{ {
BusyMoveState = EBusyMoveState::None; // 这里不对,需要栈来做 BusyMoveState = EBusyMoveState::None;
} }
} }

View File

@ -1,5 +1,6 @@
#include "Level/LevelPlayerController.h" #include "Level/LevelPlayerController.h"
#include "Level/Actor/BusyPlayerRole.h" #include "Level/Actor/BusyPlayerRole.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "EnhancedInput/Public/EnhancedInputSubsystems.h" #include "EnhancedInput/Public/EnhancedInputSubsystems.h"
#include "Level/LevelPlayerState.h" #include "Level/LevelPlayerState.h"
#include "EnhancedInput/Public/EnhancedInputComponent.h" #include "EnhancedInput/Public/EnhancedInputComponent.h"
@ -52,6 +53,14 @@ void ALevelPlayerController::SetupInputComponent()
BindEnhancedInputAction(EnhancedInput, PrimarySkillAction, this, "OnPrimarySkill"); BindEnhancedInputAction(EnhancedInput, PrimarySkillAction, this, "OnPrimarySkill");
BindEnhancedInputAction(EnhancedInput, UltimateSkillAction, this, "OnUltimateSkill"); BindEnhancedInputAction(EnhancedInput, UltimateSkillAction, this, "OnUltimateSkill");
BindEnhancedInputAction(EnhancedInput, SwitchRoleAction, this, "OnSwitchRole"); 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) void ALevelPlayerController::Tick(float DeltaTime)
@ -107,6 +116,20 @@ bool ALevelPlayerController::GetCursorPosition(FVector2D& Position) const
return false; 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<AActor*>& Results) const void ALevelPlayerController::GetCursorHitResult(TArray<AActor*>& Results) const
{ {
} }
@ -192,3 +215,14 @@ void ALevelPlayerController::OnSwitchRole(const FInputActionValue& Value)
SwitchControlledRole(ControlledRole); 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);
}
}

View File

@ -53,4 +53,12 @@ public:
UFUNCTION(BlueprintPure) UFUNCTION(BlueprintPure)
static bool GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData); static bool GetCookMaterialStateConfig(const FName& RowName, FBusyCookMaterialStateConfig& RowData);
public:
UFUNCTION(BlueprintPure)
static FGameplayTag RequestGameplayTag(const FName& TagName);
UFUNCTION(BlueprintCallable)
static FGameplayTagContainer RequestGameplayTags(const TArray<FName>& TagNames);
}; };

View File

@ -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<FName, TSubclassOf<UGameplayEffect>> AbilityEffects;
};

View File

@ -4,13 +4,14 @@
#include "Level/Actor/Components/BusyAbilitySystemComponent.h" #include "Level/Actor/Components/BusyAbilitySystemComponent.h"
#include "BusyPawnBase.generated.h" #include "BusyPawnBase.generated.h"
struct FBusyPawnBaseConfig;
class USphereComponent;
class USpineBoneFollowerComponent; class USpineBoneFollowerComponent;
class USpineSkeletonRendererComponent; class USpineSkeletonRendererComponent;
class USpineSkeletonAnimationComponent; class USpineSkeletonAnimationComponent;
class UBusyPawnMovementComponent; class UBusyPawnMovementComponent;
DECLARE_DYNAMIC_DELEGATE_TwoParams(FGameplayTagAddOrRemoveDelegate, const FGameplayTag&, Tag, const int32, Value);
#define MY_ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \ #define MY_ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \ GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
@ -63,25 +64,21 @@ public:
virtual float GetSpeed_Implementation()const override; virtual float GetSpeed_Implementation()const override;
public: public:
virtual bool InitRoleAttributes() { return false; } virtual void InitPawnAttributes(const FBusyPawnBaseConfig& Config);
virtual void InitPawnAbilities(const FBusyPawnBaseConfig& Config) const;
public:
UFUNCTION(BlueprintCallable)
void BindGameplayTagAddOrRemove(const FGameplayTag& Tag, FGameplayTagAddOrRemoveDelegate Delegate)const;
protected: protected:
UFUNCTION(BlueprintCallable) void InitCollision();
void InitMoveSpeed(const float MoveSpeed)const;
UFUNCTION(BlueprintCallable)
void InitHealth(const float Health, const float MaxHealth)const;
protected: protected:
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
TObjectPtr<USceneComponent> RootScene; //场景根组件 TObjectPtr<USceneComponent> RootScene; //场景根组件
/*-----------------------------碰撞相关组件-----------------------------*/
UPROPERTY(EditDefaultsOnly)
TObjectPtr<USphereComponent> SphereComponent;
/*-------------------------------------------------------------------*/
/*----------------------------spine相关组件----------------------------*/ /*----------------------------spine相关组件----------------------------*/
UPROPERTY(EditDefaultsOnly) UPROPERTY(EditDefaultsOnly)
TObjectPtr<USceneComponent> SpineRoot; TObjectPtr<USceneComponent> SpineRoot;
@ -111,7 +108,7 @@ public:
protected: protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TObjectPtr<UBusyPawnAttributeSet> Attribute = nullptr; TObjectPtr<UBusyPawnAttributeSet> Attributes = nullptr;
protected: protected:

View File

@ -46,7 +46,8 @@ public:
virtual void BeginPlay() override; virtual void BeginPlay() override;
virtual bool InitRoleAttributes()override; virtual void InitPawnAttributes(const struct FBusyPawnBaseConfig& Config)override;
protected: protected:

View File

@ -9,7 +9,7 @@ class UBusyAbilitySystemComponent : public UAbilitySystemComponent, public ILuaO
{ {
GENERATED_BODY() GENERATED_BODY()
public: public:
virtual FString GetLuaFilePath_Implementation() const override; virtual FString GetLuaFilePath_Implementation() const override;
protected: protected:

View File

@ -54,6 +54,23 @@ public:
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void SprintTo(const float Distance, const float SpeedRate); 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) * @return 返回朝向的单位向量,如果没动返回(0,0)
@ -98,9 +115,16 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadOnly) UPROPERTY(EditAnywhere, BlueprintReadOnly)
FVector2D ForwardDirection; FVector2D ForwardDirection;
// 冲刺相关
protected:
FVector2D SprintDirection; // 冲刺的方向
float SprintTotalTime; // 冲刺总时长
float SprintRemainTime; // 冲刺的剩余时间
float SprintSpeed; // 指定的冲刺速度, 为0表示使用自己的速度
protected: // 冲刺相关
float SprintSpeedRate = 1.f; float SprintSpeedRate = 1.f;
float SprintDistance = 100.f; float SprintDistance = 100.f;
FVector2D SprintStartLocation; FVector2D SprintStartLocation;

View File

@ -1,16 +1,18 @@
#pragma once #pragma once
#include "LuaPlayerController.h" #include "LuaPlayerController.h"
#include "GameplayTagContainer.h"
#include "InputAction.h"
#include "LevelPlayerController.generated.h" #include "LevelPlayerController.generated.h"
UINTERFACE(MinimalAPI, Blueprintable) UINTERFACE(MinimalAPI, Blueprintable)
class UBusyControllable: public UInterface class UBusyControllable: public UInterface
{ {
GENERATED_BODY() GENERATED_BODY()
}; };
class IBusyControllable class IBusyControllable
{ {
GENERATED_BODY() GENERATED_BODY()
@ -29,8 +31,22 @@ public:
}; };
struct FInputActionValue;
class ABusyPlayerRole; class ABusyPlayerRole;
struct FInputActionValue;
USTRUCT(BlueprintType)
struct FBusySkillActionConfig
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly)
FGameplayTag ActionTag;
UPROPERTY(EditAnywhere, BlueprintReadOnly)
UInputAction* InputAction;
};
UCLASS() UCLASS()
class ALevelPlayerController : public ALuaPlayerController class ALevelPlayerController : public ALuaPlayerController
@ -48,6 +64,14 @@ public:
UFUNCTION(BlueprintCallable, Category = "Controller") UFUNCTION(BlueprintCallable, Category = "Controller")
bool GetCursorPosition(FVector2D& Position) const; bool GetCursorPosition(FVector2D& Position) const;
/**
* 获取光标相对于所控制的人物的方向
* @param Direction
* @return false -> 获取失败, 没有角色或者鼠标不在游戏内
*/
UFUNCTION(BlueprintCallable, Category = "Controller")
bool GetCursorDirection(FVector2D& Direction) const;
UFUNCTION(BlueprintCallable, Category = "Controller") UFUNCTION(BlueprintCallable, Category = "Controller")
ABusyPlayerRole* GetControlledRole() const; ABusyPlayerRole* GetControlledRole() const;
@ -88,6 +112,10 @@ public: // 输入相关
UPROPERTY(EditDefaultsOnly, Category = "Input") UPROPERTY(EditDefaultsOnly, Category = "Input")
TObjectPtr<class UInputAction> SwitchRoleAction; // 切换控制的角色 TObjectPtr<class UInputAction> SwitchRoleAction; // 切换控制的角色
UPROPERTY(EditDefaultsOnly, Category = "Input")
TArray<FBusySkillActionConfig> RoleSkillActions;
public: public:
UFUNCTION() UFUNCTION()
void OnMove(const FInputActionValue& Value)const; void OnMove(const FInputActionValue& Value)const;
@ -104,6 +132,9 @@ public:
UFUNCTION() UFUNCTION()
void OnSwitchRole(const FInputActionValue& Value); void OnSwitchRole(const FInputActionValue& Value);
UFUNCTION()
void OnRoleSkillTriggered(FGameplayTag GameplayTag);
protected: protected:
UPROPERTY() UPROPERTY()