A Walking Skeleton
At long last I've implemented a first basic version of fighting. There aren't any significant choices to make as a player yet but I thought it might be interesting to talk a little bit about how it works and where I'm planning to go with it.
The first part of implementing this was to build a core timer system. The MUD has a heartbeat and sends a TimerEvent
once per second. Objects annotated with @EventListener
can register to receive messages once per second, minute, hour or day. The first use of this was for time notifications, but I was always mostly thinking about using it for combat. There's an interesting problem with timers though. Agony Forge is designed in such a way that it's possible to run more than one server at a time if you need horizontal scaling. You don't want every server to run its own timer because every server you add would add its own timer events, effectively speeding up time! I solved this with a poor man's "election" system between the servers. Only the server whose UUID is first alphabetically will create timer events. The events are put onto the message queue where any of the servers can receive and process them. So as you scale by adding more servers, the processing for fights gets spread out between all of the servers but only one of them runs a clock to keep things ticking. If that server disappears, the next one at the top of the list will start.
Once I had created time, I created a HIT command. The game rules are based on ICRPG's combat system (used with permission), as are the stats and dice rolls. In a nutshell, you roll 1d20+STR to attack and you have to beat 12+DEF to hit. In the future some types of attacks (e.g. ranged or magic) could use something other than STR, and things like environmental conditions or physical conditions could change the 12 to a higher or lower target. Equipment will be able to change your stats as well.
After the initial attack each character gets a turn to attack. Turns happen once per second. The HIT command checks to see if a Fight
object exists yet between the attacker and the defender, and creates one if there isn't one. The FightService
listens to timer events once per second, walking through each Fight
and making each character perform a hit automatically. The hits happen in reverse order: defender first, then attacker. That's because when you type hit goblin
the command performs an attack for you immediately. When the FightService
kicks in about a second later, it's the goblin retaliating first before you can attack a second time.
All in all I think it's a pretty typical way for MUD combat to work and a good skeleton to start hanging options and choices off of to make a fun system.
Fleshing it Out
Death
The most obvious thing this system needs is death. In the current implementation when you reach 0 hit points both combatants are instantly restored to full health and the fight stops. Fights should result in corpses, but there are two small problems I need to solve before I get to that. One is that the corpse is the first "system item" the game needs. By that I mean that the game needs to know what item number is the corpse, and there must be an item to use as a corpse. So I need to make something that can load a corpse item into the game on the first boot, and I haven't done that yet. The second issue is that there is no such thing as a container yet. Corpses need to contain all the deceased person's loot, and so I need to make items that can be containers and commands to look inside, get things from, and put things into containers.
Found Weapons
Some items work well as weapons and others don't, so it's not sufficient to treat every item as a weapon equally. I've got to figure out how I want item types to work, and I've got a few different ideas to choose from. It could be based on weight, or handles, or maybe "weapons" work best as weapons and other things work less well. I'm not sure yet. I like the idea that everything can be a weapon but maybe there's a sweet spot between being too light or too heavy, or too big or too small, or too bulky or awkward. I also like the idea of knowing any item's sharpness and pointiness to determine whether it deals blunt, slicing or stabby damage. I'm just not quite sure yet how to turn that into a practical system.
Choices
A key part of what makes a combat system interesting and fun is choices, and being able to do stuff that other characters can't. In MUDs the normal hits typically go automatically but you can also perform your character's particular skills and spells and stuff at the same time. In tabletop games like ICRPG the choices come from how open-ended roleplaying games are: you just say whatever you want to do, the GM tells you to roll something and figures out what happens as a result. Interestingly, ICRPG does not have "skills" in the typical sense, because they expect you to just say what you want to try to do. Want to backstab someone in combat? Roll and see if it works! Want to shoot that guy in the eyeball? Roll! Want to run away? Roll for that too! In other MUDs all of those things would be commands, probably tied to character skills and your stats. In our case there are a lot of them that anybody could attempt but would require a roll to see if it works. But I'm also thinking about hiding some of them because not everybody is a generalist and some things in life must be learned. Maybe you need to find a particular trainer to teach you a combat move. Maybe you only get it once your character reaches a milestone. Maybe you have to join a guild or a secret society of some kind. It needs more thought before I start working on it, but I want an advancement system that is a bit realistic and can't be "solved" by following instructions from a Wiki, but also doesn't gate progress by making you grind. There's got to be a middle ground there.
Environment
Environmental factors are a big part of the ICRPG book when it comes to combat, and I want them to play a big role in combat in Agony Forge as well. I don't want fighting to just be back and forth automatic hack and slash in one room. I want options to run and chase, to fill the place with elements like water or lava, to summon or dispel help, to hide and seek. That means rooms need to be able to have lots of different environmental conditions, magic needs to be able to modify a lot of them, and regular non-magic characters should be able to use their wits and brawn to do the same. Generally speaking, typing the KILL command and letting the fight run automatically should be a recipe for getting killed. Surviving should take some strategy.