1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Merge pull request #106 from vcmi/rmgTemplatesAsMods

Okay, looks stable for now.
This commit is contained in:
DjWarmonger 2015-06-02 17:45:20 +02:00
commit 5d067416a1
26 changed files with 1278 additions and 836 deletions

View File

@ -0,0 +1,63 @@
{
"Analogy" :
{
"minSize" : "m", "maxSize" : "m+u",
"players" : "4",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 2, "owner" : 1,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1},
"treasure" : [
{"min" : 2100, "max": 3000, "density" : 5},
{"min" : 300, "max": 1500, "density" : 10}
]
},
"2" :
{
"type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3" :
{
"type" : "playerStart", "size" : 2, "owner" : 3,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"4" :
{
"type" : "playerStart", "size" : 2, "owner" : 4,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"5" :
{
"type" : "treasure", "size" : 3, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
"neutralTowns" : { "castles" : 1 },
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
{"min" : 9000, "max": 10000, "density" : 3},
{"min" : 6000, "max": 10000, "density" : 15}
]
}
},
"connections" :
[
{ "a" : "1", "b" : "5", "guard" : 5000 },
{ "a" : "2", "b" : "5", "guard" : 5000 },
{ "a" : "3", "b" : "5", "guard" : 5000 },
{ "a" : "4", "b" : "5", "guard" : 5000 }
]
}
}

View File

@ -0,0 +1,12 @@
{
"name" : "Analogy",
"description" : "Random map template, 4p M/M+U",
"version" : "0.99",
"author" : "VCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Templates",
"templates" : [
"config/defaultTemplates/analogy"
],
}

View File

@ -0,0 +1,227 @@
{
"Clash of Dragons 1.2":
{
"minSize" : "l+u", "maxSize" : "xl+u",
"players" : "2",
"zones":
{
"1":
{
"type" : "playerStart", "size" : 100, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"monsters" : "weak",
"mines" : {"wood" : 1, "ore" : 1, "gold" : 1},
"treasure" : [
{"min" : 2000, "max": 5000, "density": 4},
{"min" : 5000, "max": 9000, "density": 6},
{"min" : 300, "max": 1900, "density": 15}
]
},
"2":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypes" : ["grass"], "matchTerrainToTown" : false,
"monsters" : "normal",
"mines" : {"gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 5000, "max": 12000, "density": 2},
{"min" : 10000, "max": 20000, "density": 4},
{"min" : 300, "max": 1900, "density": 15}
]
},
"3":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypes" : ["lava"], "matchTerrainToTown" : false,
"monsters" : "strong",
"mines" : {"wood" : 1, "ore" : 1, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 20000, "max": 25000, "density": 10},
{"min" : 10000, "max": 15000, "density": 8},
{"min" : 300, "max": 1900, "density": 10}
]
},
"4":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypes" : ["dirt"], "matchTerrainToTown" : false,
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
{"min" : 20000, "max": 25000, "density": 15},
{"min" : 10000, "max": 15000, "density": 10},
{"min" : 300, "max": 1900, "density": 6}
]
},
"5":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "castles" : 1 },
"terrainTypes" : ["snow"], "matchTerrainToTown" : false,
"allowedTowns" : ["tower"],
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
{"min" : 20000, "max": 30000, "density": 15}
]
},
"6":
{
"type" : "treasure", "size" : 40,
"terrainTypes" : ["grass"], "matchTerrainToTown" : false,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 80000, "max": 120000, "density": 10}
]
},
"7":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 6,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"sulfur" : 1, "gold" : 1},
"treasureLikeZone" : 6
},
"8":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 6,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"crystal" : 1, "gold" : 1},
"treasureLikeZone" : 6
},
"9":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 6,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"gems" : 1, "gold" : 1},
"treasureLikeZone" : 6
},
"10":
{
"type" : "treasure", "size" : 40,
"terrainTypes" : ["snow"], "matchTerrainToTown" : false,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 80000, "max": 80000, "density": 10}
]
},
"11":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 10,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"minesLikeZone" : 10,
"treasureLikeZone" : 10
},
"12":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 10,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"minesLikeZone" : 10,
"treasureLikeZone" : 10
},
"13":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 10,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"minesLikeZone" : 10,
"treasureLikeZone" : 10
},
"14":
{
"type" : "playerStart", "size" : 100, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"15":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypeLikeZone" : 2,
"monsters" : "normal",
"minesLikeZone" : 2,
"treasureLikeZone" : 2
},
"16":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypeLikeZone" : 3,
"monsters" : "strong",
"minesLikeZone" : 3,
"treasureLikeZone" : 3
},
"17":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypeLikeZone" : 4,
"monsters" : "strong",
"minesLikeZone" : 4,
"treasureLikeZone" : 4
},
"18":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "castles" : 1 },
"terrainTypeLikeZone" : 5,
"townTypeLikeZone" : 5,
"monsters" : "strong",
"minesLikeZone" : 5,
"treasureLikeZone" : 5
}
},
"connections" :
[
{ "a" : "1", "b" : "2", "guard" : 4000 },
{ "a" : "2", "b" : "3", "guard" : 12000 },
{ "a" : "2", "b" : "4", "guard" : 20000 },
{ "a" : "4", "b" : "5", "guard" : 30000 },
{ "a" : "5", "b" : "6", "guard" : 50000 },
{ "a" : "6", "b" : "7", "guard" : 50000 },
{ "a" : "7", "b" : "8", "guard" : 50000 },
{ "a" : "7", "b" : "9", "guard" : 50000 },
{ "a" : "18", "b" : "9", "guard" : 50000 },
{ "a" : "5", "b" : "10", "guard" : 50000 },
{ "a" : "10", "b" : "11", "guard" : 50000 },
{ "a" : "11", "b" : "12", "guard" : 50000 },
{ "a" : "11", "b" : "13", "guard" : 50000 },
{ "a" : "14", "b" : "15", "guard" : 4000 },
{ "a" : "15", "b" : "16", "guard" : 12000 },
{ "a" : "15", "b" : "17", "guard" : 20000 },
{ "a" : "17", "b" : "18", "guard" : 30000 },
{ "a" : "18", "b" : "13", "guard" : 50000 },
{ "a" : "18", "b" : "5", "guard" : 150000 },
{ "a" : "3", "b" : "16", "guard" : 180000 }
]
}
}

View File

@ -0,0 +1,12 @@
{
"name" : "Clash of Dragons",
"description" : "Random map template, 1v1 L+U/XL+U",
"version" : "0.99",
"author" : "Malekith, ported by VCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Templates",
"templates" : [
"config/defaultTemplates/clashOfDragons"
],
}

View File

@ -0,0 +1,239 @@
{
"Coldshadow's Fantasy":
{
"minSize" : "xl+u", "maxSize" : "xl+u",
"players" : "4-8", "cpu" : "3-6",
"zones":
{
"1":
{
"type" : "playerStart", "size" : 30, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 1 },
"monsters" : "normal",
"mines" : {"wood" : 2, "ore" : 2, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 7500, "max": 25000, "density": 4},
{"min" : 3000, "max": 9000, "density": 6},
{"min" : 300, "max": 3000, "density": 8}
]
},
"2":
{
"type" : "cpuStart", "size" : 30, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 1 },
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3":
{
"type" : "cpuStart", "size" : 30, "owner" : 3,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 1 },
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"4":
{
"type" : "cpuStart", "size" : 30, "owner" : 4,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 1 },
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"5":
{
"type" : "playerStart", "size" : 30, "owner" : 5,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"6":
{
"type" : "cpuStart", "size" : 30, "owner" : 6,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 1 },
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"7":
{
"type" : "cpuStart", "size" : 30, "owner" : 7,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 1 },
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"8":
{
"type" : "cpuStart", "size" : 30, "owner" : 8,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 1 },
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"9":
{
"type" : "treasure", "size" : 15,
"terrainTypes" : ["subterra"], "matchTerrainToTown" : false,
"neutralTowns" : { "castles" : 1 },
"monsters" : "strong",
"mines" : {"gems" : 1, "sulfur" : 1, "mercury" : 1, "crystal" : 1},
"treasure" : [
{"min" : 45000, "max": 75000, "density": 3},
{"min" : 15000, "max": 50000, "density": 3},
{"min" : 3080, "max": 12500, "density": 4}
]
},
"10":
{
"type" : "treasure", "size" : 15,
"terrainTypeLikeZone" : 9,
"neutralTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 9,
"treasureLikeZone" : 9
},
"11":
{
"type" : "treasure", "size" : 15,
"terrainTypeLikeZone" : 9,
"neutralTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 9,
"treasureLikeZone" : 9
},
"12":
{
"type" : "treasure", "size" : 15,
"terrainTypeLikeZone" : 9,
"neutralTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 9,
"treasureLikeZone" : 9
},
"13":
{
"type" : "treasure", "size" : 15,
"terrainTypeLikeZone" : 9,
"neutralTowns" : { "castles" : 1 },
"monsters" : "strong",
"minesLikeZone" : 9,
"treasureLikeZone" : 9
},
"14":
{
"type" : "treasure", "size" : 15,
"terrainTypeLikeZone" : 9,
"neutralTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 9,
"treasureLikeZone" : 9
},
"15":
{
"type" : "treasure", "size" : 15,
"terrainTypeLikeZone" : 9,
"neutralTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 9,
"treasureLikeZone" : 9
},
"16":
{
"type" : "treasure", "size" : 15,
"terrainTypeLikeZone" : 9,
"neutralTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 9,
"treasureLikeZone" : 9
},
"17":
{
"type" : "junction", "size" : 30,
"terrainTypeLikeZone" : 9,
"allowedTowns" : ["neutral"],
"monsters" : "strong",
"mines" : {"gold" : 1},
"treasure" : [
{"min" : 65000, "max": 100000, "density": 3},
{"min" : 50000, "max": 100000, "density": 3},
{"min" : 10000, "max": 15000, "density": 3}
]
},
"18":
{
"type" : "junction", "size" : 30,
"terrainTypeLikeZone" : 9,
"allowedTowns" : ["neutral"],
"monsters" : "strong",
"minesLikeZone" : 17,
"treasureLikeZone" : 17
},
"19":
{
"type" : "junction", "size" : 30,
"terrainTypeLikeZone" : 9,
"allowedTowns" : ["neutral"],
"monsters" : "strong",
"minesLikeZone" : 17,
"treasureLikeZone" : 17
},
"20":
{
"type" : "junction", "size" : 30,
"terrainTypeLikeZone" : 9,
"allowedTowns" : ["neutral"],
"monsters" : "strong",
"minesLikeZone" : 17,
"treasureLikeZone" : 17
},
"21":
{
"type" : "treasure", "size" : 20,
"terrainTypeLikeZone" : 9,
"neutralTowns" : { "castles" : 1 },
"monsters" : "strong",
"treasure" : [
{"min" : 100000, "max": 130000, "density": 3},
{"min" : 100000, "max": 150000, "density": 3},
{"min" : 20000, "max": 60000, "density": 3}
]
}
},
"connections" :
[
{ "a" : "1", "b" : "9", "guard" : 36000 },
{ "a" : "2", "b" : "10", "guard" : 12000 },
{ "a" : "3", "b" : "11", "guard" : 12000 },
{ "a" : "4", "b" : "12", "guard" : 12000 },
{ "a" : "5", "b" : "13", "guard" : 36000 },
{ "a" : "6", "b" : "14", "guard" : 12000 },
{ "a" : "7", "b" : "15", "guard" : 12000 },
{ "a" : "8", "b" : "16", "guard" : 12000 },
{ "a" : "9", "b" : "17", "guard" : 75000 },
{ "a" : "10", "b" : "17", "guard" : 25000 },
{ "a" : "11", "b" : "18", "guard" : 25000 },
{ "a" : "12", "b" : "18", "guard" : 25000 },
{ "a" : "13", "b" : "19", "guard" : 75000 },
{ "a" : "14", "b" : "19", "guard" : 25000 },
{ "a" : "15", "b" : "20", "guard" : 25000 },
{ "a" : "16", "b" : "20", "guard" : 25000 },
{ "a" : "17", "b" : "18", "guard" : 50000 },
{ "a" : "19", "b" : "20", "guard" : 50000 },
{ "a" : "17", "b" : "21", "guard" : 60000 },
{ "a" : "18", "b" : "21", "guard" : 60000 },
{ "a" : "19", "b" : "21", "guard" : 60000 },
{ "a" : "20", "b" : "21", "guard" : 60000 }
]
}
}

View File

@ -0,0 +1,12 @@
{
"name" : "Coldshadow's Fantasy",
"description" : "Random map template, 4-8p XL+U",
"version" : "0.99",
"author" : "Coldshadow, ported by VCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Templates",
"templates" : [
"config/defaultTemplates/coldshadowsFantasy"
],
}

View File

@ -0,0 +1,76 @@
{
"Golden Ring" :
{
"minSize" : "m+u", "maxSize" : "l",
"players" : "3",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 2, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1},
"treasure" : [
{"min" : 300, "max": 2000, "density": 15},
{"min" : 2100, "max": 2500, "density": 5}
]
},
"2" :
{
"type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3" :
{
"type" : "playerStart", "size" : 2, "owner" : 3,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"4" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 1,
"monsters" : "normal",
"mines" : {"gems" : 1, "crystal" : 1},
"treasure" : [
{"min" : 3000, "max": 10000, "density" : 12},
{"min" : 6000, "max": 10000, "density" : 6}
]},
"5" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 1,
"monsters" : "normal",
"mines" : {"sulfur" : 1, "mercury" : 1},
"treasureLikeZone" : 4},
"6" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 2, "monsters" : "normal", "minesLikeZone" : 5, "treasureLikeZone" : 4 },
"7" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 2, "monsters" : "normal", "minesLikeZone" : 4, "treasureLikeZone" : 4 },
"8" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 3, "monsters" : "normal", "minesLikeZone" : 4, "treasureLikeZone" : 4 },
"9" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 3, "monsters" : "normal", "minesLikeZone" : 5, "treasureLikeZone" : 4 },
"10" : { "type" : "treasure", "size" : 1, "neutralTowns" : { "towns" : 1 },
"monsters" : "strong",
"mines" : {"gold" : 1},
"treasure" : [
{"min" : 21000, "max": 25000, "density" : 3},
{"min" : 10000, "max": 21000, "density" : 10}
]},
"11" : { "type" : "treasure", "size" : 1, "neutralTowns" : { "towns" : 1 }, "monsters" : "strong", "minesLikeZone" : 10, "treasureLikeZone" : 10 },
"12" : { "type" : "treasure", "size" : 1, "neutralTowns" : { "towns" : 1 }, "monsters" : "strong", "minesLikeZone" : 10, "treasureLikeZone" : 10 }
},
"connections" :
[
{ "a" : "1", "b" : "4", "guard" : 2500 },
{ "a" : "1", "b" : "5", "guard" : 2500 },
{ "a" : "2", "b" : "6", "guard" : 2500 },
{ "a" : "2", "b" : "7", "guard" : 2500 },
{ "a" : "3", "b" : "8", "guard" : 2500 },
{ "a" : "3", "b" : "9", "guard" : 2500 },
{ "a" : "4", "b" : "10", "guard" : 20000 },
{ "a" : "5", "b" : "12", "guard" : 20000 },
{ "a" : "6", "b" : "10", "guard" : 20000 },
{ "a" : "7", "b" : "11", "guard" : 20000 },
{ "a" : "8", "b" : "12", "guard" : 20000 },
{ "a" : "9", "b" : "11", "guard" : 20000 }
]
}
}

View File

@ -0,0 +1,12 @@
{
"name" : "Golden Ring",
"description" : "Random map template, 3p M+U/L",
"version" : "0.99",
"author" : "VCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Templates",
"templates" : [
"config/defaultTemplates/goldenRing"
],
}

View File

@ -0,0 +1,75 @@
{
"Jebus Cross":
{
"minSize" : "l+u", "maxSize" : "xl+u",
"players" : "2-4",
"zones":
{
"1":
{
"type" : "playerStart", "size" : 30, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "weak",
"mines" : {"wood" : 4, "ore" : 4, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 2},
"treasure" : [
{"min" : 12000, "max": 22000, "density": 1},
{"min" : 5000, "max": 16000, "density": 6},
{"min" : 300, "max": 3000, "density": 14}
]
},
"2":
{
"type" : "playerStart", "size" : 30, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3":
{
"type" : "playerStart", "size" : 30, "owner" : 3,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"4":
{
"type" : "playerStart", "size" : 30, "owner" : 4,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"5" :
{
"type" : "treasure", "size" : 40,
"neutralTowns" : { "castles" : 2 },
"terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "strong",
"mines" : {"gold" : 4},
"treasure" : [
{"min" : 35000, "max": 55000, "density" : 3},
{"min" : 25000, "max": 35000, "density" : 10},
{"min" : 10000, "max": 25000, "density" : 10}
]
}
},
"connections" :
[
{ "a" : "1", "b" : "5", "guard" : 45000 },
{ "a" : "2", "b" : "5", "guard" : 45000 },
{ "a" : "3", "b" : "5", "guard" : 45000 },
{ "a" : "4", "b" : "5", "guard" : 45000 }
]
}
}

View File

@ -0,0 +1,12 @@
{
"name" : "Jebus Cross",
"description" : "Random map template, 4p L+U/XL+U",
"version" : "0.99",
"author" : "Bjorn190, ported by VCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Templates",
"templates" : [
"config/defaultTemplates/jebusCross"
],
}

View File

@ -0,0 +1,65 @@
{
"Upgrade" :
{
"minSize" : "s+u", "maxSize" : "m",
"players" : "2",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 3, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1},
"treasure" : [
{"min" : 400, "max": 1500, "density" : 16},
{"min" : 1500, "max": 2500, "density" : 4}
]
},
"2" :
{
"type" : "playerStart", "size" : 3, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3" :
{
"type" : "treasure", "size" : 4, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 1,
"monsters" : "weak",
"mines" : {"gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 2000, "max": 4000, "density" : 15},
{"min" : 4000, "max": 5000, "density" : 5}
]
},
"4" :
{
"type" : "treasure", "size" : 4, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 2,
"monsters" : "weak",
"minesLikeZone" : 3,
"treasureLikeZone" : 3
},
"5" :
{
"type" : "treasure", "size" : 5, "neutralTowns" : { "castles" : 1 }, "terrainTypes" : [ "sand" ],
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
{"min" : 11000, "max": 12000, "density" : 5},
{"min" : 6000, "max": 11000, "density" : 10}
]
}
},
"connections" :
[
{ "a" : "1", "b" : "3", "guard" : 3000 },
{ "a" : "1", "b" : "5", "guard" : 9000 },
{ "a" : "2", "b" : "4", "guard" : 3000 },
{ "a" : "2", "b" : "5", "guard" : 9000 },
{ "a" : "3", "b" : "5", "guard" : 6000 },
{ "a" : "4", "b" : "5", "guard" : 6000 }
]
}
}

View File

@ -0,0 +1,12 @@
{
"name" : "Upgrade",
"description" : "Random map template, 1v1 S+U/M",
"version" : "0.99",
"author" : "BVCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Templates",
"templates" : [
"config/defaultTemplates/upgrade"
],
}

View File

@ -0,0 +1,9 @@
{
"name" : "Default templates",
"description" : "A set of random map templates for VCMI",
"version" : "0.99",
"author" : "VCMI Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Templates"
}

View File

@ -1671,7 +1671,7 @@ CRandomMapTab::CRandomMapTab()
{
mapGenOptions.setPlayerCount(btnId);
deactivateButtonsFrom(teamsCntGroup, btnId);
deactivateButtonsFrom(compOnlyPlayersCntGroup, 8 - btnId + 1);
deactivateButtonsFrom(compOnlyPlayersCntGroup, btnId);
validatePlayersCnt(btnId);
if(!SEL->isGuest())
updateMapInfo();
@ -1694,7 +1694,6 @@ CRandomMapTab::CRandomMapTab()
compOnlyPlayersCntGroup->pos.y += 285;
compOnlyPlayersCntGroup->pos.x += BTNS_GROUP_LEFT_MARGIN;
addButtonsWithRandToGroup(compOnlyPlayersCntGroup, numberDefs, 0, 7, NUMBERS_WIDTH, 224, 232);
compOnlyPlayersCntGroup->setSelected(0);
compOnlyPlayersCntGroup->addCallback([&](int btnId)
{
mapGenOptions.setCompOnlyPlayerCount(btnId);
@ -1808,9 +1807,9 @@ void CRandomMapTab::validatePlayersCnt(int playersCnt)
mapGenOptions.setTeamCount(playersCnt - 1);
teamsCntGroup->setSelected(mapGenOptions.getTeamCount());
}
if(mapGenOptions.getCompOnlyPlayerCount() > 8 - playersCnt)
if(mapGenOptions.getCompOnlyPlayerCount() >= playersCnt)
{
mapGenOptions.setCompOnlyPlayerCount(8 - playersCnt);
mapGenOptions.setCompOnlyPlayerCount(playersCnt - 1);
compOnlyPlayersCntGroup->setSelected(mapGenOptions.getCompOnlyPlayerCount());
}

View File

@ -1,542 +0,0 @@
// Defines random map templates.
{
"Analogy" :
{
"minSize" : "m", "maxSize" : "m+u",
"players" : "4",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 2, "owner" : 1,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1},
"treasure" : [
{"min" : 2100, "max": 3000, "density" : 5},
{"min" : 300, "max": 1500, "density" : 10}
]
},
"2" :
{
"type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3" :
{
"type" : "playerStart", "size" : 2, "owner" : 3,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"4" :
{
"type" : "playerStart", "size" : 2, "owner" : 4,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"5" :
{
"type" : "treasure", "size" : 3, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
"neutralTowns" : { "castles" : 1 },
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
{"min" : 9000, "max": 10000, "density" : 3},
{"min" : 6000, "max": 10000, "density" : 15}
]
}
},
"connections" :
[
{ "a" : "1", "b" : "5", "guard" : 5000 },
{ "a" : "2", "b" : "5", "guard" : 5000 },
{ "a" : "3", "b" : "5", "guard" : 5000 },
{ "a" : "4", "b" : "5", "guard" : 5000 }
]
},
"Upgrade" :
{
"minSize" : "s+u", "maxSize" : "m",
"players" : "2",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 3, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1},
"treasure" : [
{"min" : 400, "max": 1500, "density" : 16},
{"min" : 1500, "max": 2500, "density" : 4}
]
},
"2" :
{
"type" : "playerStart", "size" : 3, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3" :
{
"type" : "treasure", "size" : 4, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 1,
"monsters" : "weak",
"mines" : {"gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 2000, "max": 4000, "density" : 15},
{"min" : 4000, "max": 5000, "density" : 5}
]
},
"4" :
{
"type" : "treasure", "size" : 4, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 2,
"monsters" : "weak",
"minesLikeZone" : 3,
"treasureLikeZone" : 3
},
"5" :
{
"type" : "treasure", "size" : 5, "neutralTowns" : { "castles" : 1 }, "terrainTypes" : [ "sand" ],
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
{"min" : 11000, "max": 12000, "density" : 5},
{"min" : 6000, "max": 11000, "density" : 10}
]
}
},
"connections" :
[
{ "a" : "1", "b" : "3", "guard" : 3000 },
{ "a" : "1", "b" : "5", "guard" : 9000 },
{ "a" : "2", "b" : "4", "guard" : 3000 },
{ "a" : "2", "b" : "5", "guard" : 9000 },
{ "a" : "3", "b" : "5", "guard" : 6000 },
{ "a" : "4", "b" : "5", "guard" : 6000 }
]
},
"Golden Ring" :
{
"minSize" : "m+u", "maxSize" : "l",
"players" : "3",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 2, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1},
"treasure" : [
{"min" : 300, "max": 2000, "density": 15},
{"min" : 2100, "max": 2500, "density": 5}
]
},
"2" :
{
"type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3" :
{
"type" : "playerStart", "size" : 2, "owner" : 3,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"4" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 1,
"monsters" : "normal",
"mines" : {"gems" : 1, "crystal" : 1},
"treasure" : [
{"min" : 3000, "max": 10000, "density" : 12},
{"min" : 6000, "max": 10000, "density" : 6}
]},
"5" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 1,
"monsters" : "normal",
"mines" : {"sulfur" : 1, "mercury" : 1},
"treasureLikeZone" : 4},
"6" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 2, "monsters" : "normal", "minesLikeZone" : 5, "treasureLikeZone" : 4 },
"7" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 2, "monsters" : "normal", "minesLikeZone" : 4, "treasureLikeZone" : 4 },
"8" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 3, "monsters" : "normal", "minesLikeZone" : 4, "treasureLikeZone" : 4 },
"9" : { "type" : "treasure", "size" : 1, "terrainTypeLikeZone" : 3, "monsters" : "normal", "minesLikeZone" : 5, "treasureLikeZone" : 4 },
"10" : { "type" : "treasure", "size" : 1, "neutralTowns" : { "towns" : 1 },
"monsters" : "strong",
"mines" : {"gold" : 1},
"treasure" : [
{"min" : 21000, "max": 25000, "density" : 3},
{"min" : 10000, "max": 21000, "density" : 10}
]},
"11" : { "type" : "treasure", "size" : 1, "neutralTowns" : { "towns" : 1 }, "monsters" : "strong", "minesLikeZone" : 10, "treasureLikeZone" : 10 },
"12" : { "type" : "treasure", "size" : 1, "neutralTowns" : { "towns" : 1 }, "monsters" : "strong", "minesLikeZone" : 10, "treasureLikeZone" : 10 }
},
"connections" :
[
{ "a" : "1", "b" : "4", "guard" : 2500 },
{ "a" : "1", "b" : "5", "guard" : 2500 },
{ "a" : "2", "b" : "6", "guard" : 2500 },
{ "a" : "2", "b" : "7", "guard" : 2500 },
{ "a" : "3", "b" : "8", "guard" : 2500 },
{ "a" : "3", "b" : "9", "guard" : 2500 },
{ "a" : "4", "b" : "10", "guard" : 20000 },
{ "a" : "5", "b" : "12", "guard" : 20000 },
{ "a" : "6", "b" : "10", "guard" : 20000 },
{ "a" : "7", "b" : "11", "guard" : 20000 },
{ "a" : "8", "b" : "12", "guard" : 20000 },
{ "a" : "9", "b" : "11", "guard" : 20000 }
]
},
"Unfair Game" :
{
"minSize" : "m", "maxSize" : "m",
"players" : "2", "cpu" : "2",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 2, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
},
"2" :
{
"type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
},
"3" :
{
"type" : "cpuStart", "size" : 3, "owner" : 3,
"playerTowns" : { "castles" : 1 },
"monsters" : "weak",
},
"4" :
{
"type" : "cpuStart", "size" : 3, "owner" : 4,
"playerTowns" : { "castles" : 1 },
"monsters" : "weak",
},
"5" : { "type" : "treasure", "size" : 1, "monsters" : "strong", "terrainTypeLikeZone" : 3 },
"6" : { "type" : "treasure", "size" : 1, "monsters" : "strong", "terrainTypeLikeZone" : 4 }
},
"connections" :
[
{ "a" : "1", "b" : "3", "guard" : 5000 },
{ "a" : "1", "b" : "4", "guard" : 5000 },
{ "a" : "2", "b" : "3", "guard" : 5000 },
{ "a" : "2", "b" : "4", "guard" : 5000 },
{ "a" : "3", "b" : "5", "guard" : 2000 },
{ "a" : "4", "b" : "6", "guard" : 2000 }
]
},
"Jebus Cross":
{
"minSize" : "l+u", "maxSize" : "xl+u",
"players" : "4",
"zones":
{
"1":
{
"type" : "playerStart", "size" : 30, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "weak",
"mines" : {"wood" : 4, "ore" : 4, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 2},
"treasure" : [
{"min" : 12000, "max": 22000, "density": 1},
{"min" : 5000, "max": 16000, "density": 6},
{"min" : 300, "max": 3000, "density": 14}
]
},
"2":
{
"type" : "playerStart", "size" : 30, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"3":
{
"type" : "playerStart", "size" : 30, "owner" : 3,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"4":
{
"type" : "playerStart", "size" : 30, "owner" : 4,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"5" :
{
"type" : "treasure", "size" : 40,
"neutralTowns" : { "castles" : 2 },
"terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
"bannedTowns" : ["necropolis", "conflux"],
"monsters" : "strong",
"mines" : {"gold" : 4},
"treasure" : [
{"min" : 35000, "max": 55000, "density" : 3},
{"min" : 25000, "max": 35000, "density" : 10},
{"min" : 10000, "max": 25000, "density" : 10}
]
}
},
"connections" :
[
{ "a" : "1", "b" : "5", "guard" : 45000 },
{ "a" : "2", "b" : "5", "guard" : 45000 },
{ "a" : "3", "b" : "5", "guard" : 45000 },
{ "a" : "4", "b" : "5", "guard" : 45000 }
]
},
"Clash of Dragons 1.2":
{
"minSize" : "l+u", "maxSize" : "xl+u",
"players" : "2",
"zones":
{
"1":
{
"type" : "playerStart", "size" : 100, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"monsters" : "weak",
"mines" : {"wood" : 1, "ore" : 1, "gold" : 1},
"treasure" : [
{"min" : 2000, "max": 5000, "density": 4},
{"min" : 5000, "max": 9000, "density": 6},
{"min" : 300, "max": 1900, "density": 15}
]
},
"2":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypes" : ["grass"], "matchTerrainToTown" : false,
"monsters" : "normal",
"mines" : {"gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 5000, "max": 12000, "density": 2},
{"min" : 10000, "max": 20000, "density": 4},
{"min" : 300, "max": 1900, "density": 15}
]
},
"3":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypes" : ["lava"], "matchTerrainToTown" : false,
"monsters" : "strong",
"mines" : {"wood" : 1, "ore" : 1, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 20000, "max": 25000, "density": 10},
{"min" : 10000, "max": 15000, "density": 8},
{"min" : 300, "max": 1900, "density": 10}
]
},
"4":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypes" : ["dirt"], "matchTerrainToTown" : false,
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
{"min" : 20000, "max": 25000, "density": 15},
{"min" : 10000, "max": 15000, "density": 10},
{"min" : 300, "max": 1900, "density": 6}
]
},
"5":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "castles" : 1 },
"terrainTypes" : ["snow"], "matchTerrainToTown" : false,
"allowedTowns" : ["tower"],
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
{"min" : 20000, "max": 30000, "density": 15}
]
},
"6":
{
"type" : "treasure", "size" : 40,
"terrainTypes" : ["grass"], "matchTerrainToTown" : false,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 80000, "max": 120000, "density": 10}
]
},
"7":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 6,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"sulfur" : 1, "gold" : 1},
"treasureLikeZone" : 6
},
"8":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 6,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"crystal" : 1, "gold" : 1},
"treasureLikeZone" : 6
},
"9":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 6,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"gems" : 1, "gold" : 1},
"treasureLikeZone" : 6
},
"10":
{
"type" : "treasure", "size" : 40,
"terrainTypes" : ["snow"], "matchTerrainToTown" : false,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"mines" : {"mercury" : 1, "gold" : 1},
"treasure" : [
{"min" : 80000, "max": 80000, "density": 10}
]
},
"11":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 10,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"minesLikeZone" : 10,
"treasureLikeZone" : 10
},
"12":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 10,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"minesLikeZone" : 10,
"treasureLikeZone" : 10
},
"13":
{
"type" : "treasure", "size" : 40,
"terrainTypeLikeZone" : 10,
"allowedTowns" : ["tower", "castle", "neutral"],
"allowedMonsters" : ["neutral", "rampart", "dungeon"],
"monsters" : "strong",
"minesLikeZone" : 10,
"treasureLikeZone" : 10
},
"14":
{
"type" : "playerStart", "size" : 100, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"neutralTowns" : { "towns" : 2 },
"monsters" : "weak",
"minesLikeZone" : 1,
"treasureLikeZone" : 1
},
"15":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypeLikeZone" : 2,
"monsters" : "normal",
"minesLikeZone" : 2,
"treasureLikeZone" : 2
},
"16":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypeLikeZone" : 3,
"monsters" : "strong",
"minesLikeZone" : 3,
"treasureLikeZone" : 3
},
"17":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "towns" : 1 },
"terrainTypeLikeZone" : 4,
"monsters" : "strong",
"minesLikeZone" : 4,
"treasureLikeZone" : 4
},
"18":
{
"type" : "treasure", "size" : 100,
"neutralTowns" : { "castles" : 1 },
"terrainTypeLikeZone" : 5,
"townTypeLikeZone" : 5,
"monsters" : "strong",
"minesLikeZone" : 5,
"treasureLikeZone" : 5
}
},
"connections" :
[
{ "a" : "1", "b" : "2", "guard" : 4000 },
{ "a" : "2", "b" : "3", "guard" : 12000 },
{ "a" : "2", "b" : "4", "guard" : 20000 },
{ "a" : "4", "b" : "5", "guard" : 30000 },
{ "a" : "5", "b" : "6", "guard" : 50000 },
{ "a" : "6", "b" : "7", "guard" : 50000 },
{ "a" : "7", "b" : "8", "guard" : 50000 },
{ "a" : "7", "b" : "9", "guard" : 50000 },
{ "a" : "18", "b" : "9", "guard" : 50000 },
{ "a" : "5", "b" : "10", "guard" : 50000 },
{ "a" : "10", "b" : "11", "guard" : 50000 },
{ "a" : "11", "b" : "12", "guard" : 50000 },
{ "a" : "11", "b" : "13", "guard" : 50000 },
{ "a" : "14", "b" : "15", "guard" : 4000 },
{ "a" : "15", "b" : "16", "guard" : 12000 },
{ "a" : "15", "b" : "17", "guard" : 20000 },
{ "a" : "17", "b" : "18", "guard" : 30000 },
{ "a" : "18", "b" : "13", "guard" : 50000 },
{ "a" : "18", "b" : "5", "guard" : 150000 },
{ "a" : "3", "b" : "16", "guard" : 180000 }
]
}
}

View File

@ -0,0 +1,79 @@
{
"type":"object",
"$schema": "",
"title" : "VCMI random map template format",
"description" : "Format used to define random map templates in VCMI",
"definitions" :
{
"zone":{
"type": "object",
"required" : ["type", "monsters", "size"],
"properties":{
"type":{"$ref" : "#/definitions/type"},
"size":{"$ref" : "#/definitions/size"},
"playerTowns":{"$ref" : "#/definitions/playerTowns"},
"neuralTowns":{"$ref" : "#/definitions/neuralTowns"},
"townsAreSameType":{"$ref" : "#/definitions/townsAreSameType"},
"monsters":{"$ref" : "#/definitions/monsters"},
"mines":{"$ref" : "#/definitions/mines"},
"treasure":{
"type":"array",
"items":{
"type": "object",
"properties":{
"min": {"type":"number", "minimum" : 0},
"max": {"type":"number", "minimum" : 0},
"density": {"type":"number", "minimum" : 1}
},
"additionalProperties" : false
}
}
}
},
"type" :{
"enum": ["playerStart", "cpuStart", "treasure", "junction"],
"additionalProperties" : false,
"type":"string"
},
"size":{
"type": "number",
"minimum": 1,
"additionalProperties" : false,
}
"connection":
{
required: ["a", "b", "guard"]
properties:{
"a":{
"type" : "string"
},
"b":{
"type" : "string"
},
"guard":
{
"type": "number",
"minimum" : 0
}
}
}
},
"properties":
{
"zones":{
"type": "object",
"additionalProperties":{"$ref" : "#/definitions/zone" }
},
"connections":{
"type": "array",
"items":{"$ref" : "#/definitions/connection"}
},
"required" : ["zones", "connections"],
"additionalProperties" : false
}
}

View File

@ -385,6 +385,7 @@ CContentHandler::CContentHandler()
handlers.insert(std::make_pair("objects", ContentTypeHandler(VLC->objtypeh, "object")));
handlers.insert(std::make_pair("heroes", ContentTypeHandler(VLC->heroh, "hero")));
handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh, "spell")));
handlers.insert(std::make_pair("templates", ContentTypeHandler((IHandlerBase *)VLC->tplh, "template")));
//TODO: any other types of moddables?
}

View File

@ -942,6 +942,8 @@ enum class ESpellSchool: ui8
EARTH = 3
};
ID_LIKE_OPERATORS_DECLS(SpellID, SpellID::ESpellID)
// Typedef declarations
typedef ui8 TFaction;
typedef si64 TExpType;

View File

@ -115,12 +115,12 @@ void LibClasses::init()
createHandler(terviewh, "Terrain view pattern", pomtime);
createHandler(tplh, "Template", pomtime); //templates need already resolved identifiers (refactor?)
logGlobal->infoStream()<<"\tInitializing handlers: "<< totalTime.getDiff();
modh->load();
createHandler(tplh, "Template", pomtime); //templates need already resolved identifiers (refactor?)
modh->afterLoad();
//FIXME: make sure that everything is ok after game restart

View File

@ -20,7 +20,7 @@
#include "../CTownHandler.h"
CMapGenOptions::CMapGenOptions() : width(CMapHeader::MAP_SIZE_MIDDLE), height(CMapHeader::MAP_SIZE_MIDDLE), hasTwoLevels(false),
playerCount(RANDOM_SIZE), teamCount(RANDOM_SIZE), compOnlyPlayerCount(0), compOnlyTeamCount(RANDOM_SIZE),
playerCount(RANDOM_SIZE), teamCount(RANDOM_SIZE), compOnlyPlayerCount(RANDOM_SIZE), compOnlyTeamCount(RANDOM_SIZE), humanPlayersCount(0),
waterContent(EWaterContent::RANDOM), monsterStrength(EMonsterStrength::RANDOM), mapTemplate(nullptr)
{
resetPlayersMap();
@ -67,9 +67,14 @@ void CMapGenOptions::setPlayerCount(si8 value)
{
assert((value >= 1 && value <= PlayerColor::PLAYER_LIMIT_I) || value == RANDOM_SIZE);
playerCount = value;
auto possibleCompPlayersCount = PlayerColor::PLAYER_LIMIT_I-value;
if(compOnlyPlayerCount > possibleCompPlayersCount)
auto possibleCompPlayersCount = value;
if (compOnlyPlayerCount > possibleCompPlayersCount)
setCompOnlyPlayerCount(possibleCompPlayersCount);
if (getPlayerCount() != RANDOM_SIZE && getCompOnlyPlayerCount() != RANDOM_SIZE)
humanPlayersCount = getPlayerCount() - getCompOnlyPlayerCount();
resetPlayersMap();
}
@ -80,7 +85,7 @@ si8 CMapGenOptions::getTeamCount() const
void CMapGenOptions::setTeamCount(si8 value)
{
assert(playerCount == RANDOM_SIZE || (value >= 0 && value < playerCount) || value == RANDOM_SIZE);
assert(getPlayerCount() == RANDOM_SIZE || (value >= 0 && value < getPlayerCount()) || value == RANDOM_SIZE);
teamCount = value;
}
@ -91,8 +96,12 @@ si8 CMapGenOptions::getCompOnlyPlayerCount() const
void CMapGenOptions::setCompOnlyPlayerCount(si8 value)
{
assert(value == RANDOM_SIZE || (value >= 0 && value <= PlayerColor::PLAYER_LIMIT_I - playerCount));
assert(value == RANDOM_SIZE || (value >= 0 && value <= getPlayerCount()));
compOnlyPlayerCount = value;
if (getPlayerCount() != RANDOM_SIZE && getCompOnlyPlayerCount() != RANDOM_SIZE)
humanPlayersCount = getPlayerCount() - getCompOnlyPlayerCount();
resetPlayersMap();
}
@ -130,18 +139,19 @@ void CMapGenOptions::setMonsterStrength(EMonsterStrength::EMonsterStrength value
void CMapGenOptions::resetPlayersMap()
{
players.clear();
int realPlayersCnt = playerCount == RANDOM_SIZE ? static_cast<int>(PlayerColor::PLAYER_LIMIT_I) : playerCount;
int realCompOnlyPlayersCnt = compOnlyPlayerCount == RANDOM_SIZE ? (PlayerColor::PLAYER_LIMIT_I - realPlayersCnt) : compOnlyPlayerCount;
int realPlayersCnt = humanPlayersCount;
int realCompOnlyPlayersCnt = (compOnlyPlayerCount == RANDOM_SIZE) ? (PlayerColor::PLAYER_LIMIT_I - realPlayersCnt) : compOnlyPlayerCount;
int totalPlayersLimit = realPlayersCnt + realCompOnlyPlayersCnt;
if(playerCount == RANDOM_SIZE || compOnlyPlayerCount == RANDOM_SIZE)
if (getPlayerCount() == RANDOM_SIZE || compOnlyPlayerCount == RANDOM_SIZE)
totalPlayersLimit = static_cast<int>(PlayerColor::PLAYER_LIMIT_I);
//FIXME: what happens with human players here?
for(int color = 0; color < totalPlayersLimit; ++color)
{
CPlayerSettings player;
player.setColor(PlayerColor(color));
auto playerType = EPlayerType::AI;
if((playerCount != RANDOM_SIZE && color >= realPlayersCnt)
if ((getPlayerCount() != RANDOM_SIZE && color >= realPlayersCnt)
|| (compOnlyPlayerCount != RANDOM_SIZE && color >= (PlayerColor::PLAYER_LIMIT_I-compOnlyPlayerCount)))
{
playerType = EPlayerType::COMP_ONLY;
@ -191,7 +201,7 @@ const std::map<std::string, CRmgTemplate *> & CMapGenOptions::getAvailableTempla
void CMapGenOptions::finalize(CRandomGenerator & rand)
{
logGlobal->infoStream() << boost::format ("RMG settings: players %d, teams %d, computer players %d, computer teams %d, water %d, monsters %d")
% playerCount % teamCount % compOnlyPlayerCount % compOnlyTeamCount % waterContent % monsterStrength;
% (int)getPlayerCount() % (int)getTeamCount() % (int)getCompOnlyPlayerCount() % (int)getCompOnlyTeamCount() % (int)getWaterContent() % (int)getMonsterStrength();
if(!mapTemplate)
{
@ -199,17 +209,18 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
}
assert(mapTemplate);
if(playerCount == RANDOM_SIZE)
if (getPlayerCount() == RANDOM_SIZE)
{
auto possiblePlayers = mapTemplate->getPlayers().getNumbers();
possiblePlayers.erase(possiblePlayers.begin(), possiblePlayers.lower_bound(countHumanPlayers()));
//ignore all non-randomized players, make sure these players will not be missing after roll
possiblePlayers.erase(possiblePlayers.begin(), possiblePlayers.lower_bound(countHumanPlayers() + countCompOnlyPlayers()));
assert(!possiblePlayers.empty());
playerCount = *RandomGeneratorUtil::nextItem(possiblePlayers, rand);
setPlayerCount (*RandomGeneratorUtil::nextItem(possiblePlayers, rand));
updatePlayers();
}
if(teamCount == RANDOM_SIZE)
{
teamCount = rand.nextInt(playerCount - 1);
teamCount = rand.nextInt(getPlayerCount() - 1);
if (teamCount == 1)
teamCount = 0;
}
@ -236,9 +247,37 @@ void CMapGenOptions::finalize(CRandomGenerator & rand)
assert (vstd::iswithin(waterContent, EWaterContent::NONE, EWaterContent::ISLANDS));
assert (vstd::iswithin(monsterStrength, EMonsterStrength::GLOBAL_WEAK, EMonsterStrength::GLOBAL_STRONG));
//rectangular maps are the future of gaming
//setHeight(20);
//setWidth(50);
logGlobal->traceStream() << "Player config:";
int humanPlayers = 0, cpuOnlyPlayers = 0, AIplayers = 0;
for (auto player : players)
{
std::string playerType;
switch (player.second.getPlayerType())
{
case EPlayerType::AI:
playerType = "AI";
AIplayers++;
break;
case EPlayerType::COMP_ONLY:
playerType = "computer only";
cpuOnlyPlayers++;
break;
case EPlayerType::HUMAN:
playerType = "human only";
humanPlayers++;
break;
default:
assert(false);
}
logGlobal->traceStream() << boost::format("Player %d: %s") % player.second.getColor() % playerType;
}
setCompOnlyPlayerCount(cpuOnlyPlayers); //human players are set automaticlaly (?)
logGlobal->infoStream() << boost::format("Final player config: %d total, %d cpu-only") % players.size() % (int)getCompOnlyPlayerCount();
}
void CMapGenOptions::updatePlayers()
@ -248,7 +287,7 @@ void CMapGenOptions::updatePlayers()
{
auto it = itrev;
--it;
if(players.size() == playerCount) break;
if (players.size() == getPlayerCount()) break;
if(it->second.getPlayerType() == EPlayerType::AI)
{
players.erase(it);
@ -262,14 +301,12 @@ void CMapGenOptions::updatePlayers()
void CMapGenOptions::updateCompOnlyPlayers()
{
auto totalPlayersCnt = playerCount + compOnlyPlayerCount;
// Remove comp only players only from the end of the players map if necessary
for(auto itrev = players.end(); itrev != players.begin();)
{
auto it = itrev;
--it;
if(players.size() <= totalPlayersCnt) break;
if (players.size() <= getPlayerCount()) break;
if(it->second.getPlayerType() == EPlayerType::COMP_ONLY)
{
players.erase(it);
@ -281,7 +318,13 @@ void CMapGenOptions::updateCompOnlyPlayers()
}
// Add some comp only players if necessary
auto compOnlyPlayersToAdd = totalPlayersCnt - players.size();
int compOnlyPlayersToAdd = getPlayerCount() - players.size();
if (compOnlyPlayersToAdd < 0)
{
logGlobal->errorStream() << boost::format("Incorrect number of players to add. Requested players %d, current players %d") % playerCount % players.size();
assert (compOnlyPlayersToAdd < 0);
}
for(int i = 0; i < compOnlyPlayersToAdd; ++i)
{
CPlayerSettings pSettings;
@ -299,6 +342,15 @@ int CMapGenOptions::countHumanPlayers() const
}));
}
int CMapGenOptions::countCompOnlyPlayers() const
{
return static_cast<int>(boost::count_if(players, [](const std::pair<PlayerColor, CPlayerSettings> & pair)
{
return pair.second.getPlayerType() == EPlayerType::COMP_ONLY;
}));
}
PlayerColor CMapGenOptions::getNextPlayerColor() const
{
for(PlayerColor i = PlayerColor(0); i < PlayerColor::PLAYER_LIMIT; i.advance(1))
@ -308,7 +360,8 @@ PlayerColor CMapGenOptions::getNextPlayerColor() const
return i;
}
}
assert(0);
logGlobal->errorStream() << "Failed to get next player color";
assert(false);
return PlayerColor(0);
}
@ -338,33 +391,36 @@ const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand
if(tplSize >= tpl->getMinSize() && tplSize <= tpl->getMaxSize())
{
bool isPlayerCountValid = false;
if(playerCount != RANDOM_SIZE)
if (getPlayerCount() != RANDOM_SIZE)
{
if(tpl->getPlayers().isInRange(playerCount)) isPlayerCountValid = true;
if (tpl->getPlayers().isInRange(getPlayerCount()))
isPlayerCountValid = true;
}
else
{
// Human players shouldn't be banned when playing with random player count
auto playerNumbers = tpl->getPlayers().getNumbers();
if(playerNumbers.lower_bound(countHumanPlayers()) != playerNumbers.end())
if(countHumanPlayers() <= *boost::min_element(playerNumbers))
{
isPlayerCountValid = true;
}
}
if(isPlayerCountValid)
if (isPlayerCountValid)
{
bool isCpuPlayerCountValid = false;
if(compOnlyPlayerCount != RANDOM_SIZE)
{
if(tpl->getCpuPlayers().isInRange(compOnlyPlayerCount)) isCpuPlayerCountValid = true;
if (tpl->getCpuPlayers().isInRange(compOnlyPlayerCount))
isCpuPlayerCountValid = true;
}
else
{
isCpuPlayerCountValid = true;
}
if(isCpuPlayerCountValid) potentialTpls.push_back(tpl);
if(isCpuPlayerCountValid)
potentialTpls.push_back(tpl);
}
}
}

View File

@ -103,7 +103,7 @@ public:
bool getHasTwoLevels() const;
void setHasTwoLevels(bool value);
/// The count of the players ranging from 1 to PlayerColor::PLAYER_LIMIT or RANDOM_SIZE for random. If you call
/// The count of all (human or computer) players ranging from 1 to PlayerColor::PLAYER_LIMIT or RANDOM_SIZE for random. If you call
/// this method, all player settings are reset to default settings.
si8 getPlayerCount() const;
void setPlayerCount(si8 value);
@ -155,6 +155,7 @@ public:
private:
void resetPlayersMap();
int countHumanPlayers() const;
int countCompOnlyPlayers() const;
PlayerColor getNextPlayerColor() const;
void updateCompOnlyPlayers();
void updatePlayers();
@ -162,7 +163,7 @@ private:
si32 width, height;
bool hasTwoLevels;
si8 playerCount, teamCount, compOnlyPlayerCount, compOnlyTeamCount;
si8 playerCount, teamCount, humanPlayersCount, compOnlyPlayerCount, compOnlyTeamCount;
EWaterContent::EWaterContent waterContent;
EMonsterStrength::EMonsterStrength monsterStrength;
std::map<PlayerColor, CPlayerSettings> players;
@ -173,7 +174,7 @@ public:
void serialize(Handler & h, const int version)
{
h & width & height & hasTwoLevels & playerCount & teamCount & compOnlyPlayerCount;
h & compOnlyTeamCount & waterContent & monsterStrength & players;
h & compOnlyTeamCount & waterContent & monsterStrength & players & humanPlayersCount;
//TODO add name of template to class, enables selection of a template by a user
}
};

View File

@ -144,7 +144,7 @@ std::string CMapGenerator::getMapDescription() const
std::stringstream ss;
ss << boost::str(boost::format(std::string("Map created by the Random Map Generator.\nTemplate was %s, Random seed was %d, size %dx%d") +
", levels %s, humans %d, computers %d, water %s, monster %s, VCMI map") % mapGenOptions->getMapTemplate()->getName() %
", levels %s, players %d, computers %d, water %s, monster %s, VCMI map") % mapGenOptions->getMapTemplate()->getName() %
randomSeed % map->width % map->height % (map->twoLevel ? "2" : "1") % static_cast<int>(mapGenOptions->getPlayerCount()) %
static_cast<int>(mapGenOptions->getCompOnlyPlayerCount()) % waterContentStr[mapGenOptions->getWaterContent()] %
monsterStrengthStr[monsterStrengthIndex]);
@ -169,19 +169,32 @@ std::string CMapGenerator::getMapDescription() const
void CMapGenerator::addPlayerInfo()
{
// Calculate which team numbers exist
std::array<std::list<int>, 2> teamNumbers; // 0= cpu/human, 1= cpu only
int teamOffset = 0;
for(int i = 0; i < 2; ++i)
{
int playerCount = i == 0 ? mapGenOptions->getPlayerCount() : mapGenOptions->getCompOnlyPlayerCount();
int teamCount = i == 0 ? mapGenOptions->getTeamCount() : mapGenOptions->getCompOnlyTeamCount();
enum ETeams {CPHUMAN = 0, CPUONLY = 1, AFTER_LAST = 2};
std::array<std::list<int>, 2> teamNumbers;
int teamOffset = 0;
int playerCount = 0;
int teamCount = 0;
for (int i = CPHUMAN; i < AFTER_LAST; ++i)
{
if (i == CPHUMAN)
{
playerCount = mapGenOptions->getPlayerCount();
teamCount = mapGenOptions->getTeamCount();
}
else
{
playerCount = mapGenOptions->getCompOnlyPlayerCount();
teamCount = mapGenOptions->getCompOnlyTeamCount();
}
if(playerCount == 0)
{
continue;
}
int playersPerTeam = playerCount /
(teamCount == 0 ? playerCount : teamCount);
int playersPerTeam = playerCount / (teamCount == 0 ? playerCount : teamCount);
int teamCountNorm = teamCount;
if(teamCountNorm == 0)
{
@ -202,17 +215,23 @@ void CMapGenerator::addPlayerInfo()
}
// Team numbers are assigned randomly to every player
//TODO: allow customize teams in rmg template
for(const auto & pair : mapGenOptions->getPlayersSettings())
{
const auto & pSettings = pair.second;
PlayerInfo player;
player.canComputerPlay = true;
int j = pSettings.getPlayerType() == EPlayerType::COMP_ONLY ? 1 : 0;
if(j == 0)
int j = (pSettings.getPlayerType() == EPlayerType::COMP_ONLY) ? CPUONLY : CPHUMAN;
if (j == CPHUMAN)
{
player.canHumanPlay = true;
}
if (teamNumbers[j].empty())
{
logGlobal->errorStream() << boost::format("Not enough places in team for %s player") % ((j == CPUONLY) ? "CPU" : "CPU or human");
assert (teamNumbers[j].size());
}
auto itTeam = RandomGeneratorUtil::nextItem(teamNumbers[j], rand);
player.team = TeamID(*itTeam);
teamNumbers[j].erase(itTeam);

View File

@ -23,214 +23,216 @@
#include "../GameConstants.h"
#include "../StringConstants.h"
const std::map<std::string, CRmgTemplate *> & CRmgTemplateLoader::getTemplates() const
const std::map<std::string, CRmgTemplate *> & CRmgTemplateStorage::getTemplates() const
{
return templates;
}
void CJsonRmgTemplateLoader::loadTemplates()
void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
{
const JsonNode rootNode(ResourceID("config/rmg.json"));
for(const auto & templatePair : rootNode.Struct())
//unused
loadObject(scope, name, data);
}
void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const JsonNode & data)
{
auto tpl = new CRmgTemplate();
try
{
auto tpl = new CRmgTemplate();
try
tpl->setName(name); //TODO?
const auto & templateNode = data;
// Parse main template data
tpl->setMinSize(parseMapTemplateSize(templateNode["minSize"].String()));
tpl->setMaxSize(parseMapTemplateSize(templateNode["maxSize"].String()));
tpl->setPlayers(parsePlayers(templateNode["players"].String()));
tpl->setCpuPlayers(parsePlayers(templateNode["cpu"].String()));
// Parse zones
std::map<TRmgTemplateZoneId, CRmgTemplateZone *> zones;
for (const auto & zonePair : templateNode["zones"].Struct())
{
tpl->setName(templatePair.first);
const auto & templateNode = templatePair.second;
auto zone = new CRmgTemplateZone();
auto zoneId = boost::lexical_cast<TRmgTemplateZoneId>(zonePair.first);
zone->setId(zoneId);
// Parse main template data
tpl->setMinSize(parseMapTemplateSize(templateNode["minSize"].String()));
tpl->setMaxSize(parseMapTemplateSize(templateNode["maxSize"].String()));
tpl->setPlayers(parsePlayers(templateNode["players"].String()));
tpl->setCpuPlayers(parsePlayers(templateNode["cpu"].String()));
const auto & zoneNode = zonePair.second;
zone->setType(parseZoneType(zoneNode["type"].String()));
zone->setSize(zoneNode["size"].Float());
if (!zoneNode["owner"].isNull()) zone->setOwner(zoneNode["owner"].Float());
// Parse zones
std::map<TRmgTemplateZoneId, CRmgTemplateZone *> zones;
for (const auto & zonePair : templateNode["zones"].Struct())
zone->setPlayerTowns(parseTemplateZoneTowns(zoneNode["playerTowns"]));
zone->setNeutralTowns(parseTemplateZoneTowns(zoneNode["neutralTowns"]));
if (!zoneNode["matchTerrainToTown"].isNull()) //default : true
zone->setMatchTerrainToTown(zoneNode["matchTerrainToTown"].Bool());
zone->setTerrainTypes(parseTerrainTypes(zoneNode["terrainTypes"].Vector(), zone->getDefaultTerrainTypes()));
if (!zoneNode["townsAreSameType"].isNull()) //default : false
zone->setTownsAreSameType((zoneNode["townsAreSameType"].Bool()));
for (int i = 0; i < 2; ++i)
{
auto zone = new CRmgTemplateZone();
auto zoneId = boost::lexical_cast<TRmgTemplateZoneId>(zonePair.first);
zone->setId(zoneId);
const auto & zoneNode = zonePair.second;
zone->setType(parseZoneType(zoneNode["type"].String()));
zone->setSize(zoneNode["size"].Float());
if (!zoneNode["owner"].isNull()) zone->setOwner(zoneNode["owner"].Float());
zone->setPlayerTowns(parseTemplateZoneTowns(zoneNode["playerTowns"]));
zone->setNeutralTowns(parseTemplateZoneTowns(zoneNode["neutralTowns"]));
if (!zoneNode["matchTerrainToTown"].isNull()) //default : true
zone->setMatchTerrainToTown(zoneNode["matchTerrainToTown"].Bool());
zone->setTerrainTypes(parseTerrainTypes(zoneNode["terrainTypes"].Vector(), zone->getDefaultTerrainTypes()));
if (!zoneNode["townsAreSameType"].isNull()) //default : false
zone->setTownsAreSameType((zoneNode["townsAreSameType"].Bool()));
for (int i = 0; i < 2; ++i)
std::set<TFaction> allowedTownTypes;
if (i)
{
std::set<TFaction> allowedTownTypes;
if (i)
{
if (zoneNode["allowedTowns"].isNull())
allowedTownTypes = zone->getDefaultTownTypes();
}
else
{
if (zoneNode["allowedMonsters"].isNull())
allowedTownTypes = VLC->townh->getAllowedFactions(false);
}
if (allowedTownTypes.empty())
{
for (const JsonNode & allowedTown : zoneNode[i ? "allowedTowns" : "allowedMonsters"].Vector())
{
//complain if the town type is not present in our game
if (auto id = VLC->modh->identifiers.getIdentifier("faction", allowedTown, false))
allowedTownTypes.insert(id.get());
}
}
if (!zoneNode[i ? "bannedTowns" : "bannedMonsters"].isNull())
{
for (const JsonNode & bannedTown : zoneNode[i ? "bannedTowns" : "bannedMonsters"].Vector())
{
//erase unindentified towns silently
if (auto id = VLC->modh->identifiers.getIdentifier("faction", bannedTown, true))
vstd::erase_if_present(allowedTownTypes, id.get());
}
}
if (i)
zone->setTownTypes(allowedTownTypes);
else
zone->setMonsterTypes(allowedTownTypes);
if (zoneNode["allowedTowns"].isNull())
allowedTownTypes = zone->getDefaultTownTypes();
}
const std::string monsterStrength = zoneNode["monsters"].String();
if (monsterStrength == "weak")
zone->setMonsterStrength(EMonsterStrength::ZONE_WEAK);
else if (monsterStrength == "normal")
zone->setMonsterStrength(EMonsterStrength::ZONE_NORMAL);
else if (monsterStrength == "strong")
zone->setMonsterStrength(EMonsterStrength::ZONE_STRONG);
else
throw (rmgException("incorrect monster power"));
if (!zoneNode["mines"].isNull())
{
auto mines = zoneNode["mines"].Struct();
//FIXME: maybe there is a smarter way to parse it already?
zone->setMinesAmount(Res::WOOD, mines["wood"].Float());
zone->setMinesAmount(Res::ORE, mines["ore"].Float());
zone->setMinesAmount(Res::GEMS, mines["gems"].Float());
zone->setMinesAmount(Res::CRYSTAL, mines["crystal"].Float());
zone->setMinesAmount(Res::SULFUR, mines["sulfur"].Float());
zone->setMinesAmount(Res::MERCURY, mines["mercury"].Float());
zone->setMinesAmount(Res::GOLD, mines["gold"].Float());
//TODO: Mithril
if (zoneNode["allowedMonsters"].isNull())
allowedTownTypes = VLC->townh->getAllowedFactions(false);
}
//treasures
if (!zoneNode["treasure"].isNull())
if (allowedTownTypes.empty())
{
//TODO: parse vector of different treasure settings
if (zoneNode["treasure"].getType() == JsonNode::DATA_STRUCT)
for (const JsonNode & allowedTown : zoneNode[i ? "allowedTowns" : "allowedMonsters"].Vector())
{
auto treasureInfo = zoneNode["treasure"].Struct();
{
CTreasureInfo ti;
ti.min = treasureInfo["min"].Float();
ti.max = treasureInfo["max"].Float();
ti.density = treasureInfo["density"].Float(); //TODO: use me
zone->addTreasureInfo(ti);
}
}
else if (zoneNode["treasure"].getType() == JsonNode::DATA_VECTOR)
{
for (auto treasureInfo : zoneNode["treasure"].Vector())
{
CTreasureInfo ti;
ti.min = treasureInfo["min"].Float();
ti.max = treasureInfo["max"].Float();
ti.density = treasureInfo["density"].Float();
zone->addTreasureInfo(ti);
}
//complain if the town type is not present in our game
if (auto id = VLC->modh->identifiers.getIdentifier("faction", allowedTown, false))
allowedTownTypes.insert(id.get());
}
}
zones[zone->getId()] = zone;
if (!zoneNode[i ? "bannedTowns" : "bannedMonsters"].isNull())
{
for (const JsonNode & bannedTown : zoneNode[i ? "bannedTowns" : "bannedMonsters"].Vector())
{
//erase unindentified towns silently
if (auto id = VLC->modh->identifiers.getIdentifier("faction", bannedTown, true))
vstd::erase_if_present(allowedTownTypes, id.get());
}
}
if (i)
zone->setTownTypes(allowedTownTypes);
else
zone->setMonsterTypes(allowedTownTypes);
}
//copy settings from already parsed zones
for (const auto & zonePair : templateNode["zones"].Struct())
const std::string monsterStrength = zoneNode["monsters"].String();
if (monsterStrength == "weak")
zone->setMonsterStrength(EMonsterStrength::ZONE_WEAK);
else if (monsterStrength == "normal")
zone->setMonsterStrength(EMonsterStrength::ZONE_NORMAL);
else if (monsterStrength == "strong")
zone->setMonsterStrength(EMonsterStrength::ZONE_STRONG);
else
throw (rmgException("incorrect monster power"));
if (!zoneNode["mines"].isNull())
{
auto zoneId = boost::lexical_cast<TRmgTemplateZoneId>(zonePair.first);
auto zone = zones[zoneId];
auto mines = zoneNode["mines"].Struct();
//FIXME: maybe there is a smarter way to parse it already?
zone->setMinesAmount(Res::WOOD, mines["wood"].Float());
zone->setMinesAmount(Res::ORE, mines["ore"].Float());
zone->setMinesAmount(Res::GEMS, mines["gems"].Float());
zone->setMinesAmount(Res::CRYSTAL, mines["crystal"].Float());
zone->setMinesAmount(Res::SULFUR, mines["sulfur"].Float());
zone->setMinesAmount(Res::MERCURY, mines["mercury"].Float());
zone->setMinesAmount(Res::GOLD, mines["gold"].Float());
//TODO: Mithril
}
const auto & zoneNode = zonePair.second;
if (!zoneNode["terrainTypeLikeZone"].isNull())
//treasures
if (!zoneNode["treasure"].isNull())
{
//TODO: parse vector of different treasure settings
if (zoneNode["treasure"].getType() == JsonNode::DATA_STRUCT)
{
int id = zoneNode["terrainTypeLikeZone"].Float();
zone->setTerrainTypes(zones[id]->getTerrainTypes());
zone->setMatchTerrainToTown(zones[id]->getMatchTerrainToTown());
}
if (!zoneNode["townTypeLikeZone"].isNull())
zone->setTownTypes (zones[zoneNode["townTypeLikeZone"].Float()]->getTownTypes());
if (!zoneNode["treasureLikeZone"].isNull())
{
for (auto treasureInfo : zones[zoneNode["treasureLikeZone"].Float()]->getTreasureInfo())
auto treasureInfo = zoneNode["treasure"].Struct();
{
zone->addTreasureInfo(treasureInfo);
CTreasureInfo ti;
ti.min = treasureInfo["min"].Float();
ti.max = treasureInfo["max"].Float();
ti.density = treasureInfo["density"].Float(); //TODO: use me
zone->addTreasureInfo(ti);
}
}
if (!zoneNode["minesLikeZone"].isNull())
else if (zoneNode["treasure"].getType() == JsonNode::DATA_VECTOR)
{
for (auto mineInfo : zones[zoneNode["minesLikeZone"].Float()]->getMinesInfo())
for (auto treasureInfo : zoneNode["treasure"].Vector())
{
zone->setMinesAmount (mineInfo.first, mineInfo.second);
CTreasureInfo ti;
ti.min = treasureInfo["min"].Float();
ti.max = treasureInfo["max"].Float();
ti.density = treasureInfo["density"].Float();
zone->addTreasureInfo(ti);
}
}
}
tpl->setZones(zones);
// Parse connections
std::list<CRmgTemplateZoneConnection> connections;
for(const auto & connPair : templateNode["connections"].Vector())
{
CRmgTemplateZoneConnection conn;
conn.setZoneA(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["a"].String()))->second);
conn.setZoneB(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["b"].String()))->second);
conn.setGuardStrength(connPair["guard"].Float());
connections.push_back(conn);
}
tpl->setConnections(connections);
{
auto zones = tpl->getZones();
for (auto con : tpl->getConnections())
{
auto idA = con.getZoneA()->getId();
auto idB = con.getZoneB()->getId();
zones[idA]->addConnection(idB);
zones[idB]->addConnection(idA);
}
}
tpl->validate();
templates[tpl->getName()] = tpl;
zones[zone->getId()] = zone;
}
catch(const std::exception & e)
//copy settings from already parsed zones
for (const auto & zonePair : templateNode["zones"].Struct())
{
logGlobal->errorStream() << boost::format("Template %s has errors. Message: %s.") % tpl->getName() % std::string(e.what());
auto zoneId = boost::lexical_cast<TRmgTemplateZoneId>(zonePair.first);
auto zone = zones[zoneId];
const auto & zoneNode = zonePair.second;
if (!zoneNode["terrainTypeLikeZone"].isNull())
{
int id = zoneNode["terrainTypeLikeZone"].Float();
zone->setTerrainTypes(zones[id]->getTerrainTypes());
zone->setMatchTerrainToTown(zones[id]->getMatchTerrainToTown());
}
if (!zoneNode["townTypeLikeZone"].isNull())
zone->setTownTypes (zones[zoneNode["townTypeLikeZone"].Float()]->getTownTypes());
if (!zoneNode["treasureLikeZone"].isNull())
{
for (auto treasureInfo : zones[zoneNode["treasureLikeZone"].Float()]->getTreasureInfo())
{
zone->addTreasureInfo(treasureInfo);
}
}
if (!zoneNode["minesLikeZone"].isNull())
{
for (auto mineInfo : zones[zoneNode["minesLikeZone"].Float()]->getMinesInfo())
{
zone->setMinesAmount (mineInfo.first, mineInfo.second);
}
}
}
tpl->setZones(zones);
// Parse connections
std::list<CRmgTemplateZoneConnection> connections;
for(const auto & connPair : templateNode["connections"].Vector())
{
CRmgTemplateZoneConnection conn;
conn.setZoneA(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["a"].String()))->second);
conn.setZoneB(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["b"].String()))->second);
conn.setGuardStrength(connPair["guard"].Float());
connections.push_back(conn);
}
tpl->setConnections(connections);
{
auto zones = tpl->getZones();
for (auto con : tpl->getConnections())
{
auto idA = con.getZoneA()->getId();
auto idB = con.getZoneB()->getId();
zones[idA]->addConnection(idB);
zones[idB]->addConnection(idA);
}
}
tpl->validate();
templates[tpl->getName()] = tpl;
}
catch(const std::exception & e)
{
logGlobal->errorStream() << boost::format("Template %s has errors. Message: %s.") % tpl->getName() % std::string(e.what());
}
}
CRmgTemplate::CSize CJsonRmgTemplateLoader::parseMapTemplateSize(const std::string & text) const
CRmgTemplate::CSize CRmgTemplateStorage::parseMapTemplateSize(const std::string & text) const
{
CRmgTemplate::CSize size;
if(text.empty()) return size;
@ -265,7 +267,7 @@ CRmgTemplate::CSize CJsonRmgTemplateLoader::parseMapTemplateSize(const std::stri
return size;
}
ETemplateZoneType::ETemplateZoneType CJsonRmgTemplateLoader::parseZoneType(const std::string & type) const
ETemplateZoneType::ETemplateZoneType CRmgTemplateStorage::parseZoneType(const std::string & type) const
{
static const std::map<std::string, ETemplateZoneType::ETemplateZoneType> zoneTypeMapping =
{
@ -279,7 +281,7 @@ ETemplateZoneType::ETemplateZoneType CJsonRmgTemplateLoader::parseZoneType(const
return it->second;
}
CRmgTemplateZone::CTownInfo CJsonRmgTemplateLoader::parseTemplateZoneTowns(const JsonNode & node) const
CRmgTemplateZone::CTownInfo CRmgTemplateStorage::parseTemplateZoneTowns(const JsonNode & node) const
{
CRmgTemplateZone::CTownInfo towns;
towns.setTownCount(node["towns"].Float());
@ -289,7 +291,7 @@ CRmgTemplateZone::CTownInfo CJsonRmgTemplateLoader::parseTemplateZoneTowns(const
return towns;
}
std::set<TFaction> CJsonRmgTemplateLoader::parseTownTypes(const JsonVector & townTypesVector, const std::set<TFaction> & defaultTownTypes) const
std::set<TFaction> CRmgTemplateStorage::parseTownTypes(const JsonVector & townTypesVector, const std::set<TFaction> & defaultTownTypes) const
{
std::set<TFaction> townTypes;
for(const auto & townTypeNode : townTypesVector)
@ -311,7 +313,7 @@ std::set<TFaction> CJsonRmgTemplateLoader::parseTownTypes(const JsonVector & tow
return townTypes;
}
std::set<ETerrainType> CJsonRmgTemplateLoader::parseTerrainTypes(const JsonVector & terTypeStrings, const std::set<ETerrainType> & defaultTerrainTypes) const
std::set<ETerrainType> CRmgTemplateStorage::parseTerrainTypes(const JsonVector & terTypeStrings, const std::set<ETerrainType> & defaultTerrainTypes) const
{
std::set<ETerrainType> terTypes;
if (terTypeStrings.empty()) //nothing was specified
@ -334,7 +336,7 @@ std::set<ETerrainType> CJsonRmgTemplateLoader::parseTerrainTypes(const JsonVecto
return terTypes;
}
CRmgTemplate::CPlayerCountRange CJsonRmgTemplateLoader::parsePlayers(const std::string & players) const
CRmgTemplate::CPlayerCountRange CRmgTemplateStorage::parsePlayers(const std::string & players) const
{
CRmgTemplate::CPlayerCountRange playerRange;
if(players.empty())
@ -363,21 +365,24 @@ CRmgTemplate::CPlayerCountRange CJsonRmgTemplateLoader::parsePlayers(const std::
return playerRange;
}
const std::map<std::string, CRmgTemplate *> & CRmgTemplateStorage::getTemplates() const
{
return templates;
}
CRmgTemplateStorage::CRmgTemplateStorage()
{
auto jsonLoader = make_unique<CJsonRmgTemplateLoader>();
jsonLoader->loadTemplates();
const auto & tpls = jsonLoader->getTemplates();
templates.insert(tpls.begin(), tpls.end());
//TODO: load all
}
CRmgTemplateStorage::~CRmgTemplateStorage()
{
for (auto & pair : templates) delete pair.second;
}
std::vector<bool> CRmgTemplateStorage::getDefaultAllowed() const
{
//all templates are allowed
return std::vector<bool>();
}
std::vector<JsonNode> CRmgTemplateStorage::loadLegacyData(size_t dataSize)
{
return std::vector<JsonNode>();
//it would be cool to load old rmg.txt files
};

View File

@ -13,28 +13,27 @@
#include "CRmgTemplate.h"
#include "CRmgTemplateZone.h"
#include "../IHandlerBase.h"
class JsonNode;
typedef std::vector<JsonNode> JsonVector;
/// The CRmgTemplateLoader is a abstract base class for loading templates.
class DLL_LINKAGE CRmgTemplateLoader
/// The CJsonRmgTemplateLoader loads templates from a JSON file.
class DLL_LINKAGE CRmgTemplateStorage : public IHandlerBase
{
public:
virtual ~CRmgTemplateLoader() { };
virtual void loadTemplates() = 0;
CRmgTemplateStorage();
~CRmgTemplateStorage();
const std::map<std::string, CRmgTemplate *> & getTemplates() const;
protected:
std::map<std::string, CRmgTemplate *> templates;
};
std::vector<bool> getDefaultAllowed() const;
std::vector<JsonNode> loadLegacyData(size_t dataSize);
/// The CJsonRmgTemplateLoader loads templates from a JSON file.
class DLL_LINKAGE CJsonRmgTemplateLoader : public CRmgTemplateLoader
{
public:
void loadTemplates() override;
/// loads single object into game. Scope is namespace of this object, same as name of source mod
virtual void loadObject(std::string scope, std::string name, const JsonNode & data);
virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index);
private:
CRmgTemplate::CSize parseMapTemplateSize(const std::string & text) const;
@ -43,17 +42,8 @@ private:
std::set<TFaction> parseTownTypes(const JsonVector & townTypesVector, const std::set<TFaction> & defaultTownTypes) const;
std::set<ETerrainType> parseTerrainTypes(const JsonVector & terTypeStrings, const std::set<ETerrainType> & defaultTerrainTypes) const;
CRmgTemplate::CPlayerCountRange parsePlayers(const std::string & players) const;
protected:
std::map<std::string, CRmgTemplate *> templates;
};
/// The class CRmgTemplateStorage stores random map templates.
class DLL_LINKAGE CRmgTemplateStorage
{
public:
CRmgTemplateStorage();
~CRmgTemplateStorage();
const std::map<std::string, CRmgTemplate *> & getTemplates() const;
private:
std::map<std::string, CRmgTemplate *> templates; /// Key: Template name
};

View File

@ -1191,70 +1191,66 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
logGlobal->infoStream() << "Preparing playing zone";
int player_id = *owner - 1;
auto & playerInfo = gen->map->players[player_id];
PlayerColor player(player_id);
if (playerInfo.canAnyonePlay())
{
PlayerColor player(player_id);
player = PlayerColor(player_id);
townType = gen->mapGenOptions->getPlayersSettings().find(player)->second.getStartingTown();
if (townType == CMapGenOptions::CPlayerSettings::RANDOM_TOWN)
{
if (townTypes.size())
townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
else
townType = *RandomGeneratorUtil::nextItem(getDefaultTownTypes(), gen->rand); //it is possible to have zone with no towns allowed
}
auto town = new CGTownInstance();
town->ID = Obj::TOWN;
randomizeTownType(gen);
}
else //no player - randomize town
{
player = PlayerColor::NEUTRAL;
randomizeTownType(gen);
}
town->subID = townType;
town->tempOwner = player;
town->builtBuildings.insert(BuildingID::FORT);
town->builtBuildings.insert(BuildingID::DEFAULT);
auto town = new CGTownInstance();
town->ID = Obj::TOWN;
for (auto spell : VLC->spellh->objects) //add all regular spells to town
{
if (!spell->isSpecialSpell() && !spell->isCreatureAbility())
town->possibleSpells.push_back(spell->id);
}
//towns are big objects and should be centered around visitable position
placeAndGuardObject(gen, town, getPos() + town->getVisitableOffset(), 0); //generate no guards, but free path to entrance
cutPathAroundTown(town);
town->subID = townType;
town->tempOwner = player;
town->builtBuildings.insert(BuildingID::FORT);
town->builtBuildings.insert(BuildingID::DEFAULT);
totalTowns++;
//register MAIN town of zone only
gen->registerZone (town->subID);
for (auto spell : VLC->spellh->objects) //add all regular spells to town
{
if (!spell->isSpecialSpell() && !spell->isCreatureAbility())
town->possibleSpells.push_back(spell->id);
}
//towns are big objects and should be centered around visitable position
placeAndGuardObject(gen, town, getPos() + town->getVisitableOffset(), 0); //generate no guards, but free path to entrance
cutPathAroundTown(town);
totalTowns++;
//register MAIN town of zone only
gen->registerZone (town->subID);
if (playerInfo.canAnyonePlay()) //configure info for owning player
{
logGlobal->traceStream() << "Fill player info " << player_id;
// Update player info
playerInfo.allowedFactions.clear();
playerInfo.allowedFactions.insert (townType);
playerInfo.allowedFactions.insert(townType);
playerInfo.hasMainTown = true;
playerInfo.posOfMainTown = town->pos - town->getVisitableOffset();
playerInfo.generateHeroAtMainTown = true;
//now create actual towns
addNewTowns (playerTowns.getCastleCount() - 1, true, player);
addNewTowns (playerTowns.getTownCount(), false, player);
//requiredObjects.push_back(town);
addNewTowns(playerTowns.getCastleCount() - 1, true, player);
addNewTowns(playerTowns.getTownCount(), false, player);
}
else
{
type = ETemplateZoneType::TREASURE;
if (townTypes.size())
townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
else
townType = *RandomGeneratorUtil::nextItem(getDefaultTownTypes(), gen->rand); //it is possible to have zone with no towns allowed
{
addNewTowns(playerTowns.getCastleCount() - 1, true, PlayerColor::NEUTRAL);
addNewTowns(playerTowns.getTownCount(), false, PlayerColor::NEUTRAL);
}
}
else //no player
else //randomize town types for any other zones as well
{
if (townTypes.size())
townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
else
townType = *RandomGeneratorUtil::nextItem(getDefaultTownTypes(), gen->rand); //it is possible to have zone with no towns allowed
randomizeTownType(gen);
}
addNewTowns (neutralTowns.getCastleCount(), true, PlayerColor::NEUTRAL);
@ -1273,11 +1269,20 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
else if (monsterTypes.size())
townType = *RandomGeneratorUtil::nextItem(monsterTypes, gen->rand); //this happens in Clash of Dragons in treasure zones, where all towns are banned
else //just in any case
randomizeTownType(gen);
}
}
}
void CRmgTemplateZone::randomizeTownType (CMapGenerator* gen)
{
if (townTypes.size())
townType = *RandomGeneratorUtil::nextItem(townTypes, gen->rand);
else
townType = *RandomGeneratorUtil::nextItem(getDefaultTownTypes(), gen->rand); //it is possible to have zone with no towns allowed, we still need some
}
void CRmgTemplateZone::initTerrainType (CMapGenerator* gen)
{

View File

@ -162,6 +162,7 @@ public:
bool placeMines (CMapGenerator* gen);
void initTownType (CMapGenerator* gen);
void paintZoneTerrain (CMapGenerator* gen, ETerrainType terrainType);
void randomizeTownType(CMapGenerator* gen); //helper function
void initTerrainType (CMapGenerator* gen);
void createBorder(CMapGenerator* gen);
void fractalize(CMapGenerator* gen);