Add PHY gameplay attributes

This commit is contained in:
2026-04-26 01:30:00 +08:00
parent ddb5f599f9
commit 408a764560
19 changed files with 1515 additions and 0 deletions

View File

@@ -2,3 +2,8 @@
bRequireServerAuthority=True
bEnableClientPrediction=True
DefaultHitConfirmWindow=0.200000
[/Script/PHY.PHYAttributeSettings]
DefaultCoreAttributes=(Strength=10.000000,Dexterity=10.000000,Vitality=10.000000,Intelligence=10.000000,Spirit=10.000000,Perception=10.000000)
CombatFormula=(MaxHealthBase=100.000000,MaxHealthVitality=18.000000,MaxHealthStrength=3.000000,MaxManaBase=60.000000,MaxManaIntelligence=12.000000,MaxManaSpirit=6.000000,MaxStaminaBase=80.000000,MaxStaminaVitality=5.000000,MaxStaminaDexterity=4.000000,PhysicalAttackPowerStrength=2.000000,PhysicalAttackPowerDexterity=0.500000,SpellPowerIntelligence=2.000000,SpellPowerSpirit=0.400000,ArmorVitality=1.200000,ArmorStrength=0.400000,MagicResistanceSpirit=1.100000,MagicResistanceIntelligence=0.300000,AccuracyBase=0.800000,AccuracyPerception=0.006000,AccuracyDexterity=0.002000,EvasionBase=0.030000,EvasionDexterity=0.003000,EvasionPerception=0.001000,CriticalChanceBase=0.050000,CriticalChanceDexterity=0.002000,CriticalChancePerception=0.001500,CriticalDamageBase=1.500000,CriticalDamageStrength=0.004000,CriticalDamagePerception=0.003000,AttackSpeedBase=1.000000,AttackSpeedDexterity=0.010000,CooldownReductionBase=0.000000,CooldownReductionIntelligence=0.001500,CooldownReductionSpirit=0.001000,BlockPowerBase=5.000000,BlockPowerStrength=1.200000,BlockPowerVitality=0.600000,GuardBreakPowerBase=5.000000,GuardBreakPowerStrength=1.100000,GuardBreakPowerPerception=0.400000,PoiseBase=20.000000,PoiseVitality=1.500000,PoiseStrength=0.500000,PoiseDamageBase=5.000000,PoiseDamageStrength=0.800000,PoiseDamageDexterity=0.200000)
ElementFormula=(DamageBonusBase=0.000000,DamageBonusIntelligence=0.001500,DamageBonusPerception=0.000500,ResistanceBase=0.020000,ResistanceSpirit=0.002000,ResistanceVitality=0.000500,PenetrationBase=0.000000,PenetrationPerception=0.001000,PenetrationIntelligence=0.000500)

View File

@@ -0,0 +1,74 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "AbilitySystem/Attributes/PHYAttributeCalculationLibrary.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYAttributeCalculationLibrary)
#include "AbilitySystem/Attributes/PHYCoreAttributeSet.h"
FPHYCoreAttributeSnapshot UPHYAttributeCalculationLibrary::MakeCoreSnapshotFromDefaults()
{
const FPHYCoreAttributeDefaults& Defaults = GetDefault<UPHYAttributeSettings>()->DefaultCoreAttributes;
FPHYCoreAttributeSnapshot Snapshot;
Snapshot.Strength = Defaults.Strength;
Snapshot.Dexterity = Defaults.Dexterity;
Snapshot.Vitality = Defaults.Vitality;
Snapshot.Intelligence = Defaults.Intelligence;
Snapshot.Spirit = Defaults.Spirit;
Snapshot.Perception = Defaults.Perception;
return Snapshot;
}
FPHYCoreAttributeSnapshot UPHYAttributeCalculationLibrary::MakeCoreSnapshotFromAttributeSet(const UPHYCoreAttributeSet* CoreAttributes)
{
if (!CoreAttributes)
{
return MakeCoreSnapshotFromDefaults();
}
FPHYCoreAttributeSnapshot Snapshot;
Snapshot.Strength = CoreAttributes->GetStrength();
Snapshot.Dexterity = CoreAttributes->GetDexterity();
Snapshot.Vitality = CoreAttributes->GetVitality();
Snapshot.Intelligence = CoreAttributes->GetIntelligence();
Snapshot.Spirit = CoreAttributes->GetSpirit();
Snapshot.Perception = CoreAttributes->GetPerception();
return Snapshot;
}
FPHYDerivedCombatAttributes UPHYAttributeCalculationLibrary::CalculateCombatAttributes(const FPHYCoreAttributeSnapshot& CoreAttributes)
{
const FPHYCombatAttributeFormula& Formula = GetDefault<UPHYAttributeSettings>()->CombatFormula;
FPHYDerivedCombatAttributes Result;
Result.MaxHealth = Formula.MaxHealthBase + CoreAttributes.Vitality * Formula.MaxHealthVitality + CoreAttributes.Strength * Formula.MaxHealthStrength;
Result.MaxMana = Formula.MaxManaBase + CoreAttributes.Intelligence * Formula.MaxManaIntelligence + CoreAttributes.Spirit * Formula.MaxManaSpirit;
Result.MaxStamina = Formula.MaxStaminaBase + CoreAttributes.Vitality * Formula.MaxStaminaVitality + CoreAttributes.Dexterity * Formula.MaxStaminaDexterity;
Result.PhysicalAttackPower = CoreAttributes.Strength * Formula.PhysicalAttackPowerStrength + CoreAttributes.Dexterity * Formula.PhysicalAttackPowerDexterity;
Result.SpellPower = CoreAttributes.Intelligence * Formula.SpellPowerIntelligence + CoreAttributes.Spirit * Formula.SpellPowerSpirit;
Result.Armor = CoreAttributes.Vitality * Formula.ArmorVitality + CoreAttributes.Strength * Formula.ArmorStrength;
Result.MagicResistance = CoreAttributes.Spirit * Formula.MagicResistanceSpirit + CoreAttributes.Intelligence * Formula.MagicResistanceIntelligence;
Result.Accuracy = FMath::Clamp(Formula.AccuracyBase + CoreAttributes.Perception * Formula.AccuracyPerception + CoreAttributes.Dexterity * Formula.AccuracyDexterity, 0.0f, 1.0f);
Result.Evasion = FMath::Clamp(Formula.EvasionBase + CoreAttributes.Dexterity * Formula.EvasionDexterity + CoreAttributes.Perception * Formula.EvasionPerception, 0.0f, 0.6f);
Result.CriticalChance = FMath::Clamp(Formula.CriticalChanceBase + CoreAttributes.Dexterity * Formula.CriticalChanceDexterity + CoreAttributes.Perception * Formula.CriticalChancePerception, 0.0f, 0.6f);
Result.CriticalDamage = FMath::Clamp(Formula.CriticalDamageBase + CoreAttributes.Strength * Formula.CriticalDamageStrength + CoreAttributes.Perception * Formula.CriticalDamagePerception, 1.0f, 3.0f);
Result.AttackSpeed = FMath::Clamp(Formula.AttackSpeedBase + CoreAttributes.Dexterity * Formula.AttackSpeedDexterity, 0.2f, 3.0f);
Result.CooldownReduction = FMath::Clamp(Formula.CooldownReductionBase + CoreAttributes.Intelligence * Formula.CooldownReductionIntelligence + CoreAttributes.Spirit * Formula.CooldownReductionSpirit, 0.0f, 0.6f);
Result.BlockPower = Formula.BlockPowerBase + CoreAttributes.Strength * Formula.BlockPowerStrength + CoreAttributes.Vitality * Formula.BlockPowerVitality;
Result.GuardBreakPower = Formula.GuardBreakPowerBase + CoreAttributes.Strength * Formula.GuardBreakPowerStrength + CoreAttributes.Perception * Formula.GuardBreakPowerPerception;
Result.Poise = Formula.PoiseBase + CoreAttributes.Vitality * Formula.PoiseVitality + CoreAttributes.Strength * Formula.PoiseStrength;
Result.PoiseDamage = Formula.PoiseDamageBase + CoreAttributes.Strength * Formula.PoiseDamageStrength + CoreAttributes.Dexterity * Formula.PoiseDamageDexterity;
return Result;
}
FPHYDerivedElementAttributes UPHYAttributeCalculationLibrary::CalculateElementAttributes(const FPHYCoreAttributeSnapshot& CoreAttributes)
{
const FPHYElementAttributeFormula& Formula = GetDefault<UPHYAttributeSettings>()->ElementFormula;
FPHYDerivedElementAttributes Result;
Result.DamageBonus = FMath::Clamp(Formula.DamageBonusBase + CoreAttributes.Intelligence * Formula.DamageBonusIntelligence + CoreAttributes.Perception * Formula.DamageBonusPerception, 0.0f, 2.0f);
Result.Resistance = FMath::Clamp(Formula.ResistanceBase + CoreAttributes.Spirit * Formula.ResistanceSpirit + CoreAttributes.Vitality * Formula.ResistanceVitality, 0.0f, 0.75f);
Result.Penetration = FMath::Clamp(Formula.PenetrationBase + CoreAttributes.Perception * Formula.PenetrationPerception + CoreAttributes.Intelligence * Formula.PenetrationIntelligence, 0.0f, 0.75f);
return Result;
}

View File

@@ -0,0 +1,5 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "AbilitySystem/Attributes/PHYAttributeSettings.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYAttributeSettings)

View File

@@ -0,0 +1,202 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "AbilitySystem/Attributes/PHYCombatAttributeSet.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYCombatAttributeSet)
#include "AbilitySystem/Attributes/PHYAttributeCalculationLibrary.h"
#include "AbilitySystem/Attributes/PHYCoreAttributeSet.h"
#include "GameplayEffectExtension.h"
#include "Net/UnrealNetwork.h"
UPHYCombatAttributeSet::UPHYCombatAttributeSet()
{
InitializeFromConfiguredCoreDefaults();
}
void UPHYCombatAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, Health, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, Mana, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, MaxMana, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, Stamina, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, MaxStamina, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, PhysicalAttackPower, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, SpellPower, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, Armor, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, MagicResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, Accuracy, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, Evasion, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, CriticalChance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, CriticalDamage, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, AttackSpeed, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, CooldownReduction, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, BlockPower, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, GuardBreakPower, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, Poise, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCombatAttributeSet, PoiseDamage, COND_None, REPNOTIFY_Always);
}
void UPHYCombatAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
if (Attribute == GetHealthAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxHealth());
}
else if (Attribute == GetManaAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxMana());
}
else if (Attribute == GetStaminaAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxStamina());
}
else if (Attribute == GetMaxHealthAttribute() || Attribute == GetMaxManaAttribute() || Attribute == GetMaxStaminaAttribute())
{
NewValue = FMath::Max(NewValue, 1.0f);
}
else if (Attribute == GetAccuracyAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.0f, 1.0f);
}
else if (Attribute == GetEvasionAttribute() || Attribute == GetCriticalChanceAttribute() || Attribute == GetCooldownReductionAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.0f, 0.6f);
}
else if (Attribute == GetCriticalDamageAttribute())
{
NewValue = FMath::Clamp(NewValue, 1.0f, 5.0f);
}
else if (Attribute == GetAttackSpeedAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.1f, 5.0f);
}
else
{
NewValue = FMath::Max(NewValue, 0.0f);
}
}
void UPHYCombatAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
SetHealth(FMath::Clamp(GetHealth(), 0.0f, GetMaxHealth()));
}
else if (Data.EvaluatedData.Attribute == GetManaAttribute())
{
SetMana(FMath::Clamp(GetMana(), 0.0f, GetMaxMana()));
}
else if (Data.EvaluatedData.Attribute == GetStaminaAttribute())
{
SetStamina(FMath::Clamp(GetStamina(), 0.0f, GetMaxStamina()));
}
}
void UPHYCombatAttributeSet::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
Super::PostAttributeChange(Attribute, OldValue, NewValue);
if (Attribute == GetMaxHealthAttribute() && GetHealth() > NewValue)
{
SetHealth(NewValue);
}
else if (Attribute == GetMaxManaAttribute() && GetMana() > NewValue)
{
SetMana(NewValue);
}
else if (Attribute == GetMaxStaminaAttribute() && GetStamina() > NewValue)
{
SetStamina(NewValue);
}
}
void UPHYCombatAttributeSet::InitializeFromConfiguredCoreDefaults()
{
const FPHYCoreAttributeSnapshot Snapshot = UPHYAttributeCalculationLibrary::MakeCoreSnapshotFromDefaults();
const FPHYDerivedCombatAttributes Derived = UPHYAttributeCalculationLibrary::CalculateCombatAttributes(Snapshot);
InitMaxHealth(Derived.MaxHealth);
InitHealth(Derived.MaxHealth);
InitMaxMana(Derived.MaxMana);
InitMana(Derived.MaxMana);
InitMaxStamina(Derived.MaxStamina);
InitStamina(Derived.MaxStamina);
InitPhysicalAttackPower(Derived.PhysicalAttackPower);
InitSpellPower(Derived.SpellPower);
InitArmor(Derived.Armor);
InitMagicResistance(Derived.MagicResistance);
InitAccuracy(Derived.Accuracy);
InitEvasion(Derived.Evasion);
InitCriticalChance(Derived.CriticalChance);
InitCriticalDamage(Derived.CriticalDamage);
InitAttackSpeed(Derived.AttackSpeed);
InitCooldownReduction(Derived.CooldownReduction);
InitBlockPower(Derived.BlockPower);
InitGuardBreakPower(Derived.GuardBreakPower);
InitPoise(Derived.Poise);
InitPoiseDamage(Derived.PoiseDamage);
}
void UPHYCombatAttributeSet::InitializeFromCoreAttributes(const UPHYCoreAttributeSet* CoreAttributes)
{
const FPHYCoreAttributeSnapshot Snapshot = UPHYAttributeCalculationLibrary::MakeCoreSnapshotFromAttributeSet(CoreAttributes);
const FPHYDerivedCombatAttributes Derived = UPHYAttributeCalculationLibrary::CalculateCombatAttributes(Snapshot);
SetMaxHealth(Derived.MaxHealth);
SetHealth(FMath::Clamp(GetHealth(), 0.0f, Derived.MaxHealth));
SetMaxMana(Derived.MaxMana);
SetMana(FMath::Clamp(GetMana(), 0.0f, Derived.MaxMana));
SetMaxStamina(Derived.MaxStamina);
SetStamina(FMath::Clamp(GetStamina(), 0.0f, Derived.MaxStamina));
SetPhysicalAttackPower(Derived.PhysicalAttackPower);
SetSpellPower(Derived.SpellPower);
SetArmor(Derived.Armor);
SetMagicResistance(Derived.MagicResistance);
SetAccuracy(Derived.Accuracy);
SetEvasion(Derived.Evasion);
SetCriticalChance(Derived.CriticalChance);
SetCriticalDamage(Derived.CriticalDamage);
SetAttackSpeed(Derived.AttackSpeed);
SetCooldownReduction(Derived.CooldownReduction);
SetBlockPower(Derived.BlockPower);
SetGuardBreakPower(Derived.GuardBreakPower);
SetPoise(Derived.Poise);
SetPoiseDamage(Derived.PoiseDamage);
}
#define PHY_COMBAT_REPNOTIFY(PropertyName) \
void UPHYCombatAttributeSet::OnRep_##PropertyName(const FGameplayAttributeData& OldValue) \
{ \
GAMEPLAYATTRIBUTE_REPNOTIFY(UPHYCombatAttributeSet, PropertyName, OldValue); \
}
PHY_COMBAT_REPNOTIFY(Health)
PHY_COMBAT_REPNOTIFY(MaxHealth)
PHY_COMBAT_REPNOTIFY(Mana)
PHY_COMBAT_REPNOTIFY(MaxMana)
PHY_COMBAT_REPNOTIFY(Stamina)
PHY_COMBAT_REPNOTIFY(MaxStamina)
PHY_COMBAT_REPNOTIFY(PhysicalAttackPower)
PHY_COMBAT_REPNOTIFY(SpellPower)
PHY_COMBAT_REPNOTIFY(Armor)
PHY_COMBAT_REPNOTIFY(MagicResistance)
PHY_COMBAT_REPNOTIFY(Accuracy)
PHY_COMBAT_REPNOTIFY(Evasion)
PHY_COMBAT_REPNOTIFY(CriticalChance)
PHY_COMBAT_REPNOTIFY(CriticalDamage)
PHY_COMBAT_REPNOTIFY(AttackSpeed)
PHY_COMBAT_REPNOTIFY(CooldownReduction)
PHY_COMBAT_REPNOTIFY(BlockPower)
PHY_COMBAT_REPNOTIFY(GuardBreakPower)
PHY_COMBAT_REPNOTIFY(Poise)
PHY_COMBAT_REPNOTIFY(PoiseDamage)
#undef PHY_COMBAT_REPNOTIFY

View File

@@ -0,0 +1,62 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "AbilitySystem/Attributes/PHYCoreAttributeSet.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYCoreAttributeSet)
#include "AbilitySystem/Attributes/PHYAttributeSettings.h"
#include "Net/UnrealNetwork.h"
UPHYCoreAttributeSet::UPHYCoreAttributeSet()
{
const FPHYCoreAttributeDefaults& Defaults = GetDefault<UPHYAttributeSettings>()->DefaultCoreAttributes;
InitStrength(Defaults.Strength);
InitDexterity(Defaults.Dexterity);
InitVitality(Defaults.Vitality);
InitIntelligence(Defaults.Intelligence);
InitSpirit(Defaults.Spirit);
InitPerception(Defaults.Perception);
}
void UPHYCoreAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCoreAttributeSet, Strength, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCoreAttributeSet, Dexterity, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCoreAttributeSet, Vitality, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCoreAttributeSet, Intelligence, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCoreAttributeSet, Spirit, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYCoreAttributeSet, Perception, COND_None, REPNOTIFY_Always);
}
void UPHYCoreAttributeSet::OnRep_Strength(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UPHYCoreAttributeSet, Strength, OldValue);
}
void UPHYCoreAttributeSet::OnRep_Dexterity(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UPHYCoreAttributeSet, Dexterity, OldValue);
}
void UPHYCoreAttributeSet::OnRep_Vitality(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UPHYCoreAttributeSet, Vitality, OldValue);
}
void UPHYCoreAttributeSet::OnRep_Intelligence(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UPHYCoreAttributeSet, Intelligence, OldValue);
}
void UPHYCoreAttributeSet::OnRep_Spirit(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UPHYCoreAttributeSet, Spirit, OldValue);
}
void UPHYCoreAttributeSet::OnRep_Perception(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(UPHYCoreAttributeSet, Perception, OldValue);
}

View File

@@ -0,0 +1,128 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "AbilitySystem/Attributes/PHYElementAttributeSet.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYElementAttributeSet)
#include "AbilitySystem/Attributes/PHYAttributeCalculationLibrary.h"
#include "AbilitySystem/Attributes/PHYCoreAttributeSet.h"
#include "Net/UnrealNetwork.h"
UPHYElementAttributeSet::UPHYElementAttributeSet()
{
InitializeFromConfiguredCoreDefaults();
}
void UPHYElementAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, FireDamageBonus, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, WaterDamageBonus, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, IceDamageBonus, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, LightningDamageBonus, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, EarthDamageBonus, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, WindDamageBonus, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, LightDamageBonus, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, DarkDamageBonus, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, FireResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, WaterResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, IceResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, LightningResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, EarthResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, WindResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, LightResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, DarkResistance, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(UPHYElementAttributeSet, ElementPenetration, COND_None, REPNOTIFY_Always);
}
void UPHYElementAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
if (Attribute == GetFireResistanceAttribute() || Attribute == GetWaterResistanceAttribute() ||
Attribute == GetIceResistanceAttribute() || Attribute == GetLightningResistanceAttribute() ||
Attribute == GetEarthResistanceAttribute() || Attribute == GetWindResistanceAttribute() ||
Attribute == GetLightResistanceAttribute() || Attribute == GetDarkResistanceAttribute() ||
Attribute == GetElementPenetrationAttribute())
{
NewValue = FMath::Clamp(NewValue, 0.0f, 0.75f);
return;
}
NewValue = FMath::Clamp(NewValue, 0.0f, 2.0f);
}
void UPHYElementAttributeSet::InitializeFromConfiguredCoreDefaults()
{
const FPHYCoreAttributeSnapshot Snapshot = UPHYAttributeCalculationLibrary::MakeCoreSnapshotFromDefaults();
const FPHYDerivedElementAttributes Derived = UPHYAttributeCalculationLibrary::CalculateElementAttributes(Snapshot);
InitFireDamageBonus(Derived.DamageBonus);
InitWaterDamageBonus(Derived.DamageBonus);
InitIceDamageBonus(Derived.DamageBonus);
InitLightningDamageBonus(Derived.DamageBonus);
InitEarthDamageBonus(Derived.DamageBonus);
InitWindDamageBonus(Derived.DamageBonus);
InitLightDamageBonus(Derived.DamageBonus);
InitDarkDamageBonus(Derived.DamageBonus);
InitFireResistance(Derived.Resistance);
InitWaterResistance(Derived.Resistance);
InitIceResistance(Derived.Resistance);
InitLightningResistance(Derived.Resistance);
InitEarthResistance(Derived.Resistance);
InitWindResistance(Derived.Resistance);
InitLightResistance(Derived.Resistance);
InitDarkResistance(Derived.Resistance);
InitElementPenetration(Derived.Penetration);
}
void UPHYElementAttributeSet::InitializeFromCoreAttributes(const UPHYCoreAttributeSet* CoreAttributes)
{
const FPHYCoreAttributeSnapshot Snapshot = UPHYAttributeCalculationLibrary::MakeCoreSnapshotFromAttributeSet(CoreAttributes);
const FPHYDerivedElementAttributes Derived = UPHYAttributeCalculationLibrary::CalculateElementAttributes(Snapshot);
SetFireDamageBonus(Derived.DamageBonus);
SetWaterDamageBonus(Derived.DamageBonus);
SetIceDamageBonus(Derived.DamageBonus);
SetLightningDamageBonus(Derived.DamageBonus);
SetEarthDamageBonus(Derived.DamageBonus);
SetWindDamageBonus(Derived.DamageBonus);
SetLightDamageBonus(Derived.DamageBonus);
SetDarkDamageBonus(Derived.DamageBonus);
SetFireResistance(Derived.Resistance);
SetWaterResistance(Derived.Resistance);
SetIceResistance(Derived.Resistance);
SetLightningResistance(Derived.Resistance);
SetEarthResistance(Derived.Resistance);
SetWindResistance(Derived.Resistance);
SetLightResistance(Derived.Resistance);
SetDarkResistance(Derived.Resistance);
SetElementPenetration(Derived.Penetration);
}
#define PHY_ELEMENT_REPNOTIFY(PropertyName) \
void UPHYElementAttributeSet::OnRep_##PropertyName(const FGameplayAttributeData& OldValue) \
{ \
GAMEPLAYATTRIBUTE_REPNOTIFY(UPHYElementAttributeSet, PropertyName, OldValue); \
}
PHY_ELEMENT_REPNOTIFY(FireDamageBonus)
PHY_ELEMENT_REPNOTIFY(WaterDamageBonus)
PHY_ELEMENT_REPNOTIFY(IceDamageBonus)
PHY_ELEMENT_REPNOTIFY(LightningDamageBonus)
PHY_ELEMENT_REPNOTIFY(EarthDamageBonus)
PHY_ELEMENT_REPNOTIFY(WindDamageBonus)
PHY_ELEMENT_REPNOTIFY(LightDamageBonus)
PHY_ELEMENT_REPNOTIFY(DarkDamageBonus)
PHY_ELEMENT_REPNOTIFY(FireResistance)
PHY_ELEMENT_REPNOTIFY(WaterResistance)
PHY_ELEMENT_REPNOTIFY(IceResistance)
PHY_ELEMENT_REPNOTIFY(LightningResistance)
PHY_ELEMENT_REPNOTIFY(EarthResistance)
PHY_ELEMENT_REPNOTIFY(WindResistance)
PHY_ELEMENT_REPNOTIFY(LightResistance)
PHY_ELEMENT_REPNOTIFY(DarkResistance)
PHY_ELEMENT_REPNOTIFY(ElementPenetration)
#undef PHY_ELEMENT_REPNOTIFY

View File

@@ -4,6 +4,9 @@
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYAICharacter)
#include "AbilitySystem/Attributes/PHYCombatAttributeSet.h"
#include "AbilitySystem/Attributes/PHYCoreAttributeSet.h"
#include "AbilitySystem/Attributes/PHYElementAttributeSet.h"
#include "Class/PHYClassComponent.h"
#include "Class/PHYClassSettings.h"
#include "GGA_AbilitySystemComponent.h"
@@ -15,6 +18,10 @@ APHYAICharacter::APHYAICharacter(const FObjectInitializer& ObjectInitializer)
AbilitySystemComponent->SetIsReplicated(true);
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
CoreAttributeSet = CreateDefaultSubobject<UPHYCoreAttributeSet>(TEXT("CoreAttributeSet"));
CombatAttributeSet = CreateDefaultSubobject<UPHYCombatAttributeSet>(TEXT("CombatAttributeSet"));
ElementAttributeSet = CreateDefaultSubobject<UPHYElementAttributeSet>(TEXT("ElementAttributeSet"));
ClassComponent = CreateDefaultSubobject<UPHYClassComponent>(TEXT("ClassComponent"));
ClassComponent->SetClassTag(GetDefault<UPHYClassSettings>()->DefaultAIClassTag);
}

View File

@@ -0,0 +1,35 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#include "GameplayTags/PHYGameplayTags_Attribute.h"
// 属性 Tag 只表达领域和分类,具体属性读写仍通过 GAS AttributeSet 完成。
namespace PHYGameplayTags
{
UE_DEFINE_GAMEPLAY_TAG(Attribute_Core, "Attribute.Core");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Core_Strength, "Attribute.Core.Strength");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Core_Dexterity, "Attribute.Core.Dexterity");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Core_Vitality, "Attribute.Core.Vitality");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Core_Intelligence, "Attribute.Core.Intelligence");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Core_Spirit, "Attribute.Core.Spirit");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Core_Perception, "Attribute.Core.Perception");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Combat, "Attribute.Combat");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Combat_Health, "Attribute.Combat.Health");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Combat_Mana, "Attribute.Combat.Mana");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Combat_Stamina, "Attribute.Combat.Stamina");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Combat_Offense, "Attribute.Combat.Offense");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Combat_Defense, "Attribute.Combat.Defense");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element, "Attribute.Element");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Fire, "Attribute.Element.Fire");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Water, "Attribute.Element.Water");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Ice, "Attribute.Element.Ice");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Lightning, "Attribute.Element.Lightning");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Earth, "Attribute.Element.Earth");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Wind, "Attribute.Element.Wind");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Light, "Attribute.Element.Light");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Dark, "Attribute.Element.Dark");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_DamageBonus, "Attribute.Element.DamageBonus");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Resistance, "Attribute.Element.Resistance");
UE_DEFINE_GAMEPLAY_TAG(Attribute_Element_Penetration, "Attribute.Element.Penetration");
}

View File

@@ -4,6 +4,9 @@
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYPlayerState)
#include "AbilitySystem/Attributes/PHYCombatAttributeSet.h"
#include "AbilitySystem/Attributes/PHYCoreAttributeSet.h"
#include "AbilitySystem/Attributes/PHYElementAttributeSet.h"
#include "Class/PHYClassComponent.h"
#include "Class/PHYClassSettings.h"
#include "GGA_AbilitySystemComponent.h"
@@ -17,6 +20,10 @@ APHYPlayerState::APHYPlayerState(const FObjectInitializer& ObjectInitializer)
AbilitySystemComponent->SetIsReplicated(true);
AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed);
CoreAttributeSet = CreateDefaultSubobject<UPHYCoreAttributeSet>(TEXT("CoreAttributeSet"));
CombatAttributeSet = CreateDefaultSubobject<UPHYCombatAttributeSet>(TEXT("CombatAttributeSet"));
ElementAttributeSet = CreateDefaultSubobject<UPHYElementAttributeSet>(TEXT("ElementAttributeSet"));
ClassComponent = CreateDefaultSubobject<UPHYClassComponent>(TEXT("ClassComponent"));
ClassComponent->SetClassTag(GetDefault<UPHYClassSettings>()->DefaultPlayerClassTag);
}

View File

@@ -0,0 +1,167 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "AbilitySystem/Attributes/PHYAttributeSettings.h"
#include "PHYAttributeCalculationLibrary.generated.h"
class UPHYCoreAttributeSet;
/**
* @brief 基础属性输入快照,用于 C++、GE 和后续 MMC 共享公式。
*/
USTRUCT(BlueprintType)
struct FPHYCoreAttributeSnapshot
{
GENERATED_BODY()
/** @brief 力量。 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="PHY|Attributes|Core")
float Strength = 0.0f;
/** @brief 灵巧。 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="PHY|Attributes|Core")
float Dexterity = 0.0f;
/** @brief 体魄。 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="PHY|Attributes|Core")
float Vitality = 0.0f;
/** @brief 智力。 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="PHY|Attributes|Core")
float Intelligence = 0.0f;
/** @brief 精神。 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="PHY|Attributes|Core")
float Spirit = 0.0f;
/** @brief 感知。 */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="PHY|Attributes|Core")
float Perception = 0.0f;
};
/**
* @brief 次级战斗属性计算结果。
*/
USTRUCT(BlueprintType)
struct FPHYDerivedCombatAttributes
{
GENERATED_BODY()
/** @brief 推导后的生命上限。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float MaxHealth = 0.0f;
/** @brief 推导后的法力上限。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float MaxMana = 0.0f;
/** @brief 推导后的耐力上限。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float MaxStamina = 0.0f;
/** @brief 推导后的物理攻击强度。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float PhysicalAttackPower = 0.0f;
/** @brief 推导后的法术强度。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float SpellPower = 0.0f;
/** @brief 推导后的护甲。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float Armor = 0.0f;
/** @brief 推导后的魔法抗性。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float MagicResistance = 0.0f;
/** @brief 推导后的命中率。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float Accuracy = 0.0f;
/** @brief 推导后的闪避率。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float Evasion = 0.0f;
/** @brief 推导后的暴击率。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float CriticalChance = 0.0f;
/** @brief 推导后的暴击伤害倍率。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float CriticalDamage = 0.0f;
/** @brief 推导后的攻击速度倍率。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float AttackSpeed = 0.0f;
/** @brief 推导后的冷却缩减比例。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float CooldownReduction = 0.0f;
/** @brief 推导后的格挡强度。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float BlockPower = 0.0f;
/** @brief 推导后的破防强度。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float GuardBreakPower = 0.0f;
/** @brief 推导后的韧性。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float Poise = 0.0f;
/** @brief 推导后的韧性伤害。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Combat")
float PoiseDamage = 0.0f;
};
/**
* @brief 元素属性计算结果。
*/
USTRUCT(BlueprintType)
struct FPHYDerivedElementAttributes
{
GENERATED_BODY()
/** @brief 推导后的通用元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Element")
float DamageBonus = 0.0f;
/** @brief 推导后的通用元素抗性。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Element")
float Resistance = 0.0f;
/** @brief 推导后的通用元素穿透。 */
UPROPERTY(BlueprintReadOnly, Category="PHY|Attributes|Element")
float Penetration = 0.0f;
};
/**
* @brief 属性公式函数库,避免首期依赖复杂 MMC 资产。
*/
UCLASS()
class PHY_API UPHYAttributeCalculationLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
/** @brief 从配置默认值创建基础属性快照。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
static FPHYCoreAttributeSnapshot MakeCoreSnapshotFromDefaults();
/** @brief 从基础属性集创建基础属性快照。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
static FPHYCoreAttributeSnapshot MakeCoreSnapshotFromAttributeSet(const UPHYCoreAttributeSet* CoreAttributes);
/** @brief 根据基础属性和配置公式计算次级战斗属性。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
static FPHYDerivedCombatAttributes CalculateCombatAttributes(const FPHYCoreAttributeSnapshot& CoreAttributes);
/** @brief 根据基础属性和配置公式计算通用元素属性。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
static FPHYDerivedElementAttributes CalculateElementAttributes(const FPHYCoreAttributeSnapshot& CoreAttributes);
};

View File

@@ -0,0 +1,12 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#define PHY_ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

View File

@@ -0,0 +1,301 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "PHYAttributeSettings.generated.h"
/**
* @brief 基础属性初始值。
*/
USTRUCT(BlueprintType)
struct FPHYCoreAttributeDefaults
{
GENERATED_BODY()
/** @brief 力量初始值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Core")
float Strength = 10.0f;
/** @brief 灵巧初始值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Core")
float Dexterity = 10.0f;
/** @brief 体魄初始值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Core")
float Vitality = 10.0f;
/** @brief 智力初始值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Core")
float Intelligence = 10.0f;
/** @brief 精神初始值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Core")
float Spirit = 10.0f;
/** @brief 感知初始值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Core")
float Perception = 10.0f;
};
/**
* @brief 次级战斗属性公式系数。
*/
USTRUCT(BlueprintType)
struct FPHYCombatAttributeFormula
{
GENERATED_BODY()
/** @brief 生命上限基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxHealthBase = 100.0f;
/** @brief 每点体魄提供的生命上限。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxHealthVitality = 18.0f;
/** @brief 每点力量提供的生命上限。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxHealthStrength = 3.0f;
/** @brief 法力上限基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxManaBase = 60.0f;
/** @brief 每点智力提供的法力上限。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxManaIntelligence = 12.0f;
/** @brief 每点精神提供的法力上限。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxManaSpirit = 6.0f;
/** @brief 耐力上限基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxStaminaBase = 80.0f;
/** @brief 每点体魄提供的耐力上限。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxStaminaVitality = 5.0f;
/** @brief 每点灵巧提供的耐力上限。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MaxStaminaDexterity = 4.0f;
/** @brief 力量对物理攻击的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float PhysicalAttackPowerStrength = 2.0f;
/** @brief 灵巧对物理攻击的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float PhysicalAttackPowerDexterity = 0.5f;
/** @brief 智力对法术强度的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float SpellPowerIntelligence = 2.0f;
/** @brief 精神对法术强度的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float SpellPowerSpirit = 0.4f;
/** @brief 体魄对护甲的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float ArmorVitality = 1.2f;
/** @brief 力量对护甲的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float ArmorStrength = 0.4f;
/** @brief 精神对魔法抗性的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MagicResistanceSpirit = 1.1f;
/** @brief 智力对魔法抗性的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float MagicResistanceIntelligence = 0.3f;
/** @brief 命中基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float AccuracyBase = 0.8f;
/** @brief 感知对命中的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float AccuracyPerception = 0.006f;
/** @brief 灵巧对命中的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float AccuracyDexterity = 0.002f;
/** @brief 闪避基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float EvasionBase = 0.03f;
/** @brief 灵巧对闪避的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float EvasionDexterity = 0.003f;
/** @brief 感知对闪避的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float EvasionPerception = 0.001f;
/** @brief 暴击率基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CriticalChanceBase = 0.05f;
/** @brief 灵巧对暴击率的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CriticalChanceDexterity = 0.002f;
/** @brief 感知对暴击率的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CriticalChancePerception = 0.0015f;
/** @brief 暴击伤害基础倍率。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CriticalDamageBase = 1.5f;
/** @brief 力量对暴击伤害的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CriticalDamageStrength = 0.004f;
/** @brief 感知对暴击伤害的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CriticalDamagePerception = 0.003f;
/** @brief 攻击速度基础倍率。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float AttackSpeedBase = 1.0f;
/** @brief 灵巧对攻击速度的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float AttackSpeedDexterity = 0.01f;
/** @brief 冷却缩减基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CooldownReductionBase = 0.0f;
/** @brief 智力对冷却缩减的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CooldownReductionIntelligence = 0.0015f;
/** @brief 精神对冷却缩减的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float CooldownReductionSpirit = 0.001f;
/** @brief 格挡强度基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float BlockPowerBase = 5.0f;
/** @brief 力量对格挡强度的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float BlockPowerStrength = 1.2f;
/** @brief 体魄对格挡强度的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float BlockPowerVitality = 0.6f;
/** @brief 破防强度基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float GuardBreakPowerBase = 5.0f;
/** @brief 力量对破防强度的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float GuardBreakPowerStrength = 1.1f;
/** @brief 感知对破防强度的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float GuardBreakPowerPerception = 0.4f;
/** @brief 韧性基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float PoiseBase = 20.0f;
/** @brief 体魄对韧性的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float PoiseVitality = 1.5f;
/** @brief 力量对韧性的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float PoiseStrength = 0.5f;
/** @brief 韧性伤害基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float PoiseDamageBase = 5.0f;
/** @brief 力量对韧性伤害的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float PoiseDamageStrength = 0.8f;
/** @brief 灵巧对韧性伤害的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Formula")
float PoiseDamageDexterity = 0.2f;
};
/**
* @brief 元素属性公式系数。
*/
USTRUCT(BlueprintType)
struct FPHYElementAttributeFormula
{
GENERATED_BODY()
/** @brief 元素伤害加成基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float DamageBonusBase = 0.0f;
/** @brief 智力对元素伤害加成的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float DamageBonusIntelligence = 0.0015f;
/** @brief 感知对元素伤害加成的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float DamageBonusPerception = 0.0005f;
/** @brief 元素抗性基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float ResistanceBase = 0.02f;
/** @brief 精神对元素抗性的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float ResistanceSpirit = 0.002f;
/** @brief 体魄对元素抗性的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float ResistanceVitality = 0.0005f;
/** @brief 通用元素穿透基础值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float PenetrationBase = 0.0f;
/** @brief 感知对通用元素穿透的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float PenetrationPerception = 0.001f;
/** @brief 智力对通用元素穿透的系数。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes|Element")
float PenetrationIntelligence = 0.0005f;
};
/**
* @brief 属性体系配置,首期放入 PHYCombat 以便和战斗公式一起维护。
*/
UCLASS(Config=PHYCombat, DefaultConfig)
class PHY_API UPHYAttributeSettings : public UObject
{
GENERATED_BODY()
public:
/** @brief 基础属性默认初始值。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes")
FPHYCoreAttributeDefaults DefaultCoreAttributes;
/** @brief 次级战斗属性公式。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes")
FPHYCombatAttributeFormula CombatFormula;
/** @brief 元素属性公式。 */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="PHY|Attributes")
FPHYElementAttributeFormula ElementFormula;
};

View File

@@ -0,0 +1,183 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystem/Attributes/PHYAttributeSet.h"
#include "PHYCombatAttributeSet.generated.h"
class UPHYCoreAttributeSet;
struct FGameplayEffectModCallbackData;
/**
* @brief PHY 次级战斗属性集,由基础属性和装备、效果共同驱动。
*/
UCLASS(BlueprintType)
class PHY_API UPHYCombatAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
/** @brief 构造战斗属性并按默认基础属性推导首期数值。 */
UPHYCombatAttributeSet();
/** @brief 注册属性复制。 */
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
/** @brief 属性变更前限制百分比和资源范围。 */
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
/** @brief GameplayEffect 执行后限制资源不超过上限。 */
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
/** @brief 属性变更后同步当前资源与上限。 */
virtual void PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue) override;
/** @brief 当前生命。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Health, Category="PHY|Attributes|Combat")
FGameplayAttributeData Health;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, Health);
/** @brief 生命上限。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_MaxHealth, Category="PHY|Attributes|Combat")
FGameplayAttributeData MaxHealth;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, MaxHealth);
/** @brief 当前法力。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Mana, Category="PHY|Attributes|Combat")
FGameplayAttributeData Mana;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, Mana);
/** @brief 法力上限。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_MaxMana, Category="PHY|Attributes|Combat")
FGameplayAttributeData MaxMana;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, MaxMana);
/** @brief 当前耐力。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Stamina, Category="PHY|Attributes|Combat")
FGameplayAttributeData Stamina;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, Stamina);
/** @brief 耐力上限。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_MaxStamina, Category="PHY|Attributes|Combat")
FGameplayAttributeData MaxStamina;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, MaxStamina);
/** @brief 物理攻击强度。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_PhysicalAttackPower, Category="PHY|Attributes|Combat")
FGameplayAttributeData PhysicalAttackPower;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, PhysicalAttackPower);
/** @brief 法术强度。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_SpellPower, Category="PHY|Attributes|Combat")
FGameplayAttributeData SpellPower;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, SpellPower);
/** @brief 护甲。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Armor, Category="PHY|Attributes|Combat")
FGameplayAttributeData Armor;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, Armor);
/** @brief 魔法抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_MagicResistance, Category="PHY|Attributes|Combat")
FGameplayAttributeData MagicResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, MagicResistance);
/** @brief 命中率,通常作为 0 到 1 的比例使用。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Accuracy, Category="PHY|Attributes|Combat")
FGameplayAttributeData Accuracy;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, Accuracy);
/** @brief 闪避率,通常作为 0 到 1 的比例使用。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Evasion, Category="PHY|Attributes|Combat")
FGameplayAttributeData Evasion;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, Evasion);
/** @brief 暴击率,通常作为 0 到 1 的比例使用。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_CriticalChance, Category="PHY|Attributes|Combat")
FGameplayAttributeData CriticalChance;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, CriticalChance);
/** @brief 暴击伤害倍率1.5 表示 150% 伤害。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_CriticalDamage, Category="PHY|Attributes|Combat")
FGameplayAttributeData CriticalDamage;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, CriticalDamage);
/** @brief 攻击速度倍率。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_AttackSpeed, Category="PHY|Attributes|Combat")
FGameplayAttributeData AttackSpeed;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, AttackSpeed);
/** @brief 冷却缩减比例。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_CooldownReduction, Category="PHY|Attributes|Combat")
FGameplayAttributeData CooldownReduction;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, CooldownReduction);
/** @brief 格挡强度。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_BlockPower, Category="PHY|Attributes|Combat")
FGameplayAttributeData BlockPower;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, BlockPower);
/** @brief 破防强度。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_GuardBreakPower, Category="PHY|Attributes|Combat")
FGameplayAttributeData GuardBreakPower;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, GuardBreakPower);
/** @brief 韧性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Poise, Category="PHY|Attributes|Combat")
FGameplayAttributeData Poise;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, Poise);
/** @brief 韧性伤害。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_PoiseDamage, Category="PHY|Attributes|Combat")
FGameplayAttributeData PoiseDamage;
PHY_ATTRIBUTE_ACCESSORS(UPHYCombatAttributeSet, PoiseDamage);
/** @brief 按默认配置中的基础属性计算并写入次级属性。 */
void InitializeFromConfiguredCoreDefaults();
/** @brief 按指定基础属性集计算并写入次级属性。 */
void InitializeFromCoreAttributes(const UPHYCoreAttributeSet* CoreAttributes);
protected:
/** @brief 复制当前生命变化。 */
UFUNCTION() void OnRep_Health(const FGameplayAttributeData& OldValue);
/** @brief 复制生命上限变化。 */
UFUNCTION() void OnRep_MaxHealth(const FGameplayAttributeData& OldValue);
/** @brief 复制当前法力变化。 */
UFUNCTION() void OnRep_Mana(const FGameplayAttributeData& OldValue);
/** @brief 复制法力上限变化。 */
UFUNCTION() void OnRep_MaxMana(const FGameplayAttributeData& OldValue);
/** @brief 复制当前耐力变化。 */
UFUNCTION() void OnRep_Stamina(const FGameplayAttributeData& OldValue);
/** @brief 复制耐力上限变化。 */
UFUNCTION() void OnRep_MaxStamina(const FGameplayAttributeData& OldValue);
/** @brief 复制物理攻击强度变化。 */
UFUNCTION() void OnRep_PhysicalAttackPower(const FGameplayAttributeData& OldValue);
/** @brief 复制法术强度变化。 */
UFUNCTION() void OnRep_SpellPower(const FGameplayAttributeData& OldValue);
/** @brief 复制护甲变化。 */
UFUNCTION() void OnRep_Armor(const FGameplayAttributeData& OldValue);
/** @brief 复制魔法抗性变化。 */
UFUNCTION() void OnRep_MagicResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制命中率变化。 */
UFUNCTION() void OnRep_Accuracy(const FGameplayAttributeData& OldValue);
/** @brief 复制闪避率变化。 */
UFUNCTION() void OnRep_Evasion(const FGameplayAttributeData& OldValue);
/** @brief 复制暴击率变化。 */
UFUNCTION() void OnRep_CriticalChance(const FGameplayAttributeData& OldValue);
/** @brief 复制暴击伤害倍率变化。 */
UFUNCTION() void OnRep_CriticalDamage(const FGameplayAttributeData& OldValue);
/** @brief 复制攻击速度倍率变化。 */
UFUNCTION() void OnRep_AttackSpeed(const FGameplayAttributeData& OldValue);
/** @brief 复制冷却缩减比例变化。 */
UFUNCTION() void OnRep_CooldownReduction(const FGameplayAttributeData& OldValue);
/** @brief 复制格挡强度变化。 */
UFUNCTION() void OnRep_BlockPower(const FGameplayAttributeData& OldValue);
/** @brief 复制破防强度变化。 */
UFUNCTION() void OnRep_GuardBreakPower(const FGameplayAttributeData& OldValue);
/** @brief 复制韧性变化。 */
UFUNCTION() void OnRep_Poise(const FGameplayAttributeData& OldValue);
/** @brief 复制韧性伤害变化。 */
UFUNCTION() void OnRep_PoiseDamage(const FGameplayAttributeData& OldValue);
};

View File

@@ -0,0 +1,78 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystem/Attributes/PHYAttributeSet.h"
#include "PHYCoreAttributeSet.generated.h"
/**
* @brief PHY 基础属性集,作为所有玩家和 AI 的通用根属性。
*/
UCLASS(BlueprintType)
class PHY_API UPHYCoreAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
/** @brief 构造基础属性并读取默认配置。 */
UPHYCoreAttributeSet();
/** @brief 注册属性复制。 */
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
/** @brief 力量,影响物理攻击、格挡、破防和负重倾向。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Strength, Category="PHY|Attributes|Core")
FGameplayAttributeData Strength;
PHY_ATTRIBUTE_ACCESSORS(UPHYCoreAttributeSet, Strength);
/** @brief 灵巧,影响暴击、攻速、命中和闪避倾向。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Dexterity, Category="PHY|Attributes|Core")
FGameplayAttributeData Dexterity;
PHY_ATTRIBUTE_ACCESSORS(UPHYCoreAttributeSet, Dexterity);
/** @brief 体魄,影响生命、护甲、耐力和韧性倾向。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Vitality, Category="PHY|Attributes|Core")
FGameplayAttributeData Vitality;
PHY_ATTRIBUTE_ACCESSORS(UPHYCoreAttributeSet, Vitality);
/** @brief 智力,影响法术强度、法力和冷却缩减倾向。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Intelligence, Category="PHY|Attributes|Core")
FGameplayAttributeData Intelligence;
PHY_ATTRIBUTE_ACCESSORS(UPHYCoreAttributeSet, Intelligence);
/** @brief 精神,影响法力、魔法抗性和元素抗性倾向。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Spirit, Category="PHY|Attributes|Core")
FGameplayAttributeData Spirit;
PHY_ATTRIBUTE_ACCESSORS(UPHYCoreAttributeSet, Spirit);
/** @brief 感知,影响命中、暴击、弱点和穿透倾向。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_Perception, Category="PHY|Attributes|Core")
FGameplayAttributeData Perception;
PHY_ATTRIBUTE_ACCESSORS(UPHYCoreAttributeSet, Perception);
protected:
/** @brief 复制力量。 */
UFUNCTION()
void OnRep_Strength(const FGameplayAttributeData& OldValue);
/** @brief 复制灵巧。 */
UFUNCTION()
void OnRep_Dexterity(const FGameplayAttributeData& OldValue);
/** @brief 复制体魄。 */
UFUNCTION()
void OnRep_Vitality(const FGameplayAttributeData& OldValue);
/** @brief 复制智力。 */
UFUNCTION()
void OnRep_Intelligence(const FGameplayAttributeData& OldValue);
/** @brief 复制精神。 */
UFUNCTION()
void OnRep_Spirit(const FGameplayAttributeData& OldValue);
/** @brief 复制感知。 */
UFUNCTION()
void OnRep_Perception(const FGameplayAttributeData& OldValue);
};

View File

@@ -0,0 +1,155 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystem/Attributes/PHYAttributeSet.h"
#include "PHYElementAttributeSet.generated.h"
class UPHYCoreAttributeSet;
/**
* @brief PHY 元素进攻与防御属性集。
*/
UCLASS(BlueprintType)
class PHY_API UPHYElementAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
/** @brief 构造元素属性并按默认基础属性推导首期数值。 */
UPHYElementAttributeSet();
/** @brief 注册属性复制。 */
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
/** @brief 限制元素比例属性范围。 */
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
/** @brief 按默认配置中的基础属性计算并写入元素属性。 */
void InitializeFromConfiguredCoreDefaults();
/** @brief 按指定基础属性集计算并写入元素属性。 */
void InitializeFromCoreAttributes(const UPHYCoreAttributeSet* CoreAttributes);
/** @brief 火元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_FireDamageBonus, Category="PHY|Attributes|Element")
FGameplayAttributeData FireDamageBonus;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, FireDamageBonus);
/** @brief 水元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_WaterDamageBonus, Category="PHY|Attributes|Element")
FGameplayAttributeData WaterDamageBonus;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, WaterDamageBonus);
/** @brief 冰元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_IceDamageBonus, Category="PHY|Attributes|Element")
FGameplayAttributeData IceDamageBonus;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, IceDamageBonus);
/** @brief 雷元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_LightningDamageBonus, Category="PHY|Attributes|Element")
FGameplayAttributeData LightningDamageBonus;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, LightningDamageBonus);
/** @brief 地元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_EarthDamageBonus, Category="PHY|Attributes|Element")
FGameplayAttributeData EarthDamageBonus;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, EarthDamageBonus);
/** @brief 风元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_WindDamageBonus, Category="PHY|Attributes|Element")
FGameplayAttributeData WindDamageBonus;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, WindDamageBonus);
/** @brief 光元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_LightDamageBonus, Category="PHY|Attributes|Element")
FGameplayAttributeData LightDamageBonus;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, LightDamageBonus);
/** @brief 暗元素伤害加成。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_DarkDamageBonus, Category="PHY|Attributes|Element")
FGameplayAttributeData DarkDamageBonus;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, DarkDamageBonus);
/** @brief 火元素抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_FireResistance, Category="PHY|Attributes|Element")
FGameplayAttributeData FireResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, FireResistance);
/** @brief 水元素抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_WaterResistance, Category="PHY|Attributes|Element")
FGameplayAttributeData WaterResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, WaterResistance);
/** @brief 冰元素抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_IceResistance, Category="PHY|Attributes|Element")
FGameplayAttributeData IceResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, IceResistance);
/** @brief 雷元素抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_LightningResistance, Category="PHY|Attributes|Element")
FGameplayAttributeData LightningResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, LightningResistance);
/** @brief 地元素抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_EarthResistance, Category="PHY|Attributes|Element")
FGameplayAttributeData EarthResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, EarthResistance);
/** @brief 风元素抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_WindResistance, Category="PHY|Attributes|Element")
FGameplayAttributeData WindResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, WindResistance);
/** @brief 光元素抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_LightResistance, Category="PHY|Attributes|Element")
FGameplayAttributeData LightResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, LightResistance);
/** @brief 暗元素抗性。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_DarkResistance, Category="PHY|Attributes|Element")
FGameplayAttributeData DarkResistance;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, DarkResistance);
/** @brief 通用元素穿透,首期不按元素拆分。 */
UPROPERTY(BlueprintReadOnly, ReplicatedUsing=OnRep_ElementPenetration, Category="PHY|Attributes|Element")
FGameplayAttributeData ElementPenetration;
PHY_ATTRIBUTE_ACCESSORS(UPHYElementAttributeSet, ElementPenetration);
protected:
/** @brief 复制火元素伤害加成变化。 */
UFUNCTION() void OnRep_FireDamageBonus(const FGameplayAttributeData& OldValue);
/** @brief 复制水元素伤害加成变化。 */
UFUNCTION() void OnRep_WaterDamageBonus(const FGameplayAttributeData& OldValue);
/** @brief 复制冰元素伤害加成变化。 */
UFUNCTION() void OnRep_IceDamageBonus(const FGameplayAttributeData& OldValue);
/** @brief 复制雷元素伤害加成变化。 */
UFUNCTION() void OnRep_LightningDamageBonus(const FGameplayAttributeData& OldValue);
/** @brief 复制地元素伤害加成变化。 */
UFUNCTION() void OnRep_EarthDamageBonus(const FGameplayAttributeData& OldValue);
/** @brief 复制风元素伤害加成变化。 */
UFUNCTION() void OnRep_WindDamageBonus(const FGameplayAttributeData& OldValue);
/** @brief 复制光元素伤害加成变化。 */
UFUNCTION() void OnRep_LightDamageBonus(const FGameplayAttributeData& OldValue);
/** @brief 复制暗元素伤害加成变化。 */
UFUNCTION() void OnRep_DarkDamageBonus(const FGameplayAttributeData& OldValue);
/** @brief 复制火元素抗性变化。 */
UFUNCTION() void OnRep_FireResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制水元素抗性变化。 */
UFUNCTION() void OnRep_WaterResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制冰元素抗性变化。 */
UFUNCTION() void OnRep_IceResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制雷元素抗性变化。 */
UFUNCTION() void OnRep_LightningResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制地元素抗性变化。 */
UFUNCTION() void OnRep_EarthResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制风元素抗性变化。 */
UFUNCTION() void OnRep_WindResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制光元素抗性变化。 */
UFUNCTION() void OnRep_LightResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制暗元素抗性变化。 */
UFUNCTION() void OnRep_DarkResistance(const FGameplayAttributeData& OldValue);
/** @brief 复制通用元素穿透变化。 */
UFUNCTION() void OnRep_ElementPenetration(const FGameplayAttributeData& OldValue);
};

View File

@@ -7,6 +7,9 @@
#include "PHYAICharacter.generated.h"
class UGGA_AbilitySystemComponent;
class UPHYCombatAttributeSet;
class UPHYCoreAttributeSet;
class UPHYElementAttributeSet;
class UPHYClassComponent;
/**
@@ -33,6 +36,18 @@ public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|AI")
UGGA_AbilitySystemComponent* GetAIAbilitySystemComponent() const { return AbilitySystemComponent; }
/** @brief 获取 AI 基础属性集。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
UPHYCoreAttributeSet* GetCoreAttributeSet() const { return CoreAttributeSet; }
/** @brief 获取 AI 战斗属性集。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
UPHYCombatAttributeSet* GetCombatAttributeSet() const { return CombatAttributeSet; }
/** @brief 获取 AI 元素属性集。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
UPHYElementAttributeSet* GetElementAttributeSet() const { return ElementAttributeSet; }
/** @brief 获取 AI 职业分类组件。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Class")
UPHYClassComponent* GetClassComponent() const { return ClassComponent; }
@@ -45,6 +60,18 @@ protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|AI")
TObjectPtr<UGGA_AbilitySystemComponent> AbilitySystemComponent;
/** @brief AI 通用基础属性集,避免职业 AbilitySet 重复添加。 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Attributes")
TObjectPtr<UPHYCoreAttributeSet> CoreAttributeSet;
/** @brief AI 通用战斗属性集,避免职业 AbilitySet 重复添加。 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Attributes")
TObjectPtr<UPHYCombatAttributeSet> CombatAttributeSet;
/** @brief AI 通用元素属性集,避免职业 AbilitySet 重复添加。 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Attributes")
TObjectPtr<UPHYElementAttributeSet> ElementAttributeSet;
/** @brief AI 职业分类组件,默认不应用玩家职业 Mesh。 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Class")
TObjectPtr<UPHYClassComponent> ClassComponent;

View File

@@ -0,0 +1,39 @@
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "NativeGameplayTags.h"
/**
* @brief PHY 属性体系原生 Gameplay Tag。
*/
namespace PHYGameplayTags
{
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Core);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Core_Strength);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Core_Dexterity);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Core_Vitality);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Core_Intelligence);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Core_Spirit);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Core_Perception);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Combat);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Combat_Health);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Combat_Mana);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Combat_Stamina);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Combat_Offense);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Combat_Defense);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Fire);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Water);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Ice);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Lightning);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Earth);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Wind);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Light);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Dark);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_DamageBonus);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Resistance);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(Attribute_Element_Penetration);
}

View File

@@ -3,6 +3,7 @@
#pragma once
#include "GameplayTags/PHYGameplayTags_Ability.h"
#include "GameplayTags/PHYGameplayTags_Attribute.h"
#include "GameplayTags/PHYGameplayTags_Class.h"
#include "GameplayTags/PHYGameplayTags_Effect.h"
#include "GameplayTags/PHYGameplayTags_Event.h"

View File

@@ -8,6 +8,9 @@
#include "PHYPlayerState.generated.h"
class UGGA_AbilitySystemComponent;
class UPHYCombatAttributeSet;
class UPHYCoreAttributeSet;
class UPHYElementAttributeSet;
class UPHYClassComponent;
/**
@@ -31,6 +34,18 @@ public:
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|PlayerState")
UGGA_AbilitySystemComponent* GetGGAAbilitySystemComponent() const { return AbilitySystemComponent; }
/** @brief 获取玩家基础属性集。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
UPHYCoreAttributeSet* GetCoreAttributeSet() const { return CoreAttributeSet; }
/** @brief 获取玩家战斗属性集。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
UPHYCombatAttributeSet* GetCombatAttributeSet() const { return CombatAttributeSet; }
/** @brief 获取玩家元素属性集。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Attributes")
UPHYElementAttributeSet* GetElementAttributeSet() const { return ElementAttributeSet; }
/** @brief 获取玩家持久职业组件。 */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Class")
UPHYClassComponent* GetClassComponent() const { return ClassComponent; }
@@ -40,6 +55,18 @@ protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|PlayerState")
TObjectPtr<UGGA_AbilitySystemComponent> AbilitySystemComponent;
/** @brief 玩家持久基础属性集,避免职业 AbilitySet 重复添加。 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Attributes")
TObjectPtr<UPHYCoreAttributeSet> CoreAttributeSet;
/** @brief 玩家持久战斗属性集,避免职业 AbilitySet 重复添加。 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Attributes")
TObjectPtr<UPHYCombatAttributeSet> CombatAttributeSet;
/** @brief 玩家持久元素属性集,避免职业 AbilitySet 重复添加。 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Attributes")
TObjectPtr<UPHYElementAttributeSet> ElementAttributeSet;
/** @brief 玩家持久职业组件,职业不保存在 PlayerCharacter 上。 */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Class")
TObjectPtr<UPHYClassComponent> ClassComponent;