1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

Merge remote-tracking branch 'remotes/origin/develop' into SpellsRefactoring8

# Conflicts:
#	client/battle/CBattleInterface.cpp
#	lib/spells/BattleSpellMechanics.cpp
This commit is contained in:
AlexVinS
2016-09-12 10:13:40 +03:00
34 changed files with 366 additions and 311 deletions

View File

@ -204,7 +204,7 @@ void CGameHandler::levelUpHero(const CGHeroInstance * hero)
// give primary skill
logGlobal->trace("%s got level %d", hero->name, hero->level);
auto primarySkill = hero->nextPrimarySkill();
auto primarySkill = hero->nextPrimarySkill(getRandomGenerator());
SetPrimSkill sps;
sps.id = hero->id;
@ -213,20 +213,24 @@ void CGameHandler::levelUpHero(const CGHeroInstance * hero)
sps.val = 1;
sendAndApply(&sps);
PrepareHeroLevelUp pre;
pre.hero = hero;
sendAndApply(&pre);
HeroLevelUp hlu;
hlu.hero = hero;
hlu.primskill = primarySkill;
hlu.skills = hero->getLevelUpProposedSecondarySkills();
hlu.skills = pre.skills;
if(hlu.skills.size() == 0)
{
sendAndApply(&hlu);
levelUpHero(hero);
}
else if(hlu.skills.size() == 1 || hero->tempOwner == PlayerColor::NEUTRAL) //choose skill automatically
else if(hlu.skills.size() == 1)
{
sendAndApply(&hlu);
levelUpHero(hero, *RandomGeneratorUtil::nextItem(hlu.skills, hero->skillsInfo.rand));
levelUpHero(hero, pre.skills.front());
}
else if(hlu.skills.size() > 1)
{
@ -364,7 +368,7 @@ void CGameHandler::levelUpCommander(const CCommanderInstance * c)
else if(skillAmount == 1 || hero->tempOwner == PlayerColor::NEUTRAL) //choose skill automatically
{
sendAndApply(&clu);
levelUpCommander(c, *RandomGeneratorUtil::nextItem(clu.skills, gs->getRandomGenerator()));
levelUpCommander(c, *RandomGeneratorUtil::nextItem(clu.skills, getRandomGenerator()));
}
else if(skillAmount > 1) //apply and ask for secondary skill
{
@ -525,7 +529,7 @@ void CGameHandler::endBattle(int3 tile, const CGHeroInstance *hero1, const CGHer
int maxLevel = eagleEyeLevel + 1;
double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::EAGLE_EYE);
for(const CSpell *sp : gs->curB->sides.at(!battleResult.data->winner).usedSpellsHistory)
if(sp->level <= maxLevel && !vstd::contains(finishingBattle->winnerHero->spells, sp->id) && gs->getRandomGenerator().nextInt(99) < eagleEyeChance)
if(sp->level <= maxLevel && !vstd::contains(finishingBattle->winnerHero->spells, sp->id) && getRandomGenerator().nextInt(99) < eagleEyeChance)
cs.spells.insert(sp->id);
}
}
@ -716,7 +720,7 @@ void CGameHandler::battleAfterLevelUp( const BattleResult &result )
if (necroSlot != SlotID())
{
finishingBattle->winnerHero->showNecromancyDialog(raisedStack);
finishingBattle->winnerHero->showNecromancyDialog(raisedStack, getRandomGenerator());
addToSlot(StackLocation(finishingBattle->winnerHero, necroSlot), raisedStack.type, raisedStack.count);
}
@ -789,20 +793,20 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
if(!vstd::contains_if(gs->curB->sides, sideHeroBlocksLuck))
{
if(attackerLuck > 0 && gs->getRandomGenerator().nextInt(23) < attackerLuck)
if(attackerLuck > 0 && getRandomGenerator().nextInt(23) < attackerLuck)
{
bat.flags |= BattleAttack::LUCKY;
}
if (VLC->modh->settings.data["hardcodedFeatures"]["NEGATIVE_LUCK"].Bool()) // negative luck enabled
{
if (attackerLuck < 0 && gs->getRandomGenerator().nextInt(23) < abs(attackerLuck))
if (attackerLuck < 0 && getRandomGenerator().nextInt(23) < abs(attackerLuck))
{
bat.flags |= BattleAttack::UNLUCKY;
}
}
}
if(gs->getRandomGenerator().nextInt(99) < att->valOfBonuses(Bonus::DOUBLE_DAMAGE_CHANCE))
if(getRandomGenerator().nextInt(99) < att->valOfBonuses(Bonus::DOUBLE_DAMAGE_CHANCE))
{
bat.flags |= BattleAttack::DEATH_BLOW;
}
@ -812,7 +816,7 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
static const int artilleryLvlToChance[] = {0, 50, 75, 100};
const CGHeroInstance * owner = gs->curB->getHero(att->owner);
int chance = artilleryLvlToChance[owner->getSecSkillLevel(SecondarySkill::ARTILLERY)];
if(chance > gs->getRandomGenerator().nextInt(99))
if(chance > getRandomGenerator().nextInt(99))
{
bat.flags |= BattleAttack::BALLISTA_DOUBLE_DMG;
}
@ -875,8 +879,8 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons
bsa.attackerID = att->ID;
bsa.stackAttacked = def->ID;
bsa.damageAmount = gs->curB->calculateDmg(att, def, gs->curB->battleGetOwner(att), gs->curB->battleGetOwner(def),
bat.shot(), distance, bat.lucky(), bat.unlucky(), bat.deathBlow(), bat.ballistaDoubleDmg(), gs->getRandomGenerator());
def->prepareAttacked(bsa, gs->getRandomGenerator()); //calculate casualties
bat.shot(), distance, bat.lucky(), bat.unlucky(), bat.deathBlow(), bat.ballistaDoubleDmg(), getRandomGenerator());
def->prepareAttacked(bsa, getRandomGenerator()); //calculate casualties
//life drain handling
if (att->hasBonusOfType(Bonus::LIFE_DRAIN) && def->isLiving())
@ -913,7 +917,7 @@ void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, cons
bsa2.effect = 11;
bsa2.damageAmount = (std::min(def->totalHelth(), bsa.damageAmount) * def->valOfBonuses(Bonus::FIRE_SHIELD)) / 100; //TODO: scale with attack/defense
att->prepareAttacked(bsa2, gameState()->getRandomGenerator());
att->prepareAttacked(bsa2, getRandomGenerator());
bat.bsa.push_back(bsa2);
}
}
@ -1337,7 +1341,7 @@ void CGameHandler::init(StartInfo *si)
logGlobal->info("Gamestate initialized!");
// reset seed, so that clients can't predict any following random values
gs->getRandomGenerator().resetSeed();
getRandomGenerator().resetSeed();
for(auto & elem : gs->players)
{
@ -1373,10 +1377,10 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
return;
}
auto dwelling = *RandomGeneratorUtil::nextItem(dwellings, gs->getRandomGenerator());
auto dwelling = *RandomGeneratorUtil::nextItem(dwellings, getRandomGenerator());
// for multi-creature dwellings like Golem Factory
auto creatureId = RandomGeneratorUtil::nextItem(dwelling->creatures, gs->getRandomGenerator())->second[0];
auto creatureId = RandomGeneratorUtil::nextItem(dwelling->creatures, getRandomGenerator())->second[0];
if(clear)
{
@ -1436,7 +1440,7 @@ void CGameHandler::newTurn()
}
else
{
int monthType = gs->getRandomGenerator().nextInt(99);
int monthType = getRandomGenerator().nextInt(99);
if(newMonth) //new month
{
if (monthType < 40) //double growth
@ -1444,13 +1448,13 @@ void CGameHandler::newTurn()
n.specialWeek = NewTurn::DOUBLE_GROWTH;
if (VLC->modh->settings.ALL_CREATURES_GET_DOUBLE_MONTHS)
{
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(gs->getRandomGenerator()));
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(getRandomGenerator()));
n.creatureid = newMonster.second;
}
else if(VLC->creh->doubledCreatures.size())
{
const std::vector<CreatureID> doubledCreatures (VLC->creh->doubledCreatures.begin(), VLC->creh->doubledCreatures.end());
n.creatureid = *RandomGeneratorUtil::nextItem(doubledCreatures, gs->getRandomGenerator());
n.creatureid = *RandomGeneratorUtil::nextItem(doubledCreatures, getRandomGenerator());
}
else
{
@ -1466,7 +1470,7 @@ void CGameHandler::newTurn()
if (monthType < 25)
{
n.specialWeek = NewTurn::BONUS_GROWTH; //+5
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(gs->getRandomGenerator()));
std::pair<int, CreatureID> newMonster(54, VLC->creh->pickRandomMonster(getRandomGenerator()));
//TODO do not pick neutrals
n.creatureid = newMonster.second;
}
@ -1515,10 +1519,10 @@ void CGameHandler::newTurn()
for (int j = 0; j < GameConstants::AVAILABLE_HEROES_PER_PLAYER; j++)
{
//first hero - native if possible, second hero -> any other class
if(CGHeroInstance *h = gs->hpool.pickHeroFor(j == 0, elem.first, getNativeTown(elem.first), pool, gs->getRandomGenerator(), banned))
if(CGHeroInstance *h = gs->hpool.pickHeroFor(j == 0, elem.first, getNativeTown(elem.first), pool, getRandomGenerator(), banned))
{
sah.hid[j] = h->subID;
h->initArmy(&sah.army[j]);
h->initArmy(getRandomGenerator(), &sah.army[j]);
banned = h->type->heroClass;
}
else
@ -1647,7 +1651,7 @@ void CGameHandler::newTurn()
{
SetAvailableArtifacts saa;
saa.id = -1;
pickAllowedArtsSet(saa.arts);
pickAllowedArtsSet(saa.arts, getRandomGenerator());
sendAndApply(&saa);
}
sendAndApply(&n);
@ -1691,12 +1695,12 @@ void CGameHandler::newTurn()
if (newMonth)
{
iw.text.addTxt(MetaString::ARRAY_TXT, (130));
iw.text.addReplacement(MetaString::ARRAY_TXT, gs->getRandomGenerator().nextInt(32, 41));
iw.text.addReplacement(MetaString::ARRAY_TXT, getRandomGenerator().nextInt(32, 41));
}
else
{
iw.text.addTxt(MetaString::ARRAY_TXT, (133));
iw.text.addReplacement(MetaString::ARRAY_TXT, gs->getRandomGenerator().nextInt(43, 57));
iw.text.addReplacement(MetaString::ARRAY_TXT, getRandomGenerator().nextInt(43, 57));
}
}
for (auto & elem : gs->players)
@ -1713,7 +1717,7 @@ void CGameHandler::newTurn()
for(auto & elem : gs->map->objects)
{
if(elem)
elem->newTurn();
elem->newTurn(getRandomGenerator());
}
synchronizeArtifactHandlerLists(); //new day events may have changed them. TODO better of managing that
@ -1859,9 +1863,18 @@ void CGameHandler::setupBattle( int3 tile, const CArmedInstance *armies[2], cons
{
battleResult.set(nullptr);
const auto t = gs->getTile(tile);
ETerrainType terrain = t->terType;
if(gs->map->isCoastalTile(tile)) //coastal tile is always ground
terrain = ETerrainType::SAND;
BFieldType terType = gs->battleGetBattlefieldType(tile, getRandomGenerator());
if (heroes[0] && heroes[0]->boat && heroes[1] && heroes[1]->boat)
terType = BFieldType::SHIP_TO_SHIP;
//send info about battles
BattleStart bs;
bs.info = gs->setupBattle(tile, armies, heroes, creatureBank, town);
bs.info = BattleInfo::setupBattle(tile, terrain, terType, armies, heroes, creatureBank, town);
sendAndApply(&bs);
}
@ -3569,7 +3582,7 @@ bool CGameHandler::hireHero(const CGObjectInstance *obj, ui8 hid, PlayerColor pl
const CGHeroInstance *newHero = nullptr;
if (theOtherHero) //on XXL maps all heroes can be imprisoned :(
{
newHero = gs->hpool.pickHeroFor(false, player, getNativeTown(player), pool, gs->getRandomGenerator(), theOtherHero->type->heroClass);
newHero = gs->hpool.pickHeroFor(false, player, getNativeTown(player), pool, getRandomGenerator(), theOtherHero->type->heroClass);
}
SetAvailableHeroes sah;
@ -3978,7 +3991,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
{
if(currentHP.at(attackedPart) != EWallState::DESTROYED && // this part can be hit
currentHP.at(attackedPart) != EWallState::NONE &&
gs->getRandomGenerator().nextInt(99) < getCatapultHitChance(attackedPart, sbi))//hit is successful
getRandomGenerator().nextInt(99) < getCatapultHitChance(attackedPart, sbi))//hit is successful
{
hitSuccessfull = true;
}
@ -3993,7 +4006,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
}
if (allowedTargets.empty())
break;
attackedPart = *RandomGeneratorUtil::nextItem(allowedTargets, gs->getRandomGenerator());
attackedPart = *RandomGeneratorUtil::nextItem(allowedTargets, getRandomGenerator());
}
}
while (!hitSuccessfull);
@ -4009,7 +4022,7 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
int dmgChance[] = { sbi.noDmg, sbi.oneDmg, sbi.twoDmg }; //dmgChance[i] - chance for doing i dmg when hit is successful
int dmgRand = gs->getRandomGenerator().nextInt(99);
int dmgRand = getRandomGenerator().nextInt(99);
//accumulating dmgChance
dmgChance[1] += dmgChance[0];
dmgChance[2] += dmgChance[1];
@ -4164,8 +4177,8 @@ bool CGameHandler::makeBattleAction( BattleAction &ba )
const Bonus * spellcaster = stack->getBonusLocalFirst(Selector::typeSubtype(Bonus::SPELLCASTER, spellID));
//TODO special bonus for genies ability
if(randSpellcaster && battleGetRandomStackSpell(stack, CBattleInfoCallback::RANDOM_AIMED) < 0)
spellID = battleGetRandomStackSpell(stack, CBattleInfoCallback::RANDOM_GENIE);
if(randSpellcaster && battleGetRandomStackSpell(getRandomGenerator(), stack, CBattleInfoCallback::RANDOM_AIMED) < 0)
spellID = battleGetRandomStackSpell(getRandomGenerator(), stack, CBattleInfoCallback::RANDOM_GENIE);
if(spellID < 0)
complain("That stack can't cast spells!");
@ -4507,7 +4520,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
}
if (fearsomeCreature)
{
if (gs->getRandomGenerator().nextInt(99) < 10) //fixed 10%
if (getRandomGenerator().nextInt(99) < 10) //fixed 10%
{
bte.effect = Bonus::FEAR;
sendAndApply(&bte);
@ -4521,7 +4534,7 @@ void CGameHandler::stackTurnTrigger(const CStack * st)
bool cast = false;
while (!bl.empty() && !cast)
{
auto bonus = *RandomGeneratorUtil::nextItem(bl, gs->getRandomGenerator());
auto bonus = *RandomGeneratorUtil::nextItem(bl, getRandomGenerator());
auto spellID = SpellID(bonus->subtype);
const CSpell * spell = SpellID(spellID).toSpell();
bl.remove_if([&bonus](Bonus * b){return b==bonus;});
@ -4635,7 +4648,7 @@ void CGameHandler::handleDamageFromObstacle(const CObstacleInstance &obstacle, c
bsa.damageAmount = damage;
bsa.stackAttacked = curStack->ID;
bsa.attackerID = -1;
curStack->prepareAttacked(bsa, gameState()->getRandomGenerator());
curStack->prepareAttacked(bsa, getRandomGenerator());
StacksInjured si;
si.stacks.push_back(bsa);
@ -5232,7 +5245,7 @@ void CGameHandler::attackCasting(const BattleAttack & bat, Bonus::BonusType atta
continue;
//check if spell should be cast (probability handling)
if(gs->getRandomGenerator().nextInt(99) >= chance)
if(getRandomGenerator().nextInt(99) >= chance)
continue;
//casting
@ -5314,7 +5327,7 @@ void CGameHandler::handleAfterAttackCasting( const BattleAttack & bat )
TBonusListPtr acidBreath = attacker->getBonuses(Selector::type(Bonus::ACID_BREATH));
for(const Bonus *b : *acidBreath)
{
if (b->additionalInfo > gs->getRandomGenerator().nextInt(99))
if (b->additionalInfo > getRandomGenerator().nextInt(99))
acidDamage += b->val;
}
if (acidDamage)
@ -5625,7 +5638,7 @@ void CGameHandler::runBattle()
|| NBonus::hasOfType(gs->curB->battleGetFightingHero(1), Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses)
)
{
if(gs->getRandomGenerator().nextInt(23) < -2 * nextStackMorale)
if(getRandomGenerator().nextInt(23) < -2 * nextStackMorale)
{
//unit loses its turn - empty freeze action
BattleAction ba;
@ -5697,7 +5710,7 @@ void CGameHandler::runBattle()
{
BattleAction attack;
attack.destinationTile = *RandomGeneratorUtil::nextItem(attackableBattleHexes,
gs->getRandomGenerator());
getRandomGenerator());
attack.actionType = Battle::CATAPULT;
attack.additionalInfo = 0;
attack.side = !next->attackerOwned;
@ -5723,7 +5736,7 @@ void CGameHandler::runBattle()
if(!curOwner || curOwner->getSecSkillLevel(SecondarySkill::FIRST_AID) == 0) //no hero or hero has no first aid
{
range::random_shuffle(possibleStacks);
RandomGeneratorUtil::randomShuffle(possibleStacks, getRandomGenerator());
const CStack * toBeHealed = possibleStacks.front();
BattleAction heal;
@ -5802,7 +5815,7 @@ void CGameHandler::runBattle()
|| NBonus::hasOfType(gs->curB->battleGetFightingHero(1), Bonus::BLOCK_MORALE)) //checking if gs->curB->heroes have (or don't have) morale blocking bonuses
)
{
if(gs->getRandomGenerator().nextInt(23) < nextStackMorale) //this stack hasn't got morale this turn
if(getRandomGenerator().nextInt(23) < nextStackMorale) //this stack hasn't got morale this turn
{
BattleTriggerEffect bte;
@ -5926,7 +5939,8 @@ void CGameHandler::spawnWanderingMonsters(CreatureID creatureID)
std::vector<int3> tiles;
getFreeTiles(tiles);
ui32 amount = tiles.size() / 200; //Chance is 0.5% for each tile
std::random_shuffle(tiles.begin(), tiles.end());
RandomGeneratorUtil::randomShuffle(tiles, getRandomGenerator());
logGlobal->trace("Spawning wandering monsters. Found %d free tiles. Creature type: %d", tiles.size(), creatureID.num);
const CCreature *cre = VLC->creh->creatures.at(creatureID);
for (int i = 0; i < amount; ++i)
@ -6230,6 +6244,11 @@ CGameHandler::FinishingBattleHelper::FinishingBattleHelper()
winnerHero = loserHero = nullptr;
}
CRandomGenerator & CGameHandler::getRandomGenerator()
{
return CRandomGenerator::getDefault();
}
///ServerSpellCastEnvironment
ServerSpellCastEnvironment::ServerSpellCastEnvironment(CGameHandler * gh): gh(gh)
{
@ -6243,7 +6262,7 @@ void ServerSpellCastEnvironment::sendAndApply(CPackForClient * info) const
CRandomGenerator & ServerSpellCastEnvironment::getRandomGenerator() const
{
return gh->gameState()->getRandomGenerator();
return gh->getRandomGenerator();
}
void ServerSpellCastEnvironment::complain(const std::string& problem) const