mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Merge pull request #30 from vcmi/RMG
Since there are no objections, I finally merge this branch.
This commit is contained in:
commit
a842068d54
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"textData" :
|
|
||||||
{
|
|
||||||
"heroClass" : 18,
|
|
||||||
"artifact" : 171,
|
|
||||||
"creature" : 197,
|
|
||||||
"faction" : 9,
|
|
||||||
"hero" : 156,
|
|
||||||
"mapVersion" : 51 // WoG
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"]
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
@ -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" ]] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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"
|
|
||||||
}
|
|
@ -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"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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,
|
||||||
@ -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,
|
||||||
|
@ -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} } },
|
||||||
|
@ -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" : {
|
||||||
|
@ -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,
|
||||||
|
"handler": "magicSpring",
|
||||||
|
"types" : {
|
||||||
|
"object" : {
|
||||||
|
"index" : 0//,
|
||||||
|
//"rmg" : {
|
||||||
|
// "zoneLimit" : 1,
|
||||||
|
// "mapLimit" : 32,
|
||||||
|
// "value" : 500,
|
||||||
|
// "rarity" : 50
|
||||||
|
//}
|
||||||
|
//banned due to problems with 2 viistable offsets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
"mysticalGarden" : { "index" :55, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
|
"mysticalGarden" : {
|
||||||
"windmill" : { "index" :112, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
|
"index" : 55,
|
||||||
"waterWheel" : { "index" :109, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
|
"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} } },
|
"leanTo" :{
|
||||||
"corpse" : { "index" :22, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
|
"index" : 39,
|
||||||
"wagon" : { "index" :105, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
|
"handler": "onceVisitable",
|
||||||
"warriorTomb" : { "index" :108, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
|
"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} } },
|
"campfire" :{
|
||||||
"flotsam" : { "index" :29, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
|
"index" : 12,
|
||||||
"seaChest" : { "index" :82, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
|
"handler": "pickable",
|
||||||
"shipwreckSurvivor" : { "index" :86, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
|
"types" : {
|
||||||
"treasureChest" : { "index" :101, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
|
"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} } },
|
"arena" : {
|
||||||
"marlettoTower" : { "index" :23, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
|
"index" : 4,
|
||||||
"gardenOfRevelation" : { "index" :32, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
|
"handler": "oncePerHero",
|
||||||
"libraryOfEnlightenment" : { "index" :41, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
|
"types" : {
|
||||||
"mercenaryCamp" : { "index" :51, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
|
"object" : {
|
||||||
"starAxis" : { "index" :61, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
|
"index" : 0,
|
||||||
"treeOfKnowledge" : { "index" :102, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
|
"rmg" : {
|
||||||
"schoolOfMagic" : { "index" :47, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
|
"mapLimit" : 32,
|
||||||
"schoolOfWar" : { "index" :107, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
|
"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" : {
|
"learningStone" : {
|
||||||
"index" : 100,
|
"index" : 100,
|
||||||
"handler": "oncePerHero",
|
"handler": "oncePerHero",
|
||||||
"types" : {
|
"types" : {
|
||||||
"object" : { "index" : 0},
|
"object" : {
|
||||||
|
"index" : 0,
|
||||||
|
"rmg" : {
|
||||||
|
"mapLimit" : 32,
|
||||||
|
"value" : 1500,
|
||||||
|
"rarity" : 200
|
||||||
|
}
|
||||||
|
},
|
||||||
"objectWoG" : { "index" : 1 } // WoG object? Present on VCMI_Tests 2011
|
"objectWoG" : { "index" : 1 } // WoG object? Present on VCMI_Tests 2011
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"buoy" : { "index" :11, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
|
"buoy" : {
|
||||||
"swanPond" : { "index" :14, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
|
"index" : 11,
|
||||||
"faerieRing" : { "index" :28, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
|
"handler": "bonusingObject",
|
||||||
"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} } },
|
"value" : 100,
|
||||||
"stables" : { "index" :94, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
|
"rarity" : 100
|
||||||
"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} } }
|
}
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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":
|
||||||
{
|
{
|
||||||
|
@ -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)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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();
|
|
||||||
|
|
||||||
|
int3 posA = zoneA->getPos();
|
||||||
|
int3 posB = zoneB->getPos();
|
||||||
|
|
||||||
|
if (posA.z == posB.z)
|
||||||
|
{
|
||||||
for (auto tile : tiles)
|
for (auto tile : tiles)
|
||||||
{
|
{
|
||||||
foreach_neighbour (tile, [&guardPos, tile, &otherZoneTiles](int3 &pos)
|
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))
|
if (vstd::contains(otherZoneTiles, pos))
|
||||||
guardPos = tile;
|
guardPos = tile;
|
||||||
});
|
});
|
||||||
if (guardPos.valid())
|
if (guardPos.valid())
|
||||||
{
|
{
|
||||||
setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
|
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
|
zoneA->addMonster (this, guardPos, connection.getGuardStrength(), false, true);
|
||||||
//zones can make paths only in their own area
|
//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
|
zoneA->crunchPath (this, guardPos, posA, 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
|
zoneB->crunchPath (this, guardPos, posB, zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center
|
||||||
break; //we're done with this connection
|
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;
|
||||||
@ -317,6 +389,13 @@ bool CMapGenerator::isFree(const int3 &tile) const
|
|||||||
|
|
||||||
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))
|
||||||
@ -351,5 +430,22 @@ int CMapGenerator::getNearestObjectDistance(const int3 &tile) const
|
|||||||
|
|
||||||
int CMapGenerator::getNextMonlithIndex()
|
int CMapGenerator::getNextMonlithIndex()
|
||||||
{
|
{
|
||||||
|
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++;
|
return monolithIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMapGenerator::registerZone (TFaction faction)
|
||||||
|
{
|
||||||
|
zonesPerFaction[faction]++;
|
||||||
|
zonesTotal++;
|
||||||
|
}
|
||||||
|
ui32 CMapGenerator::getZoneCount(TFaction faction)
|
||||||
|
{
|
||||||
|
return zonesPerFaction[faction];
|
||||||
|
}
|
||||||
|
ui32 CMapGenerator::getTotalZoneCount() const
|
||||||
|
{
|
||||||
|
return zonesTotal;
|
||||||
|
}
|
||||||
|
@ -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
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
if (zone.second->getPos().z == k)
|
||||||
distances.push_back (std::make_pair(zone.second, metric(pos, zone.second->getPos())));
|
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";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user