1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Quests now handled by pointers again, this time without bugs.

Fixed some issues with quests and AI.
This commit is contained in:
DjWarmonger 2012-10-03 14:49:29 +00:00
parent 977acfafc8
commit 4bacd97497
8 changed files with 143 additions and 117 deletions

View File

@ -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

View File

@ -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<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);

View File

@ -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<Component> 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();
}

View File

@ -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)
{

View File

@ -4402,42 +4402,42 @@ void CQuest::getCompletionText (MetaString &iwText, std::vector<Component> &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<Component> &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<Component> &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<ui16>::const_iterator it = quest.m5arts.begin(); it != quest.m5arts.end(); ++it)
for (std::vector<ui16>::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);
}

View File

@ -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<Component> &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<Component> &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;

View File

@ -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<IQuestObject *>(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 <IQuestObject *>(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<IQuestObject *>(nobj));
addQuest (nobj);
break;
}
case 212: //Border Gate
{
nobj = new CGBorderGate();
addQuest (dynamic_cast<IQuestObject *>(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; yy<artNumber; ++yy)
{
int artid = read_le_u16(bufor + i); i+=2;
guard->quest.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; hh<typeNumber; ++hh)
{
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;
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<IQuestObject *>(obj);
q->quest->qid = quests.size();
quests.push_back (q->quest);
}
bool Mapa::loadArtifactToSlot(CGHeroInstance *h, int slot, const ui8 * bufor, int &i)

View File

@ -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<CMapHeader&>(*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