Trials & Triumphs
Genre: Turn-based strategy role-playing game
Software used: Unity, TortoiseGit
Role: Programmer
Of all the projects I have worked on, this had the greatest number of people behind it, with around 20 people working on it. The team had 6 programmers total, with varying degrees of experience (myself and two others having the most experience). Coming into this project, none of us knew exactly what kind of game we were making, outside of it being a role-playing game. At the start, I had volunteered to work on the combat system. However, the system that I had initially created was not the system that we would end up with. You can read about this original system on this page. The combat system that we ended up using would end up being more of a grid-based strategy RPG similar to Fire Emblem, Disgaea, or XCOM. Another programmer worked to figure out how to implement a grid-based system in Unity, and I had worked on how to create a battle system using that grid. Initially I had tried to adapt my old system to what would become the new one, but it didn't work well enough so I had to start from scratch. By the end of the project we had a base system figured out, with the player units being able to move around on their turn (implementing Astar pathfinding), as well as attack enemies. I was also able to implement simple movement and attacking for enemy units on their turn, and worked with that other programmer to implement his class and special ability systems (which he had worked on while I made the original battle system) into the new grid-based system. I additionally worked on camera control within this battle system.
Gameplay-wise, the game is split into two sections: hub sections and combat sections. In a hub section the player will be able to freely wander around different areas, and can pick up quests from NPCs, sell and buy items, change the party members (as there's a maximum of 4), things of that nature. When the player is ready they will proceed to enter a combat section, which is separated into multiple sections. Player units inside a section will activate any enemy units in that area, initiating combat. Each section features entrances to other sections, however some may have certain conditions that must be met in order for a player unit to enter it. For instance, a door might only open if a specific enemy is destroyed, a specific item is used, or a panel is stepped on. A player unit leaving a section moves all other player units as well. This "combat/rest" dynamic is handled via a state machine.
For combat, it is divided into rounds. At the start of each round, it gets a list of all the units in the activated section, then organizes them all based on their speed stat plus any modifiers those units might have obtained in a previous round. From there each unit acts in order, able to perform actions like moving, attacking, using special skills, using an item, or defending, to a maximum of 2 actions per turn. A unit can perform the same action twice. A tricky thing that took me a little bit to figure out was how to display the possible nodes a playable unit can move into or attack when selecting those options. As part of the grid system implementation, each node contains information of their neighboring nodes, allowing me to use a recursive function to get the nodes that are within a certain range value. Click here to see the code for this. From there, for each node it will create an object on the position of it that shows the node as being within the action's range. You can see an example of this here to display a unit's valid spaces for movement.
As mentioned before, units use the Astar method of pathfinding to move through the grid to reach their destination. For this game, that meant that a unit would create an array of connecting nodes that it would progress through, finding the shortest of all possible paths. With this knowledge, it was simple for me to create a simple enemy AI that moved an enemy to the closest player unit, and if the unit was in range, attack the player. For each player unit, it will check to see the number of nodes it would need to move through to reach that unit. If the player was not in attack range, move until the unit is within attack range, or until it runs out of its movement budget. Otherwise, it will just perform a standard attack. Movement is done by retrieving the list of spaces it would move through in order to reach the target, but removes nodes from the bottom if the number of spaces exceeds the movement budget, and also taking attack range into account. You can view the code for this here.
This project has so far been the greatest challenge I have faced yet, but it was still one that I learned loads from. I didn't have any experience in the past creating battle systems for RPGs, and creating both the classic and grid-based systems had taught me much in the intricacies of how they can be programmed. Communication between teams was a bit of an issue, which led to the programmers having a bit too much free reign on gameplay elements that the designers would later decide was something that was not wanted. This taught me to not get too attached to my code, especially in regards to the change in battle systems.