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

Merge pull request #30 from vcmi/RMG

Since there are no objections, I finally merge this branch.
This commit is contained in:
DjWarmonger 2014-07-23 08:06:51 +01:00
commit a842068d54
30 changed files with 1935 additions and 3410 deletions

View File

@ -1,11 +0,0 @@
{
"textData" :
{
"heroClass" : 18,
"artifact" : 171,
"creature" : 197,
"faction" : 9,
"hero" : 156,
"mapVersion" : 51 // WoG
}
}

View File

@ -1,309 +0,0 @@
{
"art144": // placeholder for selection image
{
"index" : 144,
"type" : ["HERO"]
},
"art145": // placeholder for lock image
{
"index" : 145,
"type" : ["HERO"]
},
"axeOfSmashing": //TODO: move growing bonuses to this config, someday
{
"bonuses" : [
{
"subtype" : "primSkill.attack",
"type" : "PRIMARY_SKILL",
"val" : 6,
"valueType" : "BASE_NUMBER"
}
],
"index" : 146,
"type" : ["COMMANDER"],
"growing":
{
"bonusesPerLevel":
[
{
"level": 6,
"bonus":
{
"type" : "PRIMARY_SKILL",
"subtype" : "primSkill.attack",
"val" : 1
}
}
]
}
},
"mithrilMail":
{
"bonuses" : [
{
"type" : "STACK_HEALTH",
"val" : 12,
"valueType" : "PERCENT_TO_ALL"
}
],
"index" : 147,
"type" : ["COMMANDER"],
"growing":
{
"bonusesPerLevel":
[
{
"level": 1,
"bonus":
{
"type" : "STACK_HEALTH",
"val" : 1
}
}
]
}
},
"swordOfSharpness":
{
"bonuses" : [
{
"subtype" : 0,
"type" : "CREATURE_DAMAGE",
"val" : 12,
"valueType" : "PERCENT_TO_ALL"
}
],
"index" : 148,
"type" : ["COMMANDER"],
"growing":
{
"bonusesPerLevel":
[
{
"level": 1,
"bonus":
{
"type" : "CREATURE_DAMAGE",
"val" : 1
}
}
]
}
},
"helmOfImmortality": //TODO: implement
{
"index" : 149,
"type" : ["COMMANDER"]
},
"pendantOfSorcery":
{
"bonuses" : [
{
"type" : "CASTS",
"val" : 1,
"valueType" : "BASE_NUMBER"
}
],
"index" : 150,
"type" : ["COMMANDER"],
"growing":
{
"bonusesPerLevel":
[
{
"level": 10,
"bonus":
{
"type" : "CREATURE_ENCHANT_POWER",
"val" : 1
}
}
]
}
},
"bootsOfHaste":
{
"bonuses" : [
{
"type" : "STACKS_SPEED",
"val" : 1,
"valueType" : "BASE_NUMBER"
}
],
"index" : 151,
"type" : ["COMMANDER"],
"growing":
{
"bonusesPerLevel":
[
{
"level": 10,
"bonus":
{
"type" : "STACKS_SPEED",
"val" : 1
}
}
]
}
},
"bowOfSeeking":
{
"index" : 152,
"type" : ["COMMANDER"],
"growing":
{
"thresholdBonuses":
[
{
"level": 5,
"bonus":
{
"type" : "SHOOTER"
}
},
{
"level": 25,
"bonus":
{
"type" : "NO_WALL_PENALTY"
}
},
{
"level": 50,
"bonus":
{
"type" : "NO_DISTANCE_PENALTY"
}
}
]
}
},
"dragonEyeRing": //TODO: implement
{
"index" : 153,
"type" : ["COMMANDER"],
},
"hardenedShield":
{
"bonuses" : [
{
"subtype" : "primSkill.attack",
"type" : "PRIMARY_SKILL",
"val" : 6,
"valueType" : "BASE_NUMBER"
}
],
"index" : 154,
"type" : ["COMMANDER"],
"growing":
{
"bonusesPerLevel":
[
{
"level": 6,
"bonus":
{
"type" : "PRIMARY_SKILL",
"subtype" : "primSkill.defence",
"val" : 1
}
}
]
}
},
"slavasRingOfPower": //TODO: implement if possible
{
"index" : 155,
"type" : ["COMMANDER"]
},
"warlordsBanner":
{
"bonuses" : [
{
"type" : "STACK_HEALTH",
"val" : 2,
"valueType" : "BASE_NUMBER"
}
],
"index" : 156,
"type" : ["CREATURE"]
},
"crimsonShieldOfRetribution": //TODO: implement
{
"index" : 157,
"type" : ["HERO"]
},
"barbarianLordsAxeOfFerocity": //TODO: implement
{
"index" : 158,
"type" : ["HERO"],
"components":
[
"ogresClubOfHavoc",
"targOfTheRampagingOgre",
"crownOfTheSupremeMagi",
"tunicOfTheCyclopsKing"
]
},
"dragonheart":
{
"index" : 159,
"type" : ["HERO"]
},
"gateKey":
{
"index" : 160,
"type" : ["HERO"]
},
"art161":
{
"index" : 161,
"type" : ["HERO"]
},
"art162":
{
"index" : 162,
"type" : ["HERO"]
},
"art163":
{
"index" : 163,
"type" : ["HERO"]
},
"art164":
{
"index" : 164,
"type" : ["HERO"]
},
"art165":
{
"index" : 165,
"type" : ["HERO"]
},
"art166":
{
"index" : 166,
"type" : ["HERO"]
},
"art167":
{
"index" : 167,
"type" : ["HERO"]
},
"art168":
{
"index" : 168,
"type" : ["HERO"]
},
"art169":
{
"index" : 169,
"type" : ["HERO"]
},
"art170":
{
"index" : 170,
"type" : ["HERO"]
}
}

View File

@ -1,817 +0,0 @@
{
"core:creatureBank" : {
"types" : {
"huntingLodge" : {
"name" : "Hunting Lodge",
"index" : 11,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 3, "type" : "dendroidGuard" },
{ "amount": 4, "type" : "woodElf" },
{ "amount": 3, "type" : "dendroidGuard" },
{ "amount": 4, "type" : "woodElf" }
],
"combat_value": 100,
"reward" : {
"resources":
{
"wood" : 15,
"gold" : 500
}
}
},
{
"chance": 30,
"guards": [
{ "amount": 4, "type" : "dendroidGuard" },
{ "amount": 6, "type" : "woodElf" },
{ "amount": 4, "type" : "dendroidGuard" },
{ "amount": 6, "type" : "woodElf" }
],
"combat_value": 150,
"reward" : {
"resources":
{
"wood" : 20,
"gold" : 500
},
"value": 3000
}
},
{
"chance": 30,
"guards": [
{ "amount": 5, "type" : "dendroidGuard" },
{ "amount": 8, "type" : "woodElf" },
{ "amount": 5, "type" : "dendroidGuard" },
{ "amount": 8, "type" : "woodElf" }
],
"combat_value": 200,
"reward" : {
"resources":
{
"wood" : 25,
"gold" : 500
},
"value": 4000
}
},
{
"chance": 10,
"guards": [
{ "amount": 6, "type" : "dendroidGuard" },
{ "amount": 10, "type" : "woodElf" },
{ "amount": 6, "type" : "dendroidGuard" },
{ "amount": 10, "type" : "woodElf" }
],
"combat_value": 300,
"reward" : {
"resources":
{
"wood" : 40,
"gold" : 1000
},
"value": 6000
}
}
]
},
"snowGrotto" :
{
"name" : "Snow-covered Grotto",
"index" : 12,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 5, "type" : "ironGolem" },
{ "amount": 20, "type" : "masterGremlin" },
{ "amount": 5, "type" : "ironGolem" },
{ "amount": 20, "type" : "masterGremlin" }
],
"combat_value": 100,
"reward" : {
"resources":
{
"ore" : 15,
"gold" : 500
}
}
},
{
"chance": 30,
"guards": [
{ "amount": 6, "type" : "ironGolem" },
{ "amount": 30, "type" : "masterGremlin" },
{ "amount": 6, "type" : "ironGolem" },
{ "amount": 30, "type" : "masterGremlin" }
],
"combat_value": 150,
"reward" : {
"resources":
{
"ore" : 20,
"gold" : 500
},
"value": 3000
}
},
{
"chance": 30,
"guards": [
{ "amount": 7, "type" : "ironGolem" },
{ "amount": 40, "type" : "masterGremlin" },
{ "amount": 7, "type" : "ironGolem" },
{ "amount": 40, "type" : "masterGremlin" }
],
"combat_value": 200,
"reward" : {
"resources":
{
"ore" : 30,
"gold" : 500
},
"value": 4000
}
},
{
"chance": 10,
"guards": [
{ "amount": 8, "type" : "ironGolem" },
{ "amount": 50, "type" : "masterGremlin" },
{ "amount": 8, "type" : "ironGolem" },
{ "amount": 50, "type" : "masterGremlin" }
],
"combat_value": 300,
"reward" : {
"resources":
{
"ore" : 40,
"gold" : 1000
},
"value": 6000
}
}
]
},
"martialSpiritPalace" :
{
"name" : "Palace of Martial Spirit",
"index" : 13,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 10, "type" : "godWar" },
{ "amount": 10, "type" : "godWar" },
{ "amount": 10, "type" : "godWar" },
{ "amount": 10, "type" : "godWar" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godWar" }
],
"value": 38000
}
},
{
"chance": 30,
"guards": [
{ "amount": 15, "type" : "godWar" },
{ "amount": 15, "type" : "godWar" },
{ "amount": 15, "type" : "godWar" },
{ "amount": 15, "type" : "godWar" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godWar" }
],
"value": 57000
}
},
{
"chance": 30,
"guards": [
{ "amount": 20, "type" : "godWar" },
{ "amount": 20, "type" : "godWar" },
{ "amount": 20, "type" : "godWar" },
{ "amount": 20, "type" : "godWar" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godWar" }
],
"value": 75000
}
},
{
"chance": 10,
"guards": [
{ "amount": 30, "type" : "godWar" },
{ "amount": 30, "type" : "godWar" },
{ "amount": 30, "type" : "godWar" },
{ "amount": 30, "type" : "godWar" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godWar" }
],
"value": 90000
}
}
]
},
"pacificationCitadel" :
{
"name" : "Citadel of Pacification",
"index" : 14,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 10, "type" : "godPeace" },
{ "amount": 10, "type" : "godPeace" },
{ "amount": 10, "type" : "godPeace" },
{ "amount": 10, "type" : "godPeace" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godPeace" }
],
"value": 38000
}
},
{
"chance": 30,
"guards": [
{ "amount": 15, "type" : "godPeace" },
{ "amount": 15, "type" : "godPeace" },
{ "amount": 15, "type" : "godPeace" },
{ "amount": 15, "type" : "godPeace" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godPeace" }
],
"value": 57000
}
},
{
"chance": 30,
"guards": [
{ "amount": 20, "type" : "godPeace" },
{ "amount": 20, "type" : "godPeace" },
{ "amount": 20, "type" : "godPeace" },
{ "amount": 20, "type" : "godPeace" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godPeace" }
],
"value": 75000
}
},
{
"chance": 10,
"guards": [
{ "amount": 30, "type" : "godPeace" },
{ "amount": 30, "type" : "godPeace" },
{ "amount": 30, "type" : "godPeace" },
{ "amount": 30, "type" : "godPeace" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godPeace" }
],
"value": 90000
}
}
]
},
"magiciansMonastery" :
{
"name" : "Monastery of Magicians",
"index" : 15,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 10, "type" : "godMana" },
{ "amount": 10, "type" : "godMana" },
{ "amount": 10, "type" : "godMana" },
{ "amount": 10, "type" : "godMana" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godMana" }
],
"value": 38000
}
},
{
"chance": 30,
"guards": [
{ "amount": 15, "type" : "godMana" },
{ "amount": 15, "type" : "godMana" },
{ "amount": 15, "type" : "godMana" },
{ "amount": 15, "type" : "godMana" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godMana" }
],
"value": 57000
}
},
{
"chance": 30,
"guards": [
{ "amount": 20, "type" : "godMana" },
{ "amount": 20, "type" : "godMana" },
{ "amount": 20, "type" : "godMana" },
{ "amount": 20, "type" : "godMana" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godMana" }
],
"value": 75000
}
},
{
"chance": 10,
"guards": [
{ "amount": 30, "type" : "godMana" },
{ "amount": 30, "type" : "godMana" },
{ "amount": 30, "type" : "godMana" },
{ "amount": 30, "type" : "godMana" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godMana" }
],
"value": 90000
}
}
]
},
"legendsLibrary" :
{
"name" : "Library of Legends",
"index" : 16,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 10, "type" : "godLore" },
{ "amount": 10, "type" : "godLore" },
{ "amount": 10, "type" : "godLore" },
{ "amount": 10, "type" : "godLore" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godLore" }
],
"value": 38000
}
},
{
"chance": 30,
"guards": [
{ "amount": 15, "type" : "godLore" },
{ "amount": 15, "type" : "godLore" },
{ "amount": 15, "type" : "godLore" },
{ "amount": 15, "type" : "godLore" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godLore" }
],
"value": 57000
}
},
{
"chance": 30,
"guards": [
{ "amount": 20, "type" : "godLore" },
{ "amount": 20, "type" : "godLore" },
{ "amount": 20, "type" : "godLore" },
{ "amount": 20, "type" : "godLore" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godLore" }
],
"value": 75000
}
},
{
"chance": 10,
"guards": [
{ "amount": 30, "type" : "godLore" },
{ "amount": 30, "type" : "godLore" },
{ "amount": 30, "type" : "godLore" },
{ "amount": 30, "type" : "godLore" }
],
"combat_value": 2000,
"reward" : {
"creatures": [
{ "amount": 1, "type" : "godLore" }
],
"value": 90000
}
}
]
},
"transylvanianTavern" :
{
"name" : "Transylvanian Tavern",
"index" : 17,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 2, "type" : "vampire" },
{ "amount": 2, "type" : "vampire" },
{ "amount": 2, "type" : "vampire" },
{ "amount": 2, "type" : "vampire" },
{ "amount": 2, "type" : "vampire" }
],
"combat_value": 100,
"reward" : {
"resources":
{
"gold" : 1500
},
"creatures": [
{ "amount": 3, "type" : "vampireLord" }
]
}
},
{
"chance": 30,
"guards": [
{ "amount": 3, "type" : "vampire" },
{ "amount": 3, "type" : "vampire" },
{ "amount": 3, "type" : "vampire" },
{ "amount": 3, "type" : "vampire" },
{ "amount": 3, "type" : "vampire" }
],
"combat_value": 150,
"reward" : {
"resources":
{
"gold" : 2500
},
"creatures": [
{ "amount": 5, "type" : "vampireLord" }
],
"value": 3000
}
},
{
"chance": 30,
"guards": [
{ "amount": 4, "type" : "vampire" },
{ "amount": 4, "type" : "vampire" },
{ "amount": 4, "type" : "vampire" },
{ "amount": 4, "type" : "vampire" },
{ "amount": 4, "type" : "vampire" }
],
"combat_value": 200,
"reward" : {
"resources":
{
"gold" : 3500
},
"creatures": [
{ "amount": 7, "type" : "vampireLord" }
],
"value": 4000
}
},
{
"chance": 10,
"guards": [
{ "amount": 6, "type" : "vampire" },
{ "amount": 6, "type" : "vampire" },
{ "amount": 6, "type" : "vampire" },
{ "amount": 6, "type" : "vampire" },
{ "amount": 6, "type" : "vampire" }
],
"combat_value": 250,
"reward" : {
"resources":
{
"gold" : 5000
},
"creatures": [
{ "amount": 9, "type" : "vampireLord" }
],
"value": 5000
}
}
]
},
"homeofthebat" :
{
"name" : "Home of the Bat",
"index" : 18,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 2, "type" : "vampire" },
{ "amount": 2, "type" : "vampire" },
{ "amount": 2, "type" : "vampire", "upgrade_chance": 50 },
{ "amount": 2, "type" : "vampire" },
{ "amount": 2, "type" : "vampire" }
],
"combat_value": 100,
"reward" : {
"resources":
{
"mercury" : 2,
"sulfur" : 2,
"crystal" : 2,
"gems" : 2
},
"creatures": [
{ "amount": 3, "type" : "vampireLord" }
]
}
},
{
"chance": 30,
"guards": [
{ "amount": 3, "type" : "vampire" },
{ "amount": 3, "type" : "vampire" },
{ "amount": 3, "type" : "vampire", "upgrade_chance": 70 },
{ "amount": 3, "type" : "vampire" },
{ "amount": 3, "type" : "vampire" }
],
"combat_value": 150,
"reward" : {
"resources":
{
"mercury" : 3,
"sulfur" : 3,
"crystal" : 3,
"gems" : 3
},
"creatures": [
{ "amount": 5, "type" : "vampireLord" }
],
"value": 3000
}
},
{
"chance": 30,
"guards": [
{ "amount": 4, "type" : "vampire" },
{ "amount": 4, "type" : "vampire" },
{ "amount": 4, "type" : "vampire", "upgrade_chance": 80 },
{ "amount": 4, "type" : "vampire" },
{ "amount": 4, "type" : "vampire" }
],
"combat_value": 200,
"reward" : {
"resources":
{
"mercury" : 4,
"sulfur" : 4,
"crystal" : 4,
"gems" : 4
},
"creatures": [
{ "amount": 7, "type" : "vampireLord" }
],
"value": 4000
}
},
{
"chance": 10,
"guards": [
{ "amount": 6, "type" : "vampire" },
{ "amount": 6, "type" : "vampire" },
{ "amount": 6, "type" : "vampire", "upgrade_chance": 50 },
{ "amount": 6, "type" : "vampire" },
{ "amount": 6, "type" : "vampire" }
],
"combat_value": 250,
"reward" : {
"resources":
{
"mercury" : 5,
"sulfur" : 5,
"crystal" : 5,
"gems" : 5
},
"creatures": [
{ "amount": 9, "type" : "vampireLord" }
],
"value": 5000
}
}
]
},
"lostBottle" :
{
"name" : "Lost Bottle",
"index" : 19,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 2, "type" : "genie" },
{ "amount": 2, "type" : "genie" },
{ "amount": 2, "type" : "genie", "upgrade_chance": 50 },
{ "amount": 2, "type" : "genie" },
{ "amount": 2, "type" : "genie" }
],
"combat_value": 100,
"reward" : {
"resources":
{
"mercury" : 2,
"sulfur" : 2,
"crystal" : 2,
"gems" : 2
},
"creatures": [
{ "amount": 3, "type" : "genie" }
]
}
},
{
"chance": 30,
"guards": [
{ "amount": 3, "type" : "genie" },
{ "amount": 3, "type" : "genie" },
{ "amount": 3, "type" : "genie", "upgrade_chance": 70 },
{ "amount": 3, "type" : "genie" },
{ "amount": 3, "type" : "genie" }
],
"combat_value": 150,
"reward" : {
"resources":
{
"mercury" : 3,
"sulfur" : 3,
"crystal" : 3,
"gems" : 3
},
"creatures": [
{ "amount": 5, "type" : "genie" }
],
"value": 3000
}
},
{
"chance": 30,
"guards": [
{ "amount": 4, "type" : "genie" },
{ "amount": 4, "type" : "genie" },
{ "amount": 4, "type" : "genie", "upgrade_chance": 80 },
{ "amount": 4, "type" : "genie" },
{ "amount": 4, "type" : "genie" }
],
"combat_value": 200,
"reward" : {
"resources":
{
"mercury" : 4,
"sulfur" : 4,
"crystal" : 4,
"gems" : 4
},
"creatures": [
{ "amount": 7, "type" : "genie" }
],
"value": 4000
}
},
{
"chance": 10,
"guards": [
{ "amount": 6, "type" : "genie" },
{ "amount": 6, "type" : "genie" },
{ "amount": 6, "type" : "genie", "upgrade_chance": 90 },
{ "amount": 6, "type" : "genie" },
{ "amount": 6, "type" : "genie" }
],
"combat_value": 250,
"reward" : {
"resources":
{
"mercury" : 5,
"sulfur" : 5,
"crystal" : 5,
"gems" : 5
},
"creatures": [
{ "amount": 9, "type" : "genie" }
],
"value": 5000
}
}
]
},
"grotto" :
{
"name" : "Grotto",
"index" : 20,
"levels": [
{
"chance": 30,
"guards": [
{ "amount": 3, "type" : "harpy" },
{ "amount": 3, "type" : "beholder" },
{ "amount": 3, "type" : "harpy" },
{ "amount": 3, "type" : "beholder" }
],
"combat_value": 200,
"reward" : {
"resources":
{
"ore" : 20,
"gold" : 1000
}
}
},
{
"chance": 30,
"guards": [
{ "amount": 4, "type" : "harpy" },
{ "amount": 4, "type" : "beholder" },
{ "amount": 4, "type" : "harpy" },
{ "amount": 4, "type" : "beholder" }
],
"combat_value": 300,
"reward" : {
"resources":
{
"ore" : 25,
"gold" : 1000
},
"value": 3000
}
},
{
"chance": 30,
"guards": [
{ "amount": 5, "type" : "harpy" },
{ "amount": 5, "type" : "beholder" },
{ "amount": 5, "type" : "harpy" },
{ "amount": 5, "type" : "beholder" }
],
"combat_value": 400,
"reward" : {
"resources":
{
"ore" : 30,
"gold" : 1500
},
"value": 4000
}
},
{
"chance": 10,
"guards": [
{ "amount": 6, "type" : "harpy" },
{ "amount": 6, "type" : "beholder" },
{ "amount": 6, "type" : "harpy" },
{ "amount": 6, "type" : "beholder" }
],
"combat_value": 500,
"reward" : {
"resources":
{
"ore" : 35,
"gold" : 2000
},
"value": 5000
}
}
]
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +0,0 @@
{
"core:creatureGeneratorCommon" : {
"types" : {
"supremeArchangel" : { "index" : 80, "creatures" : [[ "supremeArchangel" ]] },
"diamondDragon" : { "index" : 81, "creatures" : [[ "diamondDragon" ]] },
"lordofThunder" : { "index" : 82, "creatures" : [[ "lordofThunder" ]] },
"hellBaron" : { "index" : 83, "creatures" : [[ "hellBaron" ]] },
"bloodDragon" : { "index" : 84, "creatures" : [[ "bloodDragon" ]] },
"darknessDragon" : { "index" : 85, "creatures" : [[ "darknessDragon" ]] },
"ghostBehemoth" : { "index" : 86, "creatures" : [[ "ghostBehemoth" ]] },
"hellHydra" : { "index" : 87, "creatures" : [[ "hellHydra" ]] },
"sacredPhoenix" : { "index" : 88, "creatures" : [[ "sacredPhoenix" ]] },
"lavaSharpshooter" : { "index" : 89, "creatures" : [[ "lavaSharpshooter" ]] },
"arcticSharpshooter" : { "index" : 90, "creatures" : [[ "arcticSharpshooter" ]] },
"gorynych" : { "index" : 91, "creatures" : [[ "gorynych" ]] },
"nightmare" : { "index" : 92, "creatures" : [[ "nightmare" ]] },
"minotaurKing2" : { "index" : 93, "creatures" : [[ "minotaurKing2" ]] },
"warZealot" : { "index" : 94, "creatures" : [[ "warZealot" ]] },
"santaGremlin" : { "index" : 95, "creatures" : [[ "santaGremlin" ]] },
"sylvanCentaur" : { "index" : 96, "creatures" : [[ "sylvanCentaur" ]] },
"sorceress" : { "index" : 97, "creatures" : [[ "sorceress" ]] },
"werewolf" : { "index" : 98, "creatures" : [[ "werewolf" ]] },
"hellSteed" : { "index" : 99, "creatures" : [[ "hellSteed" ]] },
"dracolich" : { "index" :100, "creatures" : [[ "dracolich" ]] }
}
}
}

View File

@ -1,74 +0,0 @@
{
"core:knight" :
{
"commander" : "paladin1"
},
"core:cleric" :
{
"commander" : "paladin1"
},
"core:planeswalker" :
{
"commander" : "astralSpirit1"
},
"core:elementalist" :
{
"commander" : "astralSpirit1"
},
"core:warlock" :
{
"commander" : "brute1"
},
"core:overlord" :
{
"commander" : "brute1"
},
"core:beastmaster" :
{
"commander" : "shaman1"
},
"core:witch" :
{
"commander" : "shaman1"
},
"core:demoniac" :
{
"commander" : "succubus1"
},
"core:heretic" :
{
"commander" : "succubus1"
},
"core:deathknight" :
{
"commander" : "soulEater1"
},
"core:necromancer" :
{
"commander" : "soulEater1"
},
"core:ranger" :
{
"commander" : "hierophant1"
},
"core:druid" :
{
"commander" : "hierophant1"
},
"core:barbarian" :
{
"commander" : "ogreLeader1"
},
"core:battlemage" :
{
"commander" : "ogreLeader1"
},
"core:alchemist" :
{
"commander" : "templeGuardian1"
},
"core:wizard" :
{
"commander" : "templeGuardian1"
}
}

View File

@ -1,57 +0,0 @@
{
"core:implosion" :
{
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPIMP"
}
},
"core:meteorShower" : {
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPMET"
}
},
"core:armageddon" : {
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPARM"
}
},
"core:dispel" : {
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPDISP"
}
},
"core:slow" : {
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPSLOW"
}
},
"core:berserk" : {
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPBERS"
}
},
"core:hypnotize" : {
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPHYPN"
}
},
"core:blind" : {
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPBLIND"
}
},
"core:dispelHelpful" : {
"graphics" : {
"iconImmune" : "ZVS/LIB1.RES/E_SPDISB"
}
}
}

View File

@ -1,45 +0,0 @@
{
// Text configs
"data/crgen1.txt" : "data/zcrgn1.txt",
"data/crtraits.txt" : "data/zcrtrait.txt",
"data/help.txt" : "data/zelp.txt",
"data/objects.txt" : "data/zobjcts.txt",
// main menu images
"data/gamselb0.bmp" : "data/ZPIC1000.bmp", // map selection screen
"data/gamselb1.bmp" : "data/ZPIC1001.bmp", // map selection screen
"data/loadbar.bmp" : "data/ZPIC106.bmp", // loading screen
"data/gamselbk.bmp" : "data/ZPIC1005.bmp", // background
"data/newgame.bmp" : "data/ZNEWGAM.bmp", // "new game" text
"data/loadgame.bmp" : "data/ZLOADGAM.bmp", // "load game" text
// main menu buttons
"sprites/mmenung.def" : "sprites/zmenung.def",
"sprites/mmenulg.def" : "sprites/zmenulg.def",
"sprites/mmenuhs.def" : "sprites/zmenuhs.def",
"sprites/mmenucr.def" : "sprites/zmenucr.def",
"sprites/mmenuqt.def" : "sprites/zmenuqt.def",
// game type select (single/multi/campaign)
"sprites/gtsingl.def" : "sprites/ztsingl.def",
"sprites/gtmulti.def" : "sprites/ztmulti.def",
"sprites/gtcampn.def" : "sprites/ztcampn.def",
"sprites/gttutor.def" : "sprites/zttutor.def",
"sprites/gtback.def" : "sprites/ztback.def",
// campaigns
"sprites/csssod.def" : "sprites/zsssod.def",
"sprites/cssroe.def" : "sprites/zssroe.def",
"sprites/cssarm.def" : "sprites/zssarm.def",
"sprites/csscus.def" : "sprites/zsscus.def",
// resource bars
"data/tresbar.bmp" : "data/zresbar.bmp",
"data/kresbar.bmp" : "data/z2esbar.bmp",
"data/aresbar.bmp" : "data/zresbar.bmp",
// misc
"data/tpcainfo.bmp" : "data/zpcainfo.bmp", // stats images for town fort
"music/mainmenu.mp3" : "music/mainmenuwog.mp3",
"video/credits.bik" : "video/acredit.bik"
}

View File

@ -1,72 +0,0 @@
{
"name" : "In The Wake of Gods",
"description" : "Unnofficial addon for Heroes of Might and Magic III",
"version" : "0.0.0",
"author" : "WoG Team",
"contact" : "http://forum.vcmi.eu/index.php",
"modType" : "Expansion",
"artifacts" :
[
"config/wog/artifacts.json"
],
"creatures" :
[
"config/wog/creatures.json"
],
"heroClasses" :
[
"config/wog/heroClasses.json"
],
"objects" :
[
"config/wog/dwellings.json",
"config/wog/creatureBanks.json"
],
"filesystem":
{
"" :
[
{ "type" : "map", "path" : "/Config/wogFileOverrides.json"}
],
"CONFIG/" :
[
{ "type" : "dir", "path" : "/Config"}
],
"DATA/" :
[
{"type" : "lod", "path" : "/Data/hmm35wog.pac"},
{"type" : "dir", "path" : "/Data"}
],
"SPRITES/":
[
{"type" : "lod", "path" : "/Data/hmm35wog.pac"},
{"type" : "lod", "path" : "/Data/wog - animated objects.pac"},
{"type" : "lod", "path" : "/Data/wog - animated trees.pac"},
{"type" : "lod", "path" : "/Data/wog - battle decorations.pac"}
],
"SOUNDS/":
[
{"type" : "snd", "path" : "/Data/wog - sounds.snd"},
{"type" : "snd", "path" : "/Data/wog.snd"}
],
"MUSIC/":
[
{"type" : "dir", "path" : "/Mp3"}
],
"VIDEO/":
[
{"type" : "vid", "path" : "/Data/wog - video.vid"},
{"type" : "vid", "path" : "/Data/wog.vid"}
],
"MAPS/":
[
{"type" : "dir", "path" : "/Maps"}
]
}
}

View File

@ -881,6 +881,9 @@ void CSelectionScreen::startScenario()
if(sInfo.mapGenOptions) if(sInfo.mapGenOptions)
{ {
//copy settings from interface to actual options. TODO: refactor, it used to have no effect at all -.-
sInfo.mapGenOptions = std::shared_ptr<CMapGenOptions>(new CMapGenOptions(randMapTab->getMapGenOptions()));
// Update player settings for RMG // Update player settings for RMG
for(const auto & psetPair : sInfo.playerInfos) for(const auto & psetPair : sInfo.playerInfos)
{ {

View File

@ -7,6 +7,10 @@
{ {
"index" : 0, "index" : 0,
"name" : "Cyclops Stockpile", "name" : "Cyclops Stockpile",
"rmg" : {
"value" : 3000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -17,7 +21,7 @@
{ "amount": 4, "type": "cyclop" }, { "amount": 4, "type": "cyclop" },
{ "amount": 4, "type": "cyclop" } { "amount": 4, "type": "cyclop" }
], ],
"combat_value": 506, "combat_value": 506,
"reward" : { "reward" : {
"value": 10000, "value": 10000,
@ -108,6 +112,10 @@
"index" : 1, "index" : 1,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Dwarven Treasury", "name" : "Dwarven Treasury",
"rmg" : {
"value" : 2000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -191,6 +199,10 @@
"index" : 2, "index" : 2,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Griffin Conservatory", "name" : "Griffin Conservatory",
"rmg" : {
"value" : 2000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -258,6 +270,10 @@
"index" : 3, "index" : 3,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Imp Cache", "name" : "Imp Cache",
"rmg" : {
"value" : 5000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -340,6 +356,10 @@
"index" : 4, "index" : 4,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Medusa Stores", "name" : "Medusa Stores",
"rmg" : {
"value" : 1500,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -423,6 +443,10 @@
"index" : 5, "index" : 5,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Naga Bank", "name" : "Naga Bank",
"rmg" : {
"value" : 3000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -506,6 +530,10 @@
"index" : 6, "index" : 6,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Dragon Fly Hive", "name" : "Dragon Fly Hive",
"rmg" : {
"value" : 9000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -579,6 +607,10 @@
"index" : 0, "index" : 0,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Shipwreck", "name" : "Shipwreck",
"rmg" : {
"value" : 2000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -666,6 +698,10 @@
"index" : 0, "index" : 0,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Derelict Ship", "name" : "Derelict Ship",
"rmg" : {
"value" : 4000,
"rarity" : 20
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -754,6 +790,10 @@
"index" : 0, "index" : 0,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Crypt", "name" : "Crypt",
"rmg" : {
"value" : 1000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -839,6 +879,10 @@
"index" : 0, "index" : 0,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Dragon Utopia", "name" : "Dragon Utopia",
"rmg" : {
"value" : 10000,
"rarity" : 100
},
"levels": [ "levels": [
{ {
"chance": 30, "chance": 30,
@ -944,6 +988,10 @@
"index" : 0, "index" : 0,
"resetDuraition" : 28, "resetDuraition" : 28,
"name" : "Pyramid", "name" : "Pyramid",
"rmg" : {
"value" : 5000,
"rarity" : 20
},
"levels": [ "levels": [
{ {
"chance": 100, "chance": 100,
@ -963,4 +1011,4 @@
} }
} }
} }
} }

View File

@ -9,56 +9,402 @@
} }
}, },
"altarOfSacrifice" : { "index" :2, "handler": "market", "types" : { "object" : { "index" : 0} } }, "altarOfSacrifice" : {
"tradingPost" : { "index" :221, "handler": "market", "types" : { "object" : { "index" : 0} } }, "index" :2,
"tradingPostDUPLICATE" : { "index" :99, "handler": "market", "types" : { "object" : { "index" : 0} } }, "handler" : "market",
"freelancersGuild" : { "index" :213, "handler": "market", "types" : { "object" : { "index" : 0} } }, "types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 20
}
}
}
},
"tradingPost" : {
"index" :221,
"handler" : "market",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 100
}
}
}
},
"tradingPostDUPLICATE" : {
"index" :99,
"handler" : "market",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 100
}
}
}
},
"freelancersGuild" : {
"index" :213,
"handler" : "market",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 100,
"rarity" : 100
}
}
}
},
"blackMarket" : { "index" :7, "handler": "blackMarket", "types" : { "object" : { "index" : 0} } }, "blackMarket" : {
"index" :7,
"handler" : "blackMarket",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 8000,
"rarity" : 20
}
}
}
},
"pandoraBox" : { "index" :6, "handler": "pandora", "types" : { "object" : { "index" : 0} } }, "pandoraBox" : {
"event" : { "index" :26, "handler": "event", "types" : { "object" : { "index" : 0} } }, "index" :6,
"handler" : "pandora",
"types" : {
"object" : {
"index" : 0,
"templates" : {
"normal" : { "animation" : "ava0128.def", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
},
"rmg" : {
}
}
}
},
"event" : {
"index" :26,
"handler" : "event",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"redwoodObservatory" : { "index" :58, "handler": "observatory", "types" : { "object" : { "index" : 0} } }, "redwoodObservatory" : {
"pillarOfFire" : { "index" :60, "handler": "observatory", "types" : { "object" : { "index" : 0} } }, "index" :58,
"coverOfDarkness" : { "index" :15, "handler": "observatory", "types" : { "object" : { "index" : 0} } }, "handler" : "observatory",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 750,
"rarity" : 100
}
}
}
},
"pillarOfFire" : {
"index" :60,
"handler" : "observatory",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 750,
"rarity" : 100
}
}
}
},
"coverOfDarkness" : {
"index" :15,
"handler" : "observatory",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"whirlpool" : { "index" :111, "handler": "teleport", "types" : { "object" : { "index" : 0} } }, "whirlpool" : {
"index" :111,
"handler" : "teleport",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"subterraneanGate" : { "subterraneanGate" : {
"index" :103, "index" :103,
"handler": "teleport", "handler" : "teleport",
"types" : { "types" : {
"object" : { "index" : 0 }, "object" : {
"index" : 0 },
"objectWoG" : { "index" : 1 } // WoG object? Present on VCMI Test 2011b "objectWoG" : { "index" : 1 } // WoG object? Present on VCMI Test 2011b
} }
}, },
"refugeeCamp" : { "index" :78, "handler": "dwelling", "types" : { "object" : { "index" : 0} } }, "refugeeCamp" : {
"warMachineFactory" : { "index" :106, "handler": "dwelling", "types" : { "object" : { "index" : 0} } }, "index" :78,
"handler" : "dwelling",
"shrineOfMagicLevel1" : { "index" :88, "handler": "shrine", "types" : { "object" : { "index" : 0} } }, "types" : {
"shrineOfMagicLevel2" : { "index" :89, "handler": "shrine", "types" : { "object" : { "index" : 0} } }, "object" : {
"shrineOfMagicLevel3" : { "index" :90, "handler": "shrine", "types" : { "object" : { "index" : 0} } }, "index" : 0,
"rmg" : {
"eyeOfTheMagi" : { "index" :27, "handler": "magi", "types" : { "object" : { "index" : 0} } }, "value" : 5000,
"hutOfTheMagi" : { "index" :37, "handler": "magi", "types" : { "object" : { "index" : 0} } }, "rarity" : 20
}
"lighthouse" : { "index" :42, "handler": "lighthouse", "types" : { "object" : { "index" : 0} } }, }
"obelisk" : { "index" :57, "handler": "obelisk", "types" : { "object" : { "index" : 0} } }, }
"oceanBottle" : { "index" :59, "handler": "sign", "types" : { "object" : { "index" : 0} } }, },
"scholar" : { "index" :81, "handler": "scholar", "types" : { "object" : { "index" : 0} } }, "warMachineFactory" : {
"shipyard" : { "index" :87, "handler": "shipyard", "types" : { "object" : { "index" : 0} } }, "index" :106,
"sign" : { "index" :91, "handler": "sign", "types" : { "object" : { "index" : 0} } }, "handler" : "dwelling",
"sirens" : { "index" :92, "handler": "siren", "types" : { "object" : { "index" : 0} } }, "types" : {
"denOfThieves" : { "index" :97, "handler": "denOfThieves", "types" : { "object" : { "index" : 0} } }, "object" : {
"university" : { "index" :104, "handler": "university", "types" : { "object" : { "index" : 0} } }, "index" : 0,
"witchHut" : { "index" :113, "handler": "witch", "types" : { "object" : { "index" : 0} } }, "rmg" : {
"questGuard" : { "index" :215, "handler": "questGuard", "types" : { "object" : { "index" : 0} } }, "zoneLimit" : 1,
"value" : 1500,
"rarity" : 50
}
}
}
},
"shrineOfMagicLevel1" : {//incantation
"index" :88,
"handler" : "shrine",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 500,
"rarity" : 100
}
}
}
},
"shrineOfMagicLevel2" : {//gesture
"index" :89,
"handler" : "shrine",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 2000,
"rarity" : 100
}
}
}
},
"shrineOfMagicLevel3" : {//thinking
"index" :90,
"handler" : "shrine",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 3000,
"rarity" : 100
}
}
}
},
"eyeOfTheMagi" : {
"index" :27,
"handler" : "magi",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"hutOfTheMagi" : {
"index" :37,
"handler" : "magi",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"lighthouse" : {
"index" :42,
"handler" : "lighthouse",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"obelisk" : {
"index" :57,
"handler" : "obelisk",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 48,
"value" : 3500,
"rarity" : 200
}
}
}
},
"oceanBottle" : {
"index" :59,
"handler" : "sign",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"scholar" : {
"index" :81,
"handler" : "scholar",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 1500,
"rarity" : 100
}
}
}
},
"shipyard" : {
"index" :87,
"handler" : "shipyard",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"sign" : {
"index" :91,
"handler" : "sign",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"sirens" : {
"index" :92,
"handler" : "siren",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 100,
"rarity" : 20
}
}
}
},
"denOfThieves" : {
"index" :97,
"handler" : "denOfThieves",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"university" : {
"index" :104,
"handler" : "university",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 2500,
"rarity" : 20
}
}
}
},
"witchHut" : {
"index" :113,
"handler" : "witch",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 3,
"mapLimit" : 32,
"value" : 1500,
"rarity" : 80
}
}
}
},
"questGuard" : {
"index" :215,
"handler" : "questGuard",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"magicWell" : { "magicWell" : {
"index" :49, "index" :49,
"handler": "magicWell", "handler" : "magicWell",
"types" : { "types" : {
"object" : { "index" : 0}, "object" : {
"index" : 0,
"rmg" : {
"value" : 250,
"rarity" : 100
}
},
"objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Test 2011b "objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Test 2011b
} }
}, },
@ -99,6 +445,10 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"rmg" : {
"value" : 2000,
"rarity" : 150
},
"templates" : { "templates" : {
"normal" : { "animation" : "AVArnd1", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVArnd1", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@ -111,6 +461,10 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"rmg" : {
"value" : 5000,
"rarity" : 150
},
"templates" : { "templates" : {
"normal" : { "animation" : "AVArnd2", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVArnd2", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@ -123,6 +477,10 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"rmg" : {
"value" : 10000,
"rarity" : 150
},
"templates" : { "templates" : {
"normal" : { "animation" : "AVArnd3", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVArnd3", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@ -135,6 +493,10 @@
"types" : { "types" : {
"object" : { "object" : {
"index" : 0, "index" : 0,
"rmg" : {
"value" : 20000,
"rarity" : 150
},
"templates" : { "templates" : {
"normal" : { "animation" : "AVArnd4", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] } "normal" : { "animation" : "AVArnd4", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
} }
@ -240,10 +602,58 @@
}, },
/// Classes without dedicated object /// Classes without dedicated object
"hillFort" : { "index" :35, "handler": "generic", "types" : { "object" : { "index" : 0} } }, "hillFort" : {
"grail" : { "index" :36, "handler": "generic", "types" : { "object" : { "index" : 0} } }, "index" :35,
"tavern" : { "index" :95, "handler": "generic", "types" : { "object" : { "index" : 0} } }, "handler": "generic",
"sanctuary" : { "index" :80, "handler": "generic", "types" : { "object" : { "index" : 0} } }, "types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 7000,
"rarity" : 20
}
}
}
},
"grail" : {
"index" :36,
"handler": "generic",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
}
}
}
},
"tavern" : {
"index" :95,
"handler": "generic",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 100,
"rarity" : 20
}
}
}
},
"sanctuary" : {
"index" :80,
"handler": "generic",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 50
}
}
}
},
/// Passive objects, terrain overlays /// Passive objects, terrain overlays
"cursedGround" : { "index" :21, "handler": "generic", "types" : { "object" : { "index" : 0} } }, "cursedGround" : { "index" :21, "handler": "generic", "types" : { "object" : { "index" : 0} } },

View File

@ -50,13 +50,13 @@
} }
}, },
"types" : { "types" : {
"wood" : { "index" : 0, "templates" : { "res" : { "animation" : "AVTwood0.def" } } }, "wood" : { "index" : 0, "rmg" : { "value" : 1400, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTwood0.def" } } },
"mercury" : { "index" : 1, "templates" : { "res" : { "animation" : "AVTmerc0.def" } } }, "mercury" : { "index" : 1, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTmerc0.def" } } },
"ore" : { "index" : 2, "templates" : { "res" : { "animation" : "AVTore0.def" } } }, "ore" : { "index" : 2, "rmg" : { "value" : 1400, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTore0.def" } } },
"sulfur" : { "index" : 3, "templates" : { "res" : { "animation" : "AVTsulf0.def" } } }, "sulfur" : { "index" : 3, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTsulf0.def" } } },
"crystal" : { "index" : 4, "templates" : { "res" : { "animation" : "AVTcrys0.def" } } }, "crystal" : { "index" : 4, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTcrys0.def" } } },
"gems" : { "index" : 5, "templates" : { "res" : { "animation" : "AVTgems0.def" } } }, "gems" : { "index" : 5, "rmg" : { "value" : 2000, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTgems0.def" } } },
"gold" : { "index" : 6, "templates" : { "res" : { "animation" : "AVTgold0.def" } } }, "gold" : { "index" : 6, "rmg" : { "value" : 750, "rarity" : 300 }, "templates" : { "res" : { "animation" : "AVTgold0.def" } } },
"mithril" : { "index" : 7 } // TODO: move to WoG? "mithril" : { "index" : 7 } // TODO: move to WoG?
} }
}, },
@ -101,9 +101,9 @@
} }
}, },
"types" : { "types" : {
"evil" : { "index" : 0 }, "evil" : { "index" : 0, "rmg" : { "mapLimit" : 64 } },
"good" : { "index" : 1 }, "good" : { "index" : 1, "rmg" : { "mapLimit" : 64 } },
"neutral" : { "index" : 2 }, "neutral" : { "index" : 2, "rmg" : { "mapLimit" : 64 } },
} }
}, },
@ -156,9 +156,9 @@
"index" :13, "index" :13,
"handler": "cartographer", "handler": "cartographer",
"types" : { "types" : {
"water" : { "index" : 0 }, "water" : { "index" : 0, "rmg" : { "zoneLimit" : 1, "value" : 5000, "rarity" : 20 } },
"land" : { "index" : 1 }, "land" : { "index" : 1, "rmg" : { "zoneLimit" : 1, "value" : 10000, "rarity" : 20 } },
"subterra" : { "index" : 2 } "subterra" : { "index" : 2, "rmg" : { "zoneLimit" : 1, "value" : 7500, "rarity" : 20 } }
} }
}, },
@ -167,13 +167,13 @@
"index" :53, "index" :53,
"handler": "mine", "handler": "mine",
"types" : { "types" : {
"sawmill" : { "index" : 0 }, "sawmill" : { "index" : 0, "rmg" : { "value" : 1500 } },
"alchemistLab" : { "index" : 1 }, "alchemistLab" : { "index" : 1, "rmg" : { "value" : 3500 } },
"orePit" : { "index" : 2 }, "orePit" : { "index" : 2, "rmg" : { "value" : 1500 } },
"sulfurDune" : { "index" : 3 }, "sulfurDune" : { "index" : 3, "rmg" : { "value" : 3500 } },
"crystalCavern" : { "index" : 4 }, "crystalCavern" : { "index" : 4, "rmg" : { "value" : 3500 } },
"gemPond" : { "index" : 5 }, "gemPond" : { "index" : 5, "rmg" : { "value" : 3500 } },
"goldMine" : { "index" : 6 }, "goldMine" : { "index" : 6, "rmg" : { "value" : 7000 } },
} }
}, },
"abandonedMine" : { "abandonedMine" : {

View File

@ -1,51 +1,496 @@
{ {
/// These are objects that covered by concept of "configurable object" /// These are objects that covered by concept of "configurable object"
/// Most or even all of their configuration located in this file /// Most or even all of their configuration located in this file
"magicSpring" : { "index" :48, "handler": "magicSpring", "types" : { "object" : { "index" : 0} } }, "magicSpring" : {//magic source
"index" : 48,
"mysticalGarden" : { "index" :55, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } }, "handler": "magicSpring",
"windmill" : { "index" :112, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
"waterWheel" : { "index" :109, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
"leanTo" : { "index" :39, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
"corpse" : { "index" :22, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
"wagon" : { "index" :105, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
"warriorTomb" : { "index" :108, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
"campfire" : { "index" :12, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
"flotsam" : { "index" :29, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
"seaChest" : { "index" :82, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
"shipwreckSurvivor" : { "index" :86, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
"treasureChest" : { "index" :101, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
"arena" : { "index" :4, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"marlettoTower" : { "index" :23, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"gardenOfRevelation" : { "index" :32, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"libraryOfEnlightenment" : { "index" :41, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"mercenaryCamp" : { "index" :51, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"starAxis" : { "index" :61, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"treeOfKnowledge" : { "index" :102, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"schoolOfMagic" : { "index" :47, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"schoolOfWar" : { "index" :107, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
"learningStone" : {
"index" :100,
"handler": "oncePerHero",
"types" : { "types" : {
"object" : { "index" : 0}, "object" : {
"objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Tests 2011 "index" : 0//,
//"rmg" : {
// "zoneLimit" : 1,
// "mapLimit" : 32,
// "value" : 500,
// "rarity" : 50
//}
//banned due to problems with 2 viistable offsets
}
} }
}, },
"buoy" : { "index" :11, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "mysticalGarden" : {
"swanPond" : { "index" :14, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "index" : 55,
"faerieRing" : { "index" :28, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "handler": "oncePerWeek",
"fountainOfFortune" : { "index" :30, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "types" : {
"fountainOfYouth" : { "index" :31, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "object" : {
"idolOfFortune" : { "index" :38, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "index" : 0,
"mermaids" : { "index" :52, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "rmg" : {
"oasis" : { "index" :56, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "mapLimit" : 32,
"stables" : { "index" :94, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "value" : 500,
"temple" : { "index" :96, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, "rarity" : 50
"rallyFlag" : { "index" :64, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }, }
"wateringHole" : { "index" :110, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } } }
}
},
"windmill" :{
"index" : 112,
"handler": "oncePerWeek",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 1500,
"rarity" : 80
}
}
}
},
"waterWheel" : {
"index" : 109,
"handler": "oncePerWeek",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 750,
"rarity" : 50
}
}
}
},
"leanTo" :{
"index" : 39,
"handler": "onceVisitable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 500,
"rarity" : 100
}
}
}
},
"corpse" :{
"index" : 22,
"handler": "onceVisitable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 500,
"rarity" : 100
}
}
}
},
"wagon" :{
"index" : 105,
"handler": "onceVisitable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 500,
"rarity" : 50
}
}
}
},
"warriorTomb" : {
"index" : 108,
"handler": "onceVisitable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 6000,
"rarity" : 20
}
}
}
},
"campfire" :{
"index" : 12,
"handler": "pickable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 2000,
"rarity" : 500
}
}
}
},
"flotsam" :{
"index" : 29,
"handler": "pickable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 2000,
"rarity" : 100
}
}
}
},
"seaChest" :{
"index" : 82,
"handler": "pickable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 1500,
"rarity" : 500
}
}
}
},
"shipwreckSurvivor" : {
"index" : 86,
"handler": "pickable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 1500,
"rarity" : 50
}
}
}
},
"treasureChest" : {
"index" : 101,
"handler": "pickable",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 1500,
"rarity" : 1000
}
}
}
},
"arena" : {
"index" : 4,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 3000,
"rarity" : 50
}
}
}
},
"marlettoTower" : {
"index" : 23,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 1500,
"rarity" : 100
}
}
}
},
"gardenOfRevelation" : {
"index" : 32,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 1500,
"rarity" : 100
}
}
}
},
"libraryOfEnlightenment" : {
"index" : 41,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 12000,
"rarity" : 20
}
}
}
},
"mercenaryCamp" : {
"index" : 51,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 1500,
"rarity" : 100
}
}
}
},
"starAxis" :{
"index" : 61,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 1500,
"rarity" : 100
}
}
}
},
"treeOfKnowledge" : {
"index" : 102,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 2500,
"rarity" : 50
}
}
}
},
"schoolOfMagic" : {
"index" : 47,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 1000,
"rarity" : 50
}
}
}
},
"schoolOfWar" : {
"index" : 107,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 1000,
"rarity" : 50
}
}
}
},
"learningStone" : {
"index" : 100,
"handler": "oncePerHero",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 1500,
"rarity" : 200
}
},
"objectWoG" : { "index" : 1 } // WoG object? Present on VCMI_Tests 2011
}
},
"buoy" : {
"index" : 11,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 100,
"rarity" : 100
}
}
}
},
"swanPond" : {
"index" : 14,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 100
}
}
}
},
"faerieRing" : {
"index" : 28,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 100
}
}
}
},
"fountainOfFortune" : {
"index" : 30,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 100
}
}
}
},
"fountainOfYouth" : {
"index" : 31,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 50
}
}
}
},
"idolOfFortune" : {
"index" : 38,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 100
}
}
}
},
"mermaids" : {
"index" : 52,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 100,
"rarity" : 20
}
}
}
},
"oasis" : {
"index" : 56,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 50
}
}
}
},
"stables" : {
"index" : 94,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 200,
"rarity" : 40
}
}
}
},
"temple" : {
"index" : 96,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 100
}
}
}
},
"rallyFlag" : {
"index" : 64,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 100,
"rarity" : 100
}
}
}
},
"wateringHole" : {//waters
"index" : 110,
"handler": "bonusingObject",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"zoneLimit" : 1,
"value" : 500,
"rarity" : 50
}
}
}
}
} }

View File

@ -2,13 +2,13 @@
{ {
"Analogy" : "Analogy" :
{ {
"minSize" : "m", "maxSize" : "m", "minSize" : "m", "maxSize" : "m+u",
"players" : "4", "players" : "4",
"zones" : "zones" :
{ {
"1" : "1" :
{ {
"type" : "playerStart", "size" : 1, "owner" : 1, "type" : "playerStart", "size" : 2, "owner" : 1,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true, "playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal", "monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1}, "mines" : {"wood" : 1, "ore" : 1, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1},
@ -19,7 +19,7 @@
}, },
"2" : "2" :
{ {
"type" : "playerStart", "size" : 1, "owner" : 2, "type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true, "playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal", "monsters" : "normal",
"minesLikeZone" : 1, "minesLikeZone" : 1,
@ -27,7 +27,7 @@
}, },
"3" : "3" :
{ {
"type" : "playerStart", "size" : 1, "owner" : 3, "type" : "playerStart", "size" : 2, "owner" : 3,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true, "playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal", "monsters" : "normal",
"minesLikeZone" : 1, "minesLikeZone" : 1,
@ -35,7 +35,7 @@
}, },
"4" : "4" :
{ {
"type" : "playerStart", "size" : 1, "owner" : 4, "type" : "playerStart", "size" : 2, "owner" : 4,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true, "playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal", "monsters" : "normal",
"minesLikeZone" : 1, "minesLikeZone" : 1,
@ -43,7 +43,7 @@
}, },
"5" : "5" :
{ {
"type" : "treasure", "size" : 2, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false, "type" : "treasure", "size" : 3, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
"neutralTowns" : { "castles" : 1 }, "neutralTowns" : { "castles" : 1 },
"monsters" : "strong", "monsters" : "strong",
"mines" : {"gold" : 2}, "mines" : {"gold" : 2},
@ -63,13 +63,13 @@
}, },
"Upgrade" : "Upgrade" :
{ {
"minSize" : "s", "maxSize" : "m", "minSize" : "s+u", "maxSize" : "m",
"players" : "2", "players" : "2",
"zones" : "zones" :
{ {
"1" : "1" :
{ {
"type" : "playerStart", "size" : 1, "owner" : 1, "type" : "playerStart", "size" : 3, "owner" : 1,
"playerTowns" : { "castles" : 1 }, "playerTowns" : { "castles" : 1 },
"monsters" : "normal", "monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1}, "mines" : {"wood" : 1, "ore" : 1},
@ -80,7 +80,7 @@
}, },
"2" : "2" :
{ {
"type" : "playerStart", "size" : 1, "owner" : 2, "type" : "playerStart", "size" : 3, "owner" : 2,
"playerTowns" : { "castles" : 1 }, "playerTowns" : { "castles" : 1 },
"monsters" : "normal", "monsters" : "normal",
"minesLikeZone" : 1, "minesLikeZone" : 1,
@ -88,7 +88,7 @@
}, },
"3" : "3" :
{ {
"type" : "treasure", "size" : 2, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 1, "type" : "treasure", "size" : 4, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 1,
"monsters" : "weak", "monsters" : "weak",
"mines" : {"gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1}, "mines" : {"gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [ "treasure" : [
@ -98,14 +98,14 @@
}, },
"4" : "4" :
{ {
"type" : "treasure", "size" : 2, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 2, "type" : "treasure", "size" : 4, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 2,
"monsters" : "weak", "monsters" : "weak",
"minesLikeZone" : 3, "minesLikeZone" : 3,
"treasureLikeZone" : 3 "treasureLikeZone" : 3
}, },
"5" : "5" :
{ {
"type" : "treasure", "size" : 3, "neutralTowns" : { "castles" : 1 }, "terrainTypes" : [ "sand" ], "type" : "treasure", "size" : 5, "neutralTowns" : { "castles" : 1 }, "terrainTypes" : [ "sand" ],
"monsters" : "strong", "monsters" : "strong",
"mines" : {"gold" : 2}, "mines" : {"gold" : 2},
"treasure" : [ "treasure" : [
@ -126,13 +126,13 @@
}, },
"Golden Ring" : "Golden Ring" :
{ {
"minSize" : "m", "maxSize" : "l", "minSize" : "m+u", "maxSize" : "l",
"players" : "3", "players" : "3",
"zones" : "zones" :
{ {
"1" : "1" :
{ {
"type" : "playerStart", "size" : 3, "owner" : 1, "type" : "playerStart", "size" : 2, "owner" : 1,
"playerTowns" : { "castles" : 1 }, "playerTowns" : { "castles" : 1 },
"monsters" : "normal", "monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1}, "mines" : {"wood" : 1, "ore" : 1},
@ -143,7 +143,7 @@
}, },
"2" : "2" :
{ {
"type" : "playerStart", "size" : 3, "owner" : 2, "type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 }, "playerTowns" : { "castles" : 1 },
"monsters" : "normal", "monsters" : "normal",
"minesLikeZone" : 1, "minesLikeZone" : 1,
@ -151,7 +151,7 @@
}, },
"3" : "3" :
{ {
"type" : "playerStart", "size" : 3, "owner" : 3, "type" : "playerStart", "size" : 2, "owner" : 3,
"playerTowns" : { "castles" : 1 }, "playerTowns" : { "castles" : 1 },
"monsters" : "normal", "monsters" : "normal",
"minesLikeZone" : 1, "minesLikeZone" : 1,
@ -243,7 +243,7 @@
}, },
"Jebus Cross": "Jebus Cross":
{ {
"minSize" : "l", "maxSize" : "xl", "minSize" : "l+u", "maxSize" : "xl+u",
"players" : "4", "players" : "4",
"zones": "zones":
{ {

View File

@ -117,7 +117,7 @@ namespace RandomGeneratorUtil
int n = (container.end() - container.begin()); int n = (container.end() - container.begin());
for (int i = n-1; i>0; --i) for (int i = n-1; i>0; --i)
{ {
std::swap (container.begin()[i],container.begin()[rand.nextInt(i+1)]); std::swap (container.begin()[i],container.begin()[rand.nextInt(i)]);
} }
} }
} }

View File

@ -241,13 +241,7 @@ int CGObjectInstance::getSightRadious() const
int3 CGObjectInstance::getVisitableOffset() const int3 CGObjectInstance::getVisitableOffset() const
{ {
for(int y = 0; y < appearance.getHeight(); y++) return appearance.getVisitableOffset();
for (int x = 0; x < appearance.getWidth(); x++)
if (appearance.isVisitableAt(x, y))
return int3(x,y,0);
//logGlobal->warnStream() << "Warning: getVisitableOffset called on non-visitable obj!";
return int3(0,0,0);
} }
void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) const void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) const

View File

@ -218,6 +218,17 @@ bool CDwellingInstanceConstructor::producesCreature(const CCreature * crea) cons
return false; return false;
} }
std::vector<const CCreature *> CDwellingInstanceConstructor::getProducedCreatures() const
{
std::vector<const CCreature *> creatures; //no idea why it's 2D, to be honest
for (auto & entry : availableCreatures)
{
for (const CCreature * cre : entry)
creatures.push_back(cre);
}
return creatures;
}
CBankInstanceConstructor::CBankInstanceConstructor() CBankInstanceConstructor::CBankInstanceConstructor()
{ {
} }

View File

@ -13,6 +13,7 @@
* *
*/ */
class CGObjectInstance;
class CGTownInstance; class CGTownInstance;
class CGHeroInstance; class CGHeroInstance;
class CGDwelling; class CGDwelling;
@ -123,6 +124,7 @@ public:
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const; void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
bool producesCreature(const CCreature * crea) const; bool producesCreature(const CCreature * crea) const;
std::vector<const CCreature *> getProducedCreatures() const;
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {

View File

@ -871,6 +871,12 @@ void CGArtifact::initObj()
blockVisit = true; blockVisit = true;
if(ID == Obj::ARTIFACT) if(ID == Obj::ARTIFACT)
{ {
if (!storedArtifact)
{
auto a = new CArtifactInstance();
cb->gameState()->map->addNewArtifactInstance(a);
storedArtifact = a;
}
if(!storedArtifact->artType) if(!storedArtifact->artType)
storedArtifact->setType(VLC->arth->artifacts[subID]); storedArtifact->setType(VLC->arth->artifacts[subID]);
} }
@ -963,6 +969,11 @@ void CGArtifact::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
void CGWitchHut::initObj() void CGWitchHut::initObj()
{ {
if (allowedAbilities.empty()) //this can happen for RMG. regular maps load abilities from map file
{
for (int i = 0; i < GameConstants::SKILL_QUANTITY; i++)
allowedAbilities.push_back(i);
}
ability = *RandomGeneratorUtil::nextItem(allowedAbilities, cb->gameState()->getRandomGenerator()); ability = *RandomGeneratorUtil::nextItem(allowedAbilities, cb->gameState()->getRandomGenerator());
} }

View File

@ -158,6 +158,8 @@ public:
CArtifactInstance *storedArtifact; CArtifactInstance *storedArtifact;
std::string message; std::string message;
CGArtifact() : CArmedInstance() {storedArtifact = nullptr;};
void onHeroVisit(const CGHeroInstance * h) const override; void onHeroVisit(const CGHeroInstance * h) const override;
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override; void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override; void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;

View File

@ -23,7 +23,7 @@
* *
*/ */
static bool isVisitableFromTop(int identifier, int type) static bool isOnVisitableFromTopList(int identifier, int type)
{ {
if(type == 2 || type == 3 || type == 4 || type == 5) //creature, hero, artifact, resource if(type == 2 || type == 3 || type == 4 || type == 5) //creature, hero, artifact, resource
return true; return true;
@ -106,7 +106,7 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser)
int type = boost::lexical_cast<int>(strings[7]); int type = boost::lexical_cast<int>(strings[7]);
printPriority = boost::lexical_cast<int>(strings[8]) * 100; // to have some space in future printPriority = boost::lexical_cast<int>(strings[8]) * 100; // to have some space in future
if (isVisitableFromTop(id, type)) if (isOnVisitableFromTopList(id, type))
visitDir = 0xff; visitDir = 0xff;
else else
visitDir = (8|16|32|64|128); visitDir = (8|16|32|64|128);
@ -168,7 +168,7 @@ void ObjectTemplate::readMap(CBinaryReader & reader)
int type = reader.readUInt8(); int type = reader.readUInt8();
printPriority = reader.readUInt8() * 100; // to have some space in future printPriority = reader.readUInt8() * 100; // to have some space in future
if (isVisitableFromTop(id, type)) if (isOnVisitableFromTopList(id, type))
visitDir = 0xff; visitDir = 0xff;
else else
visitDir = (8|16|32|64|128); visitDir = (8|16|32|64|128);
@ -354,6 +354,24 @@ bool ObjectTemplate::isVisitableFrom(si8 X, si8 Y) const
return dirMap[dy][dx] != 0; return dirMap[dy][dx] != 0;
} }
int3 ObjectTemplate::getVisitableOffset() const
{
for(int y = 0; y < getHeight(); y++)
for (int x = 0; x < getWidth(); x++)
if (isVisitableAt(x, y))
return int3(x,y,0);
//logGlobal->warnStream() << "Warning: getVisitableOffset called on non-visitable obj!";
return int3(0,0,0);
}
bool ObjectTemplate::isVisitableFromTop() const
{
return visitDir & 2;
//for some reason the line below is never called :?
//return isVisitableFrom (0, 1);
}
bool ObjectTemplate::canBePlacedAt(ETerrainType terrain) const bool ObjectTemplate::canBePlacedAt(ETerrainType terrain) const
{ {
return allowedTerrains.count(terrain) != 0; return allowedTerrains.count(terrain) != 0;

View File

@ -62,6 +62,8 @@ public:
// Checks if object is visitable from certain direction. X and Y must be between -1..+1 // Checks if object is visitable from certain direction. X and Y must be between -1..+1
bool isVisitableFrom(si8 X, si8 Y) const; bool isVisitableFrom(si8 X, si8 Y) const;
int3 getVisitableOffset() const;
bool isVisitableFromTop() const;
// Checks if object can be placed on specific terrain // Checks if object can be placed on specific terrain
bool canBePlacedAt(ETerrainType terrain) const; bool canBePlacedAt(ETerrainType terrain) const;
@ -73,6 +75,8 @@ public:
void readMap(CBinaryReader & reader); void readMap(CBinaryReader & reader);
void readJson(const JsonNode & node); void readJson(const JsonNode & node);
bool operator==(const ObjectTemplate& ot) const { return (id == ot.id && subid == ot.subid); }
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & usedTiles & allowedTerrains & animationFile & stringID; h & usedTiles & allowedTerrains & animationFile & stringID;

View File

@ -175,14 +175,11 @@ const std::map<std::string, CRmgTemplate *> & CMapGenOptions::getAvailableTempla
return VLC->tplh->getTemplates(); return VLC->tplh->getTemplates();
} }
void CMapGenOptions::finalize()
{
CRandomGenerator rand;
finalize(rand);
}
void CMapGenOptions::finalize(CRandomGenerator & rand) 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;
if(!mapTemplate) if(!mapTemplate)
{ {
mapTemplate = getPossibleTemplate(rand); mapTemplate = getPossibleTemplate(rand);

View File

@ -145,7 +145,6 @@ public:
/// Finalizes the options. All random sizes for various properties will be overwritten by numbers from /// Finalizes the options. All random sizes for various properties will be overwritten by numbers from
/// a random number generator by keeping the options in a valid state. Check options should return true, otherwise /// a random number generator by keeping the options in a valid state. Check options should return true, otherwise
/// this function fails. /// this function fails.
void finalize();
void finalize(CRandomGenerator & rand); void finalize(CRandomGenerator & rand);
/// Returns false if there is no template available which fits to the currently selected options. /// Returns false if there is no template available which fits to the currently selected options.

View File

@ -11,6 +11,7 @@
#include "CRmgTemplate.h" #include "CRmgTemplate.h"
#include "CRmgTemplateZone.h" #include "CRmgTemplateZone.h"
#include "CZonePlacer.h" #include "CZonePlacer.h"
#include "../mapObjects/CObjectClassesHandler.h"
void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo) void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3& pos)> foo)
{ {
@ -24,7 +25,7 @@ void CMapGenerator::foreach_neighbour(const int3 &pos, std::function<void(int3&
CMapGenerator::CMapGenerator(shared_ptr<CMapGenOptions> mapGenOptions, int RandomSeed /*= std::time(nullptr)*/) : CMapGenerator::CMapGenerator(shared_ptr<CMapGenOptions> mapGenOptions, int RandomSeed /*= std::time(nullptr)*/) :
mapGenOptions(mapGenOptions), randomSeed(RandomSeed), monolithIndex(0) mapGenOptions(mapGenOptions), randomSeed(RandomSeed), monolithIndex(0), zonesTotal(0)
{ {
rand.setSeed(randomSeed); rand.setSeed(randomSeed);
} }
@ -215,9 +216,9 @@ void CMapGenerator::fillZones()
logGlobal->infoStream() << "Started filling zones"; logGlobal->infoStream() << "Started filling zones";
createConnections(); createConnections();
//make sure all connections are passable before creating borders
for (auto it : zones) for (auto it : zones)
{ {
//make sure all connections are passable before creating borders
it.second->createBorder(this); it.second->createBorder(this);
it.second->fill(this); it.second->fill(this);
} }
@ -239,25 +240,96 @@ void CMapGenerator::createConnections()
int3 guardPos(-1,-1,-1); int3 guardPos(-1,-1,-1);
auto otherZoneTiles = zoneB->getTileInfo(); auto otherZoneTiles = zoneB->getTileInfo();
//auto otherZoneCenter = zoneB->getPos();
for (auto tile : tiles) int3 posA = zoneA->getPos();
int3 posB = zoneB->getPos();
if (posA.z == posB.z)
{ {
foreach_neighbour (tile, [&guardPos, tile, &otherZoneTiles](int3 &pos) for (auto tile : tiles)
{ {
if (vstd::contains(otherZoneTiles, pos)) if (isBlocked(tile)) //tiles may be occupied by subterranean gates already placed
guardPos = tile; continue;
}); foreach_neighbour (tile, [&guardPos, tile, &otherZoneTiles, this](int3 &pos)
if (guardPos.valid()) {
{ //if (vstd::contains(otherZoneTiles, pos) && !this->isBlocked(pos))
setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn if (vstd::contains(otherZoneTiles, pos))
zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template guardPos = tile;
//zones can make paths only in their own area });
zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId(), zoneA->getFreePaths()); //make connection towards our zone center if (guardPos.valid())
zoneB->crunchPath (this, guardPos, zoneB->getPos(), zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center {
break; //we're done with this connection setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
zoneA->addMonster (this, guardPos, connection.getGuardStrength(), false, true);
//zones can make paths only in their own area
zoneA->crunchPath (this, guardPos, posA, zoneA->getId(), zoneA->getFreePaths()); //make connection towards our zone center
zoneB->crunchPath (this, guardPos, posB, zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center
break; //we're done with this connection
}
} }
} }
else //create subterranean gates between two zones
{
//find point on the path between zones
float3 offset (posB.x - posA.x, posB.y - posA.y, 0);
float distance = posB.dist2d(posA);
vstd::amax (distance, 0.5f);
offset /= distance; //get unit vector
float3 vec (0, 0, 0);
//use reduced size of underground zone - make sure gate does not stand on rock
int3 tile = posA;
int3 otherTile = tile;
bool stop = false;
while (!stop)
{
vec += offset; //this vector may extend beyond line between zone centers, in case they are directly over each other
tile = posA + int3(vec.x, vec.y, 0);
float distanceFromA = posA.dist2d(tile);
float distanceFromB = posB.dist2d(tile);
if (distanceFromA + distanceFromB > std::max<int>(zoneA->getSize() + zoneB->getSize(), distance))
break; //we are too far away to ever connect
//if zone is underground, gate must fit within its (reduced) radius
if (distanceFromA > 5 && (!posA.z || distanceFromA < zoneA->getSize() - 3) &&
distanceFromB > 5 && (!posB.z || distanceFromB < zoneB->getSize() - 3))
{
otherTile = tile;
otherTile.z = posB.z;
if (vstd::contains(tiles, tile) && vstd::contains(otherZoneTiles, otherTile))
{
bool withinZone = true;
foreach_neighbour (tile, [&withinZone, &tiles](int3 &pos)
{
if (!vstd::contains(tiles, pos))
withinZone = false;
});
foreach_neighbour (otherTile, [&withinZone, &otherZoneTiles](int3 &pos)
{
if (!vstd::contains(otherZoneTiles, pos))
withinZone = false;
});
if (withinZone)
{
auto gate1 = new CGTeleport;
gate1->ID = Obj::SUBTERRANEAN_GATE;
gate1->subID = 0;
zoneA->placeAndGuardObject(this, gate1, tile, connection.getGuardStrength());
auto gate2 = new CGTeleport(*gate1);
zoneB->placeAndGuardObject(this, gate2, otherTile, connection.getGuardStrength());
stop = true; //we are done, go to next connection
}
}
}
}
if (stop)
continue;
}
if (!guardPos.valid()) if (!guardPos.valid())
{ {
auto teleport1 = new CGTeleport; auto teleport1 = new CGTeleport;
@ -299,28 +371,35 @@ bool CMapGenerator::isBlocked(const int3 &tile) const
bool CMapGenerator::shouldBeBlocked(const int3 &tile) const bool CMapGenerator::shouldBeBlocked(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile)); throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].shouldBeBlocked(); return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();
} }
bool CMapGenerator::isPossible(const int3 &tile) const bool CMapGenerator::isPossible(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile)); throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isPossible(); return tiles[tile.x][tile.y][tile.z].isPossible();
} }
bool CMapGenerator::isFree(const int3 &tile) const bool CMapGenerator::isFree(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile)); throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isFree(); return tiles[tile.x][tile.y][tile.z].isFree();
} }
bool CMapGenerator::isUsed(const int3 &tile) const
{
if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].isUsed();
}
void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state) void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
{ {
if (!map->isInTheMap(tile)) if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile)); throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
tiles[tile.x][tile.y][tile.z].setOccupied(state); tiles[tile.x][tile.y][tile.z].setOccupied(state);
} }
@ -328,7 +407,7 @@ void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
CTileInfo CMapGenerator::getTile(const int3& tile) const CTileInfo CMapGenerator::getTile(const int3& tile) const
{ {
if (!map->isInTheMap(tile)) if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile)); throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z]; return tiles[tile.x][tile.y][tile.z];
} }
@ -336,7 +415,7 @@ CTileInfo CMapGenerator::getTile(const int3& tile) const
void CMapGenerator::setNearestObjectDistance(int3 &tile, int value) void CMapGenerator::setNearestObjectDistance(int3 &tile, int value)
{ {
if (!map->isInTheMap(tile)) if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile)); throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value); tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value);
} }
@ -344,12 +423,29 @@ void CMapGenerator::setNearestObjectDistance(int3 &tile, int value)
int CMapGenerator::getNearestObjectDistance(const int3 &tile) const int CMapGenerator::getNearestObjectDistance(const int3 &tile) const
{ {
if (!map->isInTheMap(tile)) if (!map->isInTheMap(tile))
throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile)); throw rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance(); return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();
} }
int CMapGenerator::getNextMonlithIndex() int CMapGenerator::getNextMonlithIndex()
{ {
return monolithIndex++; if (monolithIndex >= VLC->objtypeh->knownSubObjects(Obj::MONOLITH_TWO_WAY).size())
throw rmgException(boost::to_string(boost::format("There is no Monolith Two Way with index %d available!") % monolithIndex));
else
return monolithIndex++;
}
void CMapGenerator::registerZone (TFaction faction)
{
zonesPerFaction[faction]++;
zonesTotal++;
}
ui32 CMapGenerator::getZoneCount(TFaction faction)
{
return zonesPerFaction[faction];
}
ui32 CMapGenerator::getTotalZoneCount() const
{
return zonesTotal;
} }

View File

@ -70,6 +70,7 @@ public:
bool shouldBeBlocked(const int3 &tile) const; bool shouldBeBlocked(const int3 &tile) const;
bool isPossible(const int3 &tile) const; bool isPossible(const int3 &tile) const;
bool isFree(const int3 &tile) const; bool isFree(const int3 &tile) const;
bool isUsed(const int3 &tile) const;
void setOccupied(const int3 &tile, ETileType::ETileType state); void setOccupied(const int3 &tile, ETileType::ETileType state);
CTileInfo getTile(const int3 & tile) const; CTileInfo getTile(const int3 & tile) const;
@ -77,9 +78,14 @@ public:
void setNearestObjectDistance(int3 &tile, int value); void setNearestObjectDistance(int3 &tile, int value);
int getNextMonlithIndex(); int getNextMonlithIndex();
void registerZone (TFaction faction);
ui32 getZoneCount(TFaction faction);
ui32 getTotalZoneCount() const;
private: private:
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones; std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;
std::map<TFaction, ui32> zonesPerFaction;
ui32 zonesTotal; //zones that have their main town only
CTileInfo*** tiles; CTileInfo*** tiles;

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@
#include "float3.h" #include "float3.h"
#include "../int3.h" #include "../int3.h"
#include "../ResourceSet.h" //for TResource (?) #include "../ResourceSet.h" //for TResource (?)
#include "../mapObjects/ObjectTemplate.h"
class CMapGenerator; class CMapGenerator;
class CTileInfo; class CTileInfo;
@ -45,6 +46,7 @@ public:
bool shouldBeBlocked() const; bool shouldBeBlocked() const;
bool isPossible() const; bool isPossible() const;
bool isFree() const; bool isFree() const;
bool isUsed() const;
void setOccupied(ETileType::ETileType value); void setOccupied(ETileType::ETileType value);
ETerrainType getTerrainType() const; ETerrainType getTerrainType() const;
void setTerrainType(ETerrainType value); void setTerrainType(ETerrainType value);
@ -66,9 +68,25 @@ public:
struct DLL_LINKAGE ObjectInfo struct DLL_LINKAGE ObjectInfo
{ {
ObjectTemplate templ;
ui32 value; ui32 value;
ui16 probability; ui16 probability;
ui32 maxPerZone;
ui32 maxPerMap;
std::function<CGObjectInstance *()> generateObject; std::function<CGObjectInstance *()> generateObject;
void setTemplate (si32 type, si32 subtype, ETerrainType terrain);
bool operator==(const ObjectInfo& oi) const { return (templ == oi.templ); }
};
struct DLL_LINKAGE CTreasurePileInfo
{
std::set<int3> visitableFromBottomPositions; //can be visited only from bottom or side
std::set<int3> visitableFromTopPositions; //they can be visited from any direction
std::set<int3> blockedPositions;
std::set<int3> occupiedPositions; //blocked + visitable
int3 nextTreasurePos;
}; };
/// The CRmgTemplateZone describes a zone in a template. /// The CRmgTemplateZone describes a zone in a template.
@ -128,13 +146,15 @@ public:
void addTile (const int3 &pos); void addTile (const int3 &pos);
std::set<int3> getTileInfo () const; std::set<int3> getTileInfo () const;
void discardDistantTiles (CMapGenerator* gen, float distance);
void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0); void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
bool addMonster(CMapGenerator* gen, int3 &pos, si32 strength); bool addMonster(CMapGenerator* gen, int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false);
bool createTreasurePile (CMapGenerator* gen, int3 &pos); bool createTreasurePile (CMapGenerator* gen, int3 &pos);
bool fill (CMapGenerator* gen); bool fill (CMapGenerator* gen);
bool placeMines (CMapGenerator* gen); bool placeMines (CMapGenerator* gen);
void initTownType (CMapGenerator* gen); void initTownType (CMapGenerator* gen);
void paintZoneTerrain (CMapGenerator* gen, ETerrainType terrainType);
void initTerrainType (CMapGenerator* gen); void initTerrainType (CMapGenerator* gen);
void createBorder(CMapGenerator* gen); void createBorder(CMapGenerator* gen);
void fractalize(CMapGenerator* gen); void fractalize(CMapGenerator* gen);
@ -152,7 +172,9 @@ public:
std::vector<CTreasureInfo> getTreasureInfo(); std::vector<CTreasureInfo> getTreasureInfo();
std::set<int3>* getFreePaths(); std::set<int3>* getFreePaths();
ObjectInfo getRandomObject (CMapGenerator* gen, ui32 value); ObjectInfo getRandomObject (CMapGenerator* gen, CTreasurePileInfo &info, ui32 value);
void placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard = false);
private: private:
//template info //template info
@ -189,10 +211,11 @@ private:
bool pointIsIn(int x, int y); bool pointIsIn(int x, int y);
void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects void addAllPossibleObjects (CMapGenerator* gen); //add objects, including zone-specific, to possibleObjects
bool isAccessibleFromAnywhere (CMapGenerator* gen, ObjectTemplate &appearance, int3 &tile, const std::set<int3> &tilesBlockedByObject) const;
bool findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos); bool findPlaceForObject(CMapGenerator* gen, CGObjectInstance* obj, si32 min_dist, int3 &pos);
bool findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dist, int3 &pos); bool findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dist, int3 &pos);
bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos); bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos);
void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos); void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos); void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str); bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str, bool zoneGuard = false);
}; };

View File

@ -43,7 +43,8 @@ void CZonePlacer::placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGe
//some relaxation-simmulated annealing algorithm //some relaxation-simmulated annealing algorithm
const int iterations = 100; const int iterations = 100;
float temperature = 1e-2;; float temperatureConstant = 1e-2;
float currentTemperature = 2; //geater temperature - stronger gravity, weaker pushing away
const float temperatureModifier = 0.99; const float temperatureModifier = 0.99;
logGlobal->infoStream() << "Starting zone placement"; logGlobal->infoStream() << "Starting zone placement";
@ -52,8 +53,7 @@ void CZonePlacer::placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGe
int height = mapGenOptions->getHeight(); int height = mapGenOptions->getHeight();
auto zones = gen->getZones(); auto zones = gen->getZones();
bool underground = mapGenOptions->getHasTwoLevels();
//TODO: consider underground zones
/* /*
let's assume we try to fit N circular zones with radius = size on a map let's assume we try to fit N circular zones with radius = size on a map
@ -62,13 +62,37 @@ void CZonePlacer::placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGe
prescaler = sqrt((WH)/(sum(n^2)*pi)) prescaler = sqrt((WH)/(sum(n^2)*pi))
*/ */
std::vector<std::pair<TRmgTemplateZoneId, CRmgTemplateZone*>> zonesVector (zones.begin(), zones.end());
assert (zonesVector.size());
RandomGeneratorUtil::randomShuffle(zonesVector, *rand);
TRmgTemplateZoneId firstZone = zones.begin()->first; //we want lowest ID here
bool undergroundFlag = false;
float totalSize = 0; float totalSize = 0;
for (auto zone : zones) for (auto zone : zonesVector)
{ {
//even distribution for surface / underground zones. Surface zones always have priority.
int level = 0;
if (underground) //only then consider underground zones
{
if (zone.first == firstZone)
{
level = 0;
}
else
{
level = undergroundFlag;
undergroundFlag = !undergroundFlag; //toggle underground on/off
}
}
totalSize += (zone.second->getSize() * zone.second->getSize()); totalSize += (zone.second->getSize() * zone.second->getSize());
zone.second->setCenter (float3(rand->nextDouble(0.2,0.8), rand->nextDouble(0.2,0.8), 0)); //start away from borders zone.second->setCenter (float3(rand->nextDouble(0.2, 0.8), rand->nextDouble(0.2, 0.8), level)); //start away from borders
} }
//prescale zones //prescale zones
if (underground) //map is twice as big, so zones occupy only half of normal space
totalSize /= 2;
float prescaler = sqrt ((width * height) / (totalSize * 3.14f)); float prescaler = sqrt ((width * height) / (totalSize * 3.14f));
float mapSize = sqrt (width * height); float mapSize = sqrt (width * height);
for (auto zone : zones) for (auto zone : zones)
@ -95,63 +119,66 @@ void CZonePlacer::placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGe
for (auto con : zone.second->getConnections()) for (auto con : zone.second->getConnections())
{ {
auto otherZone = zones[con]; auto otherZone = zones[con];
float distance = pos.dist2d (otherZone->getCenter()); float3 otherZoneCenter = otherZone->getCenter();
float distance = pos.dist2d (otherZoneCenter);
float minDistance = (zone.second->getSize() + otherZone->getSize())/mapSize; //scale down to (0,1) coordinates float minDistance = (zone.second->getSize() + otherZone->getSize())/mapSize; //scale down to (0,1) coordinates
if (distance > minDistance) if (distance > minDistance)
{ {
forceVector += (otherZone->getCenter() - pos) / getDistance(distance); //positive value //WARNING: compiler used to 'optimize' that line so it never actually worked
forceVector += (((otherZoneCenter - pos) / getDistance(distance)) * currentTemperature); //positive value
} }
} }
//separate overlaping zones //separate overlaping zones
for (auto otherZone : zones) for (auto otherZone : zones)
{ {
if (zone == otherZone) float3 otherZoneCenter = otherZone.second->getCenter();
//zones on different levels don't push away
if (zone == otherZone || pos.z != otherZoneCenter.z)
continue; continue;
float distance = pos.dist2d (otherZone.second->getCenter()); float distance = pos.dist2d (otherZoneCenter);
float minDistance = (zone.second->getSize() + otherZone.second->getSize())/mapSize; float minDistance = (zone.second->getSize() + otherZone.second->getSize())/mapSize;
if (distance < minDistance) if (distance < minDistance)
{ {
forceVector -= (otherZone.second->getCenter() - pos) / getDistance(distance); //negative value forceVector -= (otherZoneCenter - pos) / getDistance(distance) / currentTemperature; //negative value
} }
} }
//move zones away from boundaries //move zones away from boundaries
float3 boundary(0,0,pos.z);
float size = zone.second->getSize() / mapSize; float size = zone.second->getSize() / mapSize;
auto pushAwayFromBoundary = [&forceVector, pos, currentTemperature, &getDistance](float x, float y)
{
float3 boundary = float3 (x, y, pos.z);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance) / currentTemperature; //negative value
};
if (pos.x < size) if (pos.x < size)
{ {
boundary = float3 (0, pos.y, pos.z); pushAwayFromBoundary(0, pos.y);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance); //negative value
} }
if (pos.x > 1-size) if (pos.x > 1-size)
{ {
boundary = float3 (1, pos.y, pos.z); pushAwayFromBoundary(1, pos.y);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance); //negative value
} }
if (pos.y < size) if (pos.y < size)
{ {
boundary = float3 (pos.x, 0, pos.z); pushAwayFromBoundary(pos.x, 0);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance); //negative value
} }
if (pos.y > 1-size) if (pos.y > 1-size)
{ {
boundary = float3 (pos.x, 1, pos.z); pushAwayFromBoundary(pos.x, 1);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance); //negative value
} }
forces[zone.second] = forceVector; forceVector.z = 0; //operator - doesn't preserve z coordinate :/
forces[zone.second] = forceVector * temperatureConstant;
} }
//update positions //update positions
for (auto zone : forces) for (auto zone : forces)
{ {
zone.first->setCenter (zone.first->getCenter() + zone.second * temperature); zone.first->setCenter (zone.first->getCenter() + zone.second);
} }
temperature *= temperatureModifier; //decrease temperature (needed?) currentTemperature *= temperatureModifier; //decrease temperature (needed?)
} }
for (auto zone : zones) //finalize zone positions for (auto zone : zones) //finalize zone positions
{ {
@ -213,7 +240,10 @@ void CZonePlacer::assignZones(shared_ptr<CMapGenOptions> mapGenOptions)
int3 pos(i, j, k); int3 pos(i, j, k);
for (auto zone : zones) for (auto zone : zones)
{ {
distances.push_back (std::make_pair(zone.second, metric(pos, zone.second->getPos()))); if (zone.second->getPos().z == k)
distances.push_back (std::make_pair(zone.second, metric(pos, zone.second->getPos())));
else
distances.push_back (std::make_pair(zone.second, std::numeric_limits<float>::max()));
} }
boost::sort (distances, compareByDistance); boost::sort (distances, compareByDistance);
distances.front().first->addTile(pos); //closest tile belongs to zone distances.front().first->addTile(pos); //closest tile belongs to zone
@ -230,7 +260,18 @@ void CZonePlacer::assignZones(shared_ptr<CMapGenOptions> mapGenOptions)
total += tile; total += tile;
} }
int size = tiles.size(); int size = tiles.size();
assert (size);
zone.second->setPos (int3(total.x/size, total.y/size, total.z/size)); zone.second->setPos (int3(total.x/size, total.y/size, total.z/size));
//TODO: similiar for islands
if (zone.second->getPos().z)
{
zone.second->discardDistantTiles(gen, zone.second->getSize() + 1);
//make sure that terrain inside zone is not a rock
//FIXME: reorder actions?
zone.second->paintZoneTerrain (gen, ETerrainType::SUBTERRANEAN);
}
} }
logGlobal->infoStream() << "Finished zone colouring"; logGlobal->infoStream() << "Finished zone colouring";
} }