A downloadable game for Windows

Embark on a thrilling journey as Caden, a fallen knight on a path of redemption. Transformed into a battle-hardened mercenary, he must navigate the treacherous land of Wallachia, where a malevolent force threatens to plunge the realm into darkness. Unleash your swordsmanship and tactical prowess as you confront ancient evils, forge alliances, and unveil the secrets that could reshape the fate of Wallachia forever.


Umbrarum Valachiae was created as a main project/portfolio piece while undertaking the Mastered Bootcamp, and was a collaborative effort between myself and the very talented Joe Million. Without him, the game would definitely not look nearly as polished. The castle assets were created by him from the ground up.

The wider environment was created by myself along with gameplay mechanics which are using a whole lot of C++ behind the scenes. The project is around 90% C++ with a few areas utilising the convenience of Blueprints, showcasing my understanding and experience within Unreal Engine as a C++ developer and Blueprint designer.


Interesting Project Features


Wave Based Gameplay System

I was especially proud of the wave based gameplay system for this project as I created it from scratch. I'm no stranger to following tutorials, and there are plenty of tutorials out there for creating wave based game modes using Blueprints, but nothing for C++.


I spent some time looking into how I wanted this mode to work. I approached this from a standpoint of being able to hand over the C++ built system to a game designer that specialises in Blueprints and for them to be able to customise things as much as they wanted in an intuitive and simple way.


In the end, the Blueprint class derived from my C++ code allows you to add individual waves to the game mode. You can also select any Blueprint class that derives from the base enemy and you can then pick a count of how many of these enemies you would like to spawn. This uses a custom Struct built especially for this purpose.


There is also the ability to select an audio clip to play when a round begins and also adjust the "between waves" countdown, giving any Blueprint developer all of the tools needed to customise the system.


While I am very proud of it, there is plenty of room for improvement, such as spawn order randomisation and also the ability to ensure specific enemies spawn at specific spawn points.


Directional Hit & Hit Reaction

In order to make combat more realistic and add a difficultly element, I opted for directional hits and hit reactions. This essentially ties the actual physical hit of an actor to the animation. If a character was to swing their sword in a specific way and the opponent was able to dodge, they would avoid the consequences.


To achieve this, I utilised box tracing which executes my "Get Hit" function, passing in the impact point & a reference to the person doing the hitting. Damage is then applied and depending on the position of the impact, an animation plays.

For the box tracing, we use two vector points. One at initial point of impact/overlap, and one at the end of the impact/overlap. Anything overlapping with this area triggers a Box Hit.


Before the Box Trace takes part, we can add specific actors to ignore. This is important, as we do not want to include any actual overlap events from the weapon itself or the person wielding the weapon.


We then perform a single box trace to see if a hit occurs. This is based on the location of the owner of the weapon from the pawn being attacked. The actor being attacked will play the relevant hit reaction animation in response.

This has been modified a little. The original code was using the impact point on the actual actor being hit to decide which animation to play, but this could be buggy if a sword swung through and hit a player on the side/back then the actor would stumble in the wrong direction. Using the location of the attacking actor is more reliable.


This same mechanic is in play for my character and all enemies too, using an interface which I will mention later.


User Attributes, Collectables & Weapon EquippingFor User Attributes, I have a separate class that's attached to my BaseCharacter class. This means I can reuse the same code on all classes inheriting from BaseCharacter.

The Attributes class has multiple Getters & Setters, allowing you to add and check values for multiple attributes. 

Right now we just have Health, Stamina, Gold & Experience, but there were initial plans to add Level, Speed & Damage. This way I could increase the base statistics such as Speed & Damage depending on the characters level. It would mean even more variation for enemy strength, as well as ensuring the player could level up and become stronger, giving players a sense of progression. There were also future plans to add things like stamina regen rate, health regen rate, etc.


Within the game, there are collectible items which can give the player either experience or gold. These can be obtained by breaking certain objects. The breakables themselves could use some additional work. Right now, if you break one of these but another nearby manages to roll away, the collision capsule for the "rolling" object will remain in its starting position. I would like to go back and work on this more at some point when time allows.


All items derive from a base item class. In total, there are four types of item.

- Treasure/Gold items. When collected, these give the player gold. The initial idea was to have a trader between enemy waves where weapons and usable items could be purchased, but this functionality was de-scoped due to time constraints.

- Experience Orbs - These items drop when enemies die. They can be collected to increase the players experience count. The idea here was to use this for levelling, which in turn would increase the characters base statistics and heal them when levelling up.

- Weapons. For now, only 1 weapon is in game, but a total of 7 have been created. The idea was to be able to purchase upgrades from a trader NPC.

- Triggers. Much like weapons, you can interact with these items using the E key. They can be programmed to do various things. My primary use for this type of item is to be able to trigger the Wave-based game mode. I plan on being able to open and close doors using this too, though.


Another feature, which is not really needed as it has no impact other than a visual one, is the ability to equip and unequip a weapon using the R key. This could be useful if I decided to make the player be able to run faster while not wielding a weapon, or if another game mode was introduced and certain enemies would only agro if you had a weapon equipped.





Character & Enemy States

The entire game would not work without states. My character and enemies have various ENUMs set up to ensure they can perform specific tasks while in certain states.


An example of this would be that if you are mid-attack, you can't suddenly use dodge or attempt to move away. The character would be in the Attack state, and until this returns to idle, no other actions could be taken.

The use of states would also be extremely useful if I were to convert the game to a multiplayer offering. These states could be broadcast to ensure players do not fall out of sync across the server.


Player & Hit interfaces

In Unreal Engine, an interface is a way to define a contract or set of functions that classes can implement. It allows unrelated classes to share common functionality without the need for inheritance.

An interface defines a set of function signatures that participating classes must implement. It specifies what functions a class should have but doesn't provide any implementation details. This allows multiple classes to implement the same interface, providing a consistent way to interact with them.


Interfaces are useful in scenarios where different classes need to exhibit similar behavior or respond to specific events. For example, in my case, I have a hit interface attached to both the player and enemies. This means that both the player and enemies are expected to implement the functions defined in the hit interface, such as GetHit(). By implementing the same interface, the player and enemies can share the same behavior when hit, even though they might be different classes.


Using interfaces allows for loose coupling between classes. It promotes code reusability and makes it easier to swap out implementations or extend functionality without affecting other parts of the codebase.

I also have a Player interface, allowing the player to interact with items within the game. I have attached this interface to various items, along with my player, allowing me to use functions such as AddGold() and AddExperience().



Enemies & AI (Without using a Behaviour Tree)

I'm a huge fan of behaviour trees within Unreal Engine and all of the capabilities that come with them, but for this project, I kept things retro with the enemy AI logic. I wanted to showcase as much C++ as possible, and as such, my AI logic is all based on states and a handful of parameters.

AI Helper Functions

The states play a big part, much like they do for the main logic of the game. Enemies can only perform specific tasks while in specific states, keeping the chaos in check. The enemies have x main states. The core of this code is based on the wonderful course by Stephen Ulibarri. For anyone looking to improve their skills and knowledge with UE5 and C++, I highly recommend checking out his courses.



Controls

  • WASD - Movement
  • Mouse - Move camera around
  • E - Equip Weapon & Interact with Items
  • R - Sheath & Unsheath Weapon
  • Shift - Roll/Dodge
  • Esc - Pause & Options menu

Credits

- William Mabin - Mastered Mentor

- Joe Million - Castle Assets

- Stephen Ulibarri - Udemy Course Creator & Teacher

- Various Sound assets (https://www.freesound.org)

- Various free models & animations (Mixamo, TurboSquid)

Download

Download
Umbrarum Valachiae Demo (v0.1)
External

Leave a comment

Log in with itch.io to leave a comment.