Project Cleaver


About

Project cleaver is a vertical slice of a first person combat game. Created in unreal engine using both Blueprints and C++.

Project Info

  • Role: Game Programmer
  • Team Size: 11
  • Project Duration: 6 weeks
  • Engine: Unreal Engine, C++
  • Completion Date: 8th of April 2024
View project on Github

My contributions


Weapon System


When developing this game we needed a simple way to add multiple weapons to the game. This was done using Unreal Engine's Data Assets, in this data asset you could enter every value a weapon could have. If you want to use a weapon you would need to add a WeaponComponent to your actor. This handles everything regarding the weapon. This component works together with the Health System I created to have an easy-to-use and scalable combat system.

Health System

The Health system was the first thing that I created in C++. I wanted this component to be dynamic and easy to use. This component makes use of Delegates to communicate updates of the health to blueprints.
                        
void UHealthSystem::TakeDamage(int32 amount)
{
	CurrentHealth -= abs(amount);

	OnDamageTaken.Broadcast(CurrentHealth);
	OnHealthUpdate.Broadcast(GetNormalizedHealth());

	if (CurrentHealth <= 0)
		OnDeath.Broadcast();
}
                    
View whole script

Door system

During development of the game we wanted the ability to lock the players progression behind certain objectives this was done using a gate. The gate can be opened using a blueprintable function. This component currently always takes the owner to move but this can easily be changed to a variable.
                        void UDoorSystem::MoveDoor(float MoveLerpAlpha)
{
	const FVector NewLocation = FVector(FMath::Lerp(StartLocation, EndLocation, MoveLerpAlpha));
	const FRotator NewRotator = FRotator(FMath::Lerp(StartRotator, EndRotator, MoveLerpAlpha));

	GetOwner()->GetRootComponent()->SetWorldLocationAndRotation(NewLocation, NewRotator);
	if (MoveLerpAlpha >= 1)
	{
		DoorState = Open;
		SetComponentTickEnabled(false);
	}
}
                    
View whole script

Enemy locked event

We wanted the ability to track the amount of enemies currently living in a certain place. To solve this, I created the EnemyLockedEvent component. This component acts like a listener. It keeps an ear out for whenever an enemy dies (the enemy's OnDeath event). But it only listens to enemies on a special list created by the designer. This way, the component can track exactly how many of those designated enemies are still alive.
                        void UEnemyLockedEvent::BeginPlay()
{
	Super::BeginPlay();
	AliveEnemies = Enemies.Num();
	for (const auto Enemy : Enemies)
	{
		UHealthSystem* HealthSystem = Enemy->GetComponentByClass<UHealthSystem>();

		if (!HealthSystem) return;

		HealthSystem->OnDeath.AddDynamic(this, &UEnemyLockedEvent::UpdateThreshold);
	}
}
                    

features I also made

  • UI Integration
  • Interact Shader

What I learned from this project

In this project I learned how to make my code more reusable using actor components and events. In the future I want to continue creating more reusable components and begin working on tools to improve the workflow.