mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Merge remote-tracking branch 'remotes/origin/develop' into SpellsRefactoring8
# Conflicts: # client/battle/CBattleInterface.cpp # lib/spells/BattleSpellMechanics.cpp
This commit is contained in:
commit
505e53c17d
@ -701,7 +701,7 @@ AttackPossibility AttackPossibility::evaluate(const BattleAttackInfo &AttackInfo
|
||||
for(int i = 0; i < totalAttacks; i++)
|
||||
{
|
||||
std::pair<ui32, ui32> retaliation(0,0);
|
||||
auto attackDmg = cbc->battleEstimateDamage(curBai, &retaliation);
|
||||
auto attackDmg = cbc->battleEstimateDamage(CRandomGenerator::getDefault(), curBai, &retaliation);
|
||||
ap.damageDealt = (attackDmg.first + attackDmg.second) / 2;
|
||||
ap.damageReceived = (retaliation.first + retaliation.second) / 2;
|
||||
|
||||
@ -785,7 +785,7 @@ int PotentialTargets::bestActionValue() const
|
||||
|
||||
void EnemyInfo::calcDmg(const CStack * ourStack)
|
||||
{
|
||||
TDmgRange retal, dmg = cbc->battleEstimateDamage(ourStack, s, &retal);
|
||||
TDmgRange retal, dmg = cbc->battleEstimateDamage(CRandomGenerator::getDefault(), ourStack, s, &retal);
|
||||
adi = (dmg.first + dmg.second) / 2;
|
||||
adr = (retal.first + retal.second) / 2;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ struct EnemyInfo
|
||||
{}
|
||||
void calcDmg(const CStack * ourStack)
|
||||
{
|
||||
TDmgRange retal, dmg = cbc->battleEstimateDamage(ourStack, s, &retal);
|
||||
TDmgRange retal, dmg = cbc->battleEstimateDamage(CRandomGenerator::getDefault(), ourStack, s, &retal);
|
||||
adi = (dmg.first + dmg.second) / 2;
|
||||
adr = (retal.first + retal.second) / 2;
|
||||
}
|
||||
|
@ -1587,7 +1587,7 @@ void CBattleInterface::activateStack()
|
||||
if(randomSpellcaster)
|
||||
creatureSpellToCast = -1; //spell will be set later on cast
|
||||
else
|
||||
creatureSpellToCast = curInt->cb->battleGetRandomStackSpell(s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move
|
||||
creatureSpellToCast = curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move
|
||||
//TODO: what if creature can cast BOTH random genie spell and aimed spell?
|
||||
//TODO: faerie dragon type spell should be selected by server
|
||||
}
|
||||
@ -2059,7 +2059,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
||||
{
|
||||
if (shere && ourStack && shere != sactive) //only positive spells for other allied creatures
|
||||
{
|
||||
int spellID = curInt->cb->battleGetRandomStackSpell(shere, CBattleInfoCallback::RANDOM_GENIE);
|
||||
int spellID = curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), shere, CBattleInfoCallback::RANDOM_GENIE);
|
||||
if (spellID > -1)
|
||||
{
|
||||
legalAction = true;
|
||||
@ -2203,7 +2203,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
||||
}
|
||||
};
|
||||
|
||||
std::string estDmgText = formatDmgRange(curInt->cb->battleEstimateDamage(sactive, shere)); //calculating estimated dmg
|
||||
std::string estDmgText = formatDmgRange(curInt->cb->battleEstimateDamage(CRandomGenerator::getDefault(), sactive, shere)); //calculating estimated dmg
|
||||
consoleMsg = (boost::format(CGI->generaltexth->allTexts[36]) % shere->getName() % estDmgText).str(); //Attack %s (%s damage)
|
||||
}
|
||||
break;
|
||||
@ -2215,7 +2215,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
||||
cursorFrame = ECursor::COMBAT_SHOOT;
|
||||
|
||||
realizeAction = [=] {giveCommand(Battle::SHOOT, myNumber, activeStack->ID);};
|
||||
std::string estDmgText = formatDmgRange(curInt->cb->battleEstimateDamage(sactive, shere)); //calculating estimated dmg
|
||||
std::string estDmgText = formatDmgRange(curInt->cb->battleEstimateDamage(CRandomGenerator::getDefault(), sactive, shere)); //calculating estimated dmg
|
||||
//printing - Shoot %s (%d shots left, %s damage)
|
||||
consoleMsg = (boost::format(CGI->generaltexth->allTexts[296]) % shere->getName() % sactive->shots % estDmgText).str();
|
||||
}
|
||||
@ -2359,7 +2359,7 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
|
||||
}
|
||||
else //unknown random spell
|
||||
{
|
||||
giveCommand(Battle::MONSTER_SPELL, myNumber, sactive->ID, curInt->cb->battleGetRandomStackSpell(shere, CBattleInfoCallback::RANDOM_GENIE));
|
||||
giveCommand(Battle::MONSTER_SPELL, myNumber, sactive->ID, curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), shere, CBattleInfoCallback::RANDOM_GENIE));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -521,15 +521,15 @@ std::set<BattleHex> CBattleInfoCallback::battleGetAttackedHexes(const CStack* at
|
||||
return attackedHexes;
|
||||
}
|
||||
|
||||
SpellID CBattleInfoCallback::battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const
|
||||
SpellID CBattleInfoCallback::battleGetRandomStackSpell(CRandomGenerator & rand, const CStack * stack, ERandomSpell mode) const
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case RANDOM_GENIE:
|
||||
return getRandomBeneficialSpell(stack); //target
|
||||
return getRandomBeneficialSpell(rand, stack); //target
|
||||
break;
|
||||
case RANDOM_AIMED:
|
||||
return getRandomCastedSpell(stack); //caster
|
||||
return getRandomCastedSpell(rand, stack); //caster
|
||||
break;
|
||||
default:
|
||||
logGlobal->errorStream() << "Incorrect mode of battleGetRandomSpell (" << mode <<")";
|
||||
@ -1076,15 +1076,15 @@ TDmgRange CBattleInfoCallback::calculateDmgRange( const CStack* attacker, const
|
||||
return calculateDmgRange(bai);
|
||||
}
|
||||
|
||||
TDmgRange CBattleInfoCallback::battleEstimateDamage(const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg) const
|
||||
TDmgRange CBattleInfoCallback::battleEstimateDamage(CRandomGenerator & rand, const CStack * attacker, const CStack * defender, TDmgRange * retaliationDmg) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(std::make_pair(0, 0));
|
||||
const bool shooting = battleCanShoot(attacker, defender->position);
|
||||
const BattleAttackInfo bai(attacker, defender, shooting);
|
||||
return battleEstimateDamage(bai, retaliationDmg);
|
||||
return battleEstimateDamage(rand, bai, retaliationDmg);
|
||||
}
|
||||
|
||||
std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(const BattleAttackInfo &bai, std::pair<ui32, ui32> * retaliationDmg /*= nullptr*/) const
|
||||
std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(CRandomGenerator & rand, const BattleAttackInfo &bai, std::pair<ui32, ui32> * retaliationDmg /*= nullptr*/) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(std::make_pair(0, 0));
|
||||
|
||||
@ -1106,7 +1106,7 @@ std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(const BattleAtta
|
||||
{
|
||||
BattleStackAttacked bsa;
|
||||
bsa.damageAmount = ret.*pairElems[i];
|
||||
bai.defender->prepareAttacked(bsa, gs->getRandomGenerator(), bai.defenderCount);
|
||||
bai.defender->prepareAttacked(bsa, rand, bai.defenderCount);
|
||||
|
||||
auto retaliationAttack = bai.reverse();
|
||||
retaliationAttack.attackerCount = bsa.newAmount;
|
||||
@ -1753,7 +1753,7 @@ std::set<const CStack*> CBattleInfoCallback:: batteAdjacentCreatures(const CStac
|
||||
return stacks;
|
||||
}
|
||||
|
||||
SpellID CBattleInfoCallback::getRandomBeneficialSpell(const CStack * subject) const
|
||||
SpellID CBattleInfoCallback::getRandomBeneficialSpell(CRandomGenerator & rand, const CStack * subject) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(SpellID::NONE);
|
||||
//This is complete list. No spells from mods.
|
||||
@ -1875,7 +1875,7 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(const CStack * subject) co
|
||||
|
||||
if(!beneficialSpells.empty())
|
||||
{
|
||||
return *RandomGeneratorUtil::nextItem(beneficialSpells, gs->getRandomGenerator());
|
||||
return *RandomGeneratorUtil::nextItem(beneficialSpells, rand);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1883,7 +1883,7 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(const CStack * subject) co
|
||||
}
|
||||
}
|
||||
|
||||
SpellID CBattleInfoCallback::getRandomCastedSpell(const CStack * caster) const
|
||||
SpellID CBattleInfoCallback::getRandomCastedSpell(CRandomGenerator & rand,const CStack * caster) const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(SpellID::NONE);
|
||||
|
||||
@ -1895,7 +1895,7 @@ SpellID CBattleInfoCallback::getRandomCastedSpell(const CStack * caster) const
|
||||
{
|
||||
totalWeight += std::max(b->additionalInfo, 1); //minimal chance to cast is 1
|
||||
}
|
||||
int randomPos = gs->getRandomGenerator().nextInt(totalWeight - 1);
|
||||
int randomPos = rand.nextInt(totalWeight - 1);
|
||||
for(Bonus * b : *bl)
|
||||
{
|
||||
randomPos -= std::max(b->additionalInfo, 1);
|
||||
|
@ -22,6 +22,7 @@ struct CObstacleInstance;
|
||||
class IBonusBearer;
|
||||
struct InfoAboutHero;
|
||||
class CArmedInstance;
|
||||
class CRandomGenerator;
|
||||
|
||||
namespace boost
|
||||
{class shared_mutex;}
|
||||
@ -266,8 +267,8 @@ public:
|
||||
TDmgRange calculateDmgRange(const CStack* attacker, const CStack* defender, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg) const; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
|
||||
|
||||
//hextowallpart //int battleGetWallUnderHex(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
|
||||
std::pair<ui32, ui32> battleEstimateDamage(const BattleAttackInfo &bai, std::pair<ui32, ui32> * retaliationDmg = nullptr) const; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
std::pair<ui32, ui32> battleEstimateDamage(const CStack * attacker, const CStack * defender, std::pair<ui32, ui32> * retaliationDmg = nullptr) const; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
std::pair<ui32, ui32> battleEstimateDamage(CRandomGenerator & rand, const BattleAttackInfo &bai, std::pair<ui32, ui32> * retaliationDmg = nullptr) const; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
std::pair<ui32, ui32> battleEstimateDamage(CRandomGenerator & rand, const CStack * attacker, const CStack * defender, std::pair<ui32, ui32> * retaliationDmg = nullptr) const; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
|
||||
si8 battleHasDistancePenalty( const CStack * stack, BattleHex destHex ) const;
|
||||
si8 battleHasDistancePenalty(const IBonusBearer *bonusBearer, BattleHex shooterPosition, BattleHex destHex ) const;
|
||||
si8 battleHasWallPenalty(const CStack * stack, BattleHex destHex) const; //checks if given stack has wall penalty
|
||||
@ -285,9 +286,9 @@ public:
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpell(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode) const; //checks if given player can cast given spell
|
||||
ESpellCastProblem::ESpellCastProblem battleCanCastThisSpellHere(const ISpellCaster * caster, const CSpell * spell, ECastingMode::ECastingMode mode, BattleHex dest) const; //checks if given player can cast given spell at given tile in given mode
|
||||
|
||||
SpellID battleGetRandomStackSpell(const CStack * stack, ERandomSpell mode) const;
|
||||
SpellID getRandomBeneficialSpell(const CStack * subject) const;
|
||||
SpellID getRandomCastedSpell(const CStack * caster) const; //called at the beginning of turn for Faerie Dragon
|
||||
SpellID battleGetRandomStackSpell(CRandomGenerator & rand, const CStack * stack, ERandomSpell mode) const;
|
||||
SpellID getRandomBeneficialSpell(CRandomGenerator & rand, const CStack * subject) const;
|
||||
SpellID getRandomCastedSpell(CRandomGenerator & rand, const CStack * caster) const; //called at the beginning of turn for Faerie Dragon
|
||||
|
||||
const CStack * getStackIf(std::function<bool(const CStack*)> pred) const;
|
||||
|
||||
|
@ -476,13 +476,13 @@ int CGameState::pickUnusedHeroTypeRandomly(PlayerColor owner)
|
||||
// select random hero native to "our" faction
|
||||
if(!factionHeroes.empty())
|
||||
{
|
||||
return RandomGeneratorUtil::nextItem(factionHeroes, rand)->getNum();
|
||||
return RandomGeneratorUtil::nextItem(factionHeroes, getRandomGenerator())->getNum();
|
||||
}
|
||||
|
||||
logGlobal->warnStream() << "Cannot find free hero of appropriate faction for player " << owner << " - trying to get first available...";
|
||||
if(!otherHeroes.empty())
|
||||
{
|
||||
return RandomGeneratorUtil::nextItem(otherHeroes, rand)->getNum();
|
||||
return RandomGeneratorUtil::nextItem(otherHeroes, getRandomGenerator())->getNum();
|
||||
}
|
||||
|
||||
logGlobal->error("No free allowed heroes!");
|
||||
@ -500,29 +500,29 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
||||
switch(obj->ID)
|
||||
{
|
||||
case Obj::RANDOM_ART:
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC));
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE | CArtifact::ART_MINOR | CArtifact::ART_MAJOR | CArtifact::ART_RELIC));
|
||||
case Obj::RANDOM_TREASURE_ART:
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE));
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE));
|
||||
case Obj::RANDOM_MINOR_ART:
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MINOR));
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_MINOR));
|
||||
case Obj::RANDOM_MAJOR_ART:
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MAJOR));
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_MAJOR));
|
||||
case Obj::RANDOM_RELIC_ART:
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(rand, CArtifact::ART_RELIC));
|
||||
return std::make_pair(Obj::ARTIFACT, VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_RELIC));
|
||||
case Obj::RANDOM_HERO:
|
||||
return std::make_pair(Obj::HERO, pickNextHeroType(obj->tempOwner));
|
||||
case Obj::RANDOM_MONSTER:
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand));
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator()));
|
||||
case Obj::RANDOM_MONSTER_L1:
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 1));
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 1));
|
||||
case Obj::RANDOM_MONSTER_L2:
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 2));
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 2));
|
||||
case Obj::RANDOM_MONSTER_L3:
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 3));
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 3));
|
||||
case Obj::RANDOM_MONSTER_L4:
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 4));
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 4));
|
||||
case Obj::RANDOM_RESOURCE:
|
||||
return std::make_pair(Obj::RESOURCE,rand.nextInt(6)); //now it's OH3 style, use %8 for mithril
|
||||
return std::make_pair(Obj::RESOURCE,getRandomGenerator().nextInt(6)); //now it's OH3 style, use %8 for mithril
|
||||
case Obj::RANDOM_TOWN:
|
||||
{
|
||||
PlayerColor align = PlayerColor((static_cast<CGTownInstance*>(obj))->alignment);
|
||||
@ -542,18 +542,18 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
||||
{
|
||||
do
|
||||
{
|
||||
f = rand.nextInt(VLC->townh->factions.size() - 1);
|
||||
f = getRandomGenerator().nextInt(VLC->townh->factions.size() - 1);
|
||||
}
|
||||
while (VLC->townh->factions[f]->town == nullptr); // find playable faction
|
||||
}
|
||||
return std::make_pair(Obj::TOWN,f);
|
||||
}
|
||||
case Obj::RANDOM_MONSTER_L5:
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 5));
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 5));
|
||||
case Obj::RANDOM_MONSTER_L6:
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 6));
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 6));
|
||||
case Obj::RANDOM_MONSTER_L7:
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(rand, 7));
|
||||
return std::make_pair(Obj::MONSTER, VLC->creh->pickRandomMonster(getRandomGenerator(), 7));
|
||||
case Obj::RANDOM_DWELLING:
|
||||
case Obj::RANDOM_DWELLING_LVL:
|
||||
case Obj::RANDOM_DWELLING_FACTION:
|
||||
@ -564,7 +564,7 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
||||
//if castle alignment available
|
||||
if (auto info = dynamic_cast<CCreGenAsCastleInfo*>(dwl->info))
|
||||
{
|
||||
faction = rand.nextInt(VLC->townh->factions.size() - 1);
|
||||
faction = getRandomGenerator().nextInt(VLC->townh->factions.size() - 1);
|
||||
if (info->asCastle)
|
||||
{
|
||||
for(auto & elem : map->objects)
|
||||
@ -593,7 +593,7 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
||||
{
|
||||
if((faction>7) && (info->castles[1]&(1<<(faction-8))))
|
||||
break;
|
||||
faction = rand.nextInt(GameConstants::F_NUMBER - 1);
|
||||
faction = getRandomGenerator().nextInt(GameConstants::F_NUMBER - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -605,7 +605,7 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
||||
//if level set to range
|
||||
if (auto info = dynamic_cast<CCreGenLeveledInfo*>(dwl->info))
|
||||
{
|
||||
level = rand.nextInt(info->minLevel, info->maxLevel);
|
||||
level = getRandomGenerator().nextInt(info->minLevel, info->maxLevel);
|
||||
}
|
||||
else // fixed level
|
||||
{
|
||||
@ -639,7 +639,7 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj)
|
||||
if (result.first == Obj::NO_OBJ)
|
||||
{
|
||||
logGlobal->errorStream() << "Error: failed to find dwelling for "<< VLC->townh->factions[faction]->name << " of level " << int(level);
|
||||
result = std::make_pair(Obj::CREATURE_GENERATOR1, *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::CREATURE_GENERATOR1), rand));
|
||||
result = std::make_pair(Obj::CREATURE_GENERATOR1, *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::CREATURE_GENERATOR1), getRandomGenerator()));
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -727,23 +727,10 @@ CGameState::~CGameState()
|
||||
ptr.second.dellNull();
|
||||
}
|
||||
|
||||
BattleInfo * CGameState::setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town)
|
||||
{
|
||||
const TerrainTile &t = map->getTile(tile);
|
||||
ETerrainType terrain = t.terType;
|
||||
if(map->isCoastalTile(tile)) //coastal tile is always ground
|
||||
terrain = ETerrainType::SAND;
|
||||
|
||||
BFieldType terType = battleGetBattlefieldType(tile);
|
||||
if (heroes[0] && heroes[0]->boat && heroes[1] && heroes[1]->boat)
|
||||
terType = BFieldType::SHIP_TO_SHIP;
|
||||
return BattleInfo::setupBattle(tile, terrain, terType, armies, heroes, creatureBank, town);
|
||||
}
|
||||
|
||||
void CGameState::init(StartInfo * si)
|
||||
{
|
||||
logGlobal->infoStream() << "\tUsing random seed: "<< si->seedToBeUsed;
|
||||
rand.setSeed(si->seedToBeUsed);
|
||||
getRandomGenerator().setSeed(si->seedToBeUsed);
|
||||
scenarioOps = CMemorySerializer::deepCopy(*si).release();
|
||||
initialOpts = CMemorySerializer::deepCopy(*si).release();
|
||||
si = nullptr;
|
||||
@ -800,7 +787,7 @@ void CGameState::init(StartInfo * si)
|
||||
logGlobal->debug("\tChecking objectives");
|
||||
map->checkForObjectives(); //needs to be run when all objects are properly placed
|
||||
|
||||
auto seedAfterInit = rand.nextInt();
|
||||
auto seedAfterInit = getRandomGenerator().nextInt();
|
||||
logGlobal->infoStream() << "Seed after init is " << seedAfterInit << " (before was " << scenarioOps->seedToBeUsed << ")";
|
||||
if(scenarioOps->seedPostInit > 0)
|
||||
{
|
||||
@ -925,8 +912,8 @@ void CGameState::initDuel()
|
||||
for(TSecSKill secSkill : ss.heroSecSkills)
|
||||
h->setSecSkillLevel(SecondarySkill(secSkill.first), secSkill.second, 1);
|
||||
|
||||
h->initHero(HeroTypeID(h->subID));
|
||||
obj->initObj();
|
||||
h->initHero(getRandomGenerator(), HeroTypeID(h->subID));
|
||||
obj->initObj(getRandomGenerator());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1026,7 +1013,7 @@ void CGameState::initGrailPosition()
|
||||
|
||||
if(!allowedPos.empty())
|
||||
{
|
||||
map->grailPos = *RandomGeneratorUtil::nextItem(allowedPos, rand);
|
||||
map->grailPos = *RandomGeneratorUtil::nextItem(allowedPos, getRandomGenerator());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1042,7 +1029,7 @@ void CGameState::initRandomFactionsForPlayers()
|
||||
{
|
||||
if(elem.second.castle==-1)
|
||||
{
|
||||
auto randomID = rand.nextInt(map->players[elem.first.getNum()].allowedFactions.size() - 1);
|
||||
auto randomID = getRandomGenerator().nextInt(map->players[elem.first.getNum()].allowedFactions.size() - 1);
|
||||
auto iter = map->players[elem.first.getNum()].allowedFactions.begin();
|
||||
std::advance(iter, randomID);
|
||||
|
||||
@ -1171,7 +1158,7 @@ void CGameState::placeCampaignHeroes()
|
||||
auto unusedHeroTypeIds = getUnusedAllowedHeroes();
|
||||
if(!unusedHeroTypeIds.empty())
|
||||
{
|
||||
heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, rand)).getNum();
|
||||
heroTypeId = (*RandomGeneratorUtil::nextItem(unusedHeroTypeIds, getRandomGenerator())).getNum();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1252,7 +1239,7 @@ CGameState::CrossoverHeroesList CGameState::getCrossoverHeroesFromPreviousScenar
|
||||
return crossoverHeroes;
|
||||
}
|
||||
|
||||
void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const
|
||||
void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions)
|
||||
{
|
||||
// create heroes list for convenience iterating
|
||||
std::vector<CGHeroInstance *> crossoverHeroes;
|
||||
@ -1268,7 +1255,7 @@ void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroRepl
|
||||
//trimming experience
|
||||
for(CGHeroInstance * cgh : crossoverHeroes)
|
||||
{
|
||||
cgh->initExp();
|
||||
cgh->initExp(getRandomGenerator());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1475,7 +1462,7 @@ void CGameState::initHeroes()
|
||||
continue;
|
||||
}
|
||||
|
||||
hero->initHero();
|
||||
hero->initHero(getRandomGenerator());
|
||||
getPlayer(hero->getOwner())->heroes.push_back(hero);
|
||||
map->allHeroes[hero->type->ID.getNum()] = hero;
|
||||
}
|
||||
@ -1491,7 +1478,7 @@ void CGameState::initHeroes()
|
||||
{
|
||||
if(!vstd::contains(heroesToCreate, HeroTypeID(ph->subID)))
|
||||
continue;
|
||||
ph->initHero();
|
||||
ph->initHero(getRandomGenerator());
|
||||
hpool.heroesPool[ph->subID] = ph;
|
||||
hpool.pavailable[ph->subID] = 0xff;
|
||||
heroesToCreate.erase(ph->type->ID);
|
||||
@ -1502,7 +1489,7 @@ void CGameState::initHeroes()
|
||||
for(HeroTypeID htype : heroesToCreate) //all not used allowed heroes go with default state into the pool
|
||||
{
|
||||
auto vhi = new CGHeroInstance();
|
||||
vhi->initHero(htype);
|
||||
vhi->initHero(getRandomGenerator(), htype);
|
||||
|
||||
int typeID = htype.getNum();
|
||||
map->allHeroes[typeID] = vhi;
|
||||
@ -1660,24 +1647,24 @@ void CGameState::initStartingBonus()
|
||||
{
|
||||
//starting bonus
|
||||
if(scenarioOps->playerInfos[elem.first].bonus==PlayerSettings::RANDOM)
|
||||
scenarioOps->playerInfos[elem.first].bonus = static_cast<PlayerSettings::Ebonus>(rand.nextInt(2));
|
||||
scenarioOps->playerInfos[elem.first].bonus = static_cast<PlayerSettings::Ebonus>(getRandomGenerator().nextInt(2));
|
||||
switch(scenarioOps->playerInfos[elem.first].bonus)
|
||||
{
|
||||
case PlayerSettings::GOLD:
|
||||
elem.second.resources[Res::GOLD] += rand.nextInt(5, 10) * 100;
|
||||
elem.second.resources[Res::GOLD] += getRandomGenerator().nextInt(5, 10) * 100;
|
||||
break;
|
||||
case PlayerSettings::RESOURCE:
|
||||
{
|
||||
int res = VLC->townh->factions[scenarioOps->playerInfos[elem.first].castle]->town->primaryRes;
|
||||
if(res == Res::WOOD_AND_ORE)
|
||||
{
|
||||
int amount = rand.nextInt(5, 10);
|
||||
int amount = getRandomGenerator().nextInt(5, 10);
|
||||
elem.second.resources[Res::WOOD] += amount;
|
||||
elem.second.resources[Res::ORE] += amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
elem.second.resources[res] += rand.nextInt(3, 6);
|
||||
elem.second.resources[res] += getRandomGenerator().nextInt(3, 6);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1689,7 +1676,7 @@ void CGameState::initStartingBonus()
|
||||
break;
|
||||
}
|
||||
CArtifact *toGive;
|
||||
toGive = VLC->arth->artifacts[VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE)];
|
||||
toGive = VLC->arth->artifacts[VLC->arth->pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE)];
|
||||
|
||||
CGHeroInstance *hero = elem.second.heroes[0];
|
||||
giveHeroArtifact(hero, toGive->id);
|
||||
@ -1742,7 +1729,7 @@ void CGameState::initTowns()
|
||||
}
|
||||
if(vti->name.empty())
|
||||
{
|
||||
vti->name = *RandomGeneratorUtil::nextItem(vti->town->names, rand);
|
||||
vti->name = *RandomGeneratorUtil::nextItem(vti->town->names, getRandomGenerator());
|
||||
}
|
||||
|
||||
//init buildings
|
||||
@ -1754,7 +1741,7 @@ void CGameState::initTowns()
|
||||
vti->builtBuildings.insert(BuildingID::TAVERN);
|
||||
|
||||
vti->builtBuildings.insert(BuildingID::DWELL_FIRST);
|
||||
if(rand.nextInt(1) == 1)
|
||||
if(getRandomGenerator().nextInt(1) == 1)
|
||||
{
|
||||
vti->builtBuildings.insert(BuildingID::DWELL_LVL_2);
|
||||
}
|
||||
@ -1826,7 +1813,7 @@ void CGameState::initTowns()
|
||||
if (total == 0) // remaining spells have 0 probability
|
||||
break;
|
||||
|
||||
auto r = rand.nextInt(total - 1);
|
||||
auto r = getRandomGenerator().nextInt(total - 1);
|
||||
for(ui32 ps=0; ps<vti->possibleSpells.size();ps++)
|
||||
{
|
||||
r -= vti->possibleSpells[ps].toSpell()->getProbability(vti->subID);
|
||||
@ -1859,7 +1846,7 @@ void CGameState::initMapObjects()
|
||||
if(obj)
|
||||
{
|
||||
logGlobal->traceStream() << boost::format ("Calling Init for object %d, %s, %s") % obj->id.getNum() % obj->typeName % obj->subTypeName;
|
||||
obj->initObj();
|
||||
obj->initObj(getRandomGenerator());
|
||||
}
|
||||
}
|
||||
for(CGObjectInstance *obj : map->objects)
|
||||
@ -1919,7 +1906,7 @@ void CGameState::initVisitingAndGarrisonedHeroes()
|
||||
}
|
||||
}
|
||||
|
||||
BFieldType CGameState::battleGetBattlefieldType(int3 tile)
|
||||
BFieldType CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & rand)
|
||||
{
|
||||
if(tile==int3() && curB)
|
||||
tile = curB->tile;
|
||||
@ -3263,9 +3250,12 @@ TeamState::TeamState(TeamState && other):
|
||||
std::swap(fogOfWarMap, other.fogOfWarMap);
|
||||
}
|
||||
|
||||
|
||||
CRandomGenerator & CGameState::getRandomGenerator()
|
||||
{
|
||||
//if(scenarioOps && scenarioOps->seedPostInit)
|
||||
//{
|
||||
// logGlobal->trace("CGameState::getRandomGenerator used after initialization!");
|
||||
//}
|
||||
//logGlobal->traceStream() << "Fetching CGameState::rand with seed " << rand.nextInt();
|
||||
return rand;
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ public:
|
||||
void giveHeroArtifact(CGHeroInstance *h, ArtifactID aid);
|
||||
|
||||
void apply(CPack *pack);
|
||||
BFieldType battleGetBattlefieldType(int3 tile);
|
||||
BFieldType battleGetBattlefieldType(int3 tile, CRandomGenerator & rand);
|
||||
UpgradeInfo getUpgradeInfo(const CStackInstance &stack);
|
||||
PlayerRelations::PlayerRelations getPlayerRelations(PlayerColor color1, PlayerColor color2);
|
||||
bool checkForVisitableDir(const int3 & src, const int3 & dst) const; //check if src tile is visitable from dst tile
|
||||
@ -236,7 +236,6 @@ public:
|
||||
|
||||
void obtainPlayersStats(SThievesGuildInfo & tgi, int level); //fills tgi with info about other players that is available at given level of thieves' guild
|
||||
std::map<ui32, ConstTransitivePtr<CGHeroInstance> > unusedHeroesFromPool(); //heroes pool without heroes that are available in taverns
|
||||
BattleInfo * setupBattle(int3 tile, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town);
|
||||
|
||||
bool isVisible(int3 pos, PlayerColor player);
|
||||
bool isVisible(const CGObjectInstance *obj, boost::optional<PlayerColor> player);
|
||||
@ -244,6 +243,14 @@ public:
|
||||
int getDate(Date::EDateType mode=Date::DAY) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
|
||||
|
||||
// ----- getters, setters -----
|
||||
|
||||
/// This RNG should only be used inside GS or CPackForClient-derived applyGs
|
||||
/// If this doesn't work for your code that mean you need a new netpack
|
||||
///
|
||||
/// Client-side must use CRandomGenerator::getDefault which is not serialized
|
||||
///
|
||||
/// CGameHandler have it's own getter for CRandomGenerator::getDefault
|
||||
/// Any server-side code outside of GH must use CRandomGenerator::getDefault
|
||||
CRandomGenerator & getRandomGenerator();
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -292,7 +299,7 @@ private:
|
||||
std::vector<CampaignHeroReplacement> generateCampaignHeroesToReplace(CrossoverHeroesList & crossoverHeroes);
|
||||
|
||||
/// gets prepared and copied hero instances with crossover heroes from prev. scenario and travel options from current scenario
|
||||
void prepareCrossoverHeroes(std::vector<CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const;
|
||||
void prepareCrossoverHeroes(std::vector<CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions);
|
||||
|
||||
void replaceHeroesPlaceholders(const std::vector<CampaignHeroReplacement> & campaignHeroReplacements);
|
||||
void placeStartingHeroes();
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "mapping/CCampaignHandler.h" //for CCampaignState
|
||||
#include "rmg/CMapGenerator.h" // for CMapGenOptions
|
||||
|
||||
const ui32 version = 760;
|
||||
const ui32 version = 761;
|
||||
const ui32 minSupportedVersion = 753;
|
||||
|
||||
class CISer;
|
||||
|
@ -119,14 +119,14 @@ void CPrivilagedInfoCallback::getAllTiles (std::unordered_set<int3, ShashInt3> &
|
||||
}
|
||||
}
|
||||
|
||||
void CPrivilagedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact*> &out)
|
||||
void CPrivilagedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact*> &out, CRandomGenerator & rand)
|
||||
{
|
||||
for (int j = 0; j < 3 ; j++)
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_TREASURE)]);
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(rand, CArtifact::ART_TREASURE)]);
|
||||
for (int j = 0; j < 3 ; j++)
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_MINOR)]);
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MINOR)]);
|
||||
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(gameState()->getRandomGenerator(), CArtifact::ART_MAJOR)]);
|
||||
out.push_back(VLC->arth->artifacts[VLC->arth->pickRandomArtifact(rand, CArtifact::ART_MAJOR)]);
|
||||
}
|
||||
|
||||
void CPrivilagedInfoCallback::getAllowedSpells(std::vector<SpellID> &out, ui16 level)
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CGameInfoCallback.h" // for CGameInfoCallback
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
* IGameCallback.h, part of VCMI engine
|
||||
@ -32,7 +33,7 @@ public:
|
||||
void getFreeTiles (std::vector<int3> &tiles) const; //used for random spawns
|
||||
void getTilesInRange(std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int mode = 0, bool patrolDistance = false) const; //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only unrevealed
|
||||
void getAllTiles (std::unordered_set<int3, ShashInt3> &tiles, boost::optional<PlayerColor> player = boost::optional<PlayerColor>(), int level=-1, int surface=0) const; //returns all tiles on given level (-1 - both levels, otherwise number of level); surface: 0 - land and water, 1 - only land, 2 - only water
|
||||
void pickAllowedArtsSet(std::vector<const CArtifact*> &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
||||
void pickAllowedArtsSet(std::vector<const CArtifact*> &out, CRandomGenerator & rand); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant
|
||||
void getAllowedSpells(std::vector<SpellID> &out, ui16 level);
|
||||
|
||||
template<typename Saver>
|
||||
|
@ -1093,6 +1093,23 @@ struct ChangeObjectVisitors : public CPackForClient // 1003
|
||||
}
|
||||
};
|
||||
|
||||
struct PrepareHeroLevelUp : public CPackForClient//1999
|
||||
{
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
|
||||
const CGHeroInstance *hero;
|
||||
|
||||
/// Do not serialize, used by server only
|
||||
std::vector<SecondarySkill> skills;
|
||||
|
||||
PrepareHeroLevelUp(){type = 1999;};
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & hero;
|
||||
}
|
||||
};
|
||||
|
||||
struct HeroLevelUp : public Query//2000
|
||||
{
|
||||
void applyCl(CClient *cl);
|
||||
|
@ -624,7 +624,7 @@ DLL_LINKAGE void HeroRecruited::applyGs( CGameState *gs )
|
||||
h->attachTo(p);
|
||||
if(fresh)
|
||||
{
|
||||
h->initObj();
|
||||
h->initObj(gs->getRandomGenerator());
|
||||
}
|
||||
gs->map->addBlockVisTiles(h);
|
||||
|
||||
@ -689,7 +689,7 @@ DLL_LINKAGE void NewObject::applyGs( CGameState *gs )
|
||||
|
||||
gs->map->objects.push_back(o);
|
||||
gs->map->addBlockVisTiles(o);
|
||||
o->initObj();
|
||||
o->initObj(gs->getRandomGenerator());
|
||||
gs->map->calculateGuardingGreaturePositions();
|
||||
|
||||
logGlobal->debugStream() << "added object id=" << id << "; address=" << (intptr_t)o << "; name=" << o->getObjectName();
|
||||
@ -1162,6 +1162,21 @@ DLL_LINKAGE void SetObjectProperty::applyGs( CGameState *gs )
|
||||
}
|
||||
}
|
||||
|
||||
DLL_LINKAGE void PrepareHeroLevelUp::applyGs(CGameState *gs)
|
||||
{
|
||||
CGHeroInstance * h = gs->getHero(hero->id);
|
||||
auto proposedSkills = h->getLevelUpProposedSecondarySkills();
|
||||
|
||||
if(skills.size() == 1 || hero->tempOwner == PlayerColor::NEUTRAL) //choose skill automatically
|
||||
{
|
||||
skills.push_back(*RandomGeneratorUtil::nextItem(proposedSkills, h->skillsInfo.rand));
|
||||
}
|
||||
else
|
||||
{
|
||||
skills = proposedSkills;
|
||||
}
|
||||
}
|
||||
|
||||
DLL_LINKAGE void HeroLevelUp::applyGs( CGameState *gs )
|
||||
{
|
||||
CGHeroInstance * h = gs->getHero(hero->id);
|
||||
|
@ -34,11 +34,11 @@ CBank::~CBank()
|
||||
{
|
||||
}
|
||||
|
||||
void CBank::initObj()
|
||||
void CBank::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
daycounter = 0;
|
||||
resetDuration = 0;
|
||||
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, cb->gameState()->getRandomGenerator());
|
||||
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand);
|
||||
}
|
||||
|
||||
std::string CBank::getHoverText(PlayerColor player) const
|
||||
@ -64,7 +64,8 @@ void CBank::setPropertyDer (ui8 what, ui32 val)
|
||||
daycounter+=val;
|
||||
break;
|
||||
case ObjProperty::BANK_RESET:
|
||||
initObj();
|
||||
// FIXME: Object reset must be done by separate netpack from server
|
||||
initObj(cb->gameState()->getRandomGenerator());
|
||||
daycounter = 1; //yes, 1 since "today" daycounter won't be incremented
|
||||
break;
|
||||
case ObjProperty::BANK_CLEAR:
|
||||
@ -73,7 +74,7 @@ void CBank::setPropertyDer (ui8 what, ui32 val)
|
||||
}
|
||||
}
|
||||
|
||||
void CBank::newTurn() const
|
||||
void CBank::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if (bc == nullptr)
|
||||
{
|
||||
|
@ -31,9 +31,9 @@ public:
|
||||
|
||||
void setConfig(const BankConfig & bc);
|
||||
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
void newTurn() const override;
|
||||
void newTurn(CRandomGenerator & rand) const override;
|
||||
bool wasVisited (PlayerColor player) const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
|
@ -244,10 +244,10 @@ CGHeroInstance::CGHeroInstance()
|
||||
secSkills.push_back(std::make_pair(SecondarySkill::DEFAULT, -1));
|
||||
}
|
||||
|
||||
void CGHeroInstance::initHero(HeroTypeID SUBID)
|
||||
void CGHeroInstance::initHero(CRandomGenerator & rand, HeroTypeID SUBID)
|
||||
{
|
||||
subID = SUBID.getNum();
|
||||
initHero();
|
||||
initHero(rand);
|
||||
}
|
||||
|
||||
void CGHeroInstance::setType(si32 ID, si32 subID)
|
||||
@ -259,7 +259,7 @@ void CGHeroInstance::setType(si32 ID, si32 subID)
|
||||
randomizeArmy(type->heroClass->faction);
|
||||
}
|
||||
|
||||
void CGHeroInstance::initHero()
|
||||
void CGHeroInstance::initHero(CRandomGenerator & rand)
|
||||
{
|
||||
assert(validTypes(true));
|
||||
if(!type)
|
||||
@ -302,17 +302,17 @@ void CGHeroInstance::initHero()
|
||||
setFormation(false);
|
||||
if (!stacksCount()) //standard army//initial army
|
||||
{
|
||||
initArmy();
|
||||
initArmy(rand);
|
||||
}
|
||||
assert(validTypes());
|
||||
|
||||
if(exp == 0xffffffff)
|
||||
{
|
||||
initExp();
|
||||
initExp(rand);
|
||||
}
|
||||
else
|
||||
{
|
||||
levelUpAutomatically();
|
||||
levelUpAutomatically(rand);
|
||||
}
|
||||
|
||||
if (VLC->modh->modules.COMMANDERS && !commander)
|
||||
@ -326,13 +326,13 @@ void CGHeroInstance::initHero()
|
||||
mana = manaLimit();
|
||||
}
|
||||
|
||||
void CGHeroInstance::initArmy(IArmyDescriptor *dst /*= nullptr*/)
|
||||
void CGHeroInstance::initArmy(CRandomGenerator & rand, IArmyDescriptor *dst /*= nullptr*/)
|
||||
{
|
||||
if(!dst)
|
||||
dst = this;
|
||||
|
||||
int howManyStacks = 0; //how many stacks will hero receives <1 - 3>
|
||||
int pom = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
int pom = rand.nextInt(99);
|
||||
int warMachinesGiven = 0;
|
||||
|
||||
if(pom < 9)
|
||||
@ -348,7 +348,7 @@ void CGHeroInstance::initArmy(IArmyDescriptor *dst /*= nullptr*/)
|
||||
{
|
||||
auto & stack = type->initialArmy[stackNo];
|
||||
|
||||
int count = cb->gameState()->getRandomGenerator().nextInt(stack.minAmount, stack.maxAmount);
|
||||
int count = rand.nextInt(stack.minAmount, stack.maxAmount);
|
||||
|
||||
if(stack.creature >= CreatureID::CATAPULT &&
|
||||
stack.creature <= CreatureID::ARROW_TOWERS) //war machine
|
||||
@ -483,7 +483,7 @@ void CGHeroInstance::SecondarySkillsInfo::resetWisdomCounter()
|
||||
wisdomCounter = 1;
|
||||
}
|
||||
|
||||
void CGHeroInstance::initObj()
|
||||
void CGHeroInstance::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
auto hs = new HeroSpecial();
|
||||
@ -491,9 +491,9 @@ void CGHeroInstance::initObj()
|
||||
attachTo(hs); //do we ever need to detach it?
|
||||
|
||||
if(!type)
|
||||
initHero(); //TODO: set up everything for prison before specialties are configured
|
||||
initHero(rand); //TODO: set up everything for prison before specialties are configured
|
||||
|
||||
skillsInfo.rand.setSeed(cb->gameState()->getRandomGenerator().nextInt());
|
||||
skillsInfo.rand.setSeed(rand.nextInt());
|
||||
skillsInfo.resetMagicSchoolCounter();
|
||||
skillsInfo.resetWisdomCounter();
|
||||
|
||||
@ -1063,10 +1063,10 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b
|
||||
* @param raisedStack Pair where the first element represents ID of the raised creature
|
||||
* and the second element the amount.
|
||||
*/
|
||||
void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const
|
||||
void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedStack, CRandomGenerator & rand) const
|
||||
{
|
||||
InfoWindow iw;
|
||||
iw.soundID = soundBase::pickup01 + cb->gameState()->getRandomGenerator().nextInt(6);
|
||||
iw.soundID = soundBase::pickup01 + rand.nextInt(6);
|
||||
iw.player = tempOwner;
|
||||
iw.components.push_back(Component(raisedStack));
|
||||
|
||||
@ -1169,9 +1169,9 @@ EAlignment::EAlignment CGHeroInstance::getAlignment() const
|
||||
return type->heroClass->getAlignment();
|
||||
}
|
||||
|
||||
void CGHeroInstance::initExp()
|
||||
void CGHeroInstance::initExp(CRandomGenerator & rand)
|
||||
{
|
||||
exp = cb->gameState()->getRandomGenerator().nextInt(40, 89);
|
||||
exp = rand.nextInt(40, 89);
|
||||
}
|
||||
|
||||
std::string CGHeroInstance::nodeName() const
|
||||
@ -1344,10 +1344,10 @@ std::vector<SecondarySkill> CGHeroInstance::getLevelUpProposedSecondarySkills()
|
||||
return skills;
|
||||
}
|
||||
|
||||
PrimarySkill::PrimarySkill CGHeroInstance::nextPrimarySkill() const
|
||||
PrimarySkill::PrimarySkill CGHeroInstance::nextPrimarySkill(CRandomGenerator & rand) const
|
||||
{
|
||||
assert(gainsLevel());
|
||||
int randomValue = cb->gameState()->getRandomGenerator().nextInt(99), pom = 0, primarySkill = 0;
|
||||
int randomValue = rand.nextInt(99), pom = 0, primarySkill = 0;
|
||||
const auto & skillChances = (level > 9) ? type->heroClass->primarySkillLowLevel : type->heroClass->primarySkillHighLevel;
|
||||
|
||||
for(; primarySkill < GameConstants::PRIMARY_SKILLS; ++primarySkill)
|
||||
@ -1363,7 +1363,7 @@ PrimarySkill::PrimarySkill CGHeroInstance::nextPrimarySkill() const
|
||||
return static_cast<PrimarySkill::PrimarySkill>(primarySkill);
|
||||
}
|
||||
|
||||
boost::optional<SecondarySkill> CGHeroInstance::nextSecondarySkill() const
|
||||
boost::optional<SecondarySkill> CGHeroInstance::nextSecondarySkill(CRandomGenerator & rand) const
|
||||
{
|
||||
assert(gainsLevel());
|
||||
|
||||
@ -1380,7 +1380,6 @@ boost::optional<SecondarySkill> CGHeroInstance::nextSecondarySkill() const
|
||||
}
|
||||
}
|
||||
|
||||
auto & rand = cb->gameState()->getRandomGenerator();
|
||||
if(learnedSecondarySkills.empty())
|
||||
{
|
||||
// there are only new skills to learn, so choose anyone of them
|
||||
@ -1459,16 +1458,16 @@ void CGHeroInstance::levelUp(std::vector<SecondarySkill> skills)
|
||||
Updatespecialty();
|
||||
}
|
||||
|
||||
void CGHeroInstance::levelUpAutomatically()
|
||||
void CGHeroInstance::levelUpAutomatically(CRandomGenerator & rand)
|
||||
{
|
||||
while(gainsLevel())
|
||||
{
|
||||
const auto primarySkill = nextPrimarySkill();
|
||||
const auto primarySkill = nextPrimarySkill(rand);
|
||||
setPrimarySkill(primarySkill, 1, false);
|
||||
|
||||
auto proposedSecondarySkills = getLevelUpProposedSecondarySkills();
|
||||
|
||||
const auto secondarySkill = nextSecondarySkill();
|
||||
const auto secondarySkill = nextSecondarySkill(rand);
|
||||
if(secondarySkill)
|
||||
{
|
||||
setSecSkillLevel(*secondarySkill, 1, false);
|
||||
|
@ -163,10 +163,10 @@ public:
|
||||
bool gainsLevel() const;
|
||||
|
||||
/// Returns the next primary skill on level up. Can only be called if hero can gain a level up.
|
||||
PrimarySkill::PrimarySkill nextPrimarySkill() const;
|
||||
PrimarySkill::PrimarySkill nextPrimarySkill(CRandomGenerator & rand) const;
|
||||
|
||||
/// Returns the next secondary skill randomly on level up. Can only be called if hero can gain a level up.
|
||||
boost::optional<SecondarySkill> nextSecondarySkill() const;
|
||||
boost::optional<SecondarySkill> nextSecondarySkill(CRandomGenerator & rand) const;
|
||||
|
||||
/// Gets 0, 1 or 2 secondary skills which are proposed on hero level up.
|
||||
std::vector<SecondarySkill> getLevelUpProposedSecondarySkills() const;
|
||||
@ -192,20 +192,20 @@ public:
|
||||
|
||||
bool canCastThisSpell(const CSpell * spell) const; //determines if this hero can cast given spell; takes into account existing spell in spellbook, existing spellbook and artifact bonuses
|
||||
CStackBasicDescriptor calculateNecromancy (const BattleResult &battleResult) const;
|
||||
void showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const;
|
||||
void showNecromancyDialog(const CStackBasicDescriptor &raisedStack, CRandomGenerator & rand) const;
|
||||
EDiggingStatus diggingStatus() const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void setType(si32 ID, si32 subID) override;
|
||||
|
||||
void initHero();
|
||||
void initHero(HeroTypeID SUBID);
|
||||
void initHero(CRandomGenerator & rand);
|
||||
void initHero(CRandomGenerator & rand, HeroTypeID SUBID);
|
||||
|
||||
void putArtifact(ArtifactPosition pos, CArtifactInstance *art);
|
||||
void putInBackpack(CArtifactInstance *art);
|
||||
void initExp();
|
||||
void initArmy(IArmyDescriptor *dst = nullptr);
|
||||
void initExp(CRandomGenerator & rand);
|
||||
void initArmy(CRandomGenerator & rand, IArmyDescriptor *dst = nullptr);
|
||||
//void giveArtifact (ui32 aid);
|
||||
void pushPrimSkill(PrimarySkill::PrimarySkill which, int val);
|
||||
ui8 maxlevelsToMagicSchool() const;
|
||||
@ -250,7 +250,7 @@ public:
|
||||
|
||||
void deserializationFix();
|
||||
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
std::string getObjectName() const override;
|
||||
protected:
|
||||
@ -258,7 +258,7 @@ protected:
|
||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||
|
||||
private:
|
||||
void levelUpAutomatically();
|
||||
void levelUpAutomatically(CRandomGenerator & rand);
|
||||
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
|
@ -282,18 +282,18 @@ std::vector<int> CGBlackMarket::availableItemsIds(EMarketMode::EMarketMode mode)
|
||||
}
|
||||
}
|
||||
|
||||
void CGBlackMarket::newTurn() const
|
||||
void CGBlackMarket::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if(cb->getDate(Date::DAY_OF_MONTH) != 1) //new month
|
||||
return;
|
||||
|
||||
SetAvailableArtifacts saa;
|
||||
saa.id = id.getNum();
|
||||
cb->pickAllowedArtsSet(saa.arts);
|
||||
cb->pickAllowedArtsSet(saa.arts, rand);
|
||||
cb->sendAndApply(&saa);
|
||||
}
|
||||
|
||||
void CGUniversity::initObj()
|
||||
void CGUniversity::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
std::vector<int> toChoose;
|
||||
for(int i = 0; i < GameConstants::SKILL_QUANTITY; ++i)
|
||||
@ -313,7 +313,7 @@ void CGUniversity::initObj()
|
||||
for(int i = 0; i < 4; ++i)
|
||||
{
|
||||
// move randomly one skill to selected and remove from list
|
||||
auto it = RandomGeneratorUtil::nextItem(toChoose, cb->gameState()->getRandomGenerator());
|
||||
auto it = RandomGeneratorUtil::nextItem(toChoose, rand);
|
||||
skills.push_back(*it);
|
||||
toChoose.erase(it);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class DLL_LINKAGE CGBlackMarket : public CGMarket
|
||||
public:
|
||||
std::vector<const CArtifact *> artifacts; //available artifacts
|
||||
|
||||
void newTurn() const override; //reset artifacts for black market every month
|
||||
void newTurn(CRandomGenerator & rand) const override; //reset artifacts for black market every month
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -77,7 +77,7 @@ public:
|
||||
std::vector<int> skills; //available skills
|
||||
|
||||
std::vector<int> availableItemsIds(EMarketMode::EMarketMode mode) const override;
|
||||
void initObj() override;//set skills for trade
|
||||
void initObj(CRandomGenerator & rand) override;//set skills for trade
|
||||
void onHeroVisit(const CGHeroInstance * h) const override; //open window
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
|
@ -34,7 +34,7 @@ static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16
|
||||
showInfoDialog(playerID,txtID,soundID);
|
||||
}
|
||||
|
||||
void CGPandoraBox::initObj()
|
||||
void CGPandoraBox::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = (ID==Obj::PANDORAS_BOX); //block only if it's really pandora's box (events also derive from that class)
|
||||
hasGuardians = stacks.size();
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
CCreatureSet creatures; //gained creatures
|
||||
|
||||
CGPandoraBox() : gainedExp(0), manaDiff(0), moraleDiff(0), luckDiff(0){};
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
@ -25,14 +25,14 @@
|
||||
std::vector<const CArtifact *> CGTownInstance::merchantArtifacts;
|
||||
std::vector<int> CGTownInstance::universitySkills;
|
||||
|
||||
void CGDwelling::initObj()
|
||||
void CGDwelling::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
switch(ID)
|
||||
{
|
||||
case Obj::CREATURE_GENERATOR1:
|
||||
case Obj::CREATURE_GENERATOR4:
|
||||
{
|
||||
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, cb->gameState()->getRandomGenerator());
|
||||
VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, rand);
|
||||
|
||||
if (getOwner() != PlayerColor::NEUTRAL)
|
||||
cb->gameState()->players[getOwner()].dwellings.push_back (this);
|
||||
@ -141,7 +141,7 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
|
||||
cb->showBlockingDialog(&bd);
|
||||
}
|
||||
|
||||
void CGDwelling::newTurn() const
|
||||
void CGDwelling::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if(cb->getDate(Date::DAY_OF_WEEK) != 1) //not first day of week
|
||||
return;
|
||||
@ -152,7 +152,7 @@ void CGDwelling::newTurn() const
|
||||
|
||||
if(ID == Obj::REFUGEE_CAMP) //if it's a refugee camp, we need to pick an available creature
|
||||
{
|
||||
cb->setObjProperty(id, ObjProperty::AVAILABLE_CREATURE, VLC->creh->pickRandomMonster(cb->gameState()->getRandomGenerator()));
|
||||
cb->setObjProperty(id, ObjProperty::AVAILABLE_CREATURE, VLC->creh->pickRandomMonster(rand));
|
||||
}
|
||||
|
||||
bool change = false;
|
||||
@ -595,7 +595,7 @@ std::string CGTownInstance::getObjectName() const
|
||||
return name + ", " + town->faction->name;
|
||||
}
|
||||
|
||||
void CGTownInstance::initObj()
|
||||
void CGTownInstance::initObj(CRandomGenerator & rand)
|
||||
///initialize town structures
|
||||
{
|
||||
blockVisit = true;
|
||||
@ -637,12 +637,10 @@ void CGTownInstance::initObj()
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
void CGTownInstance::newTurn() const
|
||||
void CGTownInstance::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if (cb->getDate(Date::DAY_OF_WEEK) == 1) //reset on new week
|
||||
{
|
||||
auto & rand = cb->gameState()->getRandomGenerator();
|
||||
|
||||
//give resources for Rampart, Mystic Pond
|
||||
if (hasBuilt(BuildingID::MYSTIC_POND, ETownType::RAMPART)
|
||||
&& cb->getDate(Date::DAY) != 1 && (tempOwner < PlayerColor::PLAYER_LIMIT))
|
||||
|
@ -56,9 +56,9 @@ protected:
|
||||
void serializeJsonOptions(JsonSerializeFormat & handler) override;
|
||||
|
||||
private:
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void newTurn() const override;
|
||||
void newTurn(CRandomGenerator & rand) const override;
|
||||
void setPropertyDer(ui8 what, ui32 val) override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
@ -249,10 +249,10 @@ public:
|
||||
virtual ~CGTownInstance();
|
||||
|
||||
///IObjectInterface overrides
|
||||
void newTurn() const override;
|
||||
void newTurn(CRandomGenerator & rand) const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void onHeroLeave(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
std::string getObjectName() const override;
|
||||
protected:
|
||||
|
@ -66,7 +66,7 @@ void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const
|
||||
void IObjectInterface::onHeroLeave(const CGHeroInstance * h) const
|
||||
{}
|
||||
|
||||
void IObjectInterface::newTurn () const
|
||||
void IObjectInterface::newTurn(CRandomGenerator & rand) const
|
||||
{}
|
||||
|
||||
IObjectInterface::~IObjectInterface()
|
||||
@ -75,7 +75,7 @@ IObjectInterface::~IObjectInterface()
|
||||
IObjectInterface::IObjectInterface()
|
||||
{}
|
||||
|
||||
void IObjectInterface::initObj()
|
||||
void IObjectInterface::initObj(CRandomGenerator & rand)
|
||||
{}
|
||||
|
||||
void IObjectInterface::setProperty( ui8 what, ui32 val )
|
||||
@ -207,7 +207,7 @@ void CGObjectInstance::setType(si32 ID, si32 subID)
|
||||
cb->gameState()->map->addBlockVisTiles(this);
|
||||
}
|
||||
|
||||
void CGObjectInstance::initObj()
|
||||
void CGObjectInstance::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
switch(ID)
|
||||
{
|
||||
|
@ -22,6 +22,7 @@ class CGObjectInstance;
|
||||
struct MetaString;
|
||||
struct BattleResult;
|
||||
class JsonSerializeFormat;
|
||||
class CRandomGenerator;
|
||||
|
||||
// This one teleport-specific, but has to be available everywhere in callbacks and netpacks
|
||||
// For now it's will be there till teleports code refactored and moved into own file
|
||||
@ -37,8 +38,8 @@ public:
|
||||
|
||||
virtual void onHeroVisit(const CGHeroInstance * h) const;
|
||||
virtual void onHeroLeave(const CGHeroInstance * h) const;
|
||||
virtual void newTurn() const;
|
||||
virtual void initObj(); //synchr
|
||||
virtual void newTurn(CRandomGenerator & rand) const;
|
||||
virtual void initObj(CRandomGenerator & rand); //synchr
|
||||
virtual void setProperty(ui8 what, ui32 val);//synchr
|
||||
|
||||
//Called when queries created DURING HERO VISIT are resolved
|
||||
@ -166,7 +167,7 @@ public:
|
||||
|
||||
/** OVERRIDES OF IObjectInterface **/
|
||||
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
/// method for synchronous update. Note: For new properties classes should override setPropertyDer instead
|
||||
void setProperty(ui8 what, ui32 val) override final;
|
||||
|
@ -420,16 +420,16 @@ void CGSeerHut::setObjToKill()
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::init()
|
||||
void CGSeerHut::init(CRandomGenerator & rand)
|
||||
{
|
||||
seerName = *RandomGeneratorUtil::nextItem(VLC->generaltexth->seerNames, cb->gameState()->getRandomGenerator());
|
||||
quest->textOption = cb->gameState()->getRandomGenerator().nextInt(2);
|
||||
quest->completedOption = cb->gameState()->getRandomGenerator().nextInt(1, 3);
|
||||
seerName = *RandomGeneratorUtil::nextItem(VLC->generaltexth->seerNames, rand);
|
||||
quest->textOption = rand.nextInt(2);
|
||||
quest->completedOption = rand.nextInt(1, 3);
|
||||
}
|
||||
|
||||
void CGSeerHut::initObj()
|
||||
void CGSeerHut::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
init();
|
||||
init(rand);
|
||||
|
||||
quest->progress = CQuest::NOT_ACTIVE;
|
||||
if(quest->missionType)
|
||||
@ -549,7 +549,7 @@ void CGSeerHut::setPropertyDer (ui8 what, ui32 val)
|
||||
}
|
||||
}
|
||||
|
||||
void CGSeerHut::newTurn() const
|
||||
void CGSeerHut::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if(quest->lastDay >= 0 && quest->lastDay <= cb->getDate() - 1) //time is up
|
||||
{
|
||||
@ -761,11 +761,11 @@ void CGSeerHut::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
|
||||
finishQuest(hero, answer);
|
||||
}
|
||||
|
||||
void CGQuestGuard::init()
|
||||
void CGQuestGuard::init(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
quest->textOption = cb->gameState()->getRandomGenerator().nextInt(3, 5);
|
||||
quest->completedOption = cb->gameState()->getRandomGenerator().nextInt(4, 5);
|
||||
quest->textOption = rand.nextInt(3, 5);
|
||||
quest->completedOption = rand.nextInt(4, 5);
|
||||
}
|
||||
|
||||
void CGQuestGuard::completeQuest(const CGHeroInstance *h) const
|
||||
@ -825,7 +825,7 @@ void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
|
||||
showInfoDialog(h,txt_id,soundBase::CAVEHEAD);
|
||||
}
|
||||
|
||||
void CGBorderGuard::initObj()
|
||||
void CGBorderGuard::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
//ui32 m13489val = subID; //store color as quest info
|
||||
blockVisit = true;
|
||||
|
@ -108,13 +108,13 @@ public:
|
||||
std::string seerName;
|
||||
|
||||
CGSeerHut();
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
void newTurn() const override;
|
||||
void newTurn(CRandomGenerator & rand) const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
virtual void init();
|
||||
virtual void init(CRandomGenerator & rand);
|
||||
int checkDirection() const; //calculates the region of map where monster is placed
|
||||
void setObjToKill(); //remember creatures / heroes to kill after they are initialized
|
||||
const CGHeroInstance *getHeroToKill(bool allowNull = false) const;
|
||||
@ -139,7 +139,7 @@ class DLL_LINKAGE CGQuestGuard : public CGSeerHut
|
||||
{
|
||||
public:
|
||||
CGQuestGuard() : CGSeerHut(){};
|
||||
void init() override;
|
||||
void init(CRandomGenerator & rand) override;
|
||||
void completeQuest (const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -185,7 +185,7 @@ class DLL_LINKAGE CGBorderGuard : public CGKeys, public IQuestObject
|
||||
{
|
||||
public:
|
||||
CGBorderGuard() : IQuestObject(){};
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
|
@ -158,7 +158,7 @@ void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const
|
||||
grantRewardWithMessage(rewards[0]);
|
||||
break;
|
||||
case SELECT_RANDOM: // select one randomly //TODO: use weights
|
||||
grantRewardWithMessage(rewards[cb->gameState()->getRandomGenerator().nextInt(rewards.size()-1)]);
|
||||
grantRewardWithMessage(rewards[CRandomGenerator::getDefault().nextInt(rewards.size()-1)]);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
@ -431,7 +431,7 @@ void CRewardableObject::setPropertyDer(ui8 what, ui32 val)
|
||||
}
|
||||
}
|
||||
|
||||
void CRewardableObject::newTurn() const
|
||||
void CRewardableObject::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if (resetDuration != 0 && cb->getDate(Date::DAY) > 1 && (cb->getDate(Date::DAY) % resetDuration) == 1)
|
||||
cb->setObjProperty(id, ObjProperty::REWARD_RESET, 0);
|
||||
@ -450,11 +450,11 @@ CRewardableObject::CRewardableObject():
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Helper, selects random art class based on weights
|
||||
static int selectRandomArtClass(int treasure, int minor, int major, int relic)
|
||||
static int selectRandomArtClass(CRandomGenerator & rand, int treasure, int minor, int major, int relic)
|
||||
{
|
||||
int total = treasure + minor + major + relic;
|
||||
assert(total != 0);
|
||||
int hlp = IObjectInterface::cb->gameState()->getRandomGenerator().nextInt(total - 1);
|
||||
int hlp = rand.nextInt(total - 1);
|
||||
|
||||
if(hlp < treasure)
|
||||
return CArtifact::ART_TREASURE;
|
||||
@ -466,10 +466,10 @@ static int selectRandomArtClass(int treasure, int minor, int major, int relic)
|
||||
}
|
||||
|
||||
/// Helper, adds random artifact to reward selecting class based on weights
|
||||
static void loadRandomArtifact(CVisitInfo & info, int treasure, int minor, int major, int relic)
|
||||
static void loadRandomArtifact(CRandomGenerator & rand, CVisitInfo & info, int treasure, int minor, int major, int relic)
|
||||
{
|
||||
int artClass = selectRandomArtClass(treasure, minor, major, relic);
|
||||
ArtifactID artID = VLC->arth->pickRandomArtifact(IObjectInterface::cb->gameState()->getRandomGenerator(), artClass);
|
||||
int artClass = selectRandomArtClass(rand, treasure, minor, major, relic);
|
||||
ArtifactID artID = VLC->arth->pickRandomArtifact(rand, artClass);
|
||||
info.reward.artifacts.push_back(artID);
|
||||
}
|
||||
|
||||
@ -479,7 +479,7 @@ CGPickable::CGPickable()
|
||||
selectMode = SELECT_PLAYER;
|
||||
}
|
||||
|
||||
void CGPickable::initObj()
|
||||
void CGPickable::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
switch(ID)
|
||||
@ -487,8 +487,8 @@ void CGPickable::initObj()
|
||||
case Obj::CAMPFIRE:
|
||||
{
|
||||
soundID = soundBase::experience;
|
||||
int givenRes = cb->gameState()->getRandomGenerator().nextInt(5);
|
||||
int givenAmm = cb->gameState()->getRandomGenerator().nextInt(4, 6);
|
||||
int givenRes = rand.nextInt(5);
|
||||
int givenAmm = rand.nextInt(4, 6);
|
||||
|
||||
info.resize(1);
|
||||
info[0].reward.resources[givenRes] = givenAmm;
|
||||
@ -499,7 +499,7 @@ void CGPickable::initObj()
|
||||
}
|
||||
case Obj::FLOTSAM:
|
||||
{
|
||||
int type = cb->gameState()->getRandomGenerator().nextInt(3);
|
||||
int type = rand.nextInt(3);
|
||||
soundID = soundBase::GENIE;
|
||||
switch(type)
|
||||
{
|
||||
@ -540,7 +540,7 @@ void CGPickable::initObj()
|
||||
case Obj::SEA_CHEST:
|
||||
{
|
||||
soundID = soundBase::chest;
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
int hlp = rand.nextInt(99);
|
||||
if(hlp < 20)
|
||||
{
|
||||
info.resize(1);
|
||||
@ -557,7 +557,7 @@ void CGPickable::initObj()
|
||||
else
|
||||
{
|
||||
info.resize(1);
|
||||
loadRandomArtifact(info[0], 100, 0, 0, 0);
|
||||
loadRandomArtifact(rand, info[0], 100, 0, 0, 0);
|
||||
info[0].reward.resources[Res::GOLD] = 1000;
|
||||
info[0].message.addTxt(MetaString::ADVOB_TXT, 117);
|
||||
info[0].message.addReplacement(MetaString::ART_NAMES, info[0].reward.artifacts.back());
|
||||
@ -569,7 +569,7 @@ void CGPickable::initObj()
|
||||
{
|
||||
soundID = soundBase::experience;
|
||||
info.resize(1);
|
||||
loadRandomArtifact(info[0], 55, 20, 20, 5);
|
||||
loadRandomArtifact(rand, info[0], 55, 20, 20, 5);
|
||||
info[0].message.addTxt(MetaString::ADVOB_TXT, 125);
|
||||
info[0].message.addReplacement(MetaString::ART_NAMES, info[0].reward.artifacts.back());
|
||||
info[0].reward.removeObject = true;
|
||||
@ -577,12 +577,12 @@ void CGPickable::initObj()
|
||||
break;
|
||||
case Obj::TREASURE_CHEST:
|
||||
{
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
int hlp = rand.nextInt(99);
|
||||
if(hlp >= 95)
|
||||
{
|
||||
soundID = soundBase::treasure;
|
||||
info.resize(1);
|
||||
loadRandomArtifact(info[0], 100, 0, 0, 0);
|
||||
loadRandomArtifact(rand, info[0], 100, 0, 0, 0);
|
||||
info[0].message.addTxt(MetaString::ADVOB_TXT,145);
|
||||
info[0].message.addReplacement(MetaString::ART_NAMES, info[0].reward.artifacts.back());
|
||||
info[0].reward.removeObject = true;
|
||||
@ -631,7 +631,7 @@ CGBonusingObject::CGBonusingObject()
|
||||
selectMode = SELECT_FIRST;
|
||||
}
|
||||
|
||||
void CGBonusingObject::initObj()
|
||||
void CGBonusingObject::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
auto configureBonusDuration = [&](CVisitInfo & visit, Bonus::BonusDuration duration, Bonus::BonusType type, si32 value, si32 descrID)
|
||||
{
|
||||
@ -817,7 +817,7 @@ CGOnceVisitable::CGOnceVisitable()
|
||||
selectMode = SELECT_FIRST;
|
||||
}
|
||||
|
||||
void CGOnceVisitable::initObj()
|
||||
void CGOnceVisitable::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
switch(ID)
|
||||
{
|
||||
@ -826,10 +826,10 @@ void CGOnceVisitable::initObj()
|
||||
onEmpty.addTxt(MetaString::ADVOB_TXT, 38);
|
||||
soundID = soundBase::MYSTERY;
|
||||
blockVisit = true;
|
||||
if(cb->gameState()->getRandomGenerator().nextInt(99) < 20)
|
||||
if(rand.nextInt(99) < 20)
|
||||
{
|
||||
info.resize(1);
|
||||
loadRandomArtifact(info[0], 10, 10, 10, 0);
|
||||
loadRandomArtifact(rand, info[0], 10, 10, 10, 0);
|
||||
info[0].message.addTxt(MetaString::ADVOB_TXT, 37);
|
||||
}
|
||||
}
|
||||
@ -839,8 +839,8 @@ void CGOnceVisitable::initObj()
|
||||
soundID = soundBase::GENIE;
|
||||
onEmpty.addTxt(MetaString::ADVOB_TXT, 65);
|
||||
info.resize(1);
|
||||
int type = cb->gameState()->getRandomGenerator().nextInt(5); //any basic resource without gold
|
||||
int value = cb->gameState()->getRandomGenerator().nextInt(1, 4);
|
||||
int type = rand.nextInt(5); //any basic resource without gold
|
||||
int value = rand.nextInt(1, 4);
|
||||
info[0].reward.resources[type] = value;
|
||||
info[0].message.addTxt(MetaString::ADVOB_TXT, 64);
|
||||
}
|
||||
@ -851,7 +851,7 @@ void CGOnceVisitable::initObj()
|
||||
onSelect.addTxt(MetaString::ADVOB_TXT, 161);
|
||||
|
||||
info.resize(2);
|
||||
loadRandomArtifact(info[0], 30, 50, 25, 5);
|
||||
loadRandomArtifact(rand, info[0], 30, 50, 25, 5);
|
||||
|
||||
Bonus bonus(Bonus::ONE_BATTLE, Bonus::MORALE, Bonus::OBJECT, -3, ID);
|
||||
info[0].reward.bonuses.push_back(bonus);
|
||||
@ -866,19 +866,19 @@ void CGOnceVisitable::initObj()
|
||||
soundID = soundBase::GENIE;
|
||||
onVisited.addTxt(MetaString::ADVOB_TXT, 156);
|
||||
|
||||
int hlp = cb->gameState()->getRandomGenerator().nextInt(99);
|
||||
int hlp = rand.nextInt(99);
|
||||
|
||||
if(hlp < 40) //minor or treasure art
|
||||
{
|
||||
info.resize(1);
|
||||
loadRandomArtifact(info[0], 10, 10, 0, 0);
|
||||
loadRandomArtifact(rand, info[0], 10, 10, 0, 0);
|
||||
info[0].message.addTxt(MetaString::ADVOB_TXT, 155);
|
||||
}
|
||||
else if(hlp < 90) //2 - 5 of non-gold resource
|
||||
{
|
||||
info.resize(1);
|
||||
int type = cb->gameState()->getRandomGenerator().nextInt(5);
|
||||
int value = cb->gameState()->getRandomGenerator().nextInt(2, 5);
|
||||
int type = rand.nextInt(5);
|
||||
int value = rand.nextInt(2, 5);
|
||||
info[0].reward.resources[type] = value;
|
||||
info[0].message.addTxt(MetaString::ADVOB_TXT, 154);
|
||||
}
|
||||
@ -896,7 +896,7 @@ CGVisitableOPH::CGVisitableOPH()
|
||||
selectMode = SELECT_PLAYER;
|
||||
}
|
||||
|
||||
void CGVisitableOPH::initObj()
|
||||
void CGVisitableOPH::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
switch(ID)
|
||||
{
|
||||
@ -951,7 +951,7 @@ void CGVisitableOPH::initObj()
|
||||
info[0].reward.gainedLevels = 1;
|
||||
onVisited.addTxt(MetaString::ADVOB_TXT, 147);
|
||||
info.resize(1);
|
||||
switch (cb->gameState()->getRandomGenerator().nextInt(2))
|
||||
switch (rand.nextInt(2))
|
||||
{
|
||||
case 0: // free
|
||||
onSelect.addTxt(MetaString::ADVOB_TXT, 148);
|
||||
@ -1029,7 +1029,7 @@ CGVisitableOPW::CGVisitableOPW()
|
||||
resetDuration = 7;
|
||||
}
|
||||
|
||||
void CGVisitableOPW::initObj()
|
||||
void CGVisitableOPW::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
switch (ID)
|
||||
{
|
||||
@ -1087,7 +1087,7 @@ void CGVisitableOPW::setPropertyDer(ui8 what, ui32 val)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CGMagicSpring::initObj()
|
||||
void CGMagicSpring::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
CVisitInfo visit; // TODO: "player above max mana" limiter. Use logical expressions for limiters?
|
||||
visit.reward.manaPercentage = 200;
|
||||
|
@ -227,7 +227,7 @@ public:
|
||||
void onHeroVisit(const CGHeroInstance *h) const override;
|
||||
|
||||
///possibly resets object state
|
||||
void newTurn() const override;
|
||||
void newTurn(CRandomGenerator & rand) const override;
|
||||
|
||||
/// gives second part of reward after hero level-ups for proper granting of spells/mana
|
||||
void heroLevelUpDone(const CGHeroInstance *hero) const override;
|
||||
@ -255,7 +255,7 @@ public:
|
||||
class DLL_LINKAGE CGPickable : public CRewardableObject //campfire, treasure chest, Flotsam, Shipwreck Survivor, Sea Chest
|
||||
{
|
||||
public:
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
CGPickable();
|
||||
|
||||
@ -273,7 +273,7 @@ protected:
|
||||
void grantReward(ui32 rewardID, const CGHeroInstance * hero) const override;
|
||||
|
||||
public:
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
CGBonusingObject();
|
||||
|
||||
@ -290,7 +290,7 @@ public:
|
||||
class DLL_LINKAGE CGOnceVisitable : public CRewardableObject // wagon, corpse, lean to, warriors tomb
|
||||
{
|
||||
public:
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
CGOnceVisitable();
|
||||
|
||||
@ -303,7 +303,7 @@ public:
|
||||
class DLL_LINKAGE CGVisitableOPH : public CRewardableObject //objects visitable only once per hero
|
||||
{
|
||||
public:
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
CGVisitableOPH();
|
||||
|
||||
@ -316,7 +316,7 @@ public:
|
||||
class DLL_LINKAGE CGVisitableOPW : public CRewardableObject //objects visitable once per week
|
||||
{
|
||||
public:
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
CGVisitableOPW();
|
||||
|
||||
@ -335,7 +335,7 @@ protected:
|
||||
std::vector<ui32> getAvailableRewards(const CGHeroInstance * hero) const override;
|
||||
|
||||
public:
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
std::vector<int3> getVisitableOffsets() const;
|
||||
int3 getVisitableOffset() const override;
|
||||
|
||||
|
@ -201,7 +201,7 @@ void CGCreature::onHeroVisit( const CGHeroInstance * h ) const
|
||||
|
||||
}
|
||||
|
||||
void CGCreature::initObj()
|
||||
void CGCreature::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
switch(character)
|
||||
@ -210,13 +210,13 @@ void CGCreature::initObj()
|
||||
character = -4;
|
||||
break;
|
||||
case 1:
|
||||
character = cb->gameState()->getRandomGenerator().nextInt(1, 7);
|
||||
character = rand.nextInt(1, 7);
|
||||
break;
|
||||
case 2:
|
||||
character = cb->gameState()->getRandomGenerator().nextInt(1, 10);
|
||||
character = rand.nextInt(1, 10);
|
||||
break;
|
||||
case 3:
|
||||
character = cb->gameState()->getRandomGenerator().nextInt(4, 10);
|
||||
character = rand.nextInt(4, 10);
|
||||
break;
|
||||
case 4:
|
||||
character = 10;
|
||||
@ -228,7 +228,7 @@ void CGCreature::initObj()
|
||||
CCreature &c = *VLC->creh->creatures[subID];
|
||||
if(amount == 0)
|
||||
{
|
||||
amount = cb->gameState()->getRandomGenerator().nextInt(c.ammMin, c.ammMax);
|
||||
amount = rand.nextInt(c.ammMin, c.ammMax);
|
||||
|
||||
if(amount == 0) //armies with 0 creatures are illegal
|
||||
{
|
||||
@ -241,7 +241,7 @@ void CGCreature::initObj()
|
||||
refusedJoining = false;
|
||||
}
|
||||
|
||||
void CGCreature::newTurn() const
|
||||
void CGCreature::newTurn(CRandomGenerator & rand) const
|
||||
{//Works only for stacks of single type of size up to 2 millions
|
||||
if (!notGrowingTeam)
|
||||
{
|
||||
@ -434,7 +434,7 @@ void CGCreature::fight( const CGHeroInstance *h ) const
|
||||
const auto & upgrades = getStack(slotID).type->upgrades;
|
||||
if(!upgrades.empty())
|
||||
{
|
||||
auto it = RandomGeneratorUtil::nextItem(upgrades, cb->gameState()->getRandomGenerator());
|
||||
auto it = RandomGeneratorUtil::nextItem(upgrades, CRandomGenerator::getDefault());
|
||||
cb->changeStackType(StackLocation(this, slotID), VLC->creh->creatures[*it]);
|
||||
}
|
||||
}
|
||||
@ -676,7 +676,7 @@ void CGMine::onHeroVisit( const CGHeroInstance * h ) const
|
||||
|
||||
}
|
||||
|
||||
void CGMine::newTurn() const
|
||||
void CGMine::newTurn(CRandomGenerator & rand) const
|
||||
{
|
||||
if(cb->getDate() == 1)
|
||||
return;
|
||||
@ -687,12 +687,12 @@ void CGMine::newTurn() const
|
||||
cb->giveResource(tempOwner, producedResource, producedQuantity);
|
||||
}
|
||||
|
||||
void CGMine::initObj()
|
||||
void CGMine::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
if(isAbandoned())
|
||||
{
|
||||
//set guardians
|
||||
int howManyTroglodytes = cb->gameState()->getRandomGenerator().nextInt(100, 199);
|
||||
int howManyTroglodytes = rand.nextInt(100, 199);
|
||||
auto troglodytes = new CStackInstance(CreatureID::TROGLODYTES, howManyTroglodytes);
|
||||
putStack(SlotID(0), troglodytes);
|
||||
|
||||
@ -703,7 +703,7 @@ void CGMine::initObj()
|
||||
possibleResources.push_back(static_cast<Res::ERes>(i));
|
||||
|
||||
assert(!possibleResources.empty());
|
||||
producedResource = *RandomGeneratorUtil::nextItem(possibleResources, cb->gameState()->getRandomGenerator());
|
||||
producedResource = *RandomGeneratorUtil::nextItem(possibleResources, rand);
|
||||
tempOwner = PlayerColor::NEUTRAL;
|
||||
}
|
||||
else
|
||||
@ -859,7 +859,7 @@ CGResource::CGResource()
|
||||
amount = 0;
|
||||
}
|
||||
|
||||
void CGResource::initObj()
|
||||
void CGResource::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
|
||||
@ -868,13 +868,13 @@ void CGResource::initObj()
|
||||
switch(subID)
|
||||
{
|
||||
case 6:
|
||||
amount = cb->gameState()->getRandomGenerator().nextInt(500, 1000);
|
||||
amount = rand.nextInt(500, 1000);
|
||||
break;
|
||||
case 0: case 2:
|
||||
amount = cb->gameState()->getRandomGenerator().nextInt(6, 10);
|
||||
amount = rand.nextInt(6, 10);
|
||||
break;
|
||||
default:
|
||||
amount = cb->gameState()->getRandomGenerator().nextInt(3, 5);
|
||||
amount = rand.nextInt(3, 5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -987,7 +987,7 @@ ObjectInstanceID CGTeleport::getRandomExit(const CGHeroInstance * h) const
|
||||
{
|
||||
auto passableExits = getPassableExits(cb->gameState(), h, getAllExits(true));
|
||||
if(passableExits.size())
|
||||
return *RandomGeneratorUtil::nextItem(passableExits, cb->gameState()->getRandomGenerator());
|
||||
return *RandomGeneratorUtil::nextItem(passableExits, CRandomGenerator::getDefault());
|
||||
|
||||
return ObjectInstanceID();
|
||||
}
|
||||
@ -1119,7 +1119,7 @@ void CGMonolith::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer,
|
||||
cb->moveHero(hero->id, dPos, true);
|
||||
}
|
||||
|
||||
void CGMonolith::initObj()
|
||||
void CGMonolith::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
std::vector<Obj> IDs;
|
||||
IDs.push_back(ID);
|
||||
@ -1164,7 +1164,7 @@ void CGSubterraneanGate::onHeroVisit( const CGHeroInstance * h ) const
|
||||
cb->showTeleportDialog(&td);
|
||||
}
|
||||
|
||||
void CGSubterraneanGate::initObj()
|
||||
void CGSubterraneanGate::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
type = BOTH;
|
||||
}
|
||||
@ -1283,7 +1283,7 @@ void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer
|
||||
{
|
||||
auto obj = cb->getObj(getRandomExit(hero));
|
||||
std::set<int3> tiles = obj->getBlockedPos();
|
||||
dPos = CGHeroInstance::convertPosition(*RandomGeneratorUtil::nextItem(tiles, cb->gameState()->getRandomGenerator()), true);
|
||||
dPos = CGHeroInstance::convertPosition(*RandomGeneratorUtil::nextItem(tiles, CRandomGenerator::getDefault()), true);
|
||||
}
|
||||
|
||||
cb->moveHero(hero->id, dPos, true);
|
||||
@ -1299,7 +1299,7 @@ bool CGWhirlpool::isProtected(const CGHeroInstance * h)
|
||||
return false;
|
||||
}
|
||||
|
||||
void CGArtifact::initObj()
|
||||
void CGArtifact::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
if(ID == Obj::ARTIFACT)
|
||||
@ -1441,14 +1441,14 @@ void CGArtifact::serializeJsonOptions(JsonSerializeFormat& handler)
|
||||
}
|
||||
}
|
||||
|
||||
void CGWitchHut::initObj()
|
||||
void CGWitchHut::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
if (allowedAbilities.empty()) //this can happen for RMG. regular maps load abilities from map file
|
||||
{
|
||||
for (int i = 0; i < GameConstants::SKILL_QUANTITY; i++)
|
||||
allowedAbilities.push_back(i);
|
||||
}
|
||||
ability = *RandomGeneratorUtil::nextItem(allowedAbilities, cb->gameState()->getRandomGenerator());
|
||||
ability = *RandomGeneratorUtil::nextItem(allowedAbilities, rand);
|
||||
}
|
||||
|
||||
void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
|
||||
@ -1627,7 +1627,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
|
||||
cb->showInfoDialog(&iw);
|
||||
}
|
||||
|
||||
void CGShrine::initObj()
|
||||
void CGShrine::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
if(spell == SpellID::NONE) //spell not set
|
||||
{
|
||||
@ -1641,7 +1641,7 @@ void CGShrine::initObj()
|
||||
return;
|
||||
}
|
||||
|
||||
spell = *RandomGeneratorUtil::nextItem(possibilities, cb->gameState()->getRandomGenerator());
|
||||
spell = *RandomGeneratorUtil::nextItem(possibilities, rand);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1669,12 +1669,12 @@ void CGShrine::serializeJsonOptions(JsonSerializeFormat& handler)
|
||||
handler.serializeId("spell", &CSpellHandler::decodeSpell, &CSpellHandler::encodeSpell, SpellID(SpellID::NONE), spell);
|
||||
}
|
||||
|
||||
void CGSignBottle::initObj()
|
||||
void CGSignBottle::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
//if no text is set than we pick random from the predefined ones
|
||||
if(message.empty())
|
||||
{
|
||||
message = *RandomGeneratorUtil::nextItem(VLC->generaltexth->randsign, cb->gameState()->getRandomGenerator());
|
||||
message = *RandomGeneratorUtil::nextItem(VLC->generaltexth->randsign, rand);
|
||||
}
|
||||
|
||||
if(ID == Obj::OCEAN_BOTTLE)
|
||||
@ -1714,7 +1714,7 @@ void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
|
||||
))) //hero doesn't have a spellbook or already knows the spell or doesn't have Wisdom
|
||||
{
|
||||
type = PRIM_SKILL;
|
||||
bid = cb->gameState()->getRandomGenerator().nextInt(GameConstants::PRIMARY_SKILLS - 1);
|
||||
bid = CRandomGenerator::getDefault().nextInt(GameConstants::PRIMARY_SKILLS - 1);
|
||||
}
|
||||
|
||||
InfoWindow iw;
|
||||
@ -1749,25 +1749,25 @@ void CGScholar::onHeroVisit( const CGHeroInstance * h ) const
|
||||
cb->removeObject(this);
|
||||
}
|
||||
|
||||
void CGScholar::initObj()
|
||||
void CGScholar::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
if(bonusType == RANDOM)
|
||||
{
|
||||
bonusType = static_cast<EBonusType>(cb->gameState()->getRandomGenerator().nextInt(2));
|
||||
bonusType = static_cast<EBonusType>(rand.nextInt(2));
|
||||
switch(bonusType)
|
||||
{
|
||||
case PRIM_SKILL:
|
||||
bonusID = cb->gameState()->getRandomGenerator().nextInt(GameConstants::PRIMARY_SKILLS -1);
|
||||
bonusID = rand.nextInt(GameConstants::PRIMARY_SKILLS -1);
|
||||
break;
|
||||
case SECONDARY_SKILL:
|
||||
bonusID = cb->gameState()->getRandomGenerator().nextInt(GameConstants::SKILL_QUANTITY -1);
|
||||
bonusID = rand.nextInt(GameConstants::SKILL_QUANTITY -1);
|
||||
break;
|
||||
case SPELL:
|
||||
std::vector<SpellID> possibilities;
|
||||
for (int i = 1; i < 6; ++i)
|
||||
cb->getAllowedSpells (possibilities, i);
|
||||
bonusID = *RandomGeneratorUtil::nextItem(possibilities, cb->gameState()->getRandomGenerator());
|
||||
bonusID = *RandomGeneratorUtil::nextItem(possibilities, rand);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1874,7 +1874,7 @@ void CGMagi::reset()
|
||||
eyelist.clear();
|
||||
}
|
||||
|
||||
void CGMagi::initObj()
|
||||
void CGMagi::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
if (ID == Obj::EYE_OF_MAGI)
|
||||
{
|
||||
@ -1920,12 +1920,12 @@ void CGMagi::onHeroVisit(const CGHeroInstance * h) const
|
||||
}
|
||||
|
||||
}
|
||||
void CGBoat::initObj()
|
||||
void CGBoat::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
hero = nullptr;
|
||||
}
|
||||
|
||||
void CGSirens::initObj()
|
||||
void CGSirens::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
blockVisit = true;
|
||||
}
|
||||
@ -2111,7 +2111,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
|
||||
|
||||
}
|
||||
|
||||
void CGObelisk::initObj()
|
||||
void CGObelisk::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
obeliskCount++;
|
||||
}
|
||||
@ -2172,7 +2172,7 @@ void CGLighthouse::onHeroVisit( const CGHeroInstance * h ) const
|
||||
}
|
||||
}
|
||||
|
||||
void CGLighthouse::initObj()
|
||||
void CGLighthouse::initObj(CRandomGenerator & rand)
|
||||
{
|
||||
if(tempOwner < PlayerColor::PLAYER_LIMIT)
|
||||
{
|
||||
|
@ -59,8 +59,8 @@ public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
std::string getHoverText(const CGHeroInstance * hero) const override;
|
||||
void initObj() override;
|
||||
void newTurn() const override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void newTurn(CRandomGenerator & rand) const override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
@ -105,7 +105,7 @@ public:
|
||||
std::string message;
|
||||
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -125,7 +125,7 @@ public:
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
std::string getHoverText(const CGHeroInstance * hero) const override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CPlayersVisited&>(*this);
|
||||
@ -144,7 +144,7 @@ public:
|
||||
|
||||
CGScholar() : bonusType(EBonusType::RANDOM){};
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & static_cast<CGObjectInstance&>(*this);
|
||||
@ -187,7 +187,7 @@ public:
|
||||
std::string getObjectName() const override;
|
||||
|
||||
void pick( const CGHeroInstance * h ) const;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -206,7 +206,7 @@ public:
|
||||
|
||||
CGResource();
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void battleFinished(const CGHeroInstance *hero, const BattleResult &result) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
@ -227,7 +227,7 @@ class DLL_LINKAGE CGShrine : public CPlayersVisited
|
||||
public:
|
||||
SpellID spell; //id of spell or NONE if random
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
std::string getHoverText(const CGHeroInstance * hero) const override;
|
||||
|
||||
@ -252,8 +252,8 @@ private:
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
|
||||
void flagMine(PlayerColor player) const;
|
||||
void newTurn() const override;
|
||||
void initObj() override;
|
||||
void newTurn(CRandomGenerator & rand) const override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
std::string getObjectName() const override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
@ -329,7 +329,7 @@ class DLL_LINKAGE CGMonolith : public CGTeleport
|
||||
protected:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer, TTeleportExitsList exits) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -341,7 +341,7 @@ public:
|
||||
class DLL_LINKAGE CGSubterraneanGate : public CGMonolith
|
||||
{
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
public:
|
||||
static void postInit();
|
||||
@ -382,7 +382,7 @@ class DLL_LINKAGE CGSirens : public CGObjectInstance
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
std::string getHoverText(const CGHeroInstance * hero) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
@ -407,7 +407,7 @@ public:
|
||||
ui8 direction;
|
||||
const CGHeroInstance *hero; //hero on board
|
||||
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
|
||||
CGBoat()
|
||||
{
|
||||
@ -443,7 +443,7 @@ public:
|
||||
|
||||
static void reset();
|
||||
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -478,7 +478,7 @@ public:
|
||||
static std::map<TeamID, ui8> visited; //map: team_id => how many obelisks has been visited
|
||||
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
static void reset();
|
||||
|
||||
@ -494,7 +494,7 @@ class DLL_LINKAGE CGLighthouse : public CGObjectInstance
|
||||
{
|
||||
public:
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void initObj() override;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
std::string getHoverText(PlayerColor player) const override;
|
||||
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
|
@ -253,6 +253,7 @@ void registerTypesClientPacks1(Serializer &s)
|
||||
s.template registerType<CPackForClient, SetCommanderProperty>();
|
||||
s.template registerType<CPackForClient, ChangeObjectVisitors>();
|
||||
s.template registerType<CPackForClient, ShowWorldViewEx>();
|
||||
s.template registerType<CPackForClient, PrepareHeroLevelUp>();
|
||||
}
|
||||
|
||||
template<typename Serializer>
|
||||
|
@ -449,8 +449,7 @@ void PatchObstacleMechanics::applyBattleEffects(const SpellCastEnvironment * env
|
||||
if(hex.getX() > 0 && hex.getX() < 16 && !(parameters.cb->battleGetStackByPos(hex, false)) && !(parameters.cb->battleGetObstacleOnPos(hex, false)))
|
||||
availableTiles.push_back(hex);
|
||||
}
|
||||
boost::range::random_shuffle(availableTiles);
|
||||
|
||||
RandomGeneratorUtil::randomShuffle(availableTiles, env->getRandomGenerator());
|
||||
const int patchesForSkill[] = {4, 4, 6, 8};
|
||||
const int patchesToPut = std::min<int>(patchesForSkill[parameters.spellLvl], availableTiles.size());
|
||||
|
||||
|
@ -204,7 +204,7 @@ void CGameHandler::levelUpHero(const CGHeroInstance * hero)
|
||||
|
||||
// give primary skill
|
||||
logGlobal->trace("%s got level %d", hero->name, hero->level);
|
||||
auto primarySkill = hero->nextPrimarySkill();
|
||||
auto primarySkill = hero->nextPrimarySkill(getRandomGenerator());
|
||||
|
||||
SetPrimSkill sps;
|
||||
sps.id = hero->id;
|
||||
@ -213,20 +213,24 @@ void CGameHandler::levelUpHero(const CGHeroInstance * hero)
|
||||
sps.val = 1;
|
||||
sendAndApply(&sps);
|
||||
|
||||
PrepareHeroLevelUp pre;
|
||||
pre.hero = hero;
|
||||
sendAndApply(&pre);
|
||||
|
||||
HeroLevelUp hlu;
|
||||
hlu.hero = hero;
|
||||
hlu.primskill = primarySkill;
|
||||
hlu.skills = hero->getLevelUpProposedSecondarySkills();
|
||||
hlu.skills = pre.skills;
|
||||
|
||||
if(hlu.skills.size() == 0)
|
||||
{
|
||||
sendAndApply(&hlu);
|
||||
levelUpHero(hero);
|
||||
}
|
||||
else if(hlu.skills.size() == 1 || hero->tempOwner == PlayerColor::NEUTRAL) //choose skill automatically
|
||||
else if(hlu.skills.size() == 1)
|
||||
{
|
||||
sendAndApply(&hlu);
|
||||
levelUpHero(hero, *RandomGeneratorUtil::nextItem(hlu.skills, hero->skillsInfo.rand));
|
||||
levelUpHero(hero, pre.skills.front());
|
||||
}
|
||||
else if(hlu.skills.size() > 1)
|
||||
{
|
||||
@ -364,7 +368,7 @@ void CGameHandler::levelUpCommander(const CCommanderInstance * c)
|
||||
else if(skillAmount == 1 || hero->tempOwner == PlayerColor::NEUTRAL) //choose skill automatically
|
||||
{
|
||||
sendAndApply(&clu);
|
||||
levelUpCommander(c, *RandomGeneratorUtil::nextItem(clu.skills, gs->getRandomGenerator()));
|
||||
levelUpCommander(c, *RandomGeneratorUtil::nextItem(clu.skills, getRandomGenerator()));
|
||||
}
|
||||
else if(skillAmount > 1) //apply and ask for secondary skill
|
||||
{
|
||||
@ -525,7 +529,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
|
||||
int maxLevel = eagleEyeLevel + 1;
|
||||
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::EAGLE_EYE);
|
||||
for(const CSpell *sp : gs->curB->sides.at(!battleResult.data->winner).usedSpellsHistory)
|
||||
if(sp->level <= maxLevel && !vstd::contains(finishingBattle->winnerHero->spells, sp->id) && gs->getRandomGenerator().nextInt(99) < eagleEyeChance)
|
||||
if(sp->level <= maxLevel && !vstd::contains(finishingBattle->winnerHero->spells, sp->id) && getRandomGenerator().nextInt(99) < eagleEyeChance)
|
||||
cs.spells.insert(sp->id);
|
||||
}
|
||||
}
|
||||
@ -716,7 +720,7 @@ void CGameHandler::battleAfterLevelUp( const BattleResult &result )
|
||||
|
||||
if (necroSlot != SlotID())
|
||||
{
|
||||
finishingBattle->winnerHero->showNecromancyDialog(raisedStack);
|
||||
finishingBattle->winnerHero->showNecromancyDialog(raisedStack, getRandomGenerator());
|
||||
addToSlot(StackLocation(finishingBattle->winnerHero, necroSlot), raisedStack.type, raisedStack.count);
|
||||
}
|
||||
|
||||
@ -789,20 +793,20 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
||||
|
||||
if(!vstd::contains_if(gs->curB->sides, sideHeroBlocksLuck))
|
||||
{
|
||||
if(attackerLuck > 0 && gs->getRandomGenerator().nextInt(23) < attackerLuck)
|
||||
if(attackerLuck > 0 && getRandomGenerator().nextInt(23) < attackerLuck)
|
||||
{
|
||||
bat.flags |= BattleAttack::LUCKY;
|
||||
}
|
||||
if (VLC->modh->settings.data["hardcodedFeatures"]["NEGATIVE_LUCK"].Bool()) // negative luck enabled
|
||||
{
|
||||
if (attackerLuck < 0 && gs->getRandomGenerator().nextInt(23) < abs(attackerLuck))
|
||||
if (attackerLuck < 0 && getRandomGenerator().nextInt(23) < abs(attackerLuck))
|
||||
{
|
||||
bat.flags |= BattleAttack::UNLUCKY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(gs->getRandomGenerator().nextInt(99) < att->valOfBonuses(Bonus::DOUBLE_DAMAGE_CHANCE))
|
||||
if(getRandomGenerator().nextInt(99) < att->valOfBonuses(Bonus::DOUBLE_DAMAGE_CHANCE))
|
||||
{
|
||||
bat.flags |= BattleAttack::DEATH_BLOW;
|
||||
}
|
||||
@ -812,7 +816,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
||||
static const int artilleryLvlToChance[] = {0, 50, 75, 100};
|
||||
const CGHeroInstance * owner = gs->curB->getHero(att->owner);
|
||||
int chance = artilleryLvlToChance[owner->getSecSkillLevel(SecondarySkill::ARTILLERY)];
|
||||
if(chance > gs->getRandomGenerator().nextInt(99))
|
||||
if(chance > getRandomGenerator().nextInt(99))
|
||||
{
|
||||
bat.flags |= BattleAttack::BALLISTA_DOUBLE_DMG;
|
||||
}
|
||||
@ -875,8 +879,8 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons
|
||||
bsa.attackerID = att->ID;
|
||||
bsa.stackAttacked = def->ID;
|
||||
bsa.damageAmount = gs->curB->calculateDmg(att, def, gs->curB->battleGetOwner(att), gs->curB->battleGetOwner(def),
|
||||
bat.shot(), distance, bat.lucky(), bat.unlucky(), bat.deathBlow(), bat.ballistaDoubleDmg(), gs->getRandomGenerator());
|
||||
def->prepareAttacked(bsa, gs->getRandomGenerator()); //calculate casualties
|
||||
bat.shot(), distance, bat.lucky(), bat.unlucky(), bat.deathBlow(), bat.ballistaDoubleDmg(), getRandomGenerator());
|
||||
def->prepareAttacked(bsa, getRandomGenerator()); //calculate casualties
|
||||
|
||||
//life drain handling
|
||||
if (att->hasBonusOfType(Bonus::LIFE_DRAIN) && def->isLiving())
|
||||
@ -913,7 +917,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons
|
||||
bsa2.effect = 11;
|
||||
|
||||
bsa2.damageAmount = (std::min(def->totalHelth(), bsa.damageAmount) * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100; //TODO: scale with attack/defense
|
||||
att->prepareAttacked(bsa2, gameState()->getRandomGenerator());
|
||||
att->prepareAttacked(bsa2, getRandomGenerator());
|
||||
bat.bsa.push_back(bsa2);
|
||||
}
|
||||
}
|
||||
@ -1337,7 +1341,7 @@ void CGameHandler::init(StartInfo *si)
|
||||
logGlobal->info("Gamestate initialized!");
|
||||
|
||||
// reset seed, so that clients can't predict any following random values
|
||||
gs->getRandomGenerator().resetSeed();
|
||||
getRandomGenerator().resetSeed();
|
||||
|
||||
for(auto & elem : gs->players)
|
||||
{
|
||||
@ -1373,10 +1377,10 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
|
||||
return;
|
||||
}
|
||||
|
||||
auto dwelling = *RandomGeneratorUtil::nextItem(dwellings, gs->getRandomGenerator());
|
||||
auto dwelling = *RandomGeneratorUtil::nextItem(dwellings, getRandomGenerator());
|
||||
|
||||
// for multi-creature dwellings like Golem Factory
|
||||
auto creatureId = RandomGeneratorUtil::nextItem(dwelling->creatures, gs->getRandomGenerator())->second[0];
|
||||
auto creatureId = RandomGeneratorUtil::nextItem(dwelling->creatures, getRandomGenerator())->second[0];
|
||||
|
||||
if(clear)
|
||||
{
|
||||
@ -1436,7 +1440,7 @@ void CGameHandler::newTurn()
|
||||
}
|
||||
else
|
||||
{
|
||||
int monthType = gs->getRandomGenerator().nextInt(99);
|
||||
int monthType = getRandomGenerator().nextInt(99);
|
||||
if(newMonth) //new month
|
||||
{
|
||||
if (monthType < 40) //double growth
|
||||
@ -1444,13 +1448,13 @@ void CGameHandler::newTurn()
|
||||
n.specialWeek = NewTurn::DOUBLE_GROWTH;
|
||||
if (VLC->modh->settings.ALL_CREATURES_GET_DOUBLE_MONTHS)
|
||||
{
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(gs->getRandomGenerator()));
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(getRandomGenerator()));
|
||||
n.creatureid = newMonster.second;
|
||||
}
|
||||
else if(VLC->creh->doubledCreatures.size())
|
||||
{
|
||||
const std::vector<CreatureID> doubledCreatures (VLC->creh->doubledCreatures.begin(), VLC->creh->doubledCreatures.end());
|
||||
n.creatureid = *RandomGeneratorUtil::nextItem(doubledCreatures, gs->getRandomGenerator());
|
||||
n.creatureid = *RandomGeneratorUtil::nextItem(doubledCreatures, getRandomGenerator());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1466,7 +1470,7 @@ void CGameHandler::newTurn()
|
||||
if (monthType < 25)
|
||||
{
|
||||
n.specialWeek = NewTurn::BONUS_GROWTH; //+5
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(gs->getRandomGenerator()));
|
||||
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(getRandomGenerator()));
|
||||
//TODO do not pick neutrals
|
||||
n.creatureid = newMonster.second;
|
||||
}
|
||||
@ -1515,10 +1519,10 @@ void CGameHandler::newTurn()
|
||||
for (int j = 0; j < GameConstants::AVAILABLE_HEROES_PER_PLAYER; j++)
|
||||
{
|
||||
//first hero - native if possible, second hero -> any other class
|
||||
if(CGHeroInstance *h = gs->hpool.pickHeroFor(j == 0, elem.first, getNativeTown(elem.first), pool, gs->getRandomGenerator(), banned))
|
||||
if(CGHeroInstance *h = gs->hpool.pickHeroFor(j == 0, elem.first, getNativeTown(elem.first), pool, getRandomGenerator(), banned))
|
||||
{
|
||||
sah.hid[j] = h->subID;
|
||||
h->initArmy(&sah.army[j]);
|
||||
h->initArmy(getRandomGenerator(), &sah.army[j]);
|
||||
banned = h->type->heroClass;
|
||||
}
|
||||
else
|
||||
@ -1647,7 +1651,7 @@ void CGameHandler::newTurn()
|
||||
{
|
||||
SetAvailableArtifacts saa;
|
||||
saa.id = -1;
|
||||
pickAllowedArtsSet(saa.arts);
|
||||
pickAllowedArtsSet(saa.arts, getRandomGenerator());
|
||||
sendAndApply(&saa);
|
||||
}
|
||||
sendAndApply(&n);
|
||||
@ -1691,12 +1695,12 @@ void CGameHandler::newTurn()
|
||||
if (newMonth)
|
||||
{
|
||||
iw.text.addTxt(MetaString::ARRAY_TXT, (130));
|
||||
iw.text.addReplacement(MetaString::ARRAY_TXT, gs->getRandomGenerator().nextInt(32, 41));
|
||||
iw.text.addReplacement(MetaString::ARRAY_TXT, getRandomGenerator().nextInt(32, 41));
|
||||
}
|
||||
else
|
||||
{
|
||||
iw.text.addTxt(MetaString::ARRAY_TXT, (133));
|
||||
iw.text.addReplacement(MetaString::ARRAY_TXT, gs->getRandomGenerator().nextInt(43, 57));
|
||||
iw.text.addReplacement(MetaString::ARRAY_TXT, getRandomGenerator().nextInt(43, 57));
|
||||
}
|
||||
}
|
||||
for (auto & elem : gs->players)
|
||||
@ -1713,7 +1717,7 @@ void CGameHandler::newTurn()
|
||||
for(auto & elem : gs->map->objects)
|
||||
{
|
||||
if(elem)
|
||||
elem->newTurn();
|
||||
elem->newTurn(getRandomGenerator());
|
||||
}
|
||||
|
||||
synchronizeArtifactHandlerLists(); //new day events may have changed them. TODO better of managing that
|
||||
@ -1859,9 +1863,18 @@ void CGameHandler::setupBattle( int3 tile, const CArmedInstance *armies[2], cons
|
||||
{
|
||||
battleResult.set(nullptr);
|
||||
|
||||
const auto t = gs->getTile(tile);
|
||||
ETerrainType terrain = t->terType;
|
||||
if(gs->map->isCoastalTile(tile)) //coastal tile is always ground
|
||||
terrain = ETerrainType::SAND;
|
||||
|
||||
BFieldType terType = gs->battleGetBattlefieldType(tile, getRandomGenerator());
|
||||
if (heroes[0] && heroes[0]->boat && heroes[1] && heroes[1]->boat)
|
||||
terType = BFieldType::SHIP_TO_SHIP;
|
||||
|
||||
//send info about battles
|
||||
BattleStart bs;
|
||||
bs.info = gs->setupBattle(tile, armies, heroes, creatureBank, town);
|
||||
bs.info = BattleInfo::setupBattle(tile, terrain, terType, armies, heroes, creatureBank, town);
|
||||
sendAndApply(&bs);
|
||||
}
|
||||
|
||||
@ -3569,7 +3582,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
|
||||
const CGHeroInstance *newHero = nullptr;
|
||||
if (theOtherHero) //on XXL maps all heroes can be imprisoned :(
|
||||
{
|
||||
newHero = gs->hpool.pickHeroFor(false, player, getNativeTown(player), pool, gs->getRandomGenerator(), theOtherHero->type->heroClass);
|
||||
newHero = gs->hpool.pickHeroFor(false, player, getNativeTown(player), pool, getRandomGenerator(), theOtherHero->type->heroClass);
|
||||
}
|
||||
|
||||
SetAvailableHeroes sah;
|
||||
@ -3978,7 +3991,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
{
|
||||
if(currentHP.at(attackedPart) != EWallState::DESTROYED && // this part can be hit
|
||||
currentHP.at(attackedPart) != EWallState::NONE &&
|
||||
gs->getRandomGenerator().nextInt(99) < getCatapultHitChance(attackedPart, sbi))//hit is successful
|
||||
getRandomGenerator().nextInt(99) < getCatapultHitChance(attackedPart, sbi))//hit is successful
|
||||
{
|
||||
hitSuccessfull = true;
|
||||
}
|
||||
@ -3993,7 +4006,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
}
|
||||
if (allowedTargets.empty())
|
||||
break;
|
||||
attackedPart = *RandomGeneratorUtil::nextItem(allowedTargets, gs->getRandomGenerator());
|
||||
attackedPart = *RandomGeneratorUtil::nextItem(allowedTargets, getRandomGenerator());
|
||||
}
|
||||
}
|
||||
while (!hitSuccessfull);
|
||||
@ -4009,7 +4022,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
|
||||
int dmgChance[] = { sbi.noDmg, sbi.oneDmg, sbi.twoDmg }; //dmgChance[i] - chance for doing i dmg when hit is successful
|
||||
|
||||
int dmgRand = gs->getRandomGenerator().nextInt(99);
|
||||
int dmgRand = getRandomGenerator().nextInt(99);
|
||||
//accumulating dmgChance
|
||||
dmgChance[1] += dmgChance[0];
|
||||
dmgChance[2] += dmgChance[1];
|
||||
@ -4164,8 +4177,8 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
|
||||
const Bonus * spellcaster = stack->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPELLCASTER, spellID));
|
||||
|
||||
//TODO special bonus for genies ability
|
||||
if(randSpellcaster && battleGetRandomStackSpell(stack, CBattleInfoCallback::RANDOM_AIMED) < 0)
|
||||
spellID = battleGetRandomStackSpell(stack, CBattleInfoCallback::RANDOM_GENIE);
|
||||
if(randSpellcaster && battleGetRandomStackSpell(getRandomGenerator(), stack, CBattleInfoCallback::RANDOM_AIMED) < 0)
|
||||
spellID = battleGetRandomStackSpell(getRandomGenerator(), stack, CBattleInfoCallback::RANDOM_GENIE);
|
||||
|
||||
if(spellID < 0)
|
||||
complain("That stack can't cast spells!");
|
||||
@ -4507,7 +4520,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
|
||||
}
|
||||
if (fearsomeCreature)
|
||||
{
|
||||
if (gs->getRandomGenerator().nextInt(99) < 10) //fixed 10%
|
||||
if (getRandomGenerator().nextInt(99) < 10) //fixed 10%
|
||||
{
|
||||
bte.effect = Bonus::FEAR;
|
||||
sendAndApply(&bte);
|
||||
@ -4521,7 +4534,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
|
||||
bool cast = false;
|
||||
while (!bl.empty() && !cast)
|
||||
{
|
||||
auto bonus = *RandomGeneratorUtil::nextItem(bl, gs->getRandomGenerator());
|
||||
auto bonus = *RandomGeneratorUtil::nextItem(bl, getRandomGenerator());
|
||||
auto spellID = SpellID(bonus->subtype);
|
||||
const CSpell * spell = SpellID(spellID).toSpell();
|
||||
bl.remove_if([&bonus](Bonus * b){return b==bonus;});
|
||||
@ -4635,7 +4648,7 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, c
|
||||
bsa.damageAmount = damage;
|
||||
bsa.stackAttacked = curStack->ID;
|
||||
bsa.attackerID = -1;
|
||||
curStack->prepareAttacked(bsa, gameState()->getRandomGenerator());
|
||||
curStack->prepareAttacked(bsa, getRandomGenerator());
|
||||
|
||||
StacksInjured si;
|
||||
si.stacks.push_back(bsa);
|
||||
@ -5232,7 +5245,7 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
|
||||
continue;
|
||||
|
||||
//check if spell should be cast (probability handling)
|
||||
if(gs->getRandomGenerator().nextInt(99) >= chance)
|
||||
if(getRandomGenerator().nextInt(99) >= chance)
|
||||
continue;
|
||||
|
||||
//casting
|
||||
@ -5314,7 +5327,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
|
||||
TBonusListPtr acidBreath = attacker->getBonuses(Selector::type(Bonus::ACID_BREATH));
|
||||
for(const Bonus *b : *acidBreath)
|
||||
{
|
||||
if (b->additionalInfo > gs->getRandomGenerator().nextInt(99))
|
||||
if (b->additionalInfo > getRandomGenerator().nextInt(99))
|
||||
acidDamage += b->val;
|
||||
}
|
||||
if (acidDamage)
|
||||
@ -5625,7 +5638,7 @@ void CGameHandler::runBattle()
|
||||
|| NBonus::hasOfType(gs->curB->battleGetFightingHero(1), Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses)
|
||||
)
|
||||
{
|
||||
if(gs->getRandomGenerator().nextInt(23) < -2 * nextStackMorale)
|
||||
if(getRandomGenerator().nextInt(23) < -2 * nextStackMorale)
|
||||
{
|
||||
//unit loses its turn - empty freeze action
|
||||
BattleAction ba;
|
||||
@ -5697,7 +5710,7 @@ void CGameHandler::runBattle()
|
||||
{
|
||||
BattleAction attack;
|
||||
attack.destinationTile = *RandomGeneratorUtil::nextItem(attackableBattleHexes,
|
||||
gs->getRandomGenerator());
|
||||
getRandomGenerator());
|
||||
attack.actionType = Battle::CATAPULT;
|
||||
attack.additionalInfo = 0;
|
||||
attack.side = !next->attackerOwned;
|
||||
@ -5723,7 +5736,7 @@ void CGameHandler::runBattle()
|
||||
|
||||
if(!curOwner || curOwner->getSecSkillLevel(SecondarySkill::FIRST_AID) == 0) //no hero or hero has no first aid
|
||||
{
|
||||
range::random_shuffle(possibleStacks);
|
||||
RandomGeneratorUtil::randomShuffle(possibleStacks, getRandomGenerator());
|
||||
const CStack * toBeHealed = possibleStacks.front();
|
||||
|
||||
BattleAction heal;
|
||||
@ -5802,7 +5815,7 @@ void CGameHandler::runBattle()
|
||||
|| NBonus::hasOfType(gs->curB->battleGetFightingHero(1), Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses
|
||||
)
|
||||
{
|
||||
if(gs->getRandomGenerator().nextInt(23) < nextStackMorale) //this stack hasn't got morale this turn
|
||||
if(getRandomGenerator().nextInt(23) < nextStackMorale) //this stack hasn't got morale this turn
|
||||
|
||||
{
|
||||
BattleTriggerEffect bte;
|
||||
@ -5926,7 +5939,8 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID)
|
||||
std::vector<int3> tiles;
|
||||
getFreeTiles(tiles);
|
||||
ui32 amount = tiles.size() / 200; //Chance is 0.5% for each tile
|
||||
std::random_shuffle(tiles.begin(), tiles.end());
|
||||
|
||||
RandomGeneratorUtil::randomShuffle(tiles, getRandomGenerator());
|
||||
logGlobal->trace("Spawning wandering monsters. Found %d free tiles. Creature type: %d", tiles.size(), creatureID.num);
|
||||
const CCreature *cre = VLC->creh->creatures.at(creatureID);
|
||||
for (int i = 0; i < amount; ++i)
|
||||
@ -6230,6 +6244,11 @@ CGameHandler::FinishingBattleHelper::FinishingBattleHelper()
|
||||
winnerHero = loserHero = nullptr;
|
||||
}
|
||||
|
||||
CRandomGenerator & CGameHandler::getRandomGenerator()
|
||||
{
|
||||
return CRandomGenerator::getDefault();
|
||||
}
|
||||
|
||||
///ServerSpellCastEnvironment
|
||||
ServerSpellCastEnvironment::ServerSpellCastEnvironment(CGameHandler * gh): gh(gh)
|
||||
{
|
||||
@ -6243,7 +6262,7 @@ void ServerSpellCastEnvironment::sendAndApply(CPackForClient * info) const
|
||||
|
||||
CRandomGenerator & ServerSpellCastEnvironment::getRandomGenerator() const
|
||||
{
|
||||
return gh->gameState()->getRandomGenerator();
|
||||
return gh->getRandomGenerator();
|
||||
}
|
||||
|
||||
void ServerSpellCastEnvironment::complain(const std::string& problem) const
|
||||
|
@ -247,6 +247,10 @@ public:
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & QID & states & finishingBattle;
|
||||
if(version >= 761)
|
||||
{
|
||||
h & getRandomGenerator();
|
||||
}
|
||||
}
|
||||
|
||||
void sendMessageToAll(const std::string &message);
|
||||
@ -290,6 +294,8 @@ public:
|
||||
void spawnWanderingMonsters(CreatureID creatureID);
|
||||
friend class CVCMIServer;
|
||||
|
||||
CRandomGenerator & getRandomGenerator();
|
||||
|
||||
private:
|
||||
ServerSpellCastEnvironment * spellEnv;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user