mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Reorganized artifact-related classes
- files now generally contain only 1 class (except for tightly coupled classes) - files are now located in lib/entities/artifact directory - removed excessive includes No changes to functionality
This commit is contained in:
377
lib/entities/artifact/CArtifactSet.cpp
Normal file
377
lib/entities/artifact/CArtifactSet.cpp
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* CArtifactSet.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 "CArtifactSet.h"
|
||||
|
||||
#include "CArtifact.h"
|
||||
#include "ArtifactUtils.h"
|
||||
|
||||
#include "../../constants/StringConstants.h"
|
||||
#include "../../gameState/CGameState.h"
|
||||
#include "../../mapping/CMap.h"
|
||||
#include "../../serializer/JsonSerializeFormat.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
const CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, bool excludeLocked) const
|
||||
{
|
||||
if(const ArtSlotInfo * si = getSlot(pos))
|
||||
{
|
||||
if(si->getArt() && (!excludeLocked || !si->locked))
|
||||
return si->getArt();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ArtifactInstanceID CArtifactSet::getArtID(const ArtifactPosition & pos, bool excludeLocked) const
|
||||
{
|
||||
if(const ArtSlotInfo * si = getSlot(pos))
|
||||
{
|
||||
if(si->getArt() && (!excludeLocked || !si->locked))
|
||||
return si->getArt()->getId();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ArtifactPosition CArtifactSet::getArtPos(const ArtifactID & aid, bool onlyWorn, bool allowLocked) const
|
||||
{
|
||||
for(const auto & [slot, slotInfo] : artifactsWorn)
|
||||
{
|
||||
if(slotInfo.getArt()->getTypeId() == aid && (allowLocked || !slotInfo.locked))
|
||||
return slot;
|
||||
}
|
||||
if(!onlyWorn)
|
||||
{
|
||||
size_t backpackPositionIdx = ArtifactPosition::BACKPACK_START;
|
||||
for(const auto & artInfo : artifactsInBackpack)
|
||||
{
|
||||
const auto art = artInfo.getArt();
|
||||
if(art && art->getType()->getId() == aid)
|
||||
return ArtifactPosition(backpackPositionIdx);
|
||||
backpackPositionIdx++;
|
||||
}
|
||||
}
|
||||
return ArtifactPosition::PRE_FIRST;
|
||||
}
|
||||
|
||||
const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanceID & artInstId) const
|
||||
{
|
||||
for(const auto & i : artifactsWorn)
|
||||
if(i.second.getArt()->getId() == artInstId)
|
||||
return i.second.getArt();
|
||||
|
||||
for(const auto & i : artifactsInBackpack)
|
||||
if(i.getArt()->getId() == artInstId)
|
||||
return i.getArt();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance * artInst) const
|
||||
{
|
||||
if(artInst)
|
||||
{
|
||||
for(const auto & slot : artInst->getType()->getPossibleSlots().at(bearerType()))
|
||||
if(getArt(slot) == artInst)
|
||||
return slot;
|
||||
|
||||
ArtifactPosition backpackSlot = ArtifactPosition::BACKPACK_START;
|
||||
for(auto & slotInfo : artifactsInBackpack)
|
||||
{
|
||||
if(slotInfo.getArt() == artInst)
|
||||
return backpackSlot;
|
||||
backpackSlot = ArtifactPosition(backpackSlot + 1);
|
||||
}
|
||||
}
|
||||
return ArtifactPosition::PRE_FIRST;
|
||||
}
|
||||
|
||||
bool CArtifactSet::hasArt(const ArtifactID & aid, bool onlyWorn, bool searchCombinedParts) const
|
||||
{
|
||||
if(searchCombinedParts && getCombinedArtWithPart(aid))
|
||||
return true;
|
||||
if(getArtPos(aid, onlyWorn, searchCombinedParts) != ArtifactPosition::PRE_FIRST)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(const ArtifactPosition & slot, const CArtifactInstance * art)
|
||||
{
|
||||
ArtPlacementMap resArtPlacement;
|
||||
const auto putToSlot = [this](const ArtifactPosition & targetSlot, const CArtifactInstance * targetArt, bool locked)
|
||||
{
|
||||
ArtSlotInfo newSlot(targetArt, locked);
|
||||
|
||||
if(targetSlot == ArtifactPosition::TRANSITION_POS)
|
||||
{
|
||||
artifactsTransitionPos = newSlot;
|
||||
}
|
||||
else if(ArtifactUtils::isSlotEquipment(targetSlot))
|
||||
{
|
||||
artifactsWorn.insert_or_assign(targetSlot, newSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto position = artifactsInBackpack.begin() + targetSlot - ArtifactPosition::BACKPACK_START;
|
||||
artifactsInBackpack.insert(position, newSlot);
|
||||
}
|
||||
};
|
||||
|
||||
putToSlot(slot, art, false);
|
||||
if(art->getType()->isCombined() && ArtifactUtils::isSlotEquipment(slot))
|
||||
{
|
||||
const CArtifactInstance * mainPart = nullptr;
|
||||
for(const auto & part : art->getPartsInfo())
|
||||
if(vstd::contains(part.getArtifact()->getType()->getPossibleSlots().at(bearerType()), slot)
|
||||
&& (part.slot == ArtifactPosition::PRE_FIRST))
|
||||
{
|
||||
mainPart = part.getArtifact();
|
||||
break;
|
||||
}
|
||||
|
||||
for(const auto & part : art->getPartsInfo())
|
||||
{
|
||||
if(part.getArtifact() != mainPart)
|
||||
{
|
||||
auto partSlot = part.slot;
|
||||
if(!part.getArtifact()->getType()->canBePutAt(this, partSlot))
|
||||
partSlot = ArtifactUtils::getArtAnyPosition(this, part.getArtifact()->getTypeId());
|
||||
|
||||
assert(ArtifactUtils::isSlotEquipment(partSlot));
|
||||
putToSlot(partSlot, part.getArtifact(), true);
|
||||
resArtPlacement.emplace(part.getArtifact(), partSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
resArtPlacement.emplace(part.getArtifact(), part.slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
return resArtPlacement;
|
||||
}
|
||||
|
||||
CArtifactSet::CArtifactSet(IGameCallback * cb)
|
||||
:artifactsTransitionPos(cb)
|
||||
{}
|
||||
|
||||
void CArtifactSet::removeArtifact(const ArtifactPosition & slot)
|
||||
{
|
||||
const auto eraseArtSlot = [this](const ArtifactPosition & slotForErase)
|
||||
{
|
||||
if(slotForErase == ArtifactPosition::TRANSITION_POS)
|
||||
{
|
||||
artifactsTransitionPos.artifactID = {};
|
||||
}
|
||||
else if(ArtifactUtils::isSlotBackpack(slotForErase))
|
||||
{
|
||||
auto backpackSlot = ArtifactPosition(slotForErase - ArtifactPosition::BACKPACK_START);
|
||||
|
||||
assert(artifactsInBackpack.begin() + backpackSlot < artifactsInBackpack.end());
|
||||
artifactsInBackpack.erase(artifactsInBackpack.begin() + backpackSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
artifactsWorn.erase(slotForErase);
|
||||
}
|
||||
};
|
||||
|
||||
if(const auto art = getArt(slot, false))
|
||||
{
|
||||
if(art->isCombined())
|
||||
{
|
||||
for(const auto & part : art->getPartsInfo())
|
||||
{
|
||||
if(part.slot != ArtifactPosition::PRE_FIRST)
|
||||
{
|
||||
assert(getArt(part.slot, false));
|
||||
assert(getArt(part.slot, false) == part.getArtifact());
|
||||
}
|
||||
eraseArtSlot(part.slot);
|
||||
}
|
||||
}
|
||||
eraseArtSlot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
const CArtifactInstance * CArtifactSet::getCombinedArtWithPart(const ArtifactID & partId) const
|
||||
{
|
||||
for(const auto & slot : artifactsInBackpack)
|
||||
{
|
||||
auto art = slot.getArt();
|
||||
if(art->isCombined())
|
||||
{
|
||||
for(auto & ci : art->getPartsInfo())
|
||||
{
|
||||
if(ci.getArtifact()->getTypeId() == partId)
|
||||
return art;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const
|
||||
{
|
||||
if(pos == ArtifactPosition::TRANSITION_POS)
|
||||
return &artifactsTransitionPos;
|
||||
if(vstd::contains(artifactsWorn, pos))
|
||||
return &artifactsWorn.at(pos);
|
||||
if(ArtifactUtils::isSlotBackpack(pos))
|
||||
{
|
||||
auto backpackPos = pos - ArtifactPosition::BACKPACK_START;
|
||||
if(backpackPos < 0 || backpackPos >= artifactsInBackpack.size())
|
||||
return nullptr;
|
||||
else
|
||||
return &artifactsInBackpack[backpackPos];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CArtifactSet::lockSlot(const ArtifactPosition & pos)
|
||||
{
|
||||
if(pos == ArtifactPosition::TRANSITION_POS)
|
||||
artifactsTransitionPos.locked = true;
|
||||
else if(ArtifactUtils::isSlotEquipment(pos))
|
||||
artifactsWorn.at(pos).locked = true;
|
||||
else
|
||||
{
|
||||
assert(artifactsInBackpack.size() > pos - ArtifactPosition::BACKPACK_START);
|
||||
(artifactsInBackpack.begin() + pos - ArtifactPosition::BACKPACK_START)->locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const
|
||||
{
|
||||
if(bearerType() == ArtBearer::ALTAR)
|
||||
return artifactsInBackpack.size() < GameConstants::ALTAR_ARTIFACTS_SLOTS;
|
||||
|
||||
if(const ArtSlotInfo *s = getSlot(pos))
|
||||
return (onlyLockCheck || !s->getArt()) && !s->locked;
|
||||
|
||||
return true; //no slot means not used
|
||||
}
|
||||
|
||||
void CArtifactSet::artDeserializationFix(CGameState & gs, CBonusSystemNode *node)
|
||||
{
|
||||
for(auto & elem : artifactsWorn)
|
||||
if(elem.second.artifactID.hasValue() && !elem.second.locked)
|
||||
node->attachToSource(*gs.getArtInstance(elem.second.artifactID));
|
||||
}
|
||||
|
||||
void CArtifactSet::serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map)
|
||||
{
|
||||
//todo: creature and commander artifacts
|
||||
if(handler.saving && artifactsInBackpack.empty() && artifactsWorn.empty())
|
||||
return;
|
||||
|
||||
if(!handler.saving)
|
||||
{
|
||||
artifactsInBackpack.clear();
|
||||
artifactsWorn.clear();
|
||||
}
|
||||
|
||||
auto s = handler.enterStruct(fieldName);
|
||||
|
||||
switch(bearerType())
|
||||
{
|
||||
case ArtBearer::HERO:
|
||||
serializeJsonHero(handler, map);
|
||||
break;
|
||||
case ArtBearer::CREATURE:
|
||||
serializeJsonCreature(handler);
|
||||
break;
|
||||
case ArtBearer::COMMANDER:
|
||||
serializeJsonCommander(handler);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CArtifactSet::serializeJsonHero(JsonSerializeFormat & handler, CMap * map)
|
||||
{
|
||||
for(const auto & slot : ArtifactUtils::allWornSlots())
|
||||
{
|
||||
serializeJsonSlot(handler, slot, map);
|
||||
}
|
||||
|
||||
std::vector<ArtifactID> backpackTemp;
|
||||
|
||||
if(handler.saving)
|
||||
{
|
||||
backpackTemp.reserve(artifactsInBackpack.size());
|
||||
for(const ArtSlotInfo & info : artifactsInBackpack)
|
||||
backpackTemp.push_back(info.getArt()->getTypeId());
|
||||
}
|
||||
handler.serializeIdArray(NArtifactPosition::backpack, backpackTemp);
|
||||
if(!handler.saving)
|
||||
{
|
||||
for(const ArtifactID & artifactID : backpackTemp)
|
||||
{
|
||||
auto * artifact = map->createArtifact(artifactID);
|
||||
auto slot = ArtifactPosition::BACKPACK_START + artifactsInBackpack.size();
|
||||
if(artifact->getType()->canBePutAt(this, slot))
|
||||
{
|
||||
auto artsMap = putArtifact(slot, artifact);
|
||||
artifact->addPlacementMap(artsMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CArtifactSet::serializeJsonCreature(JsonSerializeFormat & handler)
|
||||
{
|
||||
logGlobal->error("CArtifactSet::serializeJsonCreature not implemented");
|
||||
}
|
||||
|
||||
void CArtifactSet::serializeJsonCommander(JsonSerializeFormat & handler)
|
||||
{
|
||||
logGlobal->error("CArtifactSet::serializeJsonCommander not implemented");
|
||||
}
|
||||
|
||||
void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const ArtifactPosition & slot, CMap * map)
|
||||
{
|
||||
ArtifactID artifactID;
|
||||
|
||||
if(handler.saving)
|
||||
{
|
||||
const ArtSlotInfo * info = getSlot(slot);
|
||||
|
||||
if(info != nullptr && !info->locked)
|
||||
{
|
||||
artifactID = info->getArt()->getTypeId();
|
||||
handler.serializeId(NArtifactPosition::namesHero[slot.num], artifactID, ArtifactID::NONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handler.serializeId(NArtifactPosition::namesHero[slot.num], artifactID, ArtifactID::NONE);
|
||||
|
||||
if(artifactID != ArtifactID::NONE)
|
||||
{
|
||||
auto * artifact = map->createArtifact(artifactID.toEnum());
|
||||
|
||||
if(artifact->getType()->canBePutAt(this, slot))
|
||||
{
|
||||
auto artsMap = putArtifact(slot, artifact);
|
||||
artifact->addPlacementMap(artsMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->debug("Artifact can't be put at the specified location."); //TODO add more debugging information
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
Reference in New Issue
Block a user