A couple weeks ago I mentioned that I was happy to answer random questions about my game dev practice (offer still stands!), and in the following discussion I said something about having cut a bunch of text from “the anarchist art collective” portion of the Starsector missions. There was at least one person interested in hearing more, so who am I to deny this request?
It turns out that getting to that anarchist art collective involves – for the purposes of context, of course – a meandering path through the entire process of writing narrative for Starsector. Therefore, my friends, that’s what we’re going to do today.
There will be spoilers in this post for content that was released in Starsector 0.95, the March of 2021 vintage. I won’t talk about any upcoming content ( … unless?). So if you haven’t done the so-called “main quest” of the game starting at the Galatia Academy, both myself and Hegemony COMSEC recommend you hold off on reading further.
My goal in this post is to give you guys a peek into my (and our) process for creating Starsector mission arcs, and in particular to the Westernesse/Fikenhild section of the “Finding Coureuse” mission – because, if I recall correctly, it’s where I first started writing the player-facing text of the Galatia/Gates mission arc.
That is also (currently) one of the most dialog-heavy sections of the game. It seems like most people love this stuff, though a few people do hate reading. For the latter (Why are you reading this post? Oh, never mind.): If ever you want to skip the reading in Starsector, just mash the “1” key; I try to write all dialog so that you can get through quickly by the more-or-less default route by choosing the first response in any dialog. Mashing through dialog is also helpful for testing content; I certainly don’t want to have to pay close attention as I re-test a sequence for the 20th time.
Terminology note: to orient our aesthetics correctly, we use the word “mission” instead of “quest”. A mission in Starsector is a specifically coded data structure – and a bit more – upon which a bunch of objectives, script triggers, and dialog hangs. A mission arc is a series of connected, contingent missions.
High Level Planning
It all starts with Alex and I chatting about what our goals are with the plot of the game. This used to involve extremely long emails but we’ve moved a lot of this to live chat. We’ll hash out some ideas, talk about what plot points or game mechanics a mission arc should hit, then take some time to write extended proposals in a Google doc, which we’ll then share and comment on.
The structure of these documents is pretty straightforward: started with a broad overview of goals, definition of terms, and logical structure of progress through the mission, then drill down into technical implementation notes and the full text of the written content required.
Here’s a look at the start of the Galatia Academy document:
Here we define terms, describe briefly how this piece of story/content fits into the context of the rest of the world of the Persean Section, and sprinkled throughout are notes about how we’re going to make it work with existing structures and content.
The highlighting is either highlighting or a signifier of additional comments inserted by Alex or myself. Sometimes these comments are useful, possibly more often they are silly.
I try to define the personalities of any new major characters involved at the top of the document in the definition of terms section so I can keep the plot focused on them, and plan for the art assets required. When these characters become finalized, as I start actually writing their dialog, I copy their entries into one giant “List of all Starsector Characters” document that I can refer to. This is my canonical reference for every single named character and their personality, allegiances, beliefs, relationships, and – perhaps most important – any data flags associated with player interactions with the character. For example, $haveMetGargoyle == true would allow the player character to mention Gargoyle to another character in some other context.
Here are the early drafts for a couple characters you may know from the Galatia Academy arc:
Alviss Sebestyen remained pretty much as initially conceived. And to his point: I do think it’s important not to do anything completely obvious in terms of characters. So if I ever write a major NPC as a tired archetype without giving some hint of undermining that idea, kick me.
Scylla Coureuse changed a lot during implementation. Her initial characterization got moved more onto Elissa Zal (who is lightly characterized indeed; more on that later), though I kept the “player fetches a weird food item during the story” idea.
… I suppose I should say something about coming up with characters.
Sometimes the character comes first because the setting demands a position be filled; the faction leaders for example, to both embody their faction’s archetype and the contradictions of their polity. Or I need someone to plausibly take part in a mission, or deliver a skill quote – these names all go into the List Of All Characters document which I can mine later in case I need someone to show up and do something that happens to be consistent with the characterization suggested by what little role they already play.
Other times, I need a character to play a role in the narrative. This necessity also provides a first step toward defining their personality and context in the world – you need someone who would plausibly do [what the plot needs]. But I can’t leave that uncomplicated (as a verb); the primary role a character plays needs some kind of contrast, or a seed of negation both to feel real and to give the character room to change, grow, or making plausible unexpected decisions.
For example: Coureuse has a lot of reasons to cooperate with Baird, but lots of reasons not to as well. To that point, I didn’t go into this planning for her to do a runner on Baird, but once I got to writing the end of At The Gates, it made complete sense for her to be motivated to escape from the Galatia Academy. This especially aligns with Elissa Zal’s parallel arc, which wasn’t even particularly planned – I just needed Zal to be a captive of Kanta because I thought it’d be fun to bring Kanta into the story. And then Doctor Cydonia got brought in because I drew a creepy doctor portrait and really wanted to use it, so why not stick him with Kanta. And what’s a creepy doctor for if not making the creation of life itself his plaything? So we get Clone Loke, which ties back into Kanta, and it all ties back into a bunch of other stuff I’d written as throwaway lines.
(And if I may indulge for a moment, I also rather like how Coureuse and Baird contrast as Science!-themed characters: Baird is the “visionary” who generally gets credit for huge breakthroughs because she plays the game of politics. But she’s not good enough on her own to make those breakthroughs happen, her head is in the politics, not the work- she needs Coureuse, and Coureuse is able to do what she does because she doesn’t know or care about the politicking. Coureuse is just a nerd who is intensely focused on her own area of expertise and wants to be left alone. Baird needs Coureuse, badly, and wants Coureuse to want what Baird wants. But she doesn’t. And that’s an interesting story to me!)
When you build a character with contradiction inside of them, and characters with contradictions between each other, they offer all sorts of interesting plot hooks!
Let’s jump back to high-level design before I get even more carried away.
High level mission arc structure & design goals
Here’s a high-level overview of all the missions involved in the so-called “Baird Arc” of the Galatia set:
COMSEC note: Certain elements have been REDACTED To Ensure Our Safety And Security.
A few observations:
- You can see here an intent to roll new major characters in gradually rather than all at once. It’s important not to overload players with new names, better to let them get a feel for the personalities during the course of the gameplay, ideally through actions the characters take.
- I’ve found that introducing specific, named characters even for minor roles is almost always a more successful move than generating a random one (eg. the Historian, though they’re only half-random; the administrator at Laicaille is another good example, and I might make them and their replacement into specific characters depending on if we decide to do more with the politics of Laicaille). Creating specific content, specific characters, is also in some ways less work because instead of having to script around random attributes I know for sure what their deal is – and their pronouns (the most commonly used string insert tokens used in dialog). Usually.
- We obviously didn’t make this set of missions quite as nonlinear as anticipated. It was turning into a bit of a mess to code and getting the script right so everyone would say something both narratively and tonally appropriate at the right point in time.
- The multiple solutions point can be difficult to aim for, but I did my best. Starsector has a limited number of “verbs”, and the most developed verb is “fight a fleet battle”. You kinda gotta work with the tools you have and within the terms of the game you’re making rather than pulling in weirdo mechanics that relate to nothing else going on. (… Unless?)
Here’s an example of an alternate path that we cut because it’d have added a lot of work:
You can see how it could have been an option; there was a character waiting on the sidelines to be used in just such a scheme. Maybe Caliban Tseen Ke and/or the tehcnological inspectors will show up in some future plot.
Random String Table Tangent
Just for fun, I’ll share this string table for the VIP student transport mission:
*slaps the hood of the string table* You can fit so much worldbuilding into the implications of just a couple words. I love this stuff!
Walls Of Text
This first GA Mission Arc document which I’ve been pulling shots from is 121 pages. At some point mid-planning I split the four major missions out from it because the doc was simply taking too long to load. The page count for the four mission design docs are as follows:
- The Kallichore Archive: 30 pages
- Finding Coureuse: 55 pages
- Project Ziggurat: 65 pages
- At The Gates: 87 pages
I should note, in addition to all the planning and implementation notes, I do write a full first draft of all in-game dialog in these docs.
Let’s get down into the nitty-gritty details of Finding Coureuse, then focus in on the Fikenhild “I love reading” branch of the mission arc.
In the “Finding Coureuse” design document there’s a carefully structured flow plan (…that Alex makes me write because it gets turned into the mission stages as defined in code):
The commentary in point two should speak for itself; I tried to make it fairly clear when Baird asks the player what approach they want to take to find Coureuse that they’d be taking the “talky” route. This idea came to me from, of all places, Indiana Jones and the Fate of Atlantis when you get an in-world dialog choice to how you want to proceed with your adventure- with your fists, with your companion, or figuring it out on your own.
My original plan for this section was way, way too complex. But I’ll get there in a moment.
The second point you might notice is that the involved characters on Fikenhild have a pattern to their naming: A, B, C, (character D got cut), E, F. I did this so I could keep them straight in my planning (despite somewhat breaking my “don’t introduce a zillion characters” rule; I did try to make up for it by making them distinct, at least).
Here’s the original list of characters:
Adonya changed personality and “Brione” lost an ‘r’, as well. Elissa changed personality and wasn’t even slated to be a woman, but I couldn’t find an “E” name that I liked better within the selection I was using, so I rolled with it.
The Original Text Adventure Plan
It was a fine summer day. I drank a ton of coffee, sat down with my laptop, and proceeded to pound out a complicated scheme:
This will act as a hub for three known contacts, A, B, and C. (There are also a couple unknown contacts – D and E – who will only be discovered once opened up by a known contact.) The idea here is to do a simple, small “old fashioned detective work” type mystery: use contradicting stories between initial contacts to confront one or more individuals to find out things they weren’t willing to tell upfront: two of these leads will open up hidden contacts D and E. You must talk to each of them to discover contradicting info, then confront the other to progress, ultimately getting the contact of an intel operative working for a major power who will agree to help you find Coureuse by sharing information. Dead-ends in this path will give flavour text about the world or Coureuse as an individual. To make it simple, I’ll make their first names start with the letter (A, B, C… )
A has a contradiction on B, B on C, C on A. B knows D, C knows E. D and E know something about each other. F is the end goal, the intel officer.
Yeah, um. I mean, this could be a game. It should not be this game, however.
Alex told me as much, and very kindly; something like “this might be a bit too much, maybe it should be simpler?”.
Still, you can see in the released game that a lot of the intentions here did make it in. Instead of making it a puzzle, I turned this section into a branching but linear path that ensures the player always ends up at some kind of useful conclusion that points them at the next stage of the mission. Even if it’s a Burn After Reading style mess of an intelligence operation, we have to keep the player moving forward!
When Boring People Make Interesting Worlds
This is a space opera, arguably “epic”. So why does the player meet Coureuse’s retired mother and some boring stuck-raising-children childhood friend?
In short: Contrast, pacing, and giving the world a sense of verisimilitude!
It’s the difference between early-season Game of Thrones which takes place in a world made up of people in a society and late-season Game of Thrones which involves the producers smashing cool action figures into each other while looking over their shoulder at the audience for approval. When characters don’t exist in a world that believes they’re real, they turn into weightless CGI and lot of noise which means nothing.
What makes the player’s accomplishments, and those of the major characters, mean anything in the aesthetic tone of Starsector? It’s being able to compare them with what normal people in the Persean Sector live with, those people just getting by and dealing with what they’re concerned about. Coureuse isn’t just a magic scientist (even if she is); she comes from a world of people who care about her. And if not who she is now, then at least who she was or who she had or has the potential to be or who she’s become now. Baird also “cares” about her from all of these angles, but in different ways from the supporting characters you meet here.
There isn’t a single, easy answer to anything in the story of Starsector and I’m not going to condescend to players by telling them one. It’s a process of thinking what if this, then but what if that… and that, and that.
At least that’s what I’m going for. Hopefully it’s working.
Cavin Pharoh’s Anarchist Art Collective
Finally we arrive at where I really started writing all of this: a character who thinks that the player of Starsector is an awful person.
(One might find it interesting to compare this intro with the one in the game proper.)
The aesthetics here are a mix of stuff I picked up from Vancouver’s Downtown Eastside, the cops being called on a party in a crappy art studio I was at near said Downtown Eastside, and the general vibe of anarchist infighting.
(In RL: The cops cuffed the guy who informed them that they had no right to enter a private party, milled around, then let him go and left. A cake-fight ensued.)
I like giving the player fun responses. It’s funny, makes the player feel clever, and anything beats playing the boring paladin. As per the first post on Starsector writing, I’m trying to let the player character be a kind of Han Solo type figure. Clever quips, cool moves, tricks up your sleeve, etc.
Here are the cut lines that pay off the joke responses:
I did have fun here coming up with what a couple of punks might call various authority figures in their world, and am sorry to have had to cut the lines. Such is necessity.
Part of the cuts was in fact due to trying to avoid swearing (“arse”) – which, yes, is a thing Starsector doesn’t do. Let’s get into that.
G-rated Drug Trading & Terror Bombing
Here are a couple cut segments from Cavin’s dialog:
I mean, if you’re a dirt-sider living on a water world, how are you going to make fun of Spacers? I kinda like the worldbuilding, but (after another nudge from Alex), I realized that including this sort of stuff was threatening to skew the tone off from what we’d already built.
Profanity, as an aesthetic, can feel naturalistic when used well. It can also feel like try-hard edgelord posturing when used indelicately. It’s also indelibly connected to world-building because the way in which a culture swears says a lot about its values. Or anti-values. I’m currently living in Quebec and traditional Quebecois profanity is an amazing selection of corrupted Catholic terminology. The way some guy swearing on the street tells you so much about what forces created the francophone culture of Quebec.
Along those lines, I think in the context of Starsector avoiding profanity feels less like a restriction than an opportunity for worldbuilding. What does this culture abhor, or consider taboo? On the other hand, scifi cursing can often land with a thud if it doesn’t hit the poetry of profanity. For example I’m not sure that “frak” quite works as a swear-word, but if nothing else it did become a classic signifier of its setting.
One doesn’t even have to swear, of course. Just have someone say how angry they are with their words. Properly wielded words can be venom even without profanity. It’s a fun writing challenge! For instance, if you try to buy Cavin off:
(This is also a self call-out over slight overuse of bribery as a game mechanic. Some people have principles, you know. And it’s fun to load some abuse onto the player for being a powergamer. I’ll also admit here taking inspiration from the one line about adventurers in Perdido Street Station.)
Then I need to take that text and put it into the infamous Rules.csv.
This is how dialog is scripted for Starsector. Yes, a giant spreadsheet. Click the image to view at full, glorious size!
You might think this is a horrible way to visualize dialog, but to me it’s like the Matrix. All I see is dialog hub, response conditions, setting memory flags… or, er. You know.
But it really does give me all the information I need at a glance, and once you get used to the workflow it can be very fast to implement new and complicated structures. Much more than, for instance, some kind of node graph. (Which is my argument against visual programming as well. It’s neato, probably good to learn with, but to me it feels inefficient when I don’t see what the code is actually doing.)
In the above, for example, there’s normal text which fires when the player goes to talk to Cavin. But before it properly starts, there is a condition that fires off a small dialog with Finlay Siyavong, the intelligence officer spying on Cavin, if you’ve done certain actions when talking to the previous Coureuse associates. This aside returns to the main flow of the conversation once it’s complete, and will enable a new dialog option with Cavin wherein you tell him that he’s being spied on.
Deep breath, standing back. We do all of that for everything.
And we’ve got a good lot more of it to do before the end. I said I wouldn’t say anything about upcoming narrative, so I won’t. But I have more and more fun with the dialog scripting every time I make a new piece of content (like that new thing in the 0.95.1 release; you know the one) and it’s super rewarding to see people experience it.
Hope you enjoyed a look into the design and writing process of Starsector!
Comment thread here.