Wednesday, July 31, 2019

Saber's Mark

A couple months ago I threw the words "my noble phantasm is" into a Markov text generator, and I found the results weirdly evocative. I expanded the text into a short story as an exercise, and wound up liking it so much I posted it on AO3.

I wrote a follow-up to that story called Saber's Mark. It's about three times as long and much more ambitious. I'm really happy with it! It's all original characters, so you don't need to be familiar with any specific Fate/stay night story to enjoy it. (It does assume some basic knowledge of the setting.) I hope you'll take a look!

Friday, July 12, 2019

Combat Design in RPGMaker 2003 — A Technical Rundown of Facets’ Bosses

I've heard a few friends ask about how to program complex enemy behaviors in RPGMaker. There are lots of conceptual resources on this, but not as many technically-focused ones. I spent a lot of time last year fiddling with RPGMaker 2003's combat tools, so I'm going to go over what I've learned by explaining how each of the bosses from my game Facets work on a back-end level. This documentation assumes a basic level of familiarity with RPGMaker. I’m focusing on the 2003 version, but a lot of these principles are applicable to other versions as well. My hope is that this post will serve as a reference to readers who want to make interesting combat encounters in their RPGs. I’m not an expert obviously, but I want to help developers expand their toolbox for this sort of game design. Feel free to download Facets and open the game in RPGMaker 2003. The RTP assets might not load correctly because of differing folder paths, but you should still be able to look at the back-end scripting in the database and follow along. Note that I left in all the default skills and monsters, so you’ll want to scroll to the bottom of each tab to see the ones actually used in the game.1
The Crawler is probably the first boss a player will fight in Facets, and it’s one of the simplest. The Crawler randomly picks between just two attacks at first: Attack and Fire. Attack is one of the default abilities available to every enemy. Its damage is determined by the enemy’s attack stat and the target’s defense. Fire is a skill, so the damage it deals is mostly determined by its “Effect Rating.” It deals about 30 damage, with a variant of 5 or so. You can see that because the Crawler uses Fire, I also made it strong against fire based attacks and weak against ice. It has an “E” rank for fire meaning it takes very little damage, and an “A” rank for ice meaning it takes about double damage. (You can change these percentages in the attributes tab.) You’ll note that both Attack and Fire have the same Priority in the Crawler’s movepool: 50. In my experience, if you set a single move’s priority to 100 and the other to 50, it will use the one with 100 every single turn. I mostly only use priority to let bosses choose randomly between a set of 50-priority moves, or to force the use of a single 100-priority move with switches. You can control what moves a boss has available to it by setting “prerequisites” to moves in its move pool. This is how I change the Crawler’s behavior in the second half of the fight.

Once the Crawler hits half HP, it has a chance to activate its “Power Up” cycle. Power Up is a buff that raises the Crawler’s attack, and I’ve included the same skill three times in its movepool. The first Power Up becomes available at <50% HP. Once it uses that first Power Up, a switch is turned on and the second 100 priority Power Up becomes available. It will always use this on its next turn, because all other available moves are 50 priority. This second Power Up in turn activates another switch while turning off its own switch, so now once again there’s only one 100 priority move available: the third Power Up. Which in turn turns off its own switch and activates a final switch. This switch turns on the 100 priority Attack move. The end result of all this? A little after the Crawler hits half HP, it uses the Power Up buff exactly three times in a row to dramatically raise its attack. Then it starts using exclusively physical attacks and one-shotting your characters. The player has just enough time to kill the Crawler before it starts getting off these attacks, so it turns into a race to kill the Crawler before it finishing buffing itself. It’s pretty exciting! And all it takes is a few switches and no custom battle events. By manipulating the available move pool of your boss with HP totals and switches, and selectively forcing certain actions with 100 priority moves, you can make interesting behavior with very little programming logic.
The Medusa functions similarly to Crawler, except she doesn’t use any switches at all. She just has two different movepools dependent on her HP total. At 50-100% HP, she uses Attack and Bolt. Under 50% HP, she uses Attack, Double Attack, and Gaze (a skill that deals no damage but has a chance to insta-kill your characters). It’s not complex, but by giving the boss two action pools dependent on her HP it immediately feels more dynamic than an enemy with a static move pool. Note that her agility is slightly higher than the Crawler, so she attacks more often and feels a bit more dangerous as a result.
I had to squint a bit to remember what was up with the Mimic -- its action pool looks more complicated than it is just because I wasn’t ready to make custom battle events when I first made it. All it boils down to is that the Mimic uses Attack OR Ice three times in a row, then uses “Regenerate” (which fully restores its very low HP). The first action turns on the Mimic1 switch, the second turns on the Mimic2 switch, the third turns on the regenerate switch. Then it starts over from the beginning. The switches work the same way as in the Crawler fight -- it still uses three actions in a row, and then a different fourth action. But those three actions can each randomly be either Attack or Ice, and after using Regenerate it starts the cycle over again by resetting its switches.
The Lamia is the first boss the player will encounter that uses custom battle events to govern her behavior. Battle events are bits of programming logic you set at the encounter level that let you design more sophisticated enemies. You can view these battle events under the “Monster Group” menu. Like actions in the Monster tab, each battle event has a precondition, and the game checks all of these preconditions once per turn. If a precondition is true, the event activates. You can set an event to activate once every turn by setting it to “1x turn”. You can also set it to activate when a specific enemy’s HP is low, or when a switch is activated.2 The Lamia is one of the most complex enemies in the game, because I had a very specific effect in mind I was going for and I really wanted to shoehorn into RPGMaker’s engine. She has a pool of four actions from 50-100% HP: Attack, Constrict, Venom, and Fire. It works the same way as the previous bosses we went over. At 50% HP, the “Unhinge Jaw” skill is activated by a battle event. This is a blank skill that does nothing -- when the Lamia uses it, she flashes for a second, and then the text “Unhinge Jaw” flashes across the top of the screen. Blank skills like this are the ONLY way to pass messages in the small window at the top of the screen, and you CANNOT activate skills directly from the custom battle events. Whenever you want to have a battle message like this, it has to be in the form of an actual enemy action. (You can activate normal text boxes in battle from the battle events, but these take the place of the battle action window and generally feel clunky.) The Unhinge Jaw action turns on a switch, forcing the Lamia’s next turn to be the Swallow action. Swallow is another blank skill because its behavior can’t be defined in the Skill window. It just activates a switch that in turn activates a custom battle event.

The battle event activated by the Swallow switch removes a party member from the battle, permanently. Specifically, it flashes a “Bite” battle animation across the chosen player character, waits for the animation to finish, flashes the screen white for 0.5 seconds, and then during that flash removes the character from the party. The battle events keep track of how many characters have been Swallowed with a variable, and after a certain number of turns it reactivates the “Unhinge Jaw” skill, setting the process in motion again. The code for this is much more complicated than it needs to be because I originally wanted the Swallow event to select a character randomly. That’s why there are so many extra branch events. I ultimately settled on it activating first on Rory, then on Claire, then on Ellis. This was simpler both to code and to balance, and I think it’s a better player experience. There’s a problem though: RPGMaker doesn’t let you remove the final player from the party. Ideally, the Lamia should be able to Swallow the last character and then trigger a Game Over. I got around this by adding a fourth, blank party member to the team during the flash and then immediately removing Ellis. This allows the game over to work like normal. (Note that the player can see the blank party member added in the battle menu, so it’s still not a perfect solution.)

The Bat is much simpler. It uses the “Triple Guard” action immediately at the start of the fight. This is an empty skill that does nothing but play the Triple Guard battle animation over the Bat. The bat has very high defense and needs to be attacked with Magic -- the Triple Guard animation is just there to telegraph the bat’s high defense and explain why it’s there.3 Immediately after using Triple Guard, it uses “Toxin”, which poisons all party members. After that its movement pool is limited to just “Life Drain” and “Magic Drain”. Its only custom battle event is a timer, which turns back on the Toxin skill switch every 20 turns.
The Carbuncle is mostly simple: it uses all three elemental spells and the heal move. At 50% HP, a custom battle event turns on the “End of Us” ability, a blank skill which activates a custom battle event with a switch. Said battle event plays a pretty rainbow animation, stores each party member’s HP into a variable, and then subtracts that value - 1 from their HP. This multi-step process is necessary to set every party member’s HP to 1 -- you can only add or subtract party HP in battle events, not set it directly. A switch ensures The End of Us is only activated once per battle.

This is mostly straightforward, especially compared to the Lamia. Where it gets tricky is the Carbuncle’s “Barrier.” At the start of the fight, the Carbuncle uses a skill called “Barrier - 200 HP”. This plays an animation and turns the Carbuncle a different color. If you deal any damage to the Carbuncle while it has the barrier up, it heals to full HP on its next turn. If you deal more than 200 HP worth of damage in between the Carbuncle’s turns, an animation plays, and it changes back to its normal color. Basically, the Carbuncle puts up a “Barrier,” and you have to deal a lot of damage to the barrier in one set of turns in order to break it. Only then can you start dealing damage to the actual boss.

I made this effect by creating three separate Carbuncles. All three are present in the Carbuncle Monster group, just layered on top of each-other. The first is the only one set to “visible” at the start of a fight, and it does nothing but activate the barrier skill. This blank skill turns on a battle event which plays an animation, makes the differently colored “barrier” version of the Carbuncle visible, and erases the first Carbuncle. “Visible” is a misnomer in RPGMaker -- an enemy set to “invisible” is completely inactive. It makes no actions, and if you kill all visible enemies the encounter ends. Keep that in mind.
The Barrier version of the Carbuncle has access to all the skills of the “real” boss: Fire, Ice, Bolt, and Heal. But instead of 900 HP, it has 20,000 HP. This high number is to ensure that the player has no chance of killing it normally. A battle event checks whether the barrier Carbuncle has less than 20,000 HP, and turns on a switch if it is. This switch activates the “Barrier regenerates” skill which activates a battle event that heals the Carbuncle by exactly 200 HP.4 If the Carbuncle battle events detect that the barrier’s HP is less than 19,800, it plays an animation, makes the final Carbuncle visible, and erases the barrier Carbuncle. From there the fight proceeds normally with no other barrier trickery.

The two kinds of Sylph encounters are trivial programmatically. The first two have high HP and escape immediately at the start of the battle, so there’s no chance of the player killing them. The last one does nothing but Attack very weakly, Defend, and attempt to Escape. Because this fight is activated in the pincer formation, the escape attempts always fail.

The Wyvern doesn’t use any principles we haven’t already gone over. The boss attacks or does nothing for a few turns, and then starts counting down from 5. At the end of the countdown, it uses “Explosion”, which deals enough damage to kill any player character not using the Defend.5 The countdown numbers are just blank skills that manipulate switches. The time between countdowns is controlled with a simple counter battle event. Easy peasy.

The Slime is the only fight where I’m not fully satisfied with the implementation programmatically. The slime’s main gimmick is the “Multiply” move, which spawns another slime. I accomplished this by adding a single visible slime and then seven invisible slimes, then putting the Multiply move on a timer with battle events. The Multiply switch is turned on by the timer, forcing the slimes to use the Multiply skill, which itself turns on a "Multiplying" switch which activates a battle event. The battle event spawns another slime by flashing the screen, playing a sound, and making the next slime visible. It knows which slime to make visible because the events keep track of how many slimes have been spawned with a variable.

The issue with this is that only one use of Multiply should occur when the timer activates the multiply switch -- using the Multiply skill turns off the switch and makes it unavailable. But sometimes two slimes will queue up the multiply move at the same time and use it one after the other, spawning two more slimes instead of one. This is a much harder challenge to deal with for the player, and it occurs very randomly. I couldn't figure out how to fix this.6 The slimes themselves are very basic -- outside of Multiply, their move pool consists of Attack, Venom, Regenerate, and an elemental spell corresponding to their color and weakness.
The Phoenix is the final and hardest fight in Facets, and it’s actually made up of five distinct encounters, each one slightly different. They break down roughly into three phases -- the first fight, the middle three fights (which mostly share the same behaviors), and the last fight. It’s an intense set-piece, but easy to program because it has very few unique behaviors. Almost every part of the fight borrows from earlier bosses. The first fight is straight-forward. At 50-100% it pulls from a static move pool: Attack, Double Attack, and Fire. Under 50%, it starts counting down from five, just like the Wyvern did. It uses “Inferno”, an attack that looks different but is functionally identical to the Wyvern’s explosion. All of this is stuff we’ve implemented before. 

The second, third, and fourth fights are unique in Facets because they use actions in a static, cyclical order from start to finish. This was simple to implement: I just used the “turn on and off switches on 100 priority attacks” structure we’ve been building on since the first fight. Almost none of the attacks are new as well. Phoenix-2 uses Attack, then Constrict, then Life Drain, then Flame (a unique move to the Phoenix, but functionally just a stronger Fire with a different animation). It also has only 1000 HP instead of 1500 like the rest. This was to tighten up the pacing a bit, since the player was fighting five bosses in a row.

Phoenix-3 adds a few more moves. It uses Attack, Constrict, Venom, either Life Drain OR Magic Drain, Gaze, Flame, Regenerate, then Observe Battle (which does nothing). It also has a 200 HP Barrier set up at the start of the fight, the same way the Carbuncle did.

Phoenix-4 sets up a 300 HP barrier (with a different color) instead of a 200 HP one. It exclusively uses Magic Drain instead of choosing between that or Life Drain. It adds The End of Us after Flame. And it uses Power Up after the Observe Battle step. A ten action cycle. (It also uses “Piercing Gaze” instead of just Gaze, but from my testing it doesn’t insta-kill characters any more consistently, even though the effectiveness is set much higher.)
Phoenix-5 is a puzzley gimmick fight to follow the real climax (Phoenix-4). All it does is count down from 3, then use “Immolate.” Immolate is a copy of the Inferno ability that insta-kills your party if they aren’t Defending; the only difference is that it also deals 400-500 damage to the Phoenix, and it counts down from 3 instead of 5. All simple changes to implement (the self-inflicted damage is triggered by a battle event).7

Fifteen fights and ten bosses total, all differentiated enough to be interesting set-pieces, and all concocted with only a handful of tools:
  • Altering movepools based on HP.
  • Forcing specific actions using switches and custom battle events.
  • Building actions in the custom battle events and activating them with switches triggered by blank skills.
  • Stacking invisible enemies on top of a visible one and changing them out in a battle event, or spawning new enemies entirely.
If you learn how to control these tools, there’s no limit to the enemy encounters you can craft in RPGMaker! Even if you reproduce these fights exactly (as I reproduced fights from Final Fantasy), they’ll be changed by the context of your player characters’ abilities and by the context of your story.
So open up an editor and figure out how to use a few of these tools. Start off copying from here or from stories that are important to you. Before too long, you’ll have something that only you could have made. Please let me know if you do. I’ll be happy to play it <3

1 Facets uses almost exclusively default resources, but I did add two small custom scripts at the start of development. One of them removes the Fight/Auto-Battle/Flee choice prompt at the start of battle. The other removes the Row command. These cannot be turned off from within RPGMaker 2003 itself. I found the scripts with some quick googling, and all it took to implement them was dragging some DLLs into the project window. 2 This is why all encounters have a Bomb and Dream Catcher event. These are items the player can use in battle that do nothing but flip on switches. The actual item effects are defined in the battle events activated by these switches. 3 I originally wanted to give the bat very high evasion, so it could dodge your physical attacks instead of tanking them. I couldn’t figure out how to do this consistently in RPGMaker, so I settled on the Triple Guard solution. 4 I used a battle event instead of a normal skill so I could set it to heal by precisely 200 HP, preserving the illusion that the barrier has 200 HP and not 20,000. Note that the Mimic’s regenerate is just a skill, so it heals a semi-random amount HP that’s only close to 400 HP, not 400 exactly. I hadn’t figured out how to heal exact numbers with battle events when I made the Mimic, and I didn’t think to go back and change it later. 5 I originally wanted the Explosion to deal more damage and require you to use Guard several times to withstand it. But defense buffs only work against basic physical attacks. I couldn’t figure out how to have a buff raise the player’s defense against skills like Explosion in RPGMaker 2003. 6 A few months ago I fiddled around in RPGMaker and realized enemies can actually revive each other after death, completely separate from the visible/invisible setting. If I do another RPGMaker game, I'm going to experiment more with this skill and see what I can accomplish with it. 7 On a non-technical note: incorporating self-immolation into my rpgmaker game is nakedly appropriative, especially since I did next to no research on its history before releasing the game. Facets is full of politically charged imagery used without a lot of care, but this is the part that personally gives me the most pause. I think it’s a moving scene and I wouldn’t change it, but I would definitely think harder before including similar moments in my games in the future.