diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.js b/binaries/data/mods/public/gui/gamesetup/gamesetup.js
index 0d2c86358a..6ce3102757 100644
--- a/binaries/data/mods/public/gui/gamesetup/gamesetup.js
+++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.js
@@ -107,8 +107,8 @@ function initMain()
// Init map types
var mapTypes = getGUIObjectByName("mapTypeSelection");
- mapTypes.list = ["Scenario","Random"];
- mapTypes.list_data = ["scenario","random"];
+ mapTypes.list = ["Scenario","Skirmish","Random"];
+ mapTypes.list_data = ["scenario","skirmish","random"];
// Setup map filters - will appear in order they are added
addFilter("Default", function(settings) { return settings && !keywordTestOR(settings.Keywords, ["naval", "demo", "hidden"]); });
@@ -471,6 +471,7 @@ function initMapNameList()
switch (g_GameAttributes.mapType)
{
case "scenario":
+ case "skirmish":
mapFiles = getXMLFileList(g_GameAttributes.mapPath);
break;
@@ -487,7 +488,7 @@ function initMapNameList()
var mapList = [];
for (var i = 0; i < mapFiles.length; ++i)
{
- var file = mapFiles[i];
+ var file = g_GameAttributes.mapPath + mapFiles[i];
var mapData = loadMapData(file);
if (g_GameAttributes.mapFilter && mapData && testFilter(g_GameAttributes.mapFilter, mapData.settings))
@@ -521,22 +522,20 @@ function loadMapData(name)
if (!name)
return undefined;
- if (name == "random")
- {
- g_MapData[name] = {settings : {"Name" : "Random", "Description" : "Randomly selects a map from the list"}};
- return g_MapData[name];
- }
-
if (!g_MapData[name])
{
switch (g_GameAttributes.mapType)
{
case "scenario":
- g_MapData[name] = Engine.LoadMapSettings(g_GameAttributes.mapPath+name);
+ case "skirmish":
+ g_MapData[name] = Engine.LoadMapSettings(name);
break;
case "random":
- g_MapData[name] = parseJSONData(g_GameAttributes.mapPath+name+".json");
+ if (name == "random")
+ g_MapData[name] = {settings : {"Name" : "Random", "Description" : "Randomly selects a map from the list"}};
+ else
+ g_MapData[name] = parseJSONData(name+".json");
break;
default:
@@ -652,8 +651,17 @@ function selectMapType(type)
case "scenario":
// Set a default map
// TODO: This should be remembered from the last session
- g_GameAttributes.map = (g_IsNetworked ? DEFAULT_NETWORKED_MAP : DEFAULT_OFFLINE_MAP);
g_GameAttributes.mapPath = "maps/scenarios/";
+ g_GameAttributes.map = g_GameAttributes.mapPath + (g_IsNetworked ? DEFAULT_NETWORKED_MAP : DEFAULT_OFFLINE_MAP);
+ break;
+
+ case "skirmish":
+ g_GameAttributes.mapPath = "maps/skirmishes/";
+ g_GameAttributes.settings = {
+ PlayerData: g_DefaultPlayerData.slice(0, 4),
+ Seed: Math.floor(Math.random() * 65536),
+ CheatsEnabled: g_GameAttributes.settings.CheatsEnabled
+ };
break;
case "random":
@@ -799,8 +807,8 @@ function launchGame()
var chosenName = civAINames[i];
else
var chosenName = civAINames[Math.floor(Math.random() * civAINames.length)];
- for (var j = 0; j < numPlayers; ++j)
- if (g_GameAttributes.settings.PlayerData[j].Name.indexOf(chosenName) !== -1)
+ for (var j = 0; j < numPlayers; ++j)
+ if (g_GameAttributes.settings.PlayerData[j].Name && g_GameAttributes.settings.PlayerData[j].Name.indexOf(chosenName) !== -1)
usedName++;
// Assign civ specific names to AI players
@@ -899,12 +907,16 @@ function onGameAttributesChange()
startingResources.selected = (STARTING_RESOURCES_DATA.indexOf(mapSettings.StartingResources) != -1 ? STARTING_RESOURCES_DATA.indexOf(mapSettings.StartingResources) : STARTING_RESOURCES_DEFAULTIDX);
startingResourcesText.caption = STARTING_RESOURCES[startingResources.selected];
+ // Update map preview
+ getGUIObjectByName("mapPreview").sprite = "cropped:(0.78125,0.5859375)session/icons/mappreview/" + getMapPreview(mapName);
+
// Handle map type specific logic
switch (g_GameAttributes.mapType)
{
case "random":
if (g_IsController)
- { //Host
+ {
+ //Host
numPlayersSelection.selected = numPlayers - 1;
numPlayersSelection.hidden = false;
mapSize.hidden = false;
@@ -922,9 +934,6 @@ function onGameAttributesChange()
populationCapText.hidden = true;
startingResourcesText.hidden = true;
- // Update map preview
- getGUIObjectByName("mapPreview").sprite = "cropped:(0.78125,0.5859375)session/icons/mappreview/" + getMapPreview(mapName);
-
mapSizeText.caption = "Map size:";
mapSize.selected = sizeIdx;
revealMapText.caption = "Reveal map:";
@@ -947,8 +956,6 @@ function onGameAttributesChange()
populationCapText.hidden = false;
startingResources.hidden = true;
startingResourcesText.hidden = false;
- // Update map preview
- getGUIObjectByName("mapPreview").sprite = "cropped:(0.78125,0.5859375)session/icons/mappreview/" + getMapPreview(mapName);
numPlayersText.caption = numPlayers;
mapSizeText.caption = g_MapSizes.names[sizeIdx];
@@ -959,6 +966,57 @@ function onGameAttributesChange()
break;
+ case "skirmish":
+ mapSizeText.caption = "Default";
+ numPlayersText.caption = numPlayers;
+ numPlayersSelection.hidden = true;
+ mapSize.hidden = true;
+ if (g_IsController)
+ {
+ //Host
+ revealMap.hidden = false;
+ victoryCondition.hidden = false;
+ lockTeams.hidden = false;
+ populationCap.hidden = false;
+ startingResources.hidden = false;
+
+ numPlayersText.hidden = false;
+ mapSizeText.hidden = false;
+ revealMapText.hidden = true;
+ victoryConditionText.hidden = true;
+ lockTeamsText.hidden = true;
+ populationCapText.hidden = true;
+ startingResourcesText.hidden = true;
+
+ revealMapText.caption = "Reveal map:";
+ revealMap.checked = (mapSettings.RevealMap ? true : false);
+
+ victoryConditionText.caption = "Victory condition:";
+ victoryCondition.selected = victoryIdx;
+ lockTeamsText.caption = "Teams locked:";
+ lockTeams.checked = (mapSettings.LockTeams ? true : false);
+ }
+ else
+ {
+ // Client
+ numPlayersText.hidden = false;
+ mapSizeText.hidden = false;
+ revealMapText.hidden = false;
+ victoryConditionText.hidden = false;
+ lockTeamsText.hidden = false;
+ populationCap.hidden = true;
+ populationCapText.hidden = false;
+ startingResources.hidden = true;
+ startingResourcesText.hidden = false;
+
+ revealMapText.caption = (mapSettings.RevealMap ? "Yes" : "No");
+ victoryConditionText.caption = VICTORY_TEXT[victoryIdx];
+ lockTeamsText.caption = (mapSettings.LockTeams ? "Yes" : "No");
+ }
+
+ break;
+
+
case "scenario":
// For scenario just reflect settings for the current map
numPlayersSelection.hidden = true;
@@ -975,9 +1033,7 @@ function onGameAttributesChange()
populationCapText.hidden = false;
startingResources.hidden = true;
startingResourcesText.hidden = false;
-
- // Update map preview
- getGUIObjectByName("mapPreview").sprite = "cropped:(0.78125,0.5859375)session/icons/mappreview/" + getMapPreview(mapName);
+
numPlayersText.caption = numPlayers;
mapSizeText.caption = "Default";
revealMapText.caption = (mapSettings.RevealMap ? "Yes" : "No");
@@ -1046,7 +1102,7 @@ function onGameAttributesChange()
pCivText.caption = g_CivData[civ].Name;
pTeamText.caption = (team !== undefined && team >= 0) ? team+1 : "-";
}
- else if (g_GameAttributes.mapType == "random")
+ else if (g_GameAttributes.mapType != "scenario")
{
pCivText.hidden = true;
pCiv.hidden = false;
diff --git a/binaries/data/mods/public/gui/loading/loading.js b/binaries/data/mods/public/gui/loading/loading.js
index 8ca31919af..182d86cacf 100644
--- a/binaries/data/mods/public/gui/loading/loading.js
+++ b/binaries/data/mods/public/gui/loading/loading.js
@@ -46,6 +46,7 @@ function init(data)
var mapName = data.attribs.settings.Name;
switch (data.attribs.mapType)
{
+ case "skirmish":
case "scenario":
loadingMapName.caption = "Loading \"" + mapName + "\"";
break;
diff --git a/binaries/data/mods/public/simulation/components/SkirmishReplacer.js b/binaries/data/mods/public/simulation/components/SkirmishReplacer.js
new file mode 100644
index 0000000000..8ea0732e8d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/SkirmishReplacer.js
@@ -0,0 +1,63 @@
+const civList = ["general", "athen", "brit", "cart", "celt", "gaul", "hele", "iber", "mace", "maur", "pers", "rome", "spart"];
+
+function SkirmishReplacer() {}
+
+
+SkirmishReplacer.prototype.Schema = "";
+for each (var civ in civList)
+ SkirmishReplacer.prototype.Schema +=
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
+
+
+SkirmishReplacer.prototype.Init = function()
+{
+};
+
+SkirmishReplacer.prototype.OnOwnershipChanged = function(msg)
+{
+ if (msg.to == 0)
+ warn("Skirmish map elements can only be owned by regular players. Please delete entity "+this.entity+" or change the ownership to a non-gaia player.");
+};
+
+/**
+ * Replace this entity with a civ-specific entity on the first turn
+ */
+SkirmishReplacer.prototype.OnUpdate = function(msg)
+{
+ var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+ var civ = cmpPlayer.GetCiv();
+
+ var templateName = "";
+ if (civ in this.template)
+ templateName = this.template[civ];
+ else if ("general" in this.template)
+ templateName = this.template.general;
+
+ if (!templateName || civ == "gaia")
+ {
+ Engine.DestroyEntity(this.entity);
+ return;
+ }
+
+ templateName = templateName.replace(/\{civ\}/g, civ);
+
+ var cmpCurPosition = Engine.QueryInterface(this.entity, IID_Position);
+ var replacement = Engine.AddEntity(templateName);
+ var cmpReplacementPosition = Engine.QueryInterface(replacement, IID_Position)
+ var pos = cmpCurPosition.GetPosition2D();
+ cmpReplacementPosition.JumpTo(pos.x, pos.y);
+ var rot = cmpCurPosition.GetRotation();
+ cmpReplacementPosition.SetYRotation(rot.y);
+ var cmpCurOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+ var cmpReplacementOwnership = Engine.QueryInterface(replacement, IID_Ownership);
+ cmpReplacementOwnership.SetOwner(cmpCurOwnership.GetOwner());
+
+ Engine.DestroyEntity(this.entity);
+};
+
+Engine.RegisterComponentType(IID_SkirmishReplacer, "SkirmishReplacer", SkirmishReplacer);
diff --git a/binaries/data/mods/public/simulation/components/interfaces/SkirmishReplacer.js b/binaries/data/mods/public/simulation/components/interfaces/SkirmishReplacer.js
new file mode 100644
index 0000000000..7a972823fe
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/interfaces/SkirmishReplacer.js
@@ -0,0 +1 @@
+Engine.RegisterInterface("SkirmishReplacer");
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/default_civil_centre.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_civil_centre.xml
new file mode 100644
index 0000000000..513fcea81c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_civil_centre.xml
@@ -0,0 +1,12 @@
+
+
+
+ skirm
+
+
+ structures/{civ}_civil_centre
+
+
+ structures/athenians/civic_centre_new.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_gate.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_gate.xml
new file mode 100644
index 0000000000..03b31ed9bf
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_gate.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ 9.0
+
+
+ skirm
+
+
+
+
+
+
+
+
+
+ structures/{civ}_wall_gate
+
+
+
+ structures/hellenes/wall_gate.xml
+
+
+ 38.0
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_long.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_long.xml
new file mode 100644
index 0000000000..3010a88435
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_long.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ 9.0
+
+
+ skirm
+
+
+
+
+
+ structures/{civ}_wall_long
+
+
+
+ structures/hellenes/wall_long.xml
+
+
+ 36.0
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_medium.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_medium.xml
new file mode 100644
index 0000000000..260ab0d5e6
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_medium.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ 9.0
+
+
+ skirm
+
+
+
+
+
+ structures/{civ}_wall_medium
+
+
+
+ structures/hellenes/wall_medium.xml
+
+
+ 24.0
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_short.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_short.xml
new file mode 100644
index 0000000000..828120b38c
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_short.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ 9.0
+
+
+ skirm
+
+
+
+
+
+ structures/{civ}_wall_short
+
+
+
+ structures/hellenes/wall_short.xml
+
+
+ 12.0
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_tower.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_tower.xml
new file mode 100644
index 0000000000..caf4049bff
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/default_wall_tower.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ 15.0
+
+
+ skirm
+
+
+
+
+
+ structures/{civ}_wall_tower
+
+
+
+ structures/hellenes/wall_tower.xml
+
+
+ 10
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_gate.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_gate.xml
new file mode 100644
index 0000000000..6465999b52
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_gate.xml
@@ -0,0 +1,26 @@
+
+
+
+
+ 9.0
+
+
+ skirm
+
+
+
+
+
+
+
+
+
+ structures/iber_wall_gate
+
+
+ structures/iberians/wall_gate.xml
+
+
+ 36.0
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_long.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_long.xml
new file mode 100644
index 0000000000..97427264a2
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_long.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 9.0
+
+
+ skirm
+
+
+
+
+
+ structures/iber_wall_long
+
+
+ structures/iberians/wall_long.xml
+
+
+ 36.0
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_medium.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_medium.xml
new file mode 100644
index 0000000000..633b2353fc
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_medium.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 9.0
+
+
+ skirm
+
+
+
+
+
+ structures/iber_wall_medium
+
+
+ structures/iberians/wall_medium.xml
+
+
+ 24.0
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_short.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_short.xml
new file mode 100644
index 0000000000..f35cb8e31a
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_short.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 9.0
+
+
+ skirm
+
+
+
+
+
+ structures/iber_wall_short
+
+
+ structures/iberians/wall_short.xml
+
+
+ 12.0
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_tower.xml b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_tower.xml
new file mode 100644
index 0000000000..092fbc0f5b
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/structures/iber_wall_tower.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 15.0
+
+
+ skirm
+
+
+
+
+
+ structures/iber_wall_tower
+
+
+ structures/iberians/wall_tower.xml
+
+
+ 10
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/units/default_cavalry.xml b/binaries/data/mods/public/simulation/templates/skirmish/units/default_cavalry.xml
new file mode 100644
index 0000000000..db628bc6b7
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/units/default_cavalry.xml
@@ -0,0 +1,19 @@
+
+
+
+ skirm
+
+
+
+ units/{civ}_cavalry_javelinist_b
+ units/celt_cavalry_swordsman_b
+ units/gaul_cavalry_swordsman_b
+ units/hele_cavalry_swordsman_b
+ units/iber_cavalry_spearman_b
+ units/maur_support_elephant
+ units/rome_cavalry_spearman_b
+
+
+ units/athenians/cavalry_javelinist_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/units/default_infantry_melee_b.xml b/binaries/data/mods/public/simulation/templates/skirmish/units/default_infantry_melee_b.xml
new file mode 100644
index 0000000000..a001d15b7d
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/units/default_infantry_melee_b.xml
@@ -0,0 +1,14 @@
+
+
+
+ skirm
+
+
+
+ units/{civ}_infantry_spearman_b
+ units/rome_infantry_swordsman_b
+
+
+ units/athenians/infantry_spearman_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/units/default_infantry_ranged_b.xml b/binaries/data/mods/public/simulation/templates/skirmish/units/default_infantry_ranged_b.xml
new file mode 100644
index 0000000000..eea0a03ea3
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/units/default_infantry_ranged_b.xml
@@ -0,0 +1,18 @@
+
+
+
+ skirm
+
+
+
+ units/{civ}_infantry_javelinist_b
+ units/athen_infantry_slinger_b
+ units/brit_infantry_slinger_b
+ units/cart_infantry_archer_b
+ units/maur_infantry_archer_b
+ units/pers_infantry_archer_b
+
+
+ units/athenians/infantry_slinger_b.xml
+
+
diff --git a/binaries/data/mods/public/simulation/templates/skirmish/units/default_support_female_citizen.xml b/binaries/data/mods/public/simulation/templates/skirmish/units/default_support_female_citizen.xml
new file mode 100644
index 0000000000..060b0d23a1
--- /dev/null
+++ b/binaries/data/mods/public/simulation/templates/skirmish/units/default_support_female_citizen.xml
@@ -0,0 +1,12 @@
+
+
+
+ skirm
+
+
+ units/{civ}_support_female_citizen
+
+
+ units/athenians/female_citizen.xml
+
+
diff --git a/build/premake/premake4.lua b/build/premake/premake4.lua
index 0397111c2a..bba9714c99 100644
--- a/build/premake/premake4.lua
+++ b/build/premake/premake4.lua
@@ -951,6 +951,7 @@ function setup_atlas_projects()
"CustomControls/EditableListCtrl",
"CustomControls/FileHistory",
"CustomControls/HighResTimer",
+ "CustomControls/MapDialog",
"CustomControls/SnapSplitterWindow",
"CustomControls/VirtualDirTreeCtrl",
"CustomControls/Windows",
diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp
index 5230855faf..575e27b60d 100644
--- a/source/graphics/MapReader.cpp
+++ b/source/graphics/MapReader.cpp
@@ -64,7 +64,7 @@ CMapReader::CMapReader()
}
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
-void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
+void CMapReader::LoadMap(const VfsPath& pathname, const CScriptValRooted& settings, CTerrain *pTerrain_,
WaterManager* pWaterMan_, SkyManager* pSkyMan_,
CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_,
CSimulation2 *pSimulation2_, const CSimContext* pSimContext_, int playerID_, bool skipEntities)
@@ -83,6 +83,7 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
m_PlayerID = playerID_;
m_SkipEntities = skipEntities;
m_StartingCameraTarget = INVALID_ENTITY;
+ m_ScriptSettings = settings;
filename_xml = pathname.ChangeExtension(L".xml");
@@ -116,8 +117,11 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
if (pPostproc)
pPostproc->SetPostEffect(L"default");
- // load map settings script
- RegMemFun(this, &CMapReader::LoadScriptSettings, L"CMapReader::LoadScriptSettings", 50);
+ // load map or script settings script
+ if (settings.undefined())
+ RegMemFun(this, &CMapReader::LoadScriptSettings, L"CMapReader::LoadScriptSettings", 50);
+ else
+ RegMemFun(this, &CMapReader::LoadRMSettings, L"CMapReader::LoadRMSettings", 50);
// load player settings script (must be done before reading map)
RegMemFun(this, &CMapReader::LoadPlayerSettings, L"CMapReader::LoadPlayerSettings", 50);
@@ -138,7 +142,6 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
RegMemFun(this, &CMapReader::DelayLoadFinished, L"CMapReader::DelayLoadFinished", 5);
}
-
// LoadRandomMap: try to load the map data; reinitialise the scene to new data if successful
void CMapReader::LoadRandomMap(const CStrW& scriptFile, const CScriptValRooted& settings, CTerrain *pTerrain_,
WaterManager* pWaterMan_, SkyManager* pSkyMan_,
@@ -1196,6 +1199,7 @@ int CMapReader::DelayLoadFinished()
int CMapReader::LoadRMSettings()
{
// copy random map settings over to sim
+ ENSURE(pSimulation2);
pSimulation2->SetMapSettings(m_ScriptSettings);
return 0;
diff --git a/source/graphics/MapReader.h b/source/graphics/MapReader.h
index 169e08c0b2..3d61fc042f 100644
--- a/source/graphics/MapReader.h
+++ b/source/graphics/MapReader.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Wildfire Games.
+/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -53,7 +53,7 @@ public:
~CMapReader();
// LoadMap: try to load the map from given file; reinitialise the scene to new data if successful
- void LoadMap(const VfsPath& pathname, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*,
+ void LoadMap(const VfsPath& pathname, const CScriptValRooted& settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*,
CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc, CSimulation2*, const CSimContext*,
int playerID, bool skipEntities);
diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp
index f98c9d22e2..6913c2b2ed 100644
--- a/source/gui/scripting/ScriptFunctions.cpp
+++ b/source/gui/scripting/ScriptFunctions.cpp
@@ -421,7 +421,7 @@ CScriptVal LoadMapSettings(void* cbdata, VfsPath pathname)
CMapSummaryReader reader;
- if (reader.LoadMap(pathname.ChangeExtension(L".xml")) != PSRETURN_OK)
+ if (reader.LoadMap(pathname) != PSRETURN_OK)
return CScriptVal();
return reader.GetMapSettings(guiManager->GetScriptInterface()).get();
diff --git a/source/ps/Game.cpp b/source/ps/Game.cpp
index 761d65ee0f..2bf2d6c5e9 100644
--- a/source/ps/Game.cpp
+++ b/source/ps/Game.cpp
@@ -142,15 +142,7 @@ void CGame::RegisterInit(const CScriptValRooted& attribs, const std::string& sav
if (m_GameView)
m_GameView->RegisterInit();
- if (mapType == "scenario")
- {
- // Load scenario attributes
- std::wstring mapFile;
- m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "map", mapFile);
-
- m_World->RegisterInit(mapFile, m_PlayerID);
- }
- else if (mapType == "random")
+ if (mapType == "random")
{
// Load random map attributes
std::wstring scriptFile;
@@ -161,6 +153,16 @@ void CGame::RegisterInit(const CScriptValRooted& attribs, const std::string& sav
m_World->RegisterInitRMS(scriptFile, settings, m_PlayerID);
}
+ else
+ {
+ std::wstring mapFile;
+ m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "map", mapFile);
+ CScriptValRooted settings;
+ if (mapType == "skirmish")
+ m_Simulation2->GetScriptInterface().GetProperty(attribs.get(), "settings", settings);
+
+ m_World->RegisterInit(mapFile, settings, m_PlayerID);
+ }
if (m_IsSavedGame)
RegMemFun(this, &CGame::LoadInitialState, L"Loading game", 1000);
diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp
index aaff10dfaa..b675343747 100644
--- a/source/ps/GameSetup/GameSetup.cpp
+++ b/source/ps/GameSetup/GameSetup.cpp
@@ -1081,6 +1081,7 @@ bool Autostart(const CmdLineArgs& args)
* -autostart-ip=127.0.0.1 -- multiplayer connect to 127.0.0.1
* -autostart-random=104 -- random map, optional seed value = 104 (default is 0, random is -1)
* -autostart-size=192 -- random map size in tiles = 192 (default is 192)
+ * -autostart-civ=1:hele -- set player #1 civ to "hele"
*
* Examples:
* -autostart=Acropolis -autostart-host -autostart-players=2 -- Host game on Acropolis map, 2 players
@@ -1131,8 +1132,7 @@ bool Autostart(const CmdLineArgs& args)
}
// Random map definition will be loaded from JSON file, so we need to parse it
- std::wstring mapPath = L"maps/random/";
- std::wstring scriptPath = mapPath + autoStartName.FromUTF8() + L".json";
+ std::wstring scriptPath = L"maps/random/" + autoStartName.FromUTF8() + L".json";
CScriptValRooted scriptData = scriptInterface.ReadJSONFile(scriptPath);
if (!scriptData.undefined() && scriptInterface.GetProperty(scriptData.get(), "settings", settings))
{
@@ -1157,7 +1157,6 @@ bool Autostart(const CmdLineArgs& args)
}
scriptInterface.SetProperty(attrs.get(), "map", std::string(autoStartName));
- scriptInterface.SetProperty(attrs.get(), "mapPath", mapPath);
scriptInterface.SetProperty(attrs.get(), "mapType", std::string("random"));
scriptInterface.SetProperty(settings.get(), "Seed", seed); // Random seed
scriptInterface.SetProperty(settings.get(), "Size", mapSize); // Random map size (in patches)
@@ -1184,7 +1183,9 @@ bool Autostart(const CmdLineArgs& args)
}
else
{
- scriptInterface.SetProperty(attrs.get(), "map", std::string(autoStartName));
+ // TODO: support akirmish maps
+ std::string mapFile = "maps/scenarios/" + autoStartName;
+ scriptInterface.SetProperty(attrs.get(), "map", mapFile);
scriptInterface.SetProperty(attrs.get(), "mapType", std::string("scenario"));
}
diff --git a/source/ps/World.cpp b/source/ps/World.cpp
index 0a9ee5f3b6..879825ddfa 100644
--- a/source/ps/World.cpp
+++ b/source/ps/World.cpp
@@ -65,19 +65,19 @@ CWorld::CWorld(CGame *pGame):
/**
* Initializes the game world with the attributes provided.
**/
-void CWorld::RegisterInit(const CStrW& mapFile, int playerID)
+void CWorld::RegisterInit(const CStrW& mapFile, const CScriptValRooted& settings, int playerID)
{
// Load the map, if one was specified
if (mapFile.length())
{
- VfsPath mapfilename(VfsPath("maps/scenarios") / (mapFile + L".pmp"));
+ VfsPath mapfilename = VfsPath(mapFile).ChangeExtension(L".pmp");
CMapReader* reader = 0;
try
{
reader = new CMapReader;
CTriggerManager* pTriggerManager = NULL;
- reader->LoadMap(mapfilename, m_Terrain,
+ reader->LoadMap(mapfilename, settings, m_Terrain,
CRenderer::IsInitialised() ? g_Renderer.GetWaterManager() : NULL,
CRenderer::IsInitialised() ? g_Renderer.GetSkyManager() : NULL,
&g_LightEnv, m_pGame->GetView(),
@@ -89,8 +89,8 @@ void CWorld::RegisterInit(const CStrW& mapFile, int playerID)
catch (PSERROR_File& err)
{
delete reader;
- LOGERROR(L"Failed to load scenario %ls: %hs", mapfilename.string().c_str(), err.what());
- throw PSERROR_Game_World_MapLoadFailed("Failed to load scenario.\nCheck application log for details.");
+ LOGERROR(L"Failed to load map %ls: %hs", mapfilename.string().c_str(), err.what());
+ throw PSERROR_Game_World_MapLoadFailed("Failed to load map.\nCheck application log for details.");
}
}
}
diff --git a/source/ps/World.h b/source/ps/World.h
index cfc129c20f..c37c16e317 100644
--- a/source/ps/World.h
+++ b/source/ps/World.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Wildfire Games.
+/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -73,7 +73,7 @@ public:
/*
Initialize the World - load the map and all objects
*/
- void RegisterInit(const CStrW& mapFile, int playerID);
+ void RegisterInit(const CStrW& mapFile, const CScriptValRooted& settings, int playerID);
/*
Initialize the World - generate and load the random map
diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp
index ffc16f1f3b..bd93c08a69 100644
--- a/source/simulation2/Simulation2.cpp
+++ b/source/simulation2/Simulation2.cpp
@@ -387,22 +387,20 @@ void CSimulation2Impl::Update(int turnLength, const std::vectorLoadMap(mapfilename, &secondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, &secondaryContext, INVALID_PLAYER, true); // throws exception on failure
- }
- else
+ if (mapType == "random")
{
// TODO: support random map scripts
debug_warn(L"Serialization test mode only supports scenarios");
}
+ else
+ {
+ std::wstring mapFile;
+ m_ComponentManager.GetScriptInterface().GetProperty(m_InitAttributes.get(), "map", mapFile);
+ VfsPath mapfilename = VfsPath(mapFile).ChangeExtension(L".pmp");
+ mapReader->LoadMap(mapfilename, CScriptValRooted(), &secondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, &secondaryContext, INVALID_PLAYER, true); // throws exception on failure
+ }
LDR_EndRegistering();
ENSURE(LDR_NonprogressiveLoad() == INFO::OK);
diff --git a/source/simulation2/components/tests/test_Pathfinder.h b/source/simulation2/components/tests/test_Pathfinder.h
index 74b33e627c..51a1b920ae 100644
--- a/source/simulation2/components/tests/test_Pathfinder.h
+++ b/source/simulation2/components/tests/test_Pathfinder.h
@@ -68,7 +68,7 @@ public:
CMapReader* mapReader = new CMapReader(); // it'll call "delete this" itself
LDR_BeginRegistering();
- mapReader->LoadMap(L"maps/scenarios/Median Oasis 01.pmp", &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ mapReader->LoadMap(L"maps/scenarios/Median Oasis 01.pmp", CScriptValRooted(), &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&sim2, &sim2.GetSimContext(), -1, false);
LDR_EndRegistering();
TS_ASSERT_OK(LDR_NonprogressiveLoad());
diff --git a/source/simulation2/tests/test_Serializer.h b/source/simulation2/tests/test_Serializer.h
index 3784395947..942d5da733 100644
--- a/source/simulation2/tests/test_Serializer.h
+++ b/source/simulation2/tests/test_Serializer.h
@@ -25,6 +25,7 @@
#include "graphics/MapReader.h"
#include "graphics/Terrain.h"
+#include "graphics/TerrainTextureManager.h"
#include "lib/timer.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
@@ -635,6 +636,12 @@ public:
TS_ASSERT_OK(g_VFS->Mount(L"", DataDir()/"mods"/"public", VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache/", DataDir()/"cache"));
+ // Need some stuff for terrain movement costs:
+ // (TODO: this ought to be independent of any graphics code)
+ tex_codec_register_all();
+ new CTerrainTextureManager;
+ g_TexMan.LoadTerrainTextures();
+
CTerrain terrain;
CSimulation2 sim2(NULL, &terrain);
@@ -644,7 +651,7 @@ public:
CMapReader* mapReader = new CMapReader(); // it'll call "delete this" itself
LDR_BeginRegistering();
- mapReader->LoadMap(L"maps/scenarios/Latium.pmp", &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ mapReader->LoadMap(L"maps/scenarios/Acropolis 01.pmp", CScriptValRooted(), &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&sim2, &sim2.GetSimContext(), -1, false);
LDR_EndRegistering();
TS_ASSERT_OK(LDR_NonprogressiveLoad());
@@ -677,6 +684,8 @@ public:
debug_printf(L"# time = %f (%f/%d)\n", t/reps, t, (int)reps);
// Shut down the world
+ delete &g_TexMan;
+ tex_codec_unregister_all();
g_VFS.reset();
CXeromyces::Terminate();
}
diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapDialog/MapDialog.cpp b/source/tools/atlas/AtlasUI/CustomControls/MapDialog/MapDialog.cpp
new file mode 100644
index 0000000000..59f618c665
--- /dev/null
+++ b/source/tools/atlas/AtlasUI/CustomControls/MapDialog/MapDialog.cpp
@@ -0,0 +1,214 @@
+/* Copyright (C) 2013 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#include "precompiled.h"
+
+#include "MapDialog.h"
+
+#include "GameInterface/MessagePasser.h"
+#include "GameInterface/Messages.h"
+
+enum {
+ ID_MapDialogFilename = 1,
+ ID_MapDialogNotebook,
+ ID_ScenarioPage,
+ ID_SkirmishPage
+};
+
+static const wxString scenarioPath(L"maps/scenarios/");
+static const wxString skirmishPath(L"maps/skirmishes/");
+
+MapDialog::MapDialog(wxWindow* parent, MapDialogType type)
+ : wxDialog(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(600,400), wxCAPTION|wxRESIZE_BORDER|wxCLOSE_BOX|wxSYSTEM_MENU), m_Type(type)
+{
+ Freeze();
+
+ SetIcon(wxIcon(_T("ICON_ScenarioEditor"))); // load from atlas.rc
+
+ if (m_Type == MAPDIALOG_OPEN)
+ SetTitle(_("Choose map to open"));
+ else // MAPDIALOG_SAVE
+ SetTitle(_("Choose map to save"));
+
+ AtlasMessage::qGetMapList qry;
+ qry.Post();
+
+ wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
+
+ wxNotebook* notebook = new wxNotebook(this, ID_MapDialogNotebook);
+ {
+ wxPanel* page = new wxPanel(notebook, ID_ScenarioPage);
+ wxSizer* pageSizer = new wxBoxSizer(wxVERTICAL);
+ // TODO: Should display something nicer than raw VFS paths
+ wxListBox* listBox = new wxListBox(page, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE|wxLB_HSCROLL);
+ const std::vector& scenarioFilenames = *qry.scenarioFilenames;
+ for (size_t i = 0; i < scenarioFilenames.size(); ++i)
+ {
+ wxString name = scenarioFilenames[i].substr(scenarioPath.Length());
+ listBox->Append(name, new wxStringClientData(scenarioFilenames[i]));
+ }
+
+ pageSizer->Add(listBox, wxSizerFlags().Proportion(1).Expand().Align(wxBOTTOM));
+ page->SetSizer(pageSizer);
+ notebook->AddPage(page, _("Scenarios"));
+ }
+ {
+ wxPanel* page = new wxPanel(notebook, ID_SkirmishPage);
+ wxSizer* pageSizer = new wxBoxSizer(wxVERTICAL);
+ // TODO: Should display something nicer than raw VFS paths
+ wxListBox* listBox = new wxListBox(page, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, NULL, wxLB_SINGLE|wxLB_HSCROLL);
+ const std::vector& skirmishFilenames = *qry.skirmishFilenames;
+ for (size_t i = 0; i < skirmishFilenames.size(); ++i)
+ {
+ wxString name = skirmishFilenames[i].substr(skirmishPath.Length());
+ listBox->Append(name, new wxStringClientData(skirmishFilenames[i]));
+ }
+
+ pageSizer->Add(listBox, wxSizerFlags().Proportion(1).Expand());
+ page->SetSizer(pageSizer);
+ notebook->AddPage(page, _("Skirmishes"));
+ }
+
+ notebook->SetSelection(0);
+
+ sizer->Add(notebook, wxSizerFlags().Proportion(1).Expand());
+
+ sizer->AddSpacer(5);
+
+ wxSizer* filenameSizer = new wxBoxSizer(wxHORIZONTAL);
+ filenameSizer->AddSpacer(10);
+ filenameSizer->Add(new wxStaticText(this, wxID_ANY, _("Map name: ")), wxSizerFlags().Align(wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL));
+ wxTextCtrl* filename = new wxTextCtrl(this, ID_MapDialogFilename, wxEmptyString);
+ if (m_Type == MAPDIALOG_OPEN)
+ filename->Disable();
+ filenameSizer->Add(filename, wxSizerFlags().Proportion(1).Expand());
+ sizer->Add(filenameSizer, wxSizerFlags().Expand());
+
+ sizer->AddSpacer(20);
+
+ wxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
+ if (m_Type == MAPDIALOG_OPEN)
+ buttonSizer->Add(new wxButton(this, wxID_OPEN, _("Open")));
+ else // MAPDIALOG_SAVE
+ buttonSizer->Add(new wxButton(this, wxID_SAVE, _("Save")));
+ buttonSizer->AddSpacer(5);
+ buttonSizer->Add(new wxButton(this, wxID_CANCEL, _("Cancel")));
+
+ sizer->Add(buttonSizer, wxSizerFlags().Align(wxALIGN_RIGHT).Border(wxRIGHT|wxBOTTOM, 10));
+
+ SetSizer(sizer);
+
+ Layout();
+ Thaw();
+}
+
+wxString MapDialog::GetFilename() const
+{
+ wxFileName filename(m_Filename, wxPATH_UNIX);
+ filename.SetExt(L"xml");
+ if (m_SelectedPage == 0)
+ return scenarioPath + filename.GetFullPath(wxPATH_UNIX);
+ else if (m_SelectedPage == 1)
+ return skirmishPath + filename.GetFullPath(wxPATH_UNIX);
+ else
+ return wxEmptyString;
+}
+
+void MapDialog::OnListBox(wxCommandEvent& evt)
+{
+ if (evt.GetInt() < 0)
+ m_Filename = wxEmptyString;
+ else
+ m_Filename = evt.GetString();
+
+ wxDynamicCast(FindWindow(ID_MapDialogFilename), wxTextCtrl)->ChangeValue(m_Filename);
+
+ if (evt.GetEventType() == wxEVT_COMMAND_LISTBOX_DOUBLECLICKED)
+ {
+ if (m_Type == MAPDIALOG_OPEN)
+ OpenFile();
+ else
+ SaveFile();
+ }
+}
+
+void MapDialog::OnCancel(wxCommandEvent& WXUNUSED(evt))
+{
+ EndModal(wxID_CANCEL);
+}
+
+void MapDialog::OnOpen(wxCommandEvent& WXUNUSED(evt))
+{
+ OpenFile();
+}
+
+void MapDialog::OnSave(wxCommandEvent& WXUNUSED(evt))
+{
+ SaveFile();
+}
+
+void MapDialog::OnFilename(wxCommandEvent& evt)
+{
+ m_Filename = evt.GetString();
+}
+
+void MapDialog::OnNotebookChanged(wxNotebookEvent& evt)
+{
+ m_SelectedPage = evt.GetSelection();
+}
+
+void MapDialog::OpenFile()
+{
+ wxString filename = GetFilename();
+ if (filename.empty())
+ return;
+
+ AtlasMessage::qVFSFileExists qry(filename.wc_str());
+ qry.Post();
+ if (!qry.exists)
+ return;
+
+ EndModal(wxID_OK);
+}
+
+void MapDialog::SaveFile()
+{
+ wxString filename = GetFilename();
+ if (filename.empty())
+ return;
+
+ // TODO: this test would work better outside the VFS
+ AtlasMessage::qVFSFileExists qry(filename.wc_str());
+ qry.Post();
+ if (qry.exists)
+ {
+ if (wxMessageBox(_("WARNING: '") + filename + _("' already exists, it may be overwritten. Continue?"), _("Overwrite map confirmation"), wxICON_EXCLAMATION | wxYES_NO) != wxYES)
+ return;
+ }
+
+ EndModal(wxID_OK);
+}
+
+BEGIN_EVENT_TABLE(MapDialog, wxDialog)
+ EVT_BUTTON (wxID_CANCEL, MapDialog::OnCancel)
+ EVT_BUTTON (wxID_OPEN, MapDialog::OnOpen)
+ EVT_BUTTON (wxID_SAVE, MapDialog::OnSave)
+ EVT_LISTBOX (wxID_ANY, MapDialog::OnListBox)
+ EVT_LISTBOX_DCLICK (wxID_ANY, MapDialog::OnListBox)
+ EVT_TEXT (ID_MapDialogFilename, MapDialog::OnFilename)
+ EVT_NOTEBOOK_PAGE_CHANGED (ID_MapDialogNotebook, MapDialog::OnNotebookChanged)
+END_EVENT_TABLE()
diff --git a/source/tools/atlas/AtlasUI/CustomControls/MapDialog/MapDialog.h b/source/tools/atlas/AtlasUI/CustomControls/MapDialog/MapDialog.h
new file mode 100644
index 0000000000..8c9b293be9
--- /dev/null
+++ b/source/tools/atlas/AtlasUI/CustomControls/MapDialog/MapDialog.h
@@ -0,0 +1,55 @@
+/* Copyright (C) 2013 Wildfire Games.
+ * This file is part of 0 A.D.
+ *
+ * 0 A.D. is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 0 A.D. is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with 0 A.D. If not, see .
+ */
+
+#ifndef INCLUDED_MAPDIALOG
+#define INCLUDED_MAPDIALOG
+
+#include
+
+enum MapDialogType { MAPDIALOG_OPEN, MAPDIALOG_SAVE };
+
+class MapDialog : public wxDialog
+{
+public:
+ MapDialog(wxWindow* parent, MapDialogType type);
+
+ /**
+ * Returns VFS path of selected map with .xml extension, else empty string
+ */
+ wxString GetFilename() const;
+
+private:
+
+ void OnCancel(wxCommandEvent& evt);
+ void OnOpen(wxCommandEvent& evt);
+ void OnSave(wxCommandEvent& evt);
+ void OnListBox(wxCommandEvent& evt);
+ void OnFilename(wxCommandEvent& evt);
+ void OnNotebookChanged(wxNotebookEvent& evt);
+
+ void OpenFile();
+ void SaveFile();
+
+ wxArrayString m_MapFilenames;
+ wxString m_Filename;
+ MapDialogType m_Type;
+ int m_SelectedPage;
+
+ DECLARE_EVENT_TABLE();
+};
+
+#endif // INCLUDED_MAPDIALOG
diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp
index 5cdca8fc8e..57b4734e20 100644
--- a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp
+++ b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp
@@ -35,6 +35,7 @@
#include "CustomControls/Buttons/ToolButton.h"
#include "CustomControls/Canvas/Canvas.h"
#include "CustomControls/HighResTimer/HighResTimer.h"
+#include "CustomControls/MapDialog/MapDialog.h"
#include "GameInterface/MessagePasser.h"
#include "GameInterface/Messages.h"
@@ -521,7 +522,7 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterfac
// Start with a blank map (so that the editor can assume there's always
// a valid map loaded)
- POST_MESSAGE(LoadMap, (_T("_default")));
+ POST_MESSAGE(LoadMap, (_T("maps/scenarios/_default.xml")));
POST_MESSAGE(SimPlay, (0.f, false));
// Select the initial sidebar (after the map has loaded)
@@ -626,56 +627,28 @@ void ScenarioEditor::OnRedo(wxCommandEvent&)
void ScenarioEditor::OnNew(wxCommandEvent& WXUNUSED(event))
{
if (wxMessageBox(_("Discard current map and start blank new map?"), _("New map"), wxOK|wxCANCEL|wxICON_QUESTION, this) == wxOK)
- OpenFile(_T("_default"), _T(""));
+ OpenFile(_T(""), _T("maps/scenarios/_default.xml"));
}
bool ScenarioEditor::OpenFile(const wxString& name, const wxString& filename)
{
wxBusyInfo busy(_("Loading ") + name);
wxBusyCursor busyc;
-
- wxString mapPath(_T("maps/scenarios/"));
- wxFileName fullFilename(filename);
- // For compatibility it's still possible to load xml maps but in that case,
- // we want a blank filename so that we're forced to Save As
- if (filename.IsEmpty() || fullFilename.GetExt().IsSameAs(_T("xml"), false))
- {
- fullFilename = _T("");
- }
- else
- { // force extension to pmp
- fullFilename.SetExt(_T("pmp"));
-
- // check if pmp exists
- qVFSFileExists qry(std::wstring((mapPath + fullFilename.GetFullName()).wc_str()));
- qry.Post();
- if (!qry.exists)
- {
- return false;
- }
- }
-
- // Every map requires an xml file, so check that it exists
- wxFileName xmlName(name);
- xmlName.SetExt(_T("xml"));
- qVFSFileExists qry(std::wstring((mapPath + xmlName.GetFullName()).wc_str()));
+ AtlasMessage::qVFSFileExists qry(filename.wc_str());
qry.Post();
if (!qry.exists)
- {
return false;
- }
-
+
// Deactivate tools, so they don't carry forwards into the new CWorld
// and crash.
m_ToolManager.SetCurrentTool(_T(""));
// TODO: clear the undo buffer, etc
- // TODO: Work when the map is not in .../maps/scenarios/
- std::wstring map(name.wc_str());
+ std::wstring map(filename.wc_str());
POST_MESSAGE(LoadMap, (map));
- SetOpenFilename(fullFilename.GetFullName());
+ SetOpenFilename(name);
{ // Wait for it to load, while the wxBusyInfo is telling the user that we're doing that
qPing qry;
@@ -692,27 +665,12 @@ bool ScenarioEditor::OpenFile(const wxString& name, const wxString& filename)
void ScenarioEditor::OnOpen(wxCommandEvent& WXUNUSED(event))
{
- wxFileDialog dlg (NULL, wxFileSelectorPromptStr,
- Datafile::GetDataDirectory() + _T("/mods/public/maps/scenarios"), m_OpenFilename,
- _T("PMP files (*.pmp)|*.pmp|All files (*.*)|*.*"),
- wxFD_OPEN);
- // Set default filter
- dlg.SetFilterIndex(0);
-
- wxString cwd = wxFileName::GetCwd();
-
+ MapDialog dlg (NULL, MAPDIALOG_OPEN);
if (dlg.ShowModal() == wxID_OK)
{
- // TODO: Handle maps in subdirectories of maps/scenarios
- wxFileName filename(dlg.GetFilename());
- if (!OpenFile(filename.GetName(), filename.GetFullName()))
- {
- wxLogError(_("Map '%ls' does not exist"), filename.GetName().c_str());
- }
-
- // paranoia - MSDN says OFN_NOCHANGEDIR (used when we don't give wxCHANGE_DIR)
- // "is ineffective for GetOpenFileName", but it seems to work anyway
- wxCHECK_RET(cwd == wxFileName::GetCwd(), _T("cwd changed"));
+ wxString filename = dlg.GetFilename();
+ if (!OpenFile(filename, filename))
+ wxLogError(_("Map '%ls' does not exist"), filename.c_str());
}
// TODO: Make this a non-undoable command
@@ -727,12 +685,10 @@ void ScenarioEditor::OnImportHeightmap(wxCommandEvent& WXUNUSED(event))
// Set default filter
dlg.SetFilterIndex(0);
- wxString cwd = wxFileName::GetCwd();
-
if (dlg.ShowModal() != wxID_OK)
return;
- OpenFile(_T("_default"), _T(""));
+ OpenFile(_T(""), _T("maps/scenarios/_default.xml"));
std::wstring image(dlg.GetPath().wc_str());
POST_MESSAGE(ImportHeightmap, (image));
@@ -744,8 +700,16 @@ void ScenarioEditor::OnMRUFile(wxCommandEvent& event)
{
wxString filename(m_FileHistory.GetHistoryFile(event.GetId() - wxID_FILE1));
+ // Handle old MRU filenames
+ if (filename.Mid(0, 5) != _T("maps/"))
+ {
+ filename = L"maps/scenarios/" + filename;
+ m_FileHistory.RemoveFileFromHistory(event.GetId() - wxID_FILE1);
+ }
+
if (!OpenFile(filename, filename))
- { // Missing or invalid - warn and remove from MRU
+ {
+ // Missing or invalid - warn and remove from MRU
wxLogError(_("Map '%ls' does not exist"), filename.c_str());
m_FileHistory.RemoveFileFromHistory(event.GetId() - wxID_FILE1);
}
@@ -767,7 +731,6 @@ void ScenarioEditor::OnSave(wxCommandEvent& event)
// the preview units.)
m_ToolManager.SetCurrentTool(_T(""));
- // TODO: Handle maps in subdirectories of maps/scenarios
std::wstring map(m_OpenFilename.wc_str());
POST_MESSAGE(SaveMap, (map));
@@ -779,35 +742,19 @@ void ScenarioEditor::OnSave(wxCommandEvent& event)
void ScenarioEditor::OnSaveAs(wxCommandEvent& WXUNUSED(event))
{
- wxFileDialog dlg (NULL, wxFileSelectorPromptStr,
- Datafile::GetDataDirectory() + _T("/mods/public/maps/scenarios"), m_OpenFilename,
- _T("PMP files (*.pmp)|*.pmp|All files (*.*)|*.*"),
- wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
- // Set default filter
- dlg.SetFilterIndex(0);
-
+ MapDialog dlg(NULL, MAPDIALOG_SAVE);
if (dlg.ShowModal() == wxID_OK)
{
- // On wxMSW the extension is automatically set to pmp if that filter is selected
- // but not on wxGTK or wxOSX. Set it explicitly since it's the only possible format.
- wxFileName filename(dlg.GetFilename());
- filename.SetExt(_T("pmp"));
- if (!filename.IsOk())
- { // Shouldn't happen
- wxLogError(_("Invalid filename '%ls'"), filename.GetFullName().c_str());
- return;
- }
-
- wxBusyInfo busy(_("Saving ") + filename.GetFullName());
+ wxString filename(dlg.GetFilename());
+ wxBusyInfo busy(_("Saving ") + filename);
wxBusyCursor busyc;
m_ToolManager.SetCurrentTool(_T(""));
- // TODO: Handle maps in subdirectories of maps/scenarios
- std::wstring map(filename.GetFullName().wc_str());
+ std::wstring map(filename.wc_str());
POST_MESSAGE(SaveMap, (map));
- SetOpenFilename(filename.GetFullName());
+ SetOpenFilename(filename);
// Wait for it to finish saving
qPing qry;
diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp
index 6e79fa6f42..5e08cbf0e1 100644
--- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp
+++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp
@@ -34,9 +34,10 @@ enum
ID_MapDescription,
ID_MapReveal,
ID_MapType,
+ ID_MapPreview,
ID_MapTeams,
ID_MapKW_Demo,
- ID_MapKW_Hidden,
+ ID_MapKW_Naval,
ID_RandomScript,
ID_RandomSize,
ID_RandomSeed,
@@ -109,6 +110,7 @@ private:
BEGIN_EVENT_TABLE(MapSettingsControl, wxPanel)
EVT_TEXT(ID_MapName, MapSettingsControl::OnEdit)
EVT_TEXT(ID_MapDescription, MapSettingsControl::OnEdit)
+ EVT_TEXT(ID_MapPreview, MapSettingsControl::OnEdit)
EVT_CHECKBOX(wxID_ANY, MapSettingsControl::OnEdit)
EVT_CHOICE(wxID_ANY, MapSettingsControl::OnEdit)
END_EVENT_TABLE();
@@ -147,6 +149,10 @@ void MapSettingsControl::CreateWidgets()
wxFlexGridSizer* gridSizer = new wxFlexGridSizer(2, 5, 5);
gridSizer->AddGrowableCol(1);
+ // TODO: have preview selector tool?
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Preview")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+ gridSizer->Add(Tooltipped(new wxTextCtrl(this, ID_MapPreview, wxEmptyString),
+ _("Texture used for map preview")), wxSizerFlags().Expand());
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Reveal map")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(new wxCheckBox(this, ID_MapReveal, wxEmptyString),
_("If checked, players won't need to explore")));
@@ -161,12 +167,12 @@ void MapSettingsControl::CreateWidgets()
sizer->AddSpacer(5);
wxStaticBoxSizer* keywordsSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Keywords"));
- wxFlexGridSizer* kwGridSizer = new wxFlexGridSizer(2, 5, 5);
+ wxFlexGridSizer* kwGridSizer = new wxFlexGridSizer(4, 5, 5);
kwGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Demo")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
kwGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_MapKW_Demo, wxEmptyString),
_("If checked, map will only be visible using filters in game setup")));
- kwGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Hidden")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
- kwGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_MapKW_Hidden, wxEmptyString),
+ kwGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Naval")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+ kwGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_MapKW_Naval, wxEmptyString),
_("If checked, map will only be visible using filters in game setup")));
keywordsSizer->Add(kwGridSizer);
sizer->Add(keywordsSizer, wxSizerFlags().Expand());
@@ -188,6 +194,9 @@ void MapSettingsControl::ReadFromEngine()
// map description
wxDynamicCast(FindWindow(ID_MapDescription), wxTextCtrl)->ChangeValue(wxString(m_MapSettings["Description"]));
+ // map preview
+ wxDynamicCast(FindWindow(ID_MapPreview), wxTextCtrl)->ChangeValue(wxString(m_MapSettings["Preview"]));
+
// reveal map
wxDynamicCast(FindWindow(ID_MapReveal), wxCheckBox)->SetValue(wxString(m_MapSettings["RevealMap"]) == L"true");
@@ -207,7 +216,7 @@ void MapSettingsControl::ReadFromEngine()
m_MapSettingsKeywords.insert(std::wstring(keyword));
wxDynamicCast(FindWindow(ID_MapKW_Demo), wxCheckBox)->SetValue(m_MapSettingsKeywords.count(L"demo") != 0);
- wxDynamicCast(FindWindow(ID_MapKW_Hidden), wxCheckBox)->SetValue(m_MapSettingsKeywords.count(L"hidden") != 0);
+ wxDynamicCast(FindWindow(ID_MapKW_Naval), wxCheckBox)->SetValue(m_MapSettingsKeywords.count(L"naval") != 0);
}
}
@@ -227,6 +236,9 @@ AtObj MapSettingsControl::UpdateSettingsObject()
// map description
m_MapSettings.set("Description", wxDynamicCast(FindWindow(ID_MapDescription), wxTextCtrl)->GetValue());
+ // map preview
+ m_MapSettings.set("Preview", wxDynamicCast(FindWindow(ID_MapPreview), wxTextCtrl)->GetValue());
+
// reveal map
m_MapSettings.setBool("RevealMap", wxDynamicCast(FindWindow(ID_MapReveal), wxCheckBox)->GetValue());
@@ -240,10 +252,10 @@ AtObj MapSettingsControl::UpdateSettingsObject()
else
m_MapSettingsKeywords.erase(L"demo");
- if (wxDynamicCast(FindWindow(ID_MapKW_Hidden), wxCheckBox)->GetValue())
- m_MapSettingsKeywords.insert(L"hidden");
+ if (wxDynamicCast(FindWindow(ID_MapKW_Naval), wxCheckBox)->GetValue())
+ m_MapSettingsKeywords.insert(L"naval");
else
- m_MapSettingsKeywords.erase(L"hidden");
+ m_MapSettingsKeywords.erase(L"naval");
AtObj keywords;
keywords.set("@array", L"");
diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Player/Player.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Player/Player.cpp
index c9e643b10b..1d771f1398 100644
--- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Player/Player.cpp
+++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Player/Player.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Wildfire Games.
+/* Copyright (C) 2013 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -35,8 +35,18 @@ enum
ID_PlayerStone,
ID_PlayerPop,
ID_PlayerColour,
- ID_PlayerHuman,
- ID_PlayerAI,
+
+ ID_DefaultName,
+ ID_DefaultCiv,
+ ID_DefaultColour,
+ ID_DefaultAI,
+ ID_DefaultFood,
+ ID_DefaultWood,
+ ID_DefaultMetal,
+ ID_DefaultStone,
+ ID_DefaultPop,
+ ID_DefaultTeam,
+
ID_CameraSet,
ID_CameraView,
ID_CameraClear
@@ -54,6 +64,39 @@ static wxWindow* Tooltipped(wxWindow* window, const wxString& tip)
//////////////////////////////////////////////////////////////////////////
+class DefaultCheckbox : public wxCheckBox
+{
+public:
+ DefaultCheckbox(wxWindow* parent, wxWindowID id, wxWindow* control, bool initialValue = false)
+ : wxCheckBox(parent, id, wxEmptyString), m_Control(control)
+ {
+ SetValue(initialValue);
+ }
+
+ virtual void SetValue(bool value)
+ {
+ m_Control->Enable(value);
+ wxCheckBox::SetValue(value);
+ }
+
+ void OnChecked(wxCommandEvent& evt)
+ {
+ m_Control->Enable(evt.IsChecked());
+
+ evt.Skip();
+ }
+
+private:
+ wxWindow* m_Control;
+
+ DECLARE_EVENT_TABLE();
+};
+
+BEGIN_EVENT_TABLE(DefaultCheckbox, wxCheckBox)
+ EVT_CHECKBOX(wxID_ANY, DefaultCheckbox::OnChecked)
+END_EVENT_TABLE();
+
+
class PlayerNotebookPage : public wxPanel
{
@@ -73,25 +116,33 @@ public:
/////////////////////////////////////////////////////////////////////////
// Player Info
wxStaticBoxSizer* playerInfoSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Player info"));
- wxFlexGridSizer* gridSizer = new wxFlexGridSizer(2, 5, 5);
- gridSizer->AddGrowableCol(1);
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Name")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+ wxFlexGridSizer* gridSizer = new wxFlexGridSizer(3, 5, 5);
+ gridSizer->AddGrowableCol(2);
+
wxTextCtrl* nameCtrl = new wxTextCtrl(this, wxID_ANY);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultName, nameCtrl), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Name")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(nameCtrl, wxSizerFlags(1).Expand().Align(wxALIGN_RIGHT));
m_Controls.name = nameCtrl;
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Civilisation")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+
wxChoice* civChoice = new wxChoice(this, wxID_ANY);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultCiv, civChoice), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Civilisation")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(civChoice, wxSizerFlags(1).Expand().Align(wxALIGN_RIGHT));
m_Controls.civ = civChoice;
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Colour")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+
wxButton* colourButton = new wxButton(this, ID_PlayerColour);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultColour, colourButton), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Colour")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(colourButton,
_("Set player colour")), wxSizerFlags(1).Expand().Align(wxALIGN_RIGHT));
m_Controls.colour = colourButton;
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Default AI")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+
wxChoice* aiChoice = new wxChoice(this, wxID_ANY);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultAI, aiChoice), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("AI")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(aiChoice,
- _("Select default AI")), wxSizerFlags(1).Expand().Align(wxALIGN_RIGHT));
+ _("Select AI")), wxSizerFlags(1).Expand().Align(wxALIGN_RIGHT));
m_Controls.ai = aiChoice;
playerInfoSizer->Add(gridSizer, wxSizerFlags(1).Expand());
@@ -102,30 +153,40 @@ public:
/////////////////////////////////////////////////////////////////////////
// Resources
wxStaticBoxSizer* resourceSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Resources"));
- wxFlexGridSizer* gridSizer = new wxFlexGridSizer(2, 5, 5);
- gridSizer->AddGrowableCol(1);
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Food")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+ wxFlexGridSizer* gridSizer = new wxFlexGridSizer(3, 5, 5);
+ gridSizer->AddGrowableCol(2);
+
wxSpinCtrl* foodCtrl = new wxSpinCtrl(this, ID_PlayerFood, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, INT_MAX);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultFood, foodCtrl), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Food")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(foodCtrl,
_("Initial value of food resource")), wxSizerFlags().Expand());
m_Controls.food = foodCtrl;
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Wood")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+
wxSpinCtrl* woodCtrl = new wxSpinCtrl(this, ID_PlayerWood, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, INT_MAX);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultWood, woodCtrl), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Wood")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(woodCtrl,
_("Initial value of wood resource")), wxSizerFlags().Expand());
m_Controls.wood = woodCtrl;
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Metal")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+
wxSpinCtrl* metalCtrl = new wxSpinCtrl(this, ID_PlayerMetal, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, INT_MAX);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultMetal, metalCtrl), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Metal")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(metalCtrl,
_("Initial value of metal resource")), wxSizerFlags().Expand());
m_Controls.metal = metalCtrl;
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Stone")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+
wxSpinCtrl* stoneCtrl = new wxSpinCtrl(this, ID_PlayerStone, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, INT_MAX);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultStone, stoneCtrl), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Stone")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(stoneCtrl,
_("Initial value of stone resource")), wxSizerFlags().Expand());
m_Controls.stone = stoneCtrl;
- gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Pop limit")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+
wxSpinCtrl* popCtrl = new wxSpinCtrl(this, ID_PlayerPop, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, INT_MAX);
+ gridSizer->Add(new DefaultCheckbox(this, ID_DefaultPop, popCtrl), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Pop limit")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(popCtrl,
_("Population limit for this player")), wxSizerFlags().Expand());
m_Controls.pop = popCtrl;
@@ -138,8 +199,11 @@ public:
// Diplomacy
wxStaticBoxSizer* diplomacySizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Diplomacy"));
wxBoxSizer* boxSizer = new wxBoxSizer(wxHORIZONTAL);
- boxSizer->Add(new wxStaticText(this, wxID_ANY, _("Team")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
wxChoice* teamCtrl = new wxChoice(this, wxID_ANY);
+ boxSizer->Add(new DefaultCheckbox(this, ID_DefaultTeam, teamCtrl), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
+ boxSizer->AddSpacer(5);
+ boxSizer->Add(new wxStaticText(this, wxID_ANY, _("Team")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
+ boxSizer->AddSpacer(5);
teamCtrl->Append(_("None"));
teamCtrl->Append(_T("1"));
teamCtrl->Append(_T("2"));
@@ -479,6 +543,7 @@ BEGIN_EVENT_TABLE(PlayerSettingsControl, wxPanel)
EVT_BUTTON(ID_PlayerColour, PlayerSettingsControl::OnPlayerColour)
EVT_BUTTON(ID_CameraSet, PlayerSettingsControl::OnEdit)
EVT_BUTTON(ID_CameraClear, PlayerSettingsControl::OnEdit)
+ EVT_CHECKBOX(wxID_ANY, PlayerSettingsControl::OnEdit)
EVT_CHOICE(wxID_ANY, PlayerSettingsControl::OnEdit)
EVT_TEXT(ID_NumPlayers, PlayerSettingsControl::OnNumPlayersText)
EVT_TEXT(wxID_ANY, PlayerSettingsControl::OnEdit)
@@ -596,7 +661,8 @@ void PlayerSettingsControl::ReadFromEngine()
m_MapSettings = AtlasObject::LoadFromJSON(m_ScenarioEditor.GetScriptInterface().GetContext(), *qry.settings);
}
else
- { // Use blank object, it will be created next
+ {
+ // Use blank object, it will be created next
m_MapSettings = AtObj();
}
@@ -607,9 +673,7 @@ void PlayerSettingsControl::ReadFromEngine()
m_NumPlayers = MAX_NUM_PLAYERS;
}
else
- {
m_NumPlayers = player.count();
- }
wxASSERT(m_NumPlayers <= MAX_NUM_PLAYERS && m_NumPlayers != 0);
@@ -628,21 +692,24 @@ void PlayerSettingsControl::ReadFromEngine()
for (size_t i = 0; i < MAX_NUM_PLAYERS; ++i)
{
- PlayerPageControls controls = m_PlayerControls[i];
+ const PlayerPageControls& controls = m_PlayerControls[i];
// name
wxString name(_("Unknown"));
- if (player["Name"].defined())
+ bool defined = player["Name"].defined();
+ if (defined)
name = wxString(player["Name"]);
else if (playerDefs["Name"].defined())
name = wxString(playerDefs["Name"]);
controls.name->SetValue(name);
+ wxDynamicCast(FindWindowById(ID_DefaultName, controls.page), DefaultCheckbox)->SetValue(defined);
// civ
wxChoice* choice = controls.civ;
wxString civCode;
- if (player["Civ"].defined())
+ defined = player["Civ"].defined();
+ if (defined)
civCode = wxString(player["Civ"]);
else
civCode = wxString(playerDefs["Civ"]);
@@ -656,31 +723,30 @@ void PlayerSettingsControl::ReadFromEngine()
break;
}
}
+ wxDynamicCast(FindWindowById(ID_DefaultCiv, controls.page), DefaultCheckbox)->SetValue(defined);
// colour
wxColour colour;
AtObj clrObj = *player["Colour"];
- if (clrObj.defined())
- {
- colour = wxColor((*clrObj["r"]).getInt(), (*clrObj["g"]).getInt(), (*clrObj["b"]).getInt());
- }
- else
- {
+ defined = clrObj.defined();
+ if (!defined)
clrObj = *playerDefs["Colour"];
- colour = wxColor((*clrObj["r"]).getInt(), (*clrObj["g"]).getInt(), (*clrObj["b"]).getInt());
- }
+ colour = wxColor((*clrObj["r"]).getInt(), (*clrObj["g"]).getInt(), (*clrObj["b"]).getInt());
controls.colour->SetBackgroundColour(colour);
+ wxDynamicCast(FindWindowById(ID_DefaultColour, controls.page), DefaultCheckbox)->SetValue(defined);
// player type
wxString aiID;
- if (player["AI"].defined())
+ defined = player["AI"].defined();
+ if (defined)
aiID = wxString(player["AI"]);
else
aiID = wxString(playerDefs["AI"]);
choice = controls.ai;
if (!aiID.empty())
- { // AI
+ {
+ // AI
for (size_t j = 0; j < choice->GetCount(); ++j)
{
wxStringClientData* str = dynamic_cast(choice->GetClientObject(j));
@@ -691,44 +757,55 @@ void PlayerSettingsControl::ReadFromEngine()
}
}
}
- else
- { // Human
+ else // Human
choice->SetSelection(0);
- }
+ wxDynamicCast(FindWindowById(ID_DefaultAI, controls.page), DefaultCheckbox)->SetValue(defined);
// resources
AtObj resObj = *player["Resources"];
- if (resObj.defined() && resObj["food"].defined())
+ defined = resObj.defined() && resObj["food"].defined();
+ if (defined)
controls.food->SetValue(wxString(resObj["food"]));
else
controls.food->SetValue(0);
+ wxDynamicCast(FindWindowById(ID_DefaultFood, controls.page), DefaultCheckbox)->SetValue(defined);
- if (resObj.defined() && resObj["wood"].defined())
+ defined = resObj.defined() && resObj["wood"].defined();
+ if (defined)
controls.wood->SetValue(wxString(resObj["wood"]));
else
controls.wood->SetValue(0);
+ wxDynamicCast(FindWindowById(ID_DefaultWood, controls.page), DefaultCheckbox)->SetValue(defined);
- if (resObj.defined() && resObj["metal"].defined())
+ defined = resObj.defined() && resObj["metal"].defined();
+ if (defined)
controls.metal->SetValue(wxString(resObj["metal"]));
else
controls.metal->SetValue(0);
+ wxDynamicCast(FindWindowById(ID_DefaultMetal, controls.page), DefaultCheckbox)->SetValue(defined);
- if (resObj.defined() && resObj["stone"].defined())
+ defined = resObj.defined() && resObj["stone"].defined();
+ if (defined)
controls.stone->SetValue(wxString(resObj["stone"]));
else
controls.stone->SetValue(0);
+ wxDynamicCast(FindWindowById(ID_DefaultStone, controls.page), DefaultCheckbox)->SetValue(defined);
// population limit
- if (player["PopulationLimit"].defined())
+ defined = player["PopulationLimit"].defined();
+ if (defined)
controls.pop->SetValue(wxString(player["PopulationLimit"]));
else
controls.pop->SetValue(0);
+ wxDynamicCast(FindWindowById(ID_DefaultPop, controls.page), DefaultCheckbox)->SetValue(defined);
// team
- if (player["Team"].defined())
+ defined = player["Team"].defined();
+ if (defined)
controls.team->SetSelection((*player["Team"]).getInt() + 1);
else
controls.team->SetSelection(0);
+ wxDynamicCast(FindWindowById(ID_DefaultTeam, controls.page), DefaultCheckbox)->SetValue(defined);
// camera
if (player["StartingCamera"].defined())
@@ -767,7 +844,6 @@ void PlayerSettingsControl::ReadFromEngine()
AtObj PlayerSettingsControl::UpdateSettingsObject()
{
// Update player data in the map settings
- AtIter oldPlayer = m_MapSettings["PlayerData"]["item"];
AtObj players;
players.set("@array", L"");
@@ -777,66 +853,67 @@ AtObj PlayerSettingsControl::UpdateSettingsObject()
{
PlayerPageControls controls = m_PlayerControls[i];
- AtObj player = *oldPlayer;
+ AtObj player;
// name
wxTextCtrl* text = controls.name;
- if (!text->GetValue().empty())
- {
+ if (text->IsEnabled())
player.set("Name", text->GetValue());
- }
// civ
wxChoice* choice = controls.civ;
- if (choice->GetSelection() >= 0)
+ if (choice->IsEnabled() && choice->GetSelection() >= 0)
{
wxStringClientData* str = dynamic_cast(choice->GetClientObject(choice->GetSelection()));
player.set("Civ", str->GetData());
}
// colour
- wxColour colour = controls.colour->GetBackgroundColour();
- AtObj clrObj;
- clrObj.setInt("r", (int)colour.Red());
- clrObj.setInt("g", (int)colour.Green());
- clrObj.setInt("b", (int)colour.Blue());
- player.set("Colour", clrObj);
+ if (controls.colour->IsEnabled())
+ {
+ wxColour colour = controls.colour->GetBackgroundColour();
+ AtObj clrObj;
+ clrObj.setInt("r", (int)colour.Red());
+ clrObj.setInt("g", (int)colour.Green());
+ clrObj.setInt("b", (int)colour.Blue());
+ player.set("Colour", clrObj);
+ }
// player type
choice = controls.ai;
- if (choice->GetSelection() > 0)
- { // ai - get id
- wxStringClientData* str = dynamic_cast(choice->GetClientObject(choice->GetSelection()));
- player.set("AI", str->GetData());
- }
- else
- { // human
- player.set("AI", _T(""));
+ if (choice->IsEnabled())
+ {
+ if (choice->GetSelection() > 0)
+ {
+ // ai - get id
+ wxStringClientData* str = dynamic_cast(choice->GetClientObject(choice->GetSelection()));
+ player.set("AI", str->GetData());
+ }
+ else // human
+ player.set("AI", _T(""));
}
// resources
AtObj resObj;
- if (controls.food->GetValue() > 0)
+ if (controls.food->IsEnabled())
resObj.setInt("food", controls.food->GetValue());
- if (controls.wood->GetValue() > 0)
+ if (controls.wood->IsEnabled())
resObj.setInt("wood", controls.wood->GetValue());
- if (controls.metal->GetValue() > 0)
+ if (controls.metal->IsEnabled())
resObj.setInt("metal", controls.metal->GetValue());
- if (controls.stone->GetValue() > 0)
+ if (controls.stone->IsEnabled())
resObj.setInt("stone", controls.stone->GetValue());
if (resObj.defined())
player.set("Resources", resObj);
// population limit
- if (controls.pop->GetValue() > 0)
+ if (controls.pop->IsEnabled())
player.setInt("PopulationLimit", controls.pop->GetValue());
// team
choice = controls.team;
- if (choice->GetSelection() >= 0)
- { // valid selection
+ if (choice->IsEnabled() && choice->GetSelection() >= 0)
player.setInt("Team", choice->GetSelection() - 1);
- }
// camera
AtObj camObj;
@@ -858,8 +935,6 @@ AtObj PlayerSettingsControl::UpdateSettingsObject()
player.set("StartingCamera", camObj);
players.add("item", player);
- if (oldPlayer.defined())
- ++oldPlayer;
}
m_MapSettings.set("PlayerData", players);
diff --git a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
index 71272d4bfa..26111335bc 100644
--- a/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
+++ b/source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp
@@ -116,7 +116,7 @@ QUERYHANDLER(GenerateMap)
CScriptValRooted atts;
si.Eval("({})", atts);
si.SetProperty(atts.get(), "mapType", std::string("scenario"));
- si.SetProperty(atts.get(), "map", std::wstring(L"_default"));
+ si.SetProperty(atts.get(), "map", std::wstring(L"maps/scenarios/_default"));
StartGame(atts);
msg->status = -1;
@@ -226,7 +226,7 @@ MESSAGEHANDLER(ImportHeightmap)
MESSAGEHANDLER(SaveMap)
{
CMapWriter writer;
- const VfsPath pathname = VfsPath("maps/scenarios") / *msg->filename;
+ VfsPath pathname = VfsPath(*msg->filename).ChangeExtension(L".pmp");
writer.SaveMap(pathname,
g_Game->GetWorld()->GetTerrain(),
g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(),
@@ -352,4 +352,22 @@ QUERYHANDLER(VFSFileExists)
msg->exists = VfsFileExists(*msg->path);
}
+static Status AddToFilenames(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData)
+{
+ std::vector& filenames = *(std::vector*)cbData;
+ filenames.push_back(pathname.string().c_str());
+ return INFO::OK;
+}
+
+QUERYHANDLER(GetMapList)
+{
+ std::vector scenarioFilenames;
+ vfs::ForEachFile(g_VFS, L"maps/scenarios/", AddToFilenames, (uintptr_t)&scenarioFilenames, L"*.xml", vfs::DIR_RECURSIVE);
+ msg->scenarioFilenames = scenarioFilenames;
+
+ std::vector skirmishFilenames;
+ vfs::ForEachFile(g_VFS, L"maps/skirmishes/", AddToFilenames, (uintptr_t)&skirmishFilenames, L"*.xml", vfs::DIR_RECURSIVE);
+ msg->skirmishFilenames = skirmishFilenames;
+}
+
}
diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h
index cf3bb382d3..48ce2809ae 100644
--- a/source/tools/atlas/GameInterface/Messages.h
+++ b/source/tools/atlas/GameInterface/Messages.h
@@ -159,6 +159,12 @@ MESSAGE(SaveMap,
((std::wstring, filename))
);
+QUERY(GetMapList,
+ ,
+ ((std::vector, scenarioFilenames))
+ ((std::vector, skirmishFilenames))
+ );
+
QUERY(GetMapSettings,
,
((std::string, settings))