Juggernaut 2: Beginning the Remake

I’ll kick off my blog’s content with a post about my current project on ROBLOX. It is a remake of Juggernaut, my game from two years ago which won Best Co-op of 2013. Until now, the game was known as Project Naughty Wolf to keep it relatively unknown.

Screenshot of Juggernaut 2 development
Screenshot of a testing session of Juggernaut 2. Names and chat blurred for privacy.

The game was relatively popular back when it first released, but its following waned relatively quickly. There were a variety of factors that went into the original game falling out of favor, however the main reason why development on the game halted was that new methods of development were being released on Roblox. ServerScriptService, ServerStorage, ReplicatedStorage, BindableFunctions, BindableEvents, RemoteFunctions, RemoteEvents and last-but-not-least FilteringEnabled all drastically changed the way Roblox games were created – and this game still had every script in the Workspace and stored maps in the Lighting. Not just organizational things held this game back: there were a lot of weird hacks and bad programming practices used to create some of the elements like blood drips and health bars.

A complete remake was the only solution to the game’s problems. Every element of the game I could make cleaner if I were to rewrite all the code from scratch, so I began. I made sure to start simple and use a lot of the resources I had already created since making the original Juggernaut. Twoof these resources was new health bars and a new combat API.

A player losing health.
The new health bar: A player losing health.

The health bars in the original Juggernaut were lacking. You had to hover over another player to see their health, which was annoying for the Medic class to find out who needed health. You couldn’t tell how much health the Juggernaut had either, and his health bar looked exactly the same as your allies. When you lost health, you didn’t know how much you lost; only how much health you had left. All while having to mentally calculate given a fraction on the bar itself. You couldn’t tell how much stronger one player was to another, as all the bars looked the same.

A player gaining health.
The new health bar: A player gaining health.

The new health bar (shown in these gifs) solves all these problems. You can see the amount of health you currently have on the bar itself. The tick marks on the bar become thicker as a unit has more health (look at the Jug’s health in the first screenshot in this post). Red and blue effects appear on the bar itself when healing and damage are received. The pop-up text effects also were improved to be larger when larger portions of health are affected (losing 75% of your max health is more important than 25%, for example.)

Shield power-ups were also redone in Juggernaut 2. In the old game, shield power-ups gave 100% damage invulnerability for a certain duration. This was not fun to play against as it forced anyone playing against it into “defense mode”, a one-correct-choice situation. Don’t force players into making one decision unless you’re making it for them. Also, this was incredibly hard to balance number-wise because I only had one lever to control: duration. I sought a better solution.

New combat mechanic: Damage-absorbing shields.
New combat mechanic: Damage-absorbing shields. In this recording, a 50 health shield is taken. 35 damage is dealt, then 25 damage.

I wrote an API to make combat with Roblox humanoids more enriching. I call it the Rich Combat API, and one of its features is damage absorption. If a unit were to take 50 damage, you could give it a 20 damage absorption shield beforehand and instead the unit would take 50 – 20 = 30 damage. The shield would be consumed before health. This was the solution to the “anti-fun invulnerability”: replace it with temporary damage-absorbing shields. I also get another lever to control the power of shields: amount.

New combat mechanic: Bloodlust. Killing an enemy gives you a decaying shield.
New combat mechanic: Bloodlust. Killing an enemy as the Juggernaut gives you a decaying shield. Look how happy my victim was to die.

This simple new mechanic allowed me to create much more interesting combat mechanics. For example, I wanted to reward the Juggernaut for performing well and killing its targets. I didn’t want to ever heal the Juggernaut, because I wanted damage to be permanent. Instead of healing, I turned to the shield mechanic: when the Juggernaut kills prey, he gains a percentage of the victim’s maximum health (currently 65%) as a shield which decays over time. The shield loses a certain percentage of its current value or a flat amount, whichever is higher (currently 15% or 7.5 hp/s).

There’s a lot going on here in this small effect, game-play wise. First of all, the Juggernaut’s net gain in power is highest right after he has just killed someone, as it should be. It encourages the Juggernaut to be aggressive after every kill (to make use of the new shield). If this power is overbearing for his next targets, they can make the choice of running away and stalling out the shield until it runs out. Alternatively, they can face him head on with the shield and break their way through it. Because of the percent decay rate mechanic, a super healthy character dying doesn’t mean his allies have to deal with a huge spike in power for a long time. Finally, I have plenty of levers to balance this number-wise: the shield reward amount for a kill (65%), the flat decay rate (7.5 hp/s), and the percent decay rate (15%/s).

It is important to give players choices when creating games. If you feel your game has little choice for players, perhaps you should expand or replace your current mechanics. Experimentation is important, so play test your new mechanics often and don’t change too much at once.

That wraps it up for this post. I have plenty of other interesting things to journal about with Juggernaut involving the combat mechanics. Next will most likely be weapon damage and balancing around an all-vs-one style of game.


Leave a Reply

Your email address will not be published. Required fields are marked *