- Lymbo -

Project Details
  • Project Length: 4 Weeks

  • Team Size: 9 people

  • Engine: Unreal Engine 5

  • Planning: Miro, Jira & Discord

  • Project Length: 4 Weeks

  • Team Size: 9 people

  • Engine: Unreal Engine 5

  • Planning: Miro, Jira & Discord

  • Project Length: 4 Weeks

  • Team Size: 9 people

  • Engine: Unreal Engine 5

  • Planning: Miro, Jira & Discord

  • My Roles: Programmer Lead & Scrum Master

  • Checkpoint System

  • Health System (Scrapped)

  • Cinematics

  • My Roles: Programmer Lead & Scrum Master

  • Checkpoint System

  • Health System (Scrapped)

  • Cinematics

  • My Roles: Programmer Lead & Scrum Master

  • Checkpoint System

  • Health System (Scrapped)

  • Cinematics

Checkpoint System

I made a sub system that facilitates the respawning process of the player and keeps track of the latest checkpoint that has been passed.

The checkpoints come with a moveable respawn point for designers to customise where each checkpoint's respawn point.

The sub system has an event buffer where animations and fade-ins/outs can be played before the player actually gets respawned.

Show Related Code

.H

.CPP


#pragma once

#include "CoreMinimal.h"
#include "Respawnable.h"
#include "Subsystems/WorldSubsystem.h"
#include "Systems/Interactions/Interaction_Interface.h"
#include "Systems/Respawn/Checkpoints/Checkpoint.h"
#include "WorldRespawnSubsystem.generated.h"

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSetNewCheckpoint);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnPlayerRespawned);


UCLASS()
class GP4_LYMBO_API UWorldRespawnSubsystem : public UWorldSubsystem, public IRespawnable
{
	GENERATED_BODY()
private:

	UPROPERTY()
	ACheckpoint* ActiveCheckpoint = nullptr;

	UPROPERTY()
	AController* PlayerController = nullptr;

	bool RespawnInProgress = false;
	
public:

	UFUNCTION(BlueprintCallable)
	void RespawnPlayer();
	
	UFUNCTION(BlueprintCallable)
	void StartPlayerRespawn();

	UFUNCTION(BlueprintCallable)
	void SetCheckpoint(ACheckpoint* checkpoint);

	UFUNCTION(BlueprintCallable)
	void SetPlayerController(AController* pcontroller);
	
	UFUNCTION(BlueprintCallable)
	ACheckpoint* GetActiveCheckpoint();

	
	UPROPERTY(BlueprintAssignable)
	FOnSetNewCheckpoint OnSetNewCheckpoint;
	UPROPERTY(BlueprintAssignable)
	FOnPlayerRespawned OnPlayerRespawned;
}

Show Related Code

.H

.CPP


#pragma once

#include "CoreMinimal.h"
#include "Respawnable.h"
#include "Subsystems/WorldSubsystem.h"
#include "Systems/Interactions/Interaction_Interface.h"
#include "Systems/Respawn/Checkpoints/Checkpoint.h"
#include "WorldRespawnSubsystem.generated.h"

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSetNewCheckpoint);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnPlayerRespawned);


UCLASS()
class GP4_LYMBO_API UWorldRespawnSubsystem : public UWorldSubsystem, public IRespawnable
{
	GENERATED_BODY()
private:

	UPROPERTY()
	ACheckpoint* ActiveCheckpoint = nullptr;

	UPROPERTY()
	AController* PlayerController = nullptr;

	bool RespawnInProgress = false;
	
public:

	UFUNCTION(BlueprintCallable)
	void RespawnPlayer();
	
	UFUNCTION(BlueprintCallable)
	void StartPlayerRespawn();

	UFUNCTION(BlueprintCallable)
	void SetCheckpoint(ACheckpoint* checkpoint);

	UFUNCTION(BlueprintCallable)
	void SetPlayerController(AController* pcontroller);
	
	UFUNCTION(BlueprintCallable)
	ACheckpoint* GetActiveCheckpoint();

	
	UPROPERTY(BlueprintAssignable)
	FOnSetNewCheckpoint OnSetNewCheckpoint;
	UPROPERTY(BlueprintAssignable)
	FOnPlayerRespawned OnPlayerRespawned;
}

Show Related Code

.H

.CPP


#pragma once

#include "CoreMinimal.h"
#include "Respawnable.h"
#include "Subsystems/WorldSubsystem.h"
#include "Systems/Interactions/Interaction_Interface.h"
#include "Systems/Respawn/Checkpoints/Checkpoint.h"
#include "WorldRespawnSubsystem.generated.h"

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnSetNewCheckpoint);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnPlayerRespawned);


UCLASS()
class GP4_LYMBO_API UWorldRespawnSubsystem : public UWorldSubsystem, public IRespawnable
{
	GENERATED_BODY()
private:

	UPROPERTY()
	ACheckpoint* ActiveCheckpoint = nullptr;

	UPROPERTY()
	AController* PlayerController = nullptr;

	bool RespawnInProgress = false;
	
public:

	UFUNCTION(BlueprintCallable)
	void RespawnPlayer();
	
	UFUNCTION(BlueprintCallable)
	void StartPlayerRespawn();

	UFUNCTION(BlueprintCallable)
	void SetCheckpoint(ACheckpoint* checkpoint);

	UFUNCTION(BlueprintCallable)
	void SetPlayerController(AController* pcontroller);
	
	UFUNCTION(BlueprintCallable)
	ACheckpoint* GetActiveCheckpoint();

	
	UPROPERTY(BlueprintAssignable)
	FOnSetNewCheckpoint OnSetNewCheckpoint;
	UPROPERTY(BlueprintAssignable)
	FOnPlayerRespawned OnPlayerRespawned;
}

Health System

I created a health component that integrated it self with unreal engines Actor damage system so by using the inbuilt damage system that unreal provides you were able to damage the health of actors that attached this component to them selves.

Unfortunately this system got scrapped later in development due as all sources of damage in the game ended up being cut.

Show Related Code

.H

.CPP


#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "TimerManager.h"
#include "HealthComponent.generated.h"

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDeath);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnHealthChanged);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnTakenDamage);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnRecoveredHealth);

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class GP4_LYMBO_API UHealthComponent : public UActorComponent
{
	GENERATED_BODY()

	FTimerHandle IFrameTimerHandle;
	
public:
	// Sets default values for this component's properties
	UHealthComponent();

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float Health = 100;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float MaxHealth = 100;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float IFramesDuration = .2f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool CanTakeDamage = true;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool CanRecoverHealth = true;
	
protected:
	// Called when the game starts
	virtual void BeginPlay() override;
	
	void EnableDamage();

public:

	UFUNCTION(BlueprintCallable)
	void Death();
	
	UFUNCTION(BlueprintCallable)
	void TakeDamage(float Damage, UDamageType* DamageType, AController* WhoDamagedMe, AActor* DamageCauser);

	UFUNCTION(BlueprintCallable)
	void RecoverHealth(float Healing);
	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType,
	                           FActorComponentTickFunction* ThisTickFunction) override;


	UPROPERTY(BlueprintAssignable)
	FOnDeath OnDeath;
	UPROPERTY(BlueprintAssignable)
	FOnHealthChanged OnHealthChanged;
	UPROPERTY(BlueprintAssignable)
	FOnTakenDamage OnTakenDamage;
	UPROPERTY(BlueprintAssignable)
	FOnTakenDamage OnRecoveredHealth;
}

Show Related Code

.H

.CPP


#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "TimerManager.h"
#include "HealthComponent.generated.h"

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDeath);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnHealthChanged);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnTakenDamage);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnRecoveredHealth);

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class GP4_LYMBO_API UHealthComponent : public UActorComponent
{
	GENERATED_BODY()

	FTimerHandle IFrameTimerHandle;
	
public:
	// Sets default values for this component's properties
	UHealthComponent();

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float Health = 100;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float MaxHealth = 100;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float IFramesDuration = .2f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool CanTakeDamage = true;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool CanRecoverHealth = true;
	
protected:
	// Called when the game starts
	virtual void BeginPlay() override;
	
	void EnableDamage();

public:

	UFUNCTION(BlueprintCallable)
	void Death();
	
	UFUNCTION(BlueprintCallable)
	void TakeDamage(float Damage, UDamageType* DamageType, AController* WhoDamagedMe, AActor* DamageCauser);

	UFUNCTION(BlueprintCallable)
	void RecoverHealth(float Healing);
	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType,
	                           FActorComponentTickFunction* ThisTickFunction) override;


	UPROPERTY(BlueprintAssignable)
	FOnDeath OnDeath;
	UPROPERTY(BlueprintAssignable)
	FOnHealthChanged OnHealthChanged;
	UPROPERTY(BlueprintAssignable)
	FOnTakenDamage OnTakenDamage;
	UPROPERTY(BlueprintAssignable)
	FOnTakenDamage OnRecoveredHealth;
}

Show Related Code

.H

.CPP


#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "TimerManager.h"
#include "HealthComponent.generated.h"

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDeath);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnHealthChanged);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnTakenDamage);

UDELEGATE()
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnRecoveredHealth);

UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
class GP4_LYMBO_API UHealthComponent : public UActorComponent
{
	GENERATED_BODY()

	FTimerHandle IFrameTimerHandle;
	
public:
	// Sets default values for this component's properties
	UHealthComponent();

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float Health = 100;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float MaxHealth = 100;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float IFramesDuration = .2f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool CanTakeDamage = true;
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	bool CanRecoverHealth = true;
	
protected:
	// Called when the game starts
	virtual void BeginPlay() override;
	
	void EnableDamage();

public:

	UFUNCTION(BlueprintCallable)
	void Death();
	
	UFUNCTION(BlueprintCallable)
	void TakeDamage(float Damage, UDamageType* DamageType, AController* WhoDamagedMe, AActor* DamageCauser);

	UFUNCTION(BlueprintCallable)
	void RecoverHealth(float Healing);
	
	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType,
	                           FActorComponentTickFunction* ThisTickFunction) override;


	UPROPERTY(BlueprintAssignable)
	FOnDeath OnDeath;
	UPROPERTY(BlueprintAssignable)
	FOnHealthChanged OnHealthChanged;
	UPROPERTY(BlueprintAssignable)
	FOnTakenDamage OnTakenDamage;
	UPROPERTY(BlueprintAssignable)
	FOnTakenDamage OnRecoveredHealth;
}

Cinematics
Due to the short timeframe of the project and there being four programmers on the team most features were completed or already being worked on by week two so I worked on adding cinematics to raise the over all polish of the game.
Reflections

As a whole the game turned out really well but the task scoping for four programmers was a bit too low, which lead to me doing a lot of tasks that weren't related to programming but still added to the games experience.

With the role of lead programmer and scrum master I was often in discussions with the designers and communication their desires to the programming team.

Game Trailer
Smooth Scroll
This will hide itself!

Halldorkari13@gmail.com

0733920759

Contact:

Halldorkari13@gmail.com

0733920759

Contact:

Halldorkari13@gmail.com

0733920759

Contact: