1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-10 22:31:40 +02:00

Unify checks for creature limiter

This commit is contained in:
Ivan Savenko
2025-05-07 15:55:48 +03:00
parent 4b77140f4a
commit 92c4bcbf68
5 changed files with 41 additions and 46 deletions

View File

@@ -612,6 +612,38 @@ bool CCreatureSet::canBeMergedWith(const CCreatureSet &cs, bool allowMergingStac
}
}
bool CCreatureSet::hasUnits(const std::vector<CStackBasicDescriptor> & units, bool requireLastStack) const
{
bool foundExtraCreatures = false;
int testedSlots = 0;
for(const auto & reqStack : units)
{
size_t count = 0;
for(const auto & slot : Slots())
{
const auto & heroStack = slot.second;
if (heroStack->getType() == reqStack.getType())
{
count += heroStack->getCount();
testedSlots += 1;
}
}
if (count > reqStack.getCount())
foundExtraCreatures = true;
if (count < reqStack.getCount()) //not enough creatures of this kind
return false;
}
if (requireLastStack)
{
if (!foundExtraCreatures && testedSlots >= Slots().size())
return false;
}
return true;
}
bool CCreatureSet::hasStackAtSlot(const SlotID & slot) const
{
return vstd::contains(stacks, slot);

View File

@@ -333,6 +333,11 @@ public:
bool contains(const CStackInstance *stack) const;
bool canBeMergedWith(const CCreatureSet &cs, bool allowMergingStacks = true) const;
/// Returns true if this creature set contains all listed units
/// If requireLastStack is true, then this function will also
/// require presence of any unit other than requested (or more units than requested)
bool hasUnits(const std::vector<CStackBasicDescriptor> & units, bool requireLastStack = true) const;
template <typename Handler> void serialize(Handler &h)
{
h & stacks;

View File

@@ -101,29 +101,7 @@ const std::string & CQuest::missionState(int state)
bool CQuest::checkMissionArmy(const CQuest * q, const CCreatureSet * army)
{
std::vector<CStackBasicDescriptor>::const_iterator cre;
TSlots::const_iterator it;
ui32 count = 0;
ui32 slotsCount = 0;
bool hasExtraCreatures = false;
for(cre = q->mission.creatures.begin(); cre != q->mission.creatures.end(); ++cre)
{
for(count = 0, it = army->Slots().begin(); it != army->Slots().end(); ++it)
{
if(it->second->getType() == cre->getType())
{
count += it->second->getCount();
slotsCount++;
}
}
if(static_cast<TQuantity>(count) < cre->getCount()) //not enough creatures of this kind
return false;
hasExtraCreatures |= static_cast<TQuantity>(count) > cre->getCount();
}
return hasExtraCreatures || slotsCount < army->Slots().size();
return army->hasUnits(q->mission.creatures, true);
}
bool CQuest::checkQuest(const CGHeroInstance * h) const

View File

@@ -2429,6 +2429,7 @@ EQuestMission CMapLoaderH3M::readQuest(IQuestObject * guard, const int3 & positi
{
size_t typeNumber = reader->readUInt8();
guard->getQuest().mission.creatures.resize(typeNumber);
guard->getQuest().mission.hasExtraCreatures = true;
for(size_t hh = 0; hh < typeNumber; ++hh)
{
guard->getQuest().mission.creatures[hh].setType(reader->readCreature().toCreature());

View File

@@ -86,30 +86,9 @@ bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
return false;
}
bool foundExtraCreatures = false;
int testedSlots = 0;
for(const auto & reqStack : creatures)
if (!creatures.empty())
{
size_t count = 0;
for(const auto & slot : hero->Slots())
{
const auto & heroStack = slot.second;
if (heroStack->getType() == reqStack.getType())
{
count += heroStack->getCount();
testedSlots += 1;
}
}
if (count > reqStack.getCount())
foundExtraCreatures = true;
if (count < reqStack.getCount()) //not enough creatures of this kind
return false;
}
if (hasExtraCreatures)
{
if (!foundExtraCreatures && testedSlots >= hero->Slots().size())
if (!hero->hasUnits(creatures, hasExtraCreatures))
return false;
}