So! Here you are. You're almost done making an enormous adventure game full of dialogue and descriptions. It's finally time to hand your writing off to an editor, then translators, then voice actors!
...Sorry, what's that? You say that all your game's text is scattered across the code?
It'll take you literally months just to siphon it into legible documents?
You're applying all revisions, translations, etc. by hand?
You're worried you'll miss a few spots?
Repetitive strain injuries?
Oh my!
Introducing... "Resistance"
That's the kind of doomsday scenario I want to avoid in my games. So one day I thought, why not just design that possibility away? I looked into my options and decided I should make my own system from scratch. I'll walk you through how it went.
To start, imagine a gamedev-adjacent person sitting down at a workspace to interact with a video game's text. What types of workflows could they be immersed in?
This is all I could come up with:
- Writing/Editing
- Localizing/Translating
- Voice Acting
- Integrating into the Game
Can you think of any other operating modes? No seriously, I'm probably missing something.
For me it's crucial to frame my engineering in terms of RESISTANCE. In this case, we'd want certain tasks to be easy or automatic (lower resistance), while others we'd make difficult or impossible (higher resistance).
Within those four workflows above, what specific types of tasks would you wish were easy or hard?
| The opposite of "resistance" is "flow", but "flow" could also mean "flow state", so I flow toward "resistance" as I'm resistant to "flow". |
Let's take Translating as an example. It should be...
1.) easy for the translator to understand the context surrounding each line, and...
2.) difficult for that person to accidentally skip translating a line.
Pause! With those two goals alone, is a possible User Interface already forming in your head?
And so on. Now, what happens if a major plot hole is discovered... after the story was already translated?
Oof, well, send your corrected text off to be re-translated... Ok, again with a few more fixes... Now it's been a few months. Wait, did we hear back from everyone? Which localizations were updated?
Ideally, we'd just know! It should be (nearly) impossible for the dev team to be unaware of any mismatches between languages.
Anyway I played around with this framing of resistance in these workflows for a while, thinking about all the specific tasks people would have to do, despite having never done most of them myself...
And here's what I-
BUT FIRST
My system needs a good name! :D
From a thesaurus: Plot, Story, Dialogue, Script, Manuscript, Log, Book, Lines, Episode, Moment, Lexicon, Tome, Codex, Scroll, Event...
Some of these are promising. "Yo, look at this moment file." Slick.
But then I found the clear winner:
LORE.
It fits everything! Dialogue, stories, history, information... It's perfect. It's like the game we are making will someday be an ancient artifact set in stone, as if every file begins with, "Let it be known that in the year 20XX..." "...saving the game was called 'Save Game'."
So there it is. NetMission Lore or NMLore or just Lore files. For a while I've used *.nmlore extensions, but sometimes I use *.txt since that's easier to share with others. Doesn't matter.
(Future editing note: NME's users, including Team SCU, have been using this name since January 2025. "Lore" terms can be found inside all published *.exe files since then. Another organization announced a game-related product called Lore in June 2026. I do not wish to create, nor do I anticipate, any confusion between these two Lores.)
Back on Track
Anyway, here's the amazing system I came up with!
First, you just type into a plain-text file on your computer. Type whatever you want!
Hello, World!
This is some text.
Blah blah blah.
Then attach this file to a game object, like a Sign Post.
As a result, that game object can now access our message with a single function: readLore().That's it!
...
Oh, you expected more?
Fancy Schmancy
There's more of course, but hold your horses.
Sure, instead of plain text, I could have built a UI tool. An advanced all-in-one story management suite with internal schemas and external integrations.
The thing is, that's risky. Every single task might start out impossible until I eventually add the corresponding features someday. That seems like a curse.
Meanwhile in the dead-simple system I proposed above, everything is already possible in theory, even if extremely frustrating. After all, games are free to process text on their own using code! Same goes for any external software managing these files.
Therefore our focus can be on making desired tasks easier from this paltry starting point. What would be best for the workflows?
I really want you to be able to feeeel the resistance. Where is it? Which steps irk you? What have you been avoiding in life? Why??
Who's Asking?
Many games will want to know who is saying each line. Let's allow optional tags like so:
Monster: Hello, I want to pass.
Wizard: You don't have permission to pass.
To support these tags, as the game code extracts our Lore line by line, the engine conveniently provides both fields to use at each step: speaker ("Monster") and text ("Hello, I want to pass.").
There are storage and performance benefits to handling this common pattern directly in the narrative format. It also encourages conformity across games and saves developers some effort.
Congrats! We've successfully lowered those forms of resistance.
Caution
And yet, with that simple feature we've already added new resistance. Check this out. One day, we place a new Sign Post with helpful directions:
North: The Deep Mines
South: The Community College
The player approaches it and... whoops. The game has no idea who these "North" and "South" characters are. That's right, we've introduced unexpected colon interference. (Gross!)
![]() |
| You... shall not... pass... that stool. |
Luckily, there's a traditional workaround you might already know, involving this symbol: \. In common practice, that slash creates a special "escape" for whatever immediately follows. So, North\: The Deep Mines indicates that our colon is just a colon, not meant to be speaking. (Silent but deadly?)
Still, these nuanced concepts increase the workload, as people must implement, debug, document, discover, learn, and think about them. And for any games that don't use dialogue this way, all of this becomes bloat.
In the end... is this feature worth it? I said yes for NMLore, but it's honestly a fair question!
![]() |
| Bonus question: Should I allow spaces in the speaker names? There's arguably a correct answer. |
As you can see, resistance may involve a mess of competing layers. Sometimes you can improve a design by simply patching out one pain point at a time, but if that's all you do you might be missing the bigger picture. That's why I originally imagined many workflows together.
Okay, enough spinning in circles. Here's what actually sets NetMission Lore apart:
Localization
This is an approach I haven't seen before. To translate a Lore file to a new language, copy that file somewhere the engine can recognize, then insert the new target language using >>> markers like this:
That's when she realized something important.
>>> Fue entonces cuando se dio cuenta de algo importante.
The library is in the city.
>>> La biblioteca está en la ciudad.
It's not much, but... there's one detail in this design that's incredibly important: the continued existence of the source language.
"Hold on, Troid. Doesn't that mean you're duplicating the exact same data across all these different language files? That feels wrong."
True, there are concerns. For one, I'm relying on the fact that text data is relatively small, usually less than 1MB uncompressed for a full novel.
"No, what I mean is if you edit the original text in any file, the other files won't match anymore. It's sloppy and bug-prone. In your own terms, it's highly resistant to change!"
Ah, but high resistance isn't necessarily bad! Do you remember that hypothetical scenario where we struggled to keep track of which languages were updated? Well, by comparing files, NetMission will now alert us with exactly which spots are out-of-date! Manually dealing with each one... is a good policy to enforce here! Granted, there's additional nuance in making sure the alert doesn't incentivize the wrong workarounds in the heat of the moment, but hopefully you get the idea.
As a nice bonus, with the context all there, you'll never have to open multiple documents side-by-side to see the before-and-after.
![]() |
| The library is in the city. |
There's one more localization feature worth sharing: you can use [[[ and ]]] to group lines together.
[[[
That's when she realized something important.
The library is in the city.
]]] >>> [[[
Aquí hay una frase extra para aclarar que el sujeto es la mujer.
En fin, fue entonces cuando se dio cuenta de algo importante.
La biblioteca está en la ciudad.
]]]
This lets the localization team completely upend and reorder the entire scene, if that's what it takes to convey the equivalent meaning. Language and culture are so uniquely expressive that I want to avoid artificial limitations, like forcing strict sentence-to-sentence pairings.
As a final note, if translating directly with plain-text symbols like that would be too cumbersome or prohibitive, there's nothing stopping someone from building a GUI over this format to keep it clean on your screen.
In fact, I don't see why you couldn't apply a similar localization method on top of any other plain-text story/narration format! Even as a basic preprocessor layer, this particular balance of resistance levels should shine through.
Then again... I've never actually coordinated game localization before. Forgive me if this approach is already a standard, or if there's a glaring design flaw that will bite me once I cross that bridge.
Do I Have a Choice?
Another unique bit about NMLore...
Each story/narration format I've encountered allows the writer to display a menu to the player, such as a list of available conversations. These options directly shape the format's syntax and runtime, potentially spiraling into more and more advanced features to support every exceptional situation...
Well in NetMission Engine, I said no to all that!
To me, menus just seem too specialized toward specific genres to be worth all the built-in overhead. They almost force games to be ready for that scenario at any moment, even when it wouldn't make sense! If an NME game wants that, it can provide its own functions, such as this one I made up called showChoice():
Troid92: Are you still reading this blog post?
{choice = showChoice("Yes","No")}
#if {choice == "Yes"}
Troid92: That's awesome!
#else
Troid92: Are you sure?
#end
Yeah, it's bulkier than native choice syntax. But it's also very freeing. Maybe I'll change my mind on this down the road.
(If you're curious, I took the same scripting language that powers NME's games (Lua) and enabled it inside Lore, too, but in a "sandboxed" way that lets the game kinda become its own engine within NME. For Lua nerds, the reader object returned by readLore() is conveniently its own Lore environment, and this system is coroutine-friendly, meaning showChoice() could play animations and wait for the player to push a button before proceeding.)
Final Score!
There's not much else worth mentioning. NMLore has standard features one might expect, like "chapters" and "jumping" and voiceover hooks. Here's the quick rundown of how it all turned out:
- Made in my spare time in January 2025: 1 wk designing, 1 wk implementing, 1 wk debugging.
- Tried to keep memory allocations low-ish (it's basically 1 per Lore file at load time).
- NME "bakes" Lore into an optimized runtime format (e.g. custom bytecode, de-duplicated strings).
- In total adds 0.016MB to the final exe, plus 0.044MB to the developer exe for "baking".
- Lore became an essential part of gamedev in NME. Even level-building got easier from it!
- I don't use AI, if that's relevant to mention.
It'd be nice to share my Lore system with the world, but that'd be difficult. It leverages NME's existing (private) infrastructure such that there's no clear boundary line. Plus I'm still tinkering with the syntax now and then.
On the bright side, it wasn't exactly a large endeavor. I've spent at least 10x as many hours making this write-up & artwork than I ever spent on the corresponding code! So this is my way of sharing it.
If you're itching to get ahold of NMLore, instead try out the many delightful narrative formats I listed previously. Alternatively, it's a pretty fun challenge to build your own, molding it into precisely what would help your creative expression the most! No cheating.
A final note on the concept of resistance... I've really only scratched the surface here. Resistance can shift paradigms far beyond the scope of programming, and it's become my core engineering ethos from micro to macro. Sadly there's a hands-on nature to it that I may never be able to truly convey through words. I'll keep trying!
For now, take whatever bits you can from this write-up and go finish something cool.
~ Troid92
P.S. At least I'm no longer calling it the "Musty Smell"! That's a story for another day. Settled on the name "Resistance" back in July 2020.






