完成Demo
This commit is contained in:
@@ -16,10 +16,15 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
FGameplayTag GetDeadTag()
|
||||
FGameplayTag GetBotDeadTag()
|
||||
{
|
||||
return FGameplayTag::RequestGameplayTag(FName(TEXT("State.Dead")));
|
||||
}
|
||||
|
||||
FGameplayTag GetBotSlowedTag()
|
||||
{
|
||||
return FGameplayTag::RequestGameplayTag(FName(TEXT("State.Slowed")));
|
||||
}
|
||||
}
|
||||
|
||||
// Sets default values
|
||||
@@ -45,6 +50,7 @@ void ABotCharacter::BeginPlay()
|
||||
|
||||
void ABotCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
UnbindSlowedTagChangedDelegate();
|
||||
UnbindHealthChangedDelegate();
|
||||
if (UWorld* World = GetWorld())
|
||||
{
|
||||
@@ -87,9 +93,12 @@ void ABotCharacter::InitAbilityActorInfo()
|
||||
return;
|
||||
}
|
||||
|
||||
UnbindSlowedTagChangedDelegate();
|
||||
UnbindHealthChangedDelegate();
|
||||
AbilitySystemComponent->InitAbilityActorInfo(this, this);
|
||||
CacheDefaultMovementState();
|
||||
BindHealthChangedDelegate();
|
||||
BindSlowedTagChangedDelegate();
|
||||
|
||||
if (HasAuthority())
|
||||
{
|
||||
@@ -123,6 +132,34 @@ void ABotCharacter::UnbindHealthChangedDelegate()
|
||||
HealthChangedHandle.Reset();
|
||||
}
|
||||
|
||||
void ABotCharacter::BindSlowedTagChangedDelegate()
|
||||
{
|
||||
if (!AbilitySystemComponent || SlowedTagChangedHandle.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const FGameplayTag SlowedTag = GetBotSlowedTag();
|
||||
SlowedTagChangedHandle = AbilitySystemComponent
|
||||
->RegisterGameplayTagEvent(SlowedTag, EGameplayTagEventType::NewOrRemoved)
|
||||
.AddUObject(this, &ThisClass::OnSlowedTagChanged);
|
||||
|
||||
ApplySlowedState(AbilitySystemComponent->GetTagCount(SlowedTag) > 0);
|
||||
}
|
||||
|
||||
void ABotCharacter::UnbindSlowedTagChangedDelegate()
|
||||
{
|
||||
if (!AbilitySystemComponent || !SlowedTagChangedHandle.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AbilitySystemComponent
|
||||
->RegisterGameplayTagEvent(GetBotSlowedTag(), EGameplayTagEventType::NewOrRemoved)
|
||||
.Remove(SlowedTagChangedHandle);
|
||||
SlowedTagChangedHandle.Reset();
|
||||
}
|
||||
|
||||
void ABotCharacter::OnHealthChanged(const FOnAttributeChangeData& Data)
|
||||
{
|
||||
if (HasAuthority() && Data.NewValue <= 0.f)
|
||||
@@ -131,6 +168,31 @@ void ABotCharacter::OnHealthChanged(const FOnAttributeChangeData& Data)
|
||||
}
|
||||
}
|
||||
|
||||
void ABotCharacter::OnSlowedTagChanged(const FGameplayTag Tag, int32 NewCount)
|
||||
{
|
||||
ApplySlowedState(NewCount > 0);
|
||||
}
|
||||
|
||||
void ABotCharacter::CacheDefaultMovementState()
|
||||
{
|
||||
if (bHasCachedDefaultMovementState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultMaxWalkSpeed = GetCharacterMovement()->MaxWalkSpeed;
|
||||
DefaultGlobalAnimRateScale = GetMesh()->GlobalAnimRateScale;
|
||||
bHasCachedDefaultMovementState = true;
|
||||
}
|
||||
|
||||
void ABotCharacter::ApplySlowedState(bool bSlowed)
|
||||
{
|
||||
CacheDefaultMovementState();
|
||||
|
||||
GetMesh()->GlobalAnimRateScale = bSlowed ? 0.5f : DefaultGlobalAnimRateScale;
|
||||
GetCharacterMovement()->MaxWalkSpeed = bSlowed ? 300.f : DefaultMaxWalkSpeed;
|
||||
}
|
||||
|
||||
void ABotCharacter::GiveDefaultAbilities()
|
||||
{
|
||||
if (bHasGivenDefaultAbilities || !AbilitySystemComponent)
|
||||
@@ -180,7 +242,7 @@ void ABotCharacter::HandleDeath()
|
||||
|
||||
if (AbilitySystemComponent)
|
||||
{
|
||||
AbilitySystemComponent->SetLooseGameplayTagCount(GetDeadTag(), 1, EGameplayTagReplicationState::TagOnly);
|
||||
AbilitySystemComponent->SetLooseGameplayTagCount(GetBotDeadTag(), 1, EGameplayTagReplicationState::TagOnly);
|
||||
}
|
||||
|
||||
MulticastHandleDeath();
|
||||
@@ -223,7 +285,7 @@ void ABotCharacter::HandleRespawn()
|
||||
|
||||
if (AbilitySystemComponent)
|
||||
{
|
||||
AbilitySystemComponent->SetLooseGameplayTagCount(GetDeadTag(), 0, EGameplayTagReplicationState::TagOnly);
|
||||
AbilitySystemComponent->SetLooseGameplayTagCount(GetBotDeadTag(), 0, EGameplayTagReplicationState::TagOnly);
|
||||
|
||||
const float MaxHealth = AbilitySystemComponent->GetNumericAttribute(UMainAttributeSet::GetMaxHealthAttribute());
|
||||
AbilitySystemComponent->SetNumericAttributeBase(UMainAttributeSet::GetHealthAttribute(), MaxHealth);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
FGameplayTag GetDeadTag()
|
||||
FGameplayTag GetAttributeSetDeadTag()
|
||||
{
|
||||
return FGameplayTag::RequestGameplayTag(FName(TEXT("State.Dead")));
|
||||
}
|
||||
@@ -56,7 +56,7 @@ void UMainAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallba
|
||||
AActor* OwningActor = ASC->GetOwnerActor();
|
||||
if (OwningActor && OwningActor->HasAuthority())
|
||||
{
|
||||
ASC->SetLooseGameplayTagCount(GetDeadTag(), 1, EGameplayTagReplicationState::TagOnly);
|
||||
ASC->SetLooseGameplayTagCount(GetAttributeSetDeadTag(), 1, EGameplayTagReplicationState::TagOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ class UAbilitySystemComponent;
|
||||
class UAttributeSet;
|
||||
class UGameplayAbility;
|
||||
class UGameplayEffect;
|
||||
struct FGameplayTag;
|
||||
struct FOnAttributeChangeData;
|
||||
|
||||
UCLASS()
|
||||
@@ -62,7 +63,12 @@ private:
|
||||
void InitAbilityActorInfo();
|
||||
void BindHealthChangedDelegate();
|
||||
void UnbindHealthChangedDelegate();
|
||||
void BindSlowedTagChangedDelegate();
|
||||
void UnbindSlowedTagChangedDelegate();
|
||||
void OnHealthChanged(const FOnAttributeChangeData& Data);
|
||||
void OnSlowedTagChanged(const FGameplayTag Tag, int32 NewCount);
|
||||
void CacheDefaultMovementState();
|
||||
void ApplySlowedState(bool bSlowed);
|
||||
void GiveDefaultAbilities();
|
||||
void ApplyDefaultAttributeEffect();
|
||||
void HandleDeath();
|
||||
@@ -79,5 +85,9 @@ private:
|
||||
bool bHasHandledDeath = false;
|
||||
bool bHasNotifiedDeath = false;
|
||||
FDelegateHandle HealthChangedHandle;
|
||||
FDelegateHandle SlowedTagChangedHandle;
|
||||
float DefaultMaxWalkSpeed = 0.f;
|
||||
float DefaultGlobalAnimRateScale = 1.f;
|
||||
bool bHasCachedDefaultMovementState = false;
|
||||
FTimerHandle RespawnTimer;
|
||||
};
|
||||
|
||||
@@ -22,10 +22,15 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
FGameplayTag GetDeadTag()
|
||||
FGameplayTag GetPvPDemoCharacterDeadTag()
|
||||
{
|
||||
return FGameplayTag::RequestGameplayTag(FName(TEXT("State.Dead")));
|
||||
}
|
||||
|
||||
FGameplayTag GetPvPDemoCharacterSlowedTag()
|
||||
{
|
||||
return FGameplayTag::RequestGameplayTag(FName(TEXT("State.Slowed")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +90,7 @@ void APvPDemoCharacter::OnRep_PlayerState()
|
||||
|
||||
void APvPDemoCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
UnbindSlowedTagChangedDelegate();
|
||||
UnbindHealthChangedDelegate();
|
||||
|
||||
Super::EndPlay(EndPlayReason);
|
||||
@@ -188,18 +194,54 @@ UAbilitySystemComponent* APvPDemoCharacter::GetAbilitySystemComponent() const
|
||||
return AbilitySystemComponent;
|
||||
}
|
||||
|
||||
bool APvPDemoCharacter::AddHealth(float Amount)
|
||||
{
|
||||
if (Amount <= 0.f)
|
||||
{
|
||||
UE_LOG(LogPvPDemo, Warning, TEXT("AddHealth failed: Amount must be greater than 0."));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!HasAuthority())
|
||||
{
|
||||
ServerAddHealth(Amount);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!AbilitySystemComponent)
|
||||
{
|
||||
UE_LOG(LogPvPDemo, Warning, TEXT("AddHealth failed: AbilitySystemComponent is null."));
|
||||
return false;
|
||||
}
|
||||
|
||||
const float CurrentHealth = AbilitySystemComponent->GetNumericAttribute(UMainAttributeSet::GetHealthAttribute());
|
||||
const float MaxHealth = AbilitySystemComponent->GetNumericAttribute(UMainAttributeSet::GetMaxHealthAttribute());
|
||||
const float NewHealth = FMath::Clamp(CurrentHealth + Amount, 0.f, MaxHealth);
|
||||
|
||||
AbilitySystemComponent->SetNumericAttributeBase(UMainAttributeSet::GetHealthAttribute(), NewHealth);
|
||||
return true;
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::ServerAddHealth_Implementation(float Amount)
|
||||
{
|
||||
AddHealth(Amount);
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::InitAbilityActorInfo()
|
||||
{
|
||||
AMainPlayerState* MainPlayerState = GetPlayerState<AMainPlayerState>();
|
||||
check(MainPlayerState);
|
||||
|
||||
UnbindSlowedTagChangedDelegate();
|
||||
UnbindHealthChangedDelegate();
|
||||
|
||||
// 设置ASC的所有者,OwnerActor是所有者,AvatarActor是游戏中的形象
|
||||
MainPlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(MainPlayerState, this);
|
||||
AbilitySystemComponent = MainPlayerState->GetAbilitySystemComponent();
|
||||
AttributeSet = MainPlayerState->GetAttributeSet();
|
||||
CacheDefaultMovementState();
|
||||
BindHealthChangedDelegate();
|
||||
BindSlowedTagChangedDelegate();
|
||||
|
||||
if (HasAuthority() && AbilitySystemComponent && HeldItem)
|
||||
{
|
||||
@@ -234,6 +276,34 @@ void APvPDemoCharacter::UnbindHealthChangedDelegate()
|
||||
HealthChangedHandle.Reset();
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::BindSlowedTagChangedDelegate()
|
||||
{
|
||||
if (!AbilitySystemComponent || SlowedTagChangedHandle.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const FGameplayTag SlowedTag = GetPvPDemoCharacterSlowedTag();
|
||||
SlowedTagChangedHandle = AbilitySystemComponent
|
||||
->RegisterGameplayTagEvent(SlowedTag, EGameplayTagEventType::NewOrRemoved)
|
||||
.AddUObject(this, &ThisClass::OnSlowedTagChanged);
|
||||
|
||||
ApplySlowedState(AbilitySystemComponent->GetTagCount(SlowedTag) > 0);
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::UnbindSlowedTagChangedDelegate()
|
||||
{
|
||||
if (!AbilitySystemComponent || !SlowedTagChangedHandle.IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AbilitySystemComponent
|
||||
->RegisterGameplayTagEvent(GetPvPDemoCharacterSlowedTag(), EGameplayTagEventType::NewOrRemoved)
|
||||
.Remove(SlowedTagChangedHandle);
|
||||
SlowedTagChangedHandle.Reset();
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::OnHealthChanged(const FOnAttributeChangeData& Data)
|
||||
{
|
||||
if (HasAuthority() && Data.NewValue <= 0.f)
|
||||
@@ -242,6 +312,31 @@ void APvPDemoCharacter::OnHealthChanged(const FOnAttributeChangeData& Data)
|
||||
}
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::OnSlowedTagChanged(const FGameplayTag Tag, int32 NewCount)
|
||||
{
|
||||
ApplySlowedState(NewCount > 0);
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::CacheDefaultMovementState()
|
||||
{
|
||||
if (bHasCachedDefaultMovementState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultMaxWalkSpeed = GetCharacterMovement()->MaxWalkSpeed;
|
||||
DefaultGlobalAnimRateScale = GetMesh()->GlobalAnimRateScale;
|
||||
bHasCachedDefaultMovementState = true;
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::ApplySlowedState(bool bSlowed)
|
||||
{
|
||||
CacheDefaultMovementState();
|
||||
|
||||
GetMesh()->GlobalAnimRateScale = bSlowed ? 0.5f : DefaultGlobalAnimRateScale;
|
||||
GetCharacterMovement()->MaxWalkSpeed = bSlowed ? 300.f : DefaultMaxWalkSpeed;
|
||||
}
|
||||
|
||||
void APvPDemoCharacter::HandleDeath()
|
||||
{
|
||||
if (bHasHandledDeath)
|
||||
@@ -253,7 +348,7 @@ void APvPDemoCharacter::HandleDeath()
|
||||
|
||||
if (AbilitySystemComponent)
|
||||
{
|
||||
AbilitySystemComponent->SetLooseGameplayTagCount(GetDeadTag(), 1, EGameplayTagReplicationState::TagOnly);
|
||||
AbilitySystemComponent->SetLooseGameplayTagCount(GetPvPDemoCharacterDeadTag(), 1, EGameplayTagReplicationState::TagOnly);
|
||||
}
|
||||
|
||||
if (UWorld* World = GetWorld())
|
||||
@@ -333,5 +428,3 @@ bool APvPDemoCharacter::RemoveHeldItemTag(FGameplayTag Tag)
|
||||
ASC->RemoveLooseGameplayTag(Tag);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ class UAbilitySystemComponent;
|
||||
class UAttributeSet;
|
||||
struct FInputActionValue;
|
||||
struct FOnAttributeChangeData;
|
||||
struct FGameplayTag;
|
||||
class UGameplayAbility;
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogTemplateCharacter, Log, All);
|
||||
@@ -57,6 +58,9 @@ protected:
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* AttackAction;
|
||||
|
||||
UPROPERTY(EditAnywhere, Category="Input")
|
||||
UInputAction* SprintAction;
|
||||
|
||||
// ASC
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
|
||||
@@ -72,6 +76,9 @@ public:
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="GAS|Health")
|
||||
bool AddHealth(float Amount);
|
||||
|
||||
virtual void PossessedBy(AController* NewController) override;
|
||||
virtual void OnRep_PlayerState() override;
|
||||
@@ -135,9 +142,17 @@ private:
|
||||
void InitAbilityActorInfo();
|
||||
void BindHealthChangedDelegate();
|
||||
void UnbindHealthChangedDelegate();
|
||||
void BindSlowedTagChangedDelegate();
|
||||
void UnbindSlowedTagChangedDelegate();
|
||||
void OnHealthChanged(const FOnAttributeChangeData& Data);
|
||||
void OnSlowedTagChanged(const FGameplayTag Tag, int32 NewCount);
|
||||
void CacheDefaultMovementState();
|
||||
void ApplySlowedState(bool bSlowed);
|
||||
void HandleDeath();
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void ServerAddHealth(float Amount);
|
||||
|
||||
UFUNCTION(NetMulticast, Reliable)
|
||||
void MulticastHandleDeath();
|
||||
|
||||
@@ -151,6 +166,10 @@ private:
|
||||
bool RemoveHeldItemTag(FGameplayTag Tag);
|
||||
|
||||
FDelegateHandle HealthChangedHandle;
|
||||
FDelegateHandle SlowedTagChangedHandle;
|
||||
float DefaultMaxWalkSpeed = 0.f;
|
||||
float DefaultGlobalAnimRateScale = 1.f;
|
||||
bool bHasCachedDefaultMovementState = false;
|
||||
bool bHasHandledDeath = false;
|
||||
bool bHasNotifiedDeath = false;
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
FGameplayTag GetDeadTag()
|
||||
FGameplayTag GetGameModeDeadTag()
|
||||
{
|
||||
return FGameplayTag::RequestGameplayTag(FName(TEXT("State.Dead")));
|
||||
}
|
||||
@@ -86,7 +86,7 @@ void APvPDemoGameMode::ResetRespawnAttributes(AController* Controller) const
|
||||
return;
|
||||
}
|
||||
|
||||
ASC->SetLooseGameplayTagCount(GetDeadTag(), 0, EGameplayTagReplicationState::TagOnly);
|
||||
ASC->SetLooseGameplayTagCount(GetGameModeDeadTag(), 0, EGameplayTagReplicationState::TagOnly);
|
||||
|
||||
const float MaxHealth = ASC->GetNumericAttribute(UMainAttributeSet::GetMaxHealthAttribute());
|
||||
ASC->SetNumericAttributeBase(UMainAttributeSet::GetHealthAttribute(), MaxHealth);
|
||||
|
||||
@@ -76,7 +76,8 @@ void APvPDemoPlayerController::SetupInputComponent()
|
||||
bool APvPDemoPlayerController::ShouldUseTouchControls() const
|
||||
{
|
||||
// are we on a mobile platform? Should we force touch?
|
||||
return SVirtualJoystick::ShouldDisplayTouchInterface() || bForceTouchControls;
|
||||
// return SVirtualJoystick::ShouldDisplayTouchInterface() || bForceTouchControls;
|
||||
return false;
|
||||
}
|
||||
|
||||
UAbilitySystemComponent* APvPDemoPlayerController::GetMainWidgetAbilitySystemComponent() const
|
||||
|
||||
Reference in New Issue
Block a user