1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-17 00:07:41 +02:00

Refactor quests progress

This commit is contained in:
nordsoft
2023-10-11 21:10:42 +02:00
parent 22c9eecd7d
commit 7ccd4cdcb2
7 changed files with 38 additions and 30 deletions

View File

@ -25,7 +25,7 @@ namespace AIPathfinding
return dynamic_cast<const IQuestObject *>(questInfo.obj)->checkQuest(node->actor->hero); return dynamic_cast<const IQuestObject *>(questInfo.obj)->checkQuest(node->actor->hero);
} }
return questInfo.quest->progress == CQuest::NOT_ACTIVE return questInfo.quest->activeForPlayers.count(node->actor->hero->getOwner())
|| questInfo.quest->checkQuest(node->actor->hero); || questInfo.quest->checkQuest(node->actor->hero);
} }

View File

@ -25,7 +25,7 @@ TGoalVec CompleteQuest::getAllPossibleSubgoals()
{ {
TGoalVec solutions; TGoalVec solutions;
if(q.quest->progress != CQuest::COMPLETE) if(!q.quest->isCompleted)
{ {
logAi->debug("Trying to realize quest: %s", questToString()); logAi->debug("Trying to realize quest: %s", questToString());

View File

@ -152,7 +152,7 @@ void CQuestLog::recreateLabelList()
if (quests[i].quest->questName == CQuest::missionName(0)) if (quests[i].quest->questName == CQuest::missionName(0))
continue; continue;
if (quests[i].quest->progress == CQuest::COMPLETE) if (quests[i].quest->isCompleted)
{ {
completeMissing = false; completeMissing = false;
if (hideComplete) if (hideComplete)
@ -180,7 +180,7 @@ void CQuestLog::recreateLabelList()
labels.push_back(label); labels.push_back(label);
// Select latest active quest // Select latest active quest
if (quests[i].quest->progress != CQuest::COMPLETE) if(!quests[i].quest->isCompleted)
selectQuest(i, currentLabel); selectQuest(i, currentLabel);
currentLabel = static_cast<int>(labels.size()); currentLabel = static_cast<int>(labels.size());

View File

@ -38,7 +38,7 @@ std::map <PlayerColor, std::set <ui8> > CGKeys::playerKeyMap;
//TODO: Remove constructor //TODO: Remove constructor
CQuest::CQuest(): CQuest::CQuest():
qid(-1), qid(-1),
progress(NOT_ACTIVE), isCompleted(false),
lastDay(-1), lastDay(-1),
killTarget(ObjectInstanceID::NONE), killTarget(ObjectInstanceID::NONE),
textOption(0), textOption(0),
@ -451,13 +451,11 @@ void CGSeerHut::initObj(CRandomGenerator & rand)
CRewardableObject::initObj(rand); CRewardableObject::initObj(rand);
quest->progress = CQuest::NOT_ACTIVE;
setObjToKill(); setObjToKill();
quest->defineQuestName(); quest->defineQuestName();
if(quest->mission == Rewardable::Limiter{} && quest->killTarget == ObjectInstanceID::NONE) if(quest->mission == Rewardable::Limiter{} && quest->killTarget == ObjectInstanceID::NONE)
quest->progress = CQuest::COMPLETE; quest->isCompleted = true;
if(quest->questName == quest->missionName(0)) if(quest->questName == quest->missionName(0))
{ {
@ -484,13 +482,15 @@ void CGSeerHut::getRolloverText(MetaString &text, bool onHover) const
std::string CGSeerHut::getHoverText(PlayerColor player) const std::string CGSeerHut::getHoverText(PlayerColor player) const
{ {
std::string hoverName = getObjectName(); std::string hoverName = getObjectName();
if(ID == Obj::SEER_HUT && quest->progress != CQuest::NOT_ACTIVE) if(ID == Obj::SEER_HUT && quest->activeForPlayers.count(player))
{ {
hoverName = VLC->generaltexth->allTexts[347]; hoverName = VLC->generaltexth->allTexts[347];
boost::algorithm::replace_first(hoverName, "%s", seerName); boost::algorithm::replace_first(hoverName, "%s", seerName);
} }
if(quest->progress/* & quest->missionType*/) //rollover when the quest is active if(quest->activeForPlayers.count(player)
&& (quest->mission != Rewardable::Limiter{}
|| quest->killTarget != ObjectInstanceID::NONE)) //rollover when the quest is active
{ {
MetaString ms; MetaString ms;
getRolloverText (ms, true); getRolloverText (ms, true);
@ -503,10 +503,18 @@ void CGSeerHut::setPropertyDer (ui8 what, ui32 val)
{ {
switch(what) switch(what)
{ {
case CGSeerHut::OBJPROP_VISITED: case CGSeerHut::SEERHUT_VISITED:
quest->progress = static_cast<CQuest::EProgress>(val); {
quest->activeForPlayers.emplace(val);
break; break;
} }
case CGSeerHut::SEERHUT_COMPLETE:
{
quest->isCompleted = val;
quest->activeForPlayers.clear();
break;
}
}
} }
void CGSeerHut::newTurn(CRandomGenerator & rand) const void CGSeerHut::newTurn(CRandomGenerator & rand) const
@ -514,7 +522,7 @@ void CGSeerHut::newTurn(CRandomGenerator & rand) const
CRewardableObject::newTurn(rand); CRewardableObject::newTurn(rand);
if(quest->lastDay >= 0 && quest->lastDay <= cb->getDate() - 1) //time is up if(quest->lastDay >= 0 && quest->lastDay <= cb->getDate() - 1) //time is up
{ {
cb->setObjProperty (id, CGSeerHut::OBJPROP_VISITED, CQuest::COMPLETE); cb->setObjProperty (id, CGSeerHut::SEERHUT_COMPLETE, true);
} }
} }
@ -522,14 +530,14 @@ void CGSeerHut::onHeroVisit(const CGHeroInstance * h) const
{ {
InfoWindow iw; InfoWindow iw;
iw.player = h->getOwner(); iw.player = h->getOwner();
if(quest->progress < CQuest::COMPLETE) if(!quest->isCompleted)
{ {
bool firstVisit = !quest->progress; bool firstVisit = !quest->activeForPlayers.count(h->getOwner());
bool failRequirements = !checkQuest(h); bool failRequirements = !checkQuest(h);
if(firstVisit) if(firstVisit)
{ {
cb->setObjProperty(id, CGSeerHut::OBJPROP_VISITED, CQuest::IN_PROGRESS); cb->setObjProperty(id, CGSeerHut::SEERHUT_VISITED, h->getOwner());
AddQuest aq; AddQuest aq;
aq.quest = QuestInfo (quest, this, visitablePos()); aq.quest = QuestInfo (quest, this, visitablePos());
@ -612,10 +620,7 @@ void CGSeerHut::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answer)
if(answer) if(answer)
{ {
quest->completeQuest(cb, hero); quest->completeQuest(cb, hero);
if(quest && quest->repeatedQuest) cb->setObjProperty(id, CGSeerHut::SEERHUT_COMPLETE, !quest->repeatedQuest); //mission complete
cb->setObjProperty(id, CGSeerHut::OBJPROP_VISITED, CQuest::NOT_ACTIVE);
else
cb->setObjProperty(id, CGSeerHut::OBJPROP_VISITED, CQuest::COMPLETE); //mission complete
} }
} }

View File

@ -21,12 +21,6 @@ class DLL_LINKAGE CQuest final
{ {
public: public:
enum EProgress {
NOT_ACTIVE,
IN_PROGRESS,
COMPLETE
};
static const std::string & missionName(int index); static const std::string & missionName(int index);
static const std::string & missionState(int index); static const std::string & missionState(int index);
@ -34,11 +28,12 @@ public:
si32 qid; //unique quest id for serialization / identification si32 qid; //unique quest id for serialization / identification
EProgress progress;
si32 lastDay; //after this day (first day is 0) mission cannot be completed; if -1 - no limit si32 lastDay; //after this day (first day is 0) mission cannot be completed; if -1 - no limit
ObjectInstanceID killTarget; ObjectInstanceID killTarget;
Rewardable::Limiter mission; Rewardable::Limiter mission;
bool repeatedQuest; bool repeatedQuest;
bool isCompleted;
std::set<PlayerColor> activeForPlayers;
// following fields are used only for kill creature/hero missions, the original // following fields are used only for kill creature/hero missions, the original
// objects became inaccessible after their removal, so we need to store info // objects became inaccessible after their removal, so we need to store info
@ -75,7 +70,8 @@ public:
template <typename Handler> void serialize(Handler &h, const int version) template <typename Handler> void serialize(Handler &h, const int version)
{ {
h & qid; h & qid;
h & progress; h & isCompleted;
h & activeForPlayers;
h & lastDay; h & lastDay;
h & textOption; h & textOption;
h & stackToKill; h & stackToKill;
@ -143,7 +139,8 @@ public:
h & seerName; h & seerName;
} }
protected: protected:
static constexpr int OBJPROP_VISITED = 10; static constexpr int SEERHUT_VISITED = 10;
static constexpr int SEERHUT_COMPLETE = 11;
void setPropertyDer(ui8 what, ui32 val) override; void setPropertyDer(ui8 what, ui32 val) override;

View File

@ -57,6 +57,11 @@ bool operator==(const Rewardable::Limiter & l, const Rewardable::Limiter & r)
&& l.anyOf == r.anyOf; && l.anyOf == r.anyOf;
} }
bool operator!=(const Rewardable::Limiter & l, const Rewardable::Limiter & r)
{
return !(l == r);
}
bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const bool Rewardable::Limiter::heroAllowed(const CGHeroInstance * hero) const
{ {
if(dayOfWeek != 0) if(dayOfWeek != 0)

View File

@ -113,5 +113,6 @@ struct DLL_LINKAGE Limiter final
} }
bool DLL_LINKAGE operator== (const Rewardable::Limiter & l, const Rewardable::Limiter & r); bool DLL_LINKAGE operator== (const Rewardable::Limiter & l, const Rewardable::Limiter & r);
bool DLL_LINKAGE operator!= (const Rewardable::Limiter & l, const Rewardable::Limiter & r);
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END