mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	arts altar - arts holder
This commit is contained in:
		| @@ -20,14 +20,12 @@ | |||||||
| #include "../../lib/networkPacks/ArtifactLocation.h" | #include "../../lib/networkPacks/ArtifactLocation.h" | ||||||
|  |  | ||||||
| CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position) | CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position) | ||||||
| 	: visibleArtSet(ArtBearer::ArtBearer::HERO) |  | ||||||
| { | { | ||||||
| 	init( | 	init( | ||||||
| 		std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), | 		std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2), | ||||||
| 		std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2), | 		std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2), | ||||||
| 		position, | 		position, | ||||||
| 		std::bind(&CArtifactsOfHeroAltar::scrollBackpack, this, _1)); | 		std::bind(&CArtifactsOfHeroAltar::scrollBackpack, this, _1)); | ||||||
| 	pickedArtFromSlot = ArtifactPosition::PRE_FIRST; |  | ||||||
|  |  | ||||||
| 	// The backpack is in the altar window above and to the right | 	// The backpack is in the altar window above and to the right | ||||||
| 	for(auto & slot : backpack) | 	for(auto & slot : backpack) | ||||||
| @@ -41,80 +39,19 @@ CArtifactsOfHeroAltar::~CArtifactsOfHeroAltar() | |||||||
| 	putBackPickedArtifact(); | 	putBackPickedArtifact(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void CArtifactsOfHeroAltar::setHero(const CGHeroInstance * hero) |  | ||||||
| { |  | ||||||
| 	if(hero) |  | ||||||
| 	{ |  | ||||||
| 		visibleArtSet.artifactsWorn = hero->artifactsWorn; |  | ||||||
| 		visibleArtSet.artifactsInBackpack = hero->artifactsInBackpack; |  | ||||||
| 		CArtifactsOfHeroBase::setHero(hero); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void CArtifactsOfHeroAltar::updateWornSlots() |  | ||||||
| { |  | ||||||
| 	for(auto place : artWorn) |  | ||||||
| 		setSlotData(getArtPlace(place.first), place.first, visibleArtSet); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void CArtifactsOfHeroAltar::updateBackpackSlots() |  | ||||||
| { |  | ||||||
| 	for(auto artPlace : backpack) |  | ||||||
| 		setSlotData(getArtPlace(artPlace->slot), artPlace->slot, visibleArtSet); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void CArtifactsOfHeroAltar::scrollBackpack(int offset) | void CArtifactsOfHeroAltar::scrollBackpack(int offset) | ||||||
| { | { | ||||||
| 	CArtifactsOfHeroBase::scrollBackpackForArtSet(offset, visibleArtSet); | 	CArtifactsOfHeroBase::scrollBackpackForArtSet(offset, *curHero); | ||||||
| 	redraw(); | 	redraw(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void CArtifactsOfHeroAltar::pickUpArtifact(CArtPlace & artPlace) | void CArtifactsOfHeroAltar::pickUpArtifact(CArtPlace & artPlace) | ||||||
| { | { | ||||||
| 	if(const auto art = artPlace.getArt()) | 	LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot), | ||||||
| 	{ | 		ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); | ||||||
| 		pickedArtFromSlot = artPlace.slot; |  | ||||||
| 		artPlace.setArtifact(nullptr); |  | ||||||
| 		deleteFromVisible(art); |  | ||||||
| 		if(ArtifactUtils::isSlotBackpack(pickedArtFromSlot)) |  | ||||||
| 			pickedArtFromSlot = curHero->getSlotByInstance(art); |  | ||||||
| 		assert(pickedArtFromSlot != ArtifactPosition::PRE_FIRST); |  | ||||||
| 		LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, pickedArtFromSlot), ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void CArtifactsOfHeroAltar::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc) | void CArtifactsOfHeroAltar::swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc) | ||||||
| { | { | ||||||
| 	LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); | 	LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc); | ||||||
| 	const auto pickedArtInst = curHero->getArt(ArtifactPosition::TRANSITION_POS); |  | ||||||
| 	assert(pickedArtInst); |  | ||||||
| 	visibleArtSet.putArtifact(dstLoc.slot, const_cast<CArtifactInstance*>(pickedArtInst)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void CArtifactsOfHeroAltar::pickedArtMoveToAltar(const ArtifactPosition & slot) |  | ||||||
| { |  | ||||||
| 	if(ArtifactUtils::isSlotBackpack(slot) || ArtifactUtils::isSlotEquipment(slot) || slot == ArtifactPosition::TRANSITION_POS) |  | ||||||
| 	{ |  | ||||||
| 		assert(curHero->getSlot(slot)->getArt()); |  | ||||||
| 		LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, slot), ArtifactLocation(curHero->id, pickedArtFromSlot)); |  | ||||||
| 		pickedArtFromSlot = ArtifactPosition::PRE_FIRST; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void CArtifactsOfHeroAltar::deleteFromVisible(const CArtifactInstance * artInst) |  | ||||||
| { |  | ||||||
| 	const auto slot = visibleArtSet.getSlotByInstance(artInst); |  | ||||||
| 	visibleArtSet.removeArtifact(slot); |  | ||||||
| 	if(ArtifactUtils::isSlotBackpack(slot)) |  | ||||||
| 	{ |  | ||||||
| 		scrollBackpackForArtSet(0, visibleArtSet); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		for(const auto & part : artInst->getPartsInfo()) |  | ||||||
| 		{ |  | ||||||
| 			if(part.slot != ArtifactPosition::PRE_FIRST) |  | ||||||
| 				getArtPlace(part.slot)->setArtifact(nullptr); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -17,17 +17,10 @@ class CArtifactsOfHeroAltar : public CArtifactsOfHeroBase | |||||||
| { | { | ||||||
| public: | public: | ||||||
| 	std::set<const CArtifactInstance*> artifactsOnAltar; | 	std::set<const CArtifactInstance*> artifactsOnAltar; | ||||||
| 	ArtifactPosition pickedArtFromSlot; |  | ||||||
| 	CArtifactFittingSet visibleArtSet; |  | ||||||
|  |  | ||||||
| 	CArtifactsOfHeroAltar(const Point & position); | 	CArtifactsOfHeroAltar(const Point & position); | ||||||
| 	~CArtifactsOfHeroAltar(); | 	~CArtifactsOfHeroAltar(); | ||||||
| 	void setHero(const CGHeroInstance * hero) override; |  | ||||||
| 	void updateWornSlots() override; |  | ||||||
| 	void updateBackpackSlots() override; |  | ||||||
| 	void scrollBackpack(int offset) override; | 	void scrollBackpack(int offset) override; | ||||||
| 	void pickUpArtifact(CArtPlace & artPlace); | 	void pickUpArtifact(CArtPlace & artPlace); | ||||||
| 	void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); | 	void swapArtifacts(const ArtifactLocation & srcLoc, const ArtifactLocation & dstLoc); | ||||||
| 	void pickedArtMoveToAltar(const ArtifactPosition & slot); |  | ||||||
| 	void deleteFromVisible(const CArtifactInstance * artInst); |  | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -31,6 +31,11 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * | |||||||
| { | { | ||||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); | 	OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); | ||||||
|  |  | ||||||
|  | 	assert(market); | ||||||
|  | 	auto altarObj = dynamic_cast<const CGArtifactsAltar*>(market); | ||||||
|  | 	altarId = altarObj->id; | ||||||
|  | 	altarArtifacts = altarObj; | ||||||
|  |  | ||||||
| 	deal = std::make_shared<CButton>(dealButtonPos, AnimationPath::builtin("ALTSACR.DEF"), | 	deal = std::make_shared<CButton>(dealButtonPos, AnimationPath::builtin("ALTSACR.DEF"), | ||||||
| 		CGI->generaltexth->zelp[585], [this]() {CAltarArtifacts::makeDeal(); }); | 		CGI->generaltexth->zelp[585], [this]() {CAltarArtifacts::makeDeal(); }); | ||||||
| 	labels.emplace_back(std::make_shared<CLabel>(450, 34, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477])); | 	labels.emplace_back(std::make_shared<CLabel>(450, 34, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477])); | ||||||
| @@ -117,11 +122,11 @@ void CAltarArtifacts::sacrificeAll() | |||||||
|  |  | ||||||
| void CAltarArtifacts::sacrificeBackpack() | void CAltarArtifacts::sacrificeBackpack() | ||||||
| { | { | ||||||
| 	while(!arts->visibleArtSet.artifactsInBackpack.empty()) | 	/*while (!arts->visibleArtSet.artifactsInBackpack.empty()) | ||||||
| 	{ | 	{ | ||||||
| 		if(!putArtOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact)) | 		if(!putArtOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact)) | ||||||
| 			break; | 			break; | ||||||
| 	}; | 	};*/ | ||||||
| 	calcExpAltarForHero(); | 	calcExpAltarForHero(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -192,20 +197,21 @@ bool CAltarArtifacts::putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, c | |||||||
|  |  | ||||||
| void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot) | void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot) | ||||||
| { | { | ||||||
| 	const auto pickedArtInst = arts->getPickedArtifact(); | 	if(const auto pickedArtInst = arts->getPickedArtifact()) | ||||||
| 	if(pickedArtInst) |  | ||||||
| 	{ | 	{ | ||||||
| 		arts->pickedArtMoveToAltar(ArtifactPosition::TRANSITION_POS); | 		if(pickedArtInst->canBePutAt(altarArtifacts)) | ||||||
| 		moveArtToAltar(newSlot, pickedArtInst); | 		{ | ||||||
|  | 			LOCPLINT->cb->swapArtifacts(ArtifactLocation(arts->getHero()->id, ArtifactPosition::TRANSITION_POS), | ||||||
|  | 			ArtifactLocation(altarId, ArtifactPosition::ALTAR)); | ||||||
|  | 			moveArtToAltar(newSlot, pickedArtInst); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	else if(const CArtifactInstance * art = newSlot->getArtInstance()) | 	else if(const CArtifactInstance * art = newSlot->getArtInstance()) | ||||||
| 	{ | 	{ | ||||||
| 		const auto hero = arts->getHero(); | 		const auto slot = altarArtifacts->getSlotByInstance(art); | ||||||
| 		const auto slot = hero->getSlotByInstance(art); |  | ||||||
| 		assert(slot != ArtifactPosition::PRE_FIRST); | 		assert(slot != ArtifactPosition::PRE_FIRST); | ||||||
| 		LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, slot), | 		LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot), | ||||||
| 			ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS)); | 			ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS)); | ||||||
| 		arts->pickedArtFromSlot = slot; |  | ||||||
| 		arts->artifactsOnAltar.erase(art); | 		arts->artifactsOnAltar.erase(art); | ||||||
| 		newSlot->setID(-1); | 		newSlot->setID(-1); | ||||||
| 		newSlot->subtitle.clear(); | 		newSlot->subtitle.clear(); | ||||||
|   | |||||||
| @@ -25,6 +25,8 @@ public: | |||||||
| 	std::shared_ptr<CArtifactsOfHeroAltar> getAOHset() const; | 	std::shared_ptr<CArtifactsOfHeroAltar> getAOHset() const; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  | 	ObjectInstanceID altarId; | ||||||
|  | 	const CArtifactSet * altarArtifacts; | ||||||
| 	std::shared_ptr<CArtPlace> selectedArt; | 	std::shared_ptr<CArtPlace> selectedArt; | ||||||
| 	std::shared_ptr<CLabel> selectedCost; | 	std::shared_ptr<CLabel> selectedCost; | ||||||
| 	std::shared_ptr<CButton> sacrificeBackpackButton; | 	std::shared_ptr<CButton> sacrificeBackpackButton; | ||||||
|   | |||||||
| @@ -151,11 +151,16 @@ DLL_LINKAGE bool ArtifactUtils::isSlotEquipment(const ArtifactPosition & slot) | |||||||
|  |  | ||||||
| DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots) | DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots) | ||||||
| { | { | ||||||
| 	const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP); | 	if(target->bearerType() == ArtBearer::HERO) | ||||||
| 	if(backpackCap < 0) | 	{ | ||||||
| 		return true; | 		const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP); | ||||||
|  | 		if(backpackCap < 0) | ||||||
|  | 			return true; | ||||||
|  | 		else | ||||||
|  | 			return target->artifactsInBackpack.size() + reqSlots <= backpackCap; | ||||||
|  | 	} | ||||||
| 	else | 	else | ||||||
| 		return target->artifactsInBackpack.size() + reqSlots <= backpackCap; | 		return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities( | DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities( | ||||||
|   | |||||||
| @@ -181,7 +181,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b | |||||||
| { | { | ||||||
| 	auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool | 	auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool | ||||||
| 	{ | 	{ | ||||||
| 		if(ArtifactUtils::isSlotBackpack(slot)) | 		if(artSet->bearerType() == ArtBearer::HERO && ArtifactUtils::isSlotBackpack(slot)) | ||||||
| 		{ | 		{ | ||||||
| 			if(isBig() || (!assumeDestRemoved && !ArtifactUtils::isBackpackFreeSlots(artSet))) | 			if(isBig() || (!assumeDestRemoved && !ArtifactUtils::isBackpackFreeSlots(artSet))) | ||||||
| 				return false; | 				return false; | ||||||
| @@ -258,6 +258,7 @@ CArtifact::CArtifact() | |||||||
| 	possibleSlots[ArtBearer::HERO]; //we want to generate map entry even if it will be empty | 	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::CREATURE]; //we want to generate map entry even if it will be empty | ||||||
| 	possibleSlots[ArtBearer::COMMANDER]; | 	possibleSlots[ArtBearer::COMMANDER]; | ||||||
|  | 	possibleSlots[ArtBearer::ALTAR].push_back(ArtifactPosition::ALTAR); | ||||||
| } | } | ||||||
|  |  | ||||||
| //This destructor should be placed here to avoid side effects | //This destructor should be placed here to avoid side effects | ||||||
| @@ -906,6 +907,9 @@ const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const | |||||||
|  |  | ||||||
| bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const | bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const | ||||||
| { | { | ||||||
|  | 	if(bearerType() == ArtBearer::ALTAR) | ||||||
|  | 		return artifactsInBackpack.size() < 22; | ||||||
|  |  | ||||||
| 	if(const ArtSlotInfo *s = getSlot(pos)) | 	if(const ArtSlotInfo *s = getSlot(pos)) | ||||||
| 		return (onlyLockCheck || !s->artifact) && !s->locked; | 		return (onlyLockCheck || !s->artifact) && !s->locked; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,7 +30,8 @@ class JsonSerializeFormat; | |||||||
| #define ART_BEARER_LIST \ | #define ART_BEARER_LIST \ | ||||||
| 	ART_BEARER(HERO)\ | 	ART_BEARER(HERO)\ | ||||||
| 	ART_BEARER(CREATURE)\ | 	ART_BEARER(CREATURE)\ | ||||||
| 	ART_BEARER(COMMANDER) | 	ART_BEARER(COMMANDER)\ | ||||||
|  | 	ART_BEARER(ALTAR) | ||||||
|  |  | ||||||
| namespace ArtBearer | namespace ArtBearer | ||||||
| { | { | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ | |||||||
| #include "mapObjects/CGHeroInstance.h" | #include "mapObjects/CGHeroInstance.h" | ||||||
| #include "mapObjects/CGTownInstance.h" | #include "mapObjects/CGTownInstance.h" | ||||||
| #include "mapObjects/MiscObjects.h" | #include "mapObjects/MiscObjects.h" | ||||||
|  | #include "mapObjects/CGMarket.h" | ||||||
| #include "networkPacks/ArtifactLocation.h" | #include "networkPacks/ArtifactLocation.h" | ||||||
| #include "CGeneralTextHandler.h" | #include "CGeneralTextHandler.h" | ||||||
| #include "StartInfo.h" // for StartInfo | #include "StartInfo.h" // for StartInfo | ||||||
| @@ -970,17 +971,27 @@ const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid | |||||||
|  |  | ||||||
| CArtifactSet * CGameInfoCallback::getArtSet(const ArtifactLocation & loc) const | CArtifactSet * CGameInfoCallback::getArtSet(const ArtifactLocation & loc) const | ||||||
| { | { | ||||||
| 	auto hero = const_cast<CGHeroInstance*>(getHero(loc.artHolder)); | 	if(auto hero = const_cast<CGHeroInstance*>(getHero(loc.artHolder))) | ||||||
| 	if(loc.creature.has_value()) |  | ||||||
| 	{ | 	{ | ||||||
| 		if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER) | 		if(loc.creature.has_value()) | ||||||
| 			return hero->commander; | 		{ | ||||||
|  | 			if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER) | ||||||
|  | 				return hero->commander; | ||||||
|  | 			else | ||||||
|  | 				return hero->getStackPtr(loc.creature.value()); | ||||||
|  | 		} | ||||||
| 		else | 		else | ||||||
| 			return hero->getStackPtr(loc.creature.value()); | 		{ | ||||||
|  | 			return hero; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else if(auto market = dynamic_cast<const CGArtifactsAltar*>(getObj(loc.artHolder, false))) | ||||||
|  | 	{ | ||||||
|  | 		return const_cast<CGArtifactsAltar*>(market); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		return hero; | 		return nullptr; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -610,7 +610,10 @@ public: | |||||||
| 		CREATURE_SLOT = 0, | 		CREATURE_SLOT = 0, | ||||||
| 		 | 		 | ||||||
| 		// Commander | 		// Commander | ||||||
| 		COMMANDER1 = 0, COMMANDER2, COMMANDER3, COMMANDER4, COMMANDER5, COMMANDER6 | 		COMMANDER1 = 0, COMMANDER2, COMMANDER3, COMMANDER4, COMMANDER5, COMMANDER6, | ||||||
|  |  | ||||||
|  | 		// Altar | ||||||
|  | 		ALTAR = BACKPACK_START | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	static_assert(MISC5 < BACKPACK_START, "incorrect number of artifact slots"); | 	static_assert(MISC5 < BACKPACK_START, "incorrect number of artifact slots"); | ||||||
|   | |||||||
| @@ -238,6 +238,11 @@ CGMarket * MarketInstanceConstructor::createObject(IGameCallback * cb) const | |||||||
| 				return new CGUniversity(cb); | 				return new CGUniversity(cb); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	else if(marketModes.size() == 2) | ||||||
|  | 	{ | ||||||
|  | 		if(vstd::contains(marketModes, EMarketMode::ARTIFACT_EXP)) | ||||||
|  | 			return new CGArtifactsAltar(cb); | ||||||
|  | 	} | ||||||
| 	return new CGMarket(cb); | 	return new CGMarket(cb); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -113,4 +113,9 @@ void CGUniversity::onHeroVisit(const CGHeroInstance * h) const | |||||||
| 	cb->showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true); | 	cb->showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | ArtBearer::ArtBearer CGArtifactsAltar::bearerType() const | ||||||
|  | { | ||||||
|  | 	return ArtBearer::ALTAR; | ||||||
|  | } | ||||||
|  |  | ||||||
| VCMI_LIB_NAMESPACE_END | VCMI_LIB_NAMESPACE_END | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
|  |  | ||||||
| #include "CGObjectInstance.h" | #include "CGObjectInstance.h" | ||||||
| #include "IMarket.h" | #include "IMarket.h" | ||||||
|  | #include "../CArtHandler.h" | ||||||
|  |  | ||||||
| VCMI_LIB_NAMESPACE_BEGIN | VCMI_LIB_NAMESPACE_BEGIN | ||||||
|  |  | ||||||
| @@ -80,4 +81,18 @@ public: | |||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | class DLL_LINKAGE CGArtifactsAltar : public CGMarket, public CArtifactSet | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	using CGMarket::CGMarket; | ||||||
|  |  | ||||||
|  | 	ArtBearer::ArtBearer bearerType() const override; | ||||||
|  |  | ||||||
|  | 	template <typename Handler> void serialize(Handler & h) | ||||||
|  | 	{ | ||||||
|  | 		h & static_cast<CGMarket&>(*this); | ||||||
|  | 		h & static_cast<CArtifactSet&>(*this); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
| VCMI_LIB_NAMESPACE_END | VCMI_LIB_NAMESPACE_END | ||||||
|   | |||||||
| @@ -54,6 +54,7 @@ void registerTypesMapObjects(Serializer &s) | |||||||
| 	s.template registerType<CGObjectInstance, CGMarket>(); | 	s.template registerType<CGObjectInstance, CGMarket>(); | ||||||
| 		s.template registerType<CGMarket, CGBlackMarket>(); | 		s.template registerType<CGMarket, CGBlackMarket>(); | ||||||
| 		s.template registerType<CGMarket, CGUniversity>(); | 		s.template registerType<CGMarket, CGUniversity>(); | ||||||
|  | 		s.template registerType<CGMarket, CGArtifactsAltar>(); | ||||||
| 	s.template registerType<CGObjectInstance, CGHeroPlaceholder>(); | 	s.template registerType<CGObjectInstance, CGHeroPlaceholder>(); | ||||||
|  |  | ||||||
| 	s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>(); | 	s.template registerType<CGObjectInstance, CArmedInstance>(); s.template registerType<CBonusSystemNode, CArmedInstance>(); s.template registerType<CCreatureSet, CArmedInstance>(); | ||||||
|   | |||||||
| @@ -2713,17 +2713,17 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca | |||||||
| 		COMPLAIN_RET("That heroes cannot make any exchange!"); | 		COMPLAIN_RET("That heroes cannot make any exchange!"); | ||||||
|  |  | ||||||
| 	const auto srcArtifact = srcArtSet->getArt(src.slot); | 	const auto srcArtifact = srcArtSet->getArt(src.slot); | ||||||
| 	const auto dstArtifact = dstArtSet->getArt(dst.slot); | 	const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtSet->getArt(dst.slot) != nullptr; | ||||||
| 	const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dst.slot) : false; | 	const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dst.slot) : false; | ||||||
|  |  | ||||||
| 	if(srcArtifact == nullptr) | 	if(srcArtifact == nullptr) | ||||||
| 		COMPLAIN_RET("No artifact to move!"); | 		COMPLAIN_RET("No artifact to move!"); | ||||||
| 	if(dstArtifact && getHero(src.artHolder)->getOwner() != getHero(dst.artHolder)->getOwner() && !isDstSlotBackpack) | 	if(isDstSlotOccupied && getOwner(src.artHolder) != getOwner(dst.artHolder) && !isDstSlotBackpack) | ||||||
| 		COMPLAIN_RET("Can't touch artifact on hero of another player!"); | 		COMPLAIN_RET("Can't touch artifact on hero of another player!"); | ||||||
|  |  | ||||||
| 	// Check if src/dest slots are appropriate for the artifacts exchanged. | 	// Check if src/dest slots are appropriate for the artifacts exchanged. | ||||||
| 	// Moving to the backpack is always allowed. | 	// Moving to the backpack is always allowed. | ||||||
| 	if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true)) | 	if((!srcArtifact || !isDstSlotBackpack) && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true)) | ||||||
| 		COMPLAIN_RET("Cannot move artifact!"); | 		COMPLAIN_RET("Cannot move artifact!"); | ||||||
|  |  | ||||||
| 	auto srcSlotInfo = srcArtSet->getSlot(src.slot); | 	auto srcSlotInfo = srcArtSet->getSlot(src.slot); | ||||||
| @@ -2749,7 +2749,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca | |||||||
| 	ma.dstCreature = dst.creature; | 	ma.dstCreature = dst.creature; | ||||||
| 	 | 	 | ||||||
| 	// Check if dst slot is occupied | 	// Check if dst slot is occupied | ||||||
| 	if(!isDstSlotBackpack && dstArtifact) | 	if(!isDstSlotBackpack && isDstSlotOccupied) | ||||||
| 	{ | 	{ | ||||||
| 		// Previous artifact must be removed | 		// Previous artifact must be removed | ||||||
| 		ma.artsPack1.push_back(BulkMoveArtifacts::LinkedSlots(dstSlot, src.slot)); | 		ma.artsPack1.push_back(BulkMoveArtifacts::LinkedSlots(dstSlot, src.slot)); | ||||||
| @@ -3432,6 +3432,20 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2) | |||||||
| 				return true; | 				return true; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if(o1->ID == Obj::ALTAR_OF_SACRIFICE) | ||||||
|  | 		{ | ||||||
|  | 			const auto visitingHero = getVisitingHero(o1); | ||||||
|  | 			const auto thisHero = static_cast<const CGHeroInstance*>(o2); | ||||||
|  | 			if(visitingHero == thisHero) | ||||||
|  | 				return true; | ||||||
|  | 		} | ||||||
|  | 		if(o2->ID == Obj::ALTAR_OF_SACRIFICE) | ||||||
|  | 		{ | ||||||
|  | 			const auto visitingHero = getVisitingHero(o2); | ||||||
|  | 			const auto thisHero = static_cast<const CGHeroInstance*>(o1); | ||||||
|  | 			if(visitingHero == thisHero) | ||||||
|  | 				return true; | ||||||
|  | 		} | ||||||
| 		if (o1->ID == Obj::HERO && o2->ID == Obj::HERO) | 		if (o1->ID == Obj::HERO && o2->ID == Obj::HERO) | ||||||
| 		{ | 		{ | ||||||
| 			const CGHeroInstance *h1 = static_cast<const CGHeroInstance*>(o1); | 			const CGHeroInstance *h1 = static_cast<const CGHeroInstance*>(o1); | ||||||
|   | |||||||
| @@ -134,7 +134,8 @@ void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack) | |||||||
|  |  | ||||||
| void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack) | void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack) | ||||||
| { | { | ||||||
| 	gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally | 	if(gh.getHero(pack.src.artHolder)) | ||||||
|  | 		gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally | ||||||
| 	result = gh.moveArtifact(pack.src, pack.dst); | 	result = gh.moveArtifact(pack.src, pack.dst); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user