Weekly Devlog #3: Battle System and Action Queues

First boss battle

Hello from the frozen wastelands of Canadia! My name is Tyler Deren, and I am one of two programmers working on the “Shadows of Adam” project. For the past few weeks I have been hard at work re-building our old ( and very rigid ) battle system from the ground up using an entirely different approach. In this article, I am going to discuss why we decided to re-build a core component of the game, and some of the technical details to make it all work.

Ye Olde

First, let me explain why the team decided to re-write a core component of the game. Typically, when you’re working on a game project (Any project really!) of any scope or scale, re-writing or going back and fixing old work is often times a poor decision, since at that point you are spinning your wheels and not moving forward and making any progress on the game itself. We have a lot of code in Shadows of Adam that is redundant and doesn’t make much sense, but we are not re-writing it because the time spent does not justify the reward. At the end of the day, we have to weigh the decision to re-write sections of old code with new code very carefully. Our wives / girlfriends and families have only so much patience after all! ;)

So, why did we decide to re-write the most critical part of our game when we are keeping old, and often hard to use code in place? Well, let’s show some code of the old battle system…

Here is our dispatchItem function in the old battle system. What this function does is when the player selects an item during the Input phase, it dispatches and executes the associated function. If you use a Potion, we call the Heal actor function. This is fine, however the way we were determining which item was being used was to use a giant if branch checking to see which item was active. You want to add special or hidden items later? Good luck.   You don’t have to be a programmer to understand how rigid this is and how difficult it is to work with. The entire battle system uses Spaghetti code like this and giant IF-ELSE branches to control all of our actions. Further, once an action is used a timer is set. We have multiple timers for different states the battle is in. When an animation is shown, a special animation timer is set and updated. So that means we have multiple timers we have to manage, set and update to control the battle flow. Incredibly difficult to work with, and if we decide to add a new item type to the mix, what should be a simple addition ends up taking a significant amount of time for a trivial feature.

To make matters worse, EVERYTHING in the old battle system used this rigid structure. Skills were a giant heap of IF-ELSE containing the skill code, for every skill in the game. Actions the same. We also have a system where players can find “Artifacts”, which have an interesting story behind them in the game lore, what these things do is they are hidden throughout the world and allow for significant customization of every player character and can greatly change how a battle plays out. How was this system built code-wise? Pretty much IF-ELSE. So why did we decide to re-write this, if it is not obvious? Battles are a significant part of a RPG. You want them to be flexible, dynamic and most of all fun. A rigid system where we are limiting ourselves as designers will only make the game less than what it could be in the long run. So what were the goals of the new system?

  • Flexible. The key point is flexibility. We want to bend the battle system however we want as designers. We don’t want to limit ourselves nor give the players a subpar experience.
  • Ease-of-use. Our old system was a pain to work with. If we want to add new things, it should be easy! Why make our lives complicated?
  • Modular. Maybe we’ll want to push updates or new features post-release. An easy way to do that is to use a modular, plug-n-play structure.

So how do we hit all of those goals?

The Action Queue

Our new and improved battle system uses a data-driven design with a core action queue. The gist of it is you feed data (Or ‘Actions’ to execute) to the system. It is basically a code-eating monster that devours all of the data you feed it and then outputs the result you want, after a configurable time delay (Or a one-time shot, for burrito night). Everything that happens in a battle event is controlled by the action queue. You want to animate a drawing element? Create an action. You want to use an item? Action. You want to attack an enemy? That’s right, use an action. The big advantage to this system is we have full control over how we want the code to flow. We still use a timer to control game-time flow in battle, but instead of having multiple timers for different states and phases, we instead wrap a single timer around our actionQueue so we can fire off an action in a configurable duration. We can now very easily create slow-down time effects, speed-up effects and what have you, or if we want to only fire an action once we simply tell our action Queue that our action has completed via a callback function call; this causes our action queue to update immediately and start the next action.

Flow Chart

A very rough flowchart can be viewed to the right. It is very simple and you should have no problem understanding it, even if my flowchart making abilities are substandard :D.

Further, every battle is broken down into “Phases” and “States“. A phase is a child of our battle state. Currently, we have ten different battle states. These are as follows:

  1. stateSetup. This sets-up our enemies into our battle viewport and displays any starting battle actions, such as show the enemy names at start.
  2. stateFirstStrike. After our setup we then proceed to our Surprised/First Strike phase. This displays UI feedback letting the player know WHY they are being attacked before doing any actions. Very important.
  3. stateNewRound. This is the main loop of our battle states. After every round we loop back to this state. This state applies status effect damages and provides UI feedback for it. Stuff like that
  4. stateInput. The state where the player will spend the most time in. This state allows the player to navigate the UI menus and queue up actions for their party members. This state is broken down into special phases
    1. phaseActionSelect. Our main action select. This phase creates actions and displays our Action select window
    2. phaseAllySelect. This phase allows our player to select an Ally to apply either buffs or healing spells
    3. phaseItemSelect. This phase draws our item window and handles input to select an item to use in battle
    4. phaseSkillSelect. This phase is the exact same as itemSelect, except it works for skills
    5. phaseTargetSelect. This phase allows our player to select an enemy to queue up an action.
  5. stateEnemyInput. This state performs all of our AI calculations. I’ll go over this in a future article, but we essentially use finite state machines as a module that are plugged into our enemies when we want to provide AI behaviour.
  6. stateAttack. This state performs all of the actions queued by the party and enemies, and handles special cases such as counter attacks
  7. stateVictory. The party has defeated all of the enemies! Or, has completed a special battle objective
  8. stateDefeat. You lost. Loser.
  9. stateRun. The party ran away from the fight
  10. stateSpecial. A special state used for dramatic boss deaths. Screen shake, particle effects galore, stuff like that. Fun.

From there, our states loop from 3 -> 4 -> 5 -> 6. In effect, our battle system is basically an array of actions. Instead of having a giant IF-ELSE branch, we simply add new actions to our action queue via some handy helper function calls and pass along the code we want to call.

Managers

You may have noticed some “X Manager” stuff in the flow chart. Remember how we want to build a modular system as one of our new battle system design goals? Our manager classes bind our action queue with our skills, artifact effects and item code. Instead of having IF-ELSE branches, every effect, skill or artifact is in it’s own .js file. If we want to add a new skill, all we do is create a new file in the skill folder and our Skill Manager will call it when that skill is used. This greatly helps with debugging and allows us to easily find what we want to change. No more navigating massive IF-ELSE branches! Every core system uses this model now, from our Event Handler class to our Artifact effects. In the past, our event handling was done using IF-ELSE branches, like everything else (Why? I don’t know), but it was only processed on the Field Map. What if we want to create sophisticated scenes in the battle? We’d have to copy over massive amounts of code from the FieldState to the BattleState. That’s bad and annoying. So instead all of our event action commands are in their own file and are loaded, unloaded and called by our associated Event Manager. So now all we do if we want to process events in different game states is to include our Event Handler class, and it does the rest.

In closing, our battle system re-write, although far from done or polished, was a much needed change. Going forward, it will allow us to design more interesting battle encounters for the player to experience and allows Josh and I to maintain our sanity when adding new features or capability.

 

Here are some GIFs to end the article. GIFs are always fun :D.
Tweens! Actions! STUFF

Have a great week,

Ty.

Weekly Content Blog #2

Today I’m supposed to talk to you about designing levels. I’d get into the theory of it all, but I’m not really a theory guy. I’m a touch and feel guy. I live on my feral instincts, like that guy with the broken-down, silver Dodge mini-van under the bridge by the river, clutching a rusty hammer on dark nights for protection against the rabid world outside.

(insert sound of howling wolves here)

monster_wolf

Yeah, I’ve made some bad decisions in my level-designing life.  Back in ’99 I built a level called South Wall for my first computer-based RPG, Crestfallen: Inception. That level had so much wide open space you could have landed a 747 in the main hall. What you really needed was an F-22 Raptor, or anything capable of Mach 2 (at altitude), because it took about a bazillion years to get anywhere on foot. Sure, I can laugh now as I look back. But am I really better off? Are my levels better off? Maybe all that’s really happened is that I’ve put my mind in a small, agoraphobic box. Level design is tricky like that. There’s a time and a place for just about everything.

But enough about the past. What about the future?!

Tangle 4

In my future posts, I plan to take you inside both my own mind and the Impact level editor. I want to show you what goes into making a Shadows of Adam level. You’ll be a mute little angel or devil sitting on my shoulder, watching the creative process/struggle from a spectacular vantage point.

It will be fun.

Luke

Weekly Content Blog #1

Hello!

This is Tyler (Mire) here. I handle all music related tasks involving our project “Shadows of Adam”. As the composer for the project, I try to use my craft of musical composition to help express the elements of the story and characters. A good musical score can help augment emotions or even subconsciously make the player feel a certain way.

The plan for these posts is to share with you various themes throughout the development of the game, showing off different stages of the process, from rough sketch, to sheet music, to the final product. In addition I hope to show  how it connects with  Tim’s  visuals and Luke’s script.

For my first post I will share the main theme I have composed for “Shadows of Adam”. Many other pieces will be based on similar melodic and harmonic elements. First, let’s listen:

Main Theme – “Destiny Awaits!”


Now that we’ve gotten a chance to listen, let’s delve into the musical analysis of this piece. (WARNING: Music Theory ahead!)

The main motif in this piece is stated in the opening two bars:

The staple of this melodic phrase is its use of a minor 7th interval in the first bar.

This interval is wide and open, giving it a flexibility to what sorts of tonalities it can be used in. For instance, the Main Theme is in A minor but the game’s Overworld Theme is in C Major. Both open with the same minor 7th interval (with some variation). The player will subconsciously connect the two phrases as the same melody, but the major and minor switch paints the melody with a different mood. What sorts of differences do you hear in the two different keys?

Overworld Theme – “Adventure Awaits”


The last part of the Main Theme I’d like to examine is the final 2 bars. I like to call this the “Adventure Tag”. A tag is a musical device that is used to delay the end of a phrase before returning back to the tonic chord. In the Main Theme, the last section modulates to C Major and ends with these two bars:

Observe how I used the chords Ab (bVI) – Bb (bVII) – Csus (Isus) – C (I):

This bVI – bVII – Isus – I chord sequence has an adventurous sound to my ear and I used it as a cohesive harmonic motif to connect several of the musical pieces. For instance, I use the “Adventure Tag” at the end of the Adam Village theme. Adam is the home village of our heroes Kellan and Asrael and even though it’s a soft, sleepy town nestled in the woods I used this tag at the end to hint at the coming adventure of our party. Listen below:

“Adam – Home Village”


As the player plays through the game, I hope they can pick up (subconsciously) these melodic and harmonic motifs and allow them to help better tell the story. My next post will delve more into these ideas when I analyze the character Darrio’s motif.

Musically yours,

-Tyler