Home About Contact

Bound Core by Bjork

Project Description

Bound Core is a 3D bossfight game where 2 players play against a third boss player. Ready to lose friends?

Project Details

Engine: Unreal Engine 4
Programming: Primarily C++, Blueprints
Project Duration: 9 weeks
Team Size: 8 people
Project Role: Lead Programmer, Planner

My Work

Player Abilities
Player Controls
Projectiles
Boss Abilities
User Interface
Environmental Triggers
Audio-Based Skills
Artificial Intelligence
Animation System
Camera System
Leaderboard MySQL Intergration
Code Syleguide
Collision Interactions
Level Script

Showcase Pictures

Showcase Webms

Showcase Code

A code snippet of a PossessionController. This used to unposses both players when they are both ready and then start possesing the other player. It's been recycled into swapping the players their positions in a "Warp-Like" way.

Demonstration of the Warp:


                  // COPYRIGHT 2019 - Björk

                  #include "BoundCorePossessionController.h"
                  #include "BoundCoreMain.h"
                  #include "ScoreActor.h"
                  #include "Runtime/ActorSequence/Private/ActorSequencePrivatePCH.h"
                  #include "BoundCoreMainCharacter.h"

                  DEFINE_LOG_CATEGORY(BoundCorePossessionControllerLog);

                  ABoundCorePossessionController::ABoundCorePossessionController() {
                  	PrimaryActorTick.bCanEverTick = true;
                  	ReadyForPossession = false;
                  }

                  void ABoundCorePossessionController::BeginPlay() {
                  	Super::BeginPlay();

                  	for (TActorIterator It(GetWorld()); It; ++It) {
                  		AActor* BoundCoreActor = *It;
                  		BoundCoreActors.Add(BoundCoreActor);
                  	}

                  	for (TActorIterator It(GetWorld()); It; ++It) {
                  		BoundCoreActorsMainCharacter.Add(Cast(*It));
                  	}
                  }

                  void ABoundCorePossessionController::Tick(float DeltaTime) {
                  	Super::Tick(DeltaTime);
                  	CheckMainCharactersSwapStatus();

                  	if (ReadyDone) {
                  		for (int i = 0; i < BoundCoreActors.Num(); i++) {
                  			BoundCoreActorsMainCharacter[i]->SwapVFXHeightValue -= DeltaTime * 250;
                  			BoundCoreActorsMainCharacter[i]->Invulnerable = true;

                  			if (BoundCoreActorsMainCharacter[i]->SwapVFXHeightValue < -500.0f) {
                  				ReadyDone = false;
                  				BoundCoreActorsMainCharacter[i]->IsSwitching = false;
                  				BoundCoreActorsMainCharacter[i]->SwapVFXHeightValue = 500;
                  				BoundCoreActorsMainCharacter[i]->Invulnerable = false;

                  				TArray ScoreActors;
                  				UGameplayStatics::GetAllActorsOfClass(GetWorld(), AScoreActor::StaticClass(), ScoreActors);

                  				AScoreActor* TheScoreActor = Cast(ScoreActors[0]);

                  				if (i == 0) {
                  					if (BoundCoreActorsMainCharacter[i]->PregameSkillsEnabled) {
                  						TheScoreActor->ApplyScore(ScoreValue, EPlayerEnum::EP_PlayerRed);
                  					}
                  				}

                  				if (i == 1) {
                  					if (BoundCoreActorsMainCharacter[i]->PregameSkillsEnabled) {

                  						TheScoreActor->ApplyScore(ScoreValue, EPlayerEnum::EP_PlayerBlue);
                  					}
                  				}

                  			}
                  		}
                  	}
                  }

                  void ABoundCorePossessionController::CheckMainCharactersSwapStatus() {
                  	int ReadyCount = 0;

                  	for (int i = 0; i < BoundCoreActors.Num(); i++) {
                  		if (BoundCoreActorsMainCharacter[i]->AbilitySwapReady) {
                  			ReadyCount++;

                  			if (!BoundCoreActorsMainCharacter[i]->AbilitySwapHasParticle){
                  				if (ReadyParticle) {
                  					UGameplayStatics::SpawnEmitterAttached(
                  						ReadyParticle, // Particle Class
                  						BoundCoreActors[i]->FindComponentByClass(), // ActorComponent to Attach to
                  						FName("AbilitySwapCharacterParticle"), // Name BoneSocket to attach to
                  						FVector(0, 0, 0), // Pos
                  						FRotator(0, 90, 0), // Rot
                  						EAttachLocation::KeepRelativeOffset, // Offset Relative
                  						true // World or Local Space
                  					);
                  					BoundCoreActorsMainCharacter[i]->AbilitySwapHasParticle = true;
                  				}
                  			}
                  		}
                  	}

                  	if (ReadyCount == 2) {
                  		if (!ReadyDone) {
                  			FTimerHandle ParticleTimerTillReset;
                  			GetWorldTimerManager().ClearTimer(ParticleTimerTillReset);
                  			GetWorldTimerManager().SetTimer(ParticleTimerTillReset, this, &ABoundCorePossessionController::ResetParticles, ParticleTimeTillReset, false, -1.0f);

                  			ReadyCount = 0;
                  			for (int i = 0; i < BoundCoreActors.Num(); i++) {
                  				BoundCoreActorsMainCharacter[i]->IsSwitching = true;
                  				BoundCoreActorsMainCharacter[i]->AbilityDashCurrentCharges--;
                  				BoundCoreActorsMainCharacter[i]->AbilitySwapReady = false;
                  				BoundCoreActorsMainCharacter[i]->AbilityHealthRegen();
                  				BoundCoreActorsMainCharacter[i]->ResetAbilitySwapCharacterTimerForVFX();
                  			}
                  			ReadyDone = true;
                  		}
                  	}
                  }


                  TArray ABoundCorePossessionController::GetOldRotationsAndReset() {
                  	TArray  OldRotations = TArray();
                  	int BoundCoreActorsNum = BoundCoreActors.Num();

                  	for (int i = 0; i < BoundCoreActorsNum; i++) {
                  		OldRotations.Add(BoundCoreActorsMainCharacter[i]->GetActorRotation());
                  		FRotator NewRotation = FRotator::ZeroRotator;
                  		BoundCoreActors[i]->SetActorRotation(NewRotation);
                  	}
                  	return OldRotations;
                  }

                  TArray ABoundCorePossessionController::GetOldPositionsAndReset() {
                  	TArray  OldPositions = TArray();
                  	int BoundCoreActorsNum = BoundCoreActors.Num();

                  	for (int i = 0; i < BoundCoreActorsNum; i++) {
                  		OldPositions.Add(BoundCoreActorsMainCharacter[i]->GetActorLocation());
                  		FVector NewPosition = FVector::ZeroVector;
                  		BoundCoreActors[i]->SetActorLocation(NewPosition);
                  	}
                  	return OldPositions;
                  }

                  void ABoundCorePossessionController::SetNewRotations(TArray OldRotations) {
                  	int BoundCoreActorsNum = BoundCoreActors.Num();
                  	for (int i = 0; i < BoundCoreActorsNum; i++) {
                  		BoundCoreActors[i]->SetActorRotation(OldRotations[i]);
                  	}
                  }

                  void ABoundCorePossessionController::SetNewPositions(TArray OldPositions) {
                  	int BoundCoreActorsNum = BoundCoreActors.Num();
                  	for (int i = 0; i < BoundCoreActorsNum; i++) {
                  		BoundCoreActors[i]->SetActorLocation(OldPositions[i]);
                  	}
                  }

                  void ABoundCorePossessionController::ResetParticles() {
                  	int BoundCoreActorsNum = BoundCoreActors.Num();
                  	for (int i = 0; i < BoundCoreActorsNum; i++) {
                  		TArray children;
                  		BoundCoreActors[i]->GetComponents(children);

                  		if (children.Num() > 0) {
                  			for (int j = 0; j < children.Num(); j++)
                  			{
                  				int MaterialCount = children[j]->GetNumMaterials();
                  				if (MaterialCount == 1) {
                  					children[j]->DestroyComponent();
                  					BoundCoreActorsMainCharacter[i]->AbilitySwapHasParticle = false;
                  				}
                  			}
                  		}
                  	}
                  	AbilitySwapCharacter();
                  }

                  void ABoundCorePossessionController::AbilitySwapCharacter() {

                  	TArray BoundCoreCharacters;
                  	TArray BoundCoreCharacterControllers;

                  	int BoundCoreActorsNum = BoundCoreActors.Num();

                  	for (int i = 0; i < BoundCoreActorsNum; i++) {
                  		ACharacter* NewCharacter = Cast(BoundCoreActors[i]);
                  		BoundCoreCharacters.Add(NewCharacter);
                  	}

                  	for (int i = 0; i < BoundCoreActorsNum; i++) {
                  		AController* NewController = BoundCoreCharacters[i]->GetController();
                  		BoundCoreCharacterControllers.Add(NewController);
                  	}

                  	TArray OldPositions = GetOldPositionsAndReset();
                  	TArray OldRotations = GetOldRotationsAndReset();

                  	for (int i = 0; i < BoundCoreActorsNum; i++) {
                  		if (i == 0) {
                  			BoundCoreCharacters[i]->SetActorLocation(OldPositions[1]);
                  			//BoundCoreCharacterControllers[i]->Possess(BoundCoreCharacters[1]);
                  		} else if (i == 1) {
                  			BoundCoreCharacters[i]->SetActorLocation(OldPositions[0]);
                  			//BoundCoreCharacterControllers[i]->Possess(BoundCoreCharacters[0]);
                  		}
                  	}
                  	SetNewRotations(OldRotations);
                  }