2023-07-11 14:16:02 +02:00
|
|
|
/*
|
|
|
|
* TavernHeroesPool.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 "TavernHeroesPool.h"
|
|
|
|
|
|
|
|
#include "../mapObjects/CGHeroInstance.h"
|
2023-07-12 11:29:05 +02:00
|
|
|
#include "../CHeroHandler.h"
|
2023-07-11 14:16:02 +02:00
|
|
|
|
2023-07-11 16:51:14 +02:00
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
2023-07-11 14:16:02 +02:00
|
|
|
|
|
|
|
TavernHeroesPool::~TavernHeroesPool()
|
|
|
|
{
|
2023-07-11 17:49:19 +02:00
|
|
|
for(const auto & ptr : heroesPool) // clean hero pool
|
2023-07-11 14:16:02 +02:00
|
|
|
delete ptr.second;
|
|
|
|
}
|
|
|
|
|
2023-07-11 16:51:14 +02:00
|
|
|
std::map<HeroTypeID, CGHeroInstance*> TavernHeroesPool::unusedHeroesFromPool() const
|
2023-07-11 14:16:02 +02:00
|
|
|
{
|
|
|
|
std::map<HeroTypeID, CGHeroInstance*> pool = heroesPool;
|
2023-07-11 22:08:30 +02:00
|
|
|
for(const auto & slot : currentTavern)
|
2023-10-24 16:11:25 +02:00
|
|
|
pool.erase(slot.hero->getHeroType());
|
2023-07-11 14:16:02 +02:00
|
|
|
|
|
|
|
return pool;
|
|
|
|
}
|
|
|
|
|
2023-07-11 22:08:30 +02:00
|
|
|
TavernSlotRole TavernHeroesPool::getSlotRole(HeroTypeID hero) const
|
2023-07-11 14:16:02 +02:00
|
|
|
{
|
2023-07-11 22:08:30 +02:00
|
|
|
for (auto const & slot : currentTavern)
|
|
|
|
{
|
2023-10-24 16:11:25 +02:00
|
|
|
if (slot.hero->getHeroType() == hero)
|
2023-07-11 22:08:30 +02:00
|
|
|
return slot.role;
|
|
|
|
}
|
|
|
|
return TavernSlotRole::NONE;
|
|
|
|
}
|
|
|
|
|
2024-01-15 22:25:52 +02:00
|
|
|
void TavernHeroesPool::setHeroForPlayer(PlayerColor player, TavernHeroSlot slot, HeroTypeID hero, CSimpleArmy & army, TavernSlotRole role, bool replenishPoints)
|
2023-07-11 22:08:30 +02:00
|
|
|
{
|
|
|
|
vstd::erase_if(currentTavern, [&](const TavernSlot & entry){
|
|
|
|
return entry.player == player && entry.slot == slot;
|
|
|
|
});
|
2023-07-11 14:16:02 +02:00
|
|
|
|
|
|
|
if (hero == HeroTypeID::NONE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CGHeroInstance * h = heroesPool[hero];
|
|
|
|
|
|
|
|
if (h && army)
|
|
|
|
h->setToArmy(army);
|
|
|
|
|
2024-01-15 22:25:52 +02:00
|
|
|
if (h && replenishPoints)
|
|
|
|
{
|
|
|
|
h->setMovementPoints(h->movementPointsLimit(true));
|
|
|
|
h->mana = h->manaLimit();
|
|
|
|
}
|
|
|
|
|
2023-07-11 22:08:30 +02:00
|
|
|
TavernSlot newSlot;
|
|
|
|
newSlot.hero = h;
|
|
|
|
newSlot.player = player;
|
2023-07-12 11:29:05 +02:00
|
|
|
newSlot.role = role;
|
2023-07-11 22:08:30 +02:00
|
|
|
newSlot.slot = slot;
|
|
|
|
|
|
|
|
currentTavern.push_back(newSlot);
|
|
|
|
|
|
|
|
boost::range::sort(currentTavern, [](const TavernSlot & left, const TavernSlot & right)
|
|
|
|
{
|
|
|
|
if (left.slot == right.slot)
|
|
|
|
return left.player < right.player;
|
|
|
|
else
|
|
|
|
return left.slot < right.slot;
|
|
|
|
});
|
2023-07-11 14:16:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool TavernHeroesPool::isHeroAvailableFor(HeroTypeID hero, PlayerColor color) const
|
|
|
|
{
|
2023-07-12 11:29:05 +02:00
|
|
|
if (perPlayerAvailability.count(hero))
|
2023-08-25 20:40:19 +02:00
|
|
|
return perPlayerAvailability.at(hero).count(color) != 0;
|
2023-07-11 14:16:02 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<const CGHeroInstance *> TavernHeroesPool::getHeroesFor(PlayerColor color) const
|
|
|
|
{
|
|
|
|
std::vector<const CGHeroInstance *> result;
|
|
|
|
|
2023-07-11 22:08:30 +02:00
|
|
|
for(const auto & slot : currentTavern)
|
|
|
|
{
|
|
|
|
if (slot.player == color)
|
|
|
|
result.push_back(slot.hero);
|
|
|
|
}
|
2023-07-11 14:16:02 +02:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-07-12 11:29:05 +02:00
|
|
|
CGHeroInstance * TavernHeroesPool::takeHeroFromPool(HeroTypeID hero)
|
2023-07-11 14:16:02 +02:00
|
|
|
{
|
|
|
|
assert(heroesPool.count(hero));
|
|
|
|
|
|
|
|
CGHeroInstance * result = heroesPool[hero];
|
|
|
|
heroesPool.erase(hero);
|
|
|
|
|
2023-07-12 11:29:05 +02:00
|
|
|
vstd::erase_if(currentTavern, [&](const TavernSlot & entry){
|
|
|
|
return entry.hero->type->getId() == hero;
|
|
|
|
});
|
|
|
|
|
2023-07-11 14:16:02 +02:00
|
|
|
assert(result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TavernHeroesPool::onNewDay()
|
|
|
|
{
|
2023-07-27 14:51:38 +02:00
|
|
|
auto unusedHeroes = unusedHeroesFromPool();
|
|
|
|
|
2023-07-11 14:16:02 +02:00
|
|
|
for(auto & hero : heroesPool)
|
|
|
|
{
|
|
|
|
assert(hero.second);
|
|
|
|
if(!hero.second)
|
|
|
|
continue;
|
|
|
|
|
2023-09-06 08:12:23 +02:00
|
|
|
hero.second->removeBonusesRecursive(Bonus::OneDay);
|
|
|
|
hero.second->reduceBonusDurations(Bonus::NDays);
|
|
|
|
hero.second->reduceBonusDurations(Bonus::OneWeek);
|
|
|
|
|
2023-07-27 14:51:38 +02:00
|
|
|
// do not access heroes who are not present in tavern of any players
|
|
|
|
if (vstd::contains(unusedHeroes, hero.first))
|
|
|
|
continue;
|
|
|
|
|
2023-07-11 14:16:02 +02:00
|
|
|
hero.second->setMovementPoints(hero.second->movementPointsLimit(true));
|
2023-11-12 19:30:33 +02:00
|
|
|
hero.second->mana = hero.second->getManaNewTurn();
|
2023-07-11 14:16:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void TavernHeroesPool::addHeroToPool(CGHeroInstance * hero)
|
|
|
|
{
|
2023-10-24 16:11:25 +02:00
|
|
|
heroesPool[hero->getHeroType()] = hero;
|
2023-07-11 14:16:02 +02:00
|
|
|
}
|
|
|
|
|
2023-08-25 20:40:19 +02:00
|
|
|
void TavernHeroesPool::setAvailability(HeroTypeID hero, std::set<PlayerColor> mask)
|
2023-07-11 14:16:02 +02:00
|
|
|
{
|
2023-07-12 11:29:05 +02:00
|
|
|
perPlayerAvailability[hero] = mask;
|
2023-07-11 14:16:02 +02:00
|
|
|
}
|
2023-07-11 16:51:14 +02:00
|
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_END
|