mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
Refactoring: only use RNGs explicitly to avoid bug prone code in future
Now server-side code should always use CRandomGenerator::getDefault which is serialized in GH. CGameState::getRandomGenerator should be only used from GS code and CPackForClient-based applyGs.
This commit is contained in:
parent
70abae9b51
commit
c8faca8f39
@ -653,7 +653,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;
|
||||
|
||||
@ -737,7 +737,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
|
||||
|
||||
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?
|
||||
}
|
||||
else
|
||||
@ -2101,7 +2101,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;
|
||||
@ -2264,7 +2264,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;
|
||||
@ -2276,7 +2276,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();
|
||||
}
|
||||
@ -2425,7 +2425,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
|
||||
|
@ -113,11 +113,6 @@ void CCallbackBase::setBattle(const BattleInfo *B)
|
||||
battle = B;
|
||||
}
|
||||
|
||||
CRandomGenerator & CCallbackBase::getRandomGenerator() const
|
||||
{
|
||||
return rand;
|
||||
}
|
||||
|
||||
boost::optional<PlayerColor> CCallbackBase::getPlayerID() const
|
||||
{
|
||||
return player;
|
||||
@ -526,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 <<")";
|
||||
@ -1081,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));
|
||||
|
||||
@ -1111,7 +1106,7 @@ std::pair<ui32, ui32> CBattleInfoCallback::battleEstimateDamage(const BattleAtta
|
||||
{
|
||||
BattleStackAttacked bsa;
|
||||
bsa.damageAmount = ret.*pairElems[i];
|
||||
bai.defender->prepareAttacked(bsa, getRandomGenerator(), bai.defenderCount);
|
||||
bai.defender->prepareAttacked(bsa, rand, bai.defenderCount);
|
||||
|
||||
auto retaliationAttack = bai.reverse();
|
||||
retaliationAttack.attackerCount = bsa.newAmount;
|
||||
@ -1928,7 +1923,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.
|
||||
@ -2050,7 +2045,7 @@ SpellID CBattleInfoCallback::getRandomBeneficialSpell(const CStack * subject) co
|
||||
|
||||
if(!beneficialSpells.empty())
|
||||
{
|
||||
return *RandomGeneratorUtil::nextItem(beneficialSpells, getRandomGenerator());
|
||||
return *RandomGeneratorUtil::nextItem(beneficialSpells, rand);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2058,7 +2053,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);
|
||||
|
||||
@ -2070,7 +2065,7 @@ SpellID CBattleInfoCallback::getRandomCastedSpell(const CStack * caster) const
|
||||
{
|
||||
totalWeight += std::max(b->additionalInfo, 1); //minimal chance to cast is 1
|
||||
}
|
||||
int randomPos = getRandomGenerator().nextInt(totalWeight - 1);
|
||||
int randomPos = rand.nextInt(totalWeight - 1);
|
||||
for(Bonus * b : *bl)
|
||||
{
|
||||
randomPos -= std::max(b->additionalInfo, 1);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
#include "BattleHex.h"
|
||||
#include "CRandomGenerator.h"
|
||||
|
||||
/*
|
||||
* CBattleCallback.h, part of VCMI engine
|
||||
@ -23,6 +22,7 @@ struct CObstacleInstance;
|
||||
class IBonusBearer;
|
||||
struct InfoAboutHero;
|
||||
class CArmedInstance;
|
||||
class CRandomGenerator;
|
||||
|
||||
namespace boost
|
||||
{class shared_mutex;}
|
||||
@ -49,7 +49,6 @@ class DLL_LINKAGE CCallbackBase
|
||||
|
||||
protected:
|
||||
CGameState *gs;
|
||||
mutable CRandomGenerator rand;
|
||||
boost::optional<PlayerColor> player; // not set gives access to all information, otherwise callback provides only information "visible" for player
|
||||
|
||||
CCallbackBase(CGameState *GS, boost::optional<PlayerColor> Player)
|
||||
@ -65,7 +64,6 @@ protected:
|
||||
public:
|
||||
boost::shared_mutex &getGsMutex(); //just return a reference to mutex, does not lock nor anything
|
||||
boost::optional<PlayerColor> getPlayerID() const;
|
||||
CRandomGenerator & getRandomGenerator() const;
|
||||
|
||||
friend class CBattleInfoEssentials;
|
||||
};
|
||||
@ -269,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
|
||||
@ -289,9 +287,9 @@ public:
|
||||
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
|
||||
std::vector<BattleHex> battleGetPossibleTargets(PlayerColor player, const CSpell *spell) const;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -912,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
|
||||
{
|
||||
@ -1239,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;
|
||||
@ -1255,7 +1255,7 @@ void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroRepl
|
||||
//trimming experience
|
||||
for(CGHeroInstance * cgh : crossoverHeroes)
|
||||
{
|
||||
cgh->initExp();
|
||||
cgh->initExp(getRandomGenerator());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1462,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;
|
||||
}
|
||||
@ -1478,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);
|
||||
@ -1489,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;
|
||||
@ -1846,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)
|
||||
@ -1906,7 +1906,7 @@ void CGameState::initVisitingAndGarrisonedHeroes()
|
||||
}
|
||||
}
|
||||
|
||||
BFieldType CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & r)
|
||||
BFieldType CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & rand)
|
||||
{
|
||||
if(tile==int3() && curB)
|
||||
tile = curB->tile;
|
||||
@ -1955,13 +1955,13 @@ BFieldType CGameState::battleGetBattlefieldType(int3 tile, CRandomGenerator & r)
|
||||
switch(t.terType)
|
||||
{
|
||||
case ETerrainType::DIRT:
|
||||
return BFieldType(r.nextInt(3, 5));
|
||||
return BFieldType(rand.nextInt(3, 5));
|
||||
case ETerrainType::SAND:
|
||||
return BFieldType::SAND_MESAS; //TODO: coast support
|
||||
case ETerrainType::GRASS:
|
||||
return BFieldType(r.nextInt(6, 7));
|
||||
return BFieldType(rand.nextInt(6, 7));
|
||||
case ETerrainType::SNOW:
|
||||
return BFieldType(r.nextInt(10, 11));
|
||||
return BFieldType(rand.nextInt(10, 11));
|
||||
case ETerrainType::SWAMP:
|
||||
return BFieldType::SWAMP_TREES;
|
||||
case ETerrainType::ROUGH:
|
||||
@ -3250,7 +3250,6 @@ TeamState::TeamState(TeamState && other):
|
||||
std::swap(fogOfWarMap, other.fogOfWarMap);
|
||||
}
|
||||
|
||||
|
||||
CRandomGenerator & CGameState::getRandomGenerator()
|
||||
{
|
||||
//if(scenarioOps && scenarioOps->seedPostInit)
|
||||
|
@ -218,7 +218,7 @@ public:
|
||||
void giveHeroArtifact(CGHeroInstance *h, ArtifactID aid);
|
||||
|
||||
void apply(CPack *pack);
|
||||
BFieldType battleGetBattlefieldType(int3 tile, CRandomGenerator & r);
|
||||
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
|
||||
@ -243,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)
|
||||
@ -291,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();
|
||||
|
@ -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();
|
||||
|
@ -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(cb->gameState()->getRandomGenerator());
|
||||
initArmy(rand);
|
||||
}
|
||||
assert(validTypes());
|
||||
|
||||
if(exp == 0xffffffff)
|
||||
{
|
||||
initExp();
|
||||
initExp(rand);
|
||||
}
|
||||
else
|
||||
{
|
||||
levelUpAutomatically();
|
||||
levelUpAutomatically(rand);
|
||||
}
|
||||
|
||||
if (VLC->modh->modules.COMMANDERS && !commander)
|
||||
@ -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();
|
||||
|
||||
@ -1056,10 +1056,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->getRandomGenerator().nextInt(6);
|
||||
iw.soundID = soundBase::pickup01 + rand.nextInt(6);
|
||||
iw.player = tempOwner;
|
||||
iw.components.push_back(Component(raisedStack));
|
||||
|
||||
@ -1162,9 +1162,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
|
||||
@ -1356,7 +1356,7 @@ PrimarySkill::PrimarySkill CGHeroInstance::nextPrimarySkill(CRandomGenerator & r
|
||||
return static_cast<PrimarySkill::PrimarySkill>(primarySkill);
|
||||
}
|
||||
|
||||
boost::optional<SecondarySkill> CGHeroInstance::nextSecondarySkill() const
|
||||
boost::optional<SecondarySkill> CGHeroInstance::nextSecondarySkill(CRandomGenerator & rand) const
|
||||
{
|
||||
assert(gainsLevel());
|
||||
|
||||
@ -1373,7 +1373,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
|
||||
@ -1452,16 +1451,16 @@ void CGHeroInstance::levelUp(std::vector<SecondarySkill> skills)
|
||||
Updatespecialty();
|
||||
}
|
||||
|
||||
void CGHeroInstance::levelUpAutomatically()
|
||||
void CGHeroInstance::levelUpAutomatically(CRandomGenerator & rand)
|
||||
{
|
||||
while(gainsLevel())
|
||||
{
|
||||
const auto primarySkill = nextPrimarySkill(cb->gameState()->getRandomGenerator());
|
||||
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);
|
||||
|
@ -166,7 +166,7 @@ public:
|
||||
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,19 +192,19 @@ 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 initExp(CRandomGenerator & rand);
|
||||
void initArmy(CRandomGenerator & rand, IArmyDescriptor *dst = nullptr);
|
||||
//void giveArtifact (ui32 aid);
|
||||
void pushPrimSkill(PrimarySkill::PrimarySkill which, int val);
|
||||
@ -248,7 +248,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:
|
||||
@ -256,7 +256,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->getRandomGenerator());
|
||||
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->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->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->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->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->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->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->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)
|
||||
|
@ -720,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);
|
||||
}
|
||||
|
||||
@ -1717,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
|
||||
@ -4177,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!");
|
||||
@ -6247,6 +6247,11 @@ CGameHandler::FinishingBattleHelper::FinishingBattleHelper()
|
||||
winnerHero = loserHero = nullptr;
|
||||
}
|
||||
|
||||
CRandomGenerator & CGameHandler::getRandomGenerator()
|
||||
{
|
||||
return CRandomGenerator::getDefault();
|
||||
}
|
||||
|
||||
///ServerSpellCastEnvironment
|
||||
ServerSpellCastEnvironment::ServerSpellCastEnvironment(CGameHandler * gh): gh(gh)
|
||||
{
|
||||
|
@ -249,7 +249,7 @@ public:
|
||||
h & QID & states & finishingBattle;
|
||||
if(version >= 761)
|
||||
{
|
||||
h & rand;
|
||||
h & getRandomGenerator();
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,6 +294,8 @@ public:
|
||||
void spawnWanderingMonsters(CreatureID creatureID);
|
||||
friend class CVCMIServer;
|
||||
|
||||
CRandomGenerator & getRandomGenerator();
|
||||
|
||||
private:
|
||||
ServerSpellCastEnvironment * spellEnv;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user