From d4d3ddf6850ddc945728577ff1a65af38605a291 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sat, 12 Oct 2024 13:33:46 +0300 Subject: [PATCH] fused artifacts --- client/ArtifactsUIController.cpp | 2 +- .../Entities_Format/Artifact_Format.md | 3 +++ lib/CArtHandler.cpp | 23 ++++++++++++++++--- lib/CArtHandler.h | 7 +++++- lib/CArtifactInstance.cpp | 5 ++++ lib/CArtifactInstance.h | 1 + lib/networkPacks/NetPacksLib.cpp | 16 ++++++++----- lib/networkPacks/PacksForClient.h | 6 ++--- server/CGameHandler.cpp | 5 +++- 9 files changed, 53 insertions(+), 15 deletions(-) diff --git a/client/ArtifactsUIController.cpp b/client/ArtifactsUIController.cpp index 73461a58a..30374ebc2 100644 --- a/client/ArtifactsUIController.cpp +++ b/client/ArtifactsUIController.cpp @@ -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; diff --git a/docs/modders/Entities_Format/Artifact_Format.md b/docs/modders/Entities_Format/Artifact_Format.md index 928496dc7..83b1adca2 100644 --- a/docs/modders/Entities_Format/Artifact_Format.md +++ b/docs/modders/Entities_Format/Artifact_Format.md @@ -67,6 +67,9 @@ In order to make functional artifact you also need: "artifact2", "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" diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 07b83dec3..f96e17f83 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -61,6 +61,21 @@ const std::vector & 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(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) diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index e82f43147..f0bf7d8af 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -46,14 +46,19 @@ namespace ArtBearer class DLL_LINKAGE CCombinedArtifact { protected: - CCombinedArtifact() = default; + CCombinedArtifact() : fused(false) {}; std::vector constituents; // Artifacts IDs a combined artifact consists of, or nullptr. std::vector partOf; // Reverse map of constituents - combined arts that include this art + bool fused; + public: bool isCombined() const; const std::vector & getConstituents() const; const std::vector & getPartOf() const; + void setFused(bool isFused); + bool isFused() const; + bool hasParts() const; }; class DLL_LINKAGE CScrollArtifact diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index 6f191e46b..f65e6d95b 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -44,6 +44,11 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c return false; } +bool CCombinedArtifactInstance::hasParts() const +{ + return !partsInfo.empty(); +} + const std::vector & CCombinedArtifactInstance::getPartsInfo() const { return partsInfo; diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h index f679f8b44..6ff0bdbe0 100644 --- a/lib/CArtifactInstance.h +++ b/lib/CArtifactInstance.h @@ -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 & getPartsInfo() const; void addPlacementMap(const CArtifactSet::ArtPlacementMap & placementMap); diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 6ea83ab8f..f44e6411e 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -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,15 +1856,18 @@ 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(ArtifactUtils::isSlotEquipment(al.slot) && slot != al.slot) - combinedArt->addPart(constituentInstance, slot); - else - combinedArt->addPart(constituentInstance, ArtifactPosition::PRE_FIRST); + 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 diff --git a/lib/networkPacks/PacksForClient.h b/lib/networkPacks/PacksForClient.h index b9f678ba6..0413113dc 100644 --- a/lib/networkPacks/PacksForClient.h +++ b/lib/networkPacks/PacksForClient.h @@ -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 void serialize(Handler & h) { h & al; - h & builtArt; + h & artId; } }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 1f9549fa0..ab933a4f8 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -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!");