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:
parent
977acfafc8
commit
4bacd97497
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
69
lib/map.cpp
69
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<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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user