diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index 7c3b7113f..636d48a4c 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -119,14 +119,14 @@ void CPrivilagedInfoCallback::getAllTiles (std::unordered_set & } } -void CPrivilagedInfoCallback::pickAllowedArtsSet(std::vector &out) +void CPrivilagedInfoCallback::pickAllowedArtsSet(std::vector &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 &out, ui16 level) @@ -249,6 +249,11 @@ const CGCreature * IGameCallback::putNewMonster(CreatureID creID, int count, int return dynamic_cast(m); } +CRandomGenerator & IGameCallback::getRandomGenerator() +{ + return rand; +} + bool IGameCallback::isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) { //only server knows diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index 43c24d05c..4c4fb152a 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -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 &tiles) const; //used for random spawns void getTilesInRange(std::unordered_set &tiles, int3 pos, int radious, boost::optional player = boost::optional(), int mode = 0, bool patrolDistance = false) const; //mode 1 - only unrevealed tiles; mode 0 - all, mode -1 - only unrevealed void getAllTiles (std::unordered_set &tiles, boost::optional player = boost::optional(), 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 &out); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant + void pickAllowedArtsSet(std::vector &out, CRandomGenerator & rand); //gives 3 treasures, 3 minors, 1 major -> used by Black Market and Artifact Merchant void getAllowedSpells(std::vector &out, ui16 level); template @@ -123,6 +124,8 @@ public: //get info virtual bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero); + CRandomGenerator rand; + CRandomGenerator & getRandomGenerator(); friend struct CPack; friend struct CPackForClient; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index e66a62677..9a509eea7 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -332,7 +332,7 @@ void CGHeroInstance::initArmy(IArmyDescriptor *dst /*= nullptr*/) dst = this; int howManyStacks = 0; //how many stacks will hero receives <1 - 3> - int pom = cb->gameState()->getRandomGenerator().nextInt(99); + int pom = cb->getRandomGenerator().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 = cb->getRandomGenerator().nextInt(stack.minAmount, stack.maxAmount); if(stack.creature >= CreatureID::CATAPULT && stack.creature <= CreatureID::ARROW_TOWERS) //war machine @@ -1059,7 +1059,7 @@ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &b void CGHeroInstance::showNecromancyDialog(const CStackBasicDescriptor &raisedStack) const { InfoWindow iw; - iw.soundID = soundBase::pickup01 + cb->gameState()->getRandomGenerator().nextInt(6); + iw.soundID = soundBase::pickup01 + cb->getRandomGenerator().nextInt(6); iw.player = tempOwner; iw.components.push_back(Component(raisedStack)); diff --git a/lib/mapObjects/CGMarket.cpp b/lib/mapObjects/CGMarket.cpp index fbbf35c46..d76c0dddb 100644 --- a/lib/mapObjects/CGMarket.cpp +++ b/lib/mapObjects/CGMarket.cpp @@ -289,7 +289,7 @@ void CGBlackMarket::newTurn() const SetAvailableArtifacts saa; saa.id = id.getNum(); - cb->pickAllowedArtsSet(saa.arts); + cb->pickAllowedArtsSet(saa.arts, cb->getRandomGenerator()); cb->sendAndApply(&saa); } diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index f15707f65..ab8bc58cb 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -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(cb->getRandomGenerator())); } bool change = false; @@ -641,7 +641,7 @@ void CGTownInstance::newTurn() const { if (cb->getDate(Date::DAY_OF_WEEK) == 1) //reset on new week { - auto & rand = cb->gameState()->getRandomGenerator(); + auto & rand = cb->getRandomGenerator(); //give resources for Rampart, Mystic Pond if (hasBuilt(BuildingID::MYSTIC_POND, ETownType::RAMPART) diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp index 1c8163f4b..6d096c329 100644 --- a/lib/mapObjects/CRewardableObject.cpp +++ b/lib/mapObjects/CRewardableObject.cpp @@ -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[cb->getRandomGenerator().nextInt(rewards.size()-1)]); break; } return; diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index fd63509d0..8176418c6 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -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, cb->getRandomGenerator()); cb->changeStackType(StackLocation(this, slotID), VLC->creh->creatures[*it]); } } @@ -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, cb->getRandomGenerator()); return ObjectInstanceID(); } @@ -1283,7 +1283,7 @@ void CGWhirlpool::teleportDialogAnswered(const CGHeroInstance *hero, ui32 answer { auto obj = cb->getObj(getRandomExit(hero)); std::set tiles = obj->getBlockedPos(); - dPos = CGHeroInstance::convertPosition(*RandomGeneratorUtil::nextItem(tiles, cb->gameState()->getRandomGenerator()), true); + dPos = CGHeroInstance::convertPosition(*RandomGeneratorUtil::nextItem(tiles, cb->getRandomGenerator()), true); } cb->moveHero(hero->id, dPos, true); @@ -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 = cb->getRandomGenerator().nextInt(GameConstants::PRIMARY_SKILLS - 1); } InfoWindow iw; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index ac23ccba6..3cdda92a5 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -364,7 +364,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 +525,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); } } @@ -789,20 +789,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 +812,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 +875,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 +913,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 +1337,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 +1373,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 +1436,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 +1444,13 @@ void CGameHandler::newTurn() n.specialWeek = NewTurn::DOUBLE_GROWTH; if (VLC->modh->settings.ALL_CREATURES_GET_DOUBLE_MONTHS) { - std::pair newMonster(54, VLC->creh->pickRandomMonster(gs->getRandomGenerator())); + std::pair newMonster(54, VLC->creh->pickRandomMonster(getRandomGenerator())); n.creatureid = newMonster.second; } else if(VLC->creh->doubledCreatures.size()) { const std::vector 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 +1466,7 @@ void CGameHandler::newTurn() if (monthType < 25) { n.specialWeek = NewTurn::BONUS_GROWTH; //+5 - std::pair newMonster(54, VLC->creh->pickRandomMonster(gs->getRandomGenerator())); + std::pair newMonster(54, VLC->creh->pickRandomMonster(getRandomGenerator())); //TODO do not pick neutrals n.creatureid = newMonster.second; } @@ -1515,7 +1515,7 @@ 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]); @@ -1647,7 +1647,7 @@ void CGameHandler::newTurn() { SetAvailableArtifacts saa; saa.id = -1; - pickAllowedArtsSet(saa.arts); + pickAllowedArtsSet(saa.arts, getRandomGenerator()); sendAndApply(&saa); } sendAndApply(&n); @@ -1691,12 +1691,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) @@ -3569,7 +3569,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 +3978,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 +3993,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 +4009,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]; @@ -4507,7 +4507,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 +4521,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;}); @@ -4636,7 +4636,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); @@ -5233,7 +5233,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 @@ -5317,7 +5317,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) @@ -5629,7 +5629,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; @@ -5701,7 +5701,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; @@ -5806,7 +5806,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; @@ -6247,7 +6247,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 diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 3681eb067..eaceff895 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -247,6 +247,10 @@ public: template void serialize(Handler &h, const int version) { h & QID & states & finishingBattle; + if(version >= 760) + { + h & rand; + } } void sendMessageToAll(const std::string &message);