Browse Source

Merge pull request #3645 from vcmi/save_rmg_options

Save rmg options
DjWarmonger 1 year ago
parent
commit
2c9b7089ad

+ 6 - 1
client/CServerHandler.cpp

@@ -193,8 +193,13 @@ void CServerHandler::startLocalServerAndConnect(bool connectToLobby)
 		serverRunner.reset(new ServerThreadRunner());
 #endif
 
+	auto si = std::make_shared<StartInfo>();
+
+	auto lastDifficulty = settings["general"]["lastDifficulty"];
+	si->difficulty = lastDifficulty.Integer();
+
 	logNetwork->trace("\tStarting local server");
-	serverRunner->start(getLocalPort(), connectToLobby);
+	serverRunner->start(getLocalPort(), connectToLobby, si);
 	logNetwork->trace("\tConnecting to local server");
 	connectToServer(getLocalHostname(), getLocalPort());
 	logNetwork->trace("\tWaiting for connection");

+ 7 - 2
client/ServerRunner.cpp

@@ -23,10 +23,15 @@
 ServerThreadRunner::ServerThreadRunner() = default;
 ServerThreadRunner::~ServerThreadRunner() = default;
 
-void ServerThreadRunner::start(uint16_t port, bool connectToLobby)
+void ServerThreadRunner::start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo)
 {
 	server = std::make_unique<CVCMIServer>(port, connectToLobby, true);
 
+	if (startingInfo)
+	{
+		server->si = startingInfo; //Else use default
+	}
+
 	threadRunLocalServer = boost::thread([this]{
 		setThreadName("runServer");
 		server->run();
@@ -68,7 +73,7 @@ int ServerProcessRunner::exitCode()
 	return child->exit_code();
 }
 
-void ServerProcessRunner::start(uint16_t port, bool connectToLobby)
+void ServerProcessRunner::start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo)
 {
 	boost::filesystem::path serverPath = VCMIDirs::get().serverPath();
 	boost::filesystem::path logPath = VCMIDirs::get().userLogsPath() / "server_log.txt";

+ 9 - 3
client/ServerRunner.h

@@ -9,12 +9,18 @@
  */
 #pragma once
 
+VCMI_LIB_NAMESPACE_BEGIN
+
+struct StartInfo;
+
+VCMI_LIB_NAMESPACE_END
+
 class CVCMIServer;
 
 class IServerRunner
 {
 public:
-	virtual void start(uint16_t port, bool connectToLobby) = 0;
+	virtual void start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) = 0;
 	virtual void shutdown() = 0;
 	virtual void wait() = 0;
 	virtual int exitCode() = 0;
@@ -28,7 +34,7 @@ class ServerThreadRunner : public IServerRunner, boost::noncopyable
 	std::unique_ptr<CVCMIServer> server;
 	boost::thread threadRunLocalServer;
 public:
-	void start(uint16_t port, bool connectToLobby) override;
+	void start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) override;
 	void shutdown() override;
 	void wait() override;
 	int exitCode() override;
@@ -50,7 +56,7 @@ class ServerProcessRunner : public IServerRunner, boost::noncopyable
 	std::unique_ptr<boost::process::child> child;
 
 public:
-	void start(uint16_t port, bool connectToLobby) override;
+	void start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) override;
 	void shutdown() override;
 	void wait() override;
 	int exitCode() override;

+ 10 - 0
client/lobby/CLobbyScreen.cpp

@@ -156,6 +156,16 @@ void CLobbyScreen::startCampaign()
 
 void CLobbyScreen::startScenario(bool allowOnlyAI)
 {
+	if (tabRand && CSH->si->mapGenOptions)
+	{
+		// Save RMG settings at game start
+		tabRand->saveOptions(*CSH->si->mapGenOptions);
+	}
+
+	// Save chosen difficulty
+	Settings lastDifficulty = settings.write["general"]["lastDifficulty"];
+	lastDifficulty->Integer() = getCurrentDifficulty();
+
 	if (CSH->validateGameStart(allowOnlyAI))
 	{
 		CSH->sendStartGame(allowOnlyAI);

+ 43 - 6
client/lobby/RandomMapTab.cpp

@@ -38,6 +38,10 @@
 #include "../../lib/filesystem/Filesystem.h"
 #include "../../lib/RoadHandler.h"
 
+#include "../../lib/CConfigHandler.h"
+#include "../../lib/serializer/JsonSerializer.h"
+#include "../../lib/serializer/JsonDeserializer.h"
+
 RandomMapTab::RandomMapTab():
 	InterfaceObjectConfigurable()
 {
@@ -162,7 +166,7 @@ RandomMapTab::RandomMapTab():
 		};
 	}
 	
-	updateMapInfoByHost();
+	loadOptions();
 }
 
 void RandomMapTab::updateMapInfoByHost()
@@ -461,7 +465,7 @@ TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab & randomMapTab):
 	//int totalPlayers = randomMapTab.obtainMapGenOptions().getPlayerLimit();
 	int totalPlayers = randomMapTab.obtainMapGenOptions().getMaxPlayersCount();
 	assert(totalPlayers <= PlayerColor::PLAYER_LIMIT_I);
-	auto settings = randomMapTab.obtainMapGenOptions().getPlayersSettings();
+	auto playerSettings = randomMapTab.obtainMapGenOptions().getPlayersSettings();
 	variables["totalPlayers"].Integer() = totalPlayers;
 	
 	pos.w = variables["windowSize"]["x"].Integer() + totalPlayers * variables["cellMargin"]["x"].Integer();
@@ -502,20 +506,20 @@ TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab & randomMapTab):
 	// Window should have X * X columns, where X is max players allowed for current settings
 	// For random player count, X is 8
 
-	if (totalPlayers > settings.size())
+	if (totalPlayers > playerSettings.size())
 	{
 		auto savedPlayers = randomMapTab.obtainMapGenOptions().getSavedPlayersMap();
 		for (const auto & player : savedPlayers)
 		{
-			if (!vstd::contains(settings, player.first))
+			if (!vstd::contains(playerSettings, player.first))
 			{
-				settings[player.first] = player.second;
+				playerSettings[player.first] = player.second;
 			}
 		}
 	}
 
 	std::vector<CMapGenOptions::CPlayerSettings> settingsVec;
-	for (const auto & player : settings)
+	for (const auto & player : playerSettings)
 	{
 		settingsVec.push_back(player.second);
 	}
@@ -569,3 +573,36 @@ TeamAlignmentsWidget::TeamAlignmentsWidget(RandomMapTab & randomMapTab):
 	buttonOk = widget<CButton>("buttonOK");
 	buttonCancel = widget<CButton>("buttonCancel");
 }
+
+void RandomMapTab::saveOptions(const CMapGenOptions & options)
+{
+	JsonNode data;
+	JsonSerializer ser(nullptr, data);
+
+	ser.serializeStruct("lastSettings", const_cast<CMapGenOptions & >(options));
+
+	// FIXME: Do not nest fields
+	Settings rmgSettings = persistentStorage.write["rmg"];
+	rmgSettings["rmg"] = data;
+}
+
+void RandomMapTab::loadOptions()
+{
+	auto rmgSettings = persistentStorage["rmg"]["rmg"];
+	if (!rmgSettings.Struct().empty())
+	{
+		mapGenOptions.reset(new CMapGenOptions());
+		JsonDeserializer handler(nullptr, rmgSettings);
+		handler.serializeStruct("lastSettings", *mapGenOptions);
+
+		// Will check template and set other options as well
+		setTemplate(mapGenOptions->getMapTemplate());
+		if(auto w = widget<ComboBox>("templateList"))
+		{
+			w->setItem(mapGenOptions->getMapTemplate());
+		}
+	}
+	updateMapInfoByHost();
+
+	// TODO: Save & load difficulty?
+}

+ 4 - 1
client/lobby/RandomMapTab.h

@@ -36,6 +36,9 @@ public:
 	void updateMapInfoByHost();
 	void setMapGenOptions(std::shared_ptr<CMapGenOptions> opts);
 	void setTemplate(const CRmgTemplate *);
+
+	void saveOptions(const CMapGenOptions & options);
+	void loadOptions();
 	CMapGenOptions & obtainMapGenOptions() {return *mapGenOptions;}
 
 	CFunctionList<void(std::shared_ptr<CMapInfo>, std::shared_ptr<CMapGenOptions>)> mapInfoChanged;
@@ -44,8 +47,8 @@ private:
 	void deactivateButtonsFrom(CToggleGroup & group, const std::set<int> & allowed);
 	std::vector<int> getPossibleMapSizes();
 
-	std::shared_ptr<CMapGenOptions> mapGenOptions;
 	std::shared_ptr<CMapInfo> mapInfo;
+	std::shared_ptr<CMapGenOptions> mapGenOptions;
 	
 	//options allowed - need to store as impact each other
 	std::set<int> playerCountAllowed;

+ 6 - 1
client/lobby/SelectionTab.cpp

@@ -167,7 +167,12 @@ SelectionTab::SelectionTab(ESelectionScreen Type)
 		inputName->filters += CTextInput::filenameFilter;
 		labelMapSizes = std::make_shared<CLabel>(87, 62, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[510]);
 
-		int sizes[] = {36, 72, 108, 144, 0};
+		// TODO: Global constants?
+		int sizes[] = {CMapHeader::MAP_SIZE_SMALL,
+						CMapHeader::MAP_SIZE_MIDDLE,
+						CMapHeader::MAP_SIZE_LARGE,
+						CMapHeader::MAP_SIZE_XLARGE,
+						0};
 		const char * filterIconNmes[] = {"SCSMBUT.DEF", "SCMDBUT.DEF", "SCLGBUT.DEF", "SCXLBUT.DEF", "SCALBUT.DEF"};
 		for(int i = 0; i < 5; i++)
 			buttonsSortBy.push_back(std::make_shared<CButton>(Point(158 + 47 * i, 46), AnimationPath::builtin(filterIconNmes[i]), CGI->generaltexth->zelp[54 + i], std::bind(&SelectionTab::filter, this, sizes[i], true)));

+ 1 - 2
client/widgets/ComboBox.h

@@ -51,8 +51,6 @@ class ComboBox : public CButton
 	};
 	
 	friend class DropDown;
-	
-	void setItem(const void *);
 
 public:
 	ComboBox(Point position, const AnimationPath & defName, const std::pair<std::string, std::string> & help, const JsonNode & dropDownDescriptor, Point dropDownPosition, EShortcut key = {}, bool playerColoredButton = false);
@@ -67,6 +65,7 @@ public:
 	std::function<std::string(int, const void *)> getItemText;
 	
 	void setItem(int id);
+	void setItem(const void *);
 
 	void updateListItems();
 };

+ 5 - 0
config/schemas/settings.json

@@ -28,6 +28,7 @@
 				"lastSave",
 				"lastSettingsTab",
 				"lastCampaign",
+				"lastDifficulty",
 				"saveFrequency",
 				"notifications",
 				"extraDump",
@@ -85,6 +86,10 @@
 					"type" : "string",
 					"default" : ""
 				},
+				"lastDifficulty" : {
+					"type" : "number",
+					"default" : 1
+				},
 				"saveFrequency" : {
 					"type" : "number",
 					"default" : 1

+ 32 - 0
lib/rmg/CMapGenOptions.cpp

@@ -17,6 +17,7 @@
 #include "CRandomGenerator.h"
 #include "../VCMI_Lib.h"
 #include "../CTownHandler.h"
+#include "serializer/JsonSerializeFormat.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -816,4 +817,35 @@ void CMapGenOptions::CPlayerSettings::setTeam(const TeamID & value)
 	team = value;
 }
 
+void CMapGenOptions::serializeJson(JsonSerializeFormat & handler)
+{
+	handler.serializeInt("width", width);
+	handler.serializeInt("height", height);
+	handler.serializeBool("haswoLevels", hasTwoLevels);
+	handler.serializeInt("humanOrCpuPlayerCount", humanOrCpuPlayerCount);
+	handler.serializeInt("teamCount", teamCount);
+	handler.serializeInt("compOnlyPlayerCount", compOnlyPlayerCount);
+	handler.serializeInt("compOnlyTeamCount", compOnlyTeamCount);
+	handler.serializeInt("waterContent", waterContent);
+	handler.serializeInt("monsterStrength", monsterStrength);
+
+	std::string templateName;
+	if(mapTemplate && handler.saving)
+	{
+		templateName = mapTemplate->getId();
+	}
+	handler.serializeString("templateName", templateName);
+	if(!handler.saving)
+	{
+		setMapTemplate(templateName);
+	}
+
+	handler.serializeIdArray("roads", enabledRoads);
+	if (!handler.saving)
+	{
+		// Player settings won't be saved
+		resetPlayersMap();
+	}
+}
+
 VCMI_LIB_NAMESPACE_END

+ 2 - 0
lib/rmg/CMapGenOptions.h

@@ -210,6 +210,8 @@ public:
 
 		h & enabledRoads;
 	}
+
+	void serializeJson(JsonSerializeFormat & handler);
 };
 
 VCMI_LIB_NAMESPACE_END

+ 14 - 14
lib/rmg/CRmgTemplate.cpp

@@ -841,20 +841,20 @@ void CRmgTemplate::serializeSize(JsonSerializeFormat & handler, int3 & value, co
 {
 	static const std::map<std::string, int3> sizeMapping =
 	{
-		{"s",    { 36,  36, 1}},
-		{"s+u",  { 36,  36, 2}},
-		{"m",    { 72,  72, 1}},
-		{"m+u",  { 72,  72, 2}},
-		{"l",    {108, 108, 1}},
-		{"l+u",  {108, 108, 2}},
-		{"xl",   {144, 144, 1}},
-		{"xl+u", {144, 144, 2}},
-		{"h",    {180, 180, 1}},
-		{"h+u",  {180, 180, 2}},
-		{"xh",   {216, 216, 1}},
-		{"xh+u", {216, 216, 2}},
-		{"g",    {252, 252, 1}},
-		{"g+u",  {252, 252, 2}}
+		{"s",    {CMapHeader::MAP_SIZE_SMALL, 	CMapHeader::MAP_SIZE_SMALL, 	1}},
+		{"s+u",  {CMapHeader::MAP_SIZE_SMALL, 	CMapHeader::MAP_SIZE_SMALL, 	2}},
+		{"m",    {CMapHeader::MAP_SIZE_MIDDLE, 	CMapHeader::MAP_SIZE_MIDDLE, 	1}},
+		{"m+u",  {CMapHeader::MAP_SIZE_MIDDLE, 	CMapHeader::MAP_SIZE_MIDDLE, 	2}},
+		{"l",    {CMapHeader::MAP_SIZE_LARGE, 	CMapHeader::MAP_SIZE_LARGE, 	1}},
+		{"l+u",  {CMapHeader::MAP_SIZE_LARGE, 	CMapHeader::MAP_SIZE_LARGE, 	2}},
+		{"xl",   {CMapHeader::MAP_SIZE_XLARGE, 	CMapHeader::MAP_SIZE_XLARGE, 	1}}	,
+		{"xl+u", {CMapHeader::MAP_SIZE_XLARGE, 	CMapHeader::MAP_SIZE_XLARGE, 	2}}	,
+		{"h",    {CMapHeader::MAP_SIZE_HUGE, 	CMapHeader::MAP_SIZE_HUGE, 		1}},
+		{"h+u",  {CMapHeader::MAP_SIZE_HUGE, 	CMapHeader::MAP_SIZE_HUGE, 		2}},
+		{"xh",   {CMapHeader::MAP_SIZE_XHUGE, 	CMapHeader::MAP_SIZE_XHUGE, 	1}},
+		{"xh+u", {CMapHeader::MAP_SIZE_XHUGE, 	CMapHeader::MAP_SIZE_XHUGE, 	2}},
+		{"g",    {CMapHeader::MAP_SIZE_GIANT,	CMapHeader::MAP_SIZE_GIANT,		1}},
+		{"g+u",  {CMapHeader::MAP_SIZE_GIANT,	CMapHeader::MAP_SIZE_GIANT,		2}}
 	};
 
 	static const std::map<int3, std::string> sizeReverseMapping = vstd::invertMap(sizeMapping);

+ 1 - 0
mapeditor/jsonutils.cpp

@@ -69,6 +69,7 @@ QVariant toVariant(const JsonNode & node)
 		return QVariant(node.Bool());
 		break;
 	case JsonNode::JsonType::DATA_FLOAT:
+	case JsonNode::JsonType::DATA_INTEGER:
 		return QVariant(node.Float());
 		break;
 	case JsonNode::JsonType::DATA_STRING:

+ 80 - 110
mapeditor/windownewmap.cpp

@@ -17,7 +17,10 @@
 #include "../lib/mapping/CMapEditManager.h"
 #include "../lib/mapping/MapFormat.h"
 #include "../lib/CGeneralTextHandler.h"
+#include "../lib/serializer/JsonSerializer.h"
+#include "../lib/serializer/JsonDeserializer.h"
 
+#include "jsonutils.h"
 #include "windownewmap.h"
 #include "ui_windownewmap.h"
 #include "mainwindow.h"
@@ -52,84 +55,77 @@ WindowNewMap::WindowNewMap(QWidget *parent) :
 		ui->cpuTeamsCombo->setItemData(i, QVariant(cpuPlayers.at(i)));
 	}
 	
-	for(auto * combo : {ui->humanCombo, ui->cpuCombo, ui->humanTeamsCombo, ui->cpuTeamsCombo})
-		combo->setCurrentIndex(0);
 
-	loadUserSettings();
+	bool useLoaded = loadUserSettings();
+	if (!useLoaded)
+	{
+		for(auto * combo : {ui->humanCombo, ui->cpuCombo, ui->humanTeamsCombo, ui->cpuTeamsCombo})
+			combo->setCurrentIndex(0);
+	}
 
 	show();
 
-	//setup initial parameters
-	int width = ui->widthTxt->text().toInt();
-	int height = ui->heightTxt->text().toInt();
-	mapGenOptions.setWidth(width ? width : 1);
-	mapGenOptions.setHeight(height ? height : 1);
-	bool twoLevel = ui->twoLevelCheck->isChecked();
-	mapGenOptions.setHasTwoLevels(twoLevel);
-	updateTemplateList();
+	if (!useLoaded)
+	{
+		//setup initial parameters
+		int width = ui->widthTxt->text().toInt();
+		int height = ui->heightTxt->text().toInt();
+		mapGenOptions.setWidth(width ? width : 1);
+		mapGenOptions.setHeight(height ? height : 1);
+		bool twoLevel = ui->twoLevelCheck->isChecked();
+		mapGenOptions.setHasTwoLevels(twoLevel);
+
+		updateTemplateList();
+	}
 }
 
 WindowNewMap::~WindowNewMap()
 {
-	saveUserSettings();
 	delete ui;
 }
 
-void WindowNewMap::loadUserSettings()
+bool WindowNewMap::loadUserSettings()
 {
-	//load window settings
+	bool ret = false;
+	CRmgTemplate * templ = nullptr;
+
 	QSettings s(Ui::teamName, Ui::appName);
 
-	auto width = s.value(newMapWidth);
-	if (width.isValid())
-	{
-		ui->widthTxt->setText(width.toString());
-	}
-	auto height = s.value(newMapHeight);
-	if (height.isValid())
-	{
-		ui->heightTxt->setText(height.toString());
-	}
-	for(auto & sz : mapSizes)
-	{
-		if(sz.second.first == width.toInt() && sz.second.second == height.toInt())
-			ui->sizeCombo->setCurrentIndex(sz.first);
-	}
-	auto twoLevel = s.value(newMapTwoLevel);
-	if (twoLevel.isValid())
-	{
-		ui->twoLevelCheck->setChecked(twoLevel.toBool());
-	}
 	auto generateRandom = s.value(newMapGenerateRandom);
 	if (generateRandom.isValid())
 	{
 		ui->randomMapCheck->setChecked(generateRandom.toBool());
 	}
-	auto players = s.value(newMapPlayers);
-	if (players.isValid())
-	{
-		ui->humanCombo->setCurrentIndex(players.toInt());
-	}
-	auto cpuPlayers = s.value(newMapCpuPlayers);
-	if (cpuPlayers.isValid())
-	{
-		ui->cpuCombo->setCurrentIndex(cpuPlayers.toInt());
-	}
-	auto teams = s.value(newMapHumanTeams);
-	if(teams.isValid())
-	{
-		ui->humanTeamsCombo->setCurrentIndex(teams.toInt());
-	}
-	auto cputeams = s.value(newMapCpuTeams);
-	if(cputeams.isValid())
-	{
-		ui->cpuTeamsCombo->setCurrentIndex(cputeams.toInt());
-	}
-	
-	auto waterContent = s.value(newMapWaterContent);
-	if (waterContent.isValid())
+
+	auto settings = s.value(newMapWindow);
+
+	if (settings.isValid())
 	{
-		switch (waterContent.toInt())
+		auto node = JsonUtils::toJson(settings);
+		JsonDeserializer handler(nullptr, node);
+		handler.serializeStruct("lastSettings", mapGenOptions);
+		templ = const_cast<CRmgTemplate*>(mapGenOptions.getMapTemplate()); // Remember for later
+
+		ui->widthTxt->setText(QString::number(mapGenOptions.getWidth()));
+		ui->heightTxt->setText(QString::number(mapGenOptions.getHeight()));
+		for(auto & sz : mapSizes)
+		{
+			if(sz.second.first == mapGenOptions.getWidth() &&
+			sz.second.second == mapGenOptions.getHeight())
+			{
+				ui->sizeCombo->setCurrentIndex(sz.first);
+				break;
+			}
+		}
+
+		ui->twoLevelCheck->setChecked(mapGenOptions.getHasTwoLevels());
+
+		ui->humanCombo->setCurrentIndex(mapGenOptions.getHumanOrCpuPlayerCount());
+		ui->cpuCombo->setCurrentIndex(mapGenOptions.getCompOnlyPlayerCount());
+		ui->humanTeamsCombo->setCurrentIndex(mapGenOptions.getTeamCount());
+		ui->cpuTeamsCombo->setCurrentIndex(mapGenOptions.getCompOnlyTeamCount());
+
+		switch (mapGenOptions.getWaterContent())
 		{
 			case EWaterContent::RANDOM:
 				ui->waterOpt1->setChecked(true); break;
@@ -141,11 +137,7 @@ void WindowNewMap::loadUserSettings()
 				ui->waterOpt4->setChecked(true); break;
 		}
 
-	}
-	auto monsterStrength = s.value(newMapMonsterStrength);
-	if (monsterStrength.isValid())
-	{
-		switch (monsterStrength.toInt())
+		switch (mapGenOptions.getMonsterStrength())
 		{
 			case EMonsterStrength::RANDOM:
 				ui->monsterOpt1->setChecked(true); break;
@@ -156,71 +148,47 @@ void WindowNewMap::loadUserSettings()
 			case EMonsterStrength::GLOBAL_STRONG:
 				ui->monsterOpt4->setChecked(true); break;
 		}
+
+		ret = true;
 	}
 
-	auto templateName = s.value(newMapTemplate);
-	if (templateName.isValid())
+	updateTemplateList();
+	mapGenOptions.setMapTemplate(templ); // Can be null
+
+	if (templ)
 	{
-		updateTemplateList();
-		
-		auto* templ = VLC->tplh->getTemplate(templateName.toString().toStdString());
-		if (templ)
-		{
-			ui->templateCombo->setCurrentText(templateName.toString());
-			//TODO: validate inside this method
-			mapGenOptions.setMapTemplate(templ);
-		}
-		else
+		std::string name = templ->getName();
+		for (size_t i = 0; i < ui->templateCombo->count(); i++)
 		{
-			//Display problem on status bar
+			if (ui->templateCombo->itemText(i).toStdString() == name)
+			{
+				ui->templateCombo->setCurrentIndex(i);
+				break;
+			}
 		}
+		ret = true;
 	}
+
+	return ret;
 }
 
 void WindowNewMap::saveUserSettings()
 {
 	QSettings s(Ui::teamName, Ui::appName);
-	s.setValue(newMapWidth, ui->widthTxt->text().toInt());
-	s.setValue(newMapHeight, ui->heightTxt->text().toInt());
-	s.setValue(newMapTwoLevel, ui->twoLevelCheck->isChecked());
-	s.setValue(newMapGenerateRandom, ui->randomMapCheck->isChecked());
 
-	s.setValue(newMapPlayers,ui->humanCombo->currentIndex());
-	s.setValue(newMapCpuPlayers,ui->cpuCombo->currentIndex());
-	s.setValue(newMapHumanTeams, ui->humanTeamsCombo->currentIndex());
-	s.setValue(newMapCpuTeams, ui->cpuTeamsCombo->currentIndex());
+	JsonNode data;
+	JsonSerializer ser(nullptr, data);
 
-	EWaterContent::EWaterContent water = EWaterContent::RANDOM;
-	if(ui->waterOpt1->isChecked())
-		water = EWaterContent::RANDOM;
-	else if(ui->waterOpt2->isChecked())
-		water = EWaterContent::NONE;
-	else if(ui->waterOpt3->isChecked())
-		water = EWaterContent::NORMAL;
-	else if(ui->waterOpt4->isChecked())
-		water = EWaterContent::ISLANDS;
-	s.setValue(newMapWaterContent, static_cast<int>(water));
-
-	EMonsterStrength::EMonsterStrength monster = EMonsterStrength::RANDOM;
-	if(ui->monsterOpt1->isChecked())
-		monster = EMonsterStrength::RANDOM;
-	else if(ui->monsterOpt2->isChecked())
-		monster = EMonsterStrength::GLOBAL_WEAK;
-	else if(ui->monsterOpt3->isChecked())
-		monster = EMonsterStrength::GLOBAL_NORMAL;
-	else if(ui->monsterOpt4->isChecked())
-		monster = EMonsterStrength::GLOBAL_STRONG;
-	s.setValue(newMapMonsterStrength, static_cast<int>(monster));
+	ser.serializeStruct("lastSettings", mapGenOptions);
 
-	auto templateName = ui->templateCombo->currentText();
-	if (templateName.size())
-	{
-		s.setValue(newMapTemplate, templateName);
-	}
+	auto variant = JsonUtils::toVariant(data);
+	s.setValue(newMapWindow, variant);
+	s.setValue(newMapGenerateRandom, ui->randomMapCheck->isChecked());
 }
 
 void WindowNewMap::on_cancelButton_clicked()
 {
+	saveUserSettings();
 	close();
 }
 
@@ -267,6 +235,8 @@ void WindowNewMap::on_okButton_clicked()
 	mapGenOptions.setWaterContent(water);
 	mapGenOptions.setMonsterStrength(monster);
 	
+	saveUserSettings();
+
 	std::unique_ptr<CMap> nmap;
 	if(ui->randomMapCheck->isChecked())
 	{

+ 9 - 5
mapeditor/windownewmap.h

@@ -22,6 +22,7 @@ class WindowNewMap : public QDialog
 {
 	Q_OBJECT
 
+	const QString newMapWindow = "NewMapWindow/Settings";
 	const QString newMapWidth = "NewMapWindow/Width";
 	const QString newMapHeight = "NewMapWindow/Height";
 	const QString newMapTwoLevel = "NewMapWindow/TwoLevel";
@@ -64,10 +65,13 @@ class WindowNewMap : public QDialog
 	
 	const std::map<int, std::pair<int, int>> mapSizes
 	{
-		{0, {36, 36}},
-		{1, {72, 72}},
-		{2, {108, 108}},
-		{3, {144, 144}},
+		{0, {CMapHeader::MAP_SIZE_SMALL, 	CMapHeader::MAP_SIZE_SMALL}},
+		{1, {CMapHeader::MAP_SIZE_MIDDLE,	CMapHeader::MAP_SIZE_MIDDLE}},
+		{2, {CMapHeader::MAP_SIZE_LARGE,	CMapHeader::MAP_SIZE_LARGE}},
+		{3, {CMapHeader::MAP_SIZE_XLARGE,	CMapHeader::MAP_SIZE_XLARGE}},
+		{4, {CMapHeader::MAP_SIZE_HUGE,		CMapHeader::MAP_SIZE_HUGE}},
+		{5, {CMapHeader::MAP_SIZE_XHUGE,	CMapHeader::MAP_SIZE_XHUGE}},
+		{6, {CMapHeader::MAP_SIZE_GIANT,	CMapHeader::MAP_SIZE_GIANT}},
 	};
 
 public:
@@ -105,7 +109,7 @@ private:
 
 	void updateTemplateList();
 
-	void loadUserSettings();
+	bool loadUserSettings();
 	void saveUserSettings();
 
 private:

+ 33 - 6
mapeditor/windownewmap.ui

@@ -51,11 +51,11 @@
      <rect>
       <x>0</x>
       <y>20</y>
-      <width>261</width>
+      <width>281</width>
       <height>68</height>
      </rect>
     </property>
-    <layout class="QGridLayout" name="gridLayout_2" columnstretch="1,0,0">
+    <layout class="QGridLayout" name="gridLayout_2" columnstretch="3,0,1">
      <item row="1" column="0">
       <widget class="QCheckBox" name="twoLevelCheck">
        <property name="text">
@@ -65,6 +65,12 @@
      </item>
      <item row="0" column="2">
       <widget class="QLineEdit" name="widthTxt">
+       <property name="maximumSize">
+        <size>
+         <width>64</width>
+         <height>16777215</height>
+        </size>
+       </property>
        <property name="inputMethodHints">
         <set>Qt::ImhDigitsOnly</set>
        </property>
@@ -85,6 +91,12 @@
      </item>
      <item row="1" column="2">
       <widget class="QLineEdit" name="heightTxt">
+       <property name="maximumSize">
+        <size>
+         <width>64</width>
+         <height>16777215</height>
+        </size>
+       </property>
        <property name="inputMethodHints">
         <set>Qt::ImhDigitsOnly</set>
        </property>
@@ -143,23 +155,23 @@
          </property>
          <property name="maximumSize">
           <size>
-           <width>120</width>
+           <width>144</width>
            <height>16777215</height>
           </size>
          </property>
          <item>
           <property name="text">
-           <string>S (36x36)</string>
+           <string>S  (36x36)</string>
           </property>
          </item>
          <item>
           <property name="text">
-           <string>M (72x72)</string>
+           <string>M  (72x72)</string>
           </property>
          </item>
          <item>
           <property name="text">
-           <string>L (108x108)</string>
+           <string>L  (108x108)</string>
           </property>
          </item>
          <item>
@@ -167,6 +179,21 @@
            <string>XL (144x144)</string>
           </property>
          </item>
+         <item>
+          <property name="text">
+           <string>H  (180x180)</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>XH (216x216)</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>G  (252x252)</string>
+          </property>
+         </item>
         </widget>
        </item>
       </layout>