mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
Merge pull request #1027 from kambala-decapitator/fix-quest-multiple-artifacts
Fix quest check that requires identical artifacts
This commit is contained in:
commit
1aefbd14a7
@ -1191,18 +1191,27 @@ CArtifactInstance* CArtifactSet::getArt(ArtifactPosition pos, bool excludeLocked
|
||||
|
||||
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++)
|
||||
if(i->second.artifact->artType->id == aid && (allowLocked || !i->second.locked))
|
||||
return i->first;
|
||||
result.push_back(i->first);
|
||||
|
||||
if(onlyWorn)
|
||||
return ArtifactPosition::PRE_FIRST;
|
||||
return result;
|
||||
if(!getAll && !result.empty())
|
||||
return result;
|
||||
|
||||
for(int i = 0; i < artifactsInBackpack.size(); i++)
|
||||
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
|
||||
@ -1237,8 +1246,19 @@ bool CArtifactSet::hasArt(
|
||||
bool searchBackpackAssemblies,
|
||||
bool allowLocked) const
|
||||
{
|
||||
return getArtPos(aid, onlyWorn, allowLocked) != ArtifactPosition::PRE_FIRST ||
|
||||
(searchBackpackAssemblies && getHiddenArt(aid));
|
||||
return getArtPosCount(aid, onlyWorn, searchBackpackAssemblies, allowLocked) > 0;
|
||||
}
|
||||
|
||||
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 *>
|
||||
|
@ -328,6 +328,7 @@ public:
|
||||
/// (if more than one such artifact lower ID is returned)
|
||||
ArtifactPosition getArtPos(int aid, bool onlyWorn = true, bool allowLocked = true) 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;
|
||||
/// Search for constituents of assemblies in backpack which do not have an ArtifactPosition
|
||||
const CArtifactInstance *getHiddenArt(int aid) const;
|
||||
@ -335,6 +336,7 @@ public:
|
||||
/// 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 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 void putArtifact(ArtifactPosition pos, CArtifactInstance * art) = 0;
|
||||
|
@ -112,11 +112,16 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const
|
||||
return true;
|
||||
return false;
|
||||
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))
|
||||
continue;
|
||||
return false; //if the artifact was not found
|
||||
// check required amount of artifacts
|
||||
if(h->getArtPosCount(elem.first, false, true, true) < elem.second)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
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)
|
||||
{
|
||||
auto q = handler.enterStruct(fieldName);
|
||||
|
@ -19,8 +19,10 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class CGCreature;
|
||||
|
||||
class DLL_LINKAGE CQuest
|
||||
class DLL_LINKAGE CQuest final
|
||||
{
|
||||
mutable std::unordered_map<ui16, unsigned> artifactsRequirements; // artifact ID -> required count
|
||||
|
||||
public:
|
||||
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};
|
||||
@ -34,7 +36,7 @@ public:
|
||||
|
||||
ui32 m13489val;
|
||||
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<ui32> m7resources; //TODO: use resourceset?
|
||||
|
||||
@ -52,7 +54,6 @@ public:
|
||||
bool isCustomFirst, isCustomNext, isCustomComplete;
|
||||
|
||||
CQuest();
|
||||
virtual ~CQuest(){};
|
||||
|
||||
static bool checkMissionArmy(const CQuest * q, const CCreatureSet * army);
|
||||
virtual bool checkQuest (const CGHeroInstance * h) const; //determines whether the quest is complete or not
|
||||
@ -61,6 +62,7 @@ public:
|
||||
virtual void getRolloverText (MetaString &text, bool onHover) const; //hover or quest log entry
|
||||
virtual void completeQuest (const CGHeroInstance * h) const {};
|
||||
virtual void addReplacements(MetaString &out, const std::string &base) const;
|
||||
void addArtifactID(ui16 id);
|
||||
|
||||
bool operator== (const CQuest & quest) const
|
||||
{
|
||||
@ -161,7 +163,7 @@ protected:
|
||||
class DLL_LINKAGE CGQuestGuard : public CGSeerHut
|
||||
{
|
||||
public:
|
||||
CGQuestGuard() : CGSeerHut(){};
|
||||
CGQuestGuard() = default;
|
||||
void init(CRandomGenerator & rand) override;
|
||||
void completeQuest (const CGHeroInstance * h) const override;
|
||||
|
||||
@ -209,7 +211,7 @@ public:
|
||||
class DLL_LINKAGE CGBorderGuard : public CGKeys, public IQuestObject
|
||||
{
|
||||
public:
|
||||
CGBorderGuard() : IQuestObject(){};
|
||||
CGBorderGuard() = default;
|
||||
void initObj(CRandomGenerator & rand) override;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
void blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer) const override;
|
||||
@ -231,7 +233,7 @@ public:
|
||||
class DLL_LINKAGE CGBorderGate : public CGBorderGuard
|
||||
{
|
||||
public:
|
||||
CGBorderGate() : CGBorderGuard(){};
|
||||
CGBorderGate() = default;
|
||||
void onHeroVisit(const CGHeroInstance * h) const override;
|
||||
|
||||
bool passableFor(PlayerColor color) const override;
|
||||
|
@ -1758,7 +1758,7 @@ CGSeerHut * CMapLoaderH3M::readSeerHut()
|
||||
if (artID != 255)
|
||||
{
|
||||
//not none quest
|
||||
hut->quest->m5arts.push_back (artID);
|
||||
hut->quest->addArtifactID(artID);
|
||||
hut->quest->missionType = CQuest::MISSION_ART;
|
||||
}
|
||||
else
|
||||
@ -1887,7 +1887,7 @@ void CMapLoaderH3M::readQuest(IQuestObject * guard)
|
||||
for(int yy = 0; yy < artNumber; ++yy)
|
||||
{
|
||||
int artid = reader.readUInt16();
|
||||
guard->quest->m5arts.push_back(artid);
|
||||
guard->quest->addArtifactID(artid);
|
||||
map->allowedArtifact[artid] = false; //these are unavailable for random generation
|
||||
}
|
||||
break;
|
||||
|
@ -430,7 +430,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
|
||||
obj->quest->missionType = CQuest::MISSION_ART;
|
||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
||||
obj->quest->m5arts.push_back(artid);
|
||||
obj->quest->addArtifactID(artid);
|
||||
obj->quest->lastDay = -1;
|
||||
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
||||
|
||||
@ -467,7 +467,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
|
||||
obj->quest->missionType = CQuest::MISSION_ART;
|
||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
||||
obj->quest->m5arts.push_back(artid);
|
||||
obj->quest->addArtifactID(artid);
|
||||
obj->quest->lastDay = -1;
|
||||
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
||||
|
||||
@ -490,7 +490,7 @@ void TreasurePlacer::addAllPossibleObjects()
|
||||
|
||||
obj->quest->missionType = CQuest::MISSION_ART;
|
||||
ArtifactID artid = *RandomGeneratorUtil::nextItem(generator.getQuestArtsRemaning(), generator.rand);
|
||||
obj->quest->m5arts.push_back(artid);
|
||||
obj->quest->addArtifactID(artid);
|
||||
obj->quest->lastDay = -1;
|
||||
obj->quest->isCustomFirst = obj->quest->isCustomNext = obj->quest->isCustomComplete = false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user