Browse Source

ArtifactLocation now use ID for artHolder identification part3

SoundSSGood 2 years ago
parent
commit
3c5527a222

+ 1 - 0
client/widgets/CArtifactHolder.cpp

@@ -122,6 +122,7 @@ void CCommanderArtPlace::returnArtToHeroCallback()
 	else
 	{
 		ArtifactLocation src(commanderOwner->id, artifactPos);
+		src.creature = SlotID::COMMANDER_SLOT_PLACEHOLDER;
 		ArtifactLocation dst(commanderOwner->id, freeSlot);
 
 		if(ourArt->canBePutAt(commanderOwner, freeSlot, true))

+ 9 - 7
client/widgets/CGarrisonInt.cpp

@@ -196,19 +196,21 @@ bool CGarrisonSlot::highlightOrDropArtifact()
 			artSelected = true;
 			if (myStack) // try dropping the artifact only if the slot isn't empty
 			{
-				/*ArtifactLocation src(srcHero, ArtifactPosition::TRANSITION_POS);
-				ArtifactLocation dst(myStack, ArtifactPosition::CREATURE_SLOT);
-				if(pickedArtInst->canBePutAt(dst, true))
+				ArtifactLocation src(srcHero->id, ArtifactPosition::TRANSITION_POS);
+				ArtifactLocation dst(getObj()->id, ArtifactPosition::CREATURE_SLOT);
+				dst.creature = getSlot();
+
+				if(pickedArtInst->canBePutAt(myStack, ArtifactPosition::CREATURE_SLOT, true))
 				{	//equip clicked stack
-					if(dst.getArt())
+					if(auto dstArt = myStack->getArt(ArtifactPosition::CREATURE_SLOT))
 					{
 						//creature can wear only one active artifact
 						//if we are placing a new one, the old one will be returned to the hero's backpack
-						LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero,
-							ArtifactUtils::getArtBackpackPosition(srcHero, dst.getArt()->getTypeId())));
+						LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero->id,
+							ArtifactUtils::getArtBackpackPosition(srcHero, dstArt->getTypeId())));
 					}
 					LOCPLINT->cb->swapArtifacts(src, dst);
-				}*/
+				}
 			}
 		}
 	}

+ 3 - 3
client/windows/CCreatureWindow.cpp

@@ -974,12 +974,12 @@ void CStackWindow::removeStackArtifact(ArtifactPosition pos)
 	const auto slot = ArtifactUtils::getArtBackpackPosition(info->owner, art->getTypeId());
 	if(slot != ArtifactPosition::PRE_FIRST)
 	{
-		//LOCPLINT->cb->swapArtifacts(ArtifactLocation(info->stackNode, pos), ArtifactLocation(info->owner->id, slot));
+		auto artLoc = ArtifactLocation(info->owner->id, pos);
+		artLoc.creature = info->stackNode->armyObj->findStack(info->stackNode);
+		LOCPLINT->cb->swapArtifacts(artLoc, ArtifactLocation(info->owner->id, slot));
 		stackArtifactButton.reset();
 		stackArtifactHelp.reset();
 		stackArtifactIcon.reset();
 		redraw();
 	}
 }
-
-

+ 2 - 11
client/windows/CHeroWindow.cpp

@@ -336,18 +336,9 @@ void CHeroWindow::commanderWindow()
 		const auto freeSlot = ArtifactUtils::getArtAnyPosition(curHero->commander, pickedArtInst->getTypeId());
 		if(vstd::contains(ArtifactUtils::commanderSlots(), freeSlot)) // We don't want to put it in commander's backpack!
 		{
-			ArtifactLocation src(hero->id, ArtifactPosition::TRANSITION_POS);
 			ArtifactLocation dst(curHero->id, freeSlot);
-			// TODO add ->commander.get() !!!
-			/*if(pickedArtInst->canBePutAt(dst, true))
-			{	//equip clicked stack
-				if(dst.getArt())
-				{
-					LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(hero,
-						ArtifactUtils::getArtBackpackPosition(hero, pickedArtInst->getTypeId())));
-				}
-				LOCPLINT->cb->swapArtifacts(src, dst);
-			}*/
+			dst.creature = SlotID::COMMANDER_SLOT_PLACEHOLDER;
+			LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS), dst);
 		}
 	}
 	else

+ 1 - 1
lib/CCreatureSet.cpp

@@ -458,7 +458,7 @@ const CStackInstance & CCreatureSet::getStack(const SlotID & slot) const
 	return *getStackPtr(slot);
 }
 
-const CStackInstance * CCreatureSet::getStackPtr(const SlotID & slot) const
+CStackInstance * CCreatureSet::getStackPtr(const SlotID & slot) const
 {
 	if(hasStackAtSlot(slot))
 		return stacks.find(slot)->second;

+ 1 - 1
lib/CCreatureSet.h

@@ -253,7 +253,7 @@ public:
 	void setToArmy(CSimpleArmy &src); //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
 
 	const CStackInstance & getStack(const SlotID & slot) const; //stack must exist
-	const CStackInstance * getStackPtr(const SlotID & slot) const; //if stack doesn't exist, returns nullptr
+	CStackInstance * getStackPtr(const SlotID & slot) const; //if stack doesn't exist, returns nullptr
 	const CCreature * getCreature(const SlotID & slot) const; //workaround of map issue;
 	int getStackCount(const SlotID & slot) const;
 	TExpType getStackExperience(const SlotID & slot) const;

+ 16 - 0
lib/CGameInfoCallback.cpp

@@ -966,6 +966,22 @@ const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid
 	return gs->map->objects[oid.num];
 }
 
+CArtifactSet * CGameInfoCallback::getArtSet(const ArtifactLocation & loc) const
+{
+	auto hero = const_cast<CGHeroInstance*>(getHero(loc.artHolder));
+	if(loc.creature.has_value())
+	{
+		if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER)
+			return hero->commander;
+		else
+			return hero->getStackPtr(loc.creature.value());
+	}
+	else
+	{
+		return hero;
+	}
+}
+
 std::vector<ObjectInstanceID> CGameInfoCallback::getVisibleTeleportObjects(std::vector<ObjectInstanceID> ids, PlayerColor player) const
 {
 	vstd::erase_if(ids, [&](const ObjectInstanceID & id) -> bool

+ 3 - 0
lib/CGameInfoCallback.h

@@ -40,6 +40,8 @@ class CGameState;
 class PathfinderConfig;
 struct TurnTimerInfo;
 
+struct ArtifactLocation;
+class CArtifactSet;
 class CArmedInstance;
 class CGObjectInstance;
 class CGHeroInstance;
@@ -174,6 +176,7 @@ public:
 	virtual int64_t estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
 	virtual const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const;
 	virtual const CGObjectInstance * getObjInstance(ObjectInstanceID oid) const;
+	virtual CArtifactSet * getArtSet(const ArtifactLocation & loc) const;
 	//virtual const CGObjectInstance * getArmyInstance(ObjectInstanceID oid) const;
 
 	//objects

+ 12 - 45
lib/networkPacks/ArtifactLocation.h

@@ -9,67 +9,34 @@
  */
 #pragma once
 
-#include "../ConstTransitivePtr.h"
 #include "../constants/EntityIdentifiers.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-class CGHeroInstance;
-class CStackInstance;
-class CArmedInstance;
-class CArtifactSet;
-class CBonusSystemNode;
-struct ArtSlotInfo;
-
-using TArtHolder = std::variant<ConstTransitivePtr<CGHeroInstance>, ConstTransitivePtr<CStackInstance>>;
-
 struct ArtifactLocation
 {
-	TArtHolder artHolder;//TODO: identify holder by id
-	ArtifactPosition slot = ArtifactPosition::PRE_FIRST;
+	ObjectInstanceID artHolder;
+	ArtifactPosition slot;
+	std::optional<SlotID> creature;
 
 	ArtifactLocation()
-		: artHolder(ConstTransitivePtr<CGHeroInstance>())
+		: artHolder(ObjectInstanceID::NONE)
+		, slot(ArtifactPosition::PRE_FIRST)
+		, creature(std::nullopt)
 	{
 	}
-	template<typename T>
-	ArtifactLocation(const T * ArtHolder, ArtifactPosition Slot)
-		: artHolder(const_cast<T *>(ArtHolder)) //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
-		, slot(Slot)
+	ArtifactLocation(const ObjectInstanceID id, const ArtifactPosition & slot = ArtifactPosition::PRE_FIRST)
+		: artHolder(id)
+		, slot(slot)
+		, creature(std::nullopt)
 	{
 	}
-	ArtifactLocation(TArtHolder ArtHolder, const ArtifactPosition & Slot)
-		: artHolder(std::move(std::move(ArtHolder)))
-		, slot(Slot)
-	{
-	}
-
-	template <typename T>
-	bool isHolder(const T *t) const
-	{
-		if(auto ptrToT = std::get<ConstTransitivePtr<T>>(artHolder))
-		{
-			return ptrToT == t;
-		}
-		return false;
-	}
-
-	DLL_LINKAGE void removeArtifact(); // BE CAREFUL, this operation modifies holder (gs)
-
-	DLL_LINKAGE const CArmedInstance *relatedObj() const; //hero or the stack owner
-	DLL_LINKAGE PlayerColor owningPlayer() const;
-	DLL_LINKAGE CArtifactSet *getHolderArtSet();
-	DLL_LINKAGE CBonusSystemNode *getHolderNode();
-	DLL_LINKAGE CArtifactSet *getHolderArtSet() const;
-	DLL_LINKAGE const CBonusSystemNode *getHolderNode() const;
 
-	DLL_LINKAGE const CArtifactInstance *getArt() const;
-	DLL_LINKAGE CArtifactInstance *getArt();
-	DLL_LINKAGE const ArtSlotInfo *getSlot() const;
-	template <typename Handler> void serialize(Handler &h, const int version)
+	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & artHolder;
 		h & slot;
+		h & creature;
 	}
 };
 

+ 15 - 16
lib/networkPacks/NetPacksLib.cpp

@@ -1656,35 +1656,34 @@ void RebalanceStacks::applyGs(CGameState * gs)
 			
 			const auto srcHero = dynamic_cast<CGHeroInstance*>(src.army.get());
 			const auto dstHero = dynamic_cast<CGHeroInstance*>(dst.army.get());
-			auto srcLoc = ArtifactLocation(srcHero->id, ArtifactPosition::CREATURE_SLOT);
-			auto dstLoc = ArtifactLocation(dstHero->id, ArtifactPosition::CREATURE_SLOT);
-			// TODO set creature id !!!
-			/*if (auto artHere = srcLoc.getArt())
+			auto srcStack = const_cast<CStackInstance*>(src.getStack());
+			auto dstStack = const_cast<CStackInstance*>(dst.getStack());
+			if(auto srcArt = srcStack->getArt(ArtifactPosition::CREATURE_SLOT))
 			{
-				if (dstLoc.getArt())
+				if(auto dstArt = dstStack->getArt(ArtifactPosition::CREATURE_SLOT))
 				{
-					
-					auto dstSlot = ArtifactUtils::getArtBackpackPosition(srcHero, dstLoc.getArt()->getTypeId());
+					auto dstSlot = ArtifactUtils::getArtBackpackPosition(srcHero, dstArt->getTypeId());
 					if(srcHero && dstSlot != ArtifactPosition::PRE_FIRST)
 					{
-						dstLoc.getArt()->move (dstLoc, ArtifactLocation (srcHero, dstSlot));
+						dstArt->move(*dstStack, ArtifactPosition::CREATURE_SLOT, *srcHero, dstSlot);
 					}
 					//else - artifact cna be lost :/
 					else
 					{
 						EraseArtifact ea;
-						ea.al = dstLoc;
+						ea.al = ArtifactLocation(dstHero->id, ArtifactPosition::CREATURE_SLOT);
+						ea.al.creature = dst.slot;
 						ea.applyGs(gs);
 						logNetwork->warn("Cannot move artifact! No free slots");
 					}
-					artHere->move (srcLoc, dstLoc);
+					srcArt->move(*srcStack, ArtifactPosition::CREATURE_SLOT, *dstStack, ArtifactPosition::CREATURE_SLOT);
 					//TODO: choose from dialog
 				}
 				else //just move to the other slot before stack gets erased
 				{
-					artHere->move (srcLoc, dstLoc);
+					srcArt->move(*srcStack, ArtifactPosition::CREATURE_SLOT, *dstStack, ArtifactPosition::CREATURE_SLOT);
 				}
-			}*/
+			}
 			if (stackExp)
 			{
 				ui64 totalExp = srcCount * src.army->getStackExperience(src.slot) + dst.army->getStackCount(dst.slot) * dst.army->getStackExperience(dst.slot);
@@ -1757,7 +1756,7 @@ void PutArtifact::applyGs(CGameState *gs)
 	assert(!art->getParentNodes().empty());
 	auto hero = gs->getHero(al.artHolder);
 	assert(hero);
-	assert(art->canBePutAt(hero, al.slot));
+	assert(art && art->canBePutAt(hero, al.slot));
 	art->putAt(*hero, al.slot);
 }
 
@@ -1796,12 +1795,12 @@ void EraseArtifact::applyGs(CGameState *gs)
 
 void MoveArtifact::applyGs(CGameState * gs)
 {
-	auto srcHero = gs->getHero(src.artHolder);
-	auto dstHero = gs->getHero(dst.artHolder);
+	auto srcHero = gs->getArtSet(src);
+	auto dstHero = gs->getArtSet(dst);
 	assert(srcHero);
 	assert(dstHero);
 	auto art = srcHero->getArt(src.slot);
-	assert(!ArtifactUtils::isSlotEquipment(dst.slot) || !dst.getArt());
+	assert(art && art->canBePutAt(dstHero, dst.slot));
 	art->move(*srcHero, src.slot, *dstHero, dst.slot);
 }
 

+ 16 - 12
server/CGameHandler.cpp

@@ -2666,29 +2666,32 @@ bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
 // Function moves artifact from src to dst. If dst is not a backpack and is already occupied, old dst art goes to backpack and is replaced.
 bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst)
 {
-	const auto srcHero = getHero(src.artHolder), dstHero = getHero(dst.artHolder);
 	ArtifactLocation srcLoc = src, dstLoc = dst;
+	const auto srcArtSet = getArtSet(srcLoc);
+	const auto dstArtSet = getArtSet(dstLoc);
+	assert(srcArtSet);
+	assert(dstArtSet);
 
 	// Make sure exchange is even possible between the two heroes.
 	if(!isAllowedExchange(srcLoc.artHolder, dstLoc.artHolder))
 		COMPLAIN_RET("That heroes cannot make any exchange!");
 
-	const auto srcArtifact = srcHero->getArt(srcLoc.slot);
-	const auto dstArtifact = dstHero->getArt(dstLoc.slot);
-	const bool isDstSlotBackpack = ArtifactUtils::isSlotBackpack(dstLoc.slot);
+	const auto srcArtifact = srcArtSet->getArt(srcLoc.slot);
+	const auto dstArtifact = dstArtSet->getArt(dstLoc.slot);
+	const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dstLoc.slot) : false;
 
 	if(srcArtifact == nullptr)
 		COMPLAIN_RET("No artifact to move!");
-	if(dstArtifact && srcHero->getOwner() != dstHero->getOwner() && !isDstSlotBackpack)
+	if(dstArtifact && getHero(src.artHolder)->getOwner() != getHero(dst.artHolder)->getOwner() && !isDstSlotBackpack)
 		COMPLAIN_RET("Can't touch artifact on hero of another player!");
 
 	// Check if src/dest slots are appropriate for the artifacts exchanged.
 	// Moving to the backpack is always allowed.
-	if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstHero, dstLoc.slot, true))
+	if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstArtSet, dstLoc.slot, true))
 		COMPLAIN_RET("Cannot move artifact!");
 
-	auto srcSlotInfo = srcHero->getSlot(srcLoc.slot);
-	auto dstSlotInfo = dstHero->getSlot(dstLoc.slot);
+	auto srcSlotInfo = srcArtSet->getSlot(srcLoc.slot);
+	auto dstSlotInfo = dstArtSet->getSlot(dstLoc.slot);
 
 	if((srcSlotInfo && srcSlotInfo->locked) || (dstSlotInfo && dstSlotInfo->locked))
 		COMPLAIN_RET("Cannot move artifact locks.");
@@ -2700,9 +2703,9 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
 
 	if(isDstSlotBackpack)
 	{
-		if(!ArtifactUtils::isBackpackFreeSlots(dstHero))
+		if(!ArtifactUtils::isBackpackFreeSlots(dstArtSet))
 			COMPLAIN_RET("Backpack is full!");
-		vstd::amin(dstLoc.slot, ArtifactPosition::BACKPACK_START + dstHero->artifactsInBackpack.size());
+		vstd::amin(dstLoc.slot, ArtifactPosition::BACKPACK_START + dstArtSet->artifactsInBackpack.size());
 	}
 
 	if(!(srcLoc.slot == ArtifactPosition::TRANSITION_POS && dstLoc.slot == ArtifactPosition::TRANSITION_POS))
@@ -2719,8 +2722,9 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
 
 		try
 		{
-			if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, srcArtifact->artType->getId(), dstLoc.slot))
-				giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
+			auto hero = getHero(dst.artHolder);
+			if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dstLoc.slot))
+				giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
 		}
 		catch(const std::bad_variant_access &)
 		{

+ 8 - 8
server/battles/BattleResultProcessor.cpp

@@ -381,12 +381,12 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
 				{
 					MoveArtifact ma;
 					ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
-					// TODO add ->commander.get() !!!
-					/*const CArtifactInstance* art = ma.src.getArt();
+					ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
+					const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first);
 					if (art && !art->artType->isBig())
 					{
 						sendMoveArtifact(art, &ma);
-					}*/
+					}
 				}
 			}
 		}
@@ -396,17 +396,17 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
 		for (auto armySlot : battle.battleGetArmyObject(loser)->stacks)
 		{
 			auto artifactsWorn = armySlot.second->artifactsWorn;
-			/*for (auto artSlot : artifactsWorn)
+			for(auto & artSlot : artifactsWorn)
 			{
 				MoveArtifact ma;
-				ma.src = ArtifactLocation(armySlot.second, artSlot.first);
-				const CArtifactInstance* art = ma.src.getArt();
+				ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
+				ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
+				const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first);
 				if (art && !art->artType->isBig())
 				{
 					sendMoveArtifact(art, &ma);
 				}
-				// TODO add stack !!!
-			}*/
+			}
 		}
 	}