Skip to content

Highgrounds support

Alyokhin edited this page Nov 29, 2023 · 3 revisions

Brief overview

Stratagus has support for highgrounds.

Engine:

  • A elevation level (height) can be set for each map tile. Up to 256 levels (one byte) are available;
  • Sight blocking from lowgrownds to highgrounds support;
  • Lua scripted tileset generator, which allows you to generate extended tileset graphics with support for cliffs, ramps, etc. from base tilesets that were originally created without them (e.g. original warcraft 2 tilesets)

Editor:

  • Ability to highlight overlays (elevation level/unpassable/no-building etc.);
  • Set the elevation levels for tiles and save them in the map-files;
  • Use generated extended tilesets. (Unfortunately only in the manual mode for now).

Elevation level

The elevation is set by 5th arg for SetTile in the Stratagus map file:

SetTile(tile_index, tile_x, tile_y, value, elevation)

It can be omitted, then the default value (0) will be taken. So we have back compatibility for old or already created maps. Up to 256 levels (one byte) are available, but it can easily be reduced in the future to use the freed bits for something else. Say 2 bits for elevation (3 levels in total) and 6 bits for whatever we will want.

Sight blocking

To block a unit from seeing map tiles with a higher elevation than its own, you must enable the shadow-casting field of view type.

SetFieldOfViewType("shadow-casting")

note: the enhanced fog of war type will be enabled automatically, since the tiled and fast types do not support shadow-casting field of view type.

Air units can see at highgrounds with any elevation level.

Extended tileset

The base tileset format uses this indexes:

Base tileset (wc2 summer by example)

001x            light water
002x            dark water
003x            light coast
004x            dark coast
005x            light ground/grass
006x            dark ground/grass
007x            forest
008x            mountains
009x            human wall
00ax            orc walls
00bx            human walls
00cx            orc walls

boundary tiles

09..            orc wall
08..            human wall
07..            forest and grass
06..            dark grass and grass
05..            coast and grass
04..            mount and coast
03..            dark coast and coast
02..            water and coast
01..            dark water and water

where .. is:

filled  clear
0x      Dx      upper left
1x      Cx      upper right
2x      Bx      upper half
3x      Ax      lower left
4x      9x      left half
7x      6x      lower right
8x      5x      upper left, lower right

For extended tileset have been added next ones:

Extended tileset (wc2 summer by example)

101x            solid cliff
102x            solid ramp

boundary tiles

11..            cliff and dark coast lowground
12..            cliff and dark grass lowground
13..            cliff and water lowground
14..            coast highground and cliff
15..            grass highground and cliff
16..            coast highground and dark coast lowground
17..            coast highground and dark grass lowground
18..            coast highground and light water lowground (not implemented yet)
19..            grass highground and dark coast lowground
1A..            grass highground and dark grass lowground
1B..            grass highground and dark water lowground (not implemented yet)
1C..            ramp and cliff
1D..            ramp and dark coast lowground
1E..            ramp and dark grass lowground
1F..            ramp and highgrounds
21..            ramp and lowgrounds

Tileset generator

The extended tileset generator does not save the generated tileset to a file, but stores it only in RAM. Thus, it should be started each time the base tileset is loaded from a file. This behavior is done intentionally to avoid the possibility of using a tilesets generated from copyrighted graphics (e.g. warcraft 2) elsewhere.

Tileset generator usage (this must be called after the main tileset has been loaded by DefineTileset().):

GenerateExtendedTileset(
    "image", path-to-image-with-tileset-graphic, -- optional for extended tileset
    "slots", {
              slot-type, {"terrain-name", ["terrain-name",] [list-of-flags-for-all-tiles-of-this-slot,]
                          {dst, src[, additional-flags-list]}
                          [, {dst, src[, additional-flags-list]}]
                          ...
                         }
                        ...
              }
 --[[           
      where:
      slot-type: 
        "solid" or "mixed"
        Each slot consist of 16 tiles which represent one of terrain type ("solid") 
        or mix of two different solid terrains ("mixed" f.e. grass-coast, water-coast etc.)
        Second "terrain-name" in the slot definition is for mixed type.

      list-of-flags-for-all-tiles-of-this-slot: 
        comma separated list of flags which are common for all tiles in this slot

      dst:
        single argument (number or table) at position 1.
        index of defined tile (or set of indexes). Each slot consist of 16 tiles only. 
        For extended tileset indexes must be greater than already defined.
        Each slot's indexes set starts from xxx0 and ended with xxxF (where description of xxx see in PUD format explanation)
        
        'dst' can take one of the following forms:
        tile                    -- single tile index
        {tile[, tile,] ...}     -- set of tile indexes
        {"range", from, to}     -- range of indexes [from, to]
        {"slot", slot_num}      -- whole slot indexes f.e. {"slot", 0x1010} - put src continuously to slot 0x101[0..F] 
                                -- until there is a src (up to 16, if less then fill slot with 0 for absent srcs)

      src:
        single argument (number or table) at position 2.
        Describes where to get graphics for dst. It can be graphics from a tile defined in main tileset,
        or frame from image file defined by "image" field (see above), or it can be generated from
        several graphic frames by composing them as layers (with simple per-pixel manipulations)

        'src' in general looks like:
        { "layers",  { src_range [,{"do_something", parameter}...] }, -- layer 1
                     { src_range [,{"do_something", parameter}...] }, -- layer 2
                     ...
                     { src_range [,{"do_something", parameter}...] }  -- layer n
        }

        "layers" can be omitted if we have a single layer, then src takes this form:
        { src_range [,{"do_something", parameter}...] } 
        or even: 
        src_range                     -- then we just use images from src_range without any manipulations with them

        'src_range' can take one of the following forms:
        tile                                    -- tile index (within main tileset) to get graphic from
        {tile[, tile]...}}                      -- set of tiles indexes (within main tileset) to get graphics from
        {"img"|"img-base", image[, image]...}   -- set of numbers of frames from the extended (or base tileset) "image" file.
        {["img"|"img-base",] "range", from, to} -- if "img" then from frame to frame (for "image"),        
                                                -- otherwise indexes from tile to tile (within main tileset) to get graphics from
        {"slot", slot_num}                      -- f.e. {"slot", 0x0430} - to take graphics continuously from tiles with indexes of slot 0x0430

        'do_something' is a pixel modifier for src images. The form is:
        {"do_something", parameter}
        where 'do_something':
          "remove"
          usage:		{"remove", colors[, colors]..}
                  where 'colors':
                          color		-- single color
                          {from, to}	-- range of colors

          "remove-all-except"
          usage:		{"remove-all-except", colors[, colors]..}
                  where 'colors':
                          color		-- single color
                          {from, to}	-- range of colors

          "shift"
          usage		{"shift", inc, colors[, colors]..}
                  where 	'inc':
                        increment (positive or negative) to be implemented on the colors
                      'colors':
                        color		-- single color
                        {from, to}	-- range of colors

          "flip"
          usage:		{"flip", direction}
                  where 'direction':
                         "vertical"
                         "horizontal"
                         "both"

          "chroma-key"
          usage:		{"chroma-key", src_range2, key_colors[, key_colors]..}
                  where 'src_range2': (set of images to compose with images from src_range. Are taken consecutively one for each from src_range)
                        {tile}                                  -- tile index (within main tileset) to get graphic from
                        {tile[, tile]...}}                      -- set of tiles indexes (within main tileset) to get graphics from
                        {"img"|"img-base", image[, image]...}   -- set of numbers of frames from the extended (or base tileset) "image" file.
                        {["img"|"img-base",] "range", from, to} -- if "img" then from frame to frame (for "image"),        
                                                                -- otherwise indexes from tile to tile (within main tileset) to get graphics from
                        {"slot", slot_num}                      -- f.e. {"slot", 0x0430} - to take graphics continuously from tiles with indexes of slot 0x0430
                    'key_colors': (chroma keys)
                        color		-- single color
                        {from, to}	-- range of colors

      additional-flags-list:
        strings which started from position 3
        comma separated list of additional flags for this range of tiles
--]]
)