PlayerController에서 TargetActor 업데이트
private:
void OnInputStarted();
void AMyPlayerController::OnInputStarted()
{
StopMovement();
bMousePressed = true;
TargetActor = HighlightActor;
}
- 마우스로 대상을 클릭하면 Target Actor로 업데이트 해준다.
Target을 따라가서 공격하는 함수 추가
private:
void ChaseTargetAndAttack();
protected:
UPROPERTY(BlueprintReadOnly)
TObjectPtr<class AMyPlayer> MyPlayer;
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
MyPlayer = Cast<AMyPlayer>(GetCharacter());
}
void AMyPlayerController::ChaseTargetAndAttack()
{
if (TargetActor == nullptr)
{
return;
}
FVector Direction = TargetActor->GetActorLocation() - MyPlayer->GetActorLocation();
if (Direction.Length() < 250.f)
{
GEngine->AddOnScreenDebugMessage(0, 1.f, FColor::Cyan, TEXT("Attack"));
}
else
{
FVector WorldDirection = Direction.GetSafeNormal();
MyPlayer->AddMovementInput(WorldDirection, 1.0, false);
}
}
- 일정 범위안에 들어오면 공격하고 그렇지 않으면 대상에게 다가간다
공격 애니메이션 추가 및 예외처리
void AMyPlayerController::ChaseTargetAndAttack()
{
if (TargetActor == nullptr)
{
return;
}
if (GetCreatureState() == ECreatureState::Skill)
{
return;
}
FVector Direction = TargetActor->GetActorLocation() - R1Player->GetActorLocation();
if (Direction.Length() < 250.f)
{
GEngine->AddOnScreenDebugMessage(0, 1.f, FColor::Cyan, TEXT("Attack"));
if (AttackMontage)
{
if (bMousePressed)
{
FRotator Rotator = UKismetMathLibrary::FindLookAtRotation(MyPlayer->GetActorLocation(), TargetActor->GetActorLocation());
MyPlayer->SetActorRotation(Rotator);
GetCharacter()->PlayAnimMontage(AttackMontage);
SetCreatureState(ECreatureState::Skill);
TargetActor = HighlightActor;
}
else
{
TargetActor = nullptr;
}
}
}
else
{
FVector WorldDirection = Direction.GetSafeNormal();
MyPlayer->AddMovementInput(WorldDirection, 1.0, false);
}
}
- 임시로 Animation Montage는 블루프린트로 연결한다.
- 이미 공격중인 상태에서는 움직이거나 추가로 공격을 할 수 없도록 추가한다.
UENUM(BlueprintType)
enum class ECreatureState : uint8
{
None,
Moving,
Skill,
Dead
};
캐릭터에 데미지를 받는 OnDamaged와 죽었을 때 호출되는 OnDead 함수 추가
pulbic:
virtual void OnDamaged(int32 Damage, TObjectPtr<AMyCharacter> Attacker);
virtual void OnDead(TObjectPtr<AMyCharacter> Attacker);
void AMyCharacter::OnDamaged(int32 Damage, TObjectPtr<AMyCharacter> Attacker)
{
Hp = FMath::Clamp(Hp - Damage, 0, MaxHp);
if (Hp == 0)
{
OnDead(Attacker);
}
D(FString::Printf(TEXT("%d"), Hp));
}
void AMyCharacter::OnDead(TObjectPtr<AMyCharacter> Attacker)
{
if (CreatureState == ECreatureState::Dead)
{
return;
}
CreatureState = ECreatureState::Dead;
}
- Clamp는 특정 값이 최솟값, 최댓값 사이에 있도록 한다
디버그 메시지 간편하게 띄우기
#define D(x) if(GEngine) { GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Cyan, x); }