MapRewriteDesign

Contents

Summary of the biggest changes

Okay, so I'll list here the main changes, point by point. Some of these are already coded, some are still in progress.

What is this multilayer stuff?

Frames of reference

In order not to cause any more confusion, I'll sum up the reference systems we should be using:

Screen Reference System (SRS)

Pixels on the screen. X runs across, Y down, defined in the struct "ScreenCoord"

Map Reference System (MRS)

Counts in units from the origin of the map and stores only X and Y coordinates. X runs from upper right to lower left. This is defined in PointXY.

Full Reference System (FRS)

Like the Map Reference System, but it stores a Z coordinate as well. The matching struct is a "Point"

Map Tile System (MTS)

Stores the X and Y position of a Tile, in units of one Tile; this should be stored in TStackXY. Again X runs from upper right to lower left.

Tile Reference System (TRS)

Counts in units from the nothern corner of the Tile. X from upper right to lower left, Y perpendicular, Z in the vertical axis. Stored as TileSubCoords.

What does a tile look like now?

Instead of having a lot of seperate unlabeled arrays which contain miscellaneous data, we will now store information about a tile in a struct appropriately named "Tile". The exact contents are to be found in the code (where?), but we will discuss the main lines here.

A Tile will contain the following data:

There is also some stuff that isn't stored on a tile:

How do we store heights and slopes then?

In short, we will store one altitude for each tile, and 4 heights, one for each corner. To get the actual altitude of a corner, you take the tile altitude, multiply it by 4, and add the corner height to that. Simple as that :-)

Some people will notice that altitude is 4 bits, so we could multiply it by 16 (or 8) before adding. The big problem with that is that then we can't have tile that has corner altitudes of (15, 15, 17, 17) for example. I can't really explain why, just draw out the example and I hope you'll see.

Of course you should NEVER perform this calculation (or acces these values) directly, use the various helper functions (tile.h) for that.

Definitions about a tile heights

What should I use to manipulate tiles?

Most people will be inclined to start using the _map array, with the various tile variables that are used everywhere as index. You shouldn't.

This is because of 2 reasons. If everyone is just using the _map array, we can't change shit about how things are stored internally, without changing all the code again. Because of this, we will define functions to access the map. These functions can then be changed internally later on if that would be more efficient or better. This means that when using these functions, pay close attention to the comments above the function declaration and don't assume things.

For example, it is most likely that the _map array will contain the ground tile and that all the tiles above and below the ground tile are stored in the linked list formed by Tile.next. But, you still need to use the GetGroundTile function to get to the ground tile, and GetTileAbove and GetTileBelow to get to the other tiles, for the exact order might change in the future.

The second reason, or actually the second problem with dumbly converting, is that you can't just use the tile variable anymore. Because of the multilayer approach, you can't just address a tile by an index anymore. So, for addressing tiles, you will generally just use a Tile*. The biggest problem is that you can't determine an (x,y) from a Tile*, so if needed, you will pass a TileRef around. A TileRef just wraps a Tile* together with the TileXY. A tileXY is a reference to an entire stack of tiles on a given (x,y) coordinate. Lastly there is a TileXYN, but that is only used for sending tiles over the network.

Notice that you can always translate a TileRef to a Tile* or a TileXY, but not the other way around!

So, what functions should you use then? Not everyone have been defined yet, but you should definately take a look at map.h for the functions that acces tiles of the map, and at tile.h for functions that query individual tiles. There should be functions for a lot of common things, such as looking up the track type of a tile, etc. Check these files often, new functions will be introduced!

When working with these tile things, try to use consistent variable namings: "t" for a Tile*, "tr" for a TileRef*, "txy" for a TileXY*.

Variables, Variables, Variables

It's nice to know how to store tiles, but it is even nicer to know how to store references to parts of the map.

Within our openttd world, we can define three different concepts.

Description Referencable by
The map This is the collection of all tiles. Not referencable, since we only have one map for now.
Tile Stacks The map is divided into squares using a grid. Each square has a x and y cooridnate. All the tiles in one square that have the same x and y coordinates, are called a tile stack. In other words, all tiles that are stacked on top of each other are a stack.
TStack ts
This is a pointer to an entire stack (cannot be converted to a TileXY)
TStackXY tsxy
This is the (x,y) location of a tile stack (can be easily converted to a TileStack)
Tiles A tile is a essentially an element of the tile stack. It is a square on a given x and y coordinate (iow, in a given tile stack) with a given height and slope.
Tile* t
This is a pointer to a single tile (cannot be converted to a TileRef)
TileRef tr
This is essentially the location of a single tile. It stores the (x,y) and height information of a tile (can be easily converted to a Tile*)

Besides these referencing methods, there is also TileXYN, which is the network compatible variant of TileRef. You should not use it outside the network code.

Miscelaneous other changes