Adventure Simulator
Adventure Simulator1 is an open source browser game using novel technologies to revive the golden age of pseudo-MMOs.
A web-first pseudo-MMO
The mid-2000s yielded a number of highly successful "pseudo-MMO" browser games, like Neopets and Club Penguin,2 whose markets have since been captured by mobile apps and native desktop games. However, new technologies like Wasm, WebGPU, and Datastar allow us to make a new kind of browser game, one with near-feature and performance parity with native applications: a kind of game that has been impossible to build until very recently.
Bulletin-board world
A traditional MMO uses a central server to maintain the live state of the game world, run simulation logic in real time, and push state updates to clients dozens of times per second. Designing and implementing this server presents a host of complex networking challenges; building a backend that can handle massive concurrency, synchronize thousands of players in real time, ensure consistency so everyone sees the same world, and maintain low latency isn't a lot of fun, which is why most people don't make traditional MMOs.
We aren't making a traditional MMO either. Our plan is to sidestep these challenges altogether by representing our world, not as a continuous simulation on a server, but as a bulletin board.3 A database contains information about players, places, and quests, and players interact with this world-database by taking discrete actions through an asynchronous, hypertext (web-style) interface. Unlike an MMO's world-server, a bulletin board database has no active connections to maintain; as soon as it responds to your request, it forgets you exist. When players do need real-time action, e.g. when they engage enemies in combat, we create a private virtual server just for their party, though as any real-time networking can quickly become dangerously complex, we intend to keep as much state as possible on the server, using server-sent events to push updates directly to the client as events happen.4
Player characters spend their downtime in settlements, which are persistent, bulletin board-like social hubs where they can purchase equipment, join parties, and embark on quests. When their party sets out on a quest, players load into a real-time, WebGPU-rendered combat simulation when they arrive their destination or are randomly attacked along the way; when the real-time simulation is no longer required, players transition back into the discrete hypertext format.
This is all to say that we aren't building a "normal" web game that uses Wasm and WebGPU to run in the browser. We are building a hypertext bulletin-board game which can act like a normal game when needed, like in combat, and where most of the game logic isn't even running in the browser but rather streamed, via Datastar, from the server.
Gameplay
The nearest games for inspiration are Mount and Blade, Battle Brothers, Jagged Alliance, Starsector, and to some extent Kenshi.
Like the former three, the world of Adventure Simulator is separated between the "tactical" layer (a real-time simulation) and the "strategic" layer (which advances in discrete chunks of time, generally after fast travel or resting). We have the same basic gameplay formula where the player recruits a party to adventure with, defeats enemies in randomly generated missions, and uses their hard-earned rewards to buy equipment for future missions.
Like in Kenshi, Battle Brothers, and Jagged Alliance, players can control multiple characters, though in Adventure Simulator, characters can be either mortal or immortal. Mortal characters offer a more roguelike/"extraction" experience, with fast progression and frequent deaths; when one of your mortal characters dies, any wealth not on their person will be inherited by your other characters. Immortal characters offer a more conventional RPG/MMO experience, which emulates the cost of mortal characters with costly respawns and slow healing.5
If there's any design choice in particular that makes our approach unique, it is specifically that we relinquish the vision of a continuous, immersive world. Kenshi clings to that vision, despite all the systems of the game going against it,6 and most MMOs try to reach that ideal before networking gets in the way. We take our inspiration from singleplayer games like Starsector, Jagged Alliance, and Mount and Blade which all chose to have a strategic layer, not because they had to for networking, but because their gameplay loop would be really boring without one. You can actually walk around cities in Warband and Bannerlord, but zero players actually do this outside of sieges because walking around is boring. Thus, we take those games' basic design and combine it with the one infamous problem it incidentally solves: MMO networking.
Setting
The world of Adventure Simulator is a historical fantasy version of Earth. Players of Warhammer Fantasy or readers of pre-Tolkien fantasy will be familiar with the concept: essentially, the setting is historical Renaissance Earth with generic fantasy elements inexplicably sprinkled throughout.
The heuristic for the fantasy elements is to put them in places that don't fundamentally alter historical conditions. Elves generally keep to forests or fictitious islands; Dwarves dwell within mountains; and creatures like Orcs, Goblins, Beastmen, and the Undead either roam as hordes or infest caves, crypts, and abandoned Dwarven settlements. To the extent that the kingdoms of Men interact with these fantastical elements, it is generally in hiring heroes to deal with the nuisances caused by hostile fantasy creatures. Elves and Dwarves are uninterested in Human political squabbles over borders and wars of succession, and fantastical enemies don't really pose a strategic threat to Human kingdoms, so the historical and fantastical elements of the setting can generally avoid stepping on each others' toes.
As for the historical elements, the year is approximately 1543 AD. Being both the height of Charles V's transatlantic empire and the year the first Europeans reached Japan, it is the earliest possible date in which all major cultures of the world are at least indirectly aware of each other.7 For the MVP, the playable section of Earth will be limited to Italy;8 in the long term, we will gradually expand to all of Europe and beyond.
Philosophy
Below are some guiding principles for Adventure Simulator development.
Open source software
We tentatively intend to keep everything GPLv3, but we're willing to hear out the case for other licenses.
It's clear to us that Adventure Simulator is very much the kind of project which will benefit from collaboration and indefinite iteration, which makes open source the obvious choice by a country mile. For instance, though our MVP for Adventure Simulator is (deliberately)9 generic historical fantasy, we don't intend or hope for it to stay that way. The project's open source nature will allow modders to come in and take it in all sorts of unexpected directions in the future; they may create total conversions to other fantasy settings, sci-fi settings, or... something else entirely.
Procedural assets
It should be easy for players to create content for the game, so to that end, we will use low-fidelity procedural assets to greatly reduce the barrier to entry. This doesn't mean that we don't care about fidelity at all; it means fidelity must necessarily come from procedural iteration rather than a trained CG artist's skill. The system Nintendo uses for Miis, for example, is a better example of how we might approach a character creator than, say, Baldur's Gate III. But that doesn't mean that we're going for an especially cartoony art style, either; there's nothing to prevent us applying a system like to more realistically proportioned characters (as Nintendo did, more or less, with Breath of the Wild and its sequel).
The same principle for graphics applies to audio. A good introduction to procedural audio may be found in Designing Sound by Andy Farnell.
Physically based gameplay
We would like the underlying gameplay systems to be realistic, as the real world can generally offer an unambiguous answer to any design question. It's not always easy to discover that answer, nor is it always easy to implement it without resorting to simplified abstractions,10 but all the imperfect solutions at least point in the same direction. Call this philosophy physically based gameplay, parallel to "physically based rendering" for graphics.11
The real world is not always as fun as a game ought to be. Fortunately, there are two ways to get around this:
Abstraction-based approach
We can abstract away the parts of the real world that are not particularly fun.
Holding W to walk 50 km between settlements is not particularly fun, nor is resting for several months to heal a serious injury, but if we put these activities in the "strategic layer" of the game (separate from the real-time "tactical layer"), a player can skip them by fast-forwarding in time. Likewise, micromanaging inventory is not particularly fun, but as the game becomes complex enough to necessitate it, we can also add tools to automate it, such as setting a desired weight limit and value/weight ratio for loot.
Content-based approach
We can design the non-real parts of the world to be more fun.
Being that this is a fantasy world, the fantastical elements are free variables for us to balance the game with. Suppose real-life combat is too fast for it to be viable to reliably dodge most attacks; we can simply give common fantasy enemies like Goblins, Orcs, and Skeletons such poor melee skills that an agile player character can reliably dodge them. Or suppose stealth is too frustrating with realistic detection ranges; we can just ensure that these fantasy creatures tend to have very poor eyesight.
Funding and legal
Adventure Simulator Group LLC is a for-profit company owned by Bruno Segovia (CEO) and Adler Halbe (Director). The founders are willing to invest serious portions of their incomes to see at least a prototype of this through. As they will be maintaining full-time employment throughout the development process, their contributions will largely be in the form of cash, but they will be available most days to provide guidance and strategic direction, primarily during evenings and weekends (PST).
Once the game works well enough to start hosting (and is sufficiently fun to be worth anyone's time), the founders will try and transition to a more sustainable funding model: one where players may have a single character per account for free but pay a subscription fee for multi-character accounts. This funding will be used to hire more developers, pay server costs, and hopefully obtain some profit.
Due to being open source, if at any time Adventure Simulator Group starts "enshittifying" the service, the community can simply fork it and host their own instance of the server. This hopefully will never happen, however, as the threat of it ought to suffice to keep everyone's incentives aligned. At face value, this is a terrible business decision (to willingly give up one's monopoly power), but the success of Patreon and Substack is evidence that relying on the goodwill of the community can be a genuinely viable business model, especially for an inherently creative product like a game. Will it actually work? We don't know. Let's find out!
Are you accepting investors?
Probably not. We want to be very selective about adding board members. However, if you think that you can make a good case, send an email to our CEO, Bruno Segovia.
Open (paid) positions
All positions are remote-only and with no Zoom meetings (unless you actually want them). Contact halbe@adventuresim.org to apply.
Having hired our first round of developers, we are not currently seeking applicants for any positions. We will likely initiate another developer hiring round in January. In the meantime, if you think you can contribute in some other way like writing or testing, send an email to halbe@adventuresim.org.
-
Working title. ↩
-
And actual MMOs, such as Runescape and AdventureQuest. ↩
-
You can think of a bulletin board as halfway between a Discord server and an Internet forum. Think of an imageboard: the threads are more live than reddit or forums, less live than chatrooms. The benefit of the format is that it works both synchronously and asynchronously; you can have a nearly live chat with a guy on /tg/, but the format also works even if you're the only live user on a given thread at that time. This isn't an unheard-of inspiration for a fantasy RPG; Dragon's Dogma's internal project name was "BBS-RPG" due to the "custom mercenary character" system. We would be taking the idea much further than DD did, of course. ↩
-
We end up rendering a sort of network-driven "immediate mode" view of the world. ↩
-
Mortal characters will probably be randomly generated by default. The idea is that players who prefer custom characters will naturally gravitate to the immortal option. ↩
-
Even at 4x speed, which most computers can barely handle simulating, you're still spending most of your time watching your characters travel or rest. ↩
-
Any later and your combat has too much "shot", not enough "pike." We briefly considered 1650 AD as it's a very dynamic and rich setting (the EIC under Cromwell's England and VOC of the Dutch Republic scramble to take East Asian colonies from Portugal and Spain as Russian explorers reach the Pacific and Japanese pirates roam the seas), but by that time, swords and pikes just aren't seeing enough use in combat for our purposes. Someone else should totally make that game, though. ↩
-
Renaissance Italy offers huge cultural and geographic diversity in a relatively small area: in just a few hundred square kilometers, you have bustling urban centers, Alpine mountain fortresses, rural farmland and villages, and ancient Roman ruins. With warring city-states and feuding families aplenty, Italy also offers the perfect economy for professional adventurers, and all the while, it is instantly recognizable even to non-historians (Leonardo da Vinci, Machiavelli, Medicis, etc.). ↩
-
Think of this as a high-effort tech demo in the spirit of Valve (cf. Half-Life). We really enjoy "weird fiction" like Morrowind and Dune, but at least for Adventure Simulator's first iteration, the goal is to innovate in tech, not aesthetic. For now, our aesthetic is what has been proven to work. ↩
-
Quantum physics is not in-scope for the MVP, to say the least. ↩
-
A game like Team Fortress 2, deliberately cartoony and unrealistic-looking, still employs "physically based rendering" in that its visuals are based on real-world lighting and material values, just tweaked and exaggerated to produce an unreal effect. The base values come from somewhere other than pure arbitrary imagination. Also known as "you need to know the rules in order to break them." ↩
Jeff arrives home after a long day at work and logs into Adventure Simulator. He selects his character, Geoffrey, and loads into the settlement that he last logged out from, Newport. From the settlement menu, he opens up the "quests" menu to pick out an adventure for the evening.
Planning
By default, it filters for quests whose party leaders are looking for members compatible with Geoffrey's build. In this case, a moderately armored, shielded, hammer-wielding man-at-arms. Party leaders can be as open or restrictive as they like with their filters, so some parties are specifically looking for hammerers, but others merely look for armored characters and aren't too picky about weapons.
He can see both the enemies that will likely be encountered in the quest as well as the rewards. One catches his eye, a quest to hunt down a pack of orcs that have been hunting in Puzzlewood, a forest under the protection of the elves. Jeff, being the kind of guy to name his character Geoffrey, has heard that elven characters are immortal and therefore better suited his playstyle. He doesn't want to have lots of mortal characters dying all the time and rolling new ones, and if he gets enough favor with the elves he'll be able to make his own. So he joins this quest.
Dylan sees that the last party member requested has joined, a hammer-wielding man-at-arms. This fills out an important gap in the party composition, as there is a chance that some of the orcs have crude heavy armor. Dylan's character, Derthert, is a huntsman whose shortbow is not well-suited to piercing armor. Likewise, the other party member, Jack, is more of an assassin. Perfectly capable of bypassing armor when catching an enemy unaware or staggered, but his dagger will have a difficult time staggering enemies on its own which leaves him vulnerable if he fails to get the drop on an armored orc.
Dylan had not quite finished planning out the journey by the time that Jeff joined. There is still the question of which path they want to take. They have three options. All begin by taking a barge up the river severn:
- Lydney - They can get off at Lydney and trek over an open field into the forest, but a griffin has been terrorizing travelers in the area. Griffins have exceptionally good eyesight and speed, making it difficult for even a fast and stealthy party to reliably avoid it, so this area will not be safe for weaker parties until a stronger party deals with it.
- River Wye - They can switch to a rowboat at Bulwark and row up the River Wye, but the treacherous with shallow water and steep cliffs. The entire party will have to be very mobile with light equipment and good upper body strength to navigate safely.
- Long way - They can journey on foot from Bulwark, entering the forest immediately and staying safe from the griffin. But this will make the journey take much longer, exposing them to the risk of being attacked by random packs of goblins or critters. It will also require either camping in the forest or exhausting themselves before they return to Bulwark. The party is poorly equipped to defend itself from a griffin, which would normally be fought with polearms, heavy crossbows, or firearms. Likewise, they would rather not take the long way, as such a small party with no watchdog will have an extended rest duration due to the need to keep watch. Geoffrey's armor and weapon/shield will make the climb more hazardous than it would be otherwise, but he has enough strength to make up for it. After agreeing on option 2, the party sets out.
Travel
The barge to Bulwark is uneventful, and once there, they stay the night and rent a rowboat in the morning. They then begin up the river.
Adventure Simulator, in its MVP form, does not have any sort of actual simulated boat mechanics. The boat exists entirely in the travel menu, simply checking their upper body strength versus the difficulty of the terrain as they travel. If they were to randomly encounter any enemies during the journey, they would be automatically beached at the nearest spot of land for the battle. Luckily, the party is not ambushed and makes it all the way to the center of the forest without incident.
Navigating Difficult Terrain
From here, they have to ascend some difficult terrain to exit the riverbank and enter the forest. The game loads from the travel screen to a simulation, as this is not a trivial encounter (and unlike the rapids, we can simulate it in the MVP). Geoffrey keeps his gauntlets and pauldrons in his backpack, as they would otherwise restrict his movement, and straps his shield to his backpack. Derthert, likewise, slings his bow around his shoulder. Jack, being both lightweight and strong, quickly scampers up the cliff with a rope and lowers it. Using the rope, Derthert and Geoffrey have no trouble climbing up, the penalty of their equipment offset by the ease of using the rope. The party leaves the rope behind, as they will use it to safely descend back to their boat on the journey back.
The Camp
Continuing their journey in the map screen, they eventually arrive at their destination: the reported location of the orc camp. They load back out of the map screen into the world. But when they arrive, the orcs are not there. The party must make a decision:
- Wait in ambush for the orcs when they return
- Attempt to track them, using Derthert's keen senses to spot recent tracks
The party decides to go with option 1, as the quest was more on the risky side than might be ideal for a party of their strength. The reported number of orcs is 3-5, and orcs are nearly on par with trained humans, so an ambush will put the odds in their favor.
They pick locations for the three of them, placing Geoffrey furthest from the camp due to his lack of stealth and Jack the closest, as his job will be to go in first and pick off as many as he can before being detected. Once in position, the party waits for their targets to arrive. This is done by choosing how long you would like to wait, at most, but will be interrupted if any enemies arrive before then.
Stealth
After a couple hours, the orcs show up with a freshly killed elk in tow. Five of them, to be exact, one of which is in armor. They fail to detect any of the party members due to their exceptionally poor hearing and vision, plus the fact that the party is stationary and in hiding places. The orcs begin to rest, leaving one awake on night watch.
A quiet kill requires a significant surplus of accuracy, as the target must die instantaneously and preferably in melee, allowing the assassin to cover its mouth and lay the body down gently. Derthert is certainly capable of instantly killing the orc on watch with a headshot, but there is a good chance that the others will wake. Thus, it falls upon Jack to take the initiative.
The orc on watch does not have any kind of complex patrol, so sneaking up on him requires only to keep the sound of one's footsteps light. Jack's equipment has no articulated metallic bits, therefore no noise penalties, and his legs have high agility, so he is able to approach silently, though he slows down as he nears his target.
There is a short window of reaction time that an enemy has to being surprised before they can make any sound, so it is not strictly necessary for Jack to kill the orc before he is perceived. Even an orc, with dull hearing, will hear the footsteps of a mere human (as opposed to an elf) immediately behind him. But by then, it will be too late, and Jack's dagger will be lodged in his heart. Sure enough, Jack attacks, and performs a near-silent takedown. Not completely silent, but not loud enough to wake anyone. He moves on to the next.
Orcs do not bother to take their armor off to sleep. Jack would like to eliminate the armored one, but it might not be a good idea. He would likely succeed in killing it, but its high amount of armor coverage translates to a lower surplus accuracy score and therefore a louder kill. Thus, the others will likely wake. He decides to save the armored orc for last and pick off the rest, or at least however many that he can.
Assassinating a sleeping orc is easier than an awake one, all else being equal, but there is a degree of unpredictability to any skill check. In the case of an attack its how accurate he places the cursor to the center of his target's hitbox, but for avoiding noise when moving around, its just random. Unfortunately for Jack, its the randomness that gets him. We don't actually simulate this level of detail, but ostensibly Jack kicked a rock while moving that awoke the nearest orc. Jack does not manage to close the distance and kill it before it begins to lose its flat-footed penalty, and by the time he does attack, he does not have enough surplus attack to perform a silent kill.
The scuffle wakes up the rest of the camp, and Derthert whistles as he nocks his first arrow, prompting Geoffrey to make his way there.
Combat
Derthert fires on the nearest unarmored orc to Jack. The orc, though aware that the camp is under attack, does not actually see Derthert and thus cannot dodge the attack, leaving it at the mercy of Derthert's accuracy. Against a mostly still, unarmored target from close range, there is more than enough surplus accuracy to instantly incapacitate it--the arrow landing right in its neck, leaving only two orcs remaining.
Outnumbered in melee, including against an armored enemy, Jack hoofs it in Geoffrey's direction, followed by the armored orc. The other unarmored orc grabs his shield and faces Derthert.
With a shield, the only way to reliably shoot an enemy is to get lucky with a leg shot or flank them, the latter of which is not currently available to Derthert. He makes a couple attempts, but eventually has to either draw his shortsword or flee. Not being an especially trained melee combatant, but having great endurance, Derthert opts for the latter, and will attempt to juke his way toward Jack and Geoffrey.
Meanwhile, Geoffrey and Jack catch up with one another, and the two prepare to meet the armored orc in melee. Jack is little threat to the orc on his own, but if Geoffrey can manage to stagger it or knock it down with his hammer, Jack will be able to finish him off. The two surround the orc, who at first charges at Jack, managing to dodge the orc's fairly inaccurate attacks with his superior agility.
Geoffrey in turn attacks the orc, and lands a decent glancing blow on its armor. This doesn't do any damage, but does cause some amount of unbalance which will both penalize its next attack and dodge. Ignoring Geoffrey, the orc continues on Jack, being that he is unarmored and unshielded.
Dodging, blocking, and armor are not roughly interchangeable in Adventure Simulator. Dodging is a much worse way to avoid most damage, its advantage is only that it allows you to travel light and is ideal against attacks that are so devastating that armor or block would do little against them anyway, such as the club of a giant ogre. Thus, despite Jack's superior agility, even a glancing blow from the orc's axe is enough to put him out of commission. And sure enough, he presses the dodge button a tenth of a second too late, the orc carving a small chunk of flesh out of his upper right arm.
Without bandaging, the wound will continue to bleed out, and even as it is right now his right arm is practically useless. But, on account of the orc once again ignoring Geoffrey, he is free to land another hit. This time square on the back, causing enough unbalance to stagger the orc. Jack follows up with a kick to the shins, enough to completely incapacitate the orc, toppling him to the ground. A prone character has a very, very low capacity to dodge attacks, but the orc is still fully armored and Jack's dagger-arm is out of commission. Even still, Geoffrey's surplus attack is basically maxed out. His weapon isn't precise, so it can't actually bypass full armor, but he is easily able to land a direct hit on the back of the orc's head.
Orcs are thick-skulled, in both the literal and figurative sense, so this isn't quite enough to knock it out. But he is now completely stunned, which allows Geoffrey the opportunity to restrain him while Jack picks up his dagger with his left hand and slides it through the orc's visor, finishing him off.
It is at this point that Derthert arrives, shielded orc in tow. The orc, seeing its dead captain beside Jack and Geoffrey, suffers a huge morale penalty and begins to flee. Derthert turns, drawing and releasing an arrow. Though not heavily armored like his captain, this orc does still have a chain shirt and helmet, meaning that Derthert will still need some decent surplus accuracy to hit a fleshy bit. Unfortunately he whiffs it and and the arrow hits the back, its damage entirely absorbed by the chainmail and though its force causes some unbalance, the orc is too far away for Geoffrey to exploit this.
After-Battle
Orcs, having very high strength, can easily outsprint most humans. But a hunt is often a function of endurance, not speed, especially when you're already wounded. The party can take their time tracking the orc, giving them the opportunity to bandage Jack and gather their packs before setting out to finish off their quarter.
Geoffrey has a little bit of the surgery skill (as most characters do), enough to apply a bandage and tourniquet. He staunches Jack's bleeding and splashes some alcohol on the wound for good measure.
As the party leaves the area and enters the travel screen, they see a summary of all the loot. The process of actually managing your inventory is largely automated, you define only a minimum weight/value ratio and how much total weight you're willing to carry. These parameters are used for your characters to automatically decide how much loot to take, prioritizing the lightest and most valuable loot first. But you can override this, in this case Geoffrey decides to bring the orc's latest kill, the elk, even though it will significantly encumber him. He's in no rush anyway, as Derthert still needs to track down the final orc.
Tracking
From the map, the party can see the lone orc's tracks quite vividly as it flees. Every party leaves behind tracks which are visible for a duration depending on the party's size and stealth versus the tracking party's track skill and eyesight. At this point, the party splits, with Jack and Geoffrey heading back to the cliffs by their boat and Derthert following the orc.
The orc doesn't get far before becoming exhausted. He is wounded, wearing chainmail, and does not have especially high endurance to begin with. Derthert engages several times, the first couple times he is detected and unable to ambush, retreating each time. But eventually he catches his prey unaware and loads back from the map screen into the simulated world. He lets off an opening arrow on the orc's shield arm, forcing it to drop its shield, then its leg, crippling its movement, and finally square in the neck. He collects his arrows, then returns to the map screen to regroup with Geoffrey and Jack at the cliffs.
When one party is in a simulation and the others are not, they cannot advance time on the map screen due to the potential desynchronization that would occur. Essentially, both sub-parties need to declare their intentions, then when they're both ready, time jumps forward until their next encounter. This is a fairly complicated edge case, though, and we can omit the ability to split the party for the MVP. They can also disband the party, but this would make them unable to regroup without first returning to a settlement. Jack and Geoffrey chit-chat during Derthert's encounter, then continue once he returns to the map.
Descent
The party rendezvous at the cliffs and must now figure out a way to get Jack down safely, as his injury will impose a significant penalty to climbing, even with the rope and the fact that he'll be descending. They settle on having him grab onto Geoffrey with his left arm, who is still able to make the climb check despite the significantly higher weight because he is now descending and has left most of his equipment at the top of the cliff. Geoffrey then climbs back up to pick up his equipment as well as Derthert's pack, and descends once more. Derthert then unties the rope and scampers down the cliff to join them.
The three adventurers return to their rowboat, one man short for the rowing, but will now be headed downstream which is much easier. They return to Bulwark safely, then take the next barge to Newport and collect their reward by turning in five right orc ears.
Aftermath
Jack, having been wounded, is entitled to a disproportionate share of the bounty and proceeds from the loot to compensate for his injury. They otherwise typically divvy it up according to how powerful each character is according to the favor required to create them. In this case, the characters are approximately equally powerful, so Derthert and Geoffrey take equal shares. But Geoffrey specifically wants favor with the elves, while Derthert and Jack are indifferent, so he agrees to receive all of the favor and little of the money. This gives him enough favor to create a custom elf character.
Jack convalesces for a couple weeks before his arm returns to normal, and can either play as another of his characters in the meantime or skip right through it, as time between player characters is not synchronized when they aren't in a party.
Derthert, having gained an appreciation of how difficult it can be to deal with even moderately armored targets with a shortbow, uses his money to buy an elven bow, which is something like a fantastical version of a compound bow that allows him to reliably penetrate chainmail with direct hits (though not plate).
This page outlines the heuristics by which this game should be designed and implemented. The details specified in all other pages can be freely changed as long as you believe that it better fits the considerations outlined here.
Concept
The goal of this game is to make you feel like an adventurer in a believable world.
- Make/pick a character
- Take a quest
- Gather a party
- Prepare for your journey
- Venture forth
- Encounter unexpected challenges
- Finish the job
- Return for your reward
- Repeat step 2 until you die, in which case repeat step 1. We may want some kind of progression between characters later on as well as the ability to create multiple characters and switch between them, leaving each other their estate upon death or something, but this is the basic idea. In the long term, we would love to have this become some large-scale world simulator in the vein of Dorf adventure mode or Mountain Blade, as well as large-scale networking features, but for now the scope will remain limited.
Right now, we aren't too concerned about making the content especially interesting. Only the features. So what content there is can be lazily procedurally generated. But when we establish a fun formula we will eventually either focus on making the procedural generation more interesting or creating tools for players to create their own content. We want there to be a blurry line between developers and players and harness the latent potential of the modding community by offering players/modders an open-source, consistently designed platform.
Design
Realistic With Caveats
The underlying game mechanics should always be implemented in a "realistic" manner, but when we encounter a realistic mechanic that isn't fun, we should either account for this in the content or abstract over it.
Content-based approach
Suppose we are implementing a stealth system and we find realistic eyesight to be unfun (like getting spotted 200ft away under moonlight). Instead of making humans worse at detecting, we simply contrive enemies with worse eyesight. Therefore orcs, goblins, skeletons, and the like have really bad eyesight for some reason. Conversely, we can also simply give the player supernatural stealth methods like magical invisibility or a chameleon cloak.
The goal here is that since the underlying game mechanics are physically based, we have a point of reference to balance the game off of (the real world). This allows different types of gameplay to co-exist. If you want to have a really realistic, punishing time, play as a normal human fighting normal humans. If you want something else, fight enemies that are more fantastical with a character that is more fantastical. This should also help avoid the scenario where developers realize that a gameplay system is poorly balanced, change it, then retroactively break all the old content designed with that poor balance in mind.
Abstraction-based approach
Suppose we are implementing travel in the overworld and we find realistic travel times / world scales to be unfun (holding W for 10 hours on a road to get to a rest stop). We should instead use the interface to skip over these segments, therefore a fast travel system. It would still actually simulate the travel in a realistic manner though, so you will need to have food and rest and all that.
What if micromanaging food is tedious?
Same solution, abstract it in the interface. I don't really care whether my character eats his grains or his jerky or his rice. I just want to know how many days worth of food he has, he can automatically eat it as he goes. When I go back to town, I just want to give him a food budget and he chooses whatever level of nutrition is suitable for it (like 10 days on a cheap budget means grains, 10 days on a luxurious budget means jerky).
The abstractions however should be fairly scalable. If you want to walk for 10 hours to your destination, you can. If you want to manually pull food out of your inventory and eat it, you can. The lowest level of abstraction should be very precise, down to the level of which hand you are holding something in or which pocket you put it in. We should start with the lowest level of abstraction then work our way up, therefore the first iteration of the game should be more of an immersive sim than adventure sim or RPG.
World and Lore
"Kirkland Signature"
When you go to Costco and buy Kirkland Signature peanuts, you do not get xtreme flavor blasted japapeno nacho-cheese chocolate-covered peanuts. You can get salted peanuts or unsalted. Maybe you will like the flavor-blasted peanuts more, but you know that the Kirkland Signature ones will at least be solid. Their brand represents that which is generic, but high-quality. These aren't Great Value (Walmart) peanuts, they're Kirkland Signature. That is to say, we will be making our world very generic, but it should still be high-quality. Think Tolkien, or a more toned-down version of Warhammer Fantasy.
Historical Fantasy
The world is Earth and the year is ~1543, but there are also inexplicable fantasy elements added everywhere. There's elves and goblins in the forests, dwarves and orcs in the mountains, and vampires and undead in the crypts. But the human kingdoms and empires are the same, only now King Henry VIII has dragons flying around his kingdom causing mayhem and he needs YOU, noble knight, to stop them!
In general though, the fantastical elements and historical elements should try to avoid stepping on each other's toes too much. The human kingdoms regard things like griffins and orcs as nuisances, best dealt with by hiring brave adventurers from ahistorical fantasy factions, not as existential threats of relevance to the historical record. Likewise, elves and wizards don't much care which duke is sqabbling over which patch of dirt, they have evil liches to slay and cults to root out.
Therefore, most of our "lore" is just actual history. For the fantasy stuff, there will certainly need to be actual lore written, but that can come later as the game becomes more fleshed out. Its not really necessary to understand the origin of the curse of vampirism in order to be an adventurer who goes on a procedurally generated quest to slay a vampire.
This sounds too generic...
In being a platform for players to create content, eventually we imagine people might use it to make interesting, bizarre worlds. The core gameplay systems that enable this generic fantasy game should also basically work the same in a modern world of firearms and computers or a sci-fi world of spaceships and energy weapons. An AR15 is a very accurate arquebus that fires and reloads extremely quickly. A plasma rifle is an AR15 whose projectiles explode and melt through armor. A car is a faster horse, kind-of. A spaceship is a car that moves in three dimensions. There will of course need to be a lot of work done to support these systems, but in being open-source we hope that someone who would otherwise make their own sci-fi game from scratch might find it easier to extend ours to support it. But all of this is way, way down the line. For now we are making a generic fantasy adventure simulator.
Minimum Viable Product
These features demonstrate everything needed for the basic gameplay loop. It won't necessarily be a very fun game at this point, but gives an idea of the potential once each of these barebones systems are fleshed out more.
- A dude can fight another dude in standing melee combat
- Prone/supine controls, can be knocked down and get back up
- Can pick up and fight with different types of melee weapons
- Ranged combat (server authoritative, no rollback)
- Advanced movement (climbing, sliding on sloped surfaces, navigating hazardous terrain like fording a river)
- Stats system (attributes, skills, track damage to different body parts)
- Slot system
- Empty world from 1500s geological data
- Populate world with settlements extrapolated from population data (settlements are just a coordinate, name, and population level for now)
- Generic humanoid enemy types like orcs, goblins, and bandits
- Travel system with random hostile encounters
- Randomly generated quests (see: Battle Brothers for good templates)
- Rest system for health recovery
- Inventory management (loot/buy/sell items)
- Food/water/sleep system
Polished Product
With these features, the game becomes something that we can imagine players actually wanting to pay for. A fun, unique product rather than a mere tech demo.
- Procedural modeling plugin
- In-game editor for procedural models - design your own clothes or equipment
- Urban levels (houses, castles, etc and quests that involve them like thievery or assassination)
- Improved stealth detection AI (investigate noises, raise alarms, patrol routes?)
- Level editor - design your own house
- PVP
- More humanoid enemy types: beastmen, undead, ogres, and trolls
- Non-humanoid enemy types like wolves or giant spiders
- More detailed downtime (pick a job to earn a wage at)
- Elves and the immortal character system
- Also need to make settlements and assets for them
- Character creator
Simulation
Not required for the basic gameplay loop or polish, but increase the verisimilitude of the world and create opportunities for emergent storytelling.
- Settlement prosperity that is based on population and reduced by unsolved quests (see: Battle Brothers)
- Prosperity affects what items can be bought and how expensive services are
- Disease system
- Marry other characters and have children (Mount and Blade II: Bannerlord has a barebones implementation of this)
- Celebrations like holidays and birthdays - invite friends to hang out at your house
- Werewolf/Mafia/SS13/Among Us-style quests where your job is to infiltrate and do something nefarious at a rival's celebration
Not in roadmap but could be
These are all neat but aren't required for the game to feel complete. However, if someone on the team is very passionate about one of them then we can prioritize it.
- Magic system, implement on a per-element basis in order of whatever is easiest
- Wind magic is probably the easiest, just force fields in Avian that also cause unbalance. Will look much cooler with dust/leaf particles.
- Light seems fairly easy, as long as its just for illumination and some kind of blinding effect
- Shadow would be invisibility, especially in darkness
- A simple version of earth can be just causing tremors that stagger enemies (as opposed to something more complicated like fissures)
- Fire requires its own system for fire spreading and temperature
- Frost would use the opposite side of the same temperature system
- Nature to summon the assistance of wild animals in combat sounds easy, but not anything involving plants
- Lightning seems very complicated to do well (Circuits? Nope.)
- Water seems nightmarishly complicated to do well (Fluid simulation? Fuck no.)
- Become a vampire/necromancer/lich
- Changes the way a lot of systems for your character work, like food, water, sleep, exhaustion, and health
- Become biologically immortal, but still permanently killable unlike an Elf
- Don't need the game to give you quests, every night of feeding/graverobbing is essentially a self-driven quest
- Game generates PVP quests for other players to destroy you as your infamy increases
- Player-run factions
- Basically a faction board/groupchat + shared asset ownership with quests to antagonize rival factions
- Factions can manage a settlement as the mayor/governor/etc
- Would be like being moderators on a forum, plausibly a semi-democratic election for settlements in Northern Italy. Players in other settlements would need to depose bad mayors by force or get invaded
- Cultists and demons
- See: Space Station 13
- Due to the bulletin board social nature of the game, this seems like it might be a significant source of memes.
- Probably the best "outlet" for players with... "indecent" inclinations...
- If we let players customize characters and their outfits, they are going to make ridiculous coomer characters. Moderating this will be an uphill battle.
- We can just own it and tell them do whatever they like within their secret cults, and if they expose their degeneracy to anyone else who reports them then the player-run witch hunter/holy paladin faction will be given quests and empowered to come and purge them unannounced during their sex parties
- Dwarven settlements and assets
- Option of using the underway to travel in addition to the overworld and sea. Much faster through difficult terrain, but also much more dangerous
- Mounts and mounted combat
- Basically when you are charging and are holding the attack button, it can be automatically made against any enemy that comes within reach
- Horse can trample over smaller enemies
- Very high morale effect causes most weaker enemies to route instead of hold their ground
- Huge monsters that require a more detailed combat system
- Dragon, cyclops, giant, griffin, cockatrice, chimera, etc
- Dragon's Dogma does a great job of this... but it looks insanely hard to implement well
- You can climb onto enemies to attack weak points
- Detailed hitboxes for all the different body parts
- Lots of variety in the attack animations
- Total Warhammer does a workable job of this that looks much easier to implement
- They're fast, very tanky, and have sweeping attacks, but their size makes them vulnerable
- Poke them with polearms while ranged units shoot overhead
- Alternatively, anti-large hero characters are good at dueling them due to being able to reliably dodge their big, telegraphed attacks
- Flying units just magically float, their animations give the illusion of more detailed physics
- When their huge attacks send characters flying, they aren't real full-body colliders and ragdoll physics, everyone is still a capsule and the animations give the illusion of detailed physics.
- Poisons, potions, alchemy, herbalism, and gardening
- "We want the Stardew Valley audience"
- Settlements outside of Italy
- Assets between European countries are easy to share, need some kind of set of language skills that give you severe trade penalties when no one in your party speaks the local language
- Can retroactively apply this to communication with Elves/Dwarves
- Arabia, Africa, the East, and the New World need lots of unique assets, don't bother until Europe is very fleshed out (maybe modders will do this?)
- Assets between European countries are easy to share, need some kind of set of language skills that give you severe trade penalties when no one in your party speaks the local language
Organization
Strategic Layer
The "strategic layer" is the layer of the game which essentially exists at the map- level. It is asynchronous and facilitated by a HATEOAS HTML interface (generated via maud). It is essentially akin to the map/travel screens of Mount and Blade, Battle Brothers, or Starsector, where the party fast-travels from location to location and interacts with services in settlements via menus.
It is in this layer that you create characters, embark on quests, recover health, and manage inventory. Time does not advance continuously for each client, it advances in discrete chunks whenever the party leader interacts with the server. For the MVP, there is not actually a visible map client-side, quests just tell you how long the server calculates it will take to get there and what hazards you will/might encounter along the way. Later we can implement a webgpu-rendered map layer and float HTML elements on top of it like Google Maps.
Further details about the implementation are described in the networking page
Halbe: My assumption is that the underlying database for this is Postgres and the server is Rocket, but I am a web developer, and to a hammer every problem is a nail. I can vaguely conceive of an unusual configuration Bevy with an HTTP plugin that is essentially running on an event-based schedule which could sort of be made to act like Rocket+SQL, but I have no idea if this would be a good idea. It would presumably only be something that we'd do for consistency with the tactical layer.
Tactical Layer
When the party enters combat, approaches enemies in stealth, or must navigate dangerous terrain, the strategic layer composes a scene and passes it to the WASM binary of the "tactical layer". This is a real-time simulation in Bevy implemented by a generalist game programmer. Since UDP is not available on the web, the networking must be facilitated by websockets or data-star.
For at least the MVP, the simulation tactical layer is (tentatively) entirely done through the server, latency be damned. What we like about this is that it places an upper bound on how effective a cheater can be and it cleanly separates what clients are responsible for and what the server is responsible for. Clients handle input and rendering, server handles all the game logic. The felt-latency is mitigated by the fact that the animation system can eagerly act on input and that combat is mostly centered around weapons that attack more slowly than server latency. Only crossbows and firearms will necessarily have felt-latency to your inputs.
There is physics running on the tactical layer, but characters are just capsules since nothing about their animation state or model can be assumed on this layer.
Halbe: If the developer implementing this feels that rollback with more advanced physics is hardly more difficult to implement, or even easier, then they can make their case for it. I am skeptical though.
Once it concludes, the outcome of the tactical simulation is passed back to the strategic layer.
Client Layer
This exclusively exists on the client. The current state of the tactical layer is constantly received from the tactical layer server. The client layer has only two responsibilities, rendering the state of the tactical layer to the client, and passing input back to the server. Since combat is not dependent on animations, it is free to adjust the characters' animation state to immediately respond to inputs, and has a window of flexibility with things like the exact position of any character.
For example, when a character is standing still and the user gives a forward movement input, the model of their character can immediately begin moving forward, though slowly enough to start that after about a second their server-authoritative position will sync up with their actual position and their speed will increase to whatever it actually is.
Likewise, when the user starts an attack, their character can begin a wind-up animation while it waits until the server-authoritative time that their attack actually begins. If its an attack against another player, that player will receive the packet indicating that they are being attacked after the server-authoritative time, and will render a faster attack animation to catch up such that from the perspective of both clients and the server, the attack actually lands at the same time. When an attack begins, the server is saying "Character A will attack character B at time T".
There is only one way that the client-layer can affect what happens on the tactical layer: input. But input can be based on client-authoritative animation state in one narrow context: deciding the precision of an attack and what part of the enemy's body the player is trying to attack. Cheaters can report always having perfectly precise attacks with instant dodge/parry reaction times, which is fine, because they're still constrained by character stats.
Though not necessarily in the MVP, secondary physics can be implemented at this layer for things like animation physics or particle effects. Basically they have no effect on the tactical layer.
Model Layer
The actual models used for all client-rendered assets are procedurally generated client-side. They will not look very good, at least for the MVP, but essentially there is a plugin that takes all relevant information about a character or object and generates a model for it.
Though it is on the client, it can be thought of as a different layer since the developer implementing the client layer can know nothing about this other than adding the model-generating plugin to the client app.
Shared Library
There are two types of things which need to be shared between layers, components and functions.
Components
Shape
- For the MVP this is just Avian3d's collider component.
- Not all collider types would be supported for the MVP though
- Later on this will be a more fundamental component that allows for more complex shapes from which the Avian3d collider is generated.
StrataMap
- Describes everything you need to know about the material composition of an entity
- When combined with Shape (and Transform for scale), contains all of the information needed to compute all physics properties and generate the model.
- Simple placeholder version for MVP presumes that each entity only is made of one material
Functions
Some gameplay-related functions are shared between the strategic layer and the tactical layer. Generally, the tactical layer simulates combat so the programmer implementing it has the authority on how they work, but the strategic layer should be able to use these functions. For example to calculate how much reward a quest should give based on how powerful of a party it calculates would be needed to complete it. Or whether an enemy party should attempt to flee.
The developer of the tactical layer decides things like what attributes there are and gives some idea of what would constitute a "high" or "low" value, but the developer of the strategic layer is the one actually responsible for deciding what attributes a given character actually has.
Team
Adler Halbe (Director)
Can help greatly with the strategic layer (mainly frontend) and somewhat with the client-layer (mainly animation). Can also make placeholder assets in Blender and once an editor for the procedural mesher is created, can start making procedural assets.
Something of a jack-of-all-trades, so should be able to at least point you in the right direction when you're stuck, but also is only working part time due to having a day job (which is where your salary comes from).
Has been responsible for all of the design and documentation so far, but is not especially committed to the exact details of anything. Adler will only block changes to the design if he thinks it conflicts with the meta directives.
Bruno Segovia (CEO)
Will handle admin and also be writing a procedural audio plugin. The goal is that instead of recording tons of sound effects, we generate them by writing them as functions with parameters. So for example, the length, diameter, and amount of gunpowder are parameters in a function that produces the sound of a gunshot. In the case of collisions the plugin can play most audio automatically (given that each colliding object have most or all of the info needed for this in its physics components like collider shape or restitution). Until Bruno succeeds with this, stock effects (or silence) are sufficient, therefore its not a blocker.
Strategic-Layer Full-stack Developer
Implements the strategic-layer, needs some experience with HTMX and/or Alpine AJAX as well as whichever backend database the strategic layer uses.
Tactical+Client-Layer Game Programmer
Implements all of the tactical layer and a simple version of the client-layer (input, not necessarily animation).
Graphics programmer
Will be implementing a plugin for the model layer, to be used in the client layer. Should have experience with procedural modeling algorithms, specifically advancing front, and comfortable with geometry and linear algebra.
Strategic Servers
Responsibilities
The purpose of this server is to generate quests, handle trading, and serve as a register for parties. You must have a party to set out on a quest or travel to another settlement. These can be segregated per-settlement if network load demands it later down the line, or dynamically grouped into regions to balance load.
Scaling
Our network will facilitate the bare minimum of what can be considered a single-world MMO. The trick here to avoid the classic "ten thousand players suddenly decide to go to one location because a popular twitch streamer is there" problem is that the open world is not a real-time network, its structured more like a bulletin board.
When ten thousand people are "in" a city, it just means that ten thousand people are viewing a HTML page for that city and on the database, their official character location is that city. They interact with each other by making posts in the city, as if each character was a user on a forum.
HTMX or Data-star
To keep the interface very simple, we will do everything via HTTP and would prefer to handle all of our interaction in the strategic layer between the client and server with HTMX or Data-star. These two will be very similar at this layer, but the value of Data-star is that it might allow us to also use it with different plugins for the tactical layer.
Accounts
It is not strictly necessary to have users manually make accounts before they start playing. Essentially, visiting the website first checks to see if there's a cookie for an existing account that you can login with. If not, it can automatically create a new one. This is not necessarily the same cookie that actually stores credentials (which presumably expire), its just "Has an account existed on this client?". If it hasn't, create a new account automatically, if it has and the credentials expired, prompt to sign-in again. Accounts do not require emails, Oauth IDs, or any additional information. You simply have the option to add those later once you decide if you actually like the game. We might also prompt the user to do this the second time they load the website, and they can also do it themselves in the settings.
This will mean a ton of abandoned accounts from people (or bots) who visit the website then immediately leave. But the only thing that the server has to track are living characters and which account controls them. Since you can only make mortal characters by default and time advances regardless of whether or not you are actually playing, they will eventually be cleaned up.
There should also be no cost to inactive characters aside from storage and periodically checking whether they should have died of old age by now. Time does not actually advance until you log back in, at which point it advances all at once to 1 year behind the official time. If its actually a problem we can also just say that all characters only exist per-session (and for a day or so afterward) until you set up Oauth and warn players about this.
Tactical Servers
Every time characters encounter combat, stealth, or hazardous terrain they are provisioned a tactical server. A tactical server runs a headless version of the gameplay and all interactions are mediated through it, there are no peer-to-peer connections (for simplicity). The only gameplay-relevant events that originate from clients are input. Clients do not use a rollback system or anything to anticipate the future state of the server and process gameplay independently, they just have to wait for a ping roundtrip to see the effects of their inputs (for simplicity). This means that there would be a very noticeable amount of input lag, but the secondary animation system which exclusively runs client-side can mitigate this by beginning animations immediately and extending their duration. There is no PvP in the MVP, but we will eventually want to support it.
At the conclusion of a tactical simulation, the clients are referred back to the strategic server.
Websockets or Data-star
Websockets are the default choice for real-time communication on the web between the clients and server, but if we aren't trying to do rollback then it may be simpler to use Data-star. Data-star is built with server-authoritative applications in mind, but its unclear how friendly it will be to the secondary animation system since its goal is to eliminate client-side state.
Halbe: I proposed the idea on the Data-star Discord and the feedback is essentially that its certainly possible, and probably much simpler than doing actual rollback, but also much more complex than a purely server-driven state in which the client does nothing other than input and rendering. One of the devs said that he is working on a "Darkstar" plugin whose goals overlap with this, and that we'd essentially be reimplementing most of that, so it might be best to start with a purely server-driven approach then consider adding some client state for secondary animation later down the line.
PvE Combat
Network Rundown
- Attacking Client declares an attack and sends input to server.
- Server receives attack input and immediately decides what the enemy's reaction time is, informing all clients about the attack, whether it will actually hit, where it will hit, how much damage will it do, and when it will hit
- Attacking client updates animation to account for the expected outcome, other clients are able to begin the attack and dodge animations at the same time (but may choose to render an artificial reaction time on the dodge) You cannot cancel attacks, or at least if you can then it has to be done double pingtime before when it would canonically hit so that there's no need for rollback
PvP Melee Combat (not in MVP)
Cheating
If we aren't doing rollback (and therefore the client doesn't have to have a 1:1 mirror of the simulation) then we do not care about detecting or preventing cheating. Having a pro-gamer level reaction time is less of a factor in combat than having good stats, so there's an upper-limit on how much of a problem cheaters are.
Network Rundown
- Attacking Client declares an attack and sends input to server
- Server forwards attack to all clients, which includes a tentative speculation of whether it will actually hit, where it will hit, how much damage it will do, and when it will hit based on the assumption that the defender will either not attempt to dodge, or will not dodge quickly enough
- If it takes the defender longer than X milliseconds to respond then they'll receive a direct/critical hit anyways so past that point it doesn't matter if you even try to dodge, the other clients can just assume that you didn't
- Defender receives attack and may or may not respond with a dodge input in time
- (optional) Server forwards dodge response to all clients
- Clients receive dodge response and can now be certain of what will happen, updating their animations accordingly
PvP Ranged Combat
Option A: Similar to melee
Ranged combat can be treated similar to melee combat, where the duration of the attack is a function of both how long it takes to aim the weapon and how long it would take the projectile to reach its target. This should be good enough for bows, slings, and throwing weapons, which don't allow you to instantly loose a projectile (holding a bow drawn is exhausting) so its not that bad to say that pointing at an enemy and shooting is something that can plausibly take >0.3s. You cannot draw a bow first and keep the arrow held, then choose an enemy, and like with melee you either can't cancel attacks or can't cancel by the time that other clients believe that an arrow has been loosed. This will work poorly with crossbows and especially with firearms, both of which don't have to be loaded immediately before firing and the latter has projectile speeds that are too fast to work well here. They can still be functionally implemented though, as the attack duration just represents your character taking the time to aim at a particular enemy.
Option B: No dodging
To speed up ping duration, we don't assume that the defender can plausibly dodge ranged attacks (at least from loaded crossbows/firearms). Thus the outcome of the attack can be canonically decided as soon as the server receives it. This will sometimes be frustrating for players (though usually realistic), but it can be mitigated via luck.
Option C: Simulate projectile collision
Avoiding projectiles now has nothing to do with a defense calculation and is entirely simulated via physics. The accuracy of the projectile doesn't determine whether it will hit, but rather whether it will hit given that the defender does not adjust their movement trajectory or primary animation. This will make long-distance combat better, as otherwise projectiles will have to track characters that change their course if the server has decided that they will hit. But it is more complicated, and if we aren't doing rollback it will lead to scenarios where the primary and secondary animations are out of sync and a projectile which appears to hit actually misses or vice versa. Therefore this is not planned for the MVP.
Controls
This page only covers controls relating to movement, attacking, and blocking/dodging. Hotkeys are described on the slots page, and menus are described in their respective pages:
Much of this page is liable to change in the near future. We assume many of our developers will be interested in taking ownership and providing input on game design, which we strongly encourage. Thus, the goal of this page isn't really to describe the game's controls; the top priority is to provide a list of design goals and principles for the controls, mostly downstream of the principles laid out in the readme. After that, we provide a tentative proposal/outline for a control scheme which meets those goals.
Goals
In order of importance, we want controls which are unambiguous; comprehensive; immediate; convenient; and intuitive.1
Unambiguous
We are opposed to "context-sensitive actions" where the response to user input depends on the state of the game, particularly when the state is something continuous like your character's position or what you're looking at.

Certainly context-sensitive actions can make your controls "simpler" in the sense that you're using fewer buttons, but it'll also make them a lot more cumbersome than they have to be, and your player may end up quite surprised by what his character ends up doing in response to a given input. There are games with "simple" controls, enabled by context-sensitive actions, where no matter how much you play them, you can't perform these actions on instinct because you must always ensure the context is appropriate for them. That's not to mention anything with menus, which are worse for this on an entirely different level.
None of this for us! Space Station 13's controls are nowhere close to ideal, but what they have going for them is that once you get used to the controls, they're very good at becoming instinct: a quality very much worth replicating. Our contrarian view is that reliable beats simple every time.2
Comprehensive
You should be able to make your character do anything he or she could physically do which would be situationally advantageous.3
Immediate
In cases where a button does one thing if single-tapped but something else if double-tapped or held, some games will start an invisible timer after a first tap is registered, delaying the onset of the following animation until the player's intention is made clear (with a second tap/hold or lack thereof).
We will not be one of those games. It's a fair enough solution, but we want immediate feedback for the player, and we don't want any invisible timers to delay post-tap animation starts solely for the sake of single-/double-tap differentiation. Note this doesn't preclude all timers; we may certainly have two time-differentiated inputs which share the same starting animation. For instance, since jump and crouch animations begin the same way, it would be safe to use a hold or double-tap to differentiate the two.
Convenient
Buttons that you press often should be near your fingers. Buttons that you press often, like to grab an item, or need to be able to press immediately, like to dodge, should not use the same fingers as those needed to look and move.4
Intuitive
All else being equal, it'll be nice if the game's controls are intuitive and easy to learn, but this isn't a priority.
To the extent that the game's controls are complex, it'll be great if the complexity is optional, especially at the character level. Playing as an alchemist with a bandolier of different potions and doodads might require you to use more buttons than a naked barbarian with a big stick, and starter players may be encouraged to play characters more like the latter.
But ultimately, our contrarian view is that new players don't actually want "simple" controls; they want reliable controls. Insofar as that's true, following the previous guidelines should already get us where we want to be vis-à-vis accessibility.
Proposal
With our design goals established, we now suggest a tentative outline for the control scheme.
One feature we quite want in the game eventually is a split between direct and indirect controls. By default, the player has direct control of his character, and the game plays like an action game, but with a toggle, the player may relinquish control to an AI and direct it with RTS-like controls. You'd generally use this feature to navigate large, boring areas, to order around multiple characters, or simply because you don't like action games.
We posit control schemes for both modes below.
Direct controls
These are designed primarily for the first person, but we can add a third-person camera option after the MVP.
Halbe: I assume that first person is easier because with third-person cameras, you need to handle a lot of edge cases to avoid awkwardness in tight spaces or near thin obstacles like trees, not to mention smoothing out the motion or reconciling the shoulder offset when aiming. However, if I am mistaken in my assumptions, we should implement whichever is easier for the MVP.
| M+KB | Controller | Function | Notes |
|---|---|---|---|
| WASD | Left Stick | Movement. | |
| Mouse | Right Stick | Look. | |
| LMB | RT | Attack! | |
| Release SPACE | Full LT | Dodge or jump. |
|
| SHIFT | Partial LT | Crouch or duck. |
|
| CTRL | Left Stick Click | Prone–standing toggle. |
|
| Scroll | Right Stick Click | Aim. |
|
| MMB or RMB | LB or RB | Grab with left/right hand. |
|
This is somewhere between a real action game and an RPG wearing an action game's skin. We aren't actually simulating everything based on hitboxes and projectile trajectories, but we still want to use some of the player's mechanical skills, specifically accuracy and reaction time.5
- Precision is the value between 0 and 1 representing how close to the center of any of the target's hitboxes the player placed the aiming reticle. The exact formula for this number will have to come about through testing.
- Reflex is the value between 0 and 1 representing how quickly the defender pressed the dodge/parry button after the attack began. Like with precision, we aren't sure exactly how to derive this, but a value of 1.0 would correspond to pro gamer reaction time (0.1s) and ~0.75 would correspond to old person reaction time (0.25s).
- There is no need to "time" your input to correspond with when an attack will actually hit as is convention in most action games. As soon as an enemy begins its attack animation, you should press the button.
For CPU-controlled characters (NPCs or indirect mode), the server... usually... randomly samples these parameters from a normal distribution with some mean and variance of our choice.
Indirect controls
We may have some version of this concept in the MVP if only because much of the underlying behavior is shared with NPCs controlled by the server. You are essentially giving NPCs orders through the same system that the AI uses to give them orders.
The following outline gives an idea of how things might work when controlling an army with a recursive chain of command, but as we aren't actually doing any RTS stuff for the MVP, it's more here as a distant if (hopefully) attainable aspiration, or in case an implementer is a passionate RTS/RTT enthusiast. The recursive nature of the system means that the controls should still make sense for small parties or individuals.
| M+KB | Controller | Function | Notes |
|---|---|---|---|
| RMB | RT | Move to. | While in combat, characters automatically attack enemies in range, so moving to an enemy is just attacking it in melee. |
| LMB | RB | Select. |
|
CTRL+LMB/Group | LB+RB/Group | Select multiple. |
|
| MMB+Mouse | Left Stick | Rotate camera. | |
| WASD | Right Stick | Pan camera. | |
| Scroll | Hold Left Stick Click + Left Stick Up/Down | Adjust camera Y-level. | |
| SHIFT+LMB | Select everything between current selection and new selection. | ||
| SHIFT+RMB | LT+RT | Place waypoint. | |
| SPACE+RMB | LT+RB | Ping. | |
| LT+Left Stick Click | Swoop camera to selected character. |
Universal
These inputs would theoretically find use in both direct and indirect modes.
Halbe: I have not thought too hard about their mapping. They should be remapped so that the most commonly pressed buttons are the most convenient to move your finger to.
Bruno: It'll likely be the case that these inputs are unavailable when a grab or select button is held due to overlapping with slots. When you hold RB, X is a slot/group button representing a holster on your left hip; if you aren't holding RB, X can be used for one of the menu inputs below.
- Toggle inventory menu.
- Toggle logout/character menu.
- Toggle quest menu.
- Toggle rest menu.
- Toggle direct/indirect control.
- Skip time.
- In normal use, this toggles between real time and sim-time. When camped, it skips straight to the end of your rest. Either way, it's automatically interrupted if the party spots an enemy or encounters difficult terrain.
- In the strategic layer (GSG mode), you continue to see the map at a consistent speed. In the direct camera or tactical layer (RTS mode), we can display a cinematic montage of travel or night passing. Not in MVP.
-
Also, as a broad note, we would rather follow operating system conventions than video game conventions wherever we can, especially for menus and any RTS-like controls. Video game conventions are designed for people who've played a lot of video games; OS conventions are designed for people. ↩
-
By "every time", we mean it. We believe that given enough playtime, someone who's never played a game in his life would prefer a game with SS13-like unambiguous controls to a game with Hitman's. You can generally compare our view on mass appeal to that of Stanley Kubrick:
Kubrick likened the understanding of his films to popular music, in that whatever the background or intellect of the individual, a Beatles record, for instance, can be appreciated both by the Alabama truck driver and the young Cambridge intellectual, because their "emotions and subconscious are far more similar than their intellects". He believed that the subconscious emotional reaction experienced by audiences was far more powerful in the film medium than in any other traditional verbal form, and was one of the reasons why he often relied on long periods in his films without dialogue, placing emphasis on images and sound... When deciding on a subject for a film, there were many aspects that he looked for, and he always made films which would "appeal to every sort of viewer, whatever their expectation of film".
In short, contrary to popular belief, if you want to best appeal to the masses, you don't actually want to simplify things. 2001: A Space Odyssey is the highest-grossing film of 1968 in the United States and Canada. There's a Pareto frontier of artistic merit and mass appeal, on which sat Kubrick and the Beatles, and we're aiming right for it. ↩
-
That's an important caveat. There are situations where you might want to go prone, but dedicated yoga position buttons are not a priority. (This may sound like an argument for context-sensitive actions, and in some cases it may be; as stated above, our primary opposition is to continuous-state context-sensitive actions, which leaves things open for contexts depending on discrete states, say in yoga class vs. not in yoga class.) ↩
-
Thus, grabbing and dodging shouldn't use the thumbs on a controller. ↩
-
This is trivial to cheat, but since combat is still (largely) based on stats and (entirely) mediated by the server, it's not a huge deal. ↩
-
This is a bit awkward, but you shouldn't normally be skipping the chain of command anyway. ↩
Models
As a rule, we'll be keeping game assets as simple as possible. We want to make it easy for players to create content that fits with the art style; it's a barrier to entry if that style uses high-fidelity handmade assets.
Subject to that constraint, however, we want the game to look as good as possible, so the game will use procedural models: high-fidelity algorithmically created assets. In theory, an eight-year-old should be able to use our algorithms to make content that looks as good as the rest of the game.
Halbe's proposed algorithm for humanoids
Below we propose a method of generating a character mesh. By the fourth version, we have a humanoid body with muscle and flesh, and the tools we've used to get us there can give us clothing and armor with with little additional required functionality.
Mesh resolution
smooth_theta is a variable passed into the mesher which describes approximately the detail that it should be created at. We define it as:
The theta in radians between the surface normals of any two faces on an ostensibly round surface.
So, for example, a value of π / 8 implies that a cylinder ought to have 16 vertices in its rings.
The value of smooth_theta depends on how far away the mesh is from the camera, how large its bounding box is, and screen resolution. It should be set so that when looking at a sphere, it is difficult to see the flat polygonal edges of it against the background. This also means there is a dynamic LOD system: meshes are regenerated if the distance gets, say, close enough that the ideal smooth_theta is half the current value, or so far that it's twice the current value.
First version: collider-based
The simplest possible mesh for a character is one which conforms precisely to the shape of his bones' colliders.
Let's say each bone is a capsule. Traverse the skeletal hierarchy and generate a capsule mesh for each bone with the vertices all skinned to that bone.
Second version: distance fields and vertex weights
Next, in order to connect the bones, we convert their capsule meshes into 3D signed distance fields (SDFs). This affords two distinct advantages: it's easy to combine SDFs in a way that smooths out the joints, and for each point p on the surface, to estimate a given bone b's influence on p, we can just evaluate b's SDF (a real-valued function) on p; taking this "influence" estimate on each bone and point automatically gives us the skinning weights for all bone-on-point pairs.
With the 3D distance field capsule primitives giving us a function to place vertices onto, we now have the basis for constructive solid geometry. We place vertices and build triangles according to a modified version of advancing front.
Polar-space advancing front tree (rename to whatever you want)
Every vertex begins as a polar UV coordinate on a bone,
$$U,V\in[0,1]$$
with some arbitrary angle picked for the orientation of U = 0 (probably whatever places it at the back, assuming T-pose, like along the spine for the torso).
A bone is sort of between a capsule and a cylinder. V = 1 on a leaf bone (or V = 0 on the root bone) is always the center, like the apex of a capsule, and has no defined U. However, V = 1 on a bone which has another bone connected to its end has a defined U. There is essentially a V > 1 value due to the connection between the bones acting like a capsule, rather than a cylinder. You can think of this however you want, but essentially when two bones are 90 degrees from each other, the joint between them is still nice and spherical.
We begin at (0, 0) at the base of the pelvis and start constructing a triangle fan. The heuristic for placing vertices is based on the smooth_theta parameter, both for what V to place it at as well as what U. Once we have a fan, all of the vertices except for the apex are our advancing front.
There are two types of ways that the advancing front on a given bone handles connected bones. In the simple case, the other bone is a continuation of the shape of the current one. The relationship between the upper arm and forearm, or along spine bones, follows this pattern. In this case, the front seamlessly transitions between the bones using the pseudo-capsule method described above.
The second scenario is when you have bones that branch off of the current one. In this case, the front will essentially go around it by diverging at one of the vertices. The vertices in the gap created by this divergence are kept as a new, separate front which will be used later once the current bone or contiguous chain of bones has finished meshing (the mesher is depth-first). Eventually, the front will pass completely over the gap and the divergence will be restored, also creating a continuous ring for the new front to begin from, repeating the advancing front process.
When the front reaches the distal end of a bone with no more connected bones, it must place an apex vertex and connect the front to it with a triangle fan.
Because the front is advancing in UV space, not 3D space, an important optimization and simplification is available:
- The heuristic for placing vertices can forbid placing any vertex to the left of a neighbor to its left, in UV space, or to the right of its neighbor to the right.
- We assume that the hierarchy of bones is not self-intersecting.
- Because of this, in theory this can greatly speed up the algorithm since there's no need to test for intersections.
But what about the shoulder?
Many a plan to procedurally generate a skinned character mesh has been defeated by the most infamous of joints: the shoulder.
Essentially, our plan is to forget about trying to weight the shoulder correctly, or even do the topology correctly. Instead, after the mesh is generated (say, for example, in a T-pose), we apply an animation which lowers the arms, putting it in the worst-case scenario, but then calculate where each given vertex would be if it were placed on the surface again (as described above). Since these are distance fields, which combine in a smooth metaball-like fashion, the surface of the armpit will actually be quite a bit lower now as the arm and chest distance fields now nearly overlap.
There will no doubt need to be a lot of tweaking -- perhaps the armpit is now too low -- but this may just produce a mesh that looks more correct when the arms are down. Thus, we will save this as a morph target and animate it according to how much the upper arm bone is currently lowered. This can be done to every joint; even though none are quite as bad as the shoulder, none of them will have particularly good topology or thoughtful vertex weights1, so they may still benefit from the process.
Third version: heightmaps
This is the feature that enables characters, specifically body meshes, to actually look pretty realistic. As established, each bone has a UV semi-cylinder/semi-capsule space used for placing vertices. We can reuse this, not only as a universal space for textures, but also to apply a heightmap to the distance field which converts UV to 3D.
Each bone has a heightmap defined in its UV space. Though we've been treating bones as capsules up to this point, it is the heightmap which actually encodes the spherical curvature of the top of the head or tips of the fingers, i.e. it is the heightmap which gives a bone its "shape" and lets us stop treating it like a pure capsule. (However, it is still capsule-ish on connections between bones to avoid it looking jarring if they aren't perfectly aligned.) To actually produce these heightmaps, we can either bake them from a sculpt/scanned medical model or paint them with an in-game editor.
Halbe: I've experimented with both methods in Blender. They each work well enough.
Cruicially, we can also composite these heightmaps to produce many different character meshes. This has worked great in manual Blender experiments. Essentially, you can have a base heightmap representing a smooth, slender character, and you can add a bone layer, muscle layer, and fat layer on top of it. Each layer is both a mask for the layer below and additive with it, which makes for a pretty good approximation of how they're physically layered in the body.
Fourth version: face
We are under no illusion that a system as simple as this can handle geometry like ears, nose, eyes, etc. Even a sharp chin will be a little awkward to handle. For the face, we can just use a system similar to what Nintendo used for Miis (and reused for its recent Zelda games).

The simplest version of this doesn't even include separate meshes for the facial features; they're just textures that get overlaid onto the face.
Fifth version: clothing and armor
By now, we have a mesher with an unambiguous, universal coordinate system for the surface of the body (from the second version) and a way to encode height (from the third). We can use this same mesher to produce meshes for body-conforming equipment entirely through texture data.
The main thing we need to support this is an alpha mask which specifies where the clothing is and isn't. For instance, on a T-shirt, past (say) V = 0.3 on the upper arms, the value of this mask would go from 1 to 0. We could also use this to create holes in clothing, which the mesher would treat similarly to intersections between bones.
Once the outer surface of a clothing mesh is completed, we can use a solidify algorithm to turn it into a proper model.
Unlike in the third version, we probably wouldn't have the heightmap for clothing with respect to the surface of the skin -- otherwise, a baggy shirt on a ripped guy would have abs -- but rather with respect to a "convex-only version" of the base body mesh. That is, we would generate a version of the base body's heightmap where any concave surface is pushed outwards until it is no longer concave.
Armor is like clothing, except in the case of non-flexible material like metal plates, all vertices need to have 1.0 weight with a single bone regardless of their location. Without an extremely detailed physics simulation, this will mean lots of clipping, but this is acceptable.
-
All automated weighting techniques are mediocre, ours included. But in our approach, SDFs give us the ability to generate morph targets to refine the mediocrity. ↩
Slots
A slot is a physical location on your character's body which an item can be stored in, or attached to, for quick access via hotkey.
For example, the right hip can be a slot:
- If you have a belt on, you can place a sheath on your left hip with Q.
- If you have a sheath on your left hip, you can put a sword in it.
The goal is for slots to replace menus to access most of your inventory. Anything not inside a bag should be immediately accessible with a slot button. Slot buttons can overlap with other buttons because they only function as slot buttons when a grab button is held.
Keybindings
Ideally, the location of each slot button should correspond roughly to the slot's physical location. A button on the left should be used for a slot on the left side of the body, and we should attempt to group the buttons so that adjacent slots have adjacent buttons.
| M+KB | Controller | Slot |
|---|---|---|
| Q | X | Left belt. |
| E | Q | Right belt. |
| F | Y | Front belt. |
| X | A | Back belt. |
| Tab | Select | Left shoulder. |
| R | Start | Right shoulder. |
| 2 | ⇐ | Left pocket. |
| 3 | ⇒ | Right pocket. |
| 1 | ⇓⇐ | Back-left pocket. |
| 4 | ⇓⇒ | Back-right pocket. |
| T | ⇑ | Head. |
| ⇓ | Face? | |
| ` | ⇑⇐ | Left arm. |
| 5 | ⇑⇒ | Right arm. |
| Glasses? | ||
| Ears? | ||
| Z | ⇓⇓⇐ | Left foot. |
| C | ⇓⇓⇒ | Right foot. |
The controller doesn't have quite enough buttons to give every slot its own button. To get around this, we can assign certain slots to combinations of buttons; because slot inputs require the grab button be held to initiate them, and we don't execute any action until the grab button is released, no ambiguity is possible. (For instance, while holding the grab button, the face slot can be ⇑ and glasses can be ⇑⇑; only when we release the grab button does it actually perform the action.) This is also helpful for controllers that only support four D-pad directions; the diagonals can just be pressing two directions in either order. (That is, "down-left" can be "down and then left.")
In the map proposed above, we rely on button combinations for directly adjacent slots, which we imagine as lying on a navigable grid navigated by the D-pad.
Layers
Pressing a slot button once selects the outer layer of that slot. Pressing it again -- without releasing the grab button -- selects one layer deeper. For example, press Q once to draw your sword from your sheath, twice to remove the sheath itself, and three times to remove your belt.
Multi-slot items
Many items, generally clothing and armor, occupy multiple slots. A belt occupies all four belt slot buttons. It can be equipped and removed using any of these buttons.
Slot restrictions
Many items may only occupy specific slots. When such an item is held in your hand and you hold the corresponding grab button, all buttons not corresponding to those slots are unavailable.
GUI
The screen normally gives no indicator for what is in your slots or your hands. However, holding down any grab button brings up a "map" of your slots with a few properties:
- This map includes icons for each button and approximately corresponds to the keyboard/controller; the relative position of each slot should be based on the relative position of each button.
- When holding an item, any slot it may be placed in is white, and all others are grayed out; if your hand is empty, slots with items in them are white, and empty ones are greyed out.
- Each layer of item in a slot is visible in this interface. Layers for items that occupy multiple slots contiguously span all relevant slots.
Bags
Your entire inventory won't necessarily fit into the slot system, which is fine. The slot system is intended not to replace "standard inventory management" altogether but to make a significant subset of your inventory more manageable, that being the subset of items that you need readily accessible. If you don't need a given item readily accessible, you can put it in a bag.
A bag still occupies a slot, but it can hold multiple items. For example, a backpack is a bag which is slung over your shoulder(s).1 To access a bag's internal contents, you must grab the bag into one of your hands; when you are holding the bag, the grab button for the hand opposite the hand holding the bag is used to grab/place into it, and the hand holding the bag functions normally: if you simply press the associated grab button, you will drop the bag, and if you hold it and press a slot, you will place the bag in that slot.
Alternative controls
The goal of the slot system is to obviate the need for menus in inventory management, for the most part, and thereby simplify most aspects of inventory management. Following the philosophy laid out in the Controls page, it will likely be hard to learn but ultimately speed up gameplay for experienced users on account of its consistency and unambiguity.
If this is not the case, we can also try more of a middle ground with conventional systems. For instance, we could turn all slot buttons into hotkeys untethered to any physical locations on the body. Players would still place items onto these hotkeys to equip them, but it wouldn't matter which button they pressed. This would make layering and multi-slot buttons a mess, so clothing and armor would just have to be done through a normal inventory menu. Sheaths and holsters would be handled like clothing; players would have to equip them from a menu and be forbidden from hotkeying a weapon without having equipped a sheath to put it in.
-
In the real world, carrying a backpack on one shoulder can lead to strain, pain, and posture problems. It is always recommended to use both shoulder straps. ↩
State
There may be four layers to the state of a character:
- Their input/NPC AI (what action are they attempting to do?)
- What action are they actually doing? Let's call this "skeleton state".
- The forward/inverse kinematic animation playing
- Secondary animation (physics)
Input and NPC AI
When you press W, there is an input system that determines that you are trying to move forward. When an NPC has a goal to move to a position that is in front of it, it has a pathfinding system that tells it to move forward. Both of these set the same "skeleton state", which is a component that keeps track of the fact that this character is trying to move forward.
Skeleton State
The state of the skeleton tells you everything that you need to know about what a character is doing this frame. Are they moving? Attacking? Both? Grabbing an item? Staggered? Jumping? Being knocked down? This is the minimum information necessary to reproduce the current animation for your character, and thus is what would be synchronized over the network. From a client's perspective, it is not (necessarily) clear whether another character is an NPC or a player, at least were it not for the existence of voice/text chat, because the only thing your client sees is their skeleton state, not input or AI.
The skeleton state may also be more complicated than what the controls imply due to needing to include information like "which direction are they ducking in?" or "when in a combat stance, which side is currently facing the enemy?" (when you slash with a weapon, this switches since you take a single step).
Forward and Inverse Kinematics
There is a system which recieves the skeleton state and actually animates the bones. It may not actually be strictly necessary to run this on the server, its possible that only clients need to see this since the only thing that the location of your individual bones affects is your input precision. We may want to use this as a reference for producing these animations.
Halbe: There might also be a layer before this for an animation graph, if the person implementing this feels that such an abstraction would be helpful
Secondary Animation
Clients may also apply animations via joint motors to make them more realistic, as each bone can now have inertia which may be affected by movement or collisions with the environment or weapons. This is not in-scope for the MVP though.
Stylistic Principles
We want to try and keep animations realistic, in accordance with the meta-level heuristics that govern our decisionmaking for this project. This means, for example, that melee attack animations should generally be inspired by HEMA. In general this means that there is a lot less "leading" or "anticipation" to attacks than you typically see in action game or movie choreography, at least for professional characters. But beyond the MVP, we can make multiple animation sets for different skill levels of characters. Untrained characters like goblins, for example, can have lots of anticipation in their attacks which is what makes them relatively easy to dodge.
Due to the fact that this is an online game, we also have to account for the fact that animations will have different speeds depending on perspective. Since all networking will be mediated by the server, we want to be able to extend animations by the duration of a network round-trip so that they can start immediately when you press the button but end at the same time for all players. This is a pretty good excuse to add some otherwise unnecessary leading to the player character's animations, which may look better than simply slowing the attack animation down.
const LOWER_MUSCLE_MASS_PER_LEG_STRENGTH = 5
const WEIGHT_CAPACITY_PER_LOWER_MUSCLE_MASS = 30
# todo: should this be linear or nonlinear?
fn encumbrance_term(character):
average_leg_strength = (character.legs.left.strength + character.legs.right.strength) / 2
lower_muscle_mass = average_leg_strength * LOWER_MUSCLE_MASS_PER_LEG_STRENGTH
weight_capacity = WEIGHT_CAPACITY_PER_LOWER_MUSCLE_MASS * lower_muscle_mass
return 1 - ((player.calculate_body_weight() + player.equipment.calculate_weight()) / weight_capacity)
Energy is an abstraction representing approximately the maximum amount of calories can be used in a day. The lower it gets, the less effective you are, because your body is resorting to more difficult-to-extract energy sources (fat or protein instead of blood sugar, depleted glycogen reserves in muscles, etc). Additionally, your metabolism can only actually absorb so much nutrients in a given day, it takes time to digest food and extract nutrients from it.
The exact biological functions aren't really relevant to gameplay, but they are physical processes to base our equations on.
Points of reference
- A small, sedentary person uses ~1500 kcal/day
- An average male soldier marching all day uses ~6000 kcal/day
- An Olympic athlete in an endurance event can use as high as ~12000 kcal/day
- Calories metabolized by humans per-gram
- Fat: 9
- Protein: 4
- Uncooked starch: 2
- Cooked starch: 4
- Sugars: 4
- Cellulose: 0.2
- Alcohol: 7
Equations
Damage and recuperation are based on real values, but if you did this in basically any other RPG it would become extremely boring and punishing. However, in our case combat is designed around the assumption that players will reliably be able to avoid taking damage, either by dodging, blocking, or it being absorbed by armor, so this isn't a completely unreasonable target.
However, inevitably damage will occur, and to prevent this from being a fun-killer we must use the two approaches to skip the tedium:
Abstraction-based Approach
The first of which is that even if it takes a very long time to heal from injuries, we can simply skip ahead until your character is healed. This only works well when resting at settlements though. If your party is mid-quest and you take a serious injury, you're either going to have to call it off or fight with a handicap. Unless...
Content-based Approach
The other "approach" is to use the fantasy elements to circumvent this. For example, we can say that fey-blood provides supernatural healing for elves or create a reasonably cost-effective sort of rapid healing potion that only works on them, such that they might be able to recover from most non-critical wounds after a mere day of rest or so.
Why elves? Because they are the designated race for casual players who aren't looking for a hardcore survival experience.
Damage
Damage can be applied to each of the 7 body parts. Each body part has a health ranging from 1.0 to an unspecified negative value. At zero, the body part is unusable and its associated attributes are 0, and effectiveness degrades proportionally between 1.0 and 0.
Below zero, you aren't any less effective, per-se, but the body part can continue to be damaged which will increase the time it takes to be healed (or whether it even can be healed). The "unspecified negative value" is essentially the point at which the body part is so damaged that further damage doesn't really mean anything, as if the flesh were essentially ground beef or it were severed.
I believe the maximum amount of damage would be based on the mass or volume of flesh on the body part.
Healing
const ML_BLOOD_VOLUME_PER_KG_BODY_WEIGHT = 70
fn determine_max_blood(character):
character.max_blood = character.body_weight * ML_BLOOD_VOLUME_PER_KG_BODY_WEIGHT
const PERCENT_BLOOD_VOLUME_CAPACITY_RECOVERED_PER_DAY = 0.01
const SECONDS_PER_DAY = 86400
fn update_blood(character, dt):
unbandaged_damage = character.body_parts.iter().map(|p| p.damage - p.bandaged_damage - p.scarred_damage)
character.blood += dt * character.max_blood * PERCENT_BLOOD_VOLUME_CAPACITY_RECOVERED_PER_DAY / SECONDS_PER_DAY
character.blood -= dt * unbandaged_damage
fn update_scarred_damage:
// todo - gradually convert open wounds to scarred wounds
// also convert bandaged wounds to scarred wounds at faster rate(?)
fn bandage_wounds:
// todo - use surgery skill check to convert open wounds into bandaged wounds
const PERCENT_BLOOD_LOSS_UNCONSCIOUS = 0.3
fn update_blood_loss_poise_factor(character):
percentage_of_total_blood_volume = character.blood / character.max_blood
character.blood_loss_poise_factor = (1 - percentage_of_total_blood_volume) / PERCENT_BLOOD_LOSS_UNCONSCIOUS
- Broadly speaking, anything supernatural in the setting originates from collective belief
- People believe that the spirits of the dead coexist in the world alongside them.
- The "spirit world" is essentially just a separate layer of the world that generally maps 1:1 to it.
- Heaven is just being in the spirit world in good standing with God
- Hell is in poor standing
- Many spirits are in neutral standing (think: nature spirits, non-malicious pagan deities, fairies and such).
- You can't really go to or see into the spirit world, so from the player's perspective this is all very vague
- Magic is the intervention of spirits in the world of the living
- Its hard magic in the sense that there are different kinds of spirits with specific, knowable things that they can do and specific, knowable ways of communicating with them
- Its soft magic in the sense that communication with them is unreliable and since they are conscious entities, they are capricious and often unpredictable
- There is no "mana" or any explicit resource like that. How much they choose to help you is no different than how much an actual person might choose to help you, and their help may be conditional on what exactly you want their help for.
- The closest thing to "mana" or a measurement of how much magic power you have is essentially just the sum of how much various specific spirits are willing to help you out.
- You don't even have an accurate way of determining what this hypothetical number is though, due to communication being difficult and unreliable.
- Some spirits can help you out in combat, functioning as handicaps for players with poor mechanical skills
- These function at the input-level. If you are already very accurate with aiming your attacks, they won't really help you much and they can't help you be more accurate than a skilled gamer
- There are three different kinds depending on which mechanical skill you are lacking in
- Precision spirits act as if your aiming reticle is closer to the target
- Reflex spirits act as if your reaction time when performing a dodge was faster
- Leading spirits act as if you were leading a target by the correct amount, like if an enemy is moving horizontally relative to you then you can simply aim at where the enemy currently is, not where they will be, and the spirit makes up the difference
- These spirits are not discrete, you can have a small magnitude of assistance of them if you are not quite pro-gamer level or a large amount if you are extraordinarily bad at the game
- They do not apply in any PvP "dueling" context
- Spirits, by default, try and help you in a time of need
- They can cause enemies to whiff attacks, fail to detect you, or turn a lethal blow into a non-lethal one
- This works better the weaker your character is
- This lets you play as a child or a halfling or an old person and not just be dead weight in your party
- Many players will not like the realistic, hardcore nature of the world and should invest much of their favor into this kind of spirit to compensate so that it's less brutally punishing
- Alternatively, spirits can be instructed to not generally act of their own volition to help you, instead being commanded directly by the player
- To do this, you must "equip" the spirit from a slot
- A spirit can be associated with a given slot
- It can be associated with a specific trinket, like an heirloom or a crystal. It may be affixed to a wand, scepter, or staff that you hold. Or you can just hold the trinket itself. This is a western convention.
- It can be bound to a tattoo on your character at that location on your body
- It can be imbued within your body itself, aesthetically this has something to do with chakras. This is an eastern convention.
- If its a tattoo or chakra you can't have any armor covering it, otherwise you can't access it
- Using a tattoo/chakra for magic makes it very fast to equip/use, using a staff is more powerful but unwieldy
- Once equipped, a spirit may change what your actions do
- Attacking with a spirit will cause the spirit to attack with whatever sort of effect or element that its associated with.
- If you are powerful and an element is readily available in the environment the effects of the attack may extend far beyond your weapon/hand
- Attacking with a staff/wand using a spirit is essentially what a wizard normally does. The "spell" is just based on what kind of attack and spirit you do.
- Not so much "fireball", more pointing it at a lantern hanging on a building and flaring it up, causing some embers to spread around and ignite a fire
- The UI might give you some indication of what's going to happen: when you look at a source of a given element you can see some embers/snowflakes/static over the area that it might affect if you were to attack
- These "spells" are all things which spirits may normally do of their own volition, you're just causing them to do these at-will rather than automatically when you are in danger
- Even as a generalist, you don't usually see a lot of opportunities for this. If you aren't near a plentiful source of a given element there isn't a ton you can do
- Even though wind and earth might comparatively be very plentiful, you actually need the wind to be blowing or to be near a faultline to do anything significant with them
- Elemental magic is not a reliable way to fight enemies, its something that is situationally extremely useful but usually irrelevant.
- An unarmed martial artist using a spirit is essentially bending, as in Avatar: TLA
- The effects would be much less fantastical though
- In comparison to using a staff, it would be faster but with less magnitude in its effects and shorter range. Essentially you could go toe-to-toe with an equally skilled armed and armored combatant while yourself unarmed and unarmored. Staves are too unwieldy for this if an enemy gets close.
- Attacking with a regular weapon just imbues that weapon with the element. This is how you light your sword on fire or electrify it. It still has to plausibly (though improbably) obey the laws of physics though, so if you want a flaming sword it should have some oil on it to burn.
- Some types of spirits may specifically help non-attack actions more. Wind spirits help with dodging, ducking, running, and jumping. Water spirits help with swimming. Fire spirits prevent you from catching fire when walking through fire. Earth spirits help you maintain your poise.
- These defensive actions might not necessitate the spirits being actually equipped in your hands. But you probably do need appropriate slots to be unarmored.
- Some spirits will want to help you with a specific cause
- Divine spirits try and help you do good, they will not only be useless if you try and do evil but will outright work against you
- When your character prays to God, they are essentially saying "God, please lend me some divine spirits and I will use them to carry out Your will"
- There can also be lesser nature spirits that aren't necessarily acting on behalf of God, yet are similarly conditional with their assistance. This is how a druid gets their magic, and they will normally only function within a specific area (conventionally a forest) that the spirit is associated with
- Some spirits are purely transactional
- You can obtain their assistance through explicitly transactional means. Make an offering to them, help out their descendants
- This is how a wizard goes about obtaining spirits
- Some spirits can be entertained
- Play or sing music or dance to entertain spirits
- This is how a bard obtains spirits
- This isn't purely within the span of combat, if you want them to keep following you around you should be dedicating a good fraction of the day towards entertaining them
- Favor with spirits are the default sort of quest reward, rather than every random peasant having enchanted weapons lying around to give you or heaps of gold or you just receiving abstract "experience points" (not a thing)
- In general, its very rare for spirits to care much about NPCs. They are one of the factors that differentiate your characters from NPCs, which crucially doesn't require you to actually be physically powerful
- You don't normally need to worry about random NPCs being saved via divine intervention by spirits and screwing up your combat.
- You do need to worry about this in PvP. If you want to go randomly murder some poor noob your assassination might not only be foiled by their spirit, but you may be cursed if you manage to succeed in spite of this.
- If your character is powerful physically or involved in faction warfare, you will not be protected against "unfair" PvP assassinations
- Spirits try and communicate with you
- Usually to warn you of danger or guide you on a quest
- The means of communication depends on the type of spirit
- Wind spirits may cause ominous howling wind from a particular direction
- Fire spirits might flare a candle or cause it to go out
- Earth spirits might cause a tremor
- Nature spirits cause plants to wither
- Non-elemental spirits might just communicate via music, representing your character's gut intuition
- The more attuned your physical senses are the better you can sense them
- You want good hearing with no helmet on to best hear wind spirits
- You shouldn't be wearing shoes to sense earth spirits
- Outright being blind or deaf can help you focus on whatever other senses you are relying on
- You might do this situationally with a blindfold. Like you sense that something is awry, then close your eyes or put on a blindfold to better listen to the wind
- Some characters prefer to be attuned with a particular type of spirit, others are more general
- You could specifically be a pyromancer/firebender, or generalize across two or more
- The more you generalize the less effective you will be with any particular kind of spirit
- The exact taxonomy of spirits is setting-dependent
- In a modern/sci-fi setting
- Rather than there being separate "fire" and "ice" spirits there's just thermodynamic "spirits" that now obey the law of conservation of energy
- Wind/earth/water essentially become telekinesis
- Lightning/metal become electromagnetic
- Rather than being "magic" this is stylized as "psionics" or "the force"
- In a modern/sci-fi setting
Morale is a stat which defaults to zero, meaning no penalties. There are no benefits to morale above zero, except that it is a buffer against receiving morale penalties. The penalty for negative morale applies to incapacitation.
To determine a characters' morale, all of the positive and negative factors are first separately consolidated via a function that adds them with diminishing returns. Essentially this function sorts the effects from highest to lowest, then iterates through them, adding each subsequent effect at a reduced penalty. It may look something like this:
let mut positive_effects: Vec<f32> = ...;
positive_effects.sort().reverse();
let mut negative_effects: Vec<f32> = ...;
negative_effects.sort().reverse();
fn cumulative_morale(effects: &[f32]) -> f32 {
effects.iter()
.enumerate()
.fold(0., |acc, (effect, i)|
acc + effect / (i + 1) as f32
)
}
// or maybe this
fn cumulative_morale_alt(effects: &[f32]) -> f32 {
effects.iter()
.fold(0., |acc, effect|
acc + effect / acc
)
}
let cumulative_positive = cumulative_morale(&positive_effects);
let cumulative_negative = cumulative_morale(&negative_effects);
let final_morale = cumulative_positive - cumulative_negative / character.skill_check(will);
Positive Morale Effects
- Charisma skill check from each party member
- Multiplied by mutual faith of the given party member and that of oneself
- Divided by total conflicting faith of the pair (could alternatively be negative)
- Food quality
- Higher quality food (like well-seasoned) = more expensive
- Recent successes
- Each enemy routed/killed at the tactical layer, each encounter won at the strategic layer
- Allied power / enemy power
- If the total strength of your force is greater than the enemy, apply the difference as positive morale
Negative Morale Effects
- Injuries
- Disease
- Recent defeats
- Huge penalty when seeing an ally die or flee
- Enemy power / allied power
- Multiplied by the "fear multiplier" of the enemy. For most this would be 1.0, but we would give undead high multipliers and demons a huge multiplier.
- This should be one of the reasons that player characters are better at dealing with fantasy enemies than knights and soldiers. Adventurers (especially when accompanied by bards and/or clerics) should have much higher morale bonuses than normal characters.
Attributes
The maximum value of your characters' attributes is determined by their genetics, but the actual value may be quite a bit lower if they are not properly conditioned. For example, even if you have the theoretical ability to build a large amount of muscle, if you have poor nutrition or don't exercise then you will realize very little of it. Conditioning is different for each attribute, but generally no one will be able to condition all of their attributes to their maximum potential due to there only being 24 hours in a day.
Attributes are grouped between Chest/Stomach/Head/Limbs (L/R, A/L). Damage to one of these areas will affect all attributes within.
Chest
Endurance
Represents the strength of your heart, capacity of your lungs, and proportion of slow-twitch/fast-twitch muscle fiber. It determines how long you can go without suffering from exhaustion and how fast you move when traveling. Conditioned by traveling on foot. 0. Asphyxiated
- Dainty sheltered nobles
- City-folk
- Knights and peasants
- Professional soldiers
- Adventuring heroes
- Undead (cannot be tired)
Stomach
Immunity
This is essentially a combination of the liver, spleen, and other organs which regulate your immune system and ability to filter out toxins. 0. AIDS
- Infants
- Sheltered nobles and children
- Rural commoners and knights
- Elves and city-folk
- Vampires (immune to disease)
Gut
Your stomach, intestines, pancreas, and other organs involved with your digestive system. Determines how edible food needs to be in order for you to effectively digest it and how much variety you need to be decently healthy. Cooking makes food more edible, but food that is more fibrous and less nutritious can only be improved by so much. 0. Vampires (cannot digest food, must get calories directly from blood glucose)
- Elves (can only eat meat, fat, and luxurious elven plants)
- Nobles, orcs
- Professional soldiers, goblins
- Peasants (can survive almost entirely on grains without huge penalty)
- Livestock
Limbs
These attributes are separate among 4 limbs:
- Right arm
- Left arm
- Right leg
- Left leg Every physical check will use some proportion of these. For example, swinging a sword in your right hand is largely dependent on your right arm, but your left arm is also being used for balance and your legs are helping put force into it. Your torso is also twisting to support this, but rather than being a separate limb, your torso is essentially a fuzzy mix of all limb attributes (mostly arms).
Strength
Proportional to the total muscle mass of the limb. Arm-strength is important for attack damage, climb speed, and how well you keep your balance while blocking attacks. Leg-strength is important for movement speed and jump height. 0. Cripple
- Child
- Adult woman, pubescent boy
- Adult man
- Trained knight
- Olympic athlete
Agility
The speed of your muscular reflexes and your ability to control them. Arm-agility is important for accuracy and parrying, leg-agility is important for stealth and dodging. 0. Paralyzed, unaware, or tied up
- Drunken oaf, orcs, zombies
- Clumsy, goblins, skeletons
- Professional soldiers and knights
- Heroes, surgeons, locksmiths
- Elven heroes
Head
In theory eyesight/hearing should be further subdivided into eyes/ears for damage purposes, while intelligence and instinct are brain. In fact, ask a neurologist but intelligence/instinct would be correlated with different physical locations in the brain. But this is fine for now, we do not need infinite detail for the MVP.
Intelligence
The depth at which your character can think at. Applies a bonus to mental skills. In order to use your intelligence bonus, a skill has to give you time to think about the problem. 0. Not capable of conscious thought
- Low-functioning autistic, toddler
- Would struggle to learn even basic math
- Can learn high-school-level math
- Can learn college-level math
- Can meaningfully contribute to the field of mathematics
Instinct
Your ability to make snap judgements without thinking. A character with high instinct makes for a good small group leader in battle, where making a quick, decent decision is more important than making an ideal decision but taking awhile to come to it. Applies a bonus to your mental skills. The bonus does not require focus, but is lower than an equal bonus from intelligence. 0. Unconscious
- Takes a couple seconds to respond if you ask them a question
- Absentminded
- Alert
- Veteran captain
- Enlightened monk
Eyesight
- Blind
- Needs glasses, many fantasy enemies like goblins or zombies
- Below average human
- Above average human
- Elven warrior
- Hawk, elven archer
Hearing
- Deaf
- Muffled, many fantasy enemies like goblins or zombies
- Attended too many rock concerts
- Has never been to a rock concert
- Deer
- Blind monk
Skills
Skills are divided into two categories: mental and physical. The former is governed by intelligence and instinct, the latter by agility. Physical skills are
Training
Skills increase on a much longer timescale than is conventional for RPGs, they are not increased via an abstract XP/leveling system and very little of their value comes from actually using them during gameplay. Instead they are trained during your character's off-screen daily schedule. We are not actually simulating a schedule, at least not for the MVP, instead you're basically just allocating a ratio between your skills (which is given a sensible default when picking a character) and your character is ostensibly spending time training them on their own time.
The main difference between this and directly allocating skill points is that if your character is convalescing or traveling they won't be able to train most of their skills. Not all skills are equal though in terms of how much training time they need to be effective, they all have their own falloff curve. The number in the parentheses next to a listed skill here is the number of hours that it takes for it to be 50% effective. The rate of increase from training is lower the higher they get, providing an upper-asymptote for how skilled a character can be in a particular skill. Additionally, skills atrophy with disuse, so even an immortal elf or vampire cannot become optimal at everything (though they may get close) due to there being only so many hours in a day.
Intuitive vs Trained
Intuitive skills can be attempted without training, the check is an average between their associated attribute and the training rank. Trained skills on the other hand receive no benefit without actual training regardless of how high their associated attribute is, the training value is a ceiling. Most skills relevant to the MVP happen to be intuitive.
Formula
# TODO: pain_penalty, morale_penalty
const CALORIES_PER_ENDURANCE = 1000
const FATIGUE_EXPONENT = 5
fn fatigue_penalty(player):
fatigue = player.calories_used_today / (player.endurance * CALORIES_PER_ENDURANCE)
1 - fatigue^FATIGUE_EXPONENT
const MAX_CHECK = 5
fn skill_check(player, skill, focus_level):
hours = player.hours_trained(skill)
training = MAX_CHECK * (hours / (hours + skill.half()))
(reflex, focus) = match skill.type():
mental => (instinct, intelligence)
physical => (agility, precision)
attribute = reflex + focus * focus_level
mut check = if skill.is_intuitive():
(training + attribute)/2
else:
min(training, attribute)
if skill.type() == physical:
# armor penalty ranges from 0-0.4, with full-plate being 0.4
if skill.is_upper_body():
check *= 1 - player.upper_body_armor_penalty()
else:
check *= 1 - player.lower_body_armor_penalty()
check *= player.encumbrance_penalty()
return check
Each skill is represented in the stats window as a pair of horizontal bars. One represents the value as if focus_level was 0, the other as if it were 2. Each bar is measured in terms of hours trained, with non-equidistant ticks at each whole number value of the skill check. Any penalties such as from encumbrance, armor, or injuries are designated by a color on the bar, so that the white portion shows how much the skill currently is, while the colored portions show how much each penalty is affecting the final value.
Mental
Will (intuitive, 5000 hours)
Ability to resist pain or avoid morale penalties. 0. Generalized anxiety disorder / panic disorder
- Coward
- Cautious, sensitive to pain
- Professional soldier
- Brave hero
- Zen monk
Charisma (intuitive, 20000 hours)
There's no persuasion system or anything for the MVP, this is just a morale buff for the party. You lose focus during combat, so instinct gives you tactical morale while intelligence gives you traveling morale. 0. Autistic
- Cold and aloof
- Boring
- Friendly
- Funny
- Professional bard
Medicine (trained, 10000 hours)
The MVP is not going to have a herbalism system or diseases, so whoever has the highest medicine skill simply gives a party-wide bonus to health recovery speed. 0. Provides no help to anyone injured
- Knows to disinfect wounds with alcohol
- Can treat common diseases (flu/cold)
- Can treat some organ damage and uncommon diseases
- Can treat most organ damage and rare diseases
- Can treat all organ damage and all diseases
Faith (trained, 5000 hours)
This is a special sort of skill that also has an associated religion. You can only have faith in one religion. The upside of it is that it multiplies the morale bonus that you get from the charisma check of allies of the same faith (perhaps the min of each of your faiths is the multiplier). The downside is that it divides the morale bonus if you are of different faiths (add faiths together then divide?). Thus having 0 faith is advantageous in the unusual situation where you need a party of mixed faith.
Halbe: After the MVP we may want to move this into a separate system from skills called "Personality" which is more immutable and balanced via tradeoffs. "Religion" could stay as a skill, representing one's knowledge of a given religion, and is a requirement for the charisma-multiplier morale bonus from faith. Faith might also be renamed to "Conviction" and come with more downsides to balance out its huge upside, like one's unwillingness to compromise could make it difficult to deal with "morally flexible" characters.
- Agnostic, atheist, or only only identifies with the faith to participate in holidays and not be ostracized.
- Actually does pray and ostensibly believe, but doesn't think about it often in day-to-day life
- Regularly attends church and will feel guilty for skipping, but still often view most of their life through a secular lens
- Prays daily and means it, but not eager to become a martyr. Doubts only when faith is tested by serious adversity.
- Willing to live an ascetic life. Will almost certainly not blaspheme or convert even when tortured
- Will eagerly martyr for a righteous opportunity
Physical
Melee (intuitive, 8000 hours)
Agility helps you hit enemies that are actively trying to dodge or block your attacks, precision helps you hit enemies that are unaware of you or staggered. 0. Has never been shown how to use a weapon or observed for an extended period of time
- Can split firewood with an axe, zombies
- Peasant levy, orcs, goblins
- Professional soldier
- Knight
- Elven warrior
Ranged (intuitive, 15000 hours)
You have to aim at a target for awhile to get your precision bonus, whereas agility helps more with point-shooting 0. Never practiced even throwing a baseball
- Orcs, untrained peasants
- Goblins, militia
- Professional soldiers
- Huntsmen
- Elf rangers
Block (intuitive, 12000 hours)
The larger your shield is, the less you rely on your block skill to use it effectively. A pavise requires almost none (though considerable strength), a buckler or weapon require high skill to use effectively. Precision doesn't give you a bonus to your defense when blocking, but does increase the amount of poise damage that actually does occur on a successful block (automatically turning it into a parry). 0. Never been in a fight
- Has been in some barfights
- Fresh recruit
- Professional soldier
- Knights, heroes
- Elven swordmasters
Stealth (intuitive, 8000 hours)
Agility reduces the noise that you make while moving, precision reduces the radius at which your party can be detected at when traveling. 0. Has never even attempted to steal cookies from the cookie jar
- Most people
- Can tiptoe around the house in socks without waking anyone, usually
- Novice hunter, professional mercenary trained in ambush tactics
- Practiced thief, veteran hunter
- Master thief, elven hunter
Balance (intuitive, 30000 hours)
Relevant both for poise in melee and speed in difficult terrain 0. Cannot walk upright
- Bit of a klutz, orcs
- Can walk in high-heels, can dance in normal shoes, professional soldier
- Can run and dance in high heels, amateur gymnast
- Skilled gymnast or martial artist, can walk a tightrope
- Graceful elf
Surgeon (trained, 10000 hours)
The speed at which you bandage/splint wounds and the healing rate, once-bandaged 0. Cannot reliably apply a bandage
- Can dress a wound or apply a tourniquet
- Can stitch skin, probably shouldn't
- Can remove a bullet, good at stitching skin
- Can remove an appendix or stitch an organ
- Brain/heart surgeries
struct StrataMap {
map: [[SmallVec<Layer, 4>; 32]; 32]
materials: SmallVec<Material, 4>
}
struct Layer { material_index: u4, depth: UnitScalar #0.0..1.0 }
enum Material {
Skin { melanin: f32, carotin: f32, ???},
Fat,
Muscle,
Bone,
Steel,
Paint { rgba: Rgba },
Cloth,
...
}
impl Material {
pub fn albedo(&self) -> f32,
pub fn roughness(&self) -> f32,
pub fn restitution(&self) -> f32,
pub fn density(&self) -> f32,
# ... other functions relevant for either graphics or physics
}
This tells you everything that you need to know about an entity's physical properties, given a shape and the UV map for its StrataMap. Its not quite the same as a regular UV map though, because it has to be able to also convert a "depth" to a point in 3D. The total depth of all layers is essentially a heightmap for the surface of a mesh, and generally only this and the outermost layer are relevant to the model generator. All of the layers are needed to compute physics properties, most of which are used at the client-layer for secondary physics, but the sum total of all mass from the StrataMap for all entities associated with a character can be relevant at the tactical-layer for combat equations or the strategic layer for calculating fatigue from traveling with encumbrance.
For the MVP, the function which generates the StrataMap for a character and their equipment is likely the responsibility of the programmer implementing the model layer since the information is most directly relevant to them. For the MVP, this all sounds fantastically complicated, so StrataMap can have a quick n' dirty temporary version that is just a wrapper around a single Material, forget the 2D map and layering, and combine a bunch of materials like Skin/Muscle/Fat/Bone into "Flesh" or different rock types into "Rock". The characters would basically look like 3D stick figures and the only weapons will be clubs and maces, but its fine for now.
The eventual purpose of StrataMap being so fantastically detailed is not only to be able to generate all of our models from it and have very accurate physics calculations, but it can also represent things like how the clothes and armor on a character (added on as layers) affect damage. An outer layer of steel followed by some padding would distribute force very effectively. Or a gap in the steel layer (for the slit of a visor) translates to a weak point that a character could attack with sufficiently high accuracy, with the animation system using inverse kinematics to place their weapon in the exact weakpoint. This enables the simulation at the tactical level to become extraordinarily detailed in the future after the bare minimum is implemented for the MVP.
In the MVP, there are only two shapes which a StrataMap is expected to support: the pseudo-capsule and a flat terrain mesh. A shape which can support StrataMap is one which unambiguously maps a U, V, and depth value to an X, Y, and Z in an entity's local Transform space. There can be no UVDs which map to multiple XYZs or vice-versa.
Adler: Bruno, what do you call this? Some geometric term that includes the word "transformation" I assume, like "functional transformation".
The following shapes should be able to facilitate this:
- Cylinder (U: longitude, V: length, D: radius)
- Capsule (U: longitude, V: length + top and bottom latitude, D: radius)
- Sphere (U: longitude, V: latitude, D: radius)
- Box (one face is chosen as the surface)
- Blade
- May need two separate shapes for single-edge and double-edge
- There are a couple ways to map it, but it needs to support both pointed and flat heads
Management
Inventory management should NOT be a full-time job. When players come home from laboring at the spreadsheet mines all day they should not have to toil more in what is ostensibly their reprieve from such work. But this is adventure simulator, not adventure handwaver, so we need to use the interface to abstract over all of the things that normally make inventory management tedious while still preserving the underlying depth.
Automation
Most aspects of resupplying, looting, selling, and stocking rations for an upcoming adventure can be effectively automated.
Resupplying
Players can define "sets" for their character. This is their weapons, armor, ammunition, potions, and tools (like pack, rope, torch, firestarting kit, and bedroll) which they expect to have on them when they set out. When in a trade menu, you can press a "resupply" button to automatically purchase any equipment that you need for your currently selected "set" that you don't already have. The button can be blue, and any items which would be purchased, were you to press it, can be highlighted as blue.
Looting and Selling
A party can configure a weight limit using a slider, which shows them what the total party travel speed would be at a given limit presuming that the load is optimally distributed (such that all characters can maintain the same pace). When a tactical simulation ends, the party sees a screen that displays all of the loot available to collect. They could loot each individual item and decide whose inventories they are going into, or they could just press the "autoloot" button which will loot items in order of their value to weight ratio until the weight limit is reached. Like with resupplying, you can anticipate this behavior because any items to be looted will have a gold highlight which matches the gold loot button. When in a town, the loot button becomes a sell button, and any items not in any of your equipment sets will be sold.
Some items might also automatically be flagged as "keep" (perhaps a checkbox next to them in the inventory menu), such as goblin ears if you're on a quest to kill goblins and this is the required trophy to turn in for the reward.
Storage
Any items which are in your equipment sets, but not in the currently configured one (or which you have a surplus of, for example if you have 50 arrows and your set only calls for 30), can be automatically deposited in storage with a grey storage button.
Rations
The trade/loot page can also have a red button+highlight for rations. When pressed, you will purchase however many rations would be required for the currently planned journey. It may also have a slider to increase/decrease the number of expected days in case you want some safety margin or to eat something at your destination (warning: orc and goblin meat is nasty and unsanitary).
Map
The world map is a grid where each square has a height and an enum for the terrain type. Each of these affect both the speed of travel and the difficulty of climb/swim check to avoid injury. We should not try and create our own, we should be able to find both height and biome data from some open GIS dataset. At minimum, it should be easy to find modern data for these, but there may also be a historical dataset that we can use.
Height
Traveling from a lower height to a higher one may require the characters to make a climb check (based on upper body strength vs weight) based on the slope, and traveling from higher to lower may require the characters to make an agility check.
Terrain Type
As this is an enum, we can store extra information in each variant. For example, the "River" variant could include its depth and velocity, both of which would contribute to how hazardous it is to ford.
In addition to the costs imposed to traveling, it may also affect stealth and detection. Forest cover may largely prevent detection from flying enemies but also make it much easier for an enemy to ambush you, presenting a trade-off of risk which you might assess based on which enemies are known to exist in an area and which you are better able to defend against.
Pathfinding
As described in the travel page.
Weather
This probably isn't worth putting in the MVP, especially for such a temperate place like Italy, but eventually there should be a weather map that affects the way that you travel though terrain. Heavy snow would slow down land travel, frozen lakes and rivers become possible to cross without swimming (but also risky if the ice is thin), and rain makes climbing very difficult.
Points of Interest
For the MVP, there is no need for any point of interest other than enemy camps/lairs/nests relevant to active quests in an area as well as settlements. The former are simply placed randomly (though not too close to any other point of interest), the latter should be obtained from a GIS dataset. If we can't find historical GIS data on Italian settlements then we can just use modern data and rely on Cunningham's Law to fix it.
Underground
In our setting, there is ostensibly a vast underground network of caves, crypts, tunnels, Ratling under-cities, Dwarven strongholds, and even antediluvian ruins. But this sounds hard, therefore we shouldn't bother with it for the MVP. All of the quests will conveniently take you to overland locations, which don't even need to have structures.
Halbe: You are essentially being hired by local municipalities to clear out homeless encampments. If only we had this in the IRL modern setting...
Character
Characters are created by investing some amount of favor into them. The more powerful the character, as determined by their stats, the more favor you need to invest. The exact kind of favor you need also depends on what character you want. If you want an elf character, you need to go do some quests with the elves.
You aren't exactly spawning a character into the world; ostensibly, you are obtaining control over a character who already exists! This means you don't always have to start "fresh" with a young, untrained character with no background. You can create a wealthy, skilled character simply by spending a lot of favor on him.
Mortal
Mortal characters age normally and eventually die. They cannot have their physical features customized; when rolling them, players must choose from a limited selection of randomly generated characters. They are cheap and efficient, ideal for players who want a roguelike/extraction-esque experience of frequently rolling new characters, quickly obtaining power, dying, and starting over.
Humans
Dwarves
Inspired by their Tolkien/Warhammer depiction. A proud, stubborn, greedy, short sturdy, and strong race. Dwarves dwell in underground mountain cities. In their days of glory, the Dwarves built extensive tunnel networks between these cities; these tunnels have since been infested by foul creatures.
Dwarves who shame their kin by dishonoring the ancestors, breaking oaths, or engaging with prissy Elven nonsense like magic may be exiled at best, at worst compelled to redeem their honor by undertaking various suicide missions to retake an ancestral realm.
As the race needs a lot of Dwarf-specific assets, Dwarves will not be included in the MVP or tentatively even the next phase.
Halflings
Inspired by their Tolkien/Warhammer depiction. A small, jovial, provincial people generally unconcerned with the matters of the "big people." Would be found in small idyllic villages here and there. Not important enough for the MVP.
Orcs/Goblins
Inspired by Warhammer greenskins, though less comedic and specifically only grown from nasty underground funky pools. An Orc is just a Goblin who had lots of fresh meat thrown into its spawning pool (and must maintain this diet).
If you aren't familiar with Warhammer, the idea is that they are a fungus-based lifeform with genetic memories. The point is for them not to need a complex civilization to be threatening (they already know how to fight and speak) and for you to not feel bad for slaughtering them (no women or children, they emerge REDY 2 FITE). Quest fodder for the MVP.
Ratlings
Inspired by Warhammer Fantasy Skaven, though with the technology level toned down somewhat. These are wretched, craven humanoid rats who dwell underground, both in stolen Dwarven cities and in their own subterranean creations beneath prosperous human cities. They don't need to be in the MVP.
Immortal
Immortal characters do not age, will respawn if killed, and can be customized in detail. Their purpose is to give players the option of a more conventional RPG playstyle than the punishing roguelike experience of mortal characters.1
Respawning an immortal character requires a favor cost equivalent to the death cost of a similarly valuable mortal character. The cost may even be higher for immortal characters, so players would be ill-advised to use them for suicide missions. However, what immortal characters lack in cost efficiency, they compensate for with a higher effective skill ceiling, having unlimited time to train their skills.2
Immortality is based on race, not an abstract per-character flag. All immortal races are said to have "fey blood." In the current roadmap, Elves are the only immortal race planned.
Elves
Inspired by their Tolkien/Warhammer depiction. Tall, beautiful, and haughty, Elves live in either deep forests or fictitious islands. They are generally morally good. Exceptions include the evil "Dark Elves" and the somewhat more neutral, ecoterroristic "Wood Elves."
Dragons
Intelligent dragons who can take on a human form. It would be extraordinarily expensive to actually create a full-blooded dragon character. Some dragons may be unable or unwilling to take a human form. Absolutely not in the MVP and almost certainly not in the polished product unless one of the devs is very insistent.
Halbe: I am certainly not going to try and animate dragon flight.
Beastmen
(rename "Beastlings"? "Shifters"?)
Beastmen have both a beast form and human form that they may shift between. The exact type of beast depends on whatever would be local to them. Can be felines, canines, serpentines, equestrians, lizards, and more.
Probably not in the MVP. Might be in the polished product at least for wolves.
Half/quarter/etc.-blooded
These generally look like normal humans, except they can be immortal and customized. They are for players who want the mechanics of Elves/Dragons/Beastmen but don't want the pointy ears or shapeshifting. These come from breeding between mundane people and the fey-blooded.
In the case of feybloods who can shift between forms, the half-bloods may be unable to shift. Instead, they might take on some intermediate characteristics of the two forms.
Halbe: Yes, half-blooded beastmen are the "designated furry race." And I think gnomes are just elf-halfling hybrids.
Bruno: And I was expecting something tasteful and classy, like the half-bloods are our way of capturing the aesthetic of ancient Egyptian deities in a post-Christian world. Alas.
Vilebloods
When a mundane character consumes fey blood, he can become fey-blooded. However, this is evil, so it also curses him. The exact nature of the curse depends on the kind of fey blood.
- Werewolves/bears/etc are beastmen-blooded.
- True vampires are elf-blooded.
- Mostly analogous to Warhammer Dark Elves. They do not burn in the sun, and they are not actually undead.
- The aesthetic of Freaky Devil-Looking Thing (e.g. imps) is captured by mongrel vilebloods. They may take features from a mix of reptilian, mammalian, Draconic, and/or Elven blood.
Undead
Mortals risen from the dead through unnatural magic.
- A vampire is created when another vampire offers a mortal his blood and buries him alive. After the mortal suffocates to death, he becomes a vampire.
- Zombies and skeletons are not elf-blooded; they are risen via necromancy. They are mindless and must be consciously puppeted by a necromancer.
- Ghouls/wights are zombies/skeletons who have a soul bound to them (the ritual requires elf blood). They are not mindless, and though bound to their necromantic masters, they can act autonomously.
- A lich is a necromancer who has turned himself into a wight. As his soul is bound to himself, a lich is the only type of wight with free will. (This implies the possibility of ghoul-liches, who retain their flesh.)
-
However, everyone's first character (and probably the next several) will be mortal; mortal characters are playable on free accounts, and players can obtain their first with zero favor. ↩
-
Albeit with drastically diminishing returns. ↩
For the MVP, quests are not based on the state of the world. Settlements simply will always have a fixed number of quests available at different difficulty levels, and every time a party takes one another will immediately be generated. The difficulty (and proportional reward) of a quest is a function of the estimated difficulty of the enemies (greater than the sum of their individual levels), the distance to them, and the difficulty of traversing that distance (how dangerous the area is and how difficult the terrain is). For the MVP, the only quests are just bounties to kill parties of enemies, which may be mobile or immobile.
Planning
Since you know what enemies you will face at the destination and can estimate what enemies you'll possibly face on the journey, you should plan a party in advance to account for this. For now this is mainly a question of whether you expect to encounter armored enemies (and therefore need hammers/rondels), hordes of weak enemies (therefore want a cleaving sword/axe/hammer and heavy armor), large enemies (therefore want a polearm), and enemies with projectiles (therefore want armor/full-plate). You will also want to account for difficult terrain or the need for stealth/detection during travel in your party composition, the latter is important if you're traveling through an area with enemies that are too dangerous for your party to fight against.
Mixed-Level
Quests are not balanced around the assumption that all members of a party have a similar power level, in fact its generally the case that you want a mixed-strength party. When you set out to clear out a vampire crypt, you need a very skilled armored duelist or two to fight the vampire. But you'll also be encountering plenty of zombies and skeletons, which can be efficiently dealt with by a small group of decent semi-armored combatants with clubs and axes.
Reward
Rewards are proportional to difficulty, which is better thought of as a measurement of risk. Each character has a value calculated in favor, and each quest has a reward that can be expressed in terms of favor, so to calculate what the reward should be we can choose a power level that is ~90% likely to successfully complete a quest, estimate the favor needed to create a party of that power level times the chance of death plus the resources spent on completing the quest (food, arrows, healing), and multiply the final reward by some constant like ~1.2-1.8 so that its actually profitable. The chance of death versus difficulty of a quest though is not linear for your party level though. A powerful party might be twice as expensive as a weak one but only marginally less likely to die when killing a pack of goblins, so its a waste of time, and likewise the likelihood of a ragtag group of nobodies killing a vampire is basically zero, so there's always a theoretically optimal party strength for every quest.
Interface
So that new players don't naively accept difficult quests since they have no frame of reference for estimating their own/enemies power level, the quest should display recommended power level and their current value before they head out.
Equations
TODO: come up with a first-pass starting point to use to assess party power level.
Time between players is kept somewhat in-sync. The idea is that generally, time advances at 56x speed, so that one week in the real world is one year in-game. The main purpose of this is to account for the realistic travel distances and healing rate that we use, as otherwise the game would be extraordinarily boring. However, its not exactly in-sync, because at minimum there is also a real-time simulation for things like combat or navigating difficult terrain. Thus, each party is permitted to be a little-bit out-of-sync with each other, and can use accelerated downtime to catch up.
Throughout this wiki, the term "official time" refers to the most current time according to the server. Your character can be exactly one year behind official time, beyond that they will have to catch up with downtime (resting or training) before you can do anything else. You cannot go ahead of official time.
For example, in the example scenario, at the time that they venture forth from a settlement they are in sync with the official time, but their four ~20-minute simulated encounters incurs a time-debt of 80 real-world minutes. 80 minutes in the real world is about 3 days of official time, thus when their characters return to a settlement they will ostensibly be recovering, training, relaxing, traveling between settlements, or working some non-adventurous job for at least 3 days before they set out again.
Why bother keeping players within a year of each other?
Its not necessary for the game to work, true, but it would contribute to a sense in which the world feels like a real simulation rather than an abstract game as many MMOs do. When you end up at the mercy of the simulation and sustain a very serious injury that kills your weekly playtime, there is always the last resort of just creating an additional character. In fact, it is expected that players will maintain multiple alts for this purpose.
Ok, then why allow players to desync in the first place?
Because the world is to-scale with realistic healing rates. It would be really boring even if it were constantly at 56x speed. Plus, there couldn't be a real-time tactical layer.
Implications
The most odd implication of this is that ostensibly, characters that are further from official time are sort of prescient about certain things in the future, and characters closer to official time do not know the outcome of events which have ostensibly happened. As an example:
A griffon has nested near a town. Geoffrey, who is 3 weeks behind official time, decides that he wants to try and slay it. However, while he is forming his party, Jack, who is 5 months behind official time, also takes the quest and slays the griffin since he put his party together very quickly. Geoffrey then learns that actually, the griffon was apparently slain several months ago.
When Jack put his party together, he was joined by Derthert, who was actually an entire year behind official time when he saw the open party. This means that Derthert must have consulted a diviner or seen this opportunity in a dream then decided to spend 7 months training/working in this settlement before the prophecy of this quest comes true. Bizarre, but it somehow works out.
We are not actually simulating an economy (at least for the MVP) nor do quests originate from circumstances of the simulation (at least for the MVP, they're just totally arbitrary fetch/bounty quests), so the implications of this shouldn't be a big deal, but it is weird to think about.
TODO: rewrite for HTML-based strategic interface
We technically have an open world, but its not really an open world game in the sense that most people consider it. If you've played the 1.0 version of Mount and Blade (before you could walk around in settlements), Battle Brothers, or early versions of Starsector you should have an idea of what to expect here.
Essentially, the travel map is a minigame where each "party" (players or enemies) has three stats: speed, detection, and stealth.
Speed
- Your travel speed on the map
- This is not necessarily the same as the speed that a character might run at
- Humans are unique in the animal kingdom for having very high travel speed due to our ability to sweat and walk upright. A zebra might sprint much faster, but it will quickly become exhausted.
- The larger a party is, the slower your travel speed. Large parties must deal with increased logistical complexity, periodically stopping throughout the day as incidents occur, and take longer to camp and set-off
- There is also a geometric component to this, a "column" of soldiers is typically one to four men wide (depending on width-of and availability-of roads), so when a huge army set out for the day some of the army may have to wait for hours after the vanguard sets out before they start marching
- No we are not doing huge armies, that is out of scope for this project (for now 😉)
- On a per-character basis, this is based on your or your mount's endurance versus your weight. It is very exhausting to march all day, especially with a heavy pack.
- On a party basis, this is based on the total endurance against the total weight. This is because characters with high endurance will share the burden of those with low endurance or heavy packs.
Stealth and Detection
- The radius at which enemies can detect you
- Even if an enemy is faster than you, if they can't see you then you can simply go around them
- Larger parties, especially ones with horses, are easy to spot from a distance
- A party can improve its detection by relying on scouts that stealthily scout ahead of the party to spot potential enemies
- On a per-character basis, your stealth is a function of you or your mount's agility and weight. Your detection is a function of your sight and hearing.
- On a party basis, the average of each character's stealth and detection.
Interdiction, Ambush, and Rest
- In a perfectly balanced system, the vast majority of parties would ever actually fight. A small group of elite warriors could successfully pursue large groups of weak enemies, but aside from this everyone would just be able to run away from most battles. We don't actually want this.
- At the end of the day, each party needs to set camp for the night
- If you don't, you start becoming exhausted and will eventually lose travel speed
- This means that if you encounter an enemy party at the end of the day, who might ordinarily not be quite as fast as you, its possible that they could chase you to exhaustion.
- This serves the same purpose as Starsector's interdiction system (force a speed penalty on sufficiently close enemies) and Mount & Blade's disorganized penalty (receive a speed penalty when raiding a village or after any battle)
Planning Your Adventure
- The travel screen is a map that lets you place points to chart your planned journey
- In any given region, you can view a list of what sorts of enemies are in an area along with an estimate of the size of a party of that enemy type from which you could not reliably evade. This is important for planning your journey. If a particular area has parties that are too powerful for you to beat in combat or evade (because they are elite warriors), you should find a different route or rethink your party.
- Different sorts of terrain may also have different travel speed multipliers. Traveling on roads is very fast, fording a river is extremely slow. Your route will show the speed multiplier at any given point along its path.
- This isn't necessary for the MVP, but a pathfinding algorithm should be used on the terrain map to find the optimal route between each point. The point of placing points should be more to plan around resources or route around areas with dangerous enemies, not a check to see whether your brain is capable of intuitively computing A*.
Rest Stops
- A point may be made into a rest stop, at which you will rest for the day once you arrive.
- Placing a rest stop at an inn allows you to fully rest faster (no watch schedule or tent pitching) increasing the amount of time available each day for traveling. The inn also has a cost, but this is trivially cheap unless you are an impoverished mendicant.
- The time between each rest stop should be 24 hours. Your cursor when placing points displays the expected arrival time, but the longer your characters go without resting the slower their travel speed and worse their combat abilities will be.
Food
- Based on the total duration of the trip (and the return trip, which by default is to just follow the original trip backwards), you will need to bring food.
- We do not actually want players to micromanage their inventory. Your character will automatically purchase sufficient rations for the journey before they set out, displaying the cost of this on the screen before you finalize your travel plan.
- Your rations will be replenished by staying at inns. This will be accounted for when setting out. For example, if you are on a ten-day journey and plan on stopping at an inn on the fifth day, then your character will only set out with five days of rations (+30%) each day.
- Likewise, characters will automatically eat food throughout the day. We do not care to keep track of exactly what kind of food you have (for now), its just an abstract "food" resource.
- Since you can adjust your travel plan as-needed throughout the journey, you may end up taking longer than you initially rationed for. By default you'll bring, say, ~30% extra rations to account for this. But if you run out of rations you don't necessarily starve. It will effectively reduce your travel speed based on how easy it is to forage in a given area. Lush forests therefore are very forgiving, whereas in harsh desert and tundra it may not even be possible to subsist on foraging at any travel speed.
Water
- You do not normally set out with all the water that you expect to drink in a journey, unless its a very short trip. Water is very heavy and you have to consume a lot of it.
- Fortunately, its easier to obtain water than it is food (in most places)
- You instead bring a certain capacity for water, which starts out full, and must periodically stop at places where it can be replenished
- Any source of freshwater as well as settlements and inns (via wells) can provide water. It is normally pretty easy to plan around this, but certain environments (deserts, obviously) make it extremely difficult.
Services
Each settlement offers a number of services. Tentatively, these are all tabs of a unified trade page. Each tab corresponds to a different guild, represented by a single NPC. The left side is a list of everything offered by the NPC, the right side is everything offered by your party. It may be a good idea to not only include items in this menu, but also services.
Services show up at the top, above the list of items in their own list. Each service has a button to expand it, which shows a custom per-service form. To rest at an inn, for example, there is a slider for how many nights you would like to pay for. Doctors may have a healing menu for different treatments (bandaging, medicine for diseases, surgery). Smiths may have a menu where you can search for a custom piece of equipment designed by another player which you can pay them to produce. Mount & Blade Bannerlord has a good reference for this menu, including the ability to trade intangibles (the barter menu with other lords kind of has this).
Halbe: Brothels may provide... other services... for a morale bonus. ||But also a risk of being afflicted by a disease||.
In the center of the screen, clients may render a 3D window of the NPC representing the service. They can have dialogue that plays, like a greeting when you open their menu, a goodbye when you leave it, and comments as you interact with their menu. But this should never interfere with the gameplay. You don't have to click through dialogue in order to buy something, it just plays in the background as you use their service. This is not important for the MVP, and later down the line this would also be a great opportunity to add voice acting and mocap to give the world some personality.
Halbe: The inspiration for this is the Maiden in Black from Demon's Souls, who recites an incantation while you are in the level-up menu.
Social
Each settlement has at least a noticeboard and tavern, which serves as a social hub for chatting with other players and forming parties. The notice board is where NPCs post quests, which players can reply to. To form a party for a quest, you essentially post a reply on the notice for it which links to your party. This reply includes information about how many party members you're looking for and what requirements you have for them, if any. For example, you might specify that you need one character with a ranged weapon and one character with armor and a hammer. Anyone who clicks on the link will join your party's groupchat as a stranger, where you can formally let them in or kick them out. The notice for the quest will automatically update as-needed. If someone requested to join your party as the ranged specialist role and you accepted them, then this slot disappears from the party listing.
All of this is done in hypertext, but what's ostensibly physically going on in the world is the listing on the notice board was written by an NPC in need, then the reply to it is the rumors traveling around town that "a couple of adventurers are planning on slaying those goblins that have been ambushing the merchant caravans, I hear they're looking for an archer. You should seek them out at Grub's Tavern if you're interested". Then when you show up in their groupchat, you're approaching them at their table.
Off-Topic
Not all socialization in settlements is relevant to quests. The tavern is also effectively a public chatroom. Later, after the MVP, we can also give players the ability to purchase a building and make factions which may serve as faction-exclusive chatrooms.
Halbe: Or they could freely discriminate in other ways. In-world racism between Elves, Dwarves, and Humans would be very appropriate. Even the kind of discrimination that would be considered objectionable in the modern day would be fine, like sexism or intra-human racism, due to the system described in the next section
Moderation
We don't want to be the speech police, but there is inevitably going to be spam or links to pornography and other objectionable content that we will have to deal with. However, it would be great if we could give players the tools to enforce speech themselves and opt-in to more strict moderation than the bare minimum needed to stop spam and illegal content. Essentially, a player-run faction could own a place like a tavern and would be responsible for handling the moderation. There can be multiple taverns in a settlement, so if one of them has an overzealous moderator then you could simply go to one of the other ones. If they are all overzealous, especially if its that a particularly obstinate group of players are trying to establish a monopoly to enforce their annoying speech rules, then we can leverage the fact that this is a game not just a forum. Steal their stuff, assassinate their characters, burn their building down. Normally, these things would be hard to get away with. But players might have the ability to rate the moderators, and if enough people complain then we can increase the likelihood of success when attempting these "faction warfare" actions (when you do not have the will of the people, player establishments are protected by favor.
None of these player-run social hub features should be in the MVP, we will just be very selective about who we invite for testing until we add support for this stuff.
TODO: Trade documentation in progress...
Combat
Combat is the solemn duty of any good knight or mercenary, and until we have a working fashion module, it'll be what players spend most of their time doing. So let's get it right!
Attacking
When the player clicks the Attack button, initiating an attack animation, we run a shapecast in front of the player character. If there is an intersection between the attacker's hitreg and some other actor's hitbox, we calculate input precision. Then comes the skill check algorithm.
Skill check algorithm
Broadly speaking, the flow goes like this:
-
Calculate accuracy based on:
- The attacker's melee skill check
- Multiply by weapon term (small knife: 2.0, long hammer: 0.5)
- Multiply final value by input precision
-
calculate
dodge_defense:- Calculate
armor_dodge_termfrom their armor.- This isn't actually the weight of the armor; it's based on articulations on joints.
- Full-plate gives 0.6, full-body chainmail is 0.8, and unobstructed joints is 1.0.
- Calculate encumbrance_term from total weight versus leg-strength
- Multiply a dodge skill_check by
armor_dodge_termandencumbrance_term
- Calculate
-
calculate
block_defense:block = defender.skill_check(block) shield = defender.shield_bonus()shield_bonus()= 0 for weapon; 1–2 for a small shield; 2–4 for normal; 5 for pavise
$$\mathrm{defense}(\mathrm{shield},\mathrm{block}) = 5 \cdot \left(1 - e^{-\tfrac{\mathrm{shield}+\mathrm{block}}{2}}\right)$$
-
Calculate
defensefrominput reflex:if defender is parrying: defense = block_defense * 1.5 * input_reflex elif defender is dodging: defense = dodge_defense * input_reflex else: defense = block_defense -
Attack value is accuracy - defense
-
If attack is less than 0, miss and apply surplus defense as unbalance penalty to attacker
-
If attack is between 0 and 1, multiply attack force by attack
- 0.1 barely grazes the opponent, 1 is square-on, 0.5 is a glancing blow
-
If attack is above 1 and the attacker's weapon is precise, attacker now attempts to bypass armor with surplus attack.
- An armor's "coverage" is subtracted from the surplus attack to obtain the "critical attack"
- If critical attack is greater than 0, attack bypasses armor completely and its final damage is multiplied by this number
- Though not necessarily relevant for the MVP, critical attacks are relevant even when targets are unarmored because this allows the damage multiplier to exceed 1.0, allowing for instantaneous stealth one-hit-kills.
- If a critical hit cannot be made, then attack just stays at 1.0 for a direct hit
Incapacitation
A character's incapacitation represents the sum of all disabling effects on them and corresponds to the state of their animation. When above half, they are "staggered" and each additional 1% of incapacitation causes a 2% penalty to movement and attribute checks, and when above 100% they are completely incapacitated (which also causes knockdown). Most negative effects that a character has can affect their incapacitation, past a certain threshold. Your incapacitation is displayed as a wheel in the center of the screen. If it is at 0%, the wheel is invisible, and as it increases it starts from 12 o'clock and extends as an arc clockwise. Each factor that contributes to incapacitation has a different color to differentiate them.
Each of the following factors range from 0% to at least 100%.
Imbalance (white)
Halbe: This was written in terms of energy, but might make more sense in terms of momentum.
The most direct way of being incapacitated, attacks which impart force on your character or losing your footing in difficult terrain can cause imbalance. Imbalance constantly recuperates. Your mass and the directness of an attack determine how much imbalance you actually take, and your agility determines how quickly it is regenerated.
# use these for calibration
# direct hits by trained warrior in joules: halberd ~120, longsword ~70, shortsword ~30 dagger ~20
# longbow arrow 80
# kg: armored knight ~90, goblin ~40
const STAGGER_RESISTANCE_JOULES_PER_KG = 10
const UPPER_MUSCLE_KG_PER_STRENGTH = 5
const MUSCLE_KG_TO_JOULES = 2
const UPPER_MUSCLE_KG_TO_PUNCH_KG = 0.1
# attack_directness is 1.0 if square-on, 0.01 barely grazes, in-between is a glancing blow of some magnitude
fn balance_damage(attacker, defender, attack_directness):
# todo: equation for calculating striking mass for a given weapon, for now its fixed
# balance_factor is 0 for a weapon balanced at the hilt, 1 for a weapon balanced at the tip
attacker_upper_muscle_kg = attacker.strength * UPPER_MUSCLE_KG_PER_STRENGTH
punch_kg = UPPER_MUSCLE_KG_TO_PUNCH_KG * attacker_upper_muscle_kg
striking_mass_kg = punch_kg + attacker.weapon.mass_kg * (1 + attacker.weapon.balance_factor * attacker.weapon.length_meters)
joules_of_attack = attacker_upper_muscle_kg * MUSCLE_KG_TO_JOULES * striking_kg
imparted_joules = attack_directness * joules_of_attack
resistance = STAGGER_RESISTANCE_JOULES_PER_KG * defender.mass_kg
defender.imbalance += imparted_joules / resistance
Exhaustion (grey)
Exhaustion represents how out of breath your character is. Most actions will not actually exhaust faster than it recuperates, but climbing, sprinting, and fighting with heavy weapons, shield, and armor can.
const BREATH_RECOVERY_PER_ENDURANCE_PER_SECOND = 0.002
# someone with 2 endurance (poorly fed Napoleonic soldier) can march 1.2m/s all day. Therefore a simple linear ratio between velocity and breath must be about:
const BREATH_PER_METERS_PER_SECOND = 0.0034
fn update_stamina(player):
player.breath_damage += dt * character.velocity * BREATH_PER_METERS_PER_SECOND
player.breath_damage -= dt * character.endurance * BREATH_RECOVERY_PER_ENDURANCE_PER_SECOND
Pain (pink)
Injuries are a source of constant pain. Pain is divided by will.
$$ \mathrm{pain}(\mathrm{damage}, \mathrm{will}) = \frac{\mathrm{damage}}{\mathrm{damage} + \alpha\cdot\mathrm{will}}\cdot e^{-\beta\cdot\mathrm{will}};\ \alpha=0.5,\ \beta=0.2 $$
fn update_pain_factor(character):
damage = character.body_parts.iter().map(|p| p.damage).sum()
character.pain = pain(damage, character.will)
Blood loss (red)
Unbandaged wounds will cause you to bleed out, which will eventually incapacitate you.
Fear (blue)
Morale only starts affecting incapacitation when it goes below 0, at which point each negative point of morale becomes fear, translating to 1% incapacitation.
Fatigue (black)
This does not significantly accumulate in the course of combat, but is more a function of marching all day or going too long without sleeping. This probably has a threshold after which it starts applying nonlinearly ~halfway through the day.
Penetrating
Each piece of armor has a "resistance" and "padding", both are in terms of joules. When attack connects, the imparted_joules is subtracted by the resistance to determine how much energy penetrates the armor, if any. Weapons also have a "penetration" coefficient. The actual resistance used for the attack is: $$ finalResistance = resistance-flexibility\cdot{resistance}\cdot{penetration} $$ Penetration coefficient examples:
- Clubs: 0.1
- Maces: 0.5
- Swords/axes/musket ball: 1.0
- Broadhead arrows or spear: 2.0
- Mail breaker, rapier, or bodkin arrows: 4.0
Any energy that penetrates is then applied as cut damage.
Energy which is absorbed by the resistance, is the blunt energy. 50% of blunt energy is applied as unbalance, as described above, and the other 50% is subtracted by the padding to determine blunt damage.
Damage
Cut
Cut damage is divided by the penetration coefficient before being applied. This represents the greater surface area of flesh that is being torn up. Essentially, this makes axes and swords particularly ineffective against armor, but does extra damage against flesh.
Calibration:
- 80kg male's forearm is about 1.2kg
- A 20j direct hit dagger stab against an unarmored forearm should do just enough damage to incapacitate
- The point of having more powerful attacks is not to do more damage to flesh, but to get past armor
- A knight in full-plate still should be vulnerable to a mail breaker or bodkin arrow in the gaps between plates which are guarded only by chainmail
- A 20j stab from a mail breaker should just barely be able to penetrate chainmail and damage flesh
Blunt
Halbe: We may want to distinguish between bruising and bone fracturing, perhaps by picking an arbitrary amount of blunt damage energy after which it starts to fracture the bone.
Halbe: I'm not certain what a good physical base measurement is that we could use for mapping kj of energy to damage. Damage might be best represented as how many kgs of mass have been rendered inoperable, but its not clear to me how to convert between the two. Ultimately though, the damage value relevant to stats maps "0" to "gains no function from the body part" and "1" means "body part is fully functioning", so the "displaced kgs of mass" would itself be an intermediate value not displayed to the player.
Durability
Each material has two numbers relevant to durability, one is durability itself, the other is "resilience". Resilience refers to how much durability damage the armor takes from hits which do not penetrate. $$ DurabilityDamage = 1 - resilience * (ImpartedJoules - threshold) $$ Extremely hard and brittle materials, such diamond, have 1.0 resilience (but low durability). Solid, ductile materials which deform plastically have very low resilience (like metal plate). And most flexible materials have fairly high resilience, since they are able to absorb a lot of the force as they bend.
Examples
(resistance, padding, durability, flexibility, brittleness)
Halbe: These numbers are not super well thought out
- 3mm steel breastplate (120r, 60p, 1000, 0, 0)
- Steel chainmail (70r, 40p, 1000, 0.8, 0)
- Padded gambeson (60r, 40p, 250, 0.3, 0.6, 0)
- 3mm steel brigandine (100r, 40p, 600, 0.4, 0)
- 7mm wooden shield (100r, 20p, 100, 0.1, 0.9)
Strategic
When traveling, the party has a detection radius and a perception multiplier. The detection radius is the radius at which an enemy with a perception multiplier of 1.0 will detect you.
The detection radius is mostly based on party size versus the party member with the highest stealth score, who is ostensibly scouting ahead of the rest of the party. But every party member's stealth score does contribute marginally, which could mean multiple scouts if there's multiple with relatively high scores or just ensuring that everyone avoids leaving tracks.
The party perception multiplier should essentially give more weight to the party members with higher stealth, as they are further ahead, and is fundamentally based on their eyesight attribute.
If a party encounters an enemy party which does not detect them, they can choose to fight, sneak past, or take the long way around. The long way is guaranteed to succeed, but adds the most travel time. Sneaking past checks the stealth of all party members equally, so the weakest link can get you caught. If they choose to fight, then enter a tactical scenario in which the enemy party does not yet detect the players.
Tactical
The players start positioned relative to their stealth skill, essentially far enough away that enemies do not detect non-scouting party members regardless of line of sight.
For the MVP, we'll put some effort into the detection algorithm, accounting for light level, line of sight, and modify footstep sound by stealth check versus weight. But we aren't going to have a super detailed stealth AI. No patrol routes, search pattern logic, footprints, or enemies realizing that their allies are missing. At most, if they see a dead body they get a bonus to their ability to detect enemies due to now being on high alert. But in the future, there will be lots of opportunities to make this system more robust.
When an enemy does not detect you or for a short reaction-time window after they do, they are unable to dodge. This translates to a significant surplus of accuracy, allowing you to perform instantaneous kills on less-than-fully armored opponents or bypass the armor of fully-armored opponents.
Even an instantaneous takedown creates some noise, so unless nearby enemies are asleep this is typically just going to begin combat rather than allow you to take down an entire enemy camp in stealth.
If you do not manage to kill your target before their flat-footed timer has passed, they will alert nearby allies