/* * CArtifact.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 "CArtifact.h" #include "ArtifactUtils.h" #include "CArtifactFittingSet.h" #include "../../texts/CGeneralTextHandler.h" #include "../../GameLibrary.h" VCMI_LIB_NAMESPACE_BEGIN bool CCombinedArtifact::isCombined() const { return !(constituents.empty()); } const std::vector & CCombinedArtifact::getConstituents() const { return constituents; } const std::set & 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; } bool CGrowingArtifact::isGrowing() const { return !bonusesPerLevel.empty() || !thresholdBonuses.empty(); } std::vector >> & CGrowingArtifact::getBonusesPerLevel() { return bonusesPerLevel; } const std::vector >> & CGrowingArtifact::getBonusesPerLevel() const { return bonusesPerLevel; } std::vector >> & CGrowingArtifact::getThresholdBonuses() { return thresholdBonuses; } const std::vector >> & CGrowingArtifact::getThresholdBonuses() const { return thresholdBonuses; } int32_t CArtifact::getIndex() const { return id.toEnum(); } int32_t CArtifact::getIconIndex() const { return iconIndex; } std::string CArtifact::getJsonKey() const { return modScope + ':' + identifier; } std::string CArtifact::getModScope() const { return modScope; } void CArtifact::registerIcons(const IconRegistar & cb) const { cb(getIconIndex(), 0, "ARTIFACT", image); } ArtifactID CArtifact::getId() const { return id; } const IBonusBearer * CArtifact::getBonusBearer() const { return this; } std::string CArtifact::getDescriptionTranslated() const { return LIBRARY->generaltexth->translate(getDescriptionTextID()); } std::string CArtifact::getEventTranslated() const { return LIBRARY->generaltexth->translate(getEventTextID()); } std::string CArtifact::getNameTranslated() const { return LIBRARY->generaltexth->translate(getNameTextID()); } std::string CArtifact::getDescriptionTextID() const { return TextIdentifier("artifact", modScope, identifier, "description").get(); } std::string CArtifact::getEventTextID() const { return TextIdentifier("artifact", modScope, identifier, "event").get(); } std::string CArtifact::getNameTextID() const { return TextIdentifier("artifact", modScope, identifier, "name").get(); } std::string CArtifact::getBonusTextID(const std::string & bonusID) const { return TextIdentifier("artifact", modScope, identifier, "bonus", bonusID).get(); } uint32_t CArtifact::getPrice() const { return price; } CreatureID CArtifact::getWarMachine() const { return warMachine; } bool CArtifact::isBig() const { return warMachine != CreatureID::NONE; } bool CArtifact::isTradable() const { switch(id.toEnum()) { case ArtifactID::SPELLBOOK: return false; default: return !isBig(); } } bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) const { auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool { if(artSet->bearerType() == ArtBearer::HERO && ArtifactUtils::isSlotBackpack(slot)) { if(isBig() || (!assumeDestRemoved && !ArtifactUtils::isBackpackFreeSlots(artSet))) return false; return true; } if(!vstd::contains(possibleSlots.at(artSet->bearerType()), slot)) return false; return artSet->isPositionFree(slot, assumeDestRemoved); }; auto artCanBePutAt = [this, simpleArtCanBePutAt](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool { if(hasParts()) { if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved)) return false; if(ArtifactUtils::isSlotBackpack(slot)) return true; CArtifactFittingSet fittingSet(artSet->getCallback(), artSet->bearerType()); fittingSet.artifactsWorn = artSet->artifactsWorn; if(assumeDestRemoved) fittingSet.removeArtifact(slot); for(const auto art : constituents) { auto possibleSlot = ArtifactUtils::getArtAnyPosition(&fittingSet, art->getId()); if(ArtifactUtils::isSlotEquipment(possibleSlot)) { if (fittingSet.getSlot(possibleSlot) == nullptr) fittingSet.artifactsWorn.insert(std::make_pair(possibleSlot, ArtSlotInfo(fittingSet.cb))); fittingSet.lockSlot(possibleSlot); } else { return false; } } return true; } else { return simpleArtCanBePutAt(artSet, slot, assumeDestRemoved); } }; if(slot == ArtifactPosition::TRANSITION_POS) return true; if(slot == ArtifactPosition::FIRST_AVAILABLE) { for(const auto & possibleSlot : possibleSlots.at(artSet->bearerType())) { if(artCanBePutAt(artSet, possibleSlot, assumeDestRemoved)) return true; } return artCanBePutAt(artSet, ArtifactPosition::BACKPACK_START, assumeDestRemoved); } else if(ArtifactUtils::isSlotBackpack(slot)) { return artCanBePutAt(artSet, ArtifactPosition::BACKPACK_START, assumeDestRemoved); } else { return artCanBePutAt(artSet, slot, assumeDestRemoved); } } CChargedArtifact::CChargedArtifact() : condition(DischargeArtifactCondition::NONE) , removeOnDepletion(false) , defaultStartCharges(0) { } bool CChargedArtifact::isCharged() const { return condition != DischargeArtifactCondition::NONE; } void CChargedArtifact::setCondition(const DischargeArtifactCondition & dischargeCondition) { condition = dischargeCondition; } void CChargedArtifact::setRemoveOnDepletion(const bool remove) { removeOnDepletion = remove; } void CChargedArtifact::setDefaultStartCharges(const uint16_t charges) { defaultStartCharges = charges; } uint16_t CChargedArtifact::getDefaultStartCharges() const { return defaultStartCharges; } DischargeArtifactCondition CChargedArtifact::getDischargeCondition() const { return condition; } bool CChargedArtifact::getRemoveOnDepletion() const { return removeOnDepletion; } CArtifact::CArtifact() : iconIndex(ArtifactID::NONE), price(0) { setNodeType(ARTIFACT); possibleSlots[ArtBearer::HERO]; //we want to generate map entry even if it will be empty possibleSlots[ArtBearer::CREATURE]; //we want to generate map entry even if it will be empty possibleSlots[ArtBearer::COMMANDER]; possibleSlots[ArtBearer::ALTAR]; } //This destructor should be placed here to avoid side effects CArtifact::~CArtifact() = default; int CArtifact::getArtClassSerial() const { if(id == ArtifactID::SPELL_SCROLL) return 4; switch(aClass) { case EArtifactClass::ART_TREASURE: return 0; case EArtifactClass::ART_MINOR: return 1; case EArtifactClass::ART_MAJOR: return 2; case EArtifactClass::ART_RELIC: return 3; case EArtifactClass::ART_SPECIAL: return 5; } return -1; } std::string CArtifact::nodeName() const { return "Artifact: " + getNameTranslated(); } void CArtifact::addNewBonus(const std::shared_ptr& b) { b->source = BonusSource::ARTIFACT; b->duration = BonusDuration::PERMANENT; if (b->description.empty() && (b->type == BonusType::LUCK || b->type == BonusType::MORALE)) { b->description.appendTextID(getNameTextID()); b->description.appendRawString(" %+d"); } CBonusSystemNode::addNewBonus(b); } const std::map> & CArtifact::getPossibleSlots() const { return possibleSlots; } void CArtifact::updateFrom(const JsonNode& data) { //TODO:CArtifact::updateFrom } void CArtifact::setImage(int32_t newIconIndex, const std::string & newImage, const std::string & newLargeImage) { iconIndex = newIconIndex; image = newImage; scenarioBonus = newLargeImage; } VCMI_LIB_NAMESPACE_END