mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Banks now use new scheme as well
- Implemented Bank Constructor object. - Merged Pyramid object into common Bank class. Banks can now grant spells as part of their reward. - Move bank config code to config/objects/creatureBanks.json. Note: WoG banks are not updated yet, should be moved to WoG mod. - Updated AI code so it can correctly evaluate bank danger (should be generic enough for use with other objects) - New files JsonRandom.* that contain routines for loading random objects from Json (still WiP but should be stable)
This commit is contained in:
parent
0a71e89f58
commit
ab475195ac
@ -5,6 +5,7 @@
|
||||
#include "../../lib/UnlockGuard.h"
|
||||
#include "../../lib/CConfigHandler.h"
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/mapObjects/CBank.h"
|
||||
|
||||
/*
|
||||
* AIUtility.cpp, part of VCMI engine
|
||||
@ -302,11 +303,11 @@ ui64 evaluateDanger(const CGObjectInstance *obj)
|
||||
case Obj::SHIPWRECK: //shipwreck
|
||||
case Obj::DERELICT_SHIP: //derelict ship
|
||||
// case Obj::PYRAMID:
|
||||
return fh->estimateBankDanger (VLC->objh->bankObjToIndex(obj));
|
||||
return fh->estimateBankDanger (dynamic_cast<const CBank *>(obj));
|
||||
case Obj::PYRAMID:
|
||||
{
|
||||
if(obj->subID == 0)
|
||||
return fh->estimateBankDanger (VLC->objh->bankObjToIndex(obj));
|
||||
return fh->estimateBankDanger (dynamic_cast<const CBank *>(obj));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <limits>
|
||||
|
||||
#include "../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../lib/mapObjects/CommonConstructors.h"
|
||||
#include "../../lib/CCreatureHandler.h"
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../CCallback.h"
|
||||
@ -41,16 +42,6 @@ struct armyStructure
|
||||
ui32 maxSpeed;
|
||||
};
|
||||
|
||||
ui64 evaluateBankConfig (BankConfig * bc)
|
||||
{
|
||||
ui64 danger = 0;
|
||||
for (auto opt : bc->guards)
|
||||
{
|
||||
danger += VLC->creh->creatures[opt.first]->fightValue * opt.second;
|
||||
}
|
||||
return danger;
|
||||
}
|
||||
|
||||
armyStructure evaluateArmyStructure (const CArmedInstance * army)
|
||||
{
|
||||
ui64 totalStrenght = army->getArmyStrength();
|
||||
@ -208,42 +199,26 @@ void FuzzyHelper::initTacticalAdvantage()
|
||||
}
|
||||
}
|
||||
|
||||
ui64 FuzzyHelper::estimateBankDanger (int ID)
|
||||
ui64 FuzzyHelper::estimateBankDanger (const CBank * bank)
|
||||
{
|
||||
std::vector <ConstTransitivePtr<BankConfig>> & configs = VLC->objh->banksInfo[ID];
|
||||
auto info = VLC->objtypeh->getHandlerFor(bank->ID, bank->subID)->getObjectInfo(bank->appearance);
|
||||
|
||||
ui64 val = std::numeric_limits<ui64>::max();
|
||||
try
|
||||
{
|
||||
switch (configs.size())
|
||||
{
|
||||
case 4:
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
int bankVal = evaluateBankConfig (VLC->objh->banksInfo[ID][i]);
|
||||
bankDanger->term("Bank" + boost::lexical_cast<std::string>(i))->setMinimum(bankVal * 0.5f);
|
||||
bankDanger->term("Bank" + boost::lexical_cast<std::string>(i))->setMaximum(bankVal * 1.5f);
|
||||
}
|
||||
//comparison purposes
|
||||
//int averageValue = (evaluateBankConfig (VLC->objh->banksInfo[ID][0]) + evaluateBankConfig (VLC->objh->banksInfo[ID][3])) * 0.5;
|
||||
//dynamic_cast<fl::SingletonTerm*>(bankInput->term("SET"))->setValue(0.5);
|
||||
bankInput->setInput (0.5);
|
||||
engine.process (BANK_DANGER);
|
||||
//engine.process();
|
||||
val = bankDanger->output().defuzzify(); //some expected value of this bank
|
||||
}
|
||||
catch (fl::FuzzyException & fe)
|
||||
{
|
||||
logAi->errorStream() << fe.name() << ": " << fe.message();
|
||||
}
|
||||
break;
|
||||
case 1: //rare case - Pyramid
|
||||
val = evaluateBankConfig (VLC->objh->banksInfo[ID][0]);
|
||||
break;
|
||||
default:
|
||||
logAi->warnStream() << ("Uhnandled bank config!");
|
||||
}
|
||||
bankDanger->term("Bank0")->setMinimum(info->minGuards().totalStrength * 0.5f);
|
||||
bankDanger->term("Bank0")->setMaximum(info->minGuards().totalStrength * 1.5f);
|
||||
|
||||
bankDanger->term("Bank1")->setMinimum(info->maxGuards().totalStrength * 0.5f);
|
||||
bankDanger->term("Bank1")->setMaximum(info->maxGuards().totalStrength * 1.5f);
|
||||
|
||||
//comparison purposes
|
||||
//int averageValue = (evaluateBankConfig (VLC->objh->banksInfo[ID][0]) + evaluateBankConfig (VLC->objh->banksInfo[ID][3])) * 0.5;
|
||||
//dynamic_cast<fl::SingletonTerm*>(bankInput->term("SET"))->setValue(0.5);
|
||||
bankInput->setInput (0.5);
|
||||
engine.process (BANK_DANGER);
|
||||
//engine.process();
|
||||
val = bankDanger->output().defuzzify(); //some expected value of this bank
|
||||
}
|
||||
catch (fl::FuzzyException & fe)
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
class VCAI;
|
||||
class CArmedInstance;
|
||||
class CBank;
|
||||
|
||||
class FuzzyHelper
|
||||
{
|
||||
@ -72,7 +73,7 @@ public:
|
||||
float evaluate (Goals::AbstractGoal & g);
|
||||
void setPriority (Goals::TSubgoal & g);
|
||||
|
||||
ui64 estimateBankDanger (int ID);
|
||||
ui64 estimateBankDanger (const CBank * bank);
|
||||
float getTacticalAdvantage (const CArmedInstance *we, const CArmedInstance *enemy); //returns factor how many times enemy is stronger than us
|
||||
|
||||
Goals::TSubgoal chooseSolution (Goals::TGoalVec vec);
|
||||
|
@ -1,675 +1,9 @@
|
||||
//Resources: Wood, Mercury, Ore, Sulfur, Crystal, Gems, Gold
|
||||
//Artifacts: Treasure, Minor, Major, Relic
|
||||
//NOTE: all H3M banks were moved to objects/creatureBanks.json
|
||||
//Remaining part should be moved to WoG mod
|
||||
{
|
||||
"banks": [
|
||||
{
|
||||
"name" : "Cyclops Stockpile",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 94 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 506,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 4,
|
||||
"mercury" : 4,
|
||||
"ore" : 4,
|
||||
"sulfur" : 4,
|
||||
"crystal" : 4,
|
||||
"gems" : 4,
|
||||
"gold" : 0
|
||||
},
|
||||
"value": 10000,
|
||||
"profitability": 20,
|
||||
"easiest": 100
|
||||
},
|
||||
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 94 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 760,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 6,
|
||||
"mercury" : 6,
|
||||
"ore" : 6,
|
||||
"sulfur" : 6,
|
||||
"crystal" : 6,
|
||||
"gems" : 6
|
||||
},
|
||||
"value": 15000,
|
||||
"profitability": 20,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 40, "id": 94 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1013,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 8,
|
||||
"mercury" : 8,
|
||||
"ore" : 8,
|
||||
"sulfur" : 8,
|
||||
"crystal" : 8,
|
||||
"gems" : 8
|
||||
},
|
||||
"value": 20000,
|
||||
"profitability": 20,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 50, "id": 94 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1266,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 10,
|
||||
"mercury" : 10,
|
||||
"ore" : 10,
|
||||
"sulfur" : 10,
|
||||
"crystal" : 10,
|
||||
"gems" : 10
|
||||
},
|
||||
"value": 25000,
|
||||
"profitability": 20,
|
||||
"easiest": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Dwarven Treasury",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 50, "id": 16 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 194,
|
||||
"reward_resources":
|
||||
{
|
||||
"crystal" : 2,
|
||||
"gold" : 2500
|
||||
},
|
||||
"value": 3500,
|
||||
"profitability": 18,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 75, "id": 16 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 291,
|
||||
"reward_resources":
|
||||
{
|
||||
"crystal" : 3,
|
||||
"gold" : 4000
|
||||
},
|
||||
"value": 5500,
|
||||
"profitability": 19,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 100, "id": 16 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 388,
|
||||
"reward_resources":
|
||||
{
|
||||
"crystal" : 5,
|
||||
"gold" : 5000
|
||||
},
|
||||
"value": 7500,
|
||||
"profitability": 19,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 150, "id": 16 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 582,
|
||||
"reward_resources":
|
||||
{
|
||||
"crystal" : 10,
|
||||
"gold" : 7500
|
||||
},
|
||||
"value": 12500,
|
||||
"profitability": 21,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Griffin Conservatory",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 50, "id": 4 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 351,
|
||||
"reward_creatures": [ { "number": 1, "id": 12 } ],
|
||||
"value": 3000,
|
||||
"profitability": 9,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 100, "id": 4 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 702,
|
||||
"reward_creatures": [ { "number": 2, "id": 12 } ],
|
||||
"value": 6000,
|
||||
"profitability": 9,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 150, "id": 4 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1053,
|
||||
"reward_creatures": [ { "number": 3, "id": 12 } ],
|
||||
"value": 9000,
|
||||
"profitability": 9,
|
||||
"easiest": 300
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 200, "id": 4 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1404,
|
||||
"reward_creatures": [ { "number": 4, "id": 12 } ],
|
||||
"value": 12000,
|
||||
"profitability": 9,
|
||||
"easiest": 400
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Imp Cache",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 100, "id": 42 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 100,
|
||||
"reward_resources":
|
||||
{
|
||||
"wood" : 0,
|
||||
"mercury" : 2,
|
||||
"ore" : 0,
|
||||
"sulfur" : 0,
|
||||
"crystal" : 0,
|
||||
"gems" : 0,
|
||||
"gold" : 1000
|
||||
},
|
||||
"value": 2000,
|
||||
"profitability": 20,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 150, "id": 42 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 150,
|
||||
"reward_resources":
|
||||
{
|
||||
"mercury" : 3,
|
||||
"gold" : 1500
|
||||
},
|
||||
"value": 3000,
|
||||
"profitability": 20,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 200, "id": 42 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 200,
|
||||
"reward_resources":
|
||||
{
|
||||
"mercury" : 4,
|
||||
"gold" : 2000
|
||||
},
|
||||
"value": 4000,
|
||||
"profitability": 20,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 300, "id": 42 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 300,
|
||||
"reward_resources":
|
||||
{
|
||||
"mercury" : 6,
|
||||
"gold" : 3000
|
||||
},
|
||||
"value": 6000,
|
||||
"profitability": 20,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Medusa Stores",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 76 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 207,
|
||||
"reward_resources":
|
||||
{
|
||||
"sulfur" : 5,
|
||||
"gold" : 2000
|
||||
},
|
||||
"value": 4500,
|
||||
"profitability": 22,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 76 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 310,
|
||||
"reward_resources":
|
||||
{
|
||||
"sulfur" : 6,
|
||||
"gold" : 3000
|
||||
},
|
||||
"value": 6000,
|
||||
"profitability": 19,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 40, "id": 76 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 414,
|
||||
"reward_resources":
|
||||
{
|
||||
"sulfur" : 8,
|
||||
"gold" : 4000
|
||||
},
|
||||
"value": 8000,
|
||||
"profitability": 19,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 50, "id": 76 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 517,
|
||||
"reward_resources":
|
||||
{
|
||||
"sulfur" : 10,
|
||||
"gold" : 5000
|
||||
},
|
||||
"value": 10000,
|
||||
"profitability": 19,
|
||||
"easiest": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Naga Bank",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 10, "id": 38 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 403,
|
||||
"reward_resources":
|
||||
{
|
||||
"gems" : 8,
|
||||
"gold" : 4000
|
||||
},
|
||||
"value": 8000,
|
||||
"profitability": 20,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 15, "id": 38 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 605,
|
||||
"reward_resources":
|
||||
{
|
||||
"gems" : 12,
|
||||
"gold" : 6000
|
||||
},
|
||||
"value": 12000,
|
||||
"profitability": 20,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 38 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 806,
|
||||
"reward_resources":
|
||||
{
|
||||
"gems" : 16,
|
||||
"gold" : 8000
|
||||
},
|
||||
"value": 16000,
|
||||
"profitability": 20,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 30, "id": 38 } ],
|
||||
"upgrade_chance": 50,
|
||||
"combat_value": 1210,
|
||||
"reward_resources":
|
||||
{
|
||||
"gems" : 24,
|
||||
"gold" : 12000
|
||||
},
|
||||
"value": 24000,
|
||||
"profitability": 20,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Dragon Fly Hive",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 105} ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 154,
|
||||
"reward_creatures": [ { "number": 4, "id": 108 } ],
|
||||
"value": 3200,
|
||||
"profitability": 21,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 45, "id": 105 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 230,
|
||||
"reward_creatures": [ { "number": 6, "id": 108 } ],
|
||||
"value": 4800,
|
||||
"profitability": 21,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 60, "id": 105 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 307,
|
||||
"reward_creatures": [ { "number": 8, "id": 108 } ],
|
||||
"value": 6400,
|
||||
"profitability": 21,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 90, "id": 105 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 461,
|
||||
"reward_creatures": [ { "number": 12, "id": 108 } ],
|
||||
"value": 9600,
|
||||
"profitability": 21,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Shipwreck",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 10, "id": 60 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 31,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 2000
|
||||
},
|
||||
"value": 2000,
|
||||
"profitability": 65,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 15, "id": 60 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 46,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
},
|
||||
"value": 3000,
|
||||
"profitability": 65,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 25, "id": 60 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 77,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 4000
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 5000,
|
||||
"profitability": 65,
|
||||
"easiest": 250
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 50, "id": 60 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 154,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 5000
|
||||
},
|
||||
"reward_artifacts": [ 0, 1, 0, 0 ],
|
||||
"value": 7000,
|
||||
"profitability": 45,
|
||||
"easiest": 500
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Derelict Ship",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 115 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 138,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
},
|
||||
"value": 3000,
|
||||
"profitability": 22,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 115 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 207,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 4000,
|
||||
"profitability": 19,
|
||||
"easiest": 150
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 40, "id": 115 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 276,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 4000
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 5000,
|
||||
"profitability": 18,
|
||||
"easiest": 200
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 60, "id": 115 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 414,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 6000
|
||||
},
|
||||
"reward_artifacts": [ 0, 1, 0, 0 ],
|
||||
"value": 8000,
|
||||
"profitability": 19,
|
||||
"easiest": 300
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Crypt",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 30, "id": 56 }, { "number": 20, "id": 58 }, { "number": 0, "id": 60 } , { "number": 0, "id": 62 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 75,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 1500
|
||||
},
|
||||
"value": 1500,
|
||||
"profitability": 20,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 25, "id": 56 }, { "number": 20, "id": 58 }, { "number": 5, "id": 60 }, { "number": 0, "id": 62 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 94,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 2000
|
||||
},
|
||||
"value": 2000,
|
||||
"profitability": 21,
|
||||
"easiest": 126
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 20, "id": 56 }, { "number": 20, "id": 58 }, { "number": 10, "id": 60 }, { "number": 5, "id": 62 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 169,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 2500
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 3500,
|
||||
"profitability": 21,
|
||||
"easiest": 225
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 20, "id": 56 }, { "number": 20, "id": 58 }, { "number": 10, "id": 60 }, { "number": 10, "id": 62 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 225,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 5000
|
||||
},
|
||||
"reward_artifacts": [ 1, 0, 0, 0 ],
|
||||
"value": 6000,
|
||||
"profitability": 27,
|
||||
"easiest": 299
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Dragon Utopia",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 8, "id": 26 }, { "number": 5, "id": 82 }, { "number": 2, "id": 27 }, { "number": 1, "id": 83 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 769,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 20000
|
||||
},
|
||||
"reward_artifacts": [ 1, 1, 1, 1 ],
|
||||
"value": 38000,
|
||||
"profitability": 21,
|
||||
"easiest": 100
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 8, "id": 26 }, { "number": 6, "id": 82 }, { "number": 3, "id": 27 }, { "number": 2, "id": 83 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 209,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 30000
|
||||
},
|
||||
"reward_artifacts": [ 0, 1, 1, 2 ],
|
||||
"value": 57000,
|
||||
"profitability": 26,
|
||||
"easiest": 125
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [ { "number": 8, "id": 26 }, { "number": 6, "id": 82 }, { "number": 4, "id": 27 }, { "number": 3, "id": 83 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 556,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 40000
|
||||
},
|
||||
"reward_artifacts": [ 0, 0, 1, 3 ],
|
||||
"value": 75000,
|
||||
"profitability": 29,
|
||||
"easiest": 145
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [ { "number": 8, "id": 26 }, { "number": 7, "id": 82 }, { "number": 6, "id": 27 }, { "number": 5, "id": 83 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 343,
|
||||
"reward_resources":
|
||||
{
|
||||
"gold" : 50000
|
||||
},
|
||||
"reward_artifacts": [ 0, 0, 0, 4 ],
|
||||
"value": 90000,
|
||||
"profitability": 27,
|
||||
"easiest": 189
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Hunting Lodge",
|
||||
"levels": [
|
||||
@ -1252,21 +586,6 @@
|
||||
"easiest": 250
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"name" : "Pyramid",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 100,
|
||||
"guards": [ { "number": 20, "id": 116 }, { "number": 10, "id": 117 }, { "number": 20, "id": 116 }, { "number": 10, "id": 117 } ],
|
||||
"upgrade_chance": 0,
|
||||
"combat_value": 786,
|
||||
"value": 15000,
|
||||
"profitability": 19,
|
||||
"easiest": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -49,6 +49,7 @@
|
||||
[
|
||||
"config/objects/generic.json",
|
||||
"config/objects/moddables.json",
|
||||
"config/objects/creatureBanks.json",
|
||||
"config/objects/dwellings.json",
|
||||
"config/objects/rewardable.json"
|
||||
],
|
||||
|
975
config/objects/creatureBanks.json
Normal file
975
config/objects/creatureBanks.json
Normal file
@ -0,0 +1,975 @@
|
||||
{
|
||||
"creatureBank" : {
|
||||
"index" :16,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"cyclopsStockpile" :
|
||||
{
|
||||
"index" : 0,
|
||||
"name" : "Cyclops Stockpile",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 4, "type": "cyclop" },
|
||||
{ "amount": 4, "type": "cyclop" },
|
||||
{ "amount": 4, "type": "cyclop", "upgradeChance": 50 },
|
||||
{ "amount": 4, "type": "cyclop" },
|
||||
{ "amount": 4, "type": "cyclop" }
|
||||
],
|
||||
|
||||
"combat_value": 506,
|
||||
"reward" : {
|
||||
"value": 10000,
|
||||
"resources":
|
||||
{
|
||||
"wood" : 4,
|
||||
"mercury" : 4,
|
||||
"ore" : 4,
|
||||
"sulfur" : 4,
|
||||
"crystal" : 4,
|
||||
"gems" : 4,
|
||||
"gold" : 0
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "cyclop" },
|
||||
{ "amount": 6, "type": "cyclop" },
|
||||
{ "amount": 6, "type": "cyclop", "upgradeChance": 50 },
|
||||
{ "amount": 6, "type": "cyclop" },
|
||||
{ "amount": 6, "type": "cyclop" }
|
||||
],
|
||||
"combat_value": 760,
|
||||
"reward" : {
|
||||
"value": 15000,
|
||||
"resources":
|
||||
{
|
||||
"wood" : 6,
|
||||
"mercury" : 6,
|
||||
"ore" : 6,
|
||||
"sulfur" : 6,
|
||||
"crystal" : 6,
|
||||
"gems" : 6
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "cyclop" },
|
||||
{ "amount": 8, "type": "cyclop" },
|
||||
{ "amount": 8, "type": "cyclop", "upgradeChance": 50 },
|
||||
{ "amount": 8, "type": "cyclop" },
|
||||
{ "amount": 8, "type": "cyclop" }
|
||||
],
|
||||
"combat_value": 1013,
|
||||
"reward" : {
|
||||
"value": 20000
|
||||
"resources":
|
||||
{
|
||||
"wood" : 8,
|
||||
"mercury" : 8,
|
||||
"ore" : 8,
|
||||
"sulfur" : 8,
|
||||
"crystal" : 8,
|
||||
"gems" : 8
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "cyclop" },
|
||||
{ "amount": 10, "type": "cyclop" },
|
||||
{ "amount": 10, "type": "cyclop", "upgradeChance": 50 },
|
||||
{ "amount": 10, "type": "cyclop" },
|
||||
{ "amount": 10, "type": "cyclop" }
|
||||
],
|
||||
"combat_value": 1266,
|
||||
"reward" : {
|
||||
"value": 25000,
|
||||
"resources":
|
||||
{
|
||||
"wood" : 10,
|
||||
"mercury" : 10,
|
||||
"ore" : 10,
|
||||
"sulfur" : 10,
|
||||
"crystal" : 10,
|
||||
"gems" : 10
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dwarvenTreasury" : {
|
||||
"index" : 1,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Dwarven Treasury",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "dwarf" },
|
||||
{ "amount": 10, "type": "dwarf" },
|
||||
{ "amount": 10, "type": "dwarf", "upgradeChance": 50 },
|
||||
{ "amount": 10, "type": "dwarf" },
|
||||
{ "amount": 10, "type": "dwarf" }
|
||||
],
|
||||
"combat_value": 194,
|
||||
"reward" : {
|
||||
"value": 3500,
|
||||
"resources":
|
||||
{
|
||||
"crystal" : 2,
|
||||
"gold" : 2500
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 15, "type": "dwarf" },
|
||||
{ "amount": 15, "type": "dwarf" },
|
||||
{ "amount": 15, "type": "dwarf", "upgradeChance": 50 },
|
||||
{ "amount": 15, "type": "dwarf" },
|
||||
{ "amount": 15, "type": "dwarf" }
|
||||
],
|
||||
"combat_value": 291,
|
||||
"reward" : {
|
||||
"value": 5500,
|
||||
"resources":
|
||||
{
|
||||
"crystal" : 3,
|
||||
"gold" : 4000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "dwarf" },
|
||||
{ "amount": 20, "type": "dwarf" },
|
||||
{ "amount": 20, "type": "dwarf", "upgradeChance": 50 },
|
||||
{ "amount": 20, "type": "dwarf" },
|
||||
{ "amount": 20, "type": "dwarf" }
|
||||
],
|
||||
"combat_value": 388,
|
||||
"reward" : {
|
||||
"value": 7500,
|
||||
"resources":
|
||||
{
|
||||
"crystal" : 5,
|
||||
"gold" : 5000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 30, "type": "dwarf" },
|
||||
{ "amount": 30, "type": "dwarf" },
|
||||
{ "amount": 30, "type": "dwarf", "upgradeChance": 50 },
|
||||
{ "amount": 30, "type": "dwarf" },
|
||||
{ "amount": 30, "type": "dwarf" }
|
||||
],
|
||||
"combat_value": 582,
|
||||
"reward" : {
|
||||
"value": 12500,
|
||||
"resources":
|
||||
{
|
||||
"crystal" : 10,
|
||||
"gold" : 7500
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"griffinConservatory" : {
|
||||
"index" : 2,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Griffin Conservatory",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "griffin" },
|
||||
{ "amount": 10, "type": "griffin" },
|
||||
{ "amount": 10, "type": "griffin", "upgradeChance": 50 },
|
||||
{ "amount": 10, "type": "griffin" },
|
||||
{ "amount": 10, "type": "griffin" }
|
||||
],
|
||||
"combat_value": 351,
|
||||
"reward" : {
|
||||
"value": 3000,
|
||||
"creatures": [ { "amount": 1, "type": "angel" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "griffin" },
|
||||
{ "amount": 20, "type": "griffin" },
|
||||
{ "amount": 20, "type": "griffin", "upgradeChance": 50 },
|
||||
{ "amount": 20, "type": "griffin" },
|
||||
{ "amount": 20, "type": "griffin" }
|
||||
],
|
||||
"combat_value": 702,
|
||||
"reward" : {
|
||||
"value": 6000,
|
||||
"creatures": [ { "amount": 2, "type": "angel" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 30, "type": "griffin" },
|
||||
{ "amount": 30, "type": "griffin" },
|
||||
{ "amount": 30, "type": "griffin", "upgradeChance": 50 },
|
||||
{ "amount": 30, "type": "griffin" },
|
||||
{ "amount": 30, "type": "griffin" }
|
||||
],
|
||||
"combat_value": 1053,
|
||||
"reward" : {
|
||||
"value": 9000,
|
||||
"creatures": [ { "amount": 3, "type": "angel" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 40, "type": "griffin" },
|
||||
{ "amount": 40, "type": "griffin" },
|
||||
{ "amount": 40, "type": "griffin", "upgradeChance": 50 },
|
||||
{ "amount": 40, "type": "griffin" },
|
||||
{ "amount": 40, "type": "griffin" }
|
||||
],
|
||||
"combat_value": 1404,
|
||||
"reward" : {
|
||||
"value": 12000,
|
||||
"creatures": [ { "amount": 4, "type": "angel" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"inpCache" : {
|
||||
"index" : 3,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Imp Cache",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "imp" },
|
||||
{ "amount": 20, "type": "imp" },
|
||||
{ "amount": 20, "type": "imp", "upgradeChance": 50 },
|
||||
{ "amount": 20, "type": "imp" },
|
||||
{ "amount": 20, "type": "imp" }
|
||||
],
|
||||
"combat_value": 100,
|
||||
"reward" : {
|
||||
"value": 2000,
|
||||
"resources":
|
||||
{
|
||||
"wood" : 0,
|
||||
"mercury" : 2,
|
||||
"ore" : 0,
|
||||
"sulfur" : 0,
|
||||
"crystal" : 0,
|
||||
"gems" : 0,
|
||||
"gold" : 1000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 30, "type": "imp" },
|
||||
{ "amount": 30, "type": "imp" },
|
||||
{ "amount": 30, "type": "imp", "upgradeChance": 50 },
|
||||
{ "amount": 30, "type": "imp" },
|
||||
{ "amount": 30, "type": "imp" }
|
||||
],
|
||||
"combat_value": 150,
|
||||
"reward" : {
|
||||
"value": 3000,
|
||||
"resources":
|
||||
{
|
||||
"mercury" : 3,
|
||||
"gold" : 1500
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 40, "type": "imp" },
|
||||
{ "amount": 40, "type": "imp" },
|
||||
{ "amount": 40, "type": "imp", "upgradeChance": 50 },
|
||||
{ "amount": 40, "type": "imp" },
|
||||
{ "amount": 40, "type": "imp" }
|
||||
],
|
||||
"combat_value": 200,
|
||||
"reward" : {
|
||||
"value": 4000,
|
||||
"resources":
|
||||
{
|
||||
"mercury" : 4,
|
||||
"gold" : 2000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 60, "type": "imp" },
|
||||
{ "amount": 60, "type": "imp" },
|
||||
{ "amount": 60, "type": "imp", "upgradeChance": 50 },
|
||||
{ "amount": 60, "type": "imp" },
|
||||
{ "amount": 60, "type": "imp" }
|
||||
],
|
||||
"combat_value": 300,
|
||||
"reward" : {
|
||||
"value": 6000,
|
||||
"resources":
|
||||
{
|
||||
"mercury" : 6,
|
||||
"gold" : 3000
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"medusaStore" : {
|
||||
"index" : 4,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Medusa Stores",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 4, "type": "medusa" },
|
||||
{ "amount": 4, "type": "medusa" },
|
||||
{ "amount": 4, "type": "medusa", "upgradeChance": 50 },
|
||||
{ "amount": 4, "type": "medusa" },
|
||||
{ "amount": 4, "type": "medusa" }
|
||||
],
|
||||
"combat_value": 207,
|
||||
"reward" : {
|
||||
"value": 4500,
|
||||
"resources":
|
||||
{
|
||||
"sulfur" : 5,
|
||||
"gold" : 2000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "medusa" },
|
||||
{ "amount": 6, "type": "medusa" },
|
||||
{ "amount": 6, "type": "medusa", "upgradeChance": 50 },
|
||||
{ "amount": 6, "type": "medusa" },
|
||||
{ "amount": 6, "type": "medusa" }
|
||||
],
|
||||
"combat_value": 310,
|
||||
"reward" : {
|
||||
"value": 6000,
|
||||
"resources":
|
||||
{
|
||||
"sulfur" : 6,
|
||||
"gold" : 3000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "medusa" },
|
||||
{ "amount": 8, "type": "medusa" },
|
||||
{ "amount": 8, "type": "medusa", "upgradeChance": 50 },
|
||||
{ "amount": 8, "type": "medusa" },
|
||||
{ "amount": 8, "type": "medusa" }
|
||||
],
|
||||
"combat_value": 414,
|
||||
"reward" : {
|
||||
"value": 8000,
|
||||
"resources":
|
||||
{
|
||||
"sulfur" : 8,
|
||||
"gold" : 4000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "medusa" },
|
||||
{ "amount": 10, "type": "medusa" },
|
||||
{ "amount": 10, "type": "medusa", "upgradeChance": 50 },
|
||||
{ "amount": 10, "type": "medusa" },
|
||||
{ "amount": 10, "type": "medusa" }
|
||||
],
|
||||
"combat_value": 517,
|
||||
"reward" : {
|
||||
"value": 10000,
|
||||
"resources":
|
||||
{
|
||||
"sulfur" : 10,
|
||||
"gold" : 5000
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"nagaBank" : {
|
||||
"index" : 5,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Naga Bank",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 2, "type": "naga" },
|
||||
{ "amount": 2, "type": "naga" },
|
||||
{ "amount": 2, "type": "naga", "upgradeChance": 50 },
|
||||
{ "amount": 2, "type": "naga" },
|
||||
{ "amount": 2, "type": "naga" }
|
||||
],
|
||||
"combat_value": 403,
|
||||
"reward" : {
|
||||
"value": 8000,
|
||||
"resources":
|
||||
{
|
||||
"gems" : 8,
|
||||
"gold" : 4000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 3, "type": "naga" },
|
||||
{ "amount": 3, "type": "naga" },
|
||||
{ "amount": 3, "type": "naga", "upgradeChance": 50 },
|
||||
{ "amount": 3, "type": "naga" },
|
||||
{ "amount": 3, "type": "naga" }
|
||||
],
|
||||
"combat_value": 605,
|
||||
"reward" : {
|
||||
"value": 12000,
|
||||
"resources":
|
||||
{
|
||||
"gems" : 12,
|
||||
"gold" : 6000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 4, "type": "naga" },
|
||||
{ "amount": 4, "type": "naga" },
|
||||
{ "amount": 4, "type": "naga", "upgradeChance": 50 },
|
||||
{ "amount": 4, "type": "naga" },
|
||||
{ "amount": 4, "type": "naga" }
|
||||
],
|
||||
"combat_value": 806,
|
||||
"reward" : {
|
||||
"value": 16000,
|
||||
"resources":
|
||||
{
|
||||
"gems" : 16,
|
||||
"gold" : 8000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "naga" },
|
||||
{ "amount": 6, "type": "naga" },
|
||||
{ "amount": 6, "type": "naga", "upgradeChance": 50 },
|
||||
{ "amount": 6, "type": "naga" },
|
||||
{ "amount": 6, "type": "naga" }
|
||||
],
|
||||
"combat_value": 1210,
|
||||
"reward" : {
|
||||
"value": 24000,
|
||||
"resources":
|
||||
{
|
||||
"gems" : 24,
|
||||
"gold" : 12000
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dragonflyHive" : {
|
||||
"index" : 6,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Dragon Fly Hive",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "dragonFly" },
|
||||
{ "amount": 6, "type": "dragonFly" },
|
||||
{ "amount": 6, "type": "dragonFly" },
|
||||
{ "amount": 6, "type": "dragonFly" },
|
||||
{ "amount": 6, "type": "dragonFly" }
|
||||
],
|
||||
"combat_value": 154,
|
||||
"reward" : {
|
||||
"value": 3200,
|
||||
"creatures": [ { "amount": 4, "type": "vyvern" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 9, "type": "dragonFly" },
|
||||
{ "amount": 9, "type": "dragonFly" },
|
||||
{ "amount": 9, "type": "dragonFly" },
|
||||
{ "amount": 9, "type": "dragonFly" },
|
||||
{ "amount": 9, "type": "dragonFly" }
|
||||
],
|
||||
"combat_value": 230,
|
||||
"reward" : {
|
||||
"value": 4800,
|
||||
"creatures": [ { "amount": 6, "type": "vyvern" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 12, "type": "dragonFly" },
|
||||
{ "amount": 12, "type": "dragonFly" },
|
||||
{ "amount": 12, "type": "dragonFly" },
|
||||
{ "amount": 12, "type": "dragonFly" },
|
||||
{ "amount": 12, "type": "dragonFly" }
|
||||
],
|
||||
"combat_value": 307,
|
||||
"reward" : {
|
||||
"value": 6400,
|
||||
"creatures": [ { "amount": 8, "type": "vyvern" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 18, "type": "dragonFly" },
|
||||
{ "amount": 18, "type": "dragonFly" },
|
||||
{ "amount": 18, "type": "dragonFly" },
|
||||
{ "amount": 18, "type": "dragonFly" },
|
||||
{ "amount": 18, "type": "dragonFly" }
|
||||
],
|
||||
"combat_value": 461,
|
||||
"reward" : {
|
||||
"value": 9600,
|
||||
"creatures": [ { "amount": 12, "type": "vyvern" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"shipwreck" : {
|
||||
"index" :85,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"shipwreck" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Shipwreck",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 2, "type": "wight" },
|
||||
{ "amount": 2, "type": "wight" },
|
||||
{ "amount": 2, "type": "wight" },
|
||||
{ "amount": 2, "type": "wight" },
|
||||
{ "amount": 2, "type": "wight" }
|
||||
],
|
||||
"combat_value": 31,
|
||||
"reward" : {
|
||||
"value": 2000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 2000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 3, "type": "wight" },
|
||||
{ "amount": 3, "type": "wight" },
|
||||
{ "amount": 3, "type": "wight" },
|
||||
{ "amount": 3, "type": "wight" },
|
||||
{ "amount": 3, "type": "wight" }
|
||||
],
|
||||
"combat_value": 46,
|
||||
"reward" : {
|
||||
"value": 3000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 5, "type": "wight" }
|
||||
],
|
||||
"combat_value": 77,
|
||||
"reward" : {
|
||||
"value": 5000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 4000
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "wight" }
|
||||
],
|
||||
"combat_value": 154,
|
||||
"reward" : {
|
||||
"value": 7000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 5000
|
||||
},
|
||||
"artifacts": [ { "class" : "MINOR" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
"derelictShip" : {
|
||||
"index" :24,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"derelictShip" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Derelict Ship",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 4, "type": "waterElemental" },
|
||||
{ "amount": 4, "type": "waterElemental" },
|
||||
{ "amount": 4, "type": "waterElemental" },
|
||||
{ "amount": 4, "type": "waterElemental" },
|
||||
{ "amount": 4, "type": "waterElemental" }
|
||||
],
|
||||
"combat_value": 138,
|
||||
"reward" : {
|
||||
"value": 3000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 6, "type": "waterElemental" },
|
||||
{ "amount": 6, "type": "waterElemental" },
|
||||
{ "amount": 6, "type": "waterElemental" },
|
||||
{ "amount": 6, "type": "waterElemental" },
|
||||
{ "amount": 6, "type": "waterElemental" }
|
||||
],
|
||||
"combat_value": 207,
|
||||
"reward" : {
|
||||
"value": 4000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 3000
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "waterElemental" },
|
||||
{ "amount": 8, "type": "waterElemental" },
|
||||
{ "amount": 8, "type": "waterElemental" },
|
||||
{ "amount": 8, "type": "waterElemental" },
|
||||
{ "amount": 8, "type": "waterElemental" }
|
||||
],
|
||||
"combat_value": 276,
|
||||
"reward" : {
|
||||
"value": 5000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 4000
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 12, "type": "waterElemental" },
|
||||
{ "amount": 12, "type": "waterElemental" },
|
||||
{ "amount": 12, "type": "waterElemental" },
|
||||
{ "amount": 12, "type": "waterElemental" },
|
||||
{ "amount": 12, "type": "waterElemental" }
|
||||
],
|
||||
"combat_value": 414,
|
||||
"reward" : {
|
||||
"value": 8000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 6000
|
||||
},
|
||||
"artifacts": [ { "class" : "MINOR" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"crypt" : {
|
||||
"index" :84,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"crypt" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Crypt",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 10, "type": "skeleton" },
|
||||
{ "amount": 10, "type": "walkingDead" },
|
||||
{ "amount": 10, "type": "walkingDead" },
|
||||
{ "amount": 10, "type": "skeleton" },
|
||||
{ "amount": 10, "type": "skeleton" }
|
||||
],
|
||||
"combat_value": 75,
|
||||
"reward" : {
|
||||
"value": 1500,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 1500
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 13, "type": "skeleton" },
|
||||
{ "amount": 10, "type": "walkingDead" },
|
||||
{ "amount": 5, "type": "wight" },
|
||||
{ "amount": 10, "type": "walkingDead" },
|
||||
{ "amount": 12, "type": "skeleton" }
|
||||
],
|
||||
"combat_value": 94,
|
||||
"reward" : {
|
||||
"value": 2000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 2000
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "skeleton" },
|
||||
{ "amount": 20, "type": "walkingDead" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 5, "type": "vampire" }
|
||||
],
|
||||
"combat_value": 169,
|
||||
"reward" : {
|
||||
"value": 3500,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 2500
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "skeleton" },
|
||||
{ "amount": 20, "type": "walkingDead" },
|
||||
{ "amount": 10, "type": "wight" },
|
||||
{ "amount": 10, "type": "vampire" }
|
||||
],
|
||||
"combat_value": 225,
|
||||
"reward" : {
|
||||
"value": 6000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 5000
|
||||
},
|
||||
"artifacts": [ { "class" : "TREASURE" } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dragonUtopia" : {
|
||||
"index" :25,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"dragonUtopia" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Dragon Utopia",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "greenDragon" },
|
||||
{ "amount": 5, "type": "redDragon" },
|
||||
{ "amount": 2, "type": "goldDragon" },
|
||||
{ "amount": 1, "type": "blackDragon" }
|
||||
],
|
||||
"combat_value": 769,
|
||||
"reward" : {
|
||||
"value": 38000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 20000
|
||||
},
|
||||
"artifacts": [
|
||||
{ "class" : "TREASURE" }
|
||||
{ "class" : "MINOR" }
|
||||
{ "class" : "MAJOR" }
|
||||
{ "class" : "RELIC" }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "greenDragon" },
|
||||
{ "amount": 6, "type": "redDragon" },
|
||||
{ "amount": 3, "type": "goldDragon" },
|
||||
{ "amount": 2, "type": "blackDragon" }
|
||||
],
|
||||
"combat_value": 209,
|
||||
"reward" : {
|
||||
"value": 57000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 30000
|
||||
},
|
||||
"artifacts": [
|
||||
{ "class" : "MINOR" }
|
||||
{ "class" : "MAJOR" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 30,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "greenDragon" },
|
||||
{ "amount": 6, "type": "redDragon" },
|
||||
{ "amount": 4, "type": "goldDragon" },
|
||||
{ "amount": 3, "type": "blackDragon" }
|
||||
],
|
||||
"combat_value": 556,
|
||||
"reward" : {
|
||||
"value": 75000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 40000
|
||||
},
|
||||
"artifacts": [ 0, 0, 1, 3 ]
|
||||
"artifacts": [
|
||||
{ "class" : "MAJOR" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"chance": 10,
|
||||
"guards": [
|
||||
{ "amount": 8, "type": "greenDragon" },
|
||||
{ "amount": 7, "type": "redDragon" },
|
||||
{ "amount": 6, "type": "goldDragon" },
|
||||
{ "amount": 5, "type": "blackDragon" }
|
||||
],
|
||||
"combat_value": 343,
|
||||
"reward" : {
|
||||
"value": 90000,
|
||||
"resources":
|
||||
{
|
||||
"gold" : 50000
|
||||
},
|
||||
"artifacts": [ 0, 0, 0, 4 ]
|
||||
"artifacts": [
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
{ "class" : "RELIC" }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"pyramid" : {
|
||||
"index" :63,
|
||||
"handler": "bank",
|
||||
"types" : {
|
||||
"pyramid" : {
|
||||
"index" : 0,
|
||||
"resetDuraition" : 28,
|
||||
"name" : "Pyramid",
|
||||
"levels": [
|
||||
{
|
||||
"chance": 100,
|
||||
"guards": [
|
||||
{ "amount": 20, "type": "goldGolem" },
|
||||
{ "amount": 10, "type": "diamondGolem" },
|
||||
{ "amount": 20, "type": "goldGolem" },
|
||||
{ "amount": 10, "type": "diamondGolem" }
|
||||
],
|
||||
"combat_value": 786,
|
||||
"reward" : {
|
||||
"value": 15000,
|
||||
"spells" : [ { "level" : 5 } ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -104,9 +104,9 @@
|
||||
[ "fireElemental" ],
|
||||
[ "earthElemental" ]
|
||||
],
|
||||
"guards" : {
|
||||
"earthElemental" : 12
|
||||
}
|
||||
"guards" : [
|
||||
{ "amount" : 12, "type" : "earthElemental" }
|
||||
]
|
||||
},
|
||||
"golemFactory" : {
|
||||
"index" : 1,
|
||||
@ -116,10 +116,10 @@
|
||||
[ "goldGolem" ],
|
||||
[ "diamondGolem" ]
|
||||
],
|
||||
"guards" : {
|
||||
"goldGolem" : 9,
|
||||
"diamondGolem" : 6
|
||||
}
|
||||
"guards" : [
|
||||
{ "amount" : 9, "type" : "goldGolem" },
|
||||
{ "amount" : 6, "type" : "diamondGolem" }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -16,11 +16,6 @@
|
||||
|
||||
"blackMarket" : { "index" :7, "handler": "blackMarket" },
|
||||
|
||||
"crypt" : { "index" :84, "handler": "bank" },
|
||||
"shipwreck" : { "index" :85, "handler": "bank" },
|
||||
"derelictShip" : { "index" :24, "handler": "bank" },
|
||||
"dragonUtopia" : { "index" :25, "handler": "bank" },
|
||||
|
||||
"pandoraBox" : { "index" :6, "handler": "pandora" },
|
||||
"event" : { "index" :26, "handler": "event" },
|
||||
|
||||
@ -45,7 +40,6 @@
|
||||
"magicWell" : { "index" :49, "handler": "magicWell" },
|
||||
"obelisk" : { "index" :57, "handler": "obelisk" },
|
||||
"oceanBottle" : { "index" :59, "handler": "sign" },
|
||||
"pyramid" : { "index" :63, "handler": "pyramid" },
|
||||
"scholar" : { "index" :81, "handler": "scholar" },
|
||||
"shipyard" : { "index" :87, "handler": "shipyard" },
|
||||
"sign" : { "index" :91, "handler": "sign" },
|
||||
|
@ -184,9 +184,6 @@
|
||||
}
|
||||
},
|
||||
|
||||
// subtype: different content
|
||||
"creatureBank" : { "index" :16, "handler": "bank" },
|
||||
|
||||
// subtype: 0 = normal, 1 = anti-magic
|
||||
"garrisonHorizontal" : { "index" :33, "handler": "garrison" },
|
||||
"garrisonVertical" : { "index" :219, "handler": "garrison" },
|
||||
|
@ -262,12 +262,21 @@ CArtifact * CArtHandler::loadFromJson(const JsonNode & node)
|
||||
return art;
|
||||
}
|
||||
|
||||
void CArtHandler::addSlot(CArtifact * art, const std::string & slotID)
|
||||
ArtifactPosition CArtHandler::stringToSlot(std::string slotName)
|
||||
{
|
||||
#define ART_POS(x) ( #x, ArtifactPosition::x )
|
||||
static const std::map<std::string, ArtifactPosition> artifactPositionMap = boost::assign::map_list_of ART_POS_LIST;
|
||||
#undef ART_POS
|
||||
auto it = artifactPositionMap.find (slotName);
|
||||
if (it != artifactPositionMap.end())
|
||||
return it->second;
|
||||
|
||||
logGlobal->warnStream() << "Warning! Artifact slot " << slotName << " not recognized!";
|
||||
return ArtifactPosition::PRE_FIRST;
|
||||
}
|
||||
|
||||
void CArtHandler::addSlot(CArtifact * art, const std::string & slotID)
|
||||
{
|
||||
if (slotID == "MISC")
|
||||
{
|
||||
art->possibleSlots[ArtBearer::HERO] += ArtifactPosition::MISC1, ArtifactPosition::MISC2, ArtifactPosition::MISC3, ArtifactPosition::MISC4, ArtifactPosition::MISC5;
|
||||
@ -278,14 +287,9 @@ void CArtHandler::addSlot(CArtifact * art, const std::string & slotID)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto it = artifactPositionMap.find (slotID);
|
||||
if (it != artifactPositionMap.end())
|
||||
{
|
||||
auto slot = it->second;
|
||||
auto slot = stringToSlot(slotID);
|
||||
if (slot != ArtifactPosition::PRE_FIRST)
|
||||
art->possibleSlots[ArtBearer::HERO].push_back (slot);
|
||||
}
|
||||
else
|
||||
logGlobal->warnStream() << "Warning! Artifact slot " << slotID << " not recognized!";
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,7 +307,7 @@ void CArtHandler::loadSlots(CArtifact * art, const JsonNode & node)
|
||||
}
|
||||
}
|
||||
|
||||
void CArtHandler::loadClass(CArtifact * art, const JsonNode & node)
|
||||
CArtifact::EartClass CArtHandler::stringToClass(std::string className)
|
||||
{
|
||||
static const std::map<std::string, CArtifact::EartClass> artifactClassMap = boost::assign::map_list_of
|
||||
("TREASURE", CArtifact::ART_TREASURE)
|
||||
@ -312,16 +316,17 @@ void CArtHandler::loadClass(CArtifact * art, const JsonNode & node)
|
||||
("RELIC", CArtifact::ART_RELIC)
|
||||
("SPECIAL", CArtifact::ART_SPECIAL);
|
||||
|
||||
auto it = artifactClassMap.find (node["class"].String());
|
||||
auto it = artifactClassMap.find (className);
|
||||
if (it != artifactClassMap.end())
|
||||
{
|
||||
art->aClass = it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->warnStream() << "Warning! Artifact rarity " << node["class"].String() << " not recognized!";
|
||||
art->aClass = CArtifact::ART_SPECIAL;
|
||||
}
|
||||
return it->second;
|
||||
|
||||
logGlobal->warnStream() << "Warning! Artifact rarity " << className << " not recognized!";
|
||||
return CArtifact::ART_SPECIAL;
|
||||
}
|
||||
|
||||
void CArtHandler::loadClass(CArtifact * art, const JsonNode & node)
|
||||
{
|
||||
art->aClass = stringToClass(node["class"].String());
|
||||
}
|
||||
|
||||
void CArtHandler::loadType(CArtifact * art, const JsonNode & node)
|
||||
@ -424,7 +429,7 @@ CreatureID CArtHandler::machineIDToCreature(ArtifactID id)
|
||||
return CreatureID::NONE; //this artifact is not a creature
|
||||
}
|
||||
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts)
|
||||
{
|
||||
auto getAllowedArts = [&](std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, CArtifact::EartClass flag)
|
||||
{
|
||||
@ -433,8 +438,11 @@ ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
|
||||
for (auto & arts_i : *arts)
|
||||
{
|
||||
CArtifact *art = arts_i;
|
||||
out.push_back(art);
|
||||
if (accepts(arts_i->id))
|
||||
{
|
||||
CArtifact *art = arts_i;
|
||||
out.push_back(art);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -469,6 +477,16 @@ ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
return artID;
|
||||
}
|
||||
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts)
|
||||
{
|
||||
return pickRandomArtifact(rand, 0xff, accepts);
|
||||
}
|
||||
|
||||
ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags)
|
||||
{
|
||||
return pickRandomArtifact(rand, flags, [](ArtifactID){ return true;});
|
||||
}
|
||||
|
||||
Bonus *createBonus(Bonus::BonusType type, int val, int subtype, Bonus::ValueType valType, shared_ptr<ILimiter> limiter = shared_ptr<ILimiter>(), int additionalInfo = 0)
|
||||
{
|
||||
auto added = new Bonus(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,-1,subtype);
|
||||
|
@ -203,11 +203,17 @@ public:
|
||||
|
||||
boost::optional<std::vector<CArtifact*>&> listFromClass(CArtifact::EartClass artifactClass);
|
||||
|
||||
ArtifactPosition stringToSlot(std::string slotName);
|
||||
CArtifact::EartClass stringToClass(std::string className);
|
||||
|
||||
/// Gets a artifact ID randomly and removes the selected artifact from this handler.
|
||||
ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags);
|
||||
ArtifactID pickRandomArtifact(CRandomGenerator & rand, std::function<bool(ArtifactID)> accepts);
|
||||
ArtifactID pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts);
|
||||
|
||||
bool legalArtifact(ArtifactID id);
|
||||
void getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag);
|
||||
void getAllowed(std::vector<ConstTransitivePtr<CArtifact> > &out, int flags);
|
||||
//void getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag);
|
||||
//void getAllowed(std::vector<ConstTransitivePtr<CArtifact> > &out, int flags);
|
||||
bool isBigArtifact (ArtifactID artID) const {return bigArtifacts.find(artID) != bigArtifacts.end();}
|
||||
void initAllowedArtifactsList(const std::vector<bool> &allowed); //allowed[art_id] -> 0 if not allowed, 1 if allowed
|
||||
static ArtifactID creatureToMachineID(CreatureID id);
|
||||
|
@ -31,6 +31,7 @@ set(lib_SRCS
|
||||
mapObjects/CQuest.cpp
|
||||
mapObjects/CRewardableConstructor.cpp
|
||||
mapObjects/CRewardableObject.cpp
|
||||
mapObjects/JsonRandom.cpp
|
||||
mapObjects/MiscObjects.cpp
|
||||
mapObjects/ObjectTemplate.cpp
|
||||
|
||||
|
@ -1021,8 +1021,7 @@ namespace ObjProperty
|
||||
BONUS_VALUE_FIRST, BONUS_VALUE_SECOND, //used in Rampart for special building that generates resources (storing resource type and quantity)
|
||||
|
||||
//creature-bank specific
|
||||
BANK_DAYCOUNTER, BANK_CLEAR_ARTIFACTS, BANK_ADD_ARTIFACT, BANK_MULTIPLIER, BANK_CONFIG_PRESET,
|
||||
BANK_CLEAR_CONFIG, BANK_INIT_ARMY, BANK_RESET,
|
||||
BANK_DAYCOUNTER, BANK_RESET, BANK_CLEAR,
|
||||
|
||||
//object with reward
|
||||
REWARD_RESET, REWARD_SELECT
|
||||
|
@ -45,11 +45,11 @@ DLL_LINKAGE void preinitDLL(CConsoleHandler *Console)
|
||||
|
||||
DLL_LINKAGE void loadDLLClasses()
|
||||
{
|
||||
try
|
||||
//try
|
||||
{
|
||||
VLC->init();
|
||||
}
|
||||
HANDLE_EXCEPTION;
|
||||
//HANDLE_EXCEPTION;
|
||||
}
|
||||
|
||||
const IBonusTypeHandler * LibClasses::getBth() const
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include "../NetPacks.h"
|
||||
#include "../CGeneralTextHandler.h"
|
||||
#include "../CSoundBase.h"
|
||||
#include "CommonConstructors.h"
|
||||
#include "../CSpellHandler.h"
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
@ -24,134 +26,51 @@ static std::string & visitedTxt(const bool visited)
|
||||
return VLC->generaltexth->allTexts[id];
|
||||
}
|
||||
|
||||
CBank::CBank()
|
||||
{
|
||||
}
|
||||
|
||||
CBank::~CBank()
|
||||
{
|
||||
}
|
||||
|
||||
void CBank::initObj()
|
||||
{
|
||||
index = VLC->objh->bankObjToIndex(this);
|
||||
bc = nullptr;
|
||||
daycounter = 0;
|
||||
multiplier = 1;
|
||||
resetDuration = 0;
|
||||
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, cb->gameState()->getRandomGenerator());
|
||||
}
|
||||
|
||||
const std::string & CBank::getHoverText() const
|
||||
{
|
||||
bool visited = (bc == nullptr);
|
||||
hoverName = VLC->objh->creBanksNames[index] + " " + visitedTxt(visited);
|
||||
hoverName = visitedTxt(visited); // FIXME: USE BANK_SPECIFIC NAMES
|
||||
return hoverName;
|
||||
}
|
||||
void CBank::reset(ui16 var1) //prevents desync
|
||||
|
||||
void CBank::setConfig(const BankConfig & config)
|
||||
{
|
||||
ui8 chance = 0;
|
||||
for (auto & elem : VLC->objh->banksInfo[index])
|
||||
{
|
||||
if (var1 < (chance += elem->chance))
|
||||
{
|
||||
bc = elem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
artifacts.clear();
|
||||
bc.reset(new BankConfig(config));
|
||||
clear(); // remove all stacks, if any
|
||||
|
||||
for (auto & stack : config.guards)
|
||||
setCreature (SlotID(stacksCount()), stack.type->idNumber, stack.count);
|
||||
}
|
||||
|
||||
void CBank::initialize() const
|
||||
{
|
||||
cb->setObjProperty(id, ObjProperty::BANK_RESET, cb->gameState()->getRandomGenerator().nextInt()); //synchronous reset
|
||||
|
||||
for (ui8 i = 0; i <= 3; i++)
|
||||
{
|
||||
for (ui8 n = 0; n < bc->artifacts[i]; n++)
|
||||
{
|
||||
CArtifact::EartClass artClass;
|
||||
switch(i)
|
||||
{
|
||||
case 0: artClass = CArtifact::ART_TREASURE; break;
|
||||
case 1: artClass = CArtifact::ART_MINOR; break;
|
||||
case 2: artClass = CArtifact::ART_MAJOR; break;
|
||||
case 3: artClass = CArtifact::ART_RELIC; break;
|
||||
default: assert(0); continue;
|
||||
}
|
||||
|
||||
int artID = VLC->arth->pickRandomArtifact(cb->gameState()->getRandomGenerator(), artClass);
|
||||
cb->setObjProperty(id, ObjProperty::BANK_ADD_ARTIFACT, artID);
|
||||
}
|
||||
}
|
||||
|
||||
cb->setObjProperty(id, ObjProperty::BANK_INIT_ARMY, cb->gameState()->getRandomGenerator().nextInt()); //get army
|
||||
}
|
||||
void CBank::setPropertyDer (ui8 what, ui32 val)
|
||||
/// random values are passed as arguments and processed identically on all clients
|
||||
{
|
||||
switch (what)
|
||||
{
|
||||
case ObjProperty::BANK_DAYCOUNTER: //daycounter
|
||||
if (val == 0)
|
||||
daycounter = 1; //yes, 1
|
||||
else
|
||||
daycounter++;
|
||||
break;
|
||||
case ObjProperty::BANK_MULTIPLIER: //multiplier, in percent
|
||||
multiplier = val / 100.0;
|
||||
break;
|
||||
case 13: //bank preset
|
||||
bc = VLC->objh->banksInfo[index][val];
|
||||
daycounter+=val;
|
||||
break;
|
||||
case ObjProperty::BANK_RESET:
|
||||
reset (val%100);
|
||||
initObj();
|
||||
daycounter = 1; //yes, 1 since "today" daycounter won't be incremented
|
||||
break;
|
||||
case ObjProperty::BANK_CLEAR_CONFIG:
|
||||
bc = nullptr;
|
||||
case ObjProperty::BANK_CLEAR:
|
||||
bc.reset();
|
||||
break;
|
||||
case ObjProperty::BANK_CLEAR_ARTIFACTS: //remove rewards from Derelict Ship
|
||||
artifacts.clear();
|
||||
break;
|
||||
case ObjProperty::BANK_INIT_ARMY: //set ArmedInstance army
|
||||
{
|
||||
int upgraded = 0;
|
||||
if (val%100 < bc->upgradeChance) //once again anti-desync
|
||||
upgraded = 1;
|
||||
switch (bc->guards.size())
|
||||
{
|
||||
case 1:
|
||||
for (int i = 0; i < 4; ++i)
|
||||
setCreature (SlotID(i), bc->guards[0].first, bc->guards[0].second / 5 );
|
||||
setCreature (SlotID(4), CreatureID(bc->guards[0].first + upgraded), bc->guards[0].second / 5 );
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
if (bc->guards.back().second) //all stacks are present
|
||||
{
|
||||
for (auto & elem : bc->guards)
|
||||
{
|
||||
setCreature (SlotID(stacksCount()), elem.first, elem.second);
|
||||
}
|
||||
}
|
||||
else if (bc->guards[2].second)//Wraiths are present, split two stacks in Crypt
|
||||
{
|
||||
setCreature (SlotID(0), bc->guards[0].first, bc->guards[0].second / 2 );
|
||||
setCreature (SlotID(1), bc->guards[1].first, bc->guards[1].second / 2);
|
||||
setCreature (SlotID(2), CreatureID(bc->guards[2].first + upgraded), bc->guards[2].second);
|
||||
setCreature (SlotID(3), bc->guards[1].first, bc->guards[1].second / 2 );
|
||||
setCreature (SlotID(4), bc->guards[0].first, bc->guards[0].second - (bc->guards[0].second / 2) );
|
||||
|
||||
}
|
||||
else //split both stacks
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) //skellies
|
||||
setCreature (SlotID(2*i), bc->guards[0].first, bc->guards[0].second / 3);
|
||||
for (int i = 0; i < 2; ++i) //zombies
|
||||
setCreature (SlotID(2*i+1), bc->guards[1].first, bc->guards[1].second / 2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logGlobal->warnStream() << "Error: Unexpected army data: " << bc->guards.size() <<" items found";
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ObjProperty::BANK_ADD_ARTIFACT: //add Artifact
|
||||
{
|
||||
artifacts.push_back (val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,25 +78,19 @@ void CBank::newTurn() const
|
||||
{
|
||||
if (bc == nullptr)
|
||||
{
|
||||
if (cb->getDate() == 1)
|
||||
initialize(); //initialize on first day
|
||||
else if (daycounter >= 28 && (subID < 13 || subID > 16)) //no reset for Emissaries
|
||||
if (resetDuration != 0)
|
||||
{
|
||||
initialize();
|
||||
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 0); //daycounter 0
|
||||
if (ID == Obj::DERELICT_SHIP && cb->getDate() > 1)
|
||||
{
|
||||
cb->setObjProperty (id, ObjProperty::BANK_MULTIPLIER, 0);//ugly hack to make derelict ships usable only once
|
||||
cb->setObjProperty (id, ObjProperty::BANK_CLEAR_ARTIFACTS, 0);
|
||||
}
|
||||
if (daycounter >= resetDuration)
|
||||
cb->setObjProperty (id, ObjProperty::BANK_RESET, 0); //daycounter 0
|
||||
else
|
||||
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 1); //daycounter++
|
||||
}
|
||||
else
|
||||
cb->setObjProperty (id, ObjProperty::BANK_DAYCOUNTER, 1); //daycounter++
|
||||
}
|
||||
}
|
||||
|
||||
bool CBank::wasVisited (PlayerColor player) const
|
||||
{
|
||||
return !bc;
|
||||
return !bc; //FIXME: player A should not know about visit done by player B
|
||||
}
|
||||
|
||||
void CBank::onHeroVisit (const CGHeroInstance * h) const
|
||||
@ -185,6 +98,7 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const
|
||||
if (bc)
|
||||
{
|
||||
int banktext = 0;
|
||||
ui16 soundID = soundBase::ROGUE;
|
||||
switch (ID)
|
||||
{
|
||||
case Obj::CREATURE_BANK:
|
||||
@ -202,13 +116,17 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const
|
||||
case Obj::SHIPWRECK:
|
||||
banktext = 122;
|
||||
break;
|
||||
case Obj::PYRAMID:
|
||||
soundID = soundBase::MYSTERY;
|
||||
banktext = 105;
|
||||
break;
|
||||
}
|
||||
BlockingDialog bd (true, false);
|
||||
bd.player = h->getOwner();
|
||||
bd.soundID = soundBase::ROGUE;
|
||||
bd.text.addTxt(MetaString::ADVOB_TXT,banktext);
|
||||
if (ID == Obj::CREATURE_BANK)
|
||||
bd.text.addReplacement(VLC->objh->creBanksNames[index]);
|
||||
bd.soundID = soundID;
|
||||
bd.text.addTxt(MetaString::ADVOB_TXT, banktext);
|
||||
//if (ID == Obj::CREATURE_BANK)
|
||||
// bd.text.addReplacement(VLC->objh->creBanksNames[index]); // FIXME: USE BANK SPECIFIC NAMES
|
||||
cb->showBlockingDialog (&bd);
|
||||
}
|
||||
else
|
||||
@ -216,105 +134,100 @@ void CBank::onHeroVisit (const CGHeroInstance * h) const
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::GRAVEYARD;
|
||||
iw.player = h->getOwner();
|
||||
if (ID == Obj::CRYPT) //morale penalty for empty Crypt
|
||||
if (ID == Obj::PYRAMID) // You come upon the pyramid ... pyramid is completely empty.
|
||||
{
|
||||
GiveBonus gbonus;
|
||||
gbonus.id = h->id.getNum();
|
||||
gbonus.bonus.duration = Bonus::ONE_BATTLE;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
gbonus.bdescr << "\n" << VLC->generaltexth->arraytxt[98];
|
||||
gbonus.bonus.type = Bonus::MORALE;
|
||||
gbonus.bonus.val = -1;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
iw.text << VLC->generaltexth->advobtxt[120];
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
iw.text << VLC->generaltexth->advobtxt[107];
|
||||
iw.components.push_back (Component (Component::LUCK, 0 , -2, 0));
|
||||
GiveBonus gb;
|
||||
gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,-2,id.getNum(),VLC->generaltexth->arraytxt[70]);
|
||||
gb.id = h->id.getNum();
|
||||
cb->giveHeroBonus(&gb);
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text << VLC->generaltexth->advobtxt[33];
|
||||
iw.text.addReplacement(VLC->objh->creBanksNames[index]);
|
||||
iw.text << VLC->generaltexth->advobtxt[33];// This was X, now is completely empty
|
||||
//iw.text.addReplacement(VLC->objh->creBanksNames[index]); // FIXME: USE BANK SPECIFIC NAMES
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
||||
void CBank::doVisit(const CGHeroInstance * hero) const
|
||||
{
|
||||
if (result.winner == 0)
|
||||
int textID = -1;
|
||||
InfoWindow iw;
|
||||
iw.player = hero->getOwner();
|
||||
MetaString loot;
|
||||
|
||||
switch (ID)
|
||||
{
|
||||
int textID = -1;
|
||||
InfoWindow iw;
|
||||
iw.player = hero->getOwner();
|
||||
MetaString loot;
|
||||
|
||||
switch (ID)
|
||||
case Obj::CREATURE_BANK:
|
||||
case Obj::DRAGON_UTOPIA:
|
||||
textID = 34;
|
||||
break;
|
||||
case Obj::DERELICT_SHIP:
|
||||
if (!bc)
|
||||
textID = 43;
|
||||
else
|
||||
{
|
||||
case Obj::CREATURE_BANK: case Obj::DRAGON_UTOPIA:
|
||||
textID = 34;
|
||||
break;
|
||||
case Obj::DERELICT_SHIP:
|
||||
if (multiplier)
|
||||
textID = 43;
|
||||
else
|
||||
{
|
||||
GiveBonus gbonus;
|
||||
gbonus.id = hero->id.getNum();
|
||||
gbonus.bonus.duration = Bonus::ONE_BATTLE;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
gbonus.bdescr << "\n" << VLC->generaltexth->arraytxt[101];
|
||||
gbonus.bonus.type = Bonus::MORALE;
|
||||
gbonus.bonus.val = -1;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
textID = 42;
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
}
|
||||
break;
|
||||
case Obj::CRYPT:
|
||||
if (bc->resources.size() != 0)
|
||||
textID = 121;
|
||||
else
|
||||
{
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
GiveBonus gbonus;
|
||||
gbonus.id = hero->id.getNum();
|
||||
gbonus.bonus.duration = Bonus::ONE_BATTLE;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
gbonus.bdescr << "\n" << VLC->generaltexth->arraytxt[ID];
|
||||
gbonus.bonus.type = Bonus::MORALE;
|
||||
gbonus.bonus.val = -1;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
textID = 120;
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
}
|
||||
break;
|
||||
case Obj::SHIPWRECK:
|
||||
if (bc->resources.size())
|
||||
textID = 124;
|
||||
else
|
||||
textID = 123;
|
||||
break;
|
||||
GiveBonus gbonus;
|
||||
gbonus.id = hero->id.getNum();
|
||||
gbonus.bonus.duration = Bonus::ONE_BATTLE;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
gbonus.bdescr << "\n" << VLC->generaltexth->arraytxt[101];
|
||||
gbonus.bonus.type = Bonus::MORALE;
|
||||
gbonus.bonus.val = -1;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
textID = 42;
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
}
|
||||
|
||||
//grant resources
|
||||
if (textID != 42) //empty derelict ship gives no cash
|
||||
break;
|
||||
case Obj::CRYPT:
|
||||
if (bc)
|
||||
textID = 121;
|
||||
else
|
||||
{
|
||||
for (int it = 0; it < bc->resources.size(); it++)
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
GiveBonus gbonus;
|
||||
gbonus.id = hero->id.getNum();
|
||||
gbonus.bonus.duration = Bonus::ONE_BATTLE;
|
||||
gbonus.bonus.source = Bonus::OBJECT;
|
||||
gbonus.bonus.sid = ID;
|
||||
gbonus.bdescr << "\n" << VLC->generaltexth->arraytxt[ID];
|
||||
gbonus.bonus.type = Bonus::MORALE;
|
||||
gbonus.bonus.val = -1;
|
||||
cb->giveHeroBonus(&gbonus);
|
||||
textID = 120;
|
||||
iw.components.push_back (Component (Component::MORALE, 0 , -1, 0));
|
||||
}
|
||||
break;
|
||||
case Obj::SHIPWRECK:
|
||||
if (bc)
|
||||
textID = 124;
|
||||
else
|
||||
textID = 123;
|
||||
break;
|
||||
case Obj::PYRAMID:
|
||||
textID = 106;
|
||||
}
|
||||
|
||||
//grant resources
|
||||
if (bc)
|
||||
{
|
||||
for (int it = 0; it < bc->resources.size(); it++)
|
||||
{
|
||||
if (bc->resources[it] != 0)
|
||||
{
|
||||
if (bc->resources[it] != 0)
|
||||
{
|
||||
iw.components.push_back (Component (Component::RESOURCE, it, bc->resources[it], 0));
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(iw.components.back().val);
|
||||
loot.addReplacement(MetaString::RES_NAMES, iw.components.back().subtype);
|
||||
cb->giveResource (hero->getOwner(), static_cast<Res::ERes>(it), bc->resources[it]);
|
||||
}
|
||||
iw.components.push_back (Component (Component::RESOURCE, it, bc->resources[it], 0));
|
||||
loot << "%d %s";
|
||||
loot.addReplacement(iw.components.back().val);
|
||||
loot.addReplacement(MetaString::RES_NAMES, iw.components.back().subtype);
|
||||
cb->giveResource (hero->getOwner(), static_cast<Res::ERes>(it), bc->resources[it]);
|
||||
}
|
||||
}
|
||||
//grant artifacts
|
||||
for (auto & elem : artifacts)
|
||||
for (auto & elem : bc->artifacts)
|
||||
{
|
||||
iw.components.push_back (Component (Component::ARTIFACT, elem, 0, 0));
|
||||
loot << "%s";
|
||||
@ -327,22 +240,52 @@ void CBank::battleFinished(const CGHeroInstance *hero, const BattleResult &resul
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, textID);
|
||||
if (textID == 34)
|
||||
{
|
||||
iw.text.addReplacement(MetaString::CRE_PL_NAMES, result.casualties[1].begin()->first);
|
||||
const CCreature * strongest = boost::range::max_element(bc->guards, [](const CStackBasicDescriptor & a, const CStackBasicDescriptor & b)
|
||||
{
|
||||
return a.type->fightValue < b.type->fightValue;
|
||||
})->type;
|
||||
|
||||
iw.text.addReplacement(MetaString::CRE_PL_NAMES, strongest->idNumber);
|
||||
iw.text.addReplacement(loot.buildList());
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
|
||||
if (!bc->spells.empty())
|
||||
{
|
||||
std::set<SpellID> spells;
|
||||
|
||||
bool noWisdom = false;
|
||||
for (SpellID spell : bc->spells)
|
||||
{
|
||||
iw.text.addTxt (MetaString::SPELL_NAME, spell);
|
||||
if (VLC->spellh->objects[spell]->level <= hero->getSecSkillLevel(SecondarySkill::WISDOM) + 2)
|
||||
{
|
||||
spells.insert(spell);
|
||||
iw.components.push_back(Component (Component::SPELL, spell, 0, 0));
|
||||
}
|
||||
else
|
||||
noWisdom = true;
|
||||
}
|
||||
|
||||
if (!hero->getArt(ArtifactPosition::SPELLBOOK))
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 109); //no spellbook
|
||||
else if (noWisdom)
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 108); //no expert Wisdom
|
||||
if (spells.empty())
|
||||
cb->changeSpells (hero, true, spells);
|
||||
}
|
||||
loot.clear();
|
||||
iw.components.clear();
|
||||
iw.text.clear();
|
||||
|
||||
//grant creatures
|
||||
CCreatureSet ourArmy;
|
||||
for (auto it = bc->creatures.cbegin(); it != bc->creatures.cend(); it++)
|
||||
for (auto slot : bc->creatures)
|
||||
{
|
||||
SlotID slot = ourArmy.getSlotFor(it->first);
|
||||
ourArmy.addToSlot(slot, it->first, it->second);
|
||||
ourArmy.addToSlot(ourArmy.getSlotFor(slot.type->idNumber), slot.type->idNumber, slot.count);
|
||||
}
|
||||
|
||||
for (auto & elem : ourArmy.Slots())
|
||||
{
|
||||
iw.components.push_back(Component(*elem.second));
|
||||
@ -362,7 +305,15 @@ void CBank::battleFinished(const CGHeroInstance *hero, const BattleResult &resul
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->giveCreatures(this, hero, ourArmy, false);
|
||||
}
|
||||
cb->setObjProperty (id, ObjProperty::BANK_CLEAR_CONFIG, 0); //bc = nullptr
|
||||
cb->setObjProperty (id, ObjProperty::BANK_CLEAR, 0); //bc = nullptr
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
||||
{
|
||||
if (result.winner == 0)
|
||||
{
|
||||
doVisit(hero);
|
||||
}
|
||||
}
|
||||
|
||||
@ -370,74 +321,9 @@ void CBank::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) cons
|
||||
{
|
||||
if (answer)
|
||||
{
|
||||
cb->startBattleI(hero, this, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CGPyramid::initObj()
|
||||
{
|
||||
std::vector<SpellID> available;
|
||||
cb->getAllowedSpells (available, 5);
|
||||
if (available.size())
|
||||
{
|
||||
bc = VLC->objh->banksInfo[21].front(); //TODO: remove hardcoded value?
|
||||
spell = *RandomGeneratorUtil::nextItem(available, cb->gameState()->getRandomGenerator());
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->errorStream() <<"No spells available for Pyramid! Object set to empty.";
|
||||
}
|
||||
setPropertyDer(ObjProperty::BANK_INIT_ARMY, cb->gameState()->getRandomGenerator().nextInt()); //set guards at game start
|
||||
}
|
||||
const std::string & CGPyramid::getHoverText() const
|
||||
{
|
||||
hoverName = VLC->objh->creBanksNames[21]+ " " + visitedTxt((bc==nullptr));
|
||||
return hoverName;
|
||||
}
|
||||
void CGPyramid::onHeroVisit (const CGHeroInstance * h) const
|
||||
{
|
||||
if (bc)
|
||||
{
|
||||
BlockingDialog bd (true, false);
|
||||
bd.player = h->getOwner();
|
||||
bd.soundID = soundBase::MYSTERY;
|
||||
bd.text << VLC->generaltexth->advobtxt[105];
|
||||
cb->showBlockingDialog(&bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = h->getOwner();
|
||||
iw.text << VLC->generaltexth->advobtxt[107];
|
||||
iw.components.push_back (Component (Component::LUCK, 0 , -2, 0));
|
||||
GiveBonus gb;
|
||||
gb.bonus = Bonus(Bonus::ONE_BATTLE,Bonus::LUCK,Bonus::OBJECT,-2,id.getNum(),VLC->generaltexth->arraytxt[70]);
|
||||
gb.id = h->id.getNum();
|
||||
cb->giveHeroBonus(&gb);
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
}
|
||||
|
||||
void CGPyramid::battleFinished(const CGHeroInstance *hero, const BattleResult &result) const
|
||||
{
|
||||
if (result.winner == 0)
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.player = hero->getOwner();
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 106);
|
||||
iw.text.addTxt (MetaString::SPELL_NAME, spell);
|
||||
if (!hero->getArt(ArtifactPosition::SPELLBOOK))
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 109); //no spellbook
|
||||
else if (hero->getSecSkillLevel(SecondarySkill::WISDOM) < 3)
|
||||
iw.text.addTxt (MetaString::ADVOB_TXT, 108); //no expert Wisdom
|
||||
if (bc) // not looted bank
|
||||
cb->startBattleI(hero, this, true);
|
||||
else
|
||||
{
|
||||
std::set<SpellID> spells;
|
||||
spells.insert (SpellID(spell));
|
||||
cb->changeSpells (hero, true, spells);
|
||||
iw.components.push_back(Component (Component::SPELL, spell, 0, 0));
|
||||
}
|
||||
cb->showInfoDialog(&iw);
|
||||
cb->setObjProperty (id, ObjProperty::BANK_CLEAR_CONFIG, 0);
|
||||
doVisit(hero);
|
||||
}
|
||||
}
|
||||
|
@ -13,19 +13,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
class BankConfig;
|
||||
class CBankInstanceConstructor;
|
||||
|
||||
class DLL_LINKAGE CBank : public CArmedInstance
|
||||
{
|
||||
public:
|
||||
int index; //banks have unusal numbering - see ZCRBANK.txt and initObj()
|
||||
BankConfig *bc;
|
||||
double multiplier; //for improved banks script
|
||||
std::vector<ui32> artifacts; //fixed and deterministic
|
||||
std::unique_ptr<BankConfig> bc;
|
||||
ui32 daycounter;
|
||||
ui32 resetDuration;
|
||||
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
void doVisit(const CGHeroInstance * hero) const;
|
||||
|
||||
public:
|
||||
CBank();
|
||||
~CBank();
|
||||
|
||||
void setConfig(const BankConfig & bc);
|
||||
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
void initialize() const;
|
||||
void reset(ui16 var1);
|
||||
void newTurn() const override;
|
||||
bool wasVisited (PlayerColor player) const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
@ -35,25 +42,8 @@ class DLL_LINKAGE CBank : public CArmedInstance
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CArmedInstance&>(*this);
|
||||
h & index & multiplier & artifacts & daycounter & bc;
|
||||
h & daycounter & bc & resetDuration;
|
||||
}
|
||||
protected:
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
};
|
||||
class DLL_LINKAGE CGPyramid : public CBank
|
||||
{
|
||||
public:
|
||||
ui16 spell;
|
||||
|
||||
void initObj() override;
|
||||
const std::string & getHoverText() const override;
|
||||
void newTurn() const override {}; //empty, no reset
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CBank&>(*this);
|
||||
h & spell;
|
||||
}
|
||||
friend class CBankInstanceConstructor;
|
||||
};
|
||||
|
@ -35,13 +35,13 @@ CObjectClassesHandler::CObjectClassesHandler()
|
||||
SET_HANDLER_CLASS("dwelling", CDwellingInstanceConstructor);
|
||||
SET_HANDLER_CLASS("hero", CHeroInstanceConstructor);
|
||||
SET_HANDLER_CLASS("town", CTownInstanceConstructor);
|
||||
SET_HANDLER_CLASS("bank", CBankInstanceConstructor);
|
||||
|
||||
SET_HANDLER_CLASS("static", CObstacleConstructor);
|
||||
SET_HANDLER_CLASS("", CObstacleConstructor);
|
||||
|
||||
SET_HANDLER("generic", CGObjectInstance);
|
||||
SET_HANDLER("market", CGMarket);
|
||||
SET_HANDLER("bank", CBank);
|
||||
SET_HANDLER("cartographer", CCartographer);
|
||||
SET_HANDLER("artifact", CGArtifact);
|
||||
SET_HANDLER("blackMarket", CGBlackMarket);
|
||||
@ -67,7 +67,6 @@ CObjectClassesHandler::CObjectClassesHandler()
|
||||
SET_HANDLER("pandora", CGPandoraBox);
|
||||
SET_HANDLER("pickable", CGPickable);
|
||||
SET_HANDLER("prison", CGHeroInstance);
|
||||
SET_HANDLER("pyramid", CGPyramid);
|
||||
SET_HANDLER("questGuard", CGQuestGuard);
|
||||
SET_HANDLER("resource", CGResource);
|
||||
SET_HANDLER("scholar", CGScholar);
|
||||
@ -130,6 +129,11 @@ si32 selectNextID(const JsonNode & fixedID, const Map & map, si32 defaultID)
|
||||
|
||||
void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContainter * obj)
|
||||
{
|
||||
if (!handlerConstructors.count(obj->handlerName))
|
||||
{
|
||||
logGlobal->errorStream() << "Handler with name " << obj->handlerName << " was not found!";
|
||||
return;
|
||||
}
|
||||
auto handler = handlerConstructors.at(obj->handlerName)();
|
||||
handler->init(entry);
|
||||
|
||||
|
@ -50,20 +50,45 @@ struct RandomMapInfo
|
||||
class IObjectInfo
|
||||
{
|
||||
public:
|
||||
virtual bool givesResources() const = 0;
|
||||
struct CArmyStructure
|
||||
{
|
||||
ui32 totalStrength;
|
||||
ui32 shootersStrength;
|
||||
ui32 flyersStrength;
|
||||
ui32 walkersStrength;
|
||||
|
||||
virtual bool givesExperience() const = 0;
|
||||
virtual bool givesMana() const = 0;
|
||||
virtual bool givesMovement() const = 0;
|
||||
CArmyStructure() :
|
||||
totalStrength(0),
|
||||
shootersStrength(0),
|
||||
flyersStrength(0),
|
||||
walkersStrength(0)
|
||||
{}
|
||||
|
||||
virtual bool givesPrimarySkills() const = 0;
|
||||
virtual bool givesSecondarySkills() const = 0;
|
||||
bool operator <(const CArmyStructure & other)
|
||||
{
|
||||
return this->totalStrength < other.totalStrength;
|
||||
}
|
||||
};
|
||||
|
||||
virtual bool givesArtifacts() const = 0;
|
||||
virtual bool givesCreatures() const = 0;
|
||||
virtual bool givesSpells() const = 0;
|
||||
/// Returns possible composition of guards. Actual guards would be
|
||||
/// somewhere between these two values
|
||||
virtual CArmyStructure minGuards() const { return CArmyStructure(); }
|
||||
virtual CArmyStructure maxGuards() const { return CArmyStructure(); }
|
||||
|
||||
virtual bool givesBonuses() const = 0;
|
||||
virtual bool givesResources() const { return false; }
|
||||
|
||||
virtual bool givesExperience() const { return false; }
|
||||
virtual bool givesMana() const { return false; }
|
||||
virtual bool givesMovement() const { return false; }
|
||||
|
||||
virtual bool givesPrimarySkills() const { return false; }
|
||||
virtual bool givesSecondarySkills() const { return false; }
|
||||
|
||||
virtual bool givesArtifacts() const { return false; }
|
||||
virtual bool givesCreatures() const { return false; }
|
||||
virtual bool givesSpells() const { return false; }
|
||||
|
||||
virtual bool givesBonuses() const { return false; }
|
||||
};
|
||||
|
||||
class CGObjectInstance;
|
||||
@ -118,7 +143,7 @@ public:
|
||||
virtual void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const = 0;
|
||||
|
||||
/// Returns object configuration, if available. Othervice returns NULL
|
||||
virtual const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const = 0;
|
||||
virtual std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const = 0;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
|
@ -108,53 +108,6 @@ void IObjectInterface::garrisonDialogClosed(const CGHeroInstance *hero) const
|
||||
void IObjectInterface::heroLevelUpDone(const CGHeroInstance *hero) const
|
||||
{}
|
||||
|
||||
// Bank helper. Find the creature ID and their number, and store the
|
||||
// result in storage (either guards or reward creatures).
|
||||
static void readCreatures(const JsonNode &creature, std::vector< std::pair <CreatureID, ui32> > &storage)
|
||||
{
|
||||
std::pair<CreatureID, si32> creInfo = std::make_pair(CreatureID::NONE, 0);
|
||||
|
||||
//TODO: replace numeric id's with mod-friendly string id's
|
||||
creInfo.second = creature["number"].Float();
|
||||
creInfo.first = CreatureID((si32)creature["id"].Float());
|
||||
storage.push_back(creInfo);
|
||||
}
|
||||
|
||||
// Bank helper. Process a bank level.
|
||||
static void readBankLevel(const JsonNode &level, BankConfig &bc)
|
||||
{
|
||||
int idx;
|
||||
|
||||
bc.chance = level["chance"].Float();
|
||||
|
||||
for(const JsonNode &creature : level["guards"].Vector())
|
||||
{
|
||||
readCreatures(creature, bc.guards);
|
||||
}
|
||||
|
||||
bc.upgradeChance = level["upgrade_chance"].Float();
|
||||
bc.combatValue = level["combat_value"].Float();
|
||||
|
||||
bc.resources = Res::ResourceSet(level["reward_resources"]);
|
||||
|
||||
for(const JsonNode &creature : level["reward_creatures"].Vector())
|
||||
{
|
||||
readCreatures(creature, bc.creatures);
|
||||
}
|
||||
|
||||
bc.artifacts.resize(4);
|
||||
idx = 0;
|
||||
for(const JsonNode &artifact : level["reward_artifacts"].Vector())
|
||||
{
|
||||
bc.artifacts[idx] = artifact.Float();
|
||||
idx ++;
|
||||
}
|
||||
|
||||
bc.value = level["value"].Float();
|
||||
bc.rewardDifficulty = level["profitability"].Float();
|
||||
bc.easiest = level["easiest"].Float();
|
||||
}
|
||||
|
||||
CObjectHandler::CObjectHandler()
|
||||
{
|
||||
logGlobal->traceStream() << "\t\tReading resources prices ";
|
||||
@ -164,62 +117,8 @@ CObjectHandler::CObjectHandler()
|
||||
resVals.push_back(price.Float());
|
||||
}
|
||||
logGlobal->traceStream() << "\t\tDone loading resource prices!";
|
||||
|
||||
logGlobal->traceStream() << "\t\tReading banks configs";
|
||||
const JsonNode config3(ResourceID("config/bankconfig.json"));
|
||||
int bank_num = 0;
|
||||
for(const JsonNode &bank : config3["banks"].Vector())
|
||||
{
|
||||
creBanksNames[bank_num] = bank["name"].String();
|
||||
|
||||
int level_num = 0;
|
||||
for(const JsonNode &level : bank["levels"].Vector())
|
||||
{
|
||||
banksInfo[bank_num].push_back(new BankConfig);
|
||||
BankConfig &bc = *banksInfo[bank_num].back();
|
||||
bc.level = level_num;
|
||||
|
||||
readBankLevel(level, bc);
|
||||
level_num ++;
|
||||
}
|
||||
|
||||
bank_num ++;
|
||||
}
|
||||
logGlobal->traceStream() << "\t\tDone loading banks configs";
|
||||
}
|
||||
|
||||
CObjectHandler::~CObjectHandler()
|
||||
{
|
||||
for(auto & mapEntry : banksInfo)
|
||||
{
|
||||
for(auto & vecEntry : mapEntry.second)
|
||||
{
|
||||
vecEntry.dellNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CObjectHandler::bankObjToIndex (const CGObjectInstance * obj)
|
||||
{
|
||||
switch (obj->ID) //find appriopriate key
|
||||
{
|
||||
case Obj::CREATURE_BANK:
|
||||
return obj->subID;
|
||||
case Obj::DERELICT_SHIP:
|
||||
return 8;
|
||||
case Obj::DRAGON_UTOPIA:
|
||||
return 10;
|
||||
case Obj::CRYPT:
|
||||
return 9;
|
||||
case Obj::SHIPWRECK:
|
||||
return 7;
|
||||
case Obj::PYRAMID:
|
||||
return 21;
|
||||
default:
|
||||
logGlobal->warnStream() << "Unrecognized Bank indetifier!";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
PlayerColor CGObjectInstance::getOwner() const
|
||||
{
|
||||
//if (state)
|
||||
|
@ -163,41 +163,15 @@ private:
|
||||
CGObjectInstance * obj;
|
||||
};
|
||||
|
||||
struct BankConfig
|
||||
{
|
||||
BankConfig() {level = chance = upgradeChance = combatValue = value = rewardDifficulty = easiest = 0; };
|
||||
ui8 level; //1 - 4, how hard the battle will be
|
||||
ui8 chance; //chance for this level being chosen
|
||||
ui8 upgradeChance; //chance for creatures to be in upgraded versions
|
||||
std::vector< std::pair <CreatureID, ui32> > guards; //creature ID, amount
|
||||
ui32 combatValue; //how hard are guards of this level
|
||||
Res::ResourceSet resources; //resources given in case of victory
|
||||
std::vector< std::pair <CreatureID, ui32> > creatures; //creatures granted in case of victory (creature ID, amount)
|
||||
std::vector<ui16> artifacts; //number of artifacts given in case of victory [0] -> treasure, [1] -> minor [2] -> major [3] -> relic
|
||||
ui32 value; //overall value of given things
|
||||
ui32 rewardDifficulty; //proportion of reward value to difficulty of guards; how profitable is this creature Bank config
|
||||
ui16 easiest; //?!?
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & level & chance & upgradeChance & guards & combatValue & resources & creatures & artifacts & value & rewardDifficulty & easiest;
|
||||
}
|
||||
};
|
||||
|
||||
class DLL_LINKAGE CObjectHandler
|
||||
{
|
||||
public:
|
||||
std::map <ui32, std::vector < ConstTransitivePtr<BankConfig> > > banksInfo; //[index][preset]
|
||||
std::map <ui32, std::string> creBanksNames; //[crebank index] -> name of this creature bank
|
||||
std::vector<ui32> resVals; //default values of resources in gold
|
||||
|
||||
CObjectHandler();
|
||||
~CObjectHandler();
|
||||
|
||||
int bankObjToIndex (const CGObjectInstance * obj);
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & banksInfo & creBanksNames & resVals;
|
||||
h & resVals;
|
||||
}
|
||||
};
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "../StringConstants.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "JsonRandom.h"
|
||||
|
||||
/*
|
||||
* CRewardableConstructor.cpp, part of VCMI engine
|
||||
@ -16,100 +17,6 @@
|
||||
*/
|
||||
|
||||
namespace {
|
||||
si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0)
|
||||
{
|
||||
if (value.isNull())
|
||||
return defaultValue;
|
||||
if (value.getType() == JsonNode::DATA_FLOAT)
|
||||
return value.Float();
|
||||
si32 min = value["min"].Float();
|
||||
si32 max = value["max"].Float();
|
||||
return rng.getIntRange(min, max)();
|
||||
}
|
||||
|
||||
TResources loadResources(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
TResources ret;
|
||||
for (size_t i=0; i<GameConstants::RESOURCE_QUANTITY; i++)
|
||||
{
|
||||
ret[i] = loadValue(value[GameConstants::RESOURCE_NAMES[i]], rng);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::vector<si32> ret;
|
||||
for (auto & name : PrimarySkill::names)
|
||||
{
|
||||
ret.push_back(loadValue(value[name], rng));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::map<SecondarySkill, si32> loadSecondary(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::map<SecondarySkill, si32> ret;
|
||||
for (auto & pair : value.Struct())
|
||||
{
|
||||
SecondarySkill id(VLC->modh->identifiers.getIdentifier(pair.second.meta, "skill", pair.first).get());
|
||||
ret[id] = loadValue(pair.second, rng);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::vector<ArtifactID> ret;
|
||||
for (const JsonNode & entry : value.Vector())
|
||||
{
|
||||
ArtifactID art(VLC->modh->identifiers.getIdentifier("artifact", entry).get());
|
||||
ret.push_back(art);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::vector<SpellID> ret;
|
||||
for (const JsonNode & entry : value.Vector())
|
||||
{
|
||||
SpellID spell(VLC->modh->identifiers.getIdentifier("spell", entry).get());
|
||||
ret.push_back(spell);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::vector<CStackBasicDescriptor> ret;
|
||||
for (auto & pair : value.Struct())
|
||||
{
|
||||
CStackBasicDescriptor stack;
|
||||
stack.type = VLC->creh->creatures[VLC->modh->identifiers.getIdentifier(pair.second.meta, "creature", pair.first).get()];
|
||||
stack.count = loadValue(pair.second, rng);
|
||||
ret.push_back(stack);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Bonus> loadBonuses(const JsonNode & value)
|
||||
{
|
||||
std::vector<Bonus> ret;
|
||||
for (const JsonNode & entry : value.Vector())
|
||||
{
|
||||
Bonus * bonus = JsonUtils::parseBonus(entry);
|
||||
ret.push_back(*bonus);
|
||||
delete bonus;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Component> loadComponents(const JsonNode & value)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
MetaString loadMessage(const JsonNode & value)
|
||||
{
|
||||
MetaString ret;
|
||||
@ -167,38 +74,42 @@ void CRandomRewardObjectInfo::configureObject(CRewardableObject * object, CRando
|
||||
const JsonNode & limiter = reward["limiter"];
|
||||
CVisitInfo info;
|
||||
// load limiter
|
||||
info.limiter.numOfGrants = loadValue(limiter["numOfGrants"], rng);
|
||||
info.limiter.dayOfWeek = loadValue(limiter["dayOfWeek"], rng);
|
||||
info.limiter.minLevel = loadValue(limiter["minLevel"], rng);
|
||||
info.limiter.resources = loadResources(limiter["resources"], rng);
|
||||
info.limiter.numOfGrants = JsonRandom::loadValue(limiter["numOfGrants"], rng);
|
||||
info.limiter.dayOfWeek = JsonRandom::loadValue(limiter["dayOfWeek"], rng);
|
||||
info.limiter.minLevel = JsonRandom::loadValue(limiter["minLevel"], rng);
|
||||
info.limiter.resources = JsonRandom::loadResources(limiter["resources"], rng);
|
||||
|
||||
info.limiter.primary = loadPrimary(limiter["primary"], rng);
|
||||
info.limiter.secondary = loadSecondary(limiter["secondary"], rng);
|
||||
info.limiter.artifacts = loadArtifacts(limiter["artifacts"], rng);
|
||||
info.limiter.creatures = loadCreatures(limiter["creatures"], rng);
|
||||
info.limiter.primary = JsonRandom::loadPrimary(limiter["primary"], rng);
|
||||
info.limiter.secondary = JsonRandom::loadSecondary(limiter["secondary"], rng);
|
||||
info.limiter.artifacts = JsonRandom::loadArtifacts(limiter["artifacts"], rng);
|
||||
info.limiter.creatures = JsonRandom::loadCreatures(limiter["creatures"], rng);
|
||||
|
||||
info.reward.resources = loadResources(reward["resources"], rng);
|
||||
info.reward.resources = JsonRandom::loadResources(reward["resources"], rng);
|
||||
|
||||
info.reward.gainedExp = loadValue(reward["gainedExp"], rng);
|
||||
info.reward.gainedLevels = loadValue(reward["gainedLevels"], rng);
|
||||
info.reward.gainedExp = JsonRandom::loadValue(reward["gainedExp"], rng);
|
||||
info.reward.gainedLevels = JsonRandom::loadValue(reward["gainedLevels"], rng);
|
||||
|
||||
info.reward.manaDiff = loadValue(reward["manaPoints"], rng);
|
||||
info.reward.manaPercentage = loadValue(reward["manaPercentage"], rng, -1);
|
||||
info.reward.manaDiff = JsonRandom::loadValue(reward["manaPoints"], rng);
|
||||
info.reward.manaPercentage = JsonRandom::loadValue(reward["manaPercentage"], rng, -1);
|
||||
|
||||
info.reward.movePoints = loadValue(reward["movePoints"], rng);
|
||||
info.reward.movePercentage = loadValue(reward["movePercentage"], rng, -1);
|
||||
info.reward.movePoints = JsonRandom::loadValue(reward["movePoints"], rng);
|
||||
info.reward.movePercentage = JsonRandom::loadValue(reward["movePercentage"], rng, -1);
|
||||
|
||||
info.reward.bonuses = loadBonuses(reward["bonuses"]);
|
||||
info.reward.bonuses = JsonRandom::loadBonuses(reward["bonuses"]);
|
||||
|
||||
info.reward.primary = loadPrimary(reward["primary"], rng);
|
||||
info.reward.secondary = loadSecondary(reward["secondary"], rng);
|
||||
info.reward.primary = JsonRandom::loadPrimary(reward["primary"], rng);
|
||||
info.reward.secondary = JsonRandom::loadSecondary(reward["secondary"], rng);
|
||||
|
||||
info.reward.artifacts = loadArtifacts(reward["artifacts"], rng);
|
||||
info.reward.spells = loadSpells(reward["spells"], rng);
|
||||
info.reward.creatures = loadCreatures(reward["creatures"], rng);
|
||||
std::vector<SpellID> spells;
|
||||
for (size_t i=0; i<6; i++)
|
||||
IObjectInterface::cb->getAllowedSpells(spells, i);
|
||||
|
||||
info.reward.artifacts = JsonRandom::loadArtifacts(reward["artifacts"], rng);
|
||||
info.reward.spells = JsonRandom::loadSpells(reward["spells"], rng, spells);
|
||||
info.reward.creatures = JsonRandom::loadCreatures(reward["creatures"], rng);
|
||||
|
||||
info.message = loadMessage(reward["message"]);
|
||||
info.selectChance = loadValue(reward["selectChance"], rng);
|
||||
info.selectChance = JsonRandom::loadValue(reward["selectChance"], rng);
|
||||
}
|
||||
|
||||
object->onSelect = loadMessage(parameters["onSelectMessage"]);
|
||||
@ -284,7 +195,7 @@ void CRewardableConstructor::configureObject(CGObjectInstance * object, CRandomG
|
||||
objectInfo.configureObject(dynamic_cast<CRewardableObject*>(object), rng);
|
||||
}
|
||||
|
||||
const IObjectInfo * CRewardableConstructor::getObjectInfo(ObjectTemplate tmpl) const
|
||||
std::unique_ptr<IObjectInfo> CRewardableConstructor::getObjectInfo(ObjectTemplate tmpl) const
|
||||
{
|
||||
return &objectInfo;
|
||||
return std::unique_ptr<IObjectInfo>(new CRandomRewardObjectInfo(objectInfo));
|
||||
}
|
||||
|
@ -54,5 +54,5 @@ public:
|
||||
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const override;
|
||||
|
||||
const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const override;
|
||||
std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const override;
|
||||
};
|
||||
|
@ -3,9 +3,11 @@
|
||||
|
||||
#include "CGTownInstance.h"
|
||||
#include "CGHeroInstance.h"
|
||||
#include "CBank.h"
|
||||
#include "../mapping/CMap.h"
|
||||
#include "../CHeroHandler.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "JsonRandom.h"
|
||||
|
||||
/*
|
||||
* CommonConstructors.cpp, part of VCMI engine
|
||||
@ -176,33 +178,6 @@ CGObjectInstance * CDwellingInstanceConstructor::create(ObjectTemplate tmpl) con
|
||||
return obj;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0)
|
||||
{
|
||||
if (value.isNull())
|
||||
return defaultValue;
|
||||
if (value.getType() == JsonNode::DATA_FLOAT)
|
||||
return value.Float();
|
||||
si32 min = value["min"].Float();
|
||||
si32 max = value["max"].Float();
|
||||
return rng.getIntRange(min, max)();
|
||||
}
|
||||
|
||||
std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::vector<CStackBasicDescriptor> ret;
|
||||
for (auto & pair : value.Struct())
|
||||
{
|
||||
CStackBasicDescriptor stack;
|
||||
stack.type = VLC->creh->creatures[VLC->modh->identifiers.getIdentifier(pair.second.meta, "creature", pair.first).get()];
|
||||
stack.count = loadValue(pair.second, rng);
|
||||
ret.push_back(stack);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator &rng) const
|
||||
{
|
||||
CGDwelling * dwelling = dynamic_cast<CGDwelling*>(object);
|
||||
@ -221,7 +196,7 @@ void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CR
|
||||
const CCreature * crea = availableCreatures.at(0).at(0);
|
||||
dwelling->putStack(SlotID(0), new CStackInstance(crea->idNumber, crea->growth * 3 ));
|
||||
}
|
||||
else for (auto & stack : loadCreatures(guards, rng))
|
||||
else for (auto & stack : JsonRandom::loadCreatures(guards, rng))
|
||||
{
|
||||
dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->idNumber, stack.count));
|
||||
}
|
||||
@ -237,3 +212,175 @@ bool CDwellingInstanceConstructor::producesCreature(const CCreature * crea) cons
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CBankInstanceConstructor::CBankInstanceConstructor()
|
||||
{
|
||||
}
|
||||
|
||||
void CBankInstanceConstructor::initTypeData(const JsonNode & input)
|
||||
{
|
||||
//TODO: name = input["name"].String();
|
||||
levels = input["levels"].Vector();
|
||||
bankResetDuration = input["resetDuration"].Float();
|
||||
}
|
||||
|
||||
CGObjectInstance *CBankInstanceConstructor::create(ObjectTemplate tmpl) const
|
||||
{
|
||||
return createTyped(tmpl);
|
||||
}
|
||||
|
||||
BankConfig CBankInstanceConstructor::generateConfig(const JsonNode & level, CRandomGenerator & rng) const
|
||||
{
|
||||
BankConfig bc;
|
||||
|
||||
bc.chance = level["chance"].Float();
|
||||
|
||||
bc.guards = JsonRandom::loadCreatures(level["guards"], rng);
|
||||
bc.upgradeChance = level["upgrade_chance"].Float();
|
||||
bc.combatValue = level["combat_value"].Float();
|
||||
|
||||
std::vector<SpellID> spells;
|
||||
for (size_t i=0; i<6; i++)
|
||||
IObjectInterface::cb->getAllowedSpells(spells, i);
|
||||
|
||||
bc.resources = Res::ResourceSet(level["reward"]["resources"]);
|
||||
bc.creatures = JsonRandom::loadCreatures(level["reward"]["creatures"], rng);
|
||||
bc.artifacts = JsonRandom::loadArtifacts(level["reward"]["artifacts"], rng);
|
||||
bc.spells = JsonRandom::loadSpells(level["reward"]["spells"], rng, spells);
|
||||
|
||||
bc.value = level["value"].Float();
|
||||
|
||||
return bc;
|
||||
}
|
||||
|
||||
void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const
|
||||
{
|
||||
auto bank = dynamic_cast<CBank*>(object);
|
||||
|
||||
bank->resetDuration = bankResetDuration;
|
||||
|
||||
si32 totalChance = 0;
|
||||
for (auto & node : levels)
|
||||
totalChance += node["chance"].Float();
|
||||
|
||||
assert(totalChance != 0);
|
||||
|
||||
si32 selectedChance = rng.nextInt(totalChance - 1);
|
||||
|
||||
for (auto & node : levels)
|
||||
{
|
||||
if (selectedChance < node["chance"].Float())
|
||||
{
|
||||
bank->setConfig(generateConfig(node, rng));
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedChance -= node["chance"].Float();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CBankInfo::CBankInfo(JsonVector config):
|
||||
config(config)
|
||||
{
|
||||
}
|
||||
|
||||
static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount)
|
||||
{
|
||||
army.totalStrength += crea->fightValue * amount;
|
||||
|
||||
bool walker = true;
|
||||
if (crea->hasBonusOfType(Bonus::SHOOTER))
|
||||
{
|
||||
army.shootersStrength += crea->fightValue * amount;
|
||||
walker = false;
|
||||
}
|
||||
if (crea->hasBonusOfType(Bonus::FLYING))
|
||||
{
|
||||
army.flyersStrength += crea->fightValue * amount;
|
||||
walker = false;
|
||||
}
|
||||
if (walker)
|
||||
army.walkersStrength += crea->fightValue * amount;
|
||||
}
|
||||
|
||||
IObjectInfo::CArmyStructure CBankInfo::minGuards() const
|
||||
{
|
||||
std::vector<IObjectInfo::CArmyStructure> armies;
|
||||
for (auto configEntry : config)
|
||||
{
|
||||
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"]);
|
||||
IObjectInfo::CArmyStructure army;
|
||||
for (auto & stack : stacks)
|
||||
{
|
||||
assert(!stack.allowedCreatures.empty());
|
||||
auto weakest = boost::range::min_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b)
|
||||
{
|
||||
return a->fightValue < b->fightValue;
|
||||
});
|
||||
addStackToArmy(army, *weakest, stack.minAmount);
|
||||
}
|
||||
armies.push_back(army);
|
||||
}
|
||||
return *boost::range::min_element(armies);
|
||||
}
|
||||
|
||||
IObjectInfo::CArmyStructure CBankInfo::maxGuards() const
|
||||
{
|
||||
std::vector<IObjectInfo::CArmyStructure> armies;
|
||||
for (auto configEntry : config)
|
||||
{
|
||||
auto stacks = JsonRandom::evaluateCreatures(configEntry["guards"]);
|
||||
IObjectInfo::CArmyStructure army;
|
||||
for (auto & stack : stacks)
|
||||
{
|
||||
assert(!stack.allowedCreatures.empty());
|
||||
auto strongest = boost::range::max_element(stack.allowedCreatures, [](const CCreature * a, const CCreature * b)
|
||||
{
|
||||
return a->fightValue < b->fightValue;
|
||||
});
|
||||
addStackToArmy(army, *strongest, stack.maxAmount);
|
||||
}
|
||||
armies.push_back(army);
|
||||
}
|
||||
return *boost::range::max_element(armies);
|
||||
}
|
||||
|
||||
bool CBankInfo::givesResources() const
|
||||
{
|
||||
for (const JsonNode & node : config)
|
||||
if (!node["reward"]["resources"].isNull())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBankInfo::givesArtifacts() const
|
||||
{
|
||||
for (const JsonNode & node : config)
|
||||
if (!node["reward"]["artifacts"].isNull())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBankInfo::givesCreatures() const
|
||||
{
|
||||
for (const JsonNode & node : config)
|
||||
if (!node["reward"]["creatures"].isNull())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CBankInfo::givesSpells() const
|
||||
{
|
||||
for (const JsonNode & node : config)
|
||||
if (!node["reward"]["spells"].isNull())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<IObjectInfo> CBankInstanceConstructor::getObjectInfo(ObjectTemplate tmpl) const
|
||||
{
|
||||
return std::unique_ptr<IObjectInfo>(new CBankInfo(levels));
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ class CGDwelling;
|
||||
//class CGArtifact;
|
||||
//class CGCreature;
|
||||
class CHeroClass;
|
||||
class CBank;
|
||||
class CStackBasicDescriptor;
|
||||
|
||||
/// Class that is used for objects that do not have dedicated handler
|
||||
template<class ObjectType>
|
||||
@ -45,7 +47,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual const IObjectInfo * getObjectInfo(ObjectTemplate tmpl) const
|
||||
virtual std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -63,6 +65,7 @@ class CTownInstanceConstructor : public CDefaultObjectTypeHandler<CGTownInstance
|
||||
JsonNode filtersJson;
|
||||
protected:
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
|
||||
public:
|
||||
CFaction * faction;
|
||||
@ -70,7 +73,6 @@ public:
|
||||
|
||||
CTownInstanceConstructor();
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||
void afterLoadFinalization();
|
||||
|
||||
@ -86,6 +88,7 @@ class CHeroInstanceConstructor : public CDefaultObjectTypeHandler<CGHeroInstance
|
||||
JsonNode filtersJson;
|
||||
protected:
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
|
||||
public:
|
||||
CHeroClass * heroClass;
|
||||
@ -93,7 +96,6 @@ public:
|
||||
|
||||
CHeroInstanceConstructor();
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||
void afterLoadFinalization();
|
||||
|
||||
@ -112,12 +114,12 @@ class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling
|
||||
|
||||
protected:
|
||||
bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
|
||||
public:
|
||||
|
||||
CDwellingInstanceConstructor();
|
||||
CGObjectInstance * create(ObjectTemplate tmpl) const;
|
||||
void initTypeData(const JsonNode & input);
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||
|
||||
bool producesCreature(const CCreature * crea) const;
|
||||
@ -128,3 +130,56 @@ public:
|
||||
h & static_cast<CDefaultObjectTypeHandler<CGDwelling>&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
struct BankConfig
|
||||
{
|
||||
BankConfig() { chance = upgradeChance = combatValue = value = 0; };
|
||||
ui32 value; //overall value of given things
|
||||
ui32 chance; //chance for this level being chosen
|
||||
ui32 upgradeChance; //chance for creatures to be in upgraded versions
|
||||
ui32 combatValue; //how hard are guards of this level
|
||||
std::vector<CStackBasicDescriptor> guards; //creature ID, amount
|
||||
Res::ResourceSet resources; //resources given in case of victory
|
||||
std::vector<CStackBasicDescriptor> creatures; //creatures granted in case of victory (creature ID, amount)
|
||||
std::vector<ArtifactID> artifacts; //artifacts given in case of victory
|
||||
std::vector<SpellID> spells; // granted spell(s), for Pyramid
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & chance & upgradeChance & guards & combatValue & resources & creatures & artifacts & value & spells;
|
||||
}
|
||||
};
|
||||
|
||||
class CBankInfo : public IObjectInfo
|
||||
{
|
||||
JsonVector config;
|
||||
public:
|
||||
CBankInfo(JsonVector config);
|
||||
|
||||
CArmyStructure minGuards() const;
|
||||
CArmyStructure maxGuards() const;
|
||||
bool givesResources() const;
|
||||
bool givesArtifacts() const;
|
||||
bool givesCreatures() const;
|
||||
bool givesSpells() const;
|
||||
};
|
||||
|
||||
class CBankInstanceConstructor : public CDefaultObjectTypeHandler<CBank>
|
||||
{
|
||||
BankConfig generateConfig(const JsonNode & conf, CRandomGenerator & rng) const;
|
||||
|
||||
JsonVector levels;
|
||||
protected:
|
||||
void initTypeData(const JsonNode & input);
|
||||
|
||||
public:
|
||||
// all banks of this type will be reset N days after clearing,
|
||||
si32 bankResetDuration;
|
||||
|
||||
CBankInstanceConstructor();
|
||||
|
||||
CGObjectInstance *create(ObjectTemplate tmpl) const;
|
||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||
|
||||
std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const;
|
||||
};
|
||||
|
225
lib/mapObjects/JsonRandom.cpp
Normal file
225
lib/mapObjects/JsonRandom.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
*
|
||||
* CRewardableObject.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
#include "StdInc.h"
|
||||
#include "JsonRandom.h"
|
||||
|
||||
#include "../JsonNode.h"
|
||||
#include "../CRandomGenerator.h"
|
||||
#include "../StringConstants.h"
|
||||
#include "../VCMI_Lib.h"
|
||||
#include "../CModHandler.h"
|
||||
#include "../CArtHandler.h"
|
||||
#include "../CCreatureHandler.h"
|
||||
#include "../CCreatureSet.h"
|
||||
#include "../CSpellHandler.h"
|
||||
|
||||
namespace JsonRandom
|
||||
{
|
||||
si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue)
|
||||
{
|
||||
if (value.isNull())
|
||||
return defaultValue;
|
||||
if (value.getType() == JsonNode::DATA_FLOAT)
|
||||
return value.Float();
|
||||
if (!value["amount"].isNull())
|
||||
return value["amount"].Float();
|
||||
si32 min = value["min"].Float();
|
||||
si32 max = value["max"].Float();
|
||||
return rng.getIntRange(min, max)();
|
||||
}
|
||||
|
||||
TResources loadResources(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
TResources ret;
|
||||
for (size_t i=0; i<GameConstants::RESOURCE_QUANTITY; i++)
|
||||
{
|
||||
ret[i] = loadValue(value[GameConstants::RESOURCE_NAMES[i]], rng);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::vector<si32> ret;
|
||||
for (auto & name : PrimarySkill::names)
|
||||
{
|
||||
ret.push_back(loadValue(value[name], rng));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::map<SecondarySkill, si32> loadSecondary(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::map<SecondarySkill, si32> ret;
|
||||
for (auto & pair : value.Struct())
|
||||
{
|
||||
SecondarySkill id(VLC->modh->identifiers.getIdentifier(pair.second.meta, "skill", pair.first).get());
|
||||
ret[id] = loadValue(pair.second, rng);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
if (value.getType() == JsonNode::DATA_STRING)
|
||||
return ArtifactID(VLC->modh->identifiers.getIdentifier("artifact", value).get());
|
||||
|
||||
std::set<CArtifact::EartClass> allowedClasses;
|
||||
std::set<ArtifactPosition> allowedPositions;
|
||||
ui32 minValue = 0;
|
||||
ui32 maxValue = std::numeric_limits<ui32>::max();
|
||||
|
||||
if (value["class"].getType() == JsonNode::DATA_STRING)
|
||||
allowedClasses.insert(VLC->arth->stringToClass(value["class"].String()));
|
||||
else
|
||||
for (auto & entry : value["class"].Vector())
|
||||
allowedClasses.insert(VLC->arth->stringToClass(entry.String()));
|
||||
|
||||
if (value["slot"].getType() == JsonNode::DATA_STRING)
|
||||
allowedPositions.insert(VLC->arth->stringToSlot(value["class"].String()));
|
||||
else
|
||||
for (auto & entry : value["slot"].Vector())
|
||||
allowedPositions.insert(VLC->arth->stringToSlot(entry.String()));
|
||||
|
||||
if (value["minValue"].isNull()) minValue = value["minValue"].Float();
|
||||
if (value["maxValue"].isNull()) maxValue = value["maxValue"].Float();
|
||||
|
||||
return VLC->arth->pickRandomArtifact(rng, [=](ArtifactID artID) -> bool
|
||||
{
|
||||
CArtifact * art = VLC->arth->artifacts[artID];
|
||||
|
||||
if (!vstd::iswithin(art->price, minValue, maxValue))
|
||||
return false;
|
||||
|
||||
if (!allowedClasses.empty() && !allowedClasses.count(art->aClass))
|
||||
return false;
|
||||
|
||||
if (!allowedPositions.empty())
|
||||
{
|
||||
for (auto pos : art->possibleSlots[ArtBearer::HERO])
|
||||
{
|
||||
if (allowedPositions.count(pos))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::vector<ArtifactID> ret;
|
||||
for (const JsonNode & entry : value.Vector())
|
||||
{
|
||||
ret.push_back(loadArtifact(entry, rng));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, std::vector<SpellID> spells)
|
||||
{
|
||||
if (value.getType() == JsonNode::DATA_STRING)
|
||||
return SpellID(VLC->modh->identifiers.getIdentifier("spell", value).get());
|
||||
if (value["type"].getType() == JsonNode::DATA_STRING)
|
||||
return SpellID(VLC->modh->identifiers.getIdentifier("spell", value["type"]).get());
|
||||
|
||||
spells.erase(std::remove_if(spells.begin(), spells.end(), [=](SpellID spell)
|
||||
{
|
||||
return VLC->spellh->objects[spell]->level != si32(value["level"].Float());
|
||||
}), spells.end());
|
||||
|
||||
return SpellID(*RandomGeneratorUtil::nextItem(spells, rng));
|
||||
}
|
||||
|
||||
std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, std::vector<SpellID> spells)
|
||||
{
|
||||
// possible extensions: (taken from spell json config)
|
||||
// "type": "adventure",//"adventure", "combat", "ability"
|
||||
// "school": {"air":true, "earth":true, "fire":true, "water":true},
|
||||
// "level": 1,
|
||||
|
||||
std::vector<SpellID> ret;
|
||||
for (const JsonNode & entry : value.Vector())
|
||||
{
|
||||
ret.push_back(loadSpell(entry, rng, spells));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
CStackBasicDescriptor stack;
|
||||
stack.type = VLC->creh->creatures[VLC->modh->identifiers.getIdentifier("creature", value["type"]).get()];
|
||||
stack.count = loadValue(value, rng);
|
||||
if (!value["upgradeChance"].isNull() && !stack.type->upgrades.empty())
|
||||
{
|
||||
if (int(value["upgradeChance"].Float()) > rng.nextInt(99)) // select random upgrade
|
||||
{
|
||||
stack.type = VLC->creh->creatures[*RandomGeneratorUtil::nextItem(stack.type->upgrades, rng)];
|
||||
}
|
||||
}
|
||||
return stack;
|
||||
}
|
||||
|
||||
std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng)
|
||||
{
|
||||
std::vector<CStackBasicDescriptor> ret;
|
||||
for (const JsonNode & node : value.Vector())
|
||||
{
|
||||
ret.push_back(loadCreature(node, rng));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value)
|
||||
{
|
||||
std::vector<RandomStackInfo> ret;
|
||||
for (const JsonNode & node : value.Vector())
|
||||
{
|
||||
RandomStackInfo info;
|
||||
|
||||
if (!node["amount"].isNull())
|
||||
info.minAmount = info.maxAmount = node["amount"].Float();
|
||||
else
|
||||
{
|
||||
info.minAmount = node["min"].Float();
|
||||
info.maxAmount = node["max"].Float();
|
||||
}
|
||||
const CCreature * crea = VLC->creh->creatures[VLC->modh->identifiers.getIdentifier("creature", node["type"]).get()];
|
||||
info.allowedCreatures.push_back(crea);
|
||||
if (!node["upgradeChance"].Float() > 0)
|
||||
{
|
||||
for (auto creaID : crea->upgrades)
|
||||
info.allowedCreatures.push_back(VLC->creh->creatures[creaID]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Bonus> loadBonuses(const JsonNode & value)
|
||||
{
|
||||
std::vector<Bonus> ret;
|
||||
for (const JsonNode & entry : value.Vector())
|
||||
{
|
||||
Bonus * bonus = JsonUtils::parseBonus(entry);
|
||||
ret.push_back(*bonus);
|
||||
delete bonus;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Component> loadComponents(const JsonNode & value)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
}
|
50
lib/mapObjects/JsonRandom.h
Normal file
50
lib/mapObjects/JsonRandom.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GameConstants.h"
|
||||
#include "../ResourceSet.h"
|
||||
|
||||
/*
|
||||
* JsonRandom.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
|
||||
class JsonNode;
|
||||
typedef std::vector<JsonNode> JsonVector;
|
||||
class CRandomGenerator;
|
||||
|
||||
class Bonus;
|
||||
class Component;
|
||||
class CStackBasicDescriptor;
|
||||
|
||||
namespace JsonRandom
|
||||
{
|
||||
struct RandomStackInfo
|
||||
{
|
||||
std::vector<const CCreature *> allowedCreatures;
|
||||
si32 minAmount;
|
||||
si32 maxAmount;
|
||||
};
|
||||
|
||||
si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0);
|
||||
TResources loadResources(const JsonNode & value, CRandomGenerator & rng);
|
||||
std::vector<si32> loadPrimary(const JsonNode & value, CRandomGenerator & rng);
|
||||
std::map<SecondarySkill, si32> loadSecondary(const JsonNode & value, CRandomGenerator & rng);
|
||||
|
||||
ArtifactID loadArtifact(const JsonNode & value, CRandomGenerator & rng);
|
||||
std::vector<ArtifactID> loadArtifacts(const JsonNode & value, CRandomGenerator & rng);
|
||||
|
||||
SpellID loadSpell(const JsonNode & value, CRandomGenerator & rng, std::vector<SpellID> spells);
|
||||
std::vector<SpellID> loadSpells(const JsonNode & value, CRandomGenerator & rng, std::vector<SpellID> spells);
|
||||
|
||||
CStackBasicDescriptor loadCreature(const JsonNode & value, CRandomGenerator & rng);
|
||||
std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng);
|
||||
std::vector<RandomStackInfo> evaluateCreatures(const JsonNode & value);
|
||||
|
||||
std::vector<Bonus> loadBonuses(const JsonNode & value);
|
||||
std::vector<Component> loadComponents(const JsonNode & value);
|
||||
}
|
@ -1569,7 +1569,7 @@ void CMapLoaderH3M::readObjects()
|
||||
{
|
||||
if(objTempl.subid == 0)
|
||||
{
|
||||
nobj = new CGPyramid();
|
||||
nobj = new CBank();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -69,7 +69,6 @@ void registerTypesMapObjects1(Serializer &s)
|
||||
s.template registerType<CArmedInstance, CGResource>();
|
||||
s.template registerType<CArmedInstance, CGMine>();
|
||||
s.template registerType<CArmedInstance, CBank>();
|
||||
s.template registerType<CBank, CGPyramid>();
|
||||
s.template registerType<CArmedInstance, CGSeerHut>(); s.template registerType<IQuestObject, CGSeerHut>();
|
||||
s.template registerType<CGSeerHut, CGQuestGuard>();
|
||||
}
|
||||
@ -81,13 +80,13 @@ void registerTypesMapObjectTypes(Serializer &s)
|
||||
s.template registerType<AObjectTypeHandler, CHeroInstanceConstructor>();
|
||||
s.template registerType<AObjectTypeHandler, CTownInstanceConstructor>();
|
||||
s.template registerType<AObjectTypeHandler, CDwellingInstanceConstructor>();
|
||||
s.template registerType<AObjectTypeHandler, CBankInstanceConstructor>();
|
||||
s.template registerType<AObjectTypeHandler, CObstacleConstructor>();
|
||||
|
||||
#define REGISTER_GENERIC_HANDLER(TYPENAME) s.template registerType<AObjectTypeHandler, CDefaultObjectTypeHandler<TYPENAME> >()
|
||||
|
||||
REGISTER_GENERIC_HANDLER(CGObjectInstance);
|
||||
REGISTER_GENERIC_HANDLER(CGMarket);
|
||||
REGISTER_GENERIC_HANDLER(CBank);
|
||||
REGISTER_GENERIC_HANDLER(CCartographer);
|
||||
REGISTER_GENERIC_HANDLER(CGArtifact);
|
||||
REGISTER_GENERIC_HANDLER(CGBlackMarket);
|
||||
@ -113,7 +112,6 @@ void registerTypesMapObjectTypes(Serializer &s)
|
||||
REGISTER_GENERIC_HANDLER(CGOnceVisitable);
|
||||
REGISTER_GENERIC_HANDLER(CGPandoraBox);
|
||||
REGISTER_GENERIC_HANDLER(CGPickable);
|
||||
REGISTER_GENERIC_HANDLER(CGPyramid);
|
||||
REGISTER_GENERIC_HANDLER(CGQuestGuard);
|
||||
REGISTER_GENERIC_HANDLER(CGResource);
|
||||
REGISTER_GENERIC_HANDLER(CGScholar);
|
||||
|
Loading…
Reference in New Issue
Block a user