1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-15 00:05:02 +02:00

Switching costume

This commit is contained in:
SoundSSGood
2024-04-19 17:14:41 +03:00
parent 25dea7e364
commit ce9d2d8ab8
17 changed files with 154 additions and 115 deletions

View File

@ -2896,20 +2896,74 @@ bool CGameHandler::saveArtifactsCostume(const PlayerColor & player, const Object
{
auto artSet = getArtSet(heroID);
COMPLAIN_RET_FALSE_IF(artSet == nullptr, "saveArtifactsCostume: wrong hero's ID");
COMPLAIN_RET_FALSE_IF(costumeIdx >= GameConstants::HERO_COSTUMES_ARTIFACTS, "saveArtifactsCostume: wrong costume index");
ChangeArtifactsCostume costume(player, costumeIdx);
for(const auto & slot : ArtifactUtils::constituentWornSlots())
for(const auto & slot : ArtifactUtils::commonWornSlots())
{
if(const auto & slotInfo = artSet->getSlot(slot))
if(!slotInfo->locked)
costume.costumeSet.emplace(slot, slotInfo->getArt()->getTypeId());
if(const auto slotInfo = artSet->getSlot(slot); slotInfo != nullptr && !slotInfo->locked)
costume.costumeSet.emplace(slot, slotInfo->getArt()->getTypeId());
}
sendAndApply(&costume);
return true;
}
bool CGameHandler::switchArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx)
{
const auto artSet = getArtSet(heroID);
COMPLAIN_RET_FALSE_IF(artSet == nullptr, "switchArtifactsCostume: wrong hero's ID");
const auto playerState = getPlayerState(player);
COMPLAIN_RET_FALSE_IF(playerState == nullptr, "switchArtifactsCostume: wrong player");
if(auto costume = playerState->costumesArtifacts.find(costumeIdx); costume != playerState->costumesArtifacts.end())
{
CArtifactFittingSet artFittingSet(*artSet);
BulkMoveArtifacts bma(player, heroID, heroID, false);
auto costumeArtMap = costume->second;
auto estimateBackpackSize = artSet->artifactsInBackpack.size();
// First, find those artifacts that are already in place
for(const auto & slot : ArtifactUtils::commonWornSlots())
{
if(const auto * slotInfo = artFittingSet.getSlot(slot); slotInfo != nullptr && !slotInfo->locked)
if(const auto artPos = costumeArtMap.find(slot); artPos != costumeArtMap.end() && artPos->second == slotInfo->getArt()->getTypeId())
{
costumeArtMap.erase(artPos);
artFittingSet.removeArtifact(slot);
}
}
// Second, find the necessary artifacts for the costume
for(const auto & artPos : costumeArtMap)
{
if(const auto availableArts = artFittingSet.getAllArtPositions(artPos.second, false, false, false); !availableArts.empty())
{
bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots
{
artSet->getSlotByInstance(artFittingSet.getArt(availableArts.front())),
artPos.first
});
artFittingSet.removeArtifact(availableArts.front());
if(ArtifactUtils::isSlotBackpack(availableArts.front()))
estimateBackpackSize--;
}
}
// Third, put unnecessary artifacts into backpack
for(const auto & slot : ArtifactUtils::commonWornSlots())
if(artFittingSet.getArt(slot))
{
bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots{slot, ArtifactPosition::BACKPACK_START});
estimateBackpackSize++;
}
const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
if((backpackCap < 0 || estimateBackpackSize <= backpackCap) && !bma.artsPack0.empty())
sendAndApply(&bma);
}
return true;
}
/**
* Assembles or disassembles a combination artifact.
* @param heroID ID of hero holding the artifact(s).