Skip to content

Commit

Permalink
Refactored clashing and hit functions within GameMode.
Browse files Browse the repository at this point in the history
  • Loading branch information
adamriley1219 committed Jan 24, 2018
1 parent 6f46177 commit 3678a45
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 82 deletions.
3 changes: 2 additions & 1 deletion Source/BeatBoxers/BeatBoxers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ DEFINE_LOG_CATEGORY(LogABBGameMode);
DEFINE_LOG_CATEGORY(LogBBAnimation);
DEFINE_LOG_CATEGORY(LogBBUI);
DEFINE_LOG_CATEGORY(LogFretboard);
DEFINE_LOG_CATEGORY(LogBeatTiming);
DEFINE_LOG_CATEGORY(LogBeatTiming);
DEFINE_LOG_CATEGORY(LogClashing);
3 changes: 2 additions & 1 deletion Source/BeatBoxers/BeatBoxers.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ DECLARE_LOG_CATEGORY_EXTERN(LogABBGameMode, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogBBAnimation, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogBBUI, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogFretboard, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogBeatTiming, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogBeatTiming, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogClashing, Log, All);
192 changes: 113 additions & 79 deletions Source/BeatBoxers/Implementation/BBGameMode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ ABBGameMode::ABBGameMode(const class FObjectInitializer& ObjectInitializer)
bReadyToEnd = false;
RoundTime = 90;
DelayBeforeEnd = 5.f;
DefaultClashImpact.bKnocksDown = false;
DefaultClashImpact.Damage = 0.f;
DefaultClashImpact.ImpartedMovement.Delta = FVector2D(-100.f, 0.f);
DefaultClashImpact.ImpartedMovement.Duration = 0.2f;
DefaultClashImpact.ImpartedMovement.UseDeltaAsSpeed = false;
DefaultClashImpact.ImpartedMovement.IsRelativeToAttackerFacing = true;
DefaultClashImpact.ImpartedMovement.UsePhysicsLaunch = false;
DefaultClashImpact.StunLength = 0.5f;
}

EFighterDamageType ABBGameMode::GetDamageType(EStance Stance, EFighterDamageType DesiredOverride) const
Expand Down Expand Up @@ -134,6 +142,7 @@ EHitResponse ABBGameMode::HitActor(TWeakObjectPtr<AActor> Actor, EFighterDamageT

if (CheckClash(Actor, Source))
{
UE_LOG(LogClashing, Log, TEXT("Clash detected between %s and %s."), *Actor.Get()->GetName(), *Source.Get()->GetName());
OnClash(Actor, Source);
return EHitResponse::HE_Clashed;
}
Expand All @@ -142,54 +151,20 @@ EHitResponse ABBGameMode::HitActor(TWeakObjectPtr<AActor> Actor, EFighterDamageT

FImpactData* ImpactData = (WasBlocked) ? &Block : &Hit;
FImpactData ScaledImpact = GetScaledImpactData(*ImpactData, Accuracy);
if (ImpactData->StunLength > 0)
{
IFighter* Fighter = Cast<IFighter>(Actor.Get());
Fighter->StartStun(ImpactData->StunLength, WasBlocked);
}
if (ApplyMovementToActor(Actor, Source, SourceController, ScaledImpact.ImpartedMovement) == 1 && !ScaledImpact.ImpartedMovement.UsePhysicsLaunch)

if (ApplyImpact(Actor, ScaledImpact, WasBlocked, SourceController, Source) == 1
&& !ScaledImpact.ImpartedMovement.UsePhysicsLaunch)
{
UE_LOG(LogABBGameMode, Verbose, TEXT("%s::HitActor actor backed into wall, applying to source."), *GetNameSafe(this));
//The target is already pushed up against a wall, push back the source instead.
if (Source.IsValid() && SourceController.IsValid() && Source.Get() == SourceController.Get()->GetPawn())
{
//Don't do this for projectiles.
ApplyMovementToActor(Source, Source, SourceController, -ScaledImpact.ImpartedMovement);
}
}
if (ImpactData->bKnocksDown && !WasBlocked)
{
IFighter* Fighter = Cast<IFighter>(Actor.Get());
if (Fighter != nullptr)
//Don't do this for projectiles.
if (Source.IsValid() && SourceController.IsValid()
&& Source.Get() == SourceController.Get()->GetPawn())
{
Fighter->Knockdown();
ApplyMovementToActor(Source, Source, SourceController, -ImpactData->ImpartedMovement);
}
}

if (SourceController.IsValid() && SourceController.Get()->PlayerState != nullptr)
{
SourceController.Get()->PlayerState->Score += ScaledImpact.Damage;
AddSpecial(SourceController.Get()->PlayerState, ScaledImpact.SpecialGenerated);
APawn* mAPawn = Cast<APawn>(Actor.Get());
// Logic for applying damage to opponent
if (mAPawn != nullptr && mAPawn->Controller != nullptr)
{
APlayerController* mPlayerController = Cast<APlayerController>(mAPawn->Controller);
if (mPlayerController != nullptr && mPlayerController->PlayerState != nullptr)
{
ABBPlayerState* mBBPlayerState = Cast<ABBPlayerState>(mPlayerController->PlayerState);
if (mBBPlayerState != nullptr)
{
mBBPlayerState->TakeDamage(ScaledImpact.Damage);
if (mBBPlayerState->GetHealth() == 0)
{
UE_LOG(LogBeatBoxers, Log, TEXT("A player has died."));
EndRound();
}
}
}
}
}
return (WasBlocked) ? EHitResponse::HE_Blocked : EHitResponse::HE_Hit;
}

Expand Down Expand Up @@ -1102,47 +1077,53 @@ void ABBGameMode::PushMusicBalance()
MusicBox->ChangeBalance(FinalParams);
}

bool ABBGameMode::CheckClash(TWeakObjectPtr<AActor> FighterA, TWeakObjectPtr<AActor> FighterB)
bool ABBGameMode::CheckClash(TWeakObjectPtr<AActor> ActorA, TWeakObjectPtr<AActor> ActorB)
{
IFighter* mFighterA = Cast<IFighter>(FighterA.Get());
IFighter* mFighterB = Cast<IFighter>(FighterB.Get());
if (FighterA != nullptr && FighterB != nullptr
&& mFighterA != nullptr && mFighterB != nullptr
&& mFighterA->CanClash() && mFighterB->CanClash())
{
TArray<TWeakObjectPtr<AActor>> ActorsToIgnore;
FMoveHitbox Hitbox;
Hitbox.Radius = mFighterA->GetFighterHitbox().Radius;
Hitbox.Origin = mFighterA->GetFighterHitbox().Origin;
Hitbox.End = mFighterA->GetFighterHitbox().End;

//Make hitboxes relative to facing
Hitbox.Origin.X *= mFighterA->GetFacing();
Hitbox.End.X *= mFighterA->GetFacing();

FHitResult HitResult = TraceHitbox(
FighterA->GetActorLocation(),
Hitbox,
ActorsToIgnore
);
if (HitResult.bBlockingHit && HitResult.Actor.IsValid())
if (ActorA.IsValid() && ActorB.IsValid())
{
IFighter* mFighterA = Cast<IFighter>(ActorA.Get());
IFighter* mFighterB = Cast<IFighter>(ActorB.Get());
if (mFighterA != nullptr && mFighterB != nullptr
&& mFighterA->CanClash() && mFighterB->CanClash())
{
Hitbox.Radius = mFighterB->GetFighterHitbox().Radius;
Hitbox.Origin = mFighterB->GetFighterHitbox().Origin;
Hitbox.End = mFighterB->GetFighterHitbox().End;
TArray<TWeakObjectPtr<AActor>> ActorsToIgnore;
ActorsToIgnore.Add(ActorA);
FMoveHitbox Hitbox;
Hitbox.Radius = mFighterA->GetFighterHitbox().Radius;
Hitbox.Origin = mFighterA->GetFighterHitbox().Origin;
Hitbox.End = mFighterA->GetFighterHitbox().End;

//Make hitboxes relative to facing
Hitbox.Origin.X *= mFighterB->GetFacing();
Hitbox.End.X *= mFighterB->GetFacing();
Hitbox.Origin.X *= mFighterA->GetFacing();
Hitbox.End.X *= mFighterA->GetFacing();

HitResult = TraceHitbox(
FighterB->GetActorLocation(),
FHitResult HitResult = TraceHitbox(
ActorA.Get()->GetActorLocation(),
Hitbox,
ActorsToIgnore
);
if (HitResult.bBlockingHit && HitResult.Actor.IsValid())
{
return true;
ActorsToIgnore.Empty();
ActorsToIgnore.Add(ActorB);

Hitbox.Radius = mFighterB->GetFighterHitbox().Radius;
Hitbox.Origin = mFighterB->GetFighterHitbox().Origin;
Hitbox.End = mFighterB->GetFighterHitbox().End;

//Make hitboxes relative to facing
Hitbox.Origin.X *= mFighterB->GetFacing();
Hitbox.End.X *= mFighterB->GetFacing();

HitResult = TraceHitbox(
ActorB.Get()->GetActorLocation(),
Hitbox,
ActorsToIgnore
);
if (HitResult.bBlockingHit && HitResult.Actor.IsValid())
{
return true;
}
}
}
}
Expand All @@ -1153,17 +1134,70 @@ void ABBGameMode::OnClash(TWeakObjectPtr<AActor> FighterA, TWeakObjectPtr<AActor
{
IFighter* mFighterA = Cast<IFighter>(FighterA.Get());
IFighter* mFighterB = Cast<IFighter>(FighterB.Get());

if (mFighterA->GetFighterCurrentWindowAccuracy() >= mFighterA->GetFighterCurrentWindowAccuracy())
{

}

if (mFighterA != nullptr && mFighterB != nullptr)
{
mFighterA->StartStun(.5, false);
mFighterB->StartStun(.5, false);
IFighter* winner = DetermineClashWinner(mFighterA, mFighterB);
// Passes the fighters themselves as the source so the clash impact will be relative to their facing.
ApplyImpact(FighterA, GetClashImpact(mFighterA == winner), false, nullptr, FighterA);
ApplyImpact(FighterB, GetClashImpact(mFighterB == winner), false, nullptr, FighterB);
}
else
{
UE_LOG(LogClashing, Warning, TEXT("ABBGameMode::OnClash given a nullptr for a Fighter."));
}
}

IFighter* ABBGameMode::DetermineClashWinner(IFighter* FighterA, IFighter* FighterB)
{
// Nobody wins for now.
return nullptr;
}

int ABBGameMode::ApplyImpact(TWeakObjectPtr<AActor> Actor, FImpactData ImpactData, bool WasBlocked, TWeakObjectPtr<AController> SourceController, TWeakObjectPtr<AActor> Source)
{
int toRet = ApplyMovementToActor(Actor, Source, SourceController, ImpactData.ImpartedMovement);

IFighter* Fighter = Cast<IFighter>(Actor.Get());
if (Fighter != nullptr)
{
if (ImpactData.StunLength > 0)
{
Fighter->StartStun(ImpactData.StunLength, WasBlocked);
}
if (ImpactData.bKnocksDown && !WasBlocked)
{
IFighter* Fighter = Cast<IFighter>(Actor.Get());
if (Fighter != nullptr)
{
Fighter->Knockdown();
}
}
}

if (SourceController.IsValid() && SourceController.Get()->PlayerState != nullptr)
{
AddSpecial(SourceController.Get()->PlayerState, ImpactData.SpecialGenerated);
}

// Logic for applying damage to opponent
APawn* mAPawn = Cast<APawn>(Actor.Get());
if (mAPawn != nullptr && mAPawn->Controller != nullptr)
{
APlayerController* mPlayerController = Cast<APlayerController>(mAPawn->Controller);
if (mPlayerController != nullptr && mPlayerController->PlayerState != nullptr)
{
ABBPlayerState* mBBPlayerState = Cast<ABBPlayerState>(mPlayerController->PlayerState);
if (mBBPlayerState != nullptr)
{
mBBPlayerState->TakeDamage(ImpactData.Damage);
if (mBBPlayerState->GetHealth() == 0)
{
UE_LOG(LogBeatBoxers, Log, TEXT("A player has died."));
EndRound();
}
}
}
}
return toRet;
}
10 changes: 9 additions & 1 deletion Source/BeatBoxers/Implementation/BBGameMode.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class BEATBOXERS_API ABBGameMode : public AGameMode, public IFighterWorld
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
float DelayBeforeEnd;

/** Defines the Effects of a Clash. Needs to always be relative. */
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
FImpactData DefaultClashImpact;

Expand Down Expand Up @@ -155,5 +156,12 @@ class BEATBOXERS_API ABBGameMode : public AGameMode, public IFighterWorld
/** Callback for round timer. */
virtual void OnRoundTimeOut();

virtual FImpactData GetClashImpact(bool WinnerData) { return DefaultClashImpact; }
/** If ForWinner is true, it will return the the ImpactData for the winner, otherwise it will return the Default/Looser data. */
virtual FImpactData GetClashImpact(bool ForWinner) { return DefaultClashImpact; }

/** Returns nullptr if no winner, otherwise Returns the pointer to the winner. */
virtual IFighter* DetermineClashWinner(IFighter* FighterA, IFighter* FighterB);

/** Returns -1 on error, 1 if theactor in question was backed against a wall, 0 otherwise. */
virtual int ApplyImpact(TWeakObjectPtr<AActor> Actor, FImpactData ImpactData, bool WasBlocked, TWeakObjectPtr<AController> SourceController, TWeakObjectPtr<AActor> Source);
};

0 comments on commit 3678a45

Please sign in to comment.