How I write custom quests for Veure
Note: If MMORPGs are of interest to you, please read through this and answer the simple questions at the end.
I'm still diligently hacking away at Veure. About a year ago I wrote that I had 17% of the alpha tasks done. Given that I've added a number of alpha tasks (and pushed some back to beta), I'm relatively pleased that as of this writing, I have 81% of the alpha tasks finished, with over 90% of the commits by me. It's daunting single-handedly writing an MMORPG, but we've a developer who's been working on it and will be returning to it in June, so that's going to help. We're also looking at hiring a narrative designer to flesh out content. Writing a game is hard, but filling it with content? Hoo boy! It's the difference between outlining a novel and writing it (well, not exactly, but cut me some slack, eh?).
And that brings me to content. Much of $secret_mmorpg_name
(legal stuff, sorry) will be impacted by missions, but what are missions?
For most games with missions, they tend to be very linear. Do A, then B, then C.
- Gather ten Lightning Flowers
- Give them to Mage Mary
- Receive the Lightning Potion.
Boooorrrrriiiiinnnnngggg. In fact, missions (or questing) have become so standard in most MMORPGs that quests tend to fall into a fairly standard pattern of one of the following:
- Kill quest (kill X of Y)
- Delivery quest (a.k.a. "Fedex quest")
- Gather quest (gather X of Y)
- Escort quest (escort someone to destination)
Yes, sometimes you see combinations of the above, but what are those combinations? They're things like "gather information, deliver it, kill suspect, escort prisoner."
In other words, they're still linear quests, but in sequence. So much better!
No.
Quests in Veure are currently DAGs (Directed Acyclic Graphs). As a result, when you confront Hwang Woo about his shady cloning research (a hypothetical quest I haven't created), you don't just have to kill him. You could, potentially:
- Bribe him to stop
- Blackmail him to keep you quiet
- Take him prisoner and escort him to security
- Kill him
- Pretend you saw nothing
And so on.
In other words, missions have no restraints and your options can be as varied as a mission designer can imagine. Do you want to have a mystery that the player must figure out? No problem (Encyclopedia Brown in the 24th Century!). Do you want to accept a dodgy quest and later decide to take the high road or just be an evil SOB? No problem. We can make all of this happen with proper narrative design. While the missions, of course, can't be as open ended as in real life and most of the missions will likely be linear, we have the chance to open up a richer variety of game play than most other games allow.
So how do we do this?
Each mission is a state machine and to enter a given state there are preconditions you must meet. Some preconditions require that you be in a particular area, or in a room with a given NPC, but the feature I'm writing now requires that you take a particular action to enter a given state (or step, as we refer to them for missions).
I've previously written about using roles as partial classes and that's what makes this work.
In OO programming, you generally want to avoid a God Object. This is generally good advice, but when you're creating an MMORPG, the vast majority of behavior is driven by characters. Even if you have something like a box exploding, it's seen as a cheap deus ex machina if you don't give characters some forewarning. Everything must revolve around the character. Character, character, character. Narcissism is more than a virtue here, it's a requirement lest the game quickly becomes seen as random gibberish.
Thus, whatever class (assuming OO programming or something conceptually similar) represents the character takes on a lot of responsibility. Thus, the Character
class is practically forced to represent a God Object. Ordinarily this is seen as bad, but in some of my first attempts to distribute responsibilities and avoid God Objects I wrote monstrosities like this:
$mission->accept($character);
Thus, the responsibility to accept a mission fell on the mission itself, not the character. This is bad because missions don't accept characters; characters accept missions! Linguistically, this is the difference between SVO
(subject, verb, object) and OVS
(object, verb, subject). If you arbitrarily mix linguistic typologies when programming, you're going to confuse the hell out of maintenance programmers (/me waves at PHP). However, if you decide to shove every possible character behavior into the character class, you'll have this huge mess of a class that's hard to follow.
The latter concern suggests roles to separate behavior from the class, but roles are typically viewed a behaviors (or interfaces) that are shared amongst unrelated classes. I have struggled with this issue quite a bit and realized that there's no reason a role needs to be shared behavior. Think about roles: they're generally viewed as behaviors that apply to a list of classes. Think about a list. A list is "zero or more elements". A role suggests two or more classes you can apply it to. Obviously, a role you can't apply is dead code, so "zero classes" is right out, but why not a one-element role? Why can't a role be applied to only one class if you only (as of now) envision one class needing that behavior? I've taken the idea of roles and something called "partial classes" (generally a compiler artifact) and started implementing hand-crafted partial classes. Now developers can look at subsets of character behavior. Here is the current set of roles applied to the Character
class:
with qw(
Veure::PartialClass::Character::Combat
Veure::PartialClass::Character::Drug
Veure::PartialClass::Character::Inventory
Veure::PartialClass::Character::Mission
Veure::PartialClass::Character::Movement
Veure::Role::Cache
Veure::Schema::Role::ShipPiloting
);
I wrote the caching role and Yaroslav, one of our developers, wrote the ShipPiloting
role, but all of the others are true partial classes that only impact characters. Do you want to know how a character manages their inventory? Glance at the above list and you know where to find the relevant behavior. The same goes for missions, drugs, combat, and so on (note that the movement partial class might eventually extend to a true role, but I will not solve that problem until we encounter it). Using roles as partial classes allows me to take the possible related behaviors of a single class and group them logically. By using partial classes, this:
$mission->accept($character);
Becomes this:
$character->accept($mission);
That's much easier to understand.
So how does this help me write arbitrary, mission-only behaviors? In my Mission
partial class, I might have the following for "gossip" (this will actually probably be in a MissionAction
partial class):
sub action_gossip {
my ( $self, $args ) = @_;
my $chance = constrain .05, $self->local_reputation, .95;
if ( rand() > $chance ) {
$self->add_message( $args->{failure}{message} );
$self->change_local_reputation(
constrain -10, -1 * $self->level
);
return;
}
else {
$self->add_message( $args->{success}{message} );
return 1;
}
}
The above is a gross over-simplification of what's actually going on, but it shows the basics, In the JSON explaining the mission, I might have the following:
"action" : {
"label" : "Talk to bartender",
"method" : "gossip",
"success" : {
"message" : "Lunt? Yeah, he used to hang around here a lot, but stopped showing up a while ago. Heard he lives in the ruins."
},
"failure" : {
"message" : "I think you need to leave.",
},
},
Again, it's a gross oversimplification, but with this and the "missions as graphs" approach it means:
- For any arbitrary action, I can write a simple method
- Unlike graphic MMORPGs, arbitrary behaviors are easy
- Missions can be as complicated as any narrative designer can dream of
And this brings me closer to my business problem.
Sadly, while we're getting closer to the alpha, I still can't launch the marketing campaign due to legal issues with validating our trademark. When I do, I'll be releasing a marketing video (<snark>which is real fun when you want to produce a video of a text game</snark>) and creating a launchrock campaign and signing up alpha testers.
Questions
- Do you want to see more content like this?
- Is Veure a game you would be interested in playing?
- Do you want to be an alpha tester?
If you don't want to respond publicly, send me an email at ovid at allaroundtheworld.fr
.
Regarding your questions:
@gizmo_mathboy: duly noted :) I've added you to the list.
(god, it was painful to make this comment with the damned "timed out" errors)
Allow me to phrase my response in the form of a panel from a popular comic:
http://www.mspaintadventures.com/?s=6&p=003672
Here's another "heck yeah!" to all of your questions. :)
print "Yes\n" x 3;
Yes^3
Keep up the posts on this please! I look forward to playing this even though I haven't gamed in awhile.