| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 | 
							- /*
 
-  * CArmedInstance.cpp, part of VCMI engine
 
-  *
 
-  * Authors: listed in file AUTHORS in main folder
 
-  *
 
-  * License: GNU General Public License v2.0 or later
 
-  * Full text of license available in license.txt file, in main folder
 
-  *
 
-  */
 
- #include "StdInc.h"
 
- #include "CArmedInstance.h"
 
- #include "../CTownHandler.h"
 
- #include "../CCreatureHandler.h"
 
- #include "../CGeneralTextHandler.h"
 
- #include "../CGameState.h"
 
- #include "../CPlayerState.h"
 
- VCMI_LIB_NAMESPACE_BEGIN
 
- void CArmedInstance::randomizeArmy(int type)
 
- {
 
- 	for (auto & elem : stacks)
 
- 	{
 
- 		int & randID = elem.second->idRand;
 
- 		if(randID >= 0)
 
- 		{
 
- 			int level = randID / 2;
 
- 			bool upgrade = randID % 2;
 
- 			elem.second->setType((*VLC->townh)[type]->town->creatures[level][upgrade]);
 
- 			randID = -1;
 
- 		}
 
- 		assert(elem.second->valid(false));
 
- 		assert(elem.second->armyObj == this);
 
- 	}
 
- 	return;
 
- }
 
- // Take Angelic Alliance troop-mixing freedom of non-evil units into account.
 
- CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type()(Bonus::NONEVIL_ALIGNMENT_MIX);
 
- CArmedInstance::CArmedInstance()
 
- 	:CArmedInstance(false)
 
- {
 
- }
 
- CArmedInstance::CArmedInstance(bool isHypotetic)
 
- 	:CBonusSystemNode(isHypotetic), nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector)
 
- {
 
- 	battle = nullptr;
 
- }
 
- void CArmedInstance::updateMoraleBonusFromArmy()
 
- {
 
- 	if(!validTypes(false)) //object not randomized, don't bother
 
- 		return;
 
- 	auto b = getExportedBonusList().getFirst(Selector::sourceType()(Bonus::ARMY).And(Selector::type()(Bonus::MORALE)));
 
-  	if(!b)
 
- 	{
 
- 		b = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1);
 
- 		addNewBonus(b);
 
- 	}
 
- 	//number of alignments and presence of undead
 
- 	std::set<TFaction> factions;
 
- 	bool hasUndead = false;
 
- 	const std::string undeadCacheKey = "type_UNDEAD";
 
- 	static const CSelector undeadSelector = Selector::type()(Bonus::UNDEAD);
 
- 	for(auto slot : Slots())
 
- 	{
 
- 		const CStackInstance * inst = slot.second;
 
- 		const CCreature * creature  = VLC->creh->objects[inst->getCreatureID()];
 
- 		factions.insert(creature->faction);
 
- 		// Check for undead flag instead of faction (undead mummies are neutral)
 
- 		if (!hasUndead)
 
- 		{
 
- 			//this is costly check, let's skip it at first undead
 
- 			hasUndead |= inst->hasBonus(undeadSelector, undeadCacheKey);
 
- 		}
 
- 	}
 
- 	size_t factionsInArmy = factions.size(); //town garrison seems to take both sets into account
 
- 	if (nonEvilAlignmentMix.getHasBonus())
 
- 	{
 
- 		size_t mixableFactions = 0;
 
- 		for(TFaction f : factions)
 
- 		{
 
- 			if ((*VLC->townh)[f]->alignment != EAlignment::EVIL)
 
- 				mixableFactions++;
 
- 		}
 
- 		if (mixableFactions > 0)
 
- 			factionsInArmy -= mixableFactions - 1;
 
- 	}
 
- 	std::string description;
 
- 	if(factionsInArmy == 1)
 
- 	{
 
- 		b->val = +1;
 
- 		description = VLC->generaltexth->arraytxt[115]; //All troops of one alignment +1
 
- 		description = description.substr(0, description.size()-3);//trim "+1"
 
- 	}
 
- 	else if (!factions.empty()) // no bonus from empty garrison
 
- 	{
 
- 	 	b->val = 2 - (si32)factionsInArmy;
 
- 		description = boost::str(boost::format(VLC->generaltexth->arraytxt[114]) % factionsInArmy % b->val); //Troops of %d alignments %d
 
- 		description = b->description.substr(0, description.size()-2);//trim value
 
- 	}
 
- 	
 
- 	boost::algorithm::trim(description);
 
- 	b->description = description;
 
- 	CBonusSystemNode::treeHasChanged();
 
- 	//-1 modifier for any Undead unit in army
 
- 	const ui8 UNDEAD_MODIFIER_ID = -2;
 
- 	auto undeadModifier = getExportedBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID));
 
-  	if(hasUndead)
 
- 	{
 
- 		if(!undeadModifier)
 
- 		{
 
- 			undeadModifier = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]);
 
- 			undeadModifier->description = undeadModifier->description.substr(0, undeadModifier->description.size()-2);//trim value
 
- 			addNewBonus(undeadModifier);
 
- 		}
 
- 	}
 
- 	else if(undeadModifier)
 
- 		removeBonus(undeadModifier);
 
- }
 
- void CArmedInstance::armyChanged()
 
- {
 
- 	updateMoraleBonusFromArmy();
 
- }
 
- CBonusSystemNode & CArmedInstance::whereShouldBeAttached(CGameState * gs)
 
- {
 
- 	if(tempOwner < PlayerColor::PLAYER_LIMIT)
 
- 		if(auto * where = gs->getPlayerState(tempOwner))
 
- 			return *where;
 
- 	return gs->globalEffects;
 
- }
 
- CBonusSystemNode & CArmedInstance::whatShouldBeAttached()
 
- {
 
- 	return *this;
 
- }
 
- VCMI_LIB_NAMESPACE_END
 
 
  |