mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
Fix 1723 quest crash on combined arts
This commit is contained in:
parent
b02bd61c83
commit
11bce2908d
@ -1152,9 +1152,42 @@ const CArtifactInstance * CArtifactSet::getArtByInstanceId( ArtifactInstanceID a
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CArtifactSet::hasArt(ui32 aid, bool onlyWorn /*= false*/) const
|
bool CArtifactSet::hasArt(ui32 aid, bool onlyWorn /*= false*/,
|
||||||
|
bool searchBackpackAssemblies /*= false*/) const
|
||||||
{
|
{
|
||||||
return getArtPos(aid, onlyWorn) != ArtifactPosition::PRE_FIRST;
|
return getArtPos(aid, onlyWorn) != ArtifactPosition::PRE_FIRST ||
|
||||||
|
(searchBackpackAssemblies && getHiddenArt(aid));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const CCombinedArtifactInstance *, const CArtifactInstance *>
|
||||||
|
CArtifactSet::searchForConstituent(int aid) const
|
||||||
|
{
|
||||||
|
for(auto & slot : artifactsInBackpack)
|
||||||
|
{
|
||||||
|
auto art = slot.artifact;
|
||||||
|
if(art->canBeDisassembled())
|
||||||
|
{
|
||||||
|
auto ass = static_cast<CCombinedArtifactInstance *>(art.get());
|
||||||
|
for(auto& ci : ass->constituentsInfo)
|
||||||
|
{
|
||||||
|
if(ci.art->artType->id == aid)
|
||||||
|
{
|
||||||
|
return {ass, ci.art};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {nullptr, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
const CArtifactInstance *CArtifactSet::getHiddenArt(int aid) const
|
||||||
|
{
|
||||||
|
return searchForConstituent(aid).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CCombinedArtifactInstance *CArtifactSet::getAssemblyByConstituent(int aid) const
|
||||||
|
{
|
||||||
|
return searchForConstituent(aid).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ArtSlotInfo * CArtifactSet::getSlot(ArtifactPosition pos) const
|
const ArtSlotInfo * CArtifactSet::getSlot(ArtifactPosition pos) const
|
||||||
|
@ -128,7 +128,9 @@ public:
|
|||||||
virtual bool canBeDisassembled() const;
|
virtual bool canBeDisassembled() const;
|
||||||
virtual void putAt(ArtifactLocation al);
|
virtual void putAt(ArtifactLocation al);
|
||||||
virtual void removeFrom(ArtifactLocation al);
|
virtual void removeFrom(ArtifactLocation al);
|
||||||
virtual bool isPart(const CArtifactInstance *supposedPart) const; //checks if this a part of this artifact: artifact instance is a part of itself, additionally truth is returned for consituents of combined arts
|
/// Checks if this a part of this artifact: artifact instance is a part
|
||||||
|
/// of itself, additionally truth is returned for constituents of combined arts
|
||||||
|
virtual bool isPart(const CArtifactInstance *supposedPart) const;
|
||||||
|
|
||||||
std::vector<const CArtifact *> assemblyPossibilities(const CArtifactSet *h) const;
|
std::vector<const CArtifact *> assemblyPossibilities(const CArtifactSet *h) const;
|
||||||
void move(ArtifactLocation src, ArtifactLocation dst);
|
void move(ArtifactLocation src, ArtifactLocation dst);
|
||||||
@ -172,7 +174,7 @@ public:
|
|||||||
|
|
||||||
void createConstituents();
|
void createConstituents();
|
||||||
void addAsConstituent(CArtifactInstance *art, ArtifactPosition slot);
|
void addAsConstituent(CArtifactInstance *art, ArtifactPosition slot);
|
||||||
CArtifactInstance *figureMainConstituent(const ArtifactLocation al); //main constituent is replcaed with us (combined art), not lock
|
CArtifactInstance *figureMainConstituent(const ArtifactLocation al); //main constituent is replaced with us (combined art), not lock
|
||||||
|
|
||||||
CCombinedArtifactInstance();
|
CCombinedArtifactInstance();
|
||||||
|
|
||||||
@ -265,10 +267,8 @@ struct DLL_LINKAGE ArtSlotInfo
|
|||||||
ConstTransitivePtr<CArtifactInstance> artifact;
|
ConstTransitivePtr<CArtifactInstance> artifact;
|
||||||
ui8 locked; //if locked, then artifact points to the combined artifact
|
ui8 locked; //if locked, then artifact points to the combined artifact
|
||||||
|
|
||||||
ArtSlotInfo()
|
ArtSlotInfo() : locked(false) {}
|
||||||
{
|
|
||||||
locked = false;
|
|
||||||
}
|
|
||||||
template <typename Handler> void serialize(Handler &h, const int version)
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
h & artifact & locked;
|
h & artifact & locked;
|
||||||
@ -288,10 +288,16 @@ public:
|
|||||||
const ArtSlotInfo *getSlot(ArtifactPosition pos) const;
|
const ArtSlotInfo *getSlot(ArtifactPosition pos) const;
|
||||||
const CArtifactInstance* getArt(ArtifactPosition pos, bool excludeLocked = true) const; //nullptr - no artifact
|
const CArtifactInstance* getArt(ArtifactPosition pos, bool excludeLocked = true) const; //nullptr - no artifact
|
||||||
CArtifactInstance* getArt(ArtifactPosition pos, bool excludeLocked = true); //nullptr - no artifact
|
CArtifactInstance* getArt(ArtifactPosition pos, bool excludeLocked = true); //nullptr - no artifact
|
||||||
ArtifactPosition getArtPos(int aid, bool onlyWorn = true) const; //looks for equipped artifact with given ID and returns its slot ID or -1 if none(if more than one such artifact lower ID is returned)
|
/// Looks for equipped artifact with given ID and returns its slot ID or -1 if none
|
||||||
|
/// (if more than one such artifact lower ID is returned)
|
||||||
|
ArtifactPosition getArtPos(int aid, bool onlyWorn = true) const;
|
||||||
ArtifactPosition getArtPos(const CArtifactInstance *art) const;
|
ArtifactPosition getArtPos(const CArtifactInstance *art) const;
|
||||||
const CArtifactInstance *getArtByInstanceId(ArtifactInstanceID artInstId) const;
|
const CArtifactInstance *getArtByInstanceId(ArtifactInstanceID artInstId) const;
|
||||||
bool hasArt(ui32 aid, bool onlyWorn = false) const; //checks if hero possess artifact of given id (either in backack or worn)
|
/// Search for constituents of assemblies in backpack which do not have an ArtifactPosition
|
||||||
|
const CArtifactInstance *getHiddenArt(int aid) const;
|
||||||
|
const CCombinedArtifactInstance *getAssemblyByConstituent(int aid) const;
|
||||||
|
/// Checks if hero possess artifact of given id (either in backack or worn)
|
||||||
|
bool hasArt(ui32 aid, bool onlyWorn = false, bool searchBackpackAssemblies = false) const;
|
||||||
bool isPositionFree(ArtifactPosition pos, bool onlyLockCheck = false) const;
|
bool isPositionFree(ArtifactPosition pos, bool onlyLockCheck = false) const;
|
||||||
si32 getArtTypeId(ArtifactPosition pos) const;
|
si32 getArtTypeId(ArtifactPosition pos) const;
|
||||||
|
|
||||||
@ -304,4 +310,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void artDeserializationFix(CBonusSystemNode *node);
|
void artDeserializationFix(CBonusSystemNode *node);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::pair<const CCombinedArtifactInstance *, const CArtifactInstance *> searchForConstituent(int aid) const;
|
||||||
};
|
};
|
||||||
|
@ -754,7 +754,7 @@ DLL_LINKAGE const CArtifactInstance *ArtifactLocation::getArt() const
|
|||||||
return s->artifact;
|
return s->artifact;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logNetwork->warnStream() << "ArtifactLocation::getArt: That location is locked!";
|
logNetwork->warnStream() << "ArtifactLocation::getArt: This location is locked!";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -914,6 +914,32 @@ DLL_LINKAGE void PutArtifact::applyGs( CGameState *gs )
|
|||||||
|
|
||||||
DLL_LINKAGE void EraseArtifact::applyGs( CGameState *gs )
|
DLL_LINKAGE void EraseArtifact::applyGs( CGameState *gs )
|
||||||
{
|
{
|
||||||
|
auto slot = al.getSlot();
|
||||||
|
if(slot->locked)
|
||||||
|
{
|
||||||
|
logGlobal->debugStream() << "Erasing locked artifact: " << slot->artifact->artType->Name();
|
||||||
|
DisassembledArtifact dis;
|
||||||
|
dis.al.artHolder = al.artHolder;
|
||||||
|
auto aset = al.getHolderArtSet();
|
||||||
|
bool found = false;
|
||||||
|
for(auto& p : aset->artifactsWorn)
|
||||||
|
{
|
||||||
|
auto art = p.second.artifact;
|
||||||
|
if(art->canBeDisassembled() && art->isPart(slot->artifact))
|
||||||
|
{
|
||||||
|
dis.al.slot = aset->getArtPos(art);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(found && "Failed to determine the assembly this locked artifact belongs to");
|
||||||
|
logGlobal->debugStream() << "Found the corresponding assembly: " << dis.al.getSlot()->artifact->artType->Name();
|
||||||
|
dis.applyGs(gs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logGlobal->debugStream() << "Erasing artifact " << slot->artifact->artType->Name();
|
||||||
|
}
|
||||||
al.removeArtifact();
|
al.removeArtifact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
|
|||||||
case MISSION_ART:
|
case MISSION_ART:
|
||||||
for (auto & elem : m5arts)
|
for (auto & elem : m5arts)
|
||||||
{
|
{
|
||||||
if (h->hasArt(elem))
|
if (h->hasArt(elem, false, true))
|
||||||
continue;
|
continue;
|
||||||
return false; //if the artifact was not found
|
return false; //if the artifact was not found
|
||||||
}
|
}
|
||||||
@ -630,6 +630,18 @@ void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const
|
|||||||
case CQuest::MISSION_ART:
|
case CQuest::MISSION_ART:
|
||||||
for (auto & elem : quest->m5arts)
|
for (auto & elem : quest->m5arts)
|
||||||
{
|
{
|
||||||
|
if(!h->hasArt(elem))
|
||||||
|
{
|
||||||
|
// first we need to disassemble this backpack artifact
|
||||||
|
auto assembly = h->getAssemblyByConstituent(elem);
|
||||||
|
assert(assembly);
|
||||||
|
for(auto & ci : assembly->constituentsInfo)
|
||||||
|
{
|
||||||
|
cb->giveHeroNewArtifact(h, ci.art->artType, ArtifactPosition::PRE_FIRST);
|
||||||
|
}
|
||||||
|
// remove the assembly
|
||||||
|
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(assembly)));
|
||||||
|
}
|
||||||
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(elem, false)));
|
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(elem, false)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2113,7 +2113,6 @@ void CGameHandler::stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroI
|
|||||||
|
|
||||||
void CGameHandler::removeArtifact(const ArtifactLocation &al)
|
void CGameHandler::removeArtifact(const ArtifactLocation &al)
|
||||||
{
|
{
|
||||||
assert(al.getArt());
|
|
||||||
EraseArtifact ea;
|
EraseArtifact ea;
|
||||||
ea.al = al;
|
ea.al = al;
|
||||||
sendAndApply(&ea);
|
sendAndApply(&ea);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user