mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-17 00:07:41 +02:00
check amount of artifacts on hero when checking requirements of a quest that requires artifact(s)
fixes case when 2 or more identical artifacts are required
This commit is contained in:
@ -1191,18 +1191,27 @@ CArtifactInstance* CArtifactSet::getArt(ArtifactPosition pos, bool excludeLocked
|
|||||||
|
|
||||||
ArtifactPosition CArtifactSet::getArtPos(int aid, bool onlyWorn, bool allowLocked) const
|
ArtifactPosition CArtifactSet::getArtPos(int aid, bool onlyWorn, bool allowLocked) const
|
||||||
{
|
{
|
||||||
|
const auto result = getAllArtPositions(aid, onlyWorn, allowLocked, false);
|
||||||
|
return result.empty() ? ArtifactPosition{ArtifactPosition::PRE_FIRST} : result[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ArtifactPosition> CArtifactSet::getAllArtPositions(int aid, bool onlyWorn, bool allowLocked, bool getAll) const
|
||||||
|
{
|
||||||
|
std::vector<ArtifactPosition> result;
|
||||||
for(auto i = artifactsWorn.cbegin(); i != artifactsWorn.cend(); i++)
|
for(auto i = artifactsWorn.cbegin(); i != artifactsWorn.cend(); i++)
|
||||||
if(i->second.artifact->artType->id == aid && (allowLocked || !i->second.locked))
|
if(i->second.artifact->artType->id == aid && (allowLocked || !i->second.locked))
|
||||||
return i->first;
|
result.push_back(i->first);
|
||||||
|
|
||||||
if(onlyWorn)
|
if(onlyWorn)
|
||||||
return ArtifactPosition::PRE_FIRST;
|
return result;
|
||||||
|
if(!getAll && !result.empty())
|
||||||
|
return result;
|
||||||
|
|
||||||
for(int i = 0; i < artifactsInBackpack.size(); i++)
|
for(int i = 0; i < artifactsInBackpack.size(); i++)
|
||||||
if(artifactsInBackpack[i].artifact->artType->id == aid)
|
if(artifactsInBackpack[i].artifact->artType->id == aid)
|
||||||
return ArtifactPosition(GameConstants::BACKPACK_START + i);
|
result.push_back(ArtifactPosition(GameConstants::BACKPACK_START + i));
|
||||||
|
|
||||||
return ArtifactPosition::PRE_FIRST;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance *art) const
|
ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance *art) const
|
||||||
@ -1237,8 +1246,19 @@ bool CArtifactSet::hasArt(
|
|||||||
bool searchBackpackAssemblies,
|
bool searchBackpackAssemblies,
|
||||||
bool allowLocked) const
|
bool allowLocked) const
|
||||||
{
|
{
|
||||||
return getArtPos(aid, onlyWorn, allowLocked) != ArtifactPosition::PRE_FIRST ||
|
return getArtPosCount(aid, onlyWorn, searchBackpackAssemblies, allowLocked) > 0;
|
||||||
(searchBackpackAssemblies && getHiddenArt(aid));
|
}
|
||||||
|
|
||||||
|
unsigned CArtifactSet::getArtPosCount(int aid, bool onlyWorn, bool searchBackpackAssemblies, bool allowLocked) const
|
||||||
|
{
|
||||||
|
const auto allPositions = getAllArtPositions(aid, onlyWorn, allowLocked, true);
|
||||||
|
if(!allPositions.empty())
|
||||||
|
return allPositions.size();
|
||||||
|
|
||||||
|
if(searchBackpackAssemblies && getHiddenArt(aid))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<const CCombinedArtifactInstance *, const CArtifactInstance *>
|
std::pair<const CCombinedArtifactInstance *, const CArtifactInstance *>
|
||||||
|
@ -328,6 +328,7 @@ public:
|
|||||||
/// (if more than one such artifact lower ID is returned)
|
/// (if more than one such artifact lower ID is returned)
|
||||||
ArtifactPosition getArtPos(int aid, bool onlyWorn = true, bool allowLocked = true) const;
|
ArtifactPosition getArtPos(int aid, bool onlyWorn = true, bool allowLocked = true) const;
|
||||||
ArtifactPosition getArtPos(const CArtifactInstance *art) const;
|
ArtifactPosition getArtPos(const CArtifactInstance *art) const;
|
||||||
|
std::vector<ArtifactPosition> getAllArtPositions(int aid, bool onlyWorn, bool allowLocked, bool getAll) const;
|
||||||
const CArtifactInstance *getArtByInstanceId(ArtifactInstanceID artInstId) const;
|
const CArtifactInstance *getArtByInstanceId(ArtifactInstanceID artInstId) const;
|
||||||
/// Search for constituents of assemblies in backpack which do not have an ArtifactPosition
|
/// Search for constituents of assemblies in backpack which do not have an ArtifactPosition
|
||||||
const CArtifactInstance *getHiddenArt(int aid) const;
|
const CArtifactInstance *getHiddenArt(int aid) const;
|
||||||
@ -335,6 +336,7 @@ public:
|
|||||||
/// Checks if hero possess artifact of given id (either in backack or worn)
|
/// Checks if hero possess artifact of given id (either in backack or worn)
|
||||||
bool hasArt(ui32 aid, bool onlyWorn = false, bool searchBackpackAssemblies = false, bool allowLocked = true) const;
|
bool hasArt(ui32 aid, bool onlyWorn = false, bool searchBackpackAssemblies = false, bool allowLocked = true) const;
|
||||||
bool isPositionFree(ArtifactPosition pos, bool onlyLockCheck = false) const;
|
bool isPositionFree(ArtifactPosition pos, bool onlyLockCheck = false) const;
|
||||||
|
unsigned getArtPosCount(int aid, bool onlyWorn = true, bool searchBackpackAssemblies = true, bool allowLocked = true) const;
|
||||||
|
|
||||||
virtual ArtBearer::ArtBearer bearerType() const = 0;
|
virtual ArtBearer::ArtBearer bearerType() const = 0;
|
||||||
virtual void putArtifact(ArtifactPosition pos, CArtifactInstance * art) = 0;
|
virtual void putArtifact(ArtifactPosition pos, CArtifactInstance * art) = 0;
|
||||||
|
@ -112,11 +112,16 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
case MISSION_ART:
|
case MISSION_ART:
|
||||||
for(auto & elem : m5arts)
|
// if the object was deserialized
|
||||||
|
if(artifactsRequirements.empty())
|
||||||
|
for(auto id : m5arts)
|
||||||
|
++artifactsRequirements[id];
|
||||||
|
|
||||||
|
for(const auto & elem : artifactsRequirements)
|
||||||
{
|
{
|
||||||
if(h->hasArt(elem, false, true))
|
// check required amount of artifacts
|
||||||
continue;
|
if(h->getArtPosCount(elem.first, false, true, true) < elem.second)
|
||||||
return false; //if the artifact was not found
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case MISSION_ARMY:
|
case MISSION_ARMY:
|
||||||
@ -417,6 +422,12 @@ void CQuest::getCompletionText(MetaString &iwText, std::vector<Component> &compo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CQuest::addArtifactID(ui16 id)
|
||||||
|
{
|
||||||
|
m5arts.push_back(id);
|
||||||
|
++artifactsRequirements[id];
|
||||||
|
}
|
||||||
|
|
||||||
void CQuest::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName)
|
void CQuest::serializeJson(JsonSerializeFormat & handler, const std::string & fieldName)
|
||||||
{
|
{
|
||||||
auto q = handler.enterStruct(fieldName);
|
auto q = handler.enterStruct(fieldName);
|
||||||
|
@ -21,6 +21,8 @@ class CGCreature;
|
|||||||
|
|
||||||
class DLL_LINKAGE CQuest final
|
class DLL_LINKAGE CQuest final
|
||||||
{
|
{
|
||||||
|
mutable std::unordered_map<ui16, unsigned> artifactsRequirements; // artifact ID -> required count
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4,
|
enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4,
|
||||||
MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9, MISSION_KEYMASTER = 10};
|
MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9, MISSION_KEYMASTER = 10};
|
||||||
@ -34,7 +36,7 @@ public:
|
|||||||
|
|
||||||
ui32 m13489val;
|
ui32 m13489val;
|
||||||
std::vector<ui32> m2stats;
|
std::vector<ui32> m2stats;
|
||||||
std::vector<ui16> m5arts; //artifacts id
|
std::vector<ui16> m5arts; // artifact IDs. Add IDs through addArtifactID(), not directly to the field.
|
||||||
std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
|
std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
|
||||||
std::vector<ui32> m7resources; //TODO: use resourceset?
|
std::vector<ui32> m7resources; //TODO: use resourceset?
|
||||||
|
|
||||||
@ -60,6 +62,7 @@ public:
|
|||||||
virtual void getRolloverText (MetaString &text, bool onHover) const; //hover or quest log entry
|
virtual void getRolloverText (MetaString &text, bool onHover) const; //hover or quest log entry
|
||||||
virtual void completeQuest (const CGHeroInstance * h) const {};
|
virtual void completeQuest (const CGHeroInstance * h) const {};
|
||||||
virtual void addReplacements(MetaString &out, const std::string &base) const;
|
virtual void addReplacements(MetaString &out, const std::string &base) const;
|
||||||
|
void addArtifactID(ui16 id);
|
||||||
|
|
||||||
bool operator== (const CQuest & quest) const
|
bool operator== (const CQuest & quest) const
|
||||||
{
|
{
|
||||||
|
@ -1758,7 +1758,7 @@ CGSeerHut * CMapLoaderH3M::readSeerHut()
|
|||||||
if (artID != 255)
|
if (artID != 255)
|
||||||
{
|
{
|
||||||
//not none quest
|
//not none quest
|
||||||
hut->quest->m5arts.push_back (artID);
|
hut->quest->addArtifactID(artID);
|
||||||
hut->quest->missionType = CQuest::MISSION_ART;
|
hut->quest->missionType = CQuest::MISSION_ART;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1887,7 +1887,7 @@ void CMapLoaderH3M::readQuest(IQuestObject * guard)
|
|||||||
for(int yy = 0; yy < artNumber; ++yy)
|
for(int yy = 0; yy < artNumber; ++yy)
|
||||||
{
|
{
|
||||||
int artid = reader.readUInt16();
|
int artid = reader.readUInt16();
|
||||||
guard->quest->m5arts.push_back(artid);
|
guard->quest->addArtifactID(artid);
|
||||||
map->allowedArtifact[artid] = false; //these are unavailable for random generation
|
map->allowedArtifact[artid] = false; //these are unavailable for random generation
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -430,7 +430,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
|
|
||||||
obj->quest->missionType = CQuest::MISSION_ART;
|
obj->quest->missionType = CQuest::MISSION_ART;
|
||||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
||||||
obj->quest->m5arts.push_back(artid);
|
obj->quest->addArtifactID(artid);
|
||||||
obj->quest->lastDay = -1;
|
obj->quest->lastDay = -1;
|
||||||
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
||||||
|
|
||||||
@ -467,7 +467,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
|
|
||||||
obj->quest->missionType = CQuest::MISSION_ART;
|
obj->quest->missionType = CQuest::MISSION_ART;
|
||||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
||||||
obj->quest->m5arts.push_back(artid);
|
obj->quest->addArtifactID(artid);
|
||||||
obj->quest->lastDay = -1;
|
obj->quest->lastDay = -1;
|
||||||
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
||||||
|
|
||||||
@ -490,7 +490,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
|||||||
|
|
||||||
obj->quest->missionType = CQuest::MISSION_ART;
|
obj->quest->missionType = CQuest::MISSION_ART;
|
||||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
||||||
obj->quest->m5arts.push_back(artid);
|
obj->quest->addArtifactID(artid);
|
||||||
obj->quest->lastDay = -1;
|
obj->quest->lastDay = -1;
|
||||||
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user