From 4bacd9749795d235a2905355ff2e161117275add Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Wed, 3 Oct 2012 14:49:29 +0000 Subject: [PATCH] Quests now handled by pointers again, this time without bugs. Fixed some issues with quests and AI. --- AI/VCAI/VCAI.cpp | 69 ++++++++++++++++++---------- AI/VCAI/VCAI.h | 1 + client/CQuestLog.cpp | 4 +- lib/CGameState.h | 4 +- lib/CObjectHandler.cpp | 102 ++++++++++++++++++++--------------------- lib/CObjectHandler.h | 7 ++- lib/map.cpp | 69 ++++++++++++++-------------- lib/map.h | 4 +- 8 files changed, 143 insertions(+), 117 deletions(-) diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 0bd2d2a6b..2f5f59f41 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -2057,6 +2057,15 @@ bool VCAI::fulfillsGoal (CGoal &goal, CGoal &mainGoal) } return false; } +bool VCAI::fulfillsGoal (CGoal &goal, const CGoal &mainGoal) +{ + if (mainGoal.goalType == GET_OBJ && goal.goalType == VISIT_TILE) //deduce that GET_OBJ was completed by visiting object's tile + { //TODO: more universal mechanism + if (cb->getObj(mainGoal.objid)->visitablePos() == goal.tile) + return true; + } + return false; +} void VCAI::striveToGoal(const CGoal &ultimateGoal) { @@ -2123,7 +2132,7 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal) catch(goalFulfilledException &e) { completeGoal (goal); - if (fulfillsGoal (goal, abstractGoal) || maxGoals > 98) //completed goal was main goal //TODO: find better condition + if (fulfillsGoal (goal, ultimateGoal) || maxGoals > 98) //completed goal was main goal //TODO: find better condition return; } catch(std::exception &e) @@ -2185,26 +2194,26 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal) void VCAI::striveToQuest (const QuestInfo &q) { - if (q.quest.missionType && q.quest.progress < CQuest::COMPLETE) //FIXME: quests are never synchronized. Pointer handling needed + if (q.quest->missionType && q.quest->progress < CQuest::COMPLETE) //FIXME: quests are never synchronized. Pointer handling needed { MetaString ms; - q.quest.getRolloverText(ms, false); + q.quest->getRolloverText(ms, false); BNLOG ("Trying to realize quest: %s", ms.toString()); auto heroes = cb->getHeroesInfo(); - switch (q.quest.missionType) + switch (q.quest->missionType) { case CQuest::MISSION_ART: { BOOST_FOREACH (auto hero, heroes) //TODO: remove duplicated code? { - if (q.quest.checkQuest(hero)) + if (q.quest->checkQuest(hero)) { striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero)); return; } } - BOOST_FOREACH (auto art, q.quest.m5arts) + BOOST_FOREACH (auto art, q.quest->m5arts) { striveToGoal (CGoal(GET_ART_TYPE).setaid(art)); //TODO: transport? } @@ -2215,7 +2224,7 @@ void VCAI::striveToQuest (const QuestInfo &q) //striveToGoal (CGoal(RECRUIT_HERO)); BOOST_FOREACH (auto hero, heroes) { - if (q.quest.checkQuest(hero)) + if (q.quest->checkQuest(hero)) { striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero)); return; @@ -2229,13 +2238,13 @@ void VCAI::striveToQuest (const QuestInfo &q) { BOOST_FOREACH (auto hero, heroes) { - if (q.quest.checkQuest(hero)) //veyr bad info - stacks can be split between multiple heroes :( + if (q.quest->checkQuest(hero)) //veyr bad info - stacks can be split between multiple heroes :( { striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero)); return; } } - BOOST_FOREACH (auto creature, q.quest.m6creatures) + BOOST_FOREACH (auto creature, q.quest->m6creatures) { striveToGoal (CGoal(GATHER_TROOPS).setobjid(creature.type->idNumber).setvalue(creature.count)); } @@ -2247,16 +2256,16 @@ void VCAI::striveToQuest (const QuestInfo &q) { if (heroes.size()) { - if (q.quest.checkQuest(heroes.front())) //it doesn't matter which hero it is + if (q.quest->checkQuest(heroes.front())) //it doesn't matter which hero it is { striveToGoal (CGoal(VISIT_TILE).settile(q.tile)); } else { - for (int i = 0; i < q.quest.m7resources.size(); ++i) + for (int i = 0; i < q.quest->m7resources.size(); ++i) { - if (q.quest.m7resources[i]) - striveToGoal (CGoal(COLLECT_RES).setresID(i).setvalue(q.quest.m7resources[i])); + if (q.quest->m7resources[i]) + striveToGoal (CGoal(COLLECT_RES).setresID(i).setvalue(q.quest->m7resources[i])); } } } @@ -2267,7 +2276,7 @@ void VCAI::striveToQuest (const QuestInfo &q) case CQuest::MISSION_KILL_HERO: case CQuest::MISSION_KILL_CREATURE: { - auto obj = cb->getObjByQuestIdentifier(q.quest.m13489val); + auto obj = cb->getObjByQuestIdentifier(q.quest->m13489val); if (obj) striveToGoal (CGoal(GET_OBJ).setobjid(obj->id)); else @@ -2279,13 +2288,13 @@ void VCAI::striveToQuest (const QuestInfo &q) auto heroes = cb->getHeroesInfo(); BOOST_FOREACH (auto hero, heroes) { - if (q.quest.checkQuest(hero)) + if (q.quest->checkQuest(hero)) { striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero)); return; } } - for (int i = 0; i < q.quest.m2stats.size(); ++i) + for (int i = 0; i < q.quest->m2stats.size(); ++i) { BNLOG ("Don't know how to increase primary stat %d\n", i); } @@ -2296,19 +2305,19 @@ void VCAI::striveToQuest (const QuestInfo &q) auto heroes = cb->getHeroesInfo(); BOOST_FOREACH (auto hero, heroes) { - if (q.quest.checkQuest(hero)) + if (q.quest->checkQuest(hero)) { striveToGoal (CGoal(VISIT_TILE).settile(q.tile).sethero(hero)); //TODO: causes infinite loop :/ return; } } - BNLOG ("Don't know how to reach hero level %d\n", q.quest.m13489val); + BNLOG ("Don't know how to reach hero level %d\n", q.quest->m13489val); break; } case CQuest::MISSION_PLAYER: { - if (playerID != q.quest.m13489val) - BNLOG ("Can't be player of color %d\n", q.quest.m13489val); + if (playerID != q.quest->m13489val) + BNLOG ("Can't be player of color %d\n", q.quest->m13489val); break; } case CQuest::MISSION_KEYMASTER: @@ -2836,7 +2845,7 @@ TSubgoal CGoal::whatToDoToAchieve() } } } - if (o) + if (o && isReachable(o)) return CGoal(GET_OBJ).setobjid(o->id); else return CGoal(EXPLORE); @@ -3522,15 +3531,25 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj) { case Obj::BORDERGUARD: case Obj::BORDER_GATE: - case Obj::SEER_HUT: - case Obj::QUEST_GUARD: { - //return false; //fixme: avoid crash BOOST_FOREACH (auto q, ai->myCb->getMyQuests()) { if (q.obj == obj) { - if (q.quest.checkQuest(*h)) + return false; // do not visit guards or gates when wandering + } + } + return true; //we don't have this quest yet + break; + } + case Obj::SEER_HUT: + case Obj::QUEST_GUARD: + { + BOOST_FOREACH (auto q, ai->myCb->getMyQuests()) + { + if (q.obj == obj) + { + if (q.quest->checkQuest(*h)) return true; //we completed the quest else return false; //we can't complete this quest diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index 0d7e92a18..fbaf9bcfd 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -356,6 +356,7 @@ public: void completeGoal (const CGoal goal); //safely removes goal from reserved hero void striveToQuest (const QuestInfo &q); bool fulfillsGoal (CGoal &goal, CGoal &mainGoal); + bool fulfillsGoal (CGoal &goal, const CGoal &mainGoal); //TODO: something smarter void recruitHero(const CGTownInstance * t); std::vector getPossibleDestinations(HeroPtr h); diff --git a/client/CQuestLog.cpp b/client/CQuestLog.cpp index d7ef43ef4..418fbfe8a 100644 --- a/client/CQuestLog.cpp +++ b/client/CQuestLog.cpp @@ -139,7 +139,7 @@ void CQuestLog::init() for (int i = 0; i < quests.size(); ++i) { MetaString text; - quests[i].quest.getRolloverText (text, false); + quests[i].quest->getRolloverText (text, false); if (quests[i].obj) text.addReplacement (quests[i].obj->getHoverText()); //get name of the object CQuestLabel * label = new CQuestLabel (28, 199 + i * 24, FONT_SMALL, TOPLEFT, Colors::Cornsilk, text.toString()); @@ -191,7 +191,7 @@ void CQuestLog::selectQuest (int which) MetaString text; std::vector components; //TODO: display them - currentQuest->quest.getVisitText (text, components , currentQuest->quest.isCustomFirst, true); + currentQuest->quest->getVisitText (text, components , currentQuest->quest->isCustomFirst, true); description->setTxt (text.toString()); //TODO: use special log entry text redraw(); } diff --git a/lib/CGameState.h b/lib/CGameState.h index 125aa4130..411b9cb6d 100644 --- a/lib/CGameState.h +++ b/lib/CGameState.h @@ -469,13 +469,13 @@ public: struct DLL_LINKAGE QuestInfo //universal interface for human and AI { - CQuest quest; + const CQuest * quest; const CGObjectInstance * obj; //related object, most likely Seer Hut int3 tile; QuestInfo(){}; QuestInfo (const CQuest * Quest, const CGObjectInstance * Obj, int3 Tile) : - quest (*Quest), obj (Obj), tile (Tile){}; + quest (Quest), obj (Obj), tile (Tile){}; bool operator= (const QuestInfo &qi) { diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index 8bec73bd7..d37df5a9c 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -4402,42 +4402,42 @@ void CQuest::getCompletionText (MetaString &iwText, std::vector &comp } void CGSeerHut::setObjToKill() { - if (quest.missionType == CQuest::MISSION_KILL_CREATURE) + if (quest->missionType == CQuest::MISSION_KILL_CREATURE) { - quest.stackToKill = getCreatureToKill(false)->getStack(0); //FIXME: stacks tend to dissapear (desync?) on server :? - assert(quest.stackToKill.type); - quest.stackToKill.count = 0; //no count in info window - quest.stackDirection = checkDirection(); + quest->stackToKill = getCreatureToKill(false)->getStack(0); //FIXME: stacks tend to dissapear (desync?) on server :? + assert(quest->stackToKill.type); + quest->stackToKill.count = 0; //no count in info window + quest->stackDirection = checkDirection(); } - else if (quest.missionType == CQuest::MISSION_KILL_HERO) + else if (quest->missionType == CQuest::MISSION_KILL_HERO) { - quest.heroName = getHeroToKill(false)->name; - quest.heroPortrait = getHeroToKill(false)->portrait; + quest->heroName = getHeroToKill(false)->name; + quest->heroPortrait = getHeroToKill(false)->portrait; } } void CGSeerHut::initObj() { seerName = VLC->generaltexth->seerNames[ran()%VLC->generaltexth->seerNames.size()]; - quest.textOption = ran()%3; - quest.progress = 0; - if (quest.missionType) + quest->textOption = ran()%3; + quest->progress = 0; + if (quest->missionType) { - if (!quest.isCustomFirst) - quest.firstVisitText = VLC->generaltexth->quests[quest.missionType-1][0][quest.textOption]; - if (!quest.isCustomNext) - quest.nextVisitText = VLC->generaltexth->quests[quest.missionType-1][1][quest.textOption]; - if (!quest.isCustomComplete) - quest.completedText = VLC->generaltexth->quests[quest.missionType-1][2][quest.textOption]; + if (!quest->isCustomFirst) + quest->firstVisitText = VLC->generaltexth->quests[quest->missionType-1][0][quest->textOption]; + if (!quest->isCustomNext) + quest->nextVisitText = VLC->generaltexth->quests[quest->missionType-1][1][quest->textOption]; + if (!quest->isCustomComplete) + quest->completedText = VLC->generaltexth->quests[quest->missionType-1][2][quest->textOption]; } else - quest.firstVisitText = VLC->generaltexth->seerEmpty[quest.textOption]; + quest->firstVisitText = VLC->generaltexth->seerEmpty[quest->textOption]; } void CGSeerHut::getRolloverText (MetaString &text, bool onHover) const { - quest.getRolloverText (text, onHover);//TODO: simplify? + quest->getRolloverText (text, onHover);//TODO: simplify? if (!onHover) text.addReplacement(seerName); } @@ -4447,7 +4447,7 @@ const std::string & CGSeerHut::getHoverText() const switch (ID) { case Obj::SEER_HUT: - if (quest.progress) + if (quest->progress) { hoverName = VLC->generaltexth->allTexts[347]; boost::algorithm::replace_first(hoverName,"%s", seerName); @@ -4461,7 +4461,7 @@ const std::string & CGSeerHut::getHoverText() const default: tlog5 << "unrecognized quest object\n"; } - if (quest.progress & quest.missionType) //rollover when the quest is active + if (quest->progress & quest->missionType) //rollover when the quest is active { MetaString ms; getRolloverText (ms, true); @@ -4489,17 +4489,17 @@ void CQuest::addReplacements(MetaString &out, const std::string &base) const bool IQuestObject::checkQuest(const CGHeroInstance* h) const { - return quest.checkQuest(h); + return quest->checkQuest(h); } void IQuestObject::getVisitText (MetaString &text, std::vector &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h) const { - quest.getVisitText (text,components, isCustom, FirstVisit, h); + quest->getVisitText (text,components, isCustom, FirstVisit, h); } void CGSeerHut::getCompletionText(MetaString &text, std::vector &components, bool isCustom, const CGHeroInstance * h) const { - quest.getCompletionText (text, components, isCustom, h); + quest->getCompletionText (text, components, isCustom, h); switch (rewardType) { case 1: components.push_back(Component (Component::EXPERIENCE, 0, rVal*(100+h->getSecSkillLevel(CGHeroInstance::LEARNING)*5)/100.0, 0)); @@ -4530,16 +4530,16 @@ void CGSeerHut::setPropertyDer (ui8 what, ui32 val) switch (what) { case 10: - quest.progress = val; + quest->progress = val; break; case 11: - quest.missionType = CQuest::MISSION_NONE; + quest->missionType = CQuest::MISSION_NONE; break; } } void CGSeerHut::newTurn() const { - if (quest.lastDay >= 0 && quest.lastDay < cb->getDate(0)) //time is up + if (quest->lastDay >= 0 && quest->lastDay < cb->getDate(0)) //time is up { cb->setObjProperty (id, 11, 0); cb->setObjProperty (id, 10, 0); @@ -4550,25 +4550,25 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const { InfoWindow iw; iw.player = h->getOwner(); - if (quest.missionType) + if (quest->missionType) { - bool firstVisit = !quest.progress; + bool firstVisit = !quest->progress; bool failRequirements = !checkQuest(h); bool isCustom=false; if (firstVisit) { - isCustom = quest.isCustomFirst; + isCustom = quest->isCustomFirst; cb->setObjProperty (id, 10, CQuest::IN_PROGRESS); AddQuest aq; - aq.quest = QuestInfo (&quest, this, visitablePos()); + aq.quest = QuestInfo (quest, this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply (&aq); //TODO: merge with setObjProperty? } else if (failRequirements) { - isCustom = quest.isCustomNext; + isCustom = quest->isCustomNext; } if (firstVisit || failRequirements) @@ -4591,7 +4591,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const } else { - iw.text << VLC->generaltexth->seerEmpty[quest.textOption]; + iw.text << VLC->generaltexth->seerEmpty[quest->textOption]; if (ID == Obj::SEER_HUT) iw.text.addReplacement(seerName); cb->showInfoDialog(&iw); @@ -4632,21 +4632,21 @@ void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const { if (accept) { - switch (quest.missionType) + switch (quest->missionType) { case CQuest::MISSION_ART: - for (std::vector::const_iterator it = quest.m5arts.begin(); it != quest.m5arts.end(); ++it) + for (std::vector::const_iterator it = quest->m5arts.begin(); it != quest->m5arts.end(); ++it) { cb->removeArtifact(ArtifactLocation(h, h->getArtPos(*it, false))); } break; case CQuest::MISSION_ARMY: - cb->takeCreatures(h->id, quest.m6creatures); + cb->takeCreatures(h->id, quest->m6creatures); break; case CQuest::MISSION_RESOURCES: for (int i = 0; i < 7; ++i) { - cb->giveResource(h->getOwner(), i, -quest.m7resources[i]); + cb->giveResource(h->getOwner(), i, -quest->m7resources[i]); } break; default: @@ -4715,7 +4715,7 @@ void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward const CGHeroInstance * CGSeerHut::getHeroToKill(bool allowNull) const { - const CGObjectInstance *o = cb->getObjByQuestIdentifier(quest.m13489val); + const CGObjectInstance *o = cb->getObjByQuestIdentifier(quest->m13489val); if(allowNull && !o) return NULL; assert(o && o->ID == Obj::HERO); @@ -4724,7 +4724,7 @@ const CGHeroInstance * CGSeerHut::getHeroToKill(bool allowNull) const const CGCreature * CGSeerHut::getCreatureToKill(bool allowNull) const { - const CGObjectInstance *o = cb->getObjByQuestIdentifier(quest.m13489val); + const CGObjectInstance *o = cb->getObjByQuestIdentifier(quest->m13489val); if(allowNull && !o) return NULL; assert(o && o->ID == Obj::MONSTER); @@ -4734,19 +4734,19 @@ const CGCreature * CGSeerHut::getCreatureToKill(bool allowNull) const void CGQuestGuard::initObj() { blockVisit = true; - quest.progress = 0; - quest.textOption = ran()%3 + 3; //3-5 - if (quest.missionType) + quest->progress = 0; + quest->textOption = ran()%3 + 3; //3-5 + if (quest->missionType) { - if (!quest.isCustomFirst) - quest.firstVisitText = VLC->generaltexth->quests[quest.missionType-1][0][quest.textOption]; - if (!quest.isCustomNext) - quest.nextVisitText = VLC->generaltexth->quests[quest.missionType-1][1][quest.textOption]; - if (!quest.isCustomComplete) - quest.completedText = VLC->generaltexth->quests[quest.missionType-1][2][quest.textOption]; + if (!quest->isCustomFirst) + quest->firstVisitText = VLC->generaltexth->quests[quest->missionType-1][0][quest->textOption]; + if (!quest->isCustomNext) + quest->nextVisitText = VLC->generaltexth->quests[quest->missionType-1][1][quest->textOption]; + if (!quest->isCustomComplete) + quest->completedText = VLC->generaltexth->quests[quest->missionType-1][2][quest->textOption]; } else - quest.firstVisitText = VLC->generaltexth->seerEmpty[quest.textOption]; + quest->firstVisitText = VLC->generaltexth->seerEmpty[quest->textOption]; } void CGQuestGuard::completeQuest(const CGHeroInstance *h) const { @@ -6370,7 +6370,7 @@ void CGBorderGuard::onHeroVisit( const CGHeroInstance * h ) const cb->showInfoDialog (&iw); AddQuest aq; - aq.quest = QuestInfo (&quest, this, visitablePos()); + aq.quest = QuestInfo (quest, this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply (&aq); //TODO: add this quest only once OR check for multiple instances later @@ -6393,7 +6393,7 @@ void CGBorderGate::onHeroVisit( const CGHeroInstance * h ) const //TODO: passabi cb->showInfoDialog(&iw); AddQuest aq; - aq.quest = QuestInfo (&quest, this, visitablePos()); + aq.quest = QuestInfo (quest, this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply (&aq); } diff --git a/lib/CObjectHandler.h b/lib/CObjectHandler.h index 002fc24be..38b13a2a9 100644 --- a/lib/CObjectHandler.h +++ b/lib/CObjectHandler.h @@ -771,8 +771,9 @@ public: class DLL_LINKAGE IQuestObject { public: - CQuest quest; + CQuest * quest; + IQuestObject(){quest = new CQuest;}; virtual void getVisitText (MetaString &text, std::vector &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = NULL) const; virtual bool checkQuest (const CGHeroInstance * h) const; @@ -790,6 +791,7 @@ public: si32 rVal; //reward value std::string seerName; + CGSeerHut() : IQuestObject(){}; void initObj(); const std::string & getHoverText() const; void setPropertyDer (ui8 what, ui32 val); @@ -815,6 +817,7 @@ public: class DLL_LINKAGE CGQuestGuard : public CGSeerHut { public: + CGQuestGuard() : CGSeerHut(){}; void initObj(); void completeQuest (const CGHeroInstance * h) const; @@ -1093,6 +1096,7 @@ public: class DLL_LINKAGE CGBorderGuard : public CGKeys, public IQuestObject { public: + CGBorderGuard() : IQuestObject(){}; void initObj(); const std::string & getHoverText() const; void getVisitText (MetaString &text, std::vector &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = NULL) const; @@ -1112,6 +1116,7 @@ public: class DLL_LINKAGE CGBorderGate : public CGBorderGuard { public: + CGBorderGate() : CGBorderGuard(){}; void onHeroVisit(const CGHeroInstance * h) const; ui8 getPassableness() const; diff --git a/lib/map.cpp b/lib/map.cpp index bea66cd35..20608ea15 100644 --- a/lib/map.cpp +++ b/lib/map.cpp @@ -595,18 +595,18 @@ int Mapa::loadSeerHut( const ui8 * bufor, int i, CGObjectInstance *& nobj ) int artID = bufor[i]; ++i; if (artID != 255) //not none quest { - hut->quest.m5arts.push_back (artID); - hut->quest.missionType = CQuest::MISSION_ART; + hut->quest->m5arts.push_back (artID); + hut->quest->missionType = CQuest::MISSION_ART; } else { - hut->quest.missionType = CQuest::MISSION_NONE; //no mission + hut->quest->missionType = CQuest::MISSION_NONE; //no mission } - hut->quest.lastDay = -1; //no timeout - hut->quest.isCustomFirst = hut->quest.isCustomNext = hut->quest.isCustomComplete = false; + hut->quest->lastDay = -1; //no timeout + hut->quest->isCustomFirst = hut->quest->isCustomNext = hut->quest->isCustomComplete = false; } - if (hut->quest.missionType) + if (hut->quest->missionType) { ui8 rewardType = bufor[i]; ++i; hut->rewardType = rewardType; @@ -1489,7 +1489,7 @@ void Mapa::readObjects( const ui8 * bufor, int &i) case 83: //seer's hut { i = loadSeerHut(bufor, i, nobj); - addQuest (dynamic_cast(nobj)); + addQuest (nobj); break; } case 113: //witch hut @@ -1748,9 +1748,9 @@ void Mapa::readObjects( const ui8 * bufor, int &i) case 215: { CGQuestGuard *guard = new CGQuestGuard(); - nobj = guard; + addQuest (guard); loadQuest(guard, bufor, i); - addQuest (dynamic_cast (guard)); + nobj = guard; break; } case 28: //faerie ring @@ -1831,13 +1831,13 @@ void Mapa::readObjects( const ui8 * bufor, int &i) case 9: //Border Guard { nobj = new CGBorderGuard(); - addQuest (dynamic_cast(nobj)); + addQuest (nobj); break; } case 212: //Border Gate { nobj = new CGBorderGate(); - addQuest (dynamic_cast(nobj)); + addQuest (nobj); break; } case 27: case 37: //Eye and Hut of Magi @@ -1975,18 +1975,18 @@ bool Mapa::isInTheMap(const int3 &pos) const void Mapa::loadQuest(IQuestObject * guard, const ui8 * bufor, int & i) { - guard->quest.missionType = bufor[i]; ++i; + guard->quest->missionType = bufor[i]; ++i; //int len1, len2, len3; - switch(guard->quest.missionType) + switch(guard->quest->missionType) { case 0: return; case 2: { - guard->quest.m2stats.resize(4); + guard->quest->m2stats.resize(4); for(int x=0; x<4; x++) { - guard->quest.m2stats[x] = bufor[i++]; + guard->quest->m2stats[x] = bufor[i++]; } } break; @@ -1994,7 +1994,7 @@ void Mapa::loadQuest(IQuestObject * guard, const ui8 * bufor, int & i) case 3: case 4: { - guard->quest.m13489val = read_le_u32(bufor + i); i+=4; + guard->quest->m13489val = read_le_u32(bufor + i); i+=4; break; } case 5: @@ -2003,7 +2003,7 @@ void Mapa::loadQuest(IQuestObject * guard, const ui8 * bufor, int & i) for(int yy=0; yyquest.m5arts.push_back(artid); + guard->quest->m5arts.push_back(artid); allowedArtifact[artid] = false; //these are unavailable for random generation } break; @@ -2011,20 +2011,20 @@ void Mapa::loadQuest(IQuestObject * guard, const ui8 * bufor, int & i) case 6: { int typeNumber = bufor[i]; ++i; - guard->quest.m6creatures.resize(typeNumber); + guard->quest->m6creatures.resize(typeNumber); for(int hh=0; hhquest.m6creatures[hh].type = VLC->creh->creatures[read_le_u16(bufor + i)]; i+=2; - guard->quest.m6creatures[hh].count = read_le_u16(bufor + i); i+=2; + guard->quest->m6creatures[hh].type = VLC->creh->creatures[read_le_u16(bufor + i)]; i+=2; + guard->quest->m6creatures[hh].count = read_le_u16(bufor + i); i+=2; } break; } case 7: { - guard->quest.m7resources.resize(7); + guard->quest->m7resources.resize(7); for(int x=0; x<7; x++) { - guard->quest.m7resources[x] = read_le_u32(bufor + i); + guard->quest->m7resources[x] = read_le_u32(bufor + i); i+=4; } break; @@ -2032,7 +2032,7 @@ void Mapa::loadQuest(IQuestObject * guard, const ui8 * bufor, int & i) case 8: case 9: { - guard->quest.m13489val = bufor[i]; ++i; + guard->quest->m13489val = bufor[i]; ++i; break; } } @@ -2041,18 +2041,18 @@ void Mapa::loadQuest(IQuestObject * guard, const ui8 * bufor, int & i) int limit = read_le_u32(bufor + i); i+=4; if(limit == ((int)0xffffffff)) { - guard->quest.lastDay = -1; + guard->quest->lastDay = -1; } else { - guard->quest.lastDay = limit; + guard->quest->lastDay = limit; } - guard->quest.firstVisitText = readString(bufor,i); - guard->quest.nextVisitText = readString(bufor,i); - guard->quest.completedText = readString(bufor,i); - guard->quest.isCustomFirst = guard->quest.firstVisitText.size() > 0; - guard->quest.isCustomNext = guard->quest.nextVisitText.size() > 0; - guard->quest.isCustomComplete = guard->quest.completedText.size() > 0; + guard->quest->firstVisitText = readString(bufor,i); + guard->quest->nextVisitText = readString(bufor,i); + guard->quest->completedText = readString(bufor,i); + guard->quest->isCustomFirst = guard->quest->firstVisitText.size() > 0; + guard->quest->isCustomNext = guard->quest->nextVisitText.size() > 0; + guard->quest->isCustomComplete = guard->quest->completedText.size() > 0; } TerrainTile & Mapa::getTile( const int3 & tile ) @@ -2098,10 +2098,11 @@ void Mapa::addNewArtifactInstance( CArtifactInstance *art ) artInstances.push_back(art); } -void Mapa::addQuest (IQuestObject *obj) +void Mapa::addQuest (CGObjectInstance *obj) { - obj->quest.qid = quests.size(); - quests.push_back(&obj->quest); + auto q = dynamic_cast(obj); + q->quest->qid = quests.size(); + quests.push_back (q->quest); } bool Mapa::loadArtifactToSlot(CGHeroInstance *h, int slot, const ui8 * bufor, int &i) diff --git a/lib/map.h b/lib/map.h index 9d5a64efa..82d5c45ad 100644 --- a/lib/map.h +++ b/lib/map.h @@ -335,7 +335,7 @@ struct DLL_LINKAGE Mapa : public CMapHeader CArtifactInstance *createArt(int aid, int spellID = -1); void addNewArtifactInstance(CArtifactInstance *art); - void addQuest (IQuestObject *quest); + void addQuest (CGObjectInstance *obj); void eraseArtifactInstance(CArtifactInstance *art); @@ -358,7 +358,7 @@ struct DLL_LINKAGE Mapa : public CMapHeader { h & static_cast(*this); h & rumors & allowedSpell & allowedAbilities & allowedArtifact & allowedHeroes & events & grailPos; - h & artInstances; //hopefully serialization is now automagical? + h & artInstances & quests; //hopefully serialization is now automagical? h & questIdentifierToId; //TODO: viccondetails