mirror of
https://github.com/vcmi/vcmi.git
synced 2025-05-13 22:06:58 +02:00
ArtifactLocation now use ID for artHolder identification part3
This commit is contained in:
parent
ab2f6abb87
commit
3c5527a222
@ -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))
|
||||
|
@ -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);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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(TArtHolder ArtHolder, const ArtifactPosition & Slot)
|
||||
: artHolder(std::move(std::move(ArtHolder)))
|
||||
, slot(Slot)
|
||||
ArtifactLocation(const ObjectInstanceID id, const ArtifactPosition & slot = ArtifactPosition::PRE_FIRST)
|
||||
: artHolder(id)
|
||||
, slot(slot)
|
||||
, creature(std::nullopt)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 &)
|
||||
{
|
||||
|
@ -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 !!!
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user