I learned two things creating my entry:
-
You can learn enough about programming to create an RPG-style combat system in Twine.
-
If you’re trying to create a combat system that is interesting and fun, then learning how to program in Twine is the least of your problems.
Even if I had a PhD in Actuarial Science, I think I’d still be struggling with the math required to balance an entertaining combat system.
I ran into problems from the start: how many experience points should you need to level up — should it be a set number, like 100XP each time, or should it scale linearly? Or exponentially? Or one of the other scaling words that math people know? (Geometrically?)
When I tried to answer these questions with the internet, I encountered The Art of Game design: A Book of Lenses by Jesse Schell. It didn’t answer any of those questions, but it reoriented my efforts toward more productive outcomes.
Mostly, I solved problems by coming at them sideways and backwards. Instead of gaining experience for the player, the game was going to collect experience for the location. Each successful night earned one experience point, and ensuring a successful night became more demanding over time. (Focusing on the venue also allowed for a gender-neutral protagonist and avoided the additional challenges that would come from things like character classes.)
The story developed around a series of fight sequences, and each of those involved 5 encounters. What happens if the player loses an encounter? They shouldn’t die. Maybe they’re graded on the number of fights that they win? That sounded like a gladiator in an arena, which didn’t interest me. Maybe the player should collect valuable objects that can be stolen? Their performance would be evaluated based on the objects they retained.
Math vs. Reality
I created a carefully spaced progression system, leading players through six levels of development. That was thrown out when I saw that players kept quitting on level 3. They were trained early on to expect rapid advancement, and when it slowed, they thought that the story was over. (This was also a hint that the fight sequences weren’t very interesting.)
The math involved in combat mechanics wasn’t any easier than sorting out the XP issues. The original combat system was elaborate and rule-based. Weak monster attacks hit more frequently, and powerful ones connected less often. The player had an easier time hitting monsters that could take a lot of damage, and fragile monsters were harder to hit.
I tossed that system after people reported fights where both parties went unhurt for 5 or 6 rounds. Careful observers may notice that the combat mechanics in the competition entry still aren’t thrilling, but things happen much more often.
Fractions were also an issue. Smash attacks were fractionally more powerful, and the player or the opponent could end up with fractions of health — one reviewer found a game-breaking bug after their health ended up greater than 0 but less than 1. Those fractions resulted in health displayed as crazy decimal numbers.
I tried to avoid decimal issues by describing combatant health in text, which saw mixed results. For the post-competition release, I figured out how to use the .toFixed(0) syntax and managed to display player health as a percentage.
Javascript Objects
The game’s extensible bestiary may have been the only part of my process that worked as I had intended.
The combat script references the properties of a generic $monster object, and each opponent has a master passage that establishes it as an object and defines its properties. Those properties included combat variables like hit points and damage dealt, but also descriptive messages for things like attacking, winning, and losing. At the start of an encounter, Twine’s “include” command set the generic $monster.properties to match the properties of specific opponents.
I put together a prototype where the player fought goblins, kobolds, orcs, ogres, and trolls. Once that was working, I replaced them with the game’s real adversaries.
I should have spent more time coming up with a wider variety of opponents. In her postmortem for Erstwhile, Maddie noted that after you spend a lot of time working on a game, “you accrue serious doubts about its quality,” and ultimately, I choked. I convinced myself that I shouldn’t even be writing this game in the first place, so I settled for 6 different encounters as “good enough.”
The comments from reviewers and other authors were very supportive, and I had some time on my hands during the judging phase, so I created 7 new encounters for the post-competition release.
End with the Start in Mind
The game ends abruptly. The original endings were worse.
My unplanned process fell into a “prototype the hard part first” approach, which was helpful when the constraints of my programming skills encouraged me to get creative with the story. It was less helpful when I learned that the player experience was not matching the system I created on paper.
Originally, the player would be menaced by Stewart, an earlier visitor to the tavern who had also spent some time collecting things on the other side of the portal for Max and Diana. Stewart had gone native, and his mastery of The Otherside would make him a formidable opponent. This wasn’t going to work — if balancing basic combat encounters was tough, then trying to create adequate tension for a final showdown was impossible. But I needed some way to end the story.
I tried forcing random endings on the player based on their earlier answers, like the question about dealing with the royal survey team. The results felt arbitrary and unconnected to the larger story. Many of them introduced new elements at the last possible moment.
I replaced those endings with the final pursuit sequence. It turned out better than I had expected, but it still doesn’t end the story well. There’s little entertainment value in remaining at the tavern, but there’s no compelling reason to leave, either.
Conclusion
Development of this game was a thrilling exercise in blundering through things from odd directions, like the maiden voyage of an alarmed hippo that became an accidental jet ski pilot. Luckily, there were no permanent injuries.