allow adding purely decorative tiles in the editor without requiring mixing, leaving that up to the user

This commit is contained in:
Tim Felgentreff 2020-07-03 14:58:28 +02:00
parent f38702ee81
commit 7ad3935dc6
7 changed files with 90 additions and 36 deletions

View file

@ -100,6 +100,9 @@ void EditorChangeTile(const Vec2i &pos, int tileIndex, const Vec2i &lock_pos)
// Change the flags
CMapField &mf = *Map.Field(pos);
if (mf.isDecorative()) {
return;
}
int tile = tileIndex;
if (TileToolRandom) {
int n = 0;
@ -143,6 +146,10 @@ static void EditorChangeSurrounding(const Vec2i &pos, const Vec2i &lock_pos)
return;
}
if (mf.isDecorative()) {
return;
}
const unsigned int quad = QuadFromTile(pos);
const unsigned int TH_QUAD_M = 0xFFFF0000; // Top half quad mask
const unsigned int BH_QUAD_M = 0x0000FFFF; // Bottom half quad mask
@ -158,45 +165,53 @@ static void EditorChangeSurrounding(const Vec2i &pos, const Vec2i &lock_pos)
if (pos.y) {
const Vec2i offset(0, -1);
// Insert into the bottom the new tile.
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & TH_QUAD_M) | ((quad >> 16) & BH_QUAD_M);
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & BH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, lock_pos);
if (!(Map.Field(pos + offset)->isDecorative())) {
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & TH_QUAD_M) | ((quad >> 16) & BH_QUAD_M);
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & BH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, lock_pos);
}
}
}
if (pos.y < Map.Info.MapHeight - 1) {
const Vec2i offset(0, 1);
// Insert into the top the new tile.
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & BH_QUAD_M) | ((quad << 16) & TH_QUAD_M);
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & TH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, lock_pos);
if (!(Map.Field(pos + offset)->isDecorative())) {
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & BH_QUAD_M) | ((quad << 16) & TH_QUAD_M);
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & TH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, lock_pos);
}
}
}
if (pos.x) {
const Vec2i offset(-1, 0);
// Insert into the left the new tile.
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & LH_QUAD_M) | ((quad >> 8) & RH_QUAD_M);
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & RH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, lock_pos);
if (!(Map.Field(pos + offset)->isDecorative())) {
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & LH_QUAD_M) | ((quad >> 8) & RH_QUAD_M);
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & RH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, lock_pos);
}
}
}
if (pos.x < Map.Info.MapWidth - 1) {
const Vec2i offset(1, 0);
// Insert into the right the new tile.
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & RH_QUAD_M) | ((quad << 8) & LH_QUAD_M);
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & LH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, lock_pos);
if (!(Map.Field(pos + offset)->isDecorative())) {
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & RH_QUAD_M) | ((quad << 8) & LH_QUAD_M);
if (u != q2 && (pos + offset) != lock_pos) {
did_change = true;
int tile = Map.Tileset->tileFromQuad(u & LH_QUAD_M, u);
EditorChangeTile(pos + offset, tile, lock_pos);
}
}
}

View file

@ -210,6 +210,9 @@ public:
/// Returns true, if coast on the map tile field
bool RockOnMap() const;
/// Returns true if the field should not need mixing with the surroundings
bool isDecorative() const;
bool isAWall() const;
bool isHuman() const;
bool isAHumanWall() const;
@ -227,7 +230,7 @@ private:
#endif
unsigned short tile; /// graphic tile number
public:
unsigned short Flags; /// field flags
unsigned int Flags; /// field flags
private:
unsigned char cost; /// unit cost to move in this tile
public:

View file

@ -37,6 +37,7 @@
----------------------------------------------------------------------------*/
#include "vec2i.h"
#include <string>
#include <vector>
struct lua_State;
@ -61,6 +62,8 @@ struct lua_State;
#define MapFieldSeaUnit 0x4000 /// Water unit on field
#define MapFieldBuilding 0x8000 /// Building on field
#define MapFieldDecorative 0x10000 /// A field that needs no mixing with the surroundings, for the editor
/**
** These are used for lookup tiles types
** mainly used for the FOW implementation of the seen woods/rocks
@ -110,7 +113,7 @@ public:
public:
unsigned short tile; /// graphical pos
unsigned short flag; /// Flag
unsigned int flag; /// Flag
CTileInfo tileinfo; /// Tile descriptions
};
@ -164,6 +167,7 @@ public:
void parse(lua_State *l);
void buildTable(lua_State *l);
int parseTilesetTileFlags(lua_State *l, int *back, int *j);
private:
unsigned int getOrAddSolidTileIndexByName(const std::string &name);

View file

@ -233,6 +233,12 @@ bool CMapField::RockOnMap() const
return CheckMask(MapFieldRocks);
}
/// Returns true if the field should not need mixing with the surroundings
bool CMapField::isDecorative() const
{
return CheckMask(MapFieldDecorative);
}
bool CMapField::isAWall() const
{
return Flags & MapFieldWall;

View file

@ -468,8 +468,11 @@ static int CclSetTileFlags(lua_State *l)
int j = 0;
int flags = 0;
ParseTilesetTileFlags(l, &flags, &j);
unsigned char newBase = Map.Tileset->parseTilesetTileFlags(l, &flags, &j);
Map.Tileset->tiles[tilenumber].flag = flags;
if (newBase) {
Map.Tileset->tiles[tilenumber].tileinfo.BaseTerrain = newBase;
}
return 0;
}

View file

@ -38,6 +38,7 @@
#include "tileset.h"
#include "script.h"
#include <cstring>
/*----------------------------------------------------------------------------
-- Functions
@ -61,7 +62,8 @@ static bool ModifyFlag(const char *flagName, unsigned int *flag)
{"air-unit", MapFieldAirUnit},
{"sea-unit", MapFieldSeaUnit},
{"building", MapFieldBuilding},
{"human", MapFieldHuman}
{"human", MapFieldHuman},
{"decorative", MapFieldDecorative}
};
for (unsigned int i = 0; i != sizeof(flags) / sizeof(*flags); ++i) {
@ -98,8 +100,10 @@ static bool ModifyFlag(const char *flagName, unsigned int *flag)
** @param back pointer for the flags (return).
** @param j pointer for the location in the array. in and out
**
** @return index for basename, if the name this tile should be available as a different basename, or 0
**
*/
void ParseTilesetTileFlags(lua_State *l, int *back, int *j)
int CTileset::parseTilesetTileFlags(lua_State *l, int *back, int *j)
{
unsigned int flags = 3;
@ -114,12 +118,18 @@ void ParseTilesetTileFlags(lua_State *l, int *back, int *j)
const char *value = LuaToString(l, -1);
lua_pop(l, 1);
// Flags are only needed for the editor
// Flags are mostly needed for the editor
if (ModifyFlag(value, &flags) == false) {
LuaError(l, "solid: unsupported tag: %s" _C_ value);
}
}
*back = flags;
if (flags & MapFieldDecorative) {
return getOrAddSolidTileIndexByName(std::to_string(solidTerrainTypes.size()));
} else {
return 0;
}
}
/**
@ -190,7 +200,10 @@ void CTileset::parseSolid(lua_State *l)
++j;
int f = 0;
ParseTilesetTileFlags(l, &f, &j);
if (parseTilesetTileFlags(l, &f, &j)) {
LuaError(l, "cannot set a custom basename in the main set of flags");
}
// Vector: the tiles.
lua_rawgeti(l, -1, j + 1);
if (!lua_istable(l, -1)) {
@ -204,10 +217,13 @@ void CTileset::parseSolid(lua_State *l)
if (lua_istable(l, -1)) {
int k = 0;
int tile_flag = 0;
ParseTilesetTileFlags(l, &tile_flag, &k);
unsigned char new_basename = parseTilesetTileFlags(l, &tile_flag, &k);
--j;
lua_pop(l, 1);
tiles[index + j].flag = tile_flag;
if (new_basename) {
tiles[index + j].tileinfo.BaseTerrain = new_basename;
}
continue;
}
const int pud = LuaToNumber(l, -1);
@ -248,7 +264,9 @@ void CTileset::parseMixed(lua_State *l)
++j;
int f = 0;
ParseTilesetTileFlags(l, &f, &j);
if (parseTilesetTileFlags(l, &f, &j)) {
LuaError(l, "cannot set a custom basename in the main set of flags");
}
for (; j < args; ++j) {
lua_rawgeti(l, -1, j + 1);

View file

@ -656,11 +656,16 @@ unsigned CTileset::getQuadFromTile(unsigned int tile) const
void CTileset::fillSolidTiles(std::vector<unsigned int> *solidTiles) const
{
for (size_t i = 16; i < tiles.size(); i += 16) {
const CTileInfo &info = tiles[i].tileinfo;
std::vector<int> seen_types;
seen_types.resize(solidTerrainTypes.size(), 0);
for (size_t i = 16; i < tiles.size(); i++) {
const CTileInfo &info = tiles[i].tileinfo;
if (info.BaseTerrain && info.MixTerrain == 0) {
solidTiles->push_back(tiles[i].tile);
if (seen_types[info.BaseTerrain] == 0) {
seen_types[info.BaseTerrain] = 1;
solidTiles->push_back(tiles[i].tile);
}
}
}
}