diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Analogy/Content/config/defaultTemplates/analogy.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Analogy/Content/config/defaultTemplates/analogy.json new file mode 100644 index 000000000..74ee60e96 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Analogy/Content/config/defaultTemplates/analogy.json @@ -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 } + ] + } +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Analogy/mod.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Analogy/mod.json new file mode 100644 index 000000000..98d66a2ad --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Analogy/mod.json @@ -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" + ], +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Clash of Dragons/Content/config/defaultTemplates/clashOfDragons.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Clash of Dragons/Content/config/defaultTemplates/clashOfDragons.json new file mode 100644 index 000000000..521d00ea2 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Clash of Dragons/Content/config/defaultTemplates/clashOfDragons.json @@ -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 } + ] + } +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Clash of Dragons/mod.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Clash of Dragons/mod.json new file mode 100644 index 000000000..70f0edc44 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Clash of Dragons/mod.json @@ -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" + ], +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Coldshadows Fantasy/Content/config/defaultTemplates/coldshadowsFantasy.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Coldshadows Fantasy/Content/config/defaultTemplates/coldshadowsFantasy.json new file mode 100644 index 000000000..1d47aef49 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Coldshadows Fantasy/Content/config/defaultTemplates/coldshadowsFantasy.json @@ -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 } + ] + } +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Coldshadows Fantasy/mod.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Coldshadows Fantasy/mod.json new file mode 100644 index 000000000..d185c8521 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Coldshadows Fantasy/mod.json @@ -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" + ], +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Golden Ring/Content/config/defaultTemplates/goldenRing.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Golden Ring/Content/config/defaultTemplates/goldenRing.json new file mode 100644 index 000000000..d34d4773d --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Golden Ring/Content/config/defaultTemplates/goldenRing.json @@ -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 } + ] + } +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Golden Ring/mod.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Golden Ring/mod.json new file mode 100644 index 000000000..914b4dfa2 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Golden Ring/mod.json @@ -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" + ], +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Jebus Cross/Content/config/defaultTemplates/jebusCross.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Jebus Cross/Content/config/defaultTemplates/jebusCross.json new file mode 100644 index 000000000..2280aac83 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Jebus Cross/Content/config/defaultTemplates/jebusCross.json @@ -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 } + ] + } +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Jebus Cross/mod.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Jebus Cross/mod.json new file mode 100644 index 000000000..0124ca317 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Jebus Cross/mod.json @@ -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" + ], +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Upgrade/Content/config/defaultTemplates/upgrade.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Upgrade/Content/config/defaultTemplates/upgrade.json new file mode 100644 index 000000000..531a52aea --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Upgrade/Content/config/defaultTemplates/upgrade.json @@ -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 } + ] + } +} diff --git a/Mods/vcmi/Mods/defaultTemplates/Mods/Upgrade/mod.json b/Mods/vcmi/Mods/defaultTemplates/Mods/Upgrade/mod.json new file mode 100644 index 000000000..75dba71b7 --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/Mods/Upgrade/mod.json @@ -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" + ], +} diff --git a/Mods/vcmi/Mods/defaultTemplates/mod.json b/Mods/vcmi/Mods/defaultTemplates/mod.json new file mode 100644 index 000000000..31e8035db --- /dev/null +++ b/Mods/vcmi/Mods/defaultTemplates/mod.json @@ -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" +} diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index 60d723954..f1011e755 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -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()); } diff --git a/config/rmg.json b/config/rmg.json deleted file mode 100644 index b3f3f95fb..000000000 --- a/config/rmg.json +++ /dev/null @@ -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 } - ] - } -} diff --git a/config/schemas/template.json b/config/schemas/template.json new file mode 100644 index 000000000..fa74b8e51 --- /dev/null +++ b/config/schemas/template.json @@ -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 + } +} diff --git a/lib/CModHandler.cpp b/lib/CModHandler.cpp index fa54ce9a4..31a953292 100644 --- a/lib/CModHandler.cpp +++ b/lib/CModHandler.cpp @@ -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? } diff --git a/lib/GameConstants.h b/lib/GameConstants.h index eb8e33973..8cb5dcd57 100644 --- a/lib/GameConstants.h +++ b/lib/GameConstants.h @@ -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; diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index 35a699f8b..8aaae68c9 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -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 diff --git a/lib/rmg/CMapGenOptions.cpp b/lib/rmg/CMapGenOptions.cpp index dbdf8afb5..64e7c6df4 100644 --- a/lib/rmg/CMapGenOptions.cpp +++ b/lib/rmg/CMapGenOptions.cpp @@ -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(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(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 & 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(boost::count_if(players, [](const std::pair & 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); } } } diff --git a/lib/rmg/CMapGenOptions.h b/lib/rmg/CMapGenOptions.h index dc0c095de..7975c54f9 100644 --- a/lib/rmg/CMapGenOptions.h +++ b/lib/rmg/CMapGenOptions.h @@ -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 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 } }; diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index 285e913d1..aff022425 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -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(mapGenOptions->getPlayerCount()) % static_cast(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, 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, 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); diff --git a/lib/rmg/CRmgTemplateStorage.cpp b/lib/rmg/CRmgTemplateStorage.cpp index 95f457998..ee1e0692e 100644 --- a/lib/rmg/CRmgTemplateStorage.cpp +++ b/lib/rmg/CRmgTemplateStorage.cpp @@ -23,214 +23,216 @@ #include "../GameConstants.h" #include "../StringConstants.h" -const std::map & CRmgTemplateLoader::getTemplates() const +const std::map & 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 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(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 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(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 allowedTownTypes; + if (i) { - std::set 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(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 connections; - for(const auto & connPair : templateNode["connections"].Vector()) - { - CRmgTemplateZoneConnection conn; - conn.setZoneA(zones.find(boost::lexical_cast(connPair["a"].String()))->second); - conn.setZoneB(zones.find(boost::lexical_cast(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(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 connections; + for(const auto & connPair : templateNode["connections"].Vector()) + { + CRmgTemplateZoneConnection conn; + conn.setZoneA(zones.find(boost::lexical_cast(connPair["a"].String()))->second); + conn.setZoneB(zones.find(boost::lexical_cast(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 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 CJsonRmgTemplateLoader::parseTownTypes(const JsonVector & townTypesVector, const std::set & defaultTownTypes) const +std::set CRmgTemplateStorage::parseTownTypes(const JsonVector & townTypesVector, const std::set & defaultTownTypes) const { std::set townTypes; for(const auto & townTypeNode : townTypesVector) @@ -311,7 +313,7 @@ std::set CJsonRmgTemplateLoader::parseTownTypes(const JsonVector & tow return townTypes; } -std::set CJsonRmgTemplateLoader::parseTerrainTypes(const JsonVector & terTypeStrings, const std::set & defaultTerrainTypes) const +std::set CRmgTemplateStorage::parseTerrainTypes(const JsonVector & terTypeStrings, const std::set & defaultTerrainTypes) const { std::set terTypes; if (terTypeStrings.empty()) //nothing was specified @@ -334,7 +336,7 @@ std::set 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 & CRmgTemplateStorage::getTemplates() const -{ - return templates; -} - CRmgTemplateStorage::CRmgTemplateStorage() { - auto jsonLoader = make_unique(); - 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 CRmgTemplateStorage::getDefaultAllowed() const +{ + //all templates are allowed + return std::vector(); +} + +std::vector CRmgTemplateStorage::loadLegacyData(size_t dataSize) +{ + return std::vector(); + //it would be cool to load old rmg.txt files +}; diff --git a/lib/rmg/CRmgTemplateStorage.h b/lib/rmg/CRmgTemplateStorage.h index 08cc64a11..c2b3b138d 100644 --- a/lib/rmg/CRmgTemplateStorage.h +++ b/lib/rmg/CRmgTemplateStorage.h @@ -13,28 +13,27 @@ #include "CRmgTemplate.h" #include "CRmgTemplateZone.h" +#include "../IHandlerBase.h" class JsonNode; typedef std::vector 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 & getTemplates() const; -protected: - std::map templates; -}; + std::vector getDefaultAllowed() const; + std::vector 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 parseTownTypes(const JsonVector & townTypesVector, const std::set & defaultTownTypes) const; std::set parseTerrainTypes(const JsonVector & terTypeStrings, const std::set & defaultTerrainTypes) const; CRmgTemplate::CPlayerCountRange parsePlayers(const std::string & players) const; + +protected: + std::map templates; }; -/// The class CRmgTemplateStorage stores random map templates. -class DLL_LINKAGE CRmgTemplateStorage -{ -public: - CRmgTemplateStorage(); - ~CRmgTemplateStorage(); - - const std::map & getTemplates() const; - -private: - std::map templates; /// Key: Template name -}; diff --git a/lib/rmg/CRmgTemplateZone.cpp b/lib/rmg/CRmgTemplateZone.cpp index 5cc6b7ad7..2fedf66b4 100644 --- a/lib/rmg/CRmgTemplateZone.cpp +++ b/lib/rmg/CRmgTemplateZone.cpp @@ -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) { diff --git a/lib/rmg/CRmgTemplateZone.h b/lib/rmg/CRmgTemplateZone.h index 5f37586fc..7277f4e96 100644 --- a/lib/rmg/CRmgTemplateZone.h +++ b/lib/rmg/CRmgTemplateZone.h @@ -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);