Skip to content

Commit

Permalink
feat: Adding support for Local multiplayer Split Screen
Browse files Browse the repository at this point in the history
  • Loading branch information
mklabs committed Sep 12, 2021
1 parent eab6cc0 commit b018bd6
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 56 deletions.
Binary file modified TargetSystem/Content/Maps/TargetSystemTestMap.umap
Binary file not shown.
Binary file not shown.
143 changes: 92 additions & 51 deletions TargetSystem/Source/TargetSystem/Private/TargetSystemComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,50 +33,54 @@ void UTargetSystemComponent::BeginPlay()
return;
}

OwnerPlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (!OwnerPlayerController)
OwnerPawn = Cast<APawn>(OwnerActor);
if (!ensure(OwnerPawn))
{
TS_LOG(Error, TEXT("[%s] TargetSystemComponent: Cannot get PlayerController reference ..."), *OwnerActor->GetName());
TS_LOG(Error, TEXT("[%s] TargetSystemComponent: Component is meant to be added to Pawn only ..."), *GetName());
return;
}

SetupLocalPlayerController();
}

void UTargetSystemComponent::TickComponent(const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

if (bTargetLocked && LockedOnTargetActor)
if (!bTargetLocked || !LockedOnTargetActor)
{
if (!TargetIsTargetable(LockedOnTargetActor))
{
TargetLockOff();
return;
}
return;
}

SetControlRotationOnTarget(LockedOnTargetActor);
if (!TargetIsTargetable(LockedOnTargetActor))
{
TargetLockOff();
return;
}

SetControlRotationOnTarget(LockedOnTargetActor);

// Target Locked Off based on Distance
if (GetDistanceFromCharacter(LockedOnTargetActor) > MinimumDistanceToEnable)
{
TargetLockOff();
}

// Target Locked Off based on Distance
if (GetDistanceFromCharacter(LockedOnTargetActor) > MinimumDistanceToEnable)
if (ShouldBreakLineOfSight() && !bIsBreakingLineOfSight)
{
if (BreakLineOfSightDelay <= 0)
{
TargetLockOff();
}

if (ShouldBreakLineOfSight() && !bIsBreakingLineOfSight)
else
{
if (BreakLineOfSightDelay <= 0)
{
TargetLockOff();
}
else
{
bIsBreakingLineOfSight = true;
GetWorld()->GetTimerManager().SetTimer(
LineOfSightBreakTimerHandle,
this,
&UTargetSystemComponent::BreakLineOfSight,
BreakLineOfSightDelay
);
}
bIsBreakingLineOfSight = true;
GetWorld()->GetTimerManager().SetTimer(
LineOfSightBreakTimerHandle,
this,
&UTargetSystemComponent::BreakLineOfSight,
BreakLineOfSightDelay
);
}
}
}
Expand Down Expand Up @@ -309,33 +313,44 @@ bool UTargetSystemComponent::ShouldSwitchTargetActor(const float AxisValue)

void UTargetSystemComponent::TargetLockOn(AActor* TargetToLockOn)
{
if (TargetToLockOn)
if (!IsValid(TargetToLockOn))
{
bTargetLocked = true;
if (bShouldDrawLockedOnWidget)
{
CreateAndAttachTargetLockedOnWidgetComponent(TargetToLockOn);
}
return;
}

if (bShouldControlRotation)
{
ControlRotation(true);
}
// Recast PlayerController in case it wasn't already setup on Begin Play (local split screen)
SetupLocalPlayerController();

if (bAdjustPitchBasedOnDistanceToTarget || bIgnoreLookInput)
bTargetLocked = true;
if (bShouldDrawLockedOnWidget)
{
CreateAndAttachTargetLockedOnWidgetComponent(TargetToLockOn);
}

if (bShouldControlRotation)
{
ControlRotation(true);
}

if (bAdjustPitchBasedOnDistanceToTarget || bIgnoreLookInput)
{
if (IsValid(OwnerPlayerController))
{
OwnerPlayerController->SetIgnoreLookInput(true);
}
}

if (OnTargetLockedOn.IsBound())
{
OnTargetLockedOn.Broadcast(TargetToLockOn);
}
if (OnTargetLockedOn.IsBound())
{
OnTargetLockedOn.Broadcast(TargetToLockOn);
}
}

void UTargetSystemComponent::TargetLockOff()
{
// Recast PlayerController in case it wasn't already setup on Begin Play (local split screen)
SetupLocalPlayerController();

bTargetLocked = false;
if (TargetLockedOnWidgetComponent)
{
Expand All @@ -349,7 +364,10 @@ void UTargetSystemComponent::TargetLockOff()
ControlRotation(false);
}

OwnerPlayerController->ResetIgnoreLookInput();
if (IsValid(OwnerPlayerController))
{
OwnerPlayerController->ResetIgnoreLookInput();
}

if (OnTargetLockedOff.IsBound())
{
Expand All @@ -374,6 +392,11 @@ void UTargetSystemComponent::CreateAndAttachTargetLockedOnWidgetComponent(AActor
UMeshComponent* MeshComponent = TargetActor->FindComponentByClass<UMeshComponent>();
USceneComponent* ParentComponent = MeshComponent && LockedOnWidgetParentSocket != NAME_None ? MeshComponent : TargetActor->GetRootComponent();

if (IsValid(OwnerPlayerController))
{
TargetLockedOnWidgetComponent->SetOwnerPlayer(OwnerPlayerController->GetLocalPlayer());
}

TargetLockedOnWidgetComponent->ComponentTags.Add(FName("TargetSystem.LockOnWidget"));
TargetLockedOnWidgetComponent->SetWidgetSpace(EWidgetSpace::Screen);
TargetLockedOnWidgetComponent->SetupAttachment(ParentComponent, LockedOnWidgetParentSocket);
Expand Down Expand Up @@ -410,6 +433,17 @@ bool UTargetSystemComponent::TargetIsTargetable(const AActor* Actor)
return true;
}

void UTargetSystemComponent::SetupLocalPlayerController()
{
if (!IsValid(OwnerPawn))
{
TS_LOG(Error, TEXT("[%s] TargetSystemComponent: Component is meant to be added to Pawn only ..."), *GetName());
return;
}

OwnerPlayerController = Cast<APlayerController>(OwnerPawn->GetController());
}

AActor* UTargetSystemComponent::FindNearestTarget(TArray<AActor*> Actors) const
{
TArray<AActor*> ActorsHit;
Expand Down Expand Up @@ -481,8 +515,14 @@ bool UTargetSystemComponent::LineTrace(FHitResult& HitResult, const AActor* Othe
);
}

FRotator UTargetSystemComponent::GetControlRotationOnTarget(AActor* OtherActor) const
FRotator UTargetSystemComponent::GetControlRotationOnTarget(const AActor* OtherActor) const
{
if (!IsValid(OwnerPlayerController))
{
TS_LOG(Warning, TEXT("UTargetSystemComponent::GetControlRotationOnTarget - OwnerPlayerController is not valid ..."))
return FRotator::ZeroRotator;
}

const FRotator ControlRotation = OwnerPlayerController->GetControlRotation();

const FVector CharacterLocation = OwnerActor->GetActorLocation();
Expand Down Expand Up @@ -518,7 +558,7 @@ FRotator UTargetSystemComponent::GetControlRotationOnTarget(AActor* OtherActor)

void UTargetSystemComponent::SetControlRotationOnTarget(AActor* TargetActor) const
{
if (!OwnerPlayerController)
if (!IsValid(OwnerPlayerController))
{
return;
}
Expand Down Expand Up @@ -570,13 +610,14 @@ void UTargetSystemComponent::BreakLineOfSight()

void UTargetSystemComponent::ControlRotation(const bool ShouldControlRotation) const
{
APawn* Pawn = Cast<APawn>(OwnerActor);
if (Pawn)
if (!IsValid(OwnerPawn))
{
Pawn->bUseControllerRotationYaw = ShouldControlRotation;
return;
}

UCharacterMovementComponent* CharacterMovementComponent = OwnerActor->FindComponentByClass<UCharacterMovementComponent>();
OwnerPawn->bUseControllerRotationYaw = ShouldControlRotation;

UCharacterMovementComponent* CharacterMovementComponent = OwnerPawn->FindComponentByClass<UCharacterMovementComponent>();
if (CharacterMovementComponent)
{
CharacterMovementComponent->bOrientRotationToMovement = !ShouldControlRotation;
Expand All @@ -585,7 +626,7 @@ void UTargetSystemComponent::ControlRotation(const bool ShouldControlRotation) c

bool UTargetSystemComponent::IsInViewport(const AActor* TargetActor) const
{
if (!OwnerPlayerController)
if (!IsValid(OwnerPlayerController))
{
return true;
}
Expand Down
20 changes: 15 additions & 5 deletions TargetSystem/Source/TargetSystem/Public/TargetSystemComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ class TARGETSYSTEM_API UTargetSystemComponent : public UActorComponent
UPROPERTY()
AActor* OwnerActor;

UPROPERTY()
APawn* OwnerPawn;

UPROPERTY()
APlayerController* OwnerPlayerController;

Expand All @@ -196,7 +199,7 @@ class TARGETSYSTEM_API UTargetSystemComponent : public UActorComponent
bool bDesireToSwitch = false;
float StartRotatingStack = 0.0f;

/** Actors search / trace */
//~ Actors search / trace

TArray<AActor*> GetAllActorsOfClass(TSubclassOf<AActor> ActorClass) const;
TArray<AActor*> FindTargetsInRange(TArray<AActor*> ActorsToLook, float RangeMin, float RangeMax) const;
Expand All @@ -214,9 +217,9 @@ class TARGETSYSTEM_API UTargetSystemComponent : public UActorComponent
float GetDistanceFromCharacter(const AActor* OtherActor) const;


/** Actor rotation */
//~ Actor rotation

FRotator GetControlRotationOnTarget(AActor* OtherActor) const;
FRotator GetControlRotationOnTarget(const AActor* OtherActor) const;
void SetControlRotationOnTarget(AActor* TargetActor) const;
void ControlRotation(bool ShouldControlRotation) const;

Expand All @@ -225,18 +228,25 @@ class TARGETSYSTEM_API UTargetSystemComponent : public UActorComponent

static FRotator FindLookAtRotation(const FVector Start, const FVector Target);

/** Widget */
//~ Widget

void CreateAndAttachTargetLockedOnWidgetComponent(AActor* TargetActor);

/** Targeting */
//~ Targeting

void TargetLockOn(AActor* TargetToLockOn);
void ResetIsSwitchingTarget();
bool ShouldSwitchTargetActor(float AxisValue);

static bool TargetIsTargetable(const AActor* Actor);

/**
* Sets up cached Owner PlayerController from Owner Pawn.
*
* For local split screen, Pawn's Controller may not have been setup already when this component begins play.
*/
void SetupLocalPlayerController();

protected:
// Called when the game starts
virtual void BeginPlay() override;
Expand Down

0 comments on commit b018bd6

Please sign in to comment.