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)
{
//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
for(const auto & psetPair : sInfo.playerInfos)
{

View File

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

View File

@ -9,56 +9,402 @@
}
},
"altarOfSacrifice" : { "index" :2, "handler": "market", "types" : { "object" : { "index" : 0} } },
"tradingPost" : { "index" :221, "handler": "market", "types" : { "object" : { "index" : 0} } },
"tradingPostDUPLICATE" : { "index" :99, "handler": "market", "types" : { "object" : { "index" : 0} } },
"freelancersGuild" : { "index" :213, "handler": "market", "types" : { "object" : { "index" : 0} } },
"altarOfSacrifice" : {
"index" :2,
"handler" : "market",
"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} } },
"event" : { "index" :26, "handler": "event", "types" : { "object" : { "index" : 0} } },
"pandoraBox" : {
"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} } },
"pillarOfFire" : { "index" :60, "handler": "observatory", "types" : { "object" : { "index" : 0} } },
"coverOfDarkness" : { "index" :15, "handler": "observatory", "types" : { "object" : { "index" : 0} } },
"redwoodObservatory" : {
"index" :58,
"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" : {
"index" :103,
"handler": "teleport",
"handler" : "teleport",
"types" : {
"object" : { "index" : 0 },
"object" : {
"index" : 0 },
"objectWoG" : { "index" : 1 } // WoG object? Present on VCMI Test 2011b
}
},
"refugeeCamp" : { "index" :78, "handler": "dwelling", "types" : { "object" : { "index" : 0} } },
"warMachineFactory" : { "index" :106, "handler": "dwelling", "types" : { "object" : { "index" : 0} } },
"shrineOfMagicLevel1" : { "index" :88, "handler": "shrine", "types" : { "object" : { "index" : 0} } },
"shrineOfMagicLevel2" : { "index" :89, "handler": "shrine", "types" : { "object" : { "index" : 0} } },
"shrineOfMagicLevel3" : { "index" :90, "handler": "shrine", "types" : { "object" : { "index" : 0} } },
"eyeOfTheMagi" : { "index" :27, "handler": "magi", "types" : { "object" : { "index" : 0} } },
"hutOfTheMagi" : { "index" :37, "handler": "magi", "types" : { "object" : { "index" : 0} } },
"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} } },
"shipyard" : { "index" :87, "handler": "shipyard", "types" : { "object" : { "index" : 0} } },
"sign" : { "index" :91, "handler": "sign", "types" : { "object" : { "index" : 0} } },
"sirens" : { "index" :92, "handler": "siren", "types" : { "object" : { "index" : 0} } },
"denOfThieves" : { "index" :97, "handler": "denOfThieves", "types" : { "object" : { "index" : 0} } },
"university" : { "index" :104, "handler": "university", "types" : { "object" : { "index" : 0} } },
"witchHut" : { "index" :113, "handler": "witch", "types" : { "object" : { "index" : 0} } },
"questGuard" : { "index" :215, "handler": "questGuard", "types" : { "object" : { "index" : 0} } },
"refugeeCamp" : {
"index" :78,
"handler" : "dwelling",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 5000,
"rarity" : 20
}
}
}
},
"warMachineFactory" : {
"index" :106,
"handler" : "dwelling",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"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" : {
"index" :49,
"handler": "magicWell",
"handler" : "magicWell",
"types" : {
"object" : { "index" : 0},
"object" : {
"index" : 0,
"rmg" : {
"value" : 250,
"rarity" : 100
}
},
"objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Test 2011b
}
},
@ -99,6 +445,10 @@
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 2000,
"rarity" : 150
},
"templates" : {
"normal" : { "animation" : "AVArnd1", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
@ -111,6 +461,10 @@
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 5000,
"rarity" : 150
},
"templates" : {
"normal" : { "animation" : "AVArnd2", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
@ -123,6 +477,10 @@
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 10000,
"rarity" : 150
},
"templates" : {
"normal" : { "animation" : "AVArnd3", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
@ -135,6 +493,10 @@
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"value" : 20000,
"rarity" : 150
},
"templates" : {
"normal" : { "animation" : "AVArnd4", "visitableFrom" : [ "+++", "+-+", "+++" ], "mask" : [ "VV", "VA"] }
}
@ -240,10 +602,58 @@
},
/// Classes without dedicated object
"hillFort" : { "index" :35, "handler": "generic", "types" : { "object" : { "index" : 0} } },
"grail" : { "index" :36, "handler": "generic", "types" : { "object" : { "index" : 0} } },
"tavern" : { "index" :95, "handler": "generic", "types" : { "object" : { "index" : 0} } },
"sanctuary" : { "index" :80, "handler": "generic", "types" : { "object" : { "index" : 0} } },
"hillFort" : {
"index" :35,
"handler": "generic",
"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
"cursedGround" : { "index" :21, "handler": "generic", "types" : { "object" : { "index" : 0} } },

View File

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

View File

@ -1,51 +1,496 @@
{
/// These are objects that covered by concept of "configurable object"
/// Most or even all of their configuration located in this file
"magicSpring" : { "index" :48, "handler": "magicSpring", "types" : { "object" : { "index" : 0} } },
"mysticalGarden" : { "index" :55, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
"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",
"magicSpring" : {//magic source
"index" : 48,
"handler": "magicSpring",
"types" : {
"object" : { "index" : 0},
"objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Tests 2011
"object" : {
"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} } },
"swanPond" : { "index" :14, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"faerieRing" : { "index" :28, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"fountainOfFortune" : { "index" :30, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"fountainOfYouth" : { "index" :31, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"idolOfFortune" : { "index" :38, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"mermaids" : { "index" :52, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"oasis" : { "index" :56, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"stables" : { "index" :94, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"temple" : { "index" :96, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"rallyFlag" : { "index" :64, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
"wateringHole" : { "index" :110, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }
"mysticalGarden" : {
"index" : 55,
"handler": "oncePerWeek",
"types" : {
"object" : {
"index" : 0,
"rmg" : {
"mapLimit" : 32,
"value" : 500,
"rarity" : 50
}
}
}
},
"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" :
{
"minSize" : "m", "maxSize" : "m",
"minSize" : "m", "maxSize" : "m+u",
"players" : "4",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 1, "owner" : 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},
@ -19,7 +19,7 @@
},
"2" :
{
"type" : "playerStart", "size" : 1, "owner" : 2,
"type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
@ -27,7 +27,7 @@
},
"3" :
{
"type" : "playerStart", "size" : 1, "owner" : 3,
"type" : "playerStart", "size" : 2, "owner" : 3,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
@ -35,7 +35,7 @@
},
"4" :
{
"type" : "playerStart", "size" : 1, "owner" : 4,
"type" : "playerStart", "size" : 2, "owner" : 4,
"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
"monsters" : "normal",
"minesLikeZone" : 1,
@ -43,7 +43,7 @@
},
"5" :
{
"type" : "treasure", "size" : 2, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
"type" : "treasure", "size" : 3, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
"neutralTowns" : { "castles" : 1 },
"monsters" : "strong",
"mines" : {"gold" : 2},
@ -63,13 +63,13 @@
},
"Upgrade" :
{
"minSize" : "s", "maxSize" : "m",
"minSize" : "s+u", "maxSize" : "m",
"players" : "2",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 1, "owner" : 1,
"type" : "playerStart", "size" : 3, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1},
@ -80,7 +80,7 @@
},
"2" :
{
"type" : "playerStart", "size" : 1, "owner" : 2,
"type" : "playerStart", "size" : 3, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
@ -88,7 +88,7 @@
},
"3" :
{
"type" : "treasure", "size" : 2, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 1,
"type" : "treasure", "size" : 4, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 1,
"monsters" : "weak",
"mines" : {"gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1, "gold" : 1},
"treasure" : [
@ -98,14 +98,14 @@
},
"4" :
{
"type" : "treasure", "size" : 2, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 2,
"type" : "treasure", "size" : 4, "neutralTowns" : { "towns" : 1 }, "townTypeLikeZone" : 2,
"monsters" : "weak",
"minesLikeZone" : 3,
"treasureLikeZone" : 3
},
"5" :
{
"type" : "treasure", "size" : 3, "neutralTowns" : { "castles" : 1 }, "terrainTypes" : [ "sand" ],
"type" : "treasure", "size" : 5, "neutralTowns" : { "castles" : 1 }, "terrainTypes" : [ "sand" ],
"monsters" : "strong",
"mines" : {"gold" : 2},
"treasure" : [
@ -126,13 +126,13 @@
},
"Golden Ring" :
{
"minSize" : "m", "maxSize" : "l",
"minSize" : "m+u", "maxSize" : "l",
"players" : "3",
"zones" :
{
"1" :
{
"type" : "playerStart", "size" : 3, "owner" : 1,
"type" : "playerStart", "size" : 2, "owner" : 1,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"mines" : {"wood" : 1, "ore" : 1},
@ -143,7 +143,7 @@
},
"2" :
{
"type" : "playerStart", "size" : 3, "owner" : 2,
"type" : "playerStart", "size" : 2, "owner" : 2,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
@ -151,7 +151,7 @@
},
"3" :
{
"type" : "playerStart", "size" : 3, "owner" : 3,
"type" : "playerStart", "size" : 2, "owner" : 3,
"playerTowns" : { "castles" : 1 },
"monsters" : "normal",
"minesLikeZone" : 1,
@ -243,7 +243,7 @@
},
"Jebus Cross":
{
"minSize" : "l", "maxSize" : "xl",
"minSize" : "l+u", "maxSize" : "xl+u",
"players" : "4",
"zones":
{

View File

@ -117,7 +117,7 @@ namespace RandomGeneratorUtil
int n = (container.end() - container.begin());
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
{
for(int y = 0; y < appearance.getHeight(); y++)
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);
return appearance.getVisitableOffset();
}
void CGObjectInstance::giveDummyBonus(ObjectInstanceID heroID, ui8 duration) const

View File

@ -218,6 +218,17 @@ bool CDwellingInstanceConstructor::producesCreature(const CCreature * crea) cons
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()
{
}

View File

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

View File

@ -871,6 +871,12 @@ void CGArtifact::initObj()
blockVisit = true;
if(ID == Obj::ARTIFACT)
{
if (!storedArtifact)
{
auto a = new CArtifactInstance();
cb->gameState()->map->addNewArtifactInstance(a);
storedArtifact = a;
}
if(!storedArtifact->artType)
storedArtifact->setType(VLC->arth->artifacts[subID]);
}
@ -963,6 +969,11 @@ void CGArtifact::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
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());
}

View File

@ -158,6 +158,8 @@ public:
CArtifactInstance *storedArtifact;
std::string message;
CGArtifact() : CArmedInstance() {storedArtifact = nullptr;};
void onHeroVisit(const CGHeroInstance * h) const override;
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) 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
return true;
@ -106,7 +106,7 @@ void ObjectTemplate::readTxt(CLegacyConfigParser & parser)
int type = boost::lexical_cast<int>(strings[7]);
printPriority = boost::lexical_cast<int>(strings[8]) * 100; // to have some space in future
if (isVisitableFromTop(id, type))
if (isOnVisitableFromTopList(id, type))
visitDir = 0xff;
else
visitDir = (8|16|32|64|128);
@ -168,7 +168,7 @@ void ObjectTemplate::readMap(CBinaryReader & reader)
int type = reader.readUInt8();
printPriority = reader.readUInt8() * 100; // to have some space in future
if (isVisitableFromTop(id, type))
if (isOnVisitableFromTopList(id, type))
visitDir = 0xff;
else
visitDir = (8|16|32|64|128);
@ -354,6 +354,24 @@ bool ObjectTemplate::isVisitableFrom(si8 X, si8 Y) const
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
{
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
bool isVisitableFrom(si8 X, si8 Y) const;
int3 getVisitableOffset() const;
bool isVisitableFromTop() const;
// Checks if object can be placed on specific terrain
bool canBePlacedAt(ETerrainType terrain) const;
@ -73,6 +75,8 @@ public:
void readMap(CBinaryReader & reader);
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)
{
h & usedTiles & allowedTerrains & animationFile & stringID;

View File

@ -175,14 +175,11 @@ const std::map<std::string, CRmgTemplate *> & CMapGenOptions::getAvailableTempla
return VLC->tplh->getTemplates();
}
void CMapGenOptions::finalize()
{
CRandomGenerator rand;
finalize(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)
{
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
/// a random number generator by keeping the options in a valid state. Check options should return true, otherwise
/// this function fails.
void finalize();
void finalize(CRandomGenerator & rand);
/// 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 "CRmgTemplateZone.h"
#include "CZonePlacer.h"
#include "../mapObjects/CObjectClassesHandler.h"
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)*/) :
mapGenOptions(mapGenOptions), randomSeed(RandomSeed), monolithIndex(0)
mapGenOptions(mapGenOptions), randomSeed(RandomSeed), monolithIndex(0), zonesTotal(0)
{
rand.setSeed(randomSeed);
}
@ -215,9 +216,9 @@ void CMapGenerator::fillZones()
logGlobal->infoStream() << "Started filling zones";
createConnections();
//make sure all connections are passable before creating borders
for (auto it : zones)
{
//make sure all connections are passable before creating borders
it.second->createBorder(this);
it.second->fill(this);
}
@ -239,25 +240,96 @@ void CMapGenerator::createConnections()
int3 guardPos(-1,-1,-1);
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))
guardPos = tile;
});
if (guardPos.valid())
{
setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template
//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
zoneB->crunchPath (this, guardPos, zoneB->getPos(), zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center
break; //we're done with this connection
if (isBlocked(tile)) //tiles may be occupied by subterranean gates already placed
continue;
foreach_neighbour (tile, [&guardPos, tile, &otherZoneTiles, this](int3 &pos)
{
//if (vstd::contains(otherZoneTiles, pos) && !this->isBlocked(pos))
if (vstd::contains(otherZoneTiles, pos))
guardPos = tile;
});
if (guardPos.valid())
{
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())
{
auto teleport1 = new CGTeleport;
@ -299,28 +371,35 @@ bool CMapGenerator::isBlocked(const int3 &tile) const
bool CMapGenerator::shouldBeBlocked(const int3 &tile) const
{
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();
}
bool CMapGenerator::isPossible(const int3 &tile) const
{
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();
}
bool CMapGenerator::isFree(const int3 &tile) const
{
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();
}
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)
{
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);
}
@ -328,7 +407,7 @@ void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
CTileInfo CMapGenerator::getTile(const int3& tile) const
{
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];
}
@ -336,7 +415,7 @@ CTileInfo CMapGenerator::getTile(const int3& tile) const
void CMapGenerator::setNearestObjectDistance(int3 &tile, int value)
{
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);
}
@ -344,12 +423,29 @@ void CMapGenerator::setNearestObjectDistance(int3 &tile, int value)
int CMapGenerator::getNearestObjectDistance(const int3 &tile) const
{
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();
}
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 isPossible(const int3 &tile) const;
bool isFree(const int3 &tile) const;
bool isUsed(const int3 &tile) const;
void setOccupied(const int3 &tile, ETileType::ETileType state);
CTileInfo getTile(const int3 & tile) const;
@ -77,9 +78,14 @@ public:
void setNearestObjectDistance(int3 &tile, int value);
int getNextMonlithIndex();
void registerZone (TFaction faction);
ui32 getZoneCount(TFaction faction);
ui32 getTotalZoneCount() const;
private:
std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;
std::map<TFaction, ui32> zonesPerFaction;
ui32 zonesTotal; //zones that have their main town only
CTileInfo*** tiles;

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@
#include "float3.h"
#include "../int3.h"
#include "../ResourceSet.h" //for TResource (?)
#include "../mapObjects/ObjectTemplate.h"
class CMapGenerator;
class CTileInfo;
@ -45,6 +46,7 @@ public:
bool shouldBeBlocked() const;
bool isPossible() const;
bool isFree() const;
bool isUsed() const;
void setOccupied(ETileType::ETileType value);
ETerrainType getTerrainType() const;
void setTerrainType(ETerrainType value);
@ -66,9 +68,25 @@ public:
struct DLL_LINKAGE ObjectInfo
{
ObjectTemplate templ;
ui32 value;
ui16 probability;
ui32 maxPerZone;
ui32 maxPerMap;
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.
@ -128,13 +146,15 @@ public:
void addTile (const int3 &pos);
std::set<int3> getTileInfo () const;
void discardDistantTiles (CMapGenerator* gen, float distance);
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 fill (CMapGenerator* gen);
bool placeMines (CMapGenerator* gen);
void initTownType (CMapGenerator* gen);
void paintZoneTerrain (CMapGenerator* gen, ETerrainType terrainType);
void initTerrainType (CMapGenerator* gen);
void createBorder(CMapGenerator* gen);
void fractalize(CMapGenerator* gen);
@ -152,7 +172,9 @@ public:
std::vector<CTreasureInfo> getTreasureInfo();
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:
//template info
@ -189,10 +211,11 @@ private:
bool pointIsIn(int x, int y);
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 findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dist, int3 &pos);
bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos);
void checkAndPlaceObject(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
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;
logGlobal->infoStream() << "Starting zone placement";
@ -52,8 +53,7 @@ void CZonePlacer::placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGe
int height = mapGenOptions->getHeight();
auto zones = gen->getZones();
//TODO: consider underground zones
bool underground = mapGenOptions->getHasTwoLevels();
/*
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))
*/
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;
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());
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
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 mapSize = sqrt (width * height);
for (auto zone : zones)
@ -95,63 +119,66 @@ void CZonePlacer::placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGe
for (auto con : zone.second->getConnections())
{
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
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
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;
float distance = pos.dist2d (otherZone.second->getCenter());
float distance = pos.dist2d (otherZoneCenter);
float minDistance = (zone.second->getSize() + otherZone.second->getSize())/mapSize;
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
float3 boundary(0,0,pos.z);
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)
{
boundary = float3 (0, pos.y, pos.z);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance); //negative value
pushAwayFromBoundary(0, pos.y);
}
if (pos.x > 1-size)
{
boundary = float3 (1, pos.y, pos.z);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance); //negative value
pushAwayFromBoundary(1, pos.y);
}
if (pos.y < size)
{
boundary = float3 (pos.x, 0, pos.z);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance); //negative value
pushAwayFromBoundary(pos.x, 0);
}
if (pos.y > 1-size)
{
boundary = float3 (pos.x, 1, pos.z);
float distance = pos.dist2d(boundary);
forceVector -= (boundary - pos) / getDistance(distance); //negative value
pushAwayFromBoundary(pos.x, 1);
}
forces[zone.second] = forceVector;
forceVector.z = 0; //operator - doesn't preserve z coordinate :/
forces[zone.second] = forceVector * temperatureConstant;
}
//update positions
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
{
@ -213,7 +240,10 @@ void CZonePlacer::assignZones(shared_ptr<CMapGenOptions> mapGenOptions)
int3 pos(i, j, k);
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);
distances.front().first->addTile(pos); //closest tile belongs to zone
@ -230,7 +260,18 @@ void CZonePlacer::assignZones(shared_ptr<CMapGenOptions> mapGenOptions)
total += tile;
}
int size = tiles.size();
assert (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";
}