A Better City of Heroes

I guess it’s CoX week at the blog, because I’ve got more MMO stuff I want to talk about and I’m gonna use the example of CoX to talk about it. This time I’m going to talk about how to balance the needs between having a massively multiplayer population while making the player feel like they aren’t totally insignificant.

I’m using CoX because the basic tropes of super heroes are really well known, so whether you know this specific MMO or not, it’s quick and easy for me to explain it to you. The Hellions are a street gang of demon worshipers, Aurora Borealis is a super hero of some description, King’s Row is the Gotham City themed neighborhood in Paragon City, the eponymous city of heroes, and not only are you all caught up on what you need to know for me to explain a mechanic revolving around Hellions, Aurora Borealis, and King’s Row, but I probably could’ve just dropped those proper nouns straight into an explanation without any further context and you would probably figure it out. If I were doing Guild Wars, my favorite MMORPG, I would at minimum need to drop in asides that devourers are giant scorpion wildlife, that grawl are low-level enemies with primitive tech and fulfill the role of goblins in some other fantasy settings (but not the ones where goblins are high-tech crazy inventors), and that the norn are eight-foot tall vikings who turn into bears. These explanatory asides are generally good practice but once I get into the flow I often forget them, and in City of Heroes, that barely matters, because you can probably figure it out from context.

As I explained in my introductory post about a better City of Villains, City of Heroes writing actually works pretty great as-is. You are a hero, you show up to a place, there are a bunch of people with exclamation points over their heads who need help, and you punch their problems until they go away. Whether or not any specific mission chain is fun, boring, or frustrating depends entirely on the writing of that specific mission chain. Many of them are good, a bunch of them (especially the minor ones that have been there since launch, which clearly received little attention) are kind of dull, but almost none of them make you feel like you’re getting the opposite of the role you expected to inhabit.

You’re a hero, and at worst, you end up doing routine and kind of boring hero work where you run around bouncing Hellions off the street until your contact calls you up to let you know that, although their spawn rate is totally unaffected, you’ve totally got the Hellions running scared. And most of the time you’ll be doing something like save a kidnapping victim or confiscating a bunch of death rays or something else which feels like you’ve saved the day even though you haven’t made a noticeable dent in regular street crime. Plus, the criminals in CoX often spawn actually doing crimes, not just standing around minding their own business. There’ll be a cowering civilian in front of them while they make threatening gestures, or they’ll be struggling to snatch a purse from someone, or whatever. The basic limitations of an MMORPG do still rear their ugly heads, but CoH is generally quite good at mitigating them.

But we can do better. So the evil witch, apparently satisfied with my work in the beta timeline where I revamped City of Villains, is warping me back even further to, I dunno, 2001-ish, when City of Heroes first entered development, striking Jack Emmert dead and giving me total command of all his resources right after his project got greenlit, and offers me some kind of reward for actually playing along, just to stop me from defecting since at this point it seems like she might spend the rest of my life time tunneling me to different video game projects, possibly all headed by Jack Emmert, in order to get me to redo them with the benefit of hindsight.

Because we’re in 2001 (I don’t know when City of Heroes entered development, but I’m gonna say 2001), we can’t make a more action-oriented combat system. Ping time just isn’t good enough in enough parts of the world for that to be reasonable. People are gonna lag, and that’s annoying enough in a cooldown-based combat system. In a timing-based system, it’s unplayable. If I were on an actual CoX dev team at some point, I’d probably know some legacy code that would make it easy to add new powers or character creator items down the road, but I don’t know any of that, so I’m just going to tell the team that having lots of powers and character customization items is essential to success and hope they can manage as well this time around as they did in the alpha timeline.

No Fifth Column, though, we’ll start with Council right from the start. Not only is Fifth Column a dumb name to anyone who knows what the actual origin of that phrase is, we’re gonna want to sell this game in Germany eventually, and when we do people are going to be nervous about having overt Nazi references. These worries will ultimately prove to be baseless, but rather than try to convince anyone of that, I’m just gonna say we have generic-brand fascists right from the start. Also, we need to save ourselves and our players a ton of headaches and make our engine one that’s easy to build environments in. Players in super groups and also, y’know, level designers are gonna want to make environments easily and we need to make those tools for them. We can sacrifice any or all of Boomtown, Crey’s Folly, and Dark Astoria on that altar – hazard zones are a dumb idea born from an era of MMORPGs that was already dying in 2004. We’re leaving Perez Park in, but only because its position in the city is central, so if we removed it we’d need to put something else there instead, so let’s just have it be Perez Park but also put actual content there. It took until Issue 17 in 2010 for the team to figure out how to get one character to give two task forces, which resulted in the infamous Positron task force being massively long and arduous to complete – and it’s the first task force in the game! I have no idea what the code fix was, and I’m not gonna bother trying to figure it out. We’re just gonna give Positron a sidekick who stands right next to him and gives out part one, and then Positron himself gives out part two.

But our big change here is in NPC behavior.

Hideouts

In a standard MMO, including CoH at release, enemy mobs spawn in, sit around looping the same animation (spray painting a wall, mugging someone, loitering, whatever) until a player comes along to beat them up and take their lunch money. After they’re defeated, they’ll respawn after a certain amount of time. Some modern MMOs are smart enough to have the respawn set to happen at a rate based on how many players are in the zone, but most MMOs, and certainly most MMOs from CoH’s era, just have them respawn at a fixed rate, with high-traffic areas like newbie zones having a high rate of respawn, to the point where you can finish clearing a street of bad guys, turn around, and find that half the street has respawned behind you.

We’re not gonna do it like that. Instead, we’re gonna program each zone in the game with a number of hideouts. There’s gonna be a lot of hideouts, because they don’t need much gameplay to them. Whenever we have a mission that says “go to the Skulls’ hideout and beat up their leader!” we’ll go ahead and have that be attached to a door on an actual Skulls hideout, but if we end up with half the hideouts being associated with no missions, that’s fine. Those hideouts can still be enterable, but we’ll just have one generic hideout for each basic building type (i.e. “warehouse,” “abandoned office,” “sewer,” etc.) and copy/paste it for every location that isn’t getting a unique hideout. The generics need to be small, too. Like, three rooms small. Generic hideouts are boring copy/pastes enterable mainly just because it’s slightly more immersive to be able to go in the place that’s spawning bad guys and see what they’re doing in there, so we also want them to be very small. Then we’ll stamp them down one every couple hundred feet until we have a nice, even distribution across the zone. Each zone should have at least a dozen, probably two or three.

When bad guys pop out of a hideout, they will follow this psuedocode:

  1. Look around to see if any heroes are within aggro distance. They have a regular, fairly wide aggro bubble for heroes who are their level or lower (i.e. heroes for whom they appear as white, yellow, red, or purple enemies), two progressively smaller aggro bubbles for heroes who are one or two levels higher than them (i.e. heroes for whom they appear as green or blue enemies), and no aggro bubble for heroes who are three or more levels higher than them (i.e. heroes for whom they are grey enemies). If a hero  pops their aggro bubble, they attack and don’t worry about where to go next until there’s no more enemies nearby. Otherwise, GOTO 2 (but run 1 again every second or so to check to see if a hero has popped your bubble). Oh, and add something in here that allows an NPC to scan as friendly to some heroes and hostile to others. We’re not gonna actually use this feature, I just want it around in case we ever hypothetically develop a standalone expansion for playing super villains and want the option to join one of these gangs.
  2. Look around to see if any NPCs from other groups are at the address, where “address” here means a fairly small area (no more than maybe 50 yards across) which is not visible to players and used only to direct AI movement. Each zone will probably have over a hundred addresses, and the travel time between one and another is probably going to be something like thirty seconds. If there are enemy NPCs at the address, engage them, no matter how bad an idea this is. Don’t worry about where to go next until there’s no more enemies nearby. If there are no enemy NPCs at the address, GOTO 3.
  3. Double check to see if your enemy group is on red alert. If you are, immediately path to the nearest hideout in the affected neighborhood. If you’re not, GOTO 4.
  4. Double check to see if they’re at an unoccupied hideout or a hideout belonging to an enemy faction. If so, walk into the hideout and take it over. If the hideout is empty, this is immediate. If it’s occupied by an enemy gang, it’ll trigger a “gang war” status for about ten minutes, at the end of which it’ll flip to whatever faction last sent a guy in through the door. Or, if we want to be more accurate about it, we can keep track of how many guys went through the door during the timer’s duration, and flip it to whichever enemy group sent in the most guys. This despawns the NPC and causes the hideout to flip to their faction. If they’re not in the immediate vicinity of an unoccupied hideout, GOTO 5.
  5. Look around and see how many bad guys of their same group (i.e. Hellions, Skulls, Crey, whatever) are in the address. If there’s few enough that the address isn’t considered full, initiate a standby animation. If the address is full, GOTO 6.
  6. Run some kind of brief idle animation (like checking a phone or looking around or something) and randomly select one of however many pre-determined paths their address has connecting it to another address. Walk that path to the next address and GOTO 2. The idle animation helps make it look less weird if, upon reaching the next address and running through the logic chain again, the mob randomly selects the place they just came from and heads there. Instead of spinning around at a seemingly random point and walking back, the mob will stop, check their phone or something, and turn around.

What’s up with that red alert thing? To explain that, I need to explain spawning logic. Each enemy group in a neighborhood (which is a sub-region of a zone – each neighborhood has its own level range which is usually just 2-3 levels wide, within the greater 5-10 level band of the zone – loading screens break up zones but not neighborhoods) spawns bad guys at a rate based on the number of players in the zone. Two things to note here: One, the spawn timer is per neighborhood, not per hideout, which means enemy groups do not spawn more rapidly as their territory expands. As a gang controls more hideouts, the average rate they spawn mobs from each individual hideout drops, and vice-versa. This means gangs with few hideouts in a neighborhood should be able to expand rapidly into the turf of gangs with many. And two, the spawn rate is based on players per zone, not players per neighborhood, partly because we’re already tracking players per zone for other reasons so it’s easier to do it that way, and partly because this means players can concentrate forces and clean up a neighborhood if that’s something they decide they want to do.

Whenever the spawn timer triggers, every enemy group in that neighborhood will:

  1. Double check to make sure the total NPC population limit hasn’t been reached. If it has, do nothing. This place is totally overrun and has no need of new spawns. If it hasn’t, GOTO 2.
  2. Pick a hideout randomly from a list of all hideouts still belonging to the enemy group in the neighborhood and spawn some bad guys from it. If this works and the gang was on red alert before, take them off red alert, and increment the zone’s NPC population by 1. If no hideout belonging to the enemy group can be found in the neighborhood, GOTO 3.
  3. Pick a hideout randomly from a list of all empty hideouts in the neighborhood. This hideout is taken over by the enemy group. Enemies spawn inside as appropriate, but no mobs are spawned on the map yet (although this hideout will now begin spawning bad guys like normal). If this works and the gang was on red alert before, take them off red alert. If there’s no empty hideouts in the neighborhood, GOTO 4.
  4. Put the gang on red alert in the zone. As mentioned above, all mobs of the same gang in the zone will prioritize moving to the nearest hideout in the neighborhood they’ve been cleaned out of, and prioritize it so high they won’t stop to do anything else but fight heroes or enemy mobs.

Enemy groups aren’t hostile to each other by default, but can have any number of enemy groups set to hostile. For example, Hellions are hostile to Skulls due to an ongoing rivalry, and they’re hostile to Trolls and the Family for being Skull allies, but they’re not hostile to Tsoo, or Outcasts, or whatever. The computer doesn’t know the fluff reasons for the animosity, but it knows that Hellions will attack Skulls, Trolls, and Family on sight and vice-versa, but not Tsoo or Outcasts. Since they’re not hostile to each other, Skulls and Trolls will path into each other’s territory without stopping to fight, and might end up finding an empty or partly-empty address deep in one another’s territory to engage their idle crime animation. That’s fine. They’re not enemies, so there’s free movement between them, so they semi-regularly show up in each other’s turf. That might occasionally lead to enemies being seen far outside their normal turf, and that’s also fine. Sometimes a much higher or lower level enemy for the neighborhood will turn up, and this is still fine. It won’t be the norm, and they’ll still be within the level band for the zone, even if not for the neighborhood.

Some enemy groups won’t use certain hideout types. For example, the Lost and the Vahzilok will both use sewers, but regular Hellions and Skulls won’t. Clockwork have no use for caverns because there’s nothing to salvage there, and Circle of Thorns use caverns almost exclusively because nothing else connects to their underground home in Oranbega (except sewers, but they’re way too dignified for that). Additionally, some hideouts might have different maps based on what group controls them. When Hellions move into an office building, you get all the fires and pentagrams, when the Family moves in, it becomes a nice and shiny mafia front, and when Skulls or Outcasts or whoever move in, you get a standard abandoned office building.

Then there’s the police. The police are basically just a gang who spawn from police departments instead of hideouts. Police departments are much more rare (each neighborhood usually has just one) and police spawn from them less often (though when they do spawn, they spawn a lot of guys at once). When the cops come to an empty hideout, they don’t occupy it, and when they come to an enemy hideout, they make it empty. The ace up the cops’ sleeve, of course, is that they’re green dots whom the player characters will not (indeed, cannot) attack. When there’s a bunch of players in the neighborhood thinning out mobs, the cops get ahead and empty a bunch of hideouts. The police spawn rarely enough that they will probably not make much headway on their own – mainly they exist to clean up the gaps so that players can clean up a neighborhood without having to personally hunt down every mob and hideout.

Finally, occupied hideouts will sometimes catch on fire, suffer a drug overdose, or in some other way appropriate to their occupying faction draw the attention of non-police emergency services. Emergency services gets dispatched, and after a fire truck or an ambulance arrives and sprays water on it for a while or goes inside and then comes back out with a guy on a stretcher, the hideout becomes empty. This happens once every hour-ish and gives destroyed enemy groups a chance to get back in the game if they are, for some reason, consistently unable to find an empty hideout to get themselves back on the map.

Heroes and Hideouts

The outcome of this logic should be that gangs take and lose territory organically and travel around the overworld map filling it up in a mostly sensible and dynamic way. This is already slightly more interesting than normal, and allows players to clear out a city street and for that city street to stay cleared while replacement mooks spawn from a hideout somewhere else. It’s not enough to really justify the cost of development, but it’s already a solid improvement over the standard MMO method. Really, though, if this is all we wanted, we could make it happen by having enemy spawns halt until there are no more players within a certain distance of the spawn point, and it’d be way easier. This system is mainly good as a foundation for other, cooler things.

Firstly, we’re going to have missions associated with as many hideouts as possible, with different missions for each enemy group in the neighborhood. Now, the density of hideouts is driven purely by what makes the best balance of enemy spawns, like, we might need more hideouts in a place so that we can spawn enough enemies to keep the population up so there’s actually bad guys there to fight when the heroes come along. This means we’ll probably have lots of generic hideouts that don’t have any unique missions associated with them. This is fine. We can incorporate them into patrols, where defeating a mook will sometimes drop an item that places a randomly selected hideout currently controlled by that mook’s enemy group on your hideout. Hideouts are not otherwise marked, so now you can go smash up a hideout. Compelling gameplay? Not especially, but I think “clear out a [group] hideout” is a better mission than “defeat 10 [group],” so long as we make sure the drop rates are such that you end up beating up about the same number of guys. Instead of killing ten rats, you go on a real patrol and end up measurably decreasing the influence of that enemy group in that area.

Each zone is gonna have a couple of unique hideouts, though. By my estimate, each zone in the current game has at least a half-dozen or so unique building layouts used for its “door missions,” which are missions in which you enter a door into an instanced zone. Each of these can be turned into a unique hideout, with a unique mission attached to it.

For example, in the alpha timeline’s Atlas Park, there’s a mission chain involving the Vahzilok, mad doctors who chop people up and stitch them back together in an effort to make immortal Frankensteinian abominations. You discover the Vahzilok kidnapping people and have to break into a number of Vahzilok sewer maps to rescue hostages, slowly uncovering what they plan to do with them, which introduces new players to what the Vahzilok are about.

This comes with several unique sewer maps, which can be used as unique Vahzilok hideouts. When you enter them, they’re big, and they’ve got hostages they’re preparing to turn into parts or a medical lab where they’re reassembling bodies or whatever. If you get a clue from a random Vahzilok mook pointing to them, the clue will mention the kidnappings or the mad scientist conference. If you ask the police what’s up while this sewer hideout is occupied by Vahzilok, they’ll tell you about Vahzilok kidnappings in progress. If the hideout isn’t occupied by Vahzilok, they’ll give you a different mission about the Vahzilok trying to set up in the area, moving in medical equipment through the sewers and fighting police. If the Hellions are doing well, you get a mission about them attempting a summoning ritual. If they’re doing poorly, you get a mission about the Skulls moving in to try and finish them off. If Clockwork is doing well, you get a mission about raiding a hideout they’ve converted into a factory. If they’re doing poorly, you get a mission about defending a warehouse they’ve broken into to strip for parts.

But recall that we have several unique sewer maps in Atlas Park. Vahzilok are the only enemy group on the map who actually use those, which means with two unique sewer hideouts, the Vahzilok can have three different states between “on the run” and “very successful,” or four if we care whether or not it’s specifically Sewer A or Sewer B they control. When the Vahzilok are powerful, we can have a mission about their receiving funding from Joseph Botte, an actor whose brother was killed in a clash between heroes and villains, and who’s now terrified of death and thus supporting their pursuit of immortality. When they’re middling, we can have the mission where they’re kidnapping victims to try and further their research and build up their zombie army. When they’re weak, we can have the mission where they’re trying to move more material and personnel in through the sewers.

The Clockwork and Hellions have an even more interesting relationship, in that they both want the same warehouses and office buildings as the other. This means that when Hellions have no unique hideouts, that might be because Clockwork has captured all of them, and vice-versa. Perez Park has a gang war between the Skulls and Hellions as a major theme, and this system can reflect that very easily.

Finally, we want the appearance of the zone to visibly change somewhat when there’s lots of empty hideouts, especially empty unique hideouts. We don’t want the actual layout to change, as that is both costly and kind of absurd (these changes will happen every ten or fifteen minutes). But what we can do is spawn different pedestrian NPCs. When the number of occupied hideouts (especially uniques) is very high, pedestrians are suspicious, rude, walk with hunched shoulders, and look a bit shabbier. When the number of occupied hideouts (especially uniques) is very low, pedestrians are friendly and polite, stand tall when they walk, and look more cleaned up and taken care of. Exactly how that works will depend on what kind of neighborhood we’re in. King’s Row is the Gotham-esque part of town, which means that when crime is low, you’re gonna get more punk rock and goth style clubbers who give enthusiastic “rock on” greetings to passing heroes (in text, because it’s 2004 and we don’t have voice actors – passers by have lots of these kinds of random chatter in the alpha timeline’s version), some Tim Burton-esque spooky pale businesspeople in dark suits with knee-length coats, and the poor are going to be wearing heavy winter coats to keep out the chill. When crime is high, the poor become more common and start taking on more of a fingerless-gloves-and-scarves Dickensian cold look, the clubbers start yelling insults at passing heroes, and the businesspeople start dropping veiled references that they’re in it with organized crime, like “I need to run, I’m late for a meeting with an…associate” kind of thing.

The ultimate experience we’re going for is that a hero can arrive in a neighborhood and, if they’re familiar enough with the zone’s culture to tell from the pedestrians how dire the situation is, see at a glance how much help the place needs. If it needs a lot of help, they can get to work and see a measurable decrease in crime. The spawn rates are pegged so that spawns are consistent per zone, which means a super focusing on a specific neighborhood will see results there (and meanwhile crime rages uncontrolled everywhere else, but hey, out of sight, out of mind).

Of course, at higher populations, this will break down a bit. If there’s forty other heroes on the map (2004 cannot realistically sustain much more than that before it has to make a second map anyway) then cleaning up crime is going to require more coordination, at least on the level of avoiding both neighborhoods that are choked with heroes and those with so few heroes that a single extra super wandering in won’t put a dent in the jacked up spawn rate from the zone. This mostly just asks the question as to whether a super hero MMO is really a good idea. Can you really be all that super when there are thousands of other supers? Or even hundreds? Wouldn’t this be a better fit for a game with 30-40 people per server, you know, enough that there’s a bunch of other heroes out there, but not so many that there’s one on every street corner? The answer is probably yes, but this whole concept works just as well for orc war camps in a bog standard fantasy game, so we can just use it there instead if we really think this whole “super hero MMO” thing isn’t going to work. And really, the alpha timeline has demonstrated that super hero MMOs work fine, albeit granted with the possibility that an online super hero game with a mid-size population limit might work better.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s