Random thoughts about exits

I was looking yesterday at the code in CoreGrid.aslx (the map), and I ended up thinking that the way it's constructed is a bit strange. And that got me thinking that it's really odd that an exit can only have one direction. I mean, you can have an exit that goes northwest, but not an exit that goes northup. Similarly, the front door of a house may be both "north" and "out".

Rather than having to choose exactly one direction, wouldn't it make sense to allow them to be combined?

I'm thinking that in CoreEditorExit.aslx, the code:

      <control>
        <caption>[EditorExitType]</caption>
        <controltype>dropdowntypes</controltype>
        <types>*=[TypeExitNon];northwestdirection=[CompassNW];northdirection=[CompassN];northeastdirection=[CompassNE];westdirection=[CompassW];eastdirection=[CompassE];southwestdirection=[CompassSW];southdirection=[CompassS];southeastdirection=[CompassSE];updirection=[CompassUp];downdirection=[CompassDown];indirection=[CompassIn];outdirection=[CompassOut]</types>
        <width>150</width>
      </control>

Could maybe replaced by:

      <control>
        <caption>Compass Direction</caption>
        <controltype>dropdowntypes</controltype>
        <types>*=[TypeExitNon];northwestdirection=[CompassNW];northdirection=[CompassN];northeastdirection=[CompassNE];westdirection=[CompassW];eastdirection=[CompassE];southwestdirection=[CompassSW];southdirection=[CompassS];southeastdirection=[CompassSE]</types>
        <width>150</width>
      </control>

      <control>
        <caption>Vertical Direction</caption>
        <controltype>dropdowntypes</controltype>
        <types>*=Level;updirection=[CompassUp];downdirection=[CompassDown]</types>
        <width>150</width>
      </control>

      <control>
        <caption>Other Direction</caption>
        <controltype>dropdowntypes</controltype>
        <types>*=N/A;indirection=[CompassIn];outdirection=[CompassOut]</types>
        <width>150</width>
      </control>

The directional exit types in CoreTypes.aslx could have their alt attribute changed from type="simplestringlist" to type="listextend", so that a staircase leading both up and north can be activated by the player typing "go north" or "go up".

Then the function in CoreGrid.aslx could become:

  <function name="Grid_CalculateMapCoordinates" parameters="room, playerobject">
    <![CDATA[
    if (room.parent <> null) {
      if (room.grid_parent_offset_auto) {
        room.grid_parent_offset_x = (room.parent.grid_width - room.grid_width) /2.0
        room.grid_parent_offset_y = (room.parent.grid_length - room.grid_length) /2.0
      }

      Grid_SetGridCoordinateForPlayer (playerobject, room.parent, "x", Grid_GetGridCoordinateForPlayer(playerobject, room, "x") - room.grid_parent_offset_x)
      Grid_SetGridCoordinateForPlayer (playerobject, room.parent, "y", Grid_GetGridCoordinateForPlayer(playerobject, room, "y") - room.grid_parent_offset_y)
      Grid_SetGridCoordinateForPlayer (playerobject, room.parent, "z", Grid_GetGridCoordinateForPlayer(playerobject, room, "z"))

      room.parent.grid_render = true

      Grid_CalculateMapCoordinates (room.parent, playerobject)
    }

    foreach (exit, AllExits()) {
      if (exit.parent = room and not GetBoolean(exit, "lookonly")) {
        x_offset = exit.grid_offset_x
        y_offset = exit.grid_offset_y
        xdir = 0
        ydir = 0

        if (DoesInherit (exit, "westdirection") or DoesInherit (exit, "northwestdirection") or DoesInherit (exit, "southwestdirection")) {
          x_length = -exit.grid_length
          x_offset = x_offset - room.grid_width/2.0
          xdir = -1
        }
        else if (DoesInherit (exit, "eastdirection") or DoesInherit (exit, "northeastdirection") or DoesInherit (exit, "southeastdirection")) {
          x_length = exit.grid_length
          x_offset = x_offset + room.grid_width/2.0
          xdir = 1
        }
        else {
          x_length = 0
        }
        if (HasInt (exit, "x_length")) {
          x_length = exit.x_length
        }

        if (DoesInherit (exit, "northdirection") or DoesInherit (exit, "northwestdirection") or DoesInherit (exit, "northeastdirection")) {
          y_length = -exit.grid_length
          y_offset = y_offset - room.grid_length/2.0
          ydir = -1
        }
        else if (DoesInherit (exit, "southdirection") or DoesInherit (exit, "southwestdirection") or DoesInherit (exit, "southeastdirection")) {
          y_length = exit.grid_length
          y_offset = y_offset + room.grid_length/2.0
          ydir = 1
        }
        else {
          y_length = 0
        }
        if (HasInt (exit, "y_length")) {
          y_length = exit.y_length
        }

        if (DoesInherit (exit, "updirection")) {
          z_length = exit.grid_length
        }
        if (DoesInherit (exit, "downdirection")) {
          z_length = - exit.grid_length
        }

        if (HasObject (exit, "to")) {
          dest = exit.to
          dest_coords = Grid_GetPlayerCoordinatesForRoom(playerobject, dest)
          if (HasScript (dest, "overridegridcoords")) {
            do (dest, "overridegridcoords", QuickParams ("from_room", room, "exit", exit, "coords", dest_coords))
          }
          if (dest.grid_render and DictionaryContains (dest_coords, "x")) {
            x_length = DictionaryItem (dest_coords, "x") - xdir*dest.grid_width/2.0 - Grid_GetGridCoordinateForPlayer(playerobject, room, "x") - x_offset
          }
          else {
            Grid_SetGridCoordinateForPlayer (playerobject, dest, "x", Grid_GetGridCoordinateForPlayer(playerobject, room, "x") + x_offset + x_length + xdir*dest.grid_width/2.0)
          }

          if (dest.grid_render and DictionaryContains (dest_coords, "y")) {
            y_length = DictionaryItem (dest_coords, "y") - xdir*dest.grid_length/2.0 - Grid_GetGridCoordinateForPlayer(playerobject, room, "y") - y_offset
          }
          else {
            Grid_SetGridCoordinateForPlayer (playerobject, dest, "y", Grid_GetGridCoordinateForPlayer(playerobject, room, "y") + y_offset + y_length + ydir*dest.grid_length/2.0)
          }

          if (dest.grid_render and DictionaryContains (dest_coords, "z")) {
            z_length = DictionaryItem (dest_coords, "z") -Grid_GetGridCoordinateForPlayer(playerobject, room, "z")
          }
          else {
            Grid_SetGridCoordinateForPlayer (playerobject, dest, "z", Grid_GetGridCoordinateForPlayer(playerobject, room, "z") + z_length
          }
          dest.grid_render = true
        }

        Grid_SetGridCoordinateForPlayer (playerobject, exit, "x", Grid_GetGridCoordinateForPlayer(playerobject, room, "x") + x_offset)
        Grid_SetGridCoordinateForPlayer (playerobject, exit, "y", Grid_GetGridCoordinateForPlayer(playerobject, room, "y") + y_offset)
        Grid_SetGridCoordinateForPlayer (playerobject, exit, "end_x", Grid_GetGridCoordinateForPlayer(playerobject, room, "x") + x_offset + x_length)
        Grid_SetGridCoordinateForPlayer (playerobject, exit, "end_y", Grid_GetGridCoordinateForPlayer(playerobject, room, "y") + y_offset + y_length)
        exit.grid_render = exit.visible and not (x_length = 0 and y_length = 0)
      }
    }

This started as an idle thought off the top of my head, but I think it looks neater than the current system.

Advantages:

  • Script-only exits (no destination) still draw on the map, but the room they point to doesn't.
  • If you see an exit that points to an already-drawn room, the exit's start and end points will be changed to connect the existing boxes on the map, rather than messing up the display
  • You can have staircases, or doors that also have a direction, just by selecting multiple types in the GUI. No need to mess around with offsets

Disadvantages:

  • Typing off the top of my head; probably contains errors
  • Change to existing behaviour (the map scribbling on itself if you have a loop of rooms where the distances don't add up) - could be annoying if you were using that behaviour for some reason
  • I can't think of a sane way to set the alias of an exit with multiple types (not sure how the engine handles multiple types trying to set the same attribute)
  • A room can have an overridegridcoords script attribute which manually sets some of its coordinates, which could make some more complex layouts (especially procedurally generated mazes) easier to code

What do you think?


Log in to post a reply.

Support

Forums