mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Complete solution for artifact equip & exchange.
This commit is contained in:
parent
b3f482b8a8
commit
d32461d9d1
100
AI/VCAI/VCAI.cpp
100
AI/VCAI/VCAI.cpp
@ -989,63 +989,97 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance *
|
||||
|
||||
void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other)
|
||||
{
|
||||
std::vector<ArtifactLocation> allArtifacts;
|
||||
auto equipBest = [](const CGHeroInstance * h, const CGHeroInstance * otherh, bool giveStuffToFirstHero) -> void
|
||||
{
|
||||
bool changeMade = false;
|
||||
|
||||
do
|
||||
{
|
||||
changeMade = false;
|
||||
|
||||
//we collect gear always in same order
|
||||
std::vector<ArtifactLocation> allArtifacts;
|
||||
if (giveStuffToFirstHero)
|
||||
{
|
||||
for (auto p : h->artifactsWorn)
|
||||
{
|
||||
if (p.second.artifact)
|
||||
allArtifacts.push_back(ArtifactLocation(h, p.first));
|
||||
}
|
||||
}
|
||||
for (auto slot : h->artifactsInBackpack)
|
||||
allArtifacts.push_back(ArtifactLocation(h, h->getArtPos(slot.artifact)));
|
||||
|
||||
if (other)
|
||||
if (otherh)
|
||||
{
|
||||
for (auto p : other->artifactsWorn)
|
||||
for (auto p : otherh->artifactsWorn)
|
||||
{
|
||||
if (p.second.artifact)
|
||||
allArtifacts.push_back(ArtifactLocation(other, p.first));
|
||||
allArtifacts.push_back(ArtifactLocation(otherh, p.first));
|
||||
}
|
||||
for (auto slot : other->artifactsInBackpack)
|
||||
allArtifacts.push_back(ArtifactLocation(other, other->getArtPos(slot.artifact)));
|
||||
for (auto slot : otherh->artifactsInBackpack)
|
||||
allArtifacts.push_back(ArtifactLocation(otherh, otherh->getArtPos(slot.artifact)));
|
||||
}
|
||||
//we give stuff to one hero or another, depending on giveStuffToFirstHero
|
||||
|
||||
const CGHeroInstance * target = nullptr;
|
||||
if (giveStuffToFirstHero)
|
||||
target = h;
|
||||
else
|
||||
target = otherh;
|
||||
|
||||
for (auto location : allArtifacts)
|
||||
{
|
||||
auto artifact = location.getSlot()->artifact;
|
||||
auto otherSlot = h->getSlot(artifact->firstAvailableSlot(h));
|
||||
if (otherSlot && otherSlot->artifact)
|
||||
if (compareArtifacts (artifact, otherSlot->artifact)) //if that artifact is better than what we have, pick it
|
||||
cb->swapArtifacts (location, ArtifactLocation(h, h->getArtPos(otherSlot->artifact)));
|
||||
if (location.relatedObj() == target && location.slot < ArtifactPosition::AFTER_LAST)
|
||||
continue; //don't reequip artifact we already wear
|
||||
|
||||
auto s = location.getSlot();
|
||||
if (!s)
|
||||
continue;
|
||||
auto artifact = s->artifact;
|
||||
if (!artifact)
|
||||
continue;
|
||||
//FIXME: why are the above possible to be null?
|
||||
|
||||
bool emptySlotFound = false;
|
||||
for (auto slot : artifact->artType->possibleSlots.at(target->bearerType()))
|
||||
{
|
||||
if (target->isPositionFree(slot))
|
||||
{
|
||||
cb->swapArtifacts(location, ArtifactLocation(target, slot)); //just put into empty slot
|
||||
emptySlotFound = true;
|
||||
changeMade = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (other)
|
||||
{
|
||||
//do not touch artifacts worn by first (main) hero
|
||||
//slots may have moved significantly, just start from scratch
|
||||
allArtifacts.clear();
|
||||
|
||||
for (auto slot : h->artifactsInBackpack)
|
||||
allArtifacts.push_back(ArtifactLocation(h, h->getArtPos(slot.artifact)));
|
||||
|
||||
for (auto p : other->artifactsWorn)
|
||||
{
|
||||
if (p.second.artifact)
|
||||
allArtifacts.push_back(ArtifactLocation(other, p.first));
|
||||
}
|
||||
for (auto slot : other->artifactsInBackpack)
|
||||
allArtifacts.push_back(ArtifactLocation(other, other->getArtPos(slot.artifact)));
|
||||
|
||||
for (auto location : allArtifacts)
|
||||
if (!emptySlotFound) //try to put that atifact in already occupied slot
|
||||
{
|
||||
for (auto slot : artifact->artType->possibleSlots.at(target->bearerType()))
|
||||
{
|
||||
auto otherSlot = target->getSlot(slot);
|
||||
if (otherSlot && otherSlot->artifact) //we need to exchange artifact for better one
|
||||
{
|
||||
auto artifact = location.getSlot()->artifact;
|
||||
auto otherSlot = other->getSlot(artifact->firstAvailableSlot(other));
|
||||
if (otherSlot && otherSlot->artifact)
|
||||
if (compareArtifacts(artifact, otherSlot->artifact)) //if that artifact is better than what we have, pick it
|
||||
cb->swapArtifacts(location, ArtifactLocation(other, other->getArtPos(otherSlot->artifact)));
|
||||
{
|
||||
cb->swapArtifacts(location, ArtifactLocation(target, target->getArtPos(otherSlot->artifact)));
|
||||
break;
|
||||
changeMade = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changeMade)
|
||||
break; //start evaluating artifacts from scratch
|
||||
}
|
||||
} while (changeMade);
|
||||
};
|
||||
|
||||
equipBest (h, other, true);
|
||||
|
||||
if (other)
|
||||
{
|
||||
equipBest(h, other, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user