diff --git a/src/editor/editloop.cpp b/src/editor/editloop.cpp index ad5ec6f95a..a82274af3a 100644 --- a/src/editor/editloop.cpp +++ b/src/editor/editloop.cpp @@ -2137,7 +2137,7 @@ void EditorMainLoop() editorContainer->add(toolDropdown.get(), 0, 0); } - std::vector overlaysListStrings = { "Layers: None", "Unpassable", "No building allowed", "Elevation", "Opaque" }; + std::vector overlaysListStrings = { "Overlays: None", "Unpassable", "No building allowed", "Elevation", "Opaque" }; auto overlaysList = std::make_unique(overlaysListStrings); overlaysDropdown = std::make_unique(overlaysList.get()); auto overlaysDropdownListener = std::make_unique([&overlaysListStrings](const std::string&) { diff --git a/src/game/game.cpp b/src/game/game.cpp index c8275a44fb..f63f1d6f23 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -289,9 +289,10 @@ static bool WriteMapPresentation(const fs::path &mapname, CMap &map, Vec2i newSi newSize.y = map.Info.MapHeight; } - f->printf("PresentMap(\"%s\", %d, %d, %d, %d)\n", + f->printf("PresentMap(\"%s\", %d, %d, %d, %d%s)\n", map.Info.Description.c_str(), numplayers, newSize.x, newSize.y, - map.Info.MapUID + 1); + map.Info.MapUID + 1, + Map.Info.IsHighgroundsEnabled()? ", \"highgrounds-enabled\"" : ""); if (map.Info.Filename.find(".sms") == std::string::npos && !map.Info.Filename.empty()) { f->printf("DefineMapSetup(\"%s\")\n", map.Info.Filename.c_str()); diff --git a/src/include/map.h b/src/include/map.h index dcf69505d8..32f409d5a5 100644 --- a/src/include/map.h +++ b/src/include/map.h @@ -129,6 +129,9 @@ class CMapInfo bool IsPointOnMap(const Vec2i &pos) const { return IsPointOnMap(pos.x, pos.y); } + bool IsHighgroundsEnabled() const { return HighgroundsEnabled; } + void EnableHighgrounds(bool enable = true) { HighgroundsEnabled = enable; } + void Clear(); public: @@ -141,6 +144,9 @@ class CMapInfo PlayerTypes PlayerType[PlayerMax]; /// Same player->Type int PlayerSide[PlayerMax]; /// Same player->Side unsigned int MapUID; /// Unique Map ID (hash) + +private: + bool HighgroundsEnabled = false; /// Map has highgrounds }; /*---------------------------------------------------------------------------- diff --git a/src/include/script.h b/src/include/script.h index a6c76f6324..23725cbe18 100644 --- a/src/include/script.h +++ b/src/include/script.h @@ -92,12 +92,24 @@ extern int LuaCall(lua_State *L, int narg, int nresults, int base, bool exitOnEr lua_error(l); \ } while (0) -#define LuaCheckArgs(l, args) \ - do { \ - if (lua_gettop(l) != args) { \ - LuaError(l, "incorrect argument"); \ - } \ - } while (0) +inline void LuaCheckArgs(lua_State *l, int args) +{ + if (lua_gettop(l) != args) { + LuaError(l, "incorrect argument"); + } +} + +inline void LuaCheckArgs_min(lua_State *l, int args) +{ + if (lua_gettop(l) < args) { + LuaError(l, "incorrect argument"); + } +} + +inline int LuaGetArgsNum(lua_State *l) +{ + return lua_gettop(l); +} #if LUA_VERSION_NUM <= 501 diff --git a/src/include/tileset.h b/src/include/tileset.h index e501f3fafd..42bc2de70d 100644 --- a/src/include/tileset.h +++ b/src/include/tileset.h @@ -90,6 +90,7 @@ constexpr uint8_t MapFieldSubtilesMax {16}; constexpr uint8_t MapFieldSubtilesUnpassableShift {48}; constexpr tile_flags MapFieldSubtilesUnpassableMask {tile_flags(0xFFFF) << MapFieldSubtilesUnpassableShift}; /// Up to 16 unpassable subtiles, never used in MapField, only in CTile +constexpr tile_index ExtendedTilesetBeginIdx {0x1010}; /// the extended tiles indexes start form here /** ** These are used for lookup tiles types diff --git a/src/include/widgets.h b/src/include/widgets.h index b37c0a0f82..a0552c7dc1 100644 --- a/src/include/widgets.h +++ b/src/include/widgets.h @@ -319,6 +319,7 @@ class StringListModel : public gcn::ListModel int getNumberOfElements() override { return list.size(); } std::string getElementAt(int i) override { return list[i]; } + int getIdxOfElement(std::string_view element); }; class LuaListModel : public gcn::ListModel @@ -330,6 +331,7 @@ class LuaListModel : public gcn::ListModel void setList(lua_State *lua, lua_Object *lo); int getNumberOfElements() override { return list.size(); } std::string getElementAt(int i) override { return list[i]; } + int getIdxOfElement(std::string_view element); }; class ImageListBox : public gcn::ListBox @@ -471,7 +473,9 @@ class ImageDropDownWidget : public DropDownWidget void setSize(int width, int height) override; void setListModel(LuaListModel *listModel); int getSelected(); + std::string getSelectedItem(); void setSelected(int selected); + int setSelectedItem(lua_State *lua, lua_Object *lo); void adjustHeight(); void setListBox(ImageListBox *listBox); void setFont(gcn::Font *font); diff --git a/src/map/fov.cpp b/src/map/fov.cpp index a76669e4fd..63b8caed93 100644 --- a/src/map/fov.cpp +++ b/src/map/fov.cpp @@ -138,7 +138,7 @@ void CFieldOfView::Refresh(const CPlayer &player, const CUnit &unit, const Vec2i return; } if (GameSettings.FoV == FieldOfViewTypes::cShadowCasting && !unit.Type->AirUnit) { - /// FIXME: add high-/lowground + OpaqueFields = unit.Type->BoolFlag[ELEVATED_INDEX].value ? 0 : this->Settings.OpaqueFields; if (GameSettings.Inside) { OpaqueFields &= ~(MapFieldRocks); /// because of rocks-flag is used as an obstacle for ranged attackers diff --git a/src/map/map.cpp b/src/map/map.cpp index b31c5615b9..f89b96166e 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -316,6 +316,8 @@ void CMapInfo::Clear() memset(this->PlayerSide, 0, sizeof(this->PlayerSide)); memset(this->PlayerType, 0, sizeof(this->PlayerType)); this->MapUID = 0; + + this->HighgroundsEnabled = false; } CMap::~CMap() diff --git a/src/map/mapfield.cpp b/src/map/mapfield.cpp index 3abb05edd0..03acf4a9da 100644 --- a/src/map/mapfield.cpp +++ b/src/map/mapfield.cpp @@ -84,7 +84,14 @@ bool CMapField::IsTerrainResourceOnMap() const void CMapField::setTileIndex(const CTileset &tileset, const tile_index tileIndex, const int value, const uint8_t elevation, const int subtile /* = -1 */) { - const CTile &tile = tileset.tiles[tileIndex]; + uint8_t compShift = 0; // [0..F] in case that current tileset slot length is shorter than map's original + + if (tileIndex >= ExtendedTilesetBeginIdx) { // tile from extended tileset + while(tileset.tiles[tileIndex - compShift].tile == 0 && ((tileIndex & 0xF) - compShift) > 0) { + compShift++; + } + } + const CTile &tile = tileset.tiles[tileIndex - compShift]; this->tile = tile.tile; this->Value = value; this->ElevationLevel = elevation; @@ -116,7 +123,7 @@ void CMapField::setTileIndex(const CTileset &tileset, const tile_index tileIndex #endif this->cost = 1 << (tile.flag & MapFieldSpeedMask); #ifdef DEBUG - this->tilesetTile = tileIndex; + this->tilesetTile = tileIndex - compShift; #endif } diff --git a/src/map/script_map.cpp b/src/map/script_map.cpp index 54aeddcccc..4d02023499 100644 --- a/src/map/script_map.cpp +++ b/src/map/script_map.cpp @@ -1056,6 +1056,71 @@ static int CclGetIsGameHoster(lua_State *l) return 1; } +/** +** Description +** +** Set basic map caracteristics. +** +** @param l Lua state. +** +** Example: +** +**
PresentMap("Map description", PlayerCount, Width, Height, uid_number [, "highgrounds-enabled"])
+*/ +static int CclPresentMap(lua_State *l) +{ + LuaCheckArgs_min(l, 5); + + Map.Info.Description = LuaToString(l, 1); + // Number of players in LuaToNumber(l, 2); // Not used yet. + Map.Info.MapWidth = LuaToNumber(l, 3); + Map.Info.MapHeight = LuaToNumber(l, 4); + Map.Info.MapUID = LuaToNumber(l, 5); + + if(LuaGetArgsNum(l) >= 6) { + const std::string_view value = LuaToString(l, 6); + if (value == "highgrounds-enabled") { + Map.Info.EnableHighgrounds(); + } else { + LuaError(l, "Unknown value %s\n", value.data()); + } + } + + return 0; +} + +static int CclMapEnableHighgrounds(lua_State *l) +{ + Map.Info.EnableHighgrounds(LuaGetArgsNum(l) >= 1 ? LuaToBoolean(l, 1) : true); + + return 0; +} + +static int CclIsHighgroundsEnabled(lua_State *l) +{ + lua_pushboolean(l, Map.Info.IsHighgroundsEnabled()); + return 1; +} + +/** +** Description +** +** Define the lua file that will build the map +** +** @param l Lua state. +** +** Example: +** +**
-- Load map setup from file +** DefineMapSetup("Setup.sms")
+*/ +static int CclDefineMapSetup(lua_State *l) +{ + LuaCheckArgs(l, 1); + Map.Info.Filename = LuaToString(l, 1); + + return 0; +} /** ** Register CCL features for map. */ @@ -1114,6 +1179,11 @@ void MapCclRegister() lua_register(Lua, "GetIsGameHoster", CclGetIsGameHoster); + lua_register(Lua, "PresentMap", CclPresentMap); + lua_register(Lua, "MapEnableHighgrounds", CclMapEnableHighgrounds); + lua_register(Lua, "IsHighgroundsEnabled", CclIsHighgroundsEnabled); + + lua_register(Lua, "DefineMapSetup", CclDefineMapSetup); } //@} diff --git a/src/tolua/ui.pkg b/src/tolua/ui.pkg index 8e116890ab..15d1dbb1db 100644 --- a/src/tolua/ui.pkg +++ b/src/tolua/ui.pkg @@ -630,6 +630,8 @@ class DropDownWidget : public DropDown class ImageDropDownWidget : public DropDown { ImageDropDownWidget(); + std::string getSelectedItem(); + int setSelectedItem(lua_State *lua, lua_Object *lo); void setList(lua_State *lua, lua_Object *lo); virtual ListBox *getListBox(); virtual void setSize(int width, int height); diff --git a/src/ui/script_ui.cpp b/src/ui/script_ui.cpp index 1001d3497d..a2d53a0450 100644 --- a/src/ui/script_ui.cpp +++ b/src/ui/script_ui.cpp @@ -1245,49 +1245,6 @@ static int CclSetGroupKeys(lua_State *l) return 0; } -/** -** Description -** -** Set basic map caracteristics. -** -** @param l Lua state. -** -** Example: -** -**
PresentMap("Map description", 1, 128, 128, 17)
-*/ -static int CclPresentMap(lua_State *l) -{ - LuaCheckArgs(l, 5); - - Map.Info.Description = LuaToString(l, 1); - // Number of players in LuaToNumber(l, 3); // Not used yet. - Map.Info.MapWidth = LuaToNumber(l, 3); - Map.Info.MapHeight = LuaToNumber(l, 4); - Map.Info.MapUID = LuaToNumber(l, 5); - - return 0; -} - -/** -** Description -** -** Define the lua file that will build the map -** -** @param l Lua state. -** -** Example: -** -**
-- Load map setup from file -** DefineMapSetup("Setup.sms")
-*/ -static int CclDefineMapSetup(lua_State *l) -{ - LuaCheckArgs(l, 1); - Map.Info.Filename = LuaToString(l, 1); - - return 0; -} /** ** Description ** @@ -1357,9 +1314,6 @@ void UserInterfaceCclRegister() lua_register(Lua, "DefineButtonStyle", CclDefineButtonStyle); - lua_register(Lua, "PresentMap", CclPresentMap); - lua_register(Lua, "DefineMapSetup", CclDefineMapSetup); - // // Look and feel of units // diff --git a/src/ui/widgets.cpp b/src/ui/widgets.cpp index ea0ccf39a0..4173d5b119 100644 --- a/src/ui/widgets.cpp +++ b/src/ui/widgets.cpp @@ -43,6 +43,7 @@ #include "netconnect.h" #include "editor.h" #include "sound.h" +#include "util.h" /*---------------------------------------------------------------------------- -- Variables @@ -1718,9 +1719,23 @@ void ImageTextField::drawBorder(gcn::Graphics *graphics) } /*---------------------------------------------------------------------------- --- LuaListModel +-- StringListModel ----------------------------------------------------------------------------*/ +int StringListModel::getIdxOfElement(std::string_view element) +{ + auto result = ranges::find(this->list, element); + if (result != this->list.end()) { + return result - this->list.begin(); + } else { + return -1; + } + +} + +/*---------------------------------------------------------------------------- +-- LuaListModel +----------------------------------------------------------------------------*/ /** ** Set the list @@ -1735,6 +1750,16 @@ void LuaListModel::setList(lua_State *lua, lua_Object *lo) } } +int LuaListModel::getIdxOfElement(std::string_view element) +{ + auto result = ranges::find(this->list, element); + if (result != this->list.end()) { + return result - this->list.begin(); + } else { + return -1; + } +} + /*---------------------------------------------------------------------------- -- ImageListBox ----------------------------------------------------------------------------*/ @@ -2610,6 +2635,13 @@ int ImageDropDownWidget::getSelected() return mListBox.getSelected(); } +std::string ImageDropDownWidget::getSelectedItem() +{ + Assert(mScrollArea && mScrollArea->getContent() != nullptr); + + return listmodel.getElementAt(mListBox.getSelected()); +} + void ImageDropDownWidget::setSelected(int selected) { Assert(mScrollArea && mScrollArea->getContent() != nullptr); @@ -2620,6 +2652,19 @@ void ImageDropDownWidget::setSelected(int selected) } } +int ImageDropDownWidget::setSelectedItem(lua_State *lua, lua_Object *lo) +{ + Assert(mScrollArea && mScrollArea->getContent() != nullptr); + + auto item = LuaToString(lua, *lo); + int idx = this->listmodel.getIdxOfElement(item); + if (idx >= 0) + { + this->setSelected(idx); + } + return idx; +} + void ImageDropDownWidget::adjustHeight() { Assert(mScrollArea && mScrollArea->getContent() != nullptr);