Compare commits

...

2 Commits

Author SHA1 Message Date
9a18402811 更新技能配置 2025-09-02 17:26:50 +08:00
a39e01cefa 更新文档 合并背包分支 2025-09-01 14:26:26 +08:00
14 changed files with 223 additions and 140 deletions

View File

@ -2,3 +2,23 @@
#include "SkillAsset.h"
#include "Misc/Guid.h"
USkillAsset::USkillAsset()
{
// Initialize with a new GUID
SkillID = FGuid::NewGuid();
}
#if WITH_EDITOR
void USkillAsset::PostInitProperties()
{
Super::PostInitProperties();
// Generate a new GUID if it's not valid (for new assets)
if (!SkillID.IsValid())
{
SkillID = FGuid::NewGuid();
}
}
#endif

View File

@ -17,37 +17,53 @@ class PROJECTFISH_API USkillAsset : public UDataAsset
{
GENERATED_BODY()
public:
USkillAsset();
#if WITH_EDITOR
virtual void PostInitProperties() override;
#endif
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能ID"))
FGuid SkillID;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能名称"))
FText SkillName;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能分类Tag"))
TArray<ESkillType> SkillTypes;
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta = (AllowedClasses = "Texture2D", ToolTip = "技能图片"))
FSoftObjectPath SkillTexture;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能Tag"))
FGameplayTag SkillTag;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能效果组"))
TArray<FSkillEffectData> SkillEffects;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "背包占用"))
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能尺寸"))
ESkillSize SkillSize = ESkillSize::Small;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "是否为主动技能"))
bool bActiveSkill = true;
//主动技能属性
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能CD", EditConditionHides, EditCondition = "bActiveSkill"))
float CD;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "卡牌稀有度"))
ERarityType RarityType = ERarityType::Common;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能CD速度", EditConditionHides, EditCondition = "bActiveSkill"))
float Speed = 1.0f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能触发类型"))
ESkillTriggerType triggerType = ESkillTriggerType::ActiveSkill;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能耐久度", EditConditionHides, EditCondition = "bActiveSkill"))
int32 Endurance;
//主动技能属性
UPROPERTY( BlueprintReadWrite, meta = (ToolTip = "技能CD", EditConditionHides, EditCondition = "triggerType == ESkillTriggerType::ActiveSkill"))
float CD;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能CD速度", EditConditionHides, EditCondition = "triggerType == ESkillTriggerType::ActiveSkill"))
float Speed = 1.0f;
//被动技能属性
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "被动技能触发器,没有配置的话为光环类技能默认进行触发", AllowedClasses = "SkillTrigger", EditConditionHides, EditCondition = "!bActiveSkill"))
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "被动技能触发器,没有配置的话为光环类技能默认进行触发", AllowedClasses = "SkillTrigger",
EditConditionHides, EditCondition = "triggerType == ESkillTriggerType::PassiveSkill"))
TSubclassOf<class USkillTrigger> SkillTrigger;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能效果组"))
TArray<FSkillEffectData> SkillEffects;
};

View File

@ -22,33 +22,43 @@ enum class ESkillEffectType: uint8
DamageReduce UMETA(DisplayName = "减伤", ToolTip = "减少所受的伤害"),
};
//技能对象类型
UENUM(BlueprintType)
enum class ESkillTargetType: uint8
{
Self UMETA(DisplayName = "目标是自身角色"),
Other UMETA(DisplayName = "目标是对方角色"),
Around UMETA(DisplayName = "格子周围的技能")
// AdjacentLeft UMETA(DisplayName = "左侧相邻"),
// AdjacentRight UMETA(DisplayName = "右侧相邻"),
// AllLeft UMETA(DisplayName = "左侧全部"),
// AllRight UMETA(DisplayName = "右侧全部"),
};
//随机对象类型
UENUM(BlueprintType)
enum class ERandomTargetType: uint8
{
AllSelf UMETA(DisplayName = "我方全部技能"),
AllOther UMETA(DisplayName = "敌方全部技能"),
};
//技能选择器类型
UENUM(BlueprintType)
enum class ETargetSelecterType: uint8
enum class EEffectTargetType: uint8
{
SkillPos UMETA(DisplayName = "指定对象选择"),
SkillTag UMETA(DisplayName = "根据技能Tag选择"),
RandomScope UMETA(DisplayName = "指定技能组选择"),
Target UMETA(DisplayName = "对方本体"),
Self UMETA(DisplayName = "自身"),
TargetSkill UMETA(DisplayName = "对方的装备"),
SelfSkill UMETA(DisplayName = "自身的装备"),
AroundSkill UMETA(DisplayName = "当前装备周围的装备"),
SelfSkillType UMETA(DisplayName = "自身指定分类的装备"),
TargetSkillType UMETA(DisplayName = "对方指定分类的装备"),
};
UENUM(BlueprintType)
enum class ERarityType: uint8
{
Common UMETA(DisplayName = "普通"),
UnCommon UMETA(DisplayName = "精良"),
Rare UMETA(DisplayName = "稀有"),
};
UENUM(BlueprintType)
enum class ESkillTriggerType: uint8
{
ActiveSkill UMETA(DisplayName = "主动技能"),
PassiveSkill UMETA(DisplayName = "被动技能"),
AuraSkill UMETA(DisplayName = "光环技能"),
};
UENUM(BlueprintType)
enum class ESkillType: uint8
{
Type1 UMETA(DisplayName = "Type1"),
Type2 UMETA(DisplayName = "Type2"),
Type3 UMETA(DisplayName = "Type3"),
};
UENUM(BlueprintType)
@ -89,19 +99,21 @@ struct FSkillTargetSelector
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能选择器类型"))
ETargetSelecterType SelecterType;
EEffectTargetType SelecterType;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "技能目标类型",
EditConditionHides, EditCondition = "SelecterType == ETargetSelecterType::SkillPos"))
ESkillTargetType TargetType;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "指定技能的分类"
, EditConditionHides, EditCondition = "SelecterType == EEffectTargetType::SelfSkillType || SelecterType == EEffectTargetType::TargetSkillType"))
ESkillType SkillType = ESkillType::Type1;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "目标是否全部还是指定数目"
, EditConditionHides, EditCondition = "SelecterType != EEffectTargetType::Target && SelecterType != EEffectTargetType::Self"))
bool bAll = true;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "应用的技能tag",
EditConditionHides, EditCondition = "SelecterType == ETargetSelecterType::SkillTag"))
FGameplayTagContainer ApplySkillTags;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "随机目标类型"
, EditConditionHides, EditCondition = "SelecterType == ETargetSelecterType::RandomScope"))
ERandomTargetType RandomType;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (ToolTip = "指定数目"
, EditConditionHides, EditCondition = "SelecterType != EEffectTargetType::Target && SelecterType != EEffectTargetType::Self && !bAll"))
int32 MaxEffectTargetNum = 1;
};
//技能效果

View File

@ -3,6 +3,7 @@
#include "Skill.h"
#include "InputTriggers.h"
#include "SkillTrigger.h"
#include "SkillEffects/SkillEffect_Charge.h"
#include "SkillEffects/SkillEffect_Damage.h"
@ -122,8 +123,9 @@ void USkill::InitSkill(class APawnWithSkill* owner, USkillManager* skillManager,
void USkill::InitSkillTrigger()
{
if (!SkillData->bActiveSkill)
switch (SkillData->triggerType)
{
case ESkillTriggerType::PassiveSkill:
if (SkillData->SkillTrigger)
{
USkillTrigger* SkillTrigger = NewObject<USkillTrigger>(this, SkillData->SkillTrigger);
@ -132,19 +134,21 @@ void USkill::InitSkillTrigger()
context.SkillManager = SkillManager;
SkillTrigger->Init(context);
}
else
{
break;
case ESkillTriggerType::AuraSkill:
//UE_LOG(LogTemp, Warning, TEXT("没有Trigger的被动技能直接触发"));
ExecuteSkill();
}
break;
}
}
bool USkill::SkillTickAble()
{
//剩余次数无限制或者拥有者没有被韧性眩晕
return (RemainingEndurance >0 || RemainingEndurance == -1 ) && Owner->CurrentTenacity > 0 && SkillData->bActiveSkill;
return (RemainingEndurance >0 || RemainingEndurance == -1 )
&& Owner->CurrentTenacity > 0 && SkillData->triggerType == ESkillTriggerType::ActiveSkill;
}
FIntPoint USkill::GetSkillSize()

View File

@ -50,58 +50,121 @@ TArray<UObject*> USkillEffect::GetApplyTargets(const FSkillContext& context)
TArray<UObject*> result;
switch (effectData.SkillSelecter.SelecterType)
{
case ETargetSelecterType::SkillPos:
case EEffectTargetType::Target:
{
GetEffectTargetsByTargetType(context, result);
break;;
//目标是敌人
result.Add(context.SkillManager->GetEnemyPawn(OwnerSkill->GetOwner()));
break;;
}
case ETargetSelecterType::SkillTag:
{
//根据Tag 决定应用对象
for (auto skill: context.SkillManager->GetAllSkills())
case EEffectTargetType::Self:
{
if (effectData.SkillSelecter.ApplySkillTags.HasTag(skill->GetSkillData()->SkillTag))
//目标是敌人
result.Add(OwnerSkill->GetOwner());
break;;
}
case EEffectTargetType::TargetSkill:
{
TArray<USkill*> Skills = context.SkillManager->GetSkillsByOwner(context.SkillManager->GetEnemyPawn(OwnerSkill->GetOwner()));
if (effectData.SkillSelecter.bAll)
{
result.Append(Skills);
}
else
{
int TargetNum = FMath::Min(effectData.SkillSelecter.MaxEffectTargetNum, Skills.Num());
for (int i = 0; i < TargetNum; i++)
{
int randomIndex = FMath::RandRange(0, Skills.Num() - 1);
result.Add(Skills[randomIndex]);
Skills.RemoveAt(randomIndex);
}
}
break;;
}
case EEffectTargetType::SelfSkill:
{
TArray<USkill*> Skills = context.SkillManager->GetSkillsByOwner(OwnerSkill->GetOwner());
if (effectData.SkillSelecter.bAll)
{
result.Append(Skills);
}
else
{
int TargetNum = FMath::Min(effectData.SkillSelecter.MaxEffectTargetNum, Skills.Num());
for (int i = 0; i < TargetNum; i++)
{
int randomIndex = FMath::RandRange(0, Skills.Num() - 1);
result.Add(Skills[randomIndex]);
Skills.RemoveAt(randomIndex);
}
}
break;;
}
case EEffectTargetType::AroundSkill:
{
TArray<USkill*> aroundSkills = context.SkillManager->GetSkillsAround(context.OwnerSkill);
for (auto skill: aroundSkills)
{
result.Add(skill);
}
break;
}
break;;
}
case ETargetSelecterType::RandomScope:
{
//应用到随机技能
switch (effectData.SkillSelecter.RandomType)
case EEffectTargetType::SelfSkillType:
{
case ERandomTargetType::AllSelf:
//筛选指定类型的技能
TArray<USkill*> Skills = context.SkillManager->GetSkillsByOwner(OwnerSkill->GetOwner());
for (int i = Skills.Num() - 1; i >= 0; i--)
{
//所有我方的技能
for (auto skill: context.SkillManager->GetAllSkills())
{
if (OwnerSkill->GetOwner() == skill->GetOwner())
{
result.Add(skill);
}
}
break;
if (!Skills[i]->GetSkillData()->SkillTypes.Contains(effectData.SkillSelecter.SkillType))
{
Skills.RemoveAt(i);
}
}
case ERandomTargetType::AllOther:
if (effectData.SkillSelecter.bAll)
{
//所有地方的技能
for (auto skill: context.SkillManager->GetAllSkills())
{
if (OwnerSkill->GetOwner() != skill->GetOwner())
{
result.Add(skill);
}
}
break;
result.Append(Skills);
}
else
{
int TargetNum = FMath::Min(effectData.SkillSelecter.MaxEffectTargetNum, Skills.Num());
for (int i = 0; i < TargetNum; i++)
{
int randomIndex = FMath::RandRange(0, Skills.Num() - 1);
result.Add(Skills[randomIndex]);
Skills.RemoveAt(randomIndex);
}
}
break;
}
case EEffectTargetType::TargetSkillType:
{
//筛选指定类型的技能
TArray<USkill*> Skills = context.SkillManager->GetSkillsByOwner(context.SkillManager->GetEnemyPawn(OwnerSkill->GetOwner()));
for (int i = Skills.Num() - 1; i >= 0; i--)
{
if (!Skills[i]->GetSkillData()->SkillTypes.Contains(effectData.SkillSelecter.SkillType))
{
Skills.RemoveAt(i);
}
}
if (effectData.SkillSelecter.bAll)
{
result.Append(Skills);
}
else
{
int TargetNum = FMath::Min(effectData.SkillSelecter.MaxEffectTargetNum, Skills.Num());
for (int i = 0; i < TargetNum; i++)
{
int randomIndex = FMath::RandRange(0, Skills.Num() - 1);
result.Add(Skills[randomIndex]);
Skills.RemoveAt(randomIndex);
}
}
break;
}
break;
}
}
return result;
}
@ -111,37 +174,3 @@ FString USkillEffect::GetSkillEffectDes()
return FString();
}
void USkillEffect::GetEffectTargetsByTargetType(const FSkillContext& context, TArray<UObject*>& result)
{
//根据位置决定应用对象
ESkillTargetType targetType = effectData.SkillSelecter.TargetType;
switch (targetType)
{
case ESkillTargetType::Self:
{
result.Add(OwnerSkill->GetOwner());
break;
}
case ESkillTargetType::Other:
{
for (auto pawn: context.SkillManager->GetAllPawns())
{
if (pawn != OwnerSkill->GetOwner())
{
result.Add(pawn);
}
}
break;
}
case ESkillTargetType::Around:
{
//技能左侧的技能
TArray<USkill*> aroundSkills = context.SkillManager->GetSkillsAround(context.OwnerSkill);
for (auto skill: aroundSkills)
{
result.Add(skill);
}
break;;
}
}
}

View File

@ -27,8 +27,7 @@ public:
{
return effectData;
}
private:
void GetEffectTargetsByTargetType(const FSkillContext& context, TArray<UObject*>& result);
protected:
UPROPERTY()
class USkill* OwnerSkill;

View File

@ -112,15 +112,7 @@ void USkillManager::OnAllSkillAdded()
}
}
class USkill* USkillManager::GetSkillByTag(FGameplayTag Tag)
{
for (auto Skill : Skills)
{
if (Skill->GetSkillData()->SkillTag == Tag)
return Skill;
}
return nullptr;
}
int32 USkillManager::GetSkillIndex(USkill* Skill)
{
@ -168,6 +160,16 @@ TArray<APawnWithSkill*> USkillManager::GetAllPawns()
return Pawns;
}
APawnWithSkill* USkillManager::GetEnemyPawn(const APawnWithSkill* SelfPawn)
{
for (auto info: PawnInfo)
{
if (SelfPawn != info.Key)
return info.Key;
}
return nullptr;
}
TArray<class USkill*> USkillManager::GetSkillsByOwner(APawnWithSkill* Pawn)
{
TArray<class USkill*> skills;

View File

@ -32,9 +32,7 @@ public:
UFUNCTION(BlueprintCallable)
void OnAllSkillAdded();
UFUNCTION(BlueprintPure)
class USkill* GetSkillByTag(FGameplayTag Tag);
int32 GetSkillIndex(USkill* Skill);
@ -47,6 +45,9 @@ public:
UFUNCTION(BlueprintCallable)
TArray<APawnWithSkill*> GetAllPawns();
UFUNCTION(BlueprintCallable)
APawnWithSkill* GetEnemyPawn(const APawnWithSkill* SelfPawn);
UFUNCTION(BlueprintPure)
TArray<class USkill*> GetSkillsByOwner(APawnWithSkill* Pawn);

Binary file not shown.

Binary file not shown.

Binary file not shown.