| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 | 
							- /*
 
-  * Limiter.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 "Limiter.h"
 
- #include "../IGameCallback.h"
 
- #include "../CPlayerState.h"
 
- #include "../entities/artifact/ArtifactUtils.h"
 
- #include "../mapObjects/CGHeroInstance.h"
 
- #include "../networkPacks/Component.h"
 
- #include "../serializer/JsonSerializeFormat.h"
 
- #include "../constants/StringConstants.h"
 
- #include "../CSkillHandler.h"
 
- VCMI_LIB_NAMESPACE_BEGIN
 
- Rewardable::Limiter::Limiter()
 
- 	: dayOfWeek(0)
 
- 	, daysPassed(0)
 
- 	, heroExperience(0)
 
- 	, heroLevel(-1)
 
- 	, manaPercentage(0)
 
- 	, manaPoints(0)
 
- 	, canLearnSkills(false)
 
- 	, commanderAlive(false)
 
- 	, hasExtraCreatures(false)
 
- 	, primary(GameConstants::PRIMARY_SKILLS, 0)
 
- {
 
- }
 
- Rewardable::Limiter::~Limiter() = default;
 
- bool operator==(const Rewardable::Limiter & l, const Rewardable::Limiter & r)
 
- {
 
- 	return l.dayOfWeek == r.dayOfWeek
 
- 	&& l.daysPassed == r.daysPassed
 
- 	&& l.heroLevel == r.heroLevel
 
- 	&& l.heroExperience == r.heroExperience
 
- 	&& l.manaPoints == r.manaPoints
 
- 	&& l.manaPercentage == r.manaPercentage
 
- 	&& l.secondary == r.secondary
 
- 	&& l.canLearnSkills == r.canLearnSkills
 
- 	&& l.creatures == r.creatures
 
- 	&& l.spells == r.spells
 
- 	&& l.artifacts == r.artifacts
 
- 	&& l.players == r.players
 
- 	&& l.heroes == r.heroes
 
- 	&& l.heroClasses == r.heroClasses
 
- 	&& l.resources == r.resources
 
- 	&& l.primary == r.primary
 
- 	&& l.noneOf == r.noneOf
 
- 	&& l.allOf == r.allOf
 
- 	&& l.anyOf == r.anyOf;
 
- }
 
- bool operator!=(const Rewardable::Limiter & l, const Rewardable::Limiter & r)
 
- {
 
- 	return !(l == r);
 
- }
 
- bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
 
- {
 
- 	if(dayOfWeek != 0)
 
- 	{
 
- 		if (hero->cb->getDate(Date::DAY_OF_WEEK) != dayOfWeek)
 
- 			return false;
 
- 	}
 
- 	if(daysPassed != 0)
 
- 	{
 
- 		if (hero->cb->getDate(Date::DAY) < daysPassed)
 
- 			return false;
 
- 	}
 
- 	if (commanderAlive)
 
- 	{
 
- 		if (!hero->getCommander() || !hero->getCommander()->alive)
 
- 			return false;
 
- 	}
 
- 	if (!creatures.empty())
 
- 	{
 
- 		if (!hero->hasUnits(creatures, hasExtraCreatures))
 
- 			return false;
 
- 	}
 
- 	if (!canReceiveCreatures.empty())
 
- 	{
 
- 		CCreatureSet setToTest;
 
- 		for (const auto & unitToGive : canReceiveCreatures)
 
- 			setToTest.addToSlot(setToTest.getSlotFor(unitToGive.getCreature()), unitToGive.getId(), unitToGive.getCount());
 
- 		if (!hero->canBeMergedWith(setToTest))
 
- 			return false;
 
- 	}
 
- 	if(!hero->cb->getPlayerState(hero->tempOwner)->resources.canAfford(resources))
 
- 		return false;
 
- 	if(heroLevel > static_cast<si32>(hero->level))
 
- 		return false;
 
- 	if(static_cast<TExpType>(heroExperience) > hero->exp)
 
- 		return false;
 
- 	if(manaPoints > hero->mana)
 
- 		return false;
 
- 	if (canLearnSkills && !hero->canLearnSkill())
 
- 		return false;
 
- 	if (hero->manaLimit() != 0 && manaPercentage > 100 * hero->mana / hero->manaLimit())
 
- 		return false;
 
- 	for(size_t i=0; i<primary.size(); i++)
 
- 	{
 
- 		if(primary[i] > hero->getPrimSkillLevel(static_cast<PrimarySkill>(i)))
 
- 			return false;
 
- 	}
 
- 	for(const auto & skill : secondary)
 
- 	{
 
- 		if (skill.second > hero->getSecSkillLevel(skill.first))
 
- 			return false;
 
- 	}
 
- 	for(const auto & spell : spells)
 
- 	{
 
- 		if (!hero->spellbookContainsSpell(spell))
 
- 			return false;
 
- 	}
 
- 	for(const auto & spell : canLearnSpells)
 
- 	{
 
- 		if (!hero->canLearnSpell(spell.toEntity(LIBRARY), true))
 
- 			return false;
 
- 	}
 
- 	for(const auto & scroll : scrolls)
 
- 	{
 
- 		if (!hero->hasScroll(scroll, false))
 
- 			return false;
 
- 	}
 
- 	for(const auto & slot : availableSlots)
 
- 	{
 
- 		if (hero->getSlot(slot)->artifactID.hasValue())
 
- 			return false;
 
- 	}
 
- 	{
 
- 		std::unordered_map<ArtifactID, unsigned int, ArtifactID::hash> artifactsRequirements; // artifact ID -> required count
 
- 		for(const auto & art : artifacts)
 
- 			++artifactsRequirements[art];
 
- 		
 
- 		size_t reqSlots = 0;
 
- 		for(const auto & elem : artifactsRequirements)
 
- 		{
 
- 			// check required amount of artifacts
 
- 			size_t artCnt = 0;
 
- 			for(const auto & [slot, slotInfo] : hero->artifactsWorn)
 
- 				if(slotInfo.getArt()->getTypeId() == elem.first)
 
- 					artCnt++;
 
- 			for(auto & slotInfo : hero->artifactsInBackpack)
 
- 				if(slotInfo.getArt()->getTypeId() == elem.first)
 
- 				{
 
- 					artCnt++;
 
- 				}
 
- 				else if(slotInfo.getArt()->isCombined())
 
- 				{
 
- 					for(const auto & partInfo : slotInfo.getArt()->getPartsInfo())
 
- 						if(partInfo.getArtifact()->getTypeId() == elem.first)
 
- 							artCnt++;
 
- 				}
 
- 			if(artCnt < elem.second)
 
- 				return false;
 
- 			// Check if art has no own slot. (As part of combined in backpack)
 
- 			if(hero->getArtPos(elem.first, false) == ArtifactPosition::PRE_FIRST)
 
- 				reqSlots += hero->getCombinedArtWithPart(elem.first)->getPartsInfo().size() - 2;
 
- 		}
 
- 		if(!ArtifactUtils::isBackpackFreeSlots(hero, reqSlots))
 
- 			return false;
 
- 	}
 
- 	
 
- 	if(!players.empty() && !vstd::contains(players, hero->getOwner()))
 
- 		return false;
 
- 	
 
- 	if(!heroes.empty() && !vstd::contains(heroes, hero->getHeroTypeID()))
 
- 		return false;
 
- 	
 
- 	if(!heroClasses.empty() && !vstd::contains(heroClasses, hero->getHeroClassID()))
 
- 		return false;
 
- 		
 
- 	
 
- 	for(const auto & sublimiter : noneOf)
 
- 	{
 
- 		if (sublimiter->heroAllowed(hero))
 
- 			return false;
 
- 	}
 
- 	for(const auto & sublimiter : allOf)
 
- 	{
 
- 		if (!sublimiter->heroAllowed(hero))
 
- 			return false;
 
- 	}
 
- 	if(anyOf.empty())
 
- 		return true;
 
- 	for(const auto & sublimiter : anyOf)
 
- 	{
 
- 		if (sublimiter->heroAllowed(hero))
 
- 			return true;
 
- 	}
 
- 	return false;
 
- }
 
- void Rewardable::Limiter::loadComponents(std::vector<Component> & comps,
 
- 								 const CGHeroInstance * h) const
 
- {
 
- 	if (heroExperience)
 
- 		comps.emplace_back(ComponentType::EXPERIENCE, static_cast<si32>(h ? h->calculateXp(heroExperience) : heroExperience));
 
- 	if (heroLevel > 0)
 
- 		comps.emplace_back(ComponentType::EXPERIENCE, heroLevel);
 
- 	if (manaPoints || manaPercentage > 0)
 
- 	{
 
- 		int absoluteMana = (h && h->manaLimit()) ? (manaPercentage * h->mana / h->manaLimit() / 100) : 0;
 
- 		comps.emplace_back(ComponentType::MANA, absoluteMana + manaPoints);
 
- 	}
 
- 	for (size_t i=0; i<primary.size(); i++)
 
- 	{
 
- 		if (primary[i] != 0)
 
- 			comps.emplace_back(ComponentType::PRIM_SKILL, PrimarySkill(i), primary[i]);
 
- 	}
 
- 	for(const auto & entry : secondary)
 
- 		comps.emplace_back(ComponentType::SEC_SKILL, entry.first, entry.second);
 
- 	for(const auto & entry : artifacts)
 
- 		comps.emplace_back(ComponentType::ARTIFACT, entry);
 
- 	for(const auto & entry : spells)
 
- 		comps.emplace_back(ComponentType::SPELL, entry);
 
- 	for(const auto & entry : creatures)
 
- 		comps.emplace_back(ComponentType::CREATURE, entry.getId(), entry.getCount());
 
- 	
 
- 	for(const auto & entry : players)
 
- 		comps.emplace_back(ComponentType::FLAG, entry);
 
- 	
 
- 	for(const auto & entry : heroes)
 
- 		comps.emplace_back(ComponentType::HERO_PORTRAIT, entry);
 
- 	
 
- 	for (size_t i=0; i<resources.size(); i++)
 
- 	{
 
- 		if (resources[i] !=0)
 
- 			comps.emplace_back(ComponentType::RESOURCE, GameResID(i), resources[i]);
 
- 	}
 
- }
 
- void Rewardable::Limiter::serializeJson(JsonSerializeFormat & handler)
 
- {
 
- 	handler.serializeInt("dayOfWeek", dayOfWeek);
 
- 	handler.serializeInt("daysPassed", daysPassed);
 
- 	resources.serializeJson(handler, "resources");
 
- 	handler.serializeInt("manaPercentage", manaPercentage);
 
- 	handler.serializeInt("heroExperience", heroExperience);
 
- 	handler.serializeInt("heroLevel", heroLevel);
 
- 	handler.serializeIdArray("heroes", heroes);
 
- 	handler.serializeIdArray("heroClasses", heroClasses);
 
- 	handler.serializeIdArray("colors", players);
 
- 	handler.serializeInt("manaPoints", manaPoints);
 
- 	handler.serializeIdArray("artifacts", artifacts);
 
- 	handler.serializeIdArray("spells", spells);
 
- 	handler.enterArray("creatures").serializeStruct(creatures);
 
- 	handler.enterArray("primary").serializeArray(primary);
 
- 	{
 
- 		auto a = handler.enterArray("secondary");
 
- 		std::vector<std::pair<SecondarySkill, si32>> fieldValue(secondary.begin(), secondary.end());
 
- 		a.serializeStruct<std::pair<SecondarySkill, si32>>(fieldValue, [](JsonSerializeFormat & h, std::pair<SecondarySkill, si32> & e)
 
- 		{
 
- 			h.serializeId("skill", e.first, SecondarySkill(SecondarySkill::NONE));
 
- 			h.serializeId("level", e.second, 0, [](const std::string & i){return vstd::find_pos(NSecondarySkill::levels, i);}, [](si32 i){return NSecondarySkill::levels.at(i);});
 
- 		});
 
- 		a.syncSize(fieldValue);
 
- 		secondary = std::map<SecondarySkill, si32>(fieldValue.begin(), fieldValue.end());
 
- 	}
 
- 	//sublimiters
 
- 	auto serializeSublimitersList = [&handler](const std::string & field, LimitersList & container)
 
- 	{
 
- 		auto a = handler.enterArray(field);
 
- 		a.syncSize(container);
 
- 		for(int i = 0; i < container.size(); ++i)
 
- 		{
 
- 			if(!handler.saving)
 
- 				container[i] = std::make_shared<Rewardable::Limiter>();
 
- 			auto e = a.enterStruct(i);
 
- 			container[i]->serializeJson(handler);
 
- 		}
 
- 	};
 
- 	serializeSublimitersList("allOf", allOf);
 
- 	serializeSublimitersList("anyOf", anyOf);
 
- 	serializeSublimitersList("noneOf", noneOf);
 
- }
 
- VCMI_LIB_NAMESPACE_END
 
 
  |