TONY CHEN

Leyline Knights

September 2020 - Present

Summary

Leyline Knights is a top-down 3D action roguelike game. Player controls a magic-wielding knight and climb the Great World Tree in search of powerful magic to help your sick sibling. Player battles through randomly ordered room encounters and acquire elemental upgrades to aid in their climb.

The most challenging part of the project is working with a team of 16. Though the team started off as 3, we slowly grew a total of 16. This is my first time working on a team this large. The project began with me working majority on AI with another team member. But in the later stages of the project, we lost 2 systems programmers, so we had to cut scope and I shifted to work on back end systems to fill in the gap.

Format

Game Engine: Unreal Engine 4

Team Size: Fourteen

Development Time: 8 months

Roles

Tech Lead

Programmer

My Contributions

Enemy AI

Reward System

Level Generator

Achievement System

Elemental Effects

User Interface

Controller Compatibility

Enemy AI

As a Tech Lead, I responsible for setting up all basic AI and implmentation of the first boss that the player encounters during the first biome, Candlekin.

The basic enemies were created with a well-structures inheritance so that future work would be much easier. It was important that the base structure is well structured so when in the future, if we end up adding in more enemies, it would save a lot of time.

For the AI, we used a combinations of blueprints, blackboard, and behavior trees. We tried to go into EQS but after ample testing, we had scrapped that ideas and sticked to just nav meshes.

This was the first time I worked with Behavior Trees in UE4 which resulted in a slow start, but after working on several base enemies, everything was going much smoother.

Additionally, I implmented the first boss of the game, Galawick. This was the most challenging portion of creating AI. Since all the boss abilities were used by chance, all abilties were given a weight and they were selected by chance based on the weight. This is all set up in a Behavior Tree Task which can be resued on other enemies.

After vertical slice, I moved away from working on AI to other system since we lost two systems programmers.

Rewards System

The reward system at first were all random with a single reward spawning per room that the player cleared. This made the game too random where player could get runs with full upgraded elements and other runs where player would purely just get crystals(in-game currecny). This was solved by making each room spawn multiple rewards based on the room difficulty.

Based on the room difficulty, Easy, Normal or Hard, the room would spawn 1, 2, or 3 rewards. This allows the player to make the decision of low quality reward for easier playthrough, or higher quality reward in trade of higher difficulty. This solved a alot of the issues of rewards being too random. But when adding in the second biome, there were a total of 15+ rooms that player could play through which by the end of second biome, the player could already achieve all elemental upgrades majority of the time if player chose normal or hard difficulty rooms. To solve this issue, we scaled and weighed the rewards based on previous rewards that the player recieved.

Each type of reward was give a weight based on the difficulty of the room as well as player's previous rewards. For example, if player has never recieved a Elemental Upgrade and they are already at the third room, the chances of the room spawning an Elemental Upgrade is increased. This would be the same vice versa.

With this new system in, not only did it make achieving all elements easier, but it also increased the value of other upgrades. After implmentation of this system, playing with other upgrades also felt impactful. While before, players would always go for elemental upgrades since 70+ percent of the time, there were elemental upgrade option.

Once the system was done, I created data assets and added the base values and weights so that designers could easily adjust the values without going into the blueprints.

Level Generator / Wave System

With the game not allowing backtracking and requiring each level to differ from previous level, level generator was quite simple. I used prebuilt maps created by designers and placed them in arrays. When each level is loaded in, they set each door to a different level. Once the door is used, it removes the level from the array so that the level will never be used again. There are couple restrictions in amount of levels before a certain occurrence. This is completed by having a integer increment as player move through levels and once that threshold is met, it sets all the doors to that occurrence. Levels also have a difficulty rating that changes the enemy tier and element chances during that room. The difficulty is set based on random chance and is set on the doors.

With difficulty in place, the wave system set weights based on the difficulty. This is like the rewards system where it uses weights and adjusts those values based on certain conditions. For element chances, there are base chances and they are adjusted based on the difficulty level. All this information is stored in a data asset so they are easily tweaked. To spawn enemies, it takes the base element weights and added them to the difficulty weights. Then spawns the enemy based on the selected element.

Achievement System

The achievement system was a nice addon to the game as it something players try to achieve besides defeating every boss. I created this system by utilizing data assets and storing all the achievements there. Achievements themselves consist of an array of structs. The struct contains all the information of each achievement such as name, description, type, requirement, tier, etc. When actions are done, they check for the type of action and check if it is an achievement, if so, it increases the achievement values.

Elemental Effects System

Elemental effects is a core system for combat. We have four different elemental effects (burn, shock, chill, and gust) with each performing different effects. All characters that are affected by elemental effects hold a actor component. Whenever a character is dealt damage with attack that applies elemental effects, it searches for the actor component and deals the effect through that component.

For attacks that deal elemental effects, I created a function library for actors and had functions that create the damage type along with a function to change the damage of the effects. This is used since enemies and player take different amount of damage based on the effects.

User Interface

Another core system I worked on was putting together majority of the User Interface. After getting all the UI in the engine, one of the key things that were added was dynamic informational text and tooltip of elemental effects. Information texts are useful so players can understand what each upgrade does to their abilities as well as know what each upgrade does if they are recieving it for the first time. To do this, I created a function library to hold all the data and widgets would just call it to pull the information without having to connect all the information in each widget.

I also worked in getting correct information to show up based on if player is using keyboard or controller. For this, I utilized Rich Textboxes and Decorators. Since this is used across multiple widgets, I also created a function in the function library to get and assign the correct decorators based on the instance it is being called.

Controller Compatibility

This is my first time working with adding full Xbox controller support for a game and I proved to be a challenge. We also wanted seamless support from switching between controller and keyboard. With things like auto hiding mouse cursor and auto selected the correct options when switching between controller and keyboard took me a long to figure out.

To do this,in each widget, I created an array of all the widgets that are focusable, and based on the input, the widget either finds a widget to focus and set the image or brush of the widget or just put the image or brush to default if it is keyboard input.

Downloads

Available on: Mega.nz Steam