Sunday, September 03, 2017

War! What Is It Good For? Several Hours Of Gameplay.

Part ten in a weekly(🔫) devlog.

Standard development disclaimers apply. This is pre-pre-pre-Alpha content, everything is subject to change, features may not be present in the final version, there's a very strong chance none of this will ever be released, etc. etc.

There shouldn't be any plot spoilers in these posts, but there will be occasional discussions related to characters, locations, mechanics, and other aspects of my potential upcoming Shadowrun campaign (tentatively titled "CalFree in Chains"). You may wish to skip them if you'd like to be completely surprised.

So, status update: I've "finished" my first scripting pass through the first three scenes of the game. This includes the introductory/tutorial-ish scene, which is the shortest in the game. It also includes one that's... I don't know if it's necessarily the longest or the biggest, but it's the most sprawling, with lots of different elements kind of mushed up together. I still have (cough, cough, mumble, mumble) scenes left to do, so I'm still a ways off.

What I'm Doing

"Finished" is a very relative term here. I'd estimate that I'm about 90% to "feature complete" on each of those three. I've identified a few things that I'll need to circle back to later: plugging in some side-quests, updating some general mechanics (stuff like banters and failure conditions) and making a few creative updates. In terms of total work, these scenes are... I dunno, maybe around 60% of the way to where they need to be for my initial beta testing. I've run through the scenes multiple times and confirmed that they are beat-able, but I have no doubt that more bugs will continue to pop up with each additional run-through, so more polish will be needed. That said, it does feel really good to be making steady progress on them, and having this sort of early/interim signoff process allows me to feel a bit of momentum, and get a sense for how these things will chain together.

The specific mission I'm working on now is the Sacramento one that I've mentioned in my earlier posts on dialogue. This is the first of a couple of scenes that have potential pacifist routes: you can complete the entire mission without firing a shot or killing anybody.

That said, even though there is a pacifist option, there still is optional combat as well. Most players should have a pacifist route available, but in some unusual situations (like, say, a player who dumps all of their Karma into Body and doesn't bring along any other teammates) might be forced to fight. Others may just grow impatient with the puzzles, or decide that it's more in character for them to go in hot and heavy.

So: optional combat in this one, and non-optional combat in most scenes. Fighting makes up a significant part - heck, I'll go ahead and say the primary part - of my Shadowrun campaigns' gameplay. This post will look at how fights work.

Old-School Fighting

In the prehistoric era of the 1.0.4 Shadowrun Returns engine, I absolutely loved fights because they were the one part of game-creation that took longer to play than they did to build. Making a map might take ten hours and result in sixty seconds of movement. A dialogue might take an hour to write and two minutes to read. A puzzle could take two hours to create and between thirty seconds and five minutes to solve. But a fight? Maybe just around two minutes to set up, and between two and five minutes of gameplay to beat.

Over the whole course of Shadowrun modding, though, combat has been hit harder than probably anything else. One of the early updates (probably around the time of the shift to the 1.1.x engine) revamped how turns were handled. The main side-effect was that enemies now always went first in combat. Suddenly, among the hundreds of mods published for Shadowrun Returns, fights that used to be easy became impossibly difficult, allowing foes to one-shot your primary character before they even had a chance to respond.

Solving this required reworking a lot of those fights, adding specialized triggers to manage hostility and positioning and stuff to keep that dreaded ganking from occurring. That worked for a while... but then came Gumbo AI, and everything changed again.

Fortunately, stuff has ended up in a good place: the end result of all these changes is that combat is a lot more challenging and fun than in the 1.0.4 days. Fights used to mostly revolve around buffing and overwatch. Now, fights feel much more fluid, transitioning between turn-based and freemove; they're more tactical, with positioning and cover being really important; and they're much more varied, with a wider variety of weapons and spells and tactics to use.

The flip side, though, is that fights are no longer quick and easy to set up. Making a fun fight requires a bit of planning and a fair amount of scripting. I'll be examining the most common types of fights in this post; boss fights are unique one-off affairs that aren't necessarily useful to consider, so I may or may not cover those in the future.

Rules of Engagement

In the Hong Kong engine, fights might initiate in a few different ways. (Note: I'll be using the term "Lonestar" to describe a generic hostile team, in keeping with the editor's default teams.)

From the Environment

The most common setup is that Shadowrunners and Lonestar are mutually hostile, and Lonestar's backs are turned to Shadowrunners. You will see the pistol icon light up once you spot them, but will remain in free-move mode until the enemy detects you or you manually enter turn-based mode by clicking on the pistol.

This is the most forgiving type of fight to start. Since you control your positioning AND can buff in advance AND all four of your people get to move before the enemy does anything, you can inflict significant damage from the start. You'll almost certainly take out at least one enemy before they can react. Players also really like being in control so they can set the stage as they want.

That does mean that these types of fights can be a bit too easy and boring, though. And, if you try to make it more challenging by bumping of the number of opponents, then it might be too difficult in the other direction if players wander into their sights prior to initiating combat.

There are also only minimal storytelling opportunities with this setup. You don't always need storytelling: maybe you're in a cave, and there are a whole bunch of hellhounds in there too, it isn't surprising that you would open fire. But players might feel uneasy about launching an ambush on a group of people if they don't know who they are, what they're doing, and why they might be considered enemies.

Talky Shooty

This might be the most common setup for a combat encounter in my campaigns. You chat with someone, and at the end of the conversation, a fight breaks out. This might be based on a decision your character makes, or might be a pre-ordained result

I've been following Harebrained Schemes' design for this sort of fight, which works well. The basic structure is:
  • Within the conversation, enable a trigger to mark that the fight will begin.
  • That trigger fires when the conversation ends.
  • Issue orders to all of the opponents, generally telling each one to move to a specific spot on the map (probably behind cover).
  • Isolate Lonestar as the only active team for 1 round.
What this means is that the enemy moves first, but they won't attack.  In practice, this tends to lead to a challenging but non-frustrating fight. You can still plan out your strategy, can protect your main character, and, because the enemy is in a defensive position, won't immediately wipe them out.

The one slightly annoying thing about this is that enemy mages, in particular, can move and attack on the same round. I haven't been able to figure out why or how to stop it; it's probably deep Gumbo voodoo.

In general, though, this is a really good overall design for most fights. It gives the player story and context for what's going on, sets clear motivation and objectives, and presents a challenge without seeming unfair. The flip side is that you do need to write a trigger and do some additional tuning to make sure that people are moving to good locations. So, the days of creating fights in two minutes are over, but we're getting better fights as a result.


This is sort of a combination of the first two encounter types. A fight starts from the environment, but the enemies make the first move instead of you. But, we still want to avoid the "ganking" problem, so we need to ensure that the enemies don't actually hit you before you get a chance to react.

The script for this type of fight looks almost identical to the Talky Shooty one. The difference is how it is triggered: generally it's the result of your player character entering a particular region, which I tend to refer to as a "tripwire". I also generally stop the Shadowrunner teams' movement at the start of the trigger; otherwise, characters might have expended some AP in finishing their moves from before the start of the fight, and as a result will start with just 1 AP in the first round of combat.

Complexity and Victory

Trash fights are pretty boring. They aren't necessarily bad. I have a few trash fights in my early scenes, when players are still evaluating their builds and combat strategies: it gives a chance to try things and make mistakes without getting punished too badly. And it can sometimes work well thematically or for gameplay reasons. If your character did something clever to set up an ambush, then it isn't unreasonable for them to have a very easy fight as a result.

In general, though, the game is more interesting if the fights are more challenging. One of my game design shifts in CalFree in Chains has been to have fewer fights but make each one bigger and harder. I think there are a few advantages to this. In Caldecott, for example, most missions had about six fights; if you kept getting dinged up for each of the first five, then you might be entering the final fight with no consumables and low health, which could make it very frustrating and require a lot of reloading and/or lucky rolls to beat. So I was weirdly incentivized to make early fights harder (while your party is at full strength) and later fights easier (so you could still complete them with a damaged team), which is the opposite of the sort of power progression you would like to see.

Do The Wave 

The most straightforward way to add complexity and difficulty to a fight is to use multiple waves of opponents. In one example, an enemy might start with five foes on the field. After you have downed three of them, then another four rush in to reinforce them, bringing their numbers back up to six. And once only three of those are remaining, two more join the fight. This has a bunch of implications:
  • It limits the "free heal" effect that is granted at the end of each fight. Instead of three free heals for three separate fights (against 5, 4, and 3 enemies), you just get one free heal (across a total of 12 enemies).
  • Buffing is more useful. If you are just facing 3 enemies, there isn't as much point in casting spells like Aim or Armor: you're better served by just cutting down the enemies ASAP. But if the fight lasts for longer, then you'll get the full use out of those abilities.
  • The fight becomes less predictable and more interesting. In particular, you might have established a line against your foe, only to have some strikers threaten your flank or rear, forcing you to reposition.
  • Along the same lines, having foreknowledge of the fight becomes more useful. If you do lose the fight because a second team hit you from behind, then when you reload, you might be able to set up a shaman's barrier or leave a character on Overwatch, which could turn the tide and lead to a resounding victory.
I used the wave approach in Caldecott, but usually only for major boss-level fights, since I had so many smaller combat encounters; for CFiC, I'm planning to use it much more often, especially in later scenes. I'm also taking what I think is a much better approach to actually introducing new waves. In Caldecott, I would just teleport the new set of enemies onto the map. This was easy to program, but would generally leave the new enemies as sitting ducks that the player could hit hard before they had a chance to move; conversely, if they spawned at the end of a player's turn, they could strike hard before you had any chance to respond.

In CFiC, I'm using waves more like HBS does. In general, the idea here is to teleport the enemy in behind a closed and locked door - so, they're in the scene, but not yet visible or active. I issue orders for them to move to a specific location, similar to the Talky Shooty / Ambush triggers. And, that's it. When Lonestar's turn comes around, they'll charge through the door, take position behind cover, and then it will be up to the player to decide how to react. Again, more work than before, but I think it leads to a better result.

All Skate

Fights can be a lot more fun and interesting with multiple teams on the field at a time. The stereotypical approach is a three-way firefight between cops, gangers, and Shadowrunners. You can dive into the middle of the conflict, or try to fall back and let the others whale on each other for a while to soften up. But alliances are cool too: if you're facing a powerful foe, it feels good to have some friends on your side who you don't directly control but who aid you against a common enemy.

For the most part, this "just works". The Gumbo AI is pretty smart about how allies operate; you'll occasionally get hit by friendly fire, but they'll also buff you when they can.

Measuring Progress

You don't necessarily need to do anything to mark the end of a fight. The engine will automatically transition back into freeemove mode once there are no more hostiles visible, and you can continue on your way. But sometimes you'll want to do something special: start a conversation or drop a key or update a goal or whatever.

The most useful element to track fight progress is the integer function "Get count of alive actors". I tend to assign tags to enemies to track them. For example, some enemies might get "isHumanis" and "isHumanisWave1", while others might get "isHumanis" and "isHumanisWave2". When an actor dies, I can count to see if it's time to bring in the second wave yet, or if the entire fight is over.

Adjusting fights is a bit more time-consuming now than before: I can't just drag in or delete an actor spawner, I need to also update the triggers and regions associated with their initial moves. BUT, by using these counting triggers, I can track the logic of the fight independently of the specific actors involved in it, so at least that part of the scene won't need to be updated when I later adjust the opposing forces.

A Sample Fight

Let's look at some stuff! It's been way too long since I showed any video, so for this section, let's look at a fight's triggers and the results.

Code It Up

This is one of the very first fights in the game. It actually combines the Environmental and the Talky Shooty approaches, with the player able to determine their approach. You'll encounter a group of people who are threatening someone and acting menacing. You can choose to ambush them for an advantage; or you can try to talk, which will still ultimately lead to combat but will give more information about what's going on. This is a mildly important roleplaying decision for the character: are they impulsive and violent, or cautious and diplomatic? Other party members will make note of your behavior and comment accordingly.

First, here's the trigger that fires if you hit your opponents first.

  • As we'll see later, this trigger will be disabled if your opponents spot you, so this only fires if you attack first.
  • We skip the opening conversation in this flow, but show a little big of ambient dialogue. This helps establish one character as a friendly, and makes it a bit more interesting and fun.
  • We disable the other talk-related trigger to make sure that one doesn't fire when your opponents detect you.
That's pretty much it. Gumbo AI will ensure that the enemies behave smartly once it's finally their turn to move.

The Talky/Shooty flow has two parts. First, when you approach the foes while they're in place, we disable the ambush, start the conversation, and enable the actual fight trigger.

The real fight-related stuff is in the "FightAfterTalk" trigger. Note that this one is not active by default, we only set it up when going through the conversation flow.

Nothing too complex in here. After the conversation is done, they all move to their locations before the player can do anything, then wait patiently for the next turn.

And, regardless of how we begin the fight, it will end with this trigger, which starts another conversation once this particular group of enemies has been defeated.

Finally, just for fun, here's what the map looks like in the editor. Note that the actual enemies aren't on screen yet: they get moved in in response to another action that the player takes earlier. You can see a bunch of little 1x1 pink regions in there. Half of them are "TeleportDest" regions where I will place the enemies; the other half are "MoveDest" regions that describe where they should go for the Talky Shooty flow.

In Action

As promised, here are some brief videos. As in most of my debugging, I'm running through this as a Level 6 Lucky Strike, who makes short work of the Level 1 enemies I'm facing. I'll worry about tuning the difficulty of the fight later, in this phase I'm just concerned about the logic of how the fight works.

Here's the impulsive approach, sneaking behind them and attacking.

And here's the cautious approach, where you exchange words prior to opening fire.

That's it for now! Lots more fights to write and fix and tune, but on the whole, at this early stage, I'm fairly pleased by how the combat feels so far.

No comments:

Post a Comment