1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00

fused artifacts

This commit is contained in:
SoundSSGood 2024-10-12 13:33:46 +03:00
parent 5d2f3c0f86
commit d4d3ddf685
9 changed files with 53 additions and 15 deletions

View File

@ -102,7 +102,7 @@ bool ArtifactsUIController::askToDisassemble(const CGHeroInstance * hero, const
if(hero->tempOwner != LOCPLINT->playerID)
return false;
if(art->isCombined())
if(art->hasParts())
{
if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->getConstituents().size() - 1))
return false;

View File

@ -68,6 +68,9 @@ In order to make functional artifact you also need:
"artifact3"
],
// Optional, by default is false. Set to true if components are supposed to be fused.
"fusedComponents" : true,
// Creature id to use on battle field. If set, this artifact is war machine
"warMachine" : "some.creature"

View File

@ -61,6 +61,21 @@ const std::vector<const CArtifact*> & CCombinedArtifact::getPartOf() const
return partOf;
}
void CCombinedArtifact::setFused(bool isFused)
{
fused = isFused;
}
bool CCombinedArtifact::isFused() const
{
return fused;
}
bool CCombinedArtifact::hasParts() const
{
return isCombined() && !isFused();
}
bool CScrollArtifact::isScroll() const
{
return static_cast<const CArtifact*>(this)->getId() == ArtifactID::SPELL_SCROLL;
@ -203,7 +218,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b
auto artCanBePutAt = [this, simpleArtCanBePutAt](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
{
if(isCombined())
if(hasParts())
{
if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved))
return false;
@ -606,11 +621,11 @@ void CArtHandler::loadType(CArtifact * art, const JsonNode & node) const
void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node)
{
if (!node["components"].isNull())
if(!node["components"].isNull())
{
for(const auto & component : node["components"].Vector())
{
VLC->identifiers()->requestIdentifier("artifact", component, [=](si32 id)
VLC->identifiers()->requestIdentifier("artifact", component, [this, art](int32_t id)
{
// when this code is called both combinational art as well as component are loaded
// so it is safe to access any of them
@ -619,6 +634,8 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node)
});
}
}
if(!node["fusedComponents"].isNull())
art->setFused(node["fusedComponents"].Bool());
}
void CArtHandler::makeItCreatureArt(CArtifact * a, bool onlyCreature)

View File

@ -46,14 +46,19 @@ namespace ArtBearer
class DLL_LINKAGE CCombinedArtifact
{
protected:
CCombinedArtifact() = default;
CCombinedArtifact() : fused(false) {};
std::vector<const CArtifact*> constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
std::vector<const CArtifact*> partOf; // Reverse map of constituents - combined arts that include this art
bool fused;
public:
bool isCombined() const;
const std::vector<const CArtifact*> & getConstituents() const;
const std::vector<const CArtifact*> & getPartOf() const;
void setFused(bool isFused);
bool isFused() const;
bool hasParts() const;
};
class DLL_LINKAGE CScrollArtifact

View File

@ -44,6 +44,11 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c
return false;
}
bool CCombinedArtifactInstance::hasParts() const
{
return !partsInfo.empty();
}
const std::vector<CCombinedArtifactInstance::PartInfo> & CCombinedArtifactInstance::getPartsInfo() const
{
return partsInfo;

View File

@ -38,6 +38,7 @@ public:
void addPart(CArtifactInstance * art, const ArtifactPosition & slot);
// Checks if supposed part inst is part of this combined art inst
bool isPart(const CArtifactInstance * supposedPart) const;
bool hasParts() const;
const std::vector<PartInfo> & getPartsInfo() const;
void addPlacementMap(const CArtifactSet::ArtPlacementMap & placementMap);

View File

@ -1806,6 +1806,7 @@ void AssembledArtifact::applyGs(CGameState *gs)
assert(hero);
const auto transformedArt = hero->getArt(al.slot);
assert(transformedArt);
const auto builtArt = artId.toArtifact();
assert(vstd::contains_if(ArtifactUtils::assemblyPossibilities(hero, transformedArt->getTypeId()), [=](const CArtifact * art)->bool
{
return art->getId() == builtArt->getId();
@ -1832,7 +1833,7 @@ void AssembledArtifact::applyGs(CGameState *gs)
// Find a slot for combined artifact
al.slot = transformedArtSlot;
for(const auto slot : slotsInvolved)
for(const auto & slot : slotsInvolved)
{
if(ArtifactUtils::isSlotEquipment(transformedArtSlot))
{
@ -1855,16 +1856,19 @@ void AssembledArtifact::applyGs(CGameState *gs)
}
// Delete parts from hero
for(const auto slot : slotsInvolved)
for(const auto & slot : slotsInvolved)
{
const auto constituentInstance = hero->getArt(slot);
gs->map->removeArtifactInstance(*hero, slot);
if(!combinedArt->artType->isFused())
{
if(ArtifactUtils::isSlotEquipment(al.slot) && slot != al.slot)
combinedArt->addPart(constituentInstance, slot);
else
combinedArt->addPart(constituentInstance, ArtifactPosition::PRE_FIRST);
}
}
// Put new combined artifacts
gs->map->putArtifactInstance(*hero, combinedArt, al.slot);

View File

@ -1108,8 +1108,8 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
struct DLL_LINKAGE AssembledArtifact : CArtifactOperationPack
{
ArtifactLocation al; //where assembly will be put
const CArtifact * builtArt;
ArtifactLocation al;
ArtifactID artId;
void applyGs(CGameState * gs) override;
@ -1118,7 +1118,7 @@ struct DLL_LINKAGE AssembledArtifact : CArtifactOperationPack
template <typename Handler> void serialize(Handler & h)
{
h & al;
h & builtArt;
h & artId;
}
};

View File

@ -2913,7 +2913,7 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a
AssembledArtifact aa;
aa.al = dstLoc;
aa.builtArt = combinedArt;
aa.artId = assembleTo;
sendAndApply(aa);
}
else
@ -2921,6 +2921,9 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a
if(!destArtifact->isCombined())
COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble is not a combined artifact!");
if(!destArtifact->hasParts())
COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble is fused combined artifact!");
if(ArtifactUtils::isSlotBackpack(artifactSlot)
&& !ArtifactUtils::isBackpackFreeSlots(hero, destArtifact->artType->getConstituents().size() - 1))
COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble but backpack is full!");