Contexts & Control Modes ------------------------ There are 2 contexts: * Party * Combat In party context: * A single icon in the center of the screen represents the entire player party * A single icon represents npc parties (which consist of one or more characters) In combat context there are three different modes of control: * Solo mode, where a single party member moves while the others do nothing * Follow mode, where the player controls the party leader and the other member follow him/her/it * Round-robin mode, where the player moves each party member in turn Place Types ----------- And there are 4 types of places: * Wilderness (party mode) * Town (party mode) * Dungeon room (combat mode) * Temporary combat map (combat mode) Place To Place Movement ----------------------- U5 is the basic model. Linux cloned unix, nazghul is trying to clone u5. But there is at least one feature of u5 I cannot stand: first person dungeons. So those have to go. In u5, the player walks around the FP dungeon and when he enters a room the view switches back to a sane top-down combat map. Things get interesting when the player leaves the dungeon. But first, note that all party member must exit the same way. This simple rule presents a problem for nazghul: not all party members necessarily share the same passability rules. So, for example, if a floater crosses a body of water and exits off the map, what happens if the other party members can't get across the water? So this problem needs to be solved. And I think the way to solve it is to do a check before allowing the first party member to exit. The check consists of running a pathfinding alg from each other party member to the exit point. If a party member can't find a path the player gets a message and the exit is denied. This is a simple, rather stupid way to do it (it ignores the possibility of mechanisms or spells being able to create passages, for example, which could lead to pathological cases). And things get even hairier when we consider that a passability check to the destination is also necessary, which I'll cover below. Now u5 did not have any of these issues because everyone in the party had the same exact passability. If I can't figure out any other way to do it, that will be my solution as well. Now, let's consider what happens when the player party exits a dungeon combat room. There are 3 possibilities. First, the party may exit to a dungeon corridor tile. If the tile was occupied by an npc party then combat on a temporay map immediately ensued. Upon exit from combat the party was on the same exact tile (exiting temporary combat maps in a certain direction does not move the party to the tile in that direction - a sensible strategy which I will emulate). Next, the party may exit to a dungeon corridor tile with a pit or a field. I've never seen a case with an impassable energy field, so probably u5 maps were designed to avoid that tricky case. In general, corridors outside dungeon rooms were gauranteed to be passable. Unfortunately I don't have that luxury, due to the principle of freedom of expression. (The Principle of Freedom of Expression states that I don't have any control over the scripts fed to the engine.) Finally, the party may exit to another dungeon room. Note that in u5 entrance was gauranteed in all dungeon rooms. Again, u5 controlled the script, the party's passability was hardcoded, and everyone in the party had the same passablity (and the number of party members had an upper limit). Now, I want to get this damned thing finished. And I'm willing to sacrifice some dearly held feature ideas to make that happen. Here are the features which are causing problems: * The party will have a fixed passability mask specified at load time. This mask is a property of the party. It is not derived from the party members' masks. It is fixed. The purpose of this is to allow the engine to sanity-check combat map and dungeon room entrances at load time. If a map fails the check the engine refuses to load the game. * The party will have a fixed upper limit on the number of party members specified at load time. Again, this is to allow sanity-checking of entry zones in combat and dungeon room maps. * Combat maps and dungeon room maps must have an "entry zone" on all four sides. Even if the map is never placed such that the player party could possibly enter there, it doesn't matter. All four sides will have an entry zone. The zone must be able to fit the maximum number of party members with the party passability mask. The engine will be pretty flexible with zones. The algorithm will first search, starting at the midpoint of the map edge, for a passable tile. Once it finds one it will then attempt to pathfind from there to n other passable tiles, where n is the maximum number of party members. So the zones need not be square regions centered on the map edge or anything like that. Furthermore, combat maps will not be persistent, even in dungeons. They will be loaded afresh each time they are entered. * I'll disallow placing autoportals in the entry zones. This will be checked at load time when the portal is declared. * Everyone in the party will have a superset of the party passability mask. It's ok if they have extra passability (permanent or temporary). * Party members cannot teleport out of dungeon rooms. They can teleport within dungeon rooms, and I'll allow teleport spells which move the whole party at once. * Portals which lead into dungeon rooms must have an entry zone around their destinations. This will be checked at load time when the portal is defined. Now given these limitations we can solve all of our problems. The Exit Problem ---------------- All party members must exit a dungeon room the same way. (I'm going to lift this restriction on temporary combat maps because the party will not change location upon exit). If a party member attempts to exit via an edge or a portal the engine will check the destination place and location. If that place and location is not passable to the *party* then I will reject the move (note that if the tile is occupied by a non-hostile npc party it is not passable). If I cannot pathfind from any other party member to the exit point then I will reject the move. Exit From Dungeon Room To Wilderness or Town -------------------------------------------- There are several possibilities here. But impassability is not one of them - that's tested in the Exit Problem. First, the destination tile might be occupied by a hostile npc party. In this case combat begins immediately on a temporary combat map. Upon exit from that combat the party will occupy the destination tile. Next, the destination tile might contain an automatic portal. The standard rules for autoportals apply in this case. Finally, the destination tile might be empty in which case the party simply lands there. Exit From Dungeon Room To Dungeon Room -------------------------------------- Since entrance to the next room is guaranteed, there should be no issues here. Note that upon entrance to a dungeon room (or regular combat) the player party is positioned first and then the npc party. That should handle dungeon rooms. Towns are very similar to dungeons, except that the engine is always in party context in towns and combat context in dungeons. But in towns the party can still exit via a portal or by walking off the edge of the map. The exit rules from town are the same (except of course the pathfinding rule for party members because we're in party mode). Entering Wilderness ------------------- * If the destination tile's terrain is impassable and there is no unoccupied vehicle there then entry fails * Else if a non-hostile npc party is there then entry fails (revisit: add a push mechanism?) * Else if a hostile npc party is there then the player immediately enters a temporary combat map. If combat succeeds then when it is over the party is on that tile. If an autoportal was there then it is ignored. * Else if an autoportal is there then it's ignored (revisit - necessary?) Entering Temporary Combat Maps ------------------------------ * If not all player party members can be placed then combat is denied. The npc party will not be removed from the map in this case. ---------------------------------- Moving In Party Mode -------------------- Possible outcomes: * blocked by non-hostile * fought combat * game over * couldn't enter combat * success * impassable * couldn't enter dungeon * noplace to go * blocked by vehicle * entered dungeon if the destination tile is occupied { /************************************************************************** * In older versions moving toward a hostile npc party was implicitly * interpreted as an attack. This may cause some user confusion when * moving from one place to another, depending on how other features are * implemented. Examples to consider are exiting town off a map edge, * entering town via a map edge and passing through a portal or other means * of teleporting. In all of these cases the user cannot see the * destination when deciding to move, but he expects the move to take him * to a new place. * * One way to deal with this is what I have here: block the move (and let * the caller print a user message explaining what happened). I can think * two other ways to deal with this. One, let the attack happen. Two, try * to "bump" the npc out of the way to allow passage. * * Letting the attack happen opens up other problems we must solve: * What happens when combat is over - do we then run through this algorithm * again to see if the move now succeeds? What if the destination is an * autoportal entrance? * * Trying to bump also opens up more issues. What if the bump fails? Should * we allow any npc to be bumpbed? What about npcs in vehicles? What if we * bump them onto an autportal (or should that be disallowed)? * * Since these solutions require yet other solutions to support them, I * tend to disfavor them. *************************************************************************/ return blocked by npc } else if the destination tile contains an autoportal and autoportals are not ignored { /************************************************************************* * I give automatic portals higher priority than passability. This is * mainly to allow ships to have access to towns which are placed on land * but which may have a port. Passability should be determined by checking * the town map to see if it allows entrance, not checking the terrain the * tile is on. *************************************************************************/ if portal destination is a dungeon { if dungeon can be entered { return entered dungeon } else { return couldn't enter dungeon } } else { recur on portal destination with autoportals disabled if recursion resulted in combat { retry recursion and return results } else { return recursion results } } } else if the destination tile is impassable { if the tile has a vehicle (empty) and the player is not in a vehicle { move party to destination return success } else { return impassable } } else if the destination tile is off-map { if this place has no parent map { return noplace to go } else { /********************************************************************* * Yes, I'm making the following unconditional with no further checks. * The parent tile is _always_ and _unconditionally_ passable. * Consider everything that could make that tile impassable: * --Terrain on parent map... don't care * --Autoportals leading elsewhere... ignore them * --Npc's... they aren't allowed on town tiles in the wilderness, * and if one sneaks through ignore it * --Fields... unlikely, and don't care * --Vehicles (when player is already in one)... ignore them (and * don't allow player to abandon a vehicle over a town, otherwise * we can leak vehicles since consecutive abandonments will * clobber previous ones) * See notes on the ship problem in discussion #1 below. *********************************************************************/ move party to tile on parent map return success } } else if the party is in a vehicle and the destination tile also contains a vehicle { return blocked by vehicle } else { move party to destination return success } Exiting Dungeon Rooms --------------------- * You cannot exit dungeon rooms via edges. I know this differs from u5, but dungeons are just different from u5. Unlike u5, a nazgul dungeon room can be arbitrarily large. In effect a dungeon room is more like a dungeon level. * The only way in or out of dungeon rooms are portals or party teleport effects. * To avoid the stranded party member effect, dungeon exits will work like u6. First, the party must be in follow mode. When the party leader attempts to enter a portal all party members must be able to pathfind to the portal within N steps. If any cannot then entrance is denied. if party is not in follow mode or if any party members cannot pathfind to the portal within N steps { failed } else { call party move routine on portal destination (autoportals enabled?) case blocked by non-hostile { failed } case fought combat { retry } case game over { game over } case couldn't enter combat { failed } case success { success } case impassable { failed } case couldn't enter dungeon { failed } case noplace to go { portal connection error } case blocked by vehicle { failed } case entered dungeon { restart dungeon loop } } ---------------------------------------------------------------------------- Design Discussion #1: Stepping off a map edge ---------------------------------------------------------------------------- There are two ways to implement this. One way is to emulate u5, where stepping off a town map took the party to the wilderness map and the party was located directly over the town. Recall that in u5 when entering a town the party always appeared in town at the same entrance, so this was fine. Another way to implement this was suggested by Sam: stepping off the edge of town takes you to the wilderness and moves the party one tile in the direction of travel. Stepping onto a town makes the party appear on the map edge corresponding to the side of town entered from. It's a nice touch, but it is a bit of an iceberg. The advantages of this approach are: * It's more intuitive to the player * It allows games where a town blocks passages in the wilderness (for example a fortress town guarding a passage through the mountains) * Player's can save some time by entering a specific side to reach a specific part of town more quickly * Player's can avoid parts of town they don't like * It allows towns with ports and docks for ships to enter and exit from the wilderness, as well as foot traffic through a gate on another side of town The disadvantages are: * If the player does end up directly over the town in the wilderness, how does he enter and from which direction? This can be solved with a player prompt. * If the player tries to walk off a map edge but the move fails, what should the player see? One possibility is to move the player over the town in this special case, provided we can solve the reentry problem above. * If the player teleports onto a town, what should happen? One possibility is he does not enter the town, but may enter as noted above. Another is that he enters from the direction of travel, another is that he lands in the center (or the teleport fails). I like the first solution best because it's simplest. Example: the player tries to step off a map edge, but the tile in the direction of travel is occupied by a hostile npc party in a ship. 1. First the party is moved to the wilderness directly over the town 2. Next the party engages the hostiles in combat, using a combat map comprised partially of the terrain beneath the town and partially of the terrain beneath the hostile. Entrance to combat is not gauranteed, since the terrain beneath the town may be impassable to the party (the party may have entered the town through a portal). 3. If combat entry fails then the move is done. The hostile npc remains next to the town. 4. If combat entry succeeds then the party will still be on the town and the empty npc ship will be visible next to town. In general, I want to completely separate combat from movement - at least for version 1.0. In fact, I'm probably going to disable the implicit attack that occurs when you try to step on a tile with a hostile npc. Attacks will be explicit with the (A)ttack- command like u4/u5. [the ship problem] Another issue Sam and I discovered the other night is with passability on the parent map. We were in a ship on the wilderness and entered town while still on the ship. This worked because the edge of town we entered on had a tile passable to the ship. But exiting didn't work... the tile the town occupied on the parent map had land passability. Here's a disadvantage to the rule! But this needs to work. This is the reason I added the clause that moving off the edge of a town map _always_ works as long as it has a parent map. Ah... much simpler. ---------------------------------------------------------------------------- Design Discussion #2: Should the party move to the destination tile after succeeding in combat? ---------------------------------------------------------------------------- I'm thinking "no". U5 did not. And taking the opposite apporach might result in some surprises for the player. For example, if the hostile npc party was standing on an autoportal, after combat when the player party moves to occupy that tile should the autoportal be invoked? Consider what the player would see: first, he sees the npc party on the wilderness. Next, he attacks and sees combat. When he exits combat he expects to go back to the wilderness, but instead he is autoportalled somewhere. Confusing. Also, if the npc party left behind a vehicle then it would be most apparent to the player that they've just captured a vehicle if it's sitting next to them upon exit from combat. Furthermore, I can't think of a good reason to say "yes". My original reason involved exiting from towns, but with the outcomes of Design Discussion #1 I no longer think this is an issue. When the party exits town and encounters a hostile npc party then after combat they will be over the town, and are free to continue moving or to reenter. However, what if the party enters a portal but the destination tile contains a hostile npc party? If combat is entered, then after combat should the player still be standing at the portal entrance? Or at the portal destination? One way to work around that problem is to treat autportaling specially. Having the move routine return a result code is one way. When the party steps on an autportal the move routine calls itself recursively on the portal destination. If combat occurs the recursive call can return a code to that effect, and the calling layer can then do the recursive call again in the case of combat. Since the hostile npc party should be gone at that point the recursive call will "succeed". ---------------------------------------------------------------------------- Design Discussion #3: Complications when entering portals ---------------------------------------------------------------------------- What should happen when a portal destination is on impassable terrain? What if a portal itself is on impassable terrain? In the case where a portal entrance is really a town entrance, the passability of the terrain the portal is on should not be a consideration. Instead, the engine should check and see if the town edge in question has some passable terrain the party can be moved to. But what about other cases? It looks rather strange when the player can step from the shore onto a whirlpool - especially when the whirlpool is linked to another whirlpool in the middle of some ocean. Entering whirlpools on a ship makes perfect sense. But if the ocean is usually impassable to the party, what then? I think that except for the special case of town entrances the passability of the tile a portal is on should be a consideration. If the party can't leap into the ocean, they shouldn't be able to leap into a whirlpool. Likewise the destination passability should also be a consideration. On the one hand, it might be kind of fun to let the player drive a ship through a moongate and get marooned on dry land - because the player can always walk away. But letting the player get marooned someplace they can't get out of seems unfriendly. On the other hand, maybe I shouldn't be trying to make that decision for game designers. After all, it won't crash the engine. Ok, yes, that's a good principle to follow. Portal links are completely under the game developers control, so I'll leave it to them. Terrain passability will not be a consideration for portals, either on the source or on the destination. Well, I tried it and discovered that ships can turn when stranded. This is sort of disconcerting, so I tried to disable that by having the turning code check for impassable terrain. And then that broke the ship-exit-town problem! I still think that this is a good principle, though, so I'll simply permit turning while stranded. This will also permit the case where a ship portals to a stranded destination, but right next to it is another auto-portal, so the ship can still enter that autoportal and escape. Weird, but I'm not going to lose sleep over it.