Exemple #1
0
int CGHeroInstance::maxMovePoints(bool onLand) const
{
	int base;

	if(onLand)
	{
		// used function is f(x) = 66.6x + 1300, rounded to second digit, where x is lowest speed in army
		static const int baseSpeed = 1300; // base speed from creature with 0 speed

		int armySpeed = lowestSpeed(this) * 20 / 3;

		base = armySpeed * 10 + baseSpeed; // separate *10 is intentional to receive same rounding as in h3
		vstd::abetween(base, 1500, 2000); // base speed is limited by these values
	}
	else
	{
		base = 1500; //on water base movement is always 1500 (speed of army doesn't matter)
	}

	const Bonus::BonusType bt = onLand ? Bonus::LAND_MOVEMENT : Bonus::SEA_MOVEMENT;
	const int bonus = valOfBonuses(Bonus::MOVEMENT) + valOfBonuses(bt);

	const int subtype = onLand ? SecondarySkill::LOGISTICS : SecondarySkill::NAVIGATION;
	const double modifier = valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, subtype) / 100.0;

	return int(base* (1+modifier)) + bonus;
}
Exemple #2
0
si32 CGHeroInstance::manaRegain() const
{
	if (hasBonusOfType(Bonus::FULL_MANA_REGENERATION))
		return manaLimit();

	return 1 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 8) + valOfBonuses(Bonus::MANA_REGENERATION); //1 + Mysticism level
}
Exemple #3
0
bool compareArtifacts(const CArtifactInstance *a1, const CArtifactInstance *a2)
{
	auto art1 = a1->artType;
	auto art2 = a2->artType;

	if (art1->valOfBonuses(Bonus::PRIMARY_SKILL) > art2->valOfBonuses(Bonus::PRIMARY_SKILL))
		return true;
	else
		return art1->price > art2->price;
}
Exemple #4
0
si32 IBonusBearer::Attack() const
{
	si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK);

	if (double frenzyPower = valOfBonuses(Bonus::IN_FRENZY)) //frenzy for attacker
	{
		ret += (frenzyPower/100) * (double)Defense(false);
	}
	vstd::amax(ret, 0);

	return ret;
}
Exemple #5
0
int IBonusBearer::valOfBonuses(Bonus::BonusType type, int subtype /*= -1*/) const
{
	std::stringstream cachingStr;
	cachingStr << "type_" << type << "s_" << subtype;

	CSelector s = Selector::type(type);
	if(subtype != -1)
		s = s.And(Selector::subtype(subtype));

	return valOfBonuses(s, cachingStr.str());
}
Exemple #6
0
si32 CStackInstance::magicResistance() const
{
	si32 val = valOfBonuses(Selector::type(Bonus::MAGIC_RESISTANCE));
	if (const CGHeroInstance * hero = dynamic_cast<const CGHeroInstance *>(_armyObj))
	{
		//resistance skill
		val += hero->valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::RESISTANCE);
	}
	vstd::amin (val, 100);
	return val;
}
Exemple #7
0
int IBonusBearer::LuckVal() const
{
	if(hasBonusOfType(Bonus::NO_LUCK))
		return 0;

	int ret = valOfBonuses(Bonus::LUCK);

	if(hasBonusOfType(Bonus::SELF_LUCK)) //eg. halfling
		vstd::amax(ret, +1);

	return vstd::abetween(ret, -3, +3);
}
Exemple #8
0
si32 IBonusBearer::Defense(bool withFrenzy /*= true*/) const
{
	si32 ret = valOfBonuses(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE);

	if(withFrenzy && hasBonusOfType(Bonus::IN_FRENZY)) //frenzy for defender
	{
		return 0;
	}
	vstd::amax(ret, 0);

	return ret;
}
Exemple #9
0
int IBonusBearer::getPrimSkillLevel(PrimarySkill::PrimarySkill id) const
{
	int ret = 0;
	if(id == PrimarySkill::ATTACK)
		ret = Attack();
	else if(id == PrimarySkill::DEFENSE)
		ret = Defense();
	else
		ret = valOfBonuses(Bonus::PRIMARY_SKILL, id);

	vstd::amax(ret, id/2); //minimal value is 0 for attack and defense and 1 for spell power and knowledge
	return ret;
}
Exemple #10
0
int IBonusBearer::MoraleVal() const
{
	if(hasBonusOfType(Bonus::NON_LIVING) || hasBonusOfType(Bonus::UNDEAD) ||
		hasBonusOfType(Bonus::NO_MORALE) || hasBonusOfType(Bonus::SIEGE_WEAPON))
		return 0;

	int ret = valOfBonuses(Bonus::MORALE);

	if(hasBonusOfType(Bonus::SELF_MORALE)) //eg. minotaur
		vstd::amax(ret, +1);

	return vstd::abetween(ret, -3, +3);
}
Exemple #11
0
ui8 CGHeroInstance::getSpellSchoolLevel(const CSpell * spell, int *outSelectedSchool) const
{
	si16 skill = -1; //skill level
	
	spell->forEachSchool([&, this](const SpellSchoolInfo & cnf, bool & stop)
	{
		int thisSchool = std::max<int>(getSecSkillLevel(cnf.skill),	valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 1 << ((ui8)cnf.id))); 
		if(thisSchool > skill)									
		{														
			skill = thisSchool;									
			if(outSelectedSchool)								
				*outSelectedSchool = (ui8)cnf.id;				
		}																
	});
	
	vstd::amax(skill, valOfBonuses(Bonus::MAGIC_SCHOOL_SKILL, 0)); //any school bonus
	vstd::amax(skill, valOfBonuses(Bonus::SPELL, spell->id.toEnum())); //given by artifact or other effect
	if (hasBonusOfType(Bonus::MAXED_SPELL, spell->id))//hero specialty (Daremyth, Melodia)
		skill = 3;
	assert(skill >= 0 && skill <= 3);
	return skill;
}
Exemple #12
0
ui32 IBonusBearer::Speed( int turn /*= 0*/ , bool useBind /* = false*/) const
{
	//war machines cannot move
	if(hasBonus(Selector::type(Bonus::SIEGE_WEAPON).And(Selector::turns(turn))))
	{
		return 0;
	}
	//bind effect check - doesn't influence stack initiative
	if (useBind && getEffect (SpellID::BIND))
	{
		return 0;
	}

	return valOfBonuses(Selector::type(Bonus::STACKS_SPEED).And(Selector::turns(turn)));
}	
Exemple #13
0
/**
 * Calculates what creatures and how many to be raised from a battle.
 * @param battleResult The results of the battle.
 * @return Returns a pair with the first value indicating the ID of the creature
 * type and second value the amount. Both values are returned as -1 if necromancy
 * could not be applied.
 */
CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &battleResult) const
{
	const ui8 necromancyLevel = getSecSkillLevel(SecondarySkill::NECROMANCY);

	// Hero knows necromancy or has Necromancer Cloak
	if (necromancyLevel > 0 || hasBonusOfType(Bonus::IMPROVED_NECROMANCY))
	{
		double necromancySkill = valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::NECROMANCY)/100.0;
		vstd::amin(necromancySkill, 1.0); //it's impossible to raise more creatures than all...
		const std::map<ui32,si32> &casualties = battleResult.casualties[!battleResult.winner];
		ui32 raisedUnits = 0;

		// Figure out what to raise and how many.
		const CreatureID creatureTypes[] = {CreatureID::SKELETON, CreatureID::WALKING_DEAD, CreatureID::WIGHTS, CreatureID::LICHES};
		const bool improvedNecromancy = hasBonusOfType(Bonus::IMPROVED_NECROMANCY);
		const CCreature *raisedUnitType = VLC->creh->creatures[creatureTypes[improvedNecromancy ? necromancyLevel : 0]];
		const ui32 raisedUnitHP = raisedUnitType->valOfBonuses(Bonus::STACK_HEALTH);

		//calculate creatures raised from each defeated stack
		for (auto & casualtie : casualties)
		{
			// Get lost enemy hit points convertible to units.
			CCreature * c = VLC->creh->creatures[casualtie.first];

			const ui32 raisedHP = c->valOfBonuses(Bonus::STACK_HEALTH) * casualtie.second * necromancySkill;
			raisedUnits += std::min<ui32>(raisedHP / raisedUnitHP, casualtie.second * necromancySkill); //limit to % of HP and % of original stack count
		}

		// Make room for new units.
		SlotID slot = getSlotFor(raisedUnitType->idNumber);
		if (slot == SlotID())
		{
			// If there's no room for unit, try it's upgraded version 2/3rds the size.
			raisedUnitType = VLC->creh->creatures[*raisedUnitType->upgrades.begin()];
			raisedUnits = (raisedUnits*2)/3;

			slot = getSlotFor(raisedUnitType->idNumber);
		}
		if (raisedUnits <= 0)
			raisedUnits = 1;

		return CStackBasicDescriptor(raisedUnitType->idNumber, raisedUnits);
	}

	return CStackBasicDescriptor();
}
Exemple #14
0
bool CGHeroInstance::hasVisions(const CGObjectInstance * target, const int subtype) const
{
	//VISIONS spell support
	
	const std::string cached = boost::to_string((boost::format("type_%d__subtype_%d") % Bonus::VISIONS % subtype)); 
	
	const int visionsMultiplier = valOfBonuses(Selector::typeSubtype(Bonus::VISIONS,subtype), cached);
	
	int visionsRange =  visionsMultiplier * getPrimSkillLevel(PrimarySkill::SPELL_POWER);
		
	if (visionsMultiplier > 0) 	
		vstd::amax(visionsRange, 3); //minimum range is 3 tiles, but only if VISIONS bonus present
	
	const int distance = target->pos.dist2d(getPosition(false));
	
	//logGlobal->debug(boost::to_string(boost::format("Visions: dist %d, mult %d, range %d") % distance % visionsMultiplier % visionsRange));
	
	return (distance < visionsRange) && (target->pos.z == pos.z);	
}
Exemple #15
0
si32 IBonusBearer::magicResistance() const
{
	return valOfBonuses(Bonus::MAGIC_RESISTANCE);
}
Exemple #16
0
si32 IBonusBearer::manaLimit() const
{
	return si32(getPrimSkillLevel(PrimarySkill::KNOWLEDGE)
		* (100.0 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::INTELLIGENCE))
		/ 10.0);
}
Exemple #17
0
ui32 IBonusBearer::getMaxDamage() const
{
	std::stringstream cachingStr;
	cachingStr << "type_" << Bonus::CREATURE_DAMAGE << "s_0Otype_" << Bonus::CREATURE_DAMAGE << "s_2";
	return valOfBonuses(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0).Or(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 2)), cachingStr.str());
}
Exemple #18
0
ui32 IBonusBearer::MaxHealth() const
{
	return std::max(1, valOfBonuses(Bonus::STACK_HEALTH)); //never 0
}
Exemple #19
0
TExpType CGHeroInstance::calculateXp(TExpType exp) const
{
	return exp * (100 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::LEARNING))/100.0;
}
Exemple #20
0
int IBonusBearer::valOfBonuses(Bonus::BonusType type, const CSelector &selector) const
{
	return valOfBonuses(Selector::type(type).And(selector));
}
Exemple #21
0
int CGHeroInstance::getSightRadious() const
{
	return 5 + getSecSkillLevel(SecondarySkill::SCOUTING) + valOfBonuses(Bonus::SIGHT_RADIOUS); //default + scouting
}