

- 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!
This will hide itself!