mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
- Fixed unserialized GrowingArtifact, causing crash
- An attempt to teach AI completing quests - Gathering army is now continuous, abstract goal - Lots of fixes and tweaks in AI
This commit is contained in:
parent
b86706d58c
commit
624908e403
214
AI/VCAI/VCAI.cpp
214
AI/VCAI/VCAI.cpp
@ -398,6 +398,11 @@ ui64 evaluateDanger(const CGObjectInstance *obj)
|
|||||||
const CGDwelling *d = dynamic_cast<const CGDwelling*>(obj);
|
const CGDwelling *d = dynamic_cast<const CGDwelling*>(obj);
|
||||||
return d->getArmyStrength();
|
return d->getArmyStrength();
|
||||||
}
|
}
|
||||||
|
case Obj::MINE:
|
||||||
|
{
|
||||||
|
const CArmedInstance * a = dynamic_cast<const CArmedInstance*>(obj);
|
||||||
|
return a->getArmyStrength();
|
||||||
|
}
|
||||||
case Obj::CRYPT: //crypt
|
case Obj::CRYPT: //crypt
|
||||||
case Obj::CREATURE_BANK: //crebank
|
case Obj::CREATURE_BANK: //crebank
|
||||||
case Obj::DRAGON_UTOPIA:
|
case Obj::DRAGON_UTOPIA:
|
||||||
@ -959,9 +964,10 @@ void VCAI::makeTurn()
|
|||||||
++dangerousObjects;
|
++dangerousObjects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dangerousObjects && totalDanger / dangerousObjects > h->getHeroStrength())
|
ui64 averageDanger = totalDanger / dangerousObjects;
|
||||||
|
if (dangerousObjects && averageDanger > h->getHeroStrength())
|
||||||
{
|
{
|
||||||
setGoal (h, CGoal(GATHER_ARMY).sethero(h));
|
setGoal (h, CGoal(GATHER_ARMY).sethero(h).setvalue(averageDanger * SAFE_ATTACK_CONSTANT).setisAbstract(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1025,6 +1031,12 @@ void VCAI::makeTurnInternal()
|
|||||||
safeCopy.erase(it);
|
safeCopy.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto quests = myCb->getMyQuests();
|
||||||
|
BOOST_FOREACH (auto quest, quests)
|
||||||
|
{
|
||||||
|
striveToQuest (quest);
|
||||||
|
}
|
||||||
|
|
||||||
striveToGoal(CGoal(BUILD)); //TODO: smarter building management
|
striveToGoal(CGoal(BUILD)); //TODO: smarter building management
|
||||||
}
|
}
|
||||||
catch(boost::thread_interrupted &e)
|
catch(boost::thread_interrupted &e)
|
||||||
@ -1053,9 +1065,11 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
|
|||||||
{
|
{
|
||||||
case Obj::CREATURE_GENERATOR1:
|
case Obj::CREATURE_GENERATOR1:
|
||||||
recruitCreatures (dynamic_cast<const CGDwelling *>(obj));
|
recruitCreatures (dynamic_cast<const CGDwelling *>(obj));
|
||||||
|
checkHeroArmy (h);
|
||||||
break;
|
break;
|
||||||
case GameConstants::TOWNI_TYPE:
|
case GameConstants::TOWNI_TYPE:
|
||||||
moveCreaturesToHero (dynamic_cast<const CGTownInstance *>(obj));
|
moveCreaturesToHero (dynamic_cast<const CGTownInstance *>(obj));
|
||||||
|
townVisitsThisWeek[h].push_back(h->visitedTown);
|
||||||
break;
|
break;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1102,6 +1116,12 @@ void VCAI::pickBestCreatures(const CArmedInstance * army, const CArmedInstance *
|
|||||||
cb->mergeOrSwapStacks(armyPtr, army, j, i);
|
cb->mergeOrSwapStacks(armyPtr, army, j, i);
|
||||||
|
|
||||||
//TODO - having now strongest possible army, we may want to think about arranging stacks
|
//TODO - having now strongest possible army, we may want to think about arranging stacks
|
||||||
|
|
||||||
|
auto hero = dynamic_cast<const CGHeroInstance *>(army);
|
||||||
|
if (hero)
|
||||||
|
{
|
||||||
|
checkHeroArmy (hero);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCAI::recruitCreatures(const CGDwelling * d)
|
void VCAI::recruitCreatures(const CGDwelling * d)
|
||||||
@ -1769,7 +1789,7 @@ void VCAI::tryRealize(CGoal g)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw cannotFulfillGoalException("There's a blocked gate!");
|
throw cannotFulfillGoalException("There's a blocked gate!"); //TODO: get keymaster tent
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BUILD_STRUCTURE:
|
case BUILD_STRUCTURE:
|
||||||
@ -1817,7 +1837,7 @@ void VCAI::tryRealize(CGoal g)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case COLLECT_RES:
|
case COLLECT_RES: //TODO: use piles and mines?
|
||||||
if(const CGObjectInstance *obj = cb->getObj(g.objid, false))
|
if(const CGObjectInstance *obj = cb->getObj(g.objid, false))
|
||||||
{
|
{
|
||||||
if(const IMarket *m = IMarket::castFrom(obj, false))
|
if(const IMarket *m = IMarket::castFrom(obj, false))
|
||||||
@ -1851,7 +1871,7 @@ void VCAI::tryRealize(CGoal g)
|
|||||||
throw cannotFulfillGoalException("I don't know how to fulfill this!");
|
throw cannotFulfillGoalException("I don't know how to fulfill this!");
|
||||||
|
|
||||||
case BUILD:
|
case BUILD:
|
||||||
performTypicalActions();
|
performTypicalActions(); //TODO: separate build and wander
|
||||||
throw cannotFulfillGoalException("BUILD has been realized as much as possible.");
|
throw cannotFulfillGoalException("BUILD has been realized as much as possible.");
|
||||||
|
|
||||||
case INVALID:
|
case INVALID:
|
||||||
@ -1936,6 +1956,7 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
|
|||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
BNLOG("Goal %s decomposition failed: %s", goalName(goal.goalType) % e.what());
|
BNLOG("Goal %s decomposition failed: %s", goalName(goal.goalType) % e.what());
|
||||||
|
//setGoal (goal.hero, INVALID); //test: if we don't know how to realize goal, we should abandon it for now
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2005,6 +2026,7 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
|
|||||||
catch(std::exception &e)
|
catch(std::exception &e)
|
||||||
{
|
{
|
||||||
BNLOG("Goal %s decomposition failed: %s", goalName(goal.goalType) % e.what());
|
BNLOG("Goal %s decomposition failed: %s", goalName(goal.goalType) % e.what());
|
||||||
|
//setGoal (goal.hero, INVALID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2036,6 +2058,108 @@ void VCAI::striveToGoal(const CGoal &ultimateGoal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VCAI::striveToQuest (const QuestInfo &q)
|
||||||
|
{
|
||||||
|
if (q.quest && q.quest->progress < CQuest::COMPLETE)
|
||||||
|
{
|
||||||
|
MetaString ms;
|
||||||
|
q.quest->getRolloverText(ms, false);
|
||||||
|
BNLOG ("Trying to realize quest: %s\n", ms.toString());
|
||||||
|
switch (q.quest->missionType)
|
||||||
|
{
|
||||||
|
case CQuest::MISSION_ART:
|
||||||
|
{
|
||||||
|
BOOST_FOREACH (auto art, q.quest->m5arts)
|
||||||
|
{
|
||||||
|
striveToGoal (CGoal(GET_ART_TYPE).setaid(art)); //TODO: transport?
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CQuest::MISSION_HERO:
|
||||||
|
{
|
||||||
|
//striveToGoal (CGoal(RECRUIT_HERO));
|
||||||
|
auto heroes = cb->getHeroesInfo();
|
||||||
|
BOOST_FOREACH (auto hero, heroes)
|
||||||
|
{
|
||||||
|
if (q.quest->checkQuest(hero))
|
||||||
|
{
|
||||||
|
striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BNLOG ("Don't know how to recruit hero with id %d\n", q.quest->m13489val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CQuest::MISSION_ARMY:
|
||||||
|
{
|
||||||
|
BOOST_FOREACH (auto creature, q.quest->m6creatures)
|
||||||
|
{
|
||||||
|
BNLOG ("Don't know how to recruit %d of %s\n", (int)(creature.count) % creature.type->namePl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CQuest::MISSION_RESOURCES:
|
||||||
|
{
|
||||||
|
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]));
|
||||||
|
//TODO: visit object
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CQuest::MISSION_KILL_HERO:
|
||||||
|
case CQuest::MISSION_KILL_CREATURE:
|
||||||
|
{
|
||||||
|
striveToGoal (CGoal(GET_OBJ).setobjid(q.quest->m13489val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CQuest::MISSION_PRIMARY_STAT:
|
||||||
|
{
|
||||||
|
auto heroes = cb->getHeroesInfo();
|
||||||
|
BOOST_FOREACH (auto hero, heroes)
|
||||||
|
{
|
||||||
|
if (q.quest->checkQuest(hero))
|
||||||
|
{
|
||||||
|
striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < q.quest->m2stats.size(); ++i)
|
||||||
|
{
|
||||||
|
BNLOG ("Don't know how to increase primary stat %d\n", i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CQuest::MISSION_LEVEL:
|
||||||
|
{
|
||||||
|
auto heroes = cb->getHeroesInfo();
|
||||||
|
BOOST_FOREACH (auto hero, heroes)
|
||||||
|
{
|
||||||
|
if (q.quest->checkQuest(hero))
|
||||||
|
{
|
||||||
|
striveToGoal (CGoal(GET_OBJ).setobjid(q.obj->id).sethero(hero));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CQuest::MISSION_KEYMASTER:
|
||||||
|
{
|
||||||
|
striveToGoal (CGoal(FIND_OBJ).setobjid(Obj::KEYMASTER).setresID(q.quest->m13489val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VCAI::performTypicalActions()
|
void VCAI::performTypicalActions()
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const CGTownInstance *t, cb->getTownsInfo())
|
BOOST_FOREACH(const CGTownInstance *t, cb->getTownsInfo())
|
||||||
@ -2188,6 +2312,16 @@ bool VCAI::containsSavedRes(const TResources &cost) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VCAI::checkHeroArmy (HeroPtr h)
|
||||||
|
{
|
||||||
|
auto it = lockedHeroes.find(h);
|
||||||
|
if (it != lockedHeroes.end())
|
||||||
|
{
|
||||||
|
if (it->second.goalType == GATHER_ARMY && it->second.value <= h->getArmyStrength())
|
||||||
|
completeGoal(CGoal (GATHER_ARMY).sethero(h));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VCAI::recruitHero(const CGTownInstance * t)
|
void VCAI::recruitHero(const CGTownInstance * t)
|
||||||
{
|
{
|
||||||
BNLOG("Trying to recruit a hero in %s at %s", t->name % t->visitablePos())
|
BNLOG("Trying to recruit a hero in %s at %s", t->name % t->visitablePos())
|
||||||
@ -2477,7 +2611,7 @@ TSubgoal CGoal::whatToDoToAchieve()
|
|||||||
if(ratio > 0.99)
|
if(ratio > 0.99)
|
||||||
{
|
{
|
||||||
return CGoal(DIG_AT_TILE).settile(grailPos);
|
return CGoal(DIG_AT_TILE).settile(grailPos);
|
||||||
}
|
} //TODO: use FIND_OBJ
|
||||||
else if(const CGObjectInstance * obj = ai->getUnvisitedObj(objWithID<Obj::OBELISK>)) //there are unvisited Obelisks
|
else if(const CGObjectInstance * obj = ai->getUnvisitedObj(objWithID<Obj::OBELISK>)) //there are unvisited Obelisks
|
||||||
{
|
{
|
||||||
return CGoal(GET_OBJ).setobjid(obj->id);
|
return CGoal(GET_OBJ).setobjid(obj->id);
|
||||||
@ -2508,6 +2642,35 @@ TSubgoal CGoal::whatToDoToAchieve()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FIND_OBJ:
|
||||||
|
{
|
||||||
|
const CGObjectInstance * o = NULL;
|
||||||
|
if (resID > -1) //specified
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(const CGObjectInstance *obj, ai->visitableObjs)
|
||||||
|
{
|
||||||
|
if(obj->ID == objid && obj->subID == resID)
|
||||||
|
{
|
||||||
|
o = obj;
|
||||||
|
break; //TODO: consider multiple objects and choose best
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
BOOST_FOREACH(const CGObjectInstance *obj, ai->visitableObjs)
|
||||||
|
{
|
||||||
|
if(obj->ID == objid)
|
||||||
|
{
|
||||||
|
o = obj;
|
||||||
|
break; //TODO: consider multiple objects and choose best
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (o)
|
||||||
|
return CGoal(GET_OBJ).setobjid(o->id);
|
||||||
|
else
|
||||||
|
return CGoal(EXPLORE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case GET_OBJ:
|
case GET_OBJ:
|
||||||
{
|
{
|
||||||
const CGObjectInstance * obj = cb->getObj(objid);
|
const CGObjectInstance * obj = cb->getObj(objid);
|
||||||
@ -2519,17 +2682,9 @@ TSubgoal CGoal::whatToDoToAchieve()
|
|||||||
break;
|
break;
|
||||||
case GET_ART_TYPE:
|
case GET_ART_TYPE:
|
||||||
{
|
{
|
||||||
const CGObjectInstance *artInst = ai->lookForArt(aid);
|
TSubgoal alternativeWay = CGoal::lookForArtSmart(aid); //TODO: use
|
||||||
if(!artInst)
|
if(alternativeWay.invalid())
|
||||||
{
|
return CGoal(FIND_OBJ).setobjid(Obj::ARTIFACT).setresID(aid);
|
||||||
TSubgoal alternativeWay = CGoal::lookForArtSmart(aid);
|
|
||||||
if(alternativeWay.invalid())
|
|
||||||
return CGoal(EXPLORE);
|
|
||||||
else
|
|
||||||
return alternativeWay;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return CGoal(GET_OBJ).setobjid(artInst->id);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CLEAR_WAY_TO:
|
case CLEAR_WAY_TO:
|
||||||
@ -2571,7 +2726,7 @@ TSubgoal CGoal::whatToDoToAchieve()
|
|||||||
throw cannotFulfillGoalException(problem);
|
throw cannotFulfillGoalException(problem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CGoal(VISIT_TILE).settile(tileToHit).sethero(h);
|
return CGoal(VISIT_TILE).settile(tileToHit).sethero(h); //FIXME:: attempts to visit completely unreachable tile with hero results in stall
|
||||||
|
|
||||||
//TODO czy istnieje lepsza droga?
|
//TODO czy istnieje lepsza droga?
|
||||||
|
|
||||||
@ -2665,7 +2820,7 @@ TSubgoal CGoal::whatToDoToAchieve()
|
|||||||
return CGoal(*this).setisElementar(true);
|
return CGoal(*this).setisElementar(true);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return CGoal(GATHER_ARMY).sethero(hero);
|
return CGoal(GATHER_ARMY).sethero(hero).setvalue(evaluateDanger(tile, *hero) * SAFE_ATTACK_CONSTANT); //TODO: should it be abstract?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //inaccessible for all heroes
|
else //inaccessible for all heroes
|
||||||
@ -2837,7 +2992,7 @@ TSubgoal CGoal::whatToDoToAchieve()
|
|||||||
{
|
{
|
||||||
if(!t->visitingHero && howManyReinforcementsCanGet(hero,t))
|
if(!t->visitingHero && howManyReinforcementsCanGet(hero,t))
|
||||||
{
|
{
|
||||||
if(isReachable(t))
|
if(isReachable(t) && !vstd::contains (ai->townVisitsThisWeek[hero], t))
|
||||||
townsReachable.push_back(t);
|
townsReachable.push_back(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3030,6 +3185,10 @@ bool isWeeklyRevisitable (const CGObjectInstance * obj)
|
|||||||
{
|
{
|
||||||
case Obj::STABLES: //any other potential visitable objects?
|
case Obj::STABLES: //any other potential visitable objects?
|
||||||
return true;
|
return true;
|
||||||
|
case Obj::BORDER_GATE:
|
||||||
|
case Obj::BORDERGUARD:
|
||||||
|
return (dynamic_cast <const CGKeys *>(obj))->wasMyColorVisited (ai->playerID); //FIXME: they could be revisited sooner than in a week
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3038,6 +3197,21 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
|
|||||||
{
|
{
|
||||||
switch (obj->ID)
|
switch (obj->ID)
|
||||||
{
|
{
|
||||||
|
case Obj::SEER_HUT:
|
||||||
|
{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
return true; //we don't have this quest yet
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
case Obj::CREATURE_GENERATOR1:
|
case Obj::CREATURE_GENERATOR1:
|
||||||
{
|
{
|
||||||
if (obj->tempOwner != h->tempOwner)
|
if (obj->tempOwner != h->tempOwner)
|
||||||
|
@ -76,6 +76,7 @@ enum EGoals
|
|||||||
|
|
||||||
OBJECT_GOALS_BEGIN,
|
OBJECT_GOALS_BEGIN,
|
||||||
GET_OBJ, //visit or defeat or collect the object
|
GET_OBJ, //visit or defeat or collect the object
|
||||||
|
FIND_OBJ, //find and visit any obj with objid + resid //TODO: consider universal subid for various types (aid, bid)
|
||||||
|
|
||||||
GET_ART_TYPE,
|
GET_ART_TYPE,
|
||||||
|
|
||||||
@ -115,8 +116,10 @@ struct CGoal
|
|||||||
priority = 0;
|
priority = 0;
|
||||||
isElementar = false;
|
isElementar = false;
|
||||||
isAbstract = false;
|
isAbstract = false;
|
||||||
|
value = 0;
|
||||||
objid = -1;
|
objid = -1;
|
||||||
aid = -1;
|
aid = -1;
|
||||||
|
resID = -1;
|
||||||
tile = int3(-1, -1, -1);
|
tile = int3(-1, -1, -1);
|
||||||
town = NULL;
|
town = NULL;
|
||||||
}
|
}
|
||||||
@ -319,6 +322,7 @@ public:
|
|||||||
void setGoal(HeroPtr h, const CGoal goal);
|
void setGoal(HeroPtr h, const CGoal goal);
|
||||||
void setGoal(HeroPtr h, EGoals goalType = INVALID);
|
void setGoal(HeroPtr h, EGoals goalType = INVALID);
|
||||||
void completeGoal (const CGoal goal); //safely removes goal from reserved hero
|
void completeGoal (const CGoal goal); //safely removes goal from reserved hero
|
||||||
|
void striveToQuest (const QuestInfo &q);
|
||||||
|
|
||||||
void recruitHero(const CGTownInstance * t);
|
void recruitHero(const CGTownInstance * t);
|
||||||
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
|
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
|
||||||
@ -356,6 +360,7 @@ public:
|
|||||||
HeroPtr primaryHero() const;
|
HeroPtr primaryHero() const;
|
||||||
TResources estimateIncome() const;
|
TResources estimateIncome() const;
|
||||||
bool containsSavedRes(const TResources &cost) const;
|
bool containsSavedRes(const TResources &cost) const;
|
||||||
|
void checkHeroArmy (HeroPtr h);
|
||||||
|
|
||||||
void requestSent(const CPackForServer *pack, int requestID) OVERRIDE;
|
void requestSent(const CPackForServer *pack, int requestID) OVERRIDE;
|
||||||
void answerQuery(int queryID, int selection);
|
void answerQuery(int queryID, int selection);
|
||||||
|
@ -4539,10 +4539,10 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
if (firstVisit)
|
if (firstVisit)
|
||||||
{
|
{
|
||||||
isCustom = isCustomFirst;
|
isCustom = isCustomFirst;
|
||||||
cb->setObjProperty (id, 10, 1);
|
cb->setObjProperty (id, 10, IN_PROGRESS);
|
||||||
|
|
||||||
AddQuest aq;
|
AddQuest aq;
|
||||||
aq.quest = QuestInfo (this, this, pos);
|
aq.quest = QuestInfo (this, this, visitablePos());
|
||||||
aq.player = h->tempOwner;
|
aq.player = h->tempOwner;
|
||||||
cb->sendAndApply (&aq); //TODO: merge with setObjProperty?
|
cb->sendAndApply (&aq); //TODO: merge with setObjProperty?
|
||||||
}
|
}
|
||||||
@ -4632,7 +4632,8 @@ void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cb->setObjProperty(id,11,0); //no more mission available
|
cb->setObjProperty (id, 10, COMPLETE); //mission complete - for AI
|
||||||
|
cb->setObjProperty (id, 11, 0); //no more mission available - redundant?
|
||||||
completeQuest(h); //make sure to remove QuestQuard at the very end
|
completeQuest(h); //make sure to remove QuestQuard at the very end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6344,7 +6345,7 @@ void CGBorderGuard::onHeroVisit( const CGHeroInstance * h ) const
|
|||||||
cb->showInfoDialog (&iw);
|
cb->showInfoDialog (&iw);
|
||||||
|
|
||||||
AddQuest aq;
|
AddQuest aq;
|
||||||
aq.quest = QuestInfo (this, this, pos);
|
aq.quest = QuestInfo (this, this, visitablePos());
|
||||||
aq.player = h->tempOwner;
|
aq.player = h->tempOwner;
|
||||||
cb->sendAndApply (&aq);
|
cb->sendAndApply (&aq);
|
||||||
//TODO: add this quest only once OR check for multiple instances later
|
//TODO: add this quest only once OR check for multiple instances later
|
||||||
@ -6367,7 +6368,7 @@ void CGBorderGate::onHeroVisit( const CGHeroInstance * h ) const //TODO: passabi
|
|||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
|
|
||||||
AddQuest aq;
|
AddQuest aq;
|
||||||
aq.quest = QuestInfo (this, this, pos);
|
aq.quest = QuestInfo (this, this, visitablePos());
|
||||||
aq.player = h->tempOwner;
|
aq.player = h->tempOwner;
|
||||||
cb->sendAndApply (&aq);
|
cb->sendAndApply (&aq);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ class DLL_LINKAGE CQuest
|
|||||||
public:
|
public:
|
||||||
enum Emission {MISSION_NONE = 0, MISSION_LEVEL = 1, MISSION_PRIMARY_STAT = 2, MISSION_KILL_HERO = 3, MISSION_KILL_CREATURE = 4,
|
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};
|
MISSION_ART = 5, MISSION_ARMY = 6, MISSION_RESOURCES = 7, MISSION_HERO = 8, MISSION_PLAYER = 9, MISSION_KEYMASTER = 10};
|
||||||
|
enum Eprogress {NOT_ACTIVE, IN_PROGRESS, COMPLETE};
|
||||||
|
|
||||||
si32 qid; //unique quets id for serialization / identification
|
si32 qid; //unique quets id for serialization / identification
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ public:
|
|||||||
std::vector<ui32> m2stats;
|
std::vector<ui32> m2stats;
|
||||||
std::vector<ui16> m5arts; //artifacts id
|
std::vector<ui16> m5arts; //artifacts id
|
||||||
std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
|
std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
|
||||||
std::vector<ui32> m7resources;
|
std::vector<ui32> m7resources; //TODO: use resourceset?
|
||||||
|
|
||||||
//following field are used only for kill creature/hero missions, the original objects became inaccessible after their removal, so we need to store info needed for messages / hover text
|
//following field are used only for kill creature/hero missions, the original objects became inaccessible after their removal, so we need to store info needed for messages / hover text
|
||||||
ui8 textOption;
|
ui8 textOption;
|
||||||
|
@ -185,7 +185,9 @@ namespace Obj
|
|||||||
{
|
{
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
ARTIFACT = 5,
|
||||||
BOAT = 8,
|
BOAT = 8,
|
||||||
|
BORDERGUARD = 9,
|
||||||
KEYMASTER = 10,
|
KEYMASTER = 10,
|
||||||
CREATURE_BANK = 16,
|
CREATURE_BANK = 16,
|
||||||
CREATURE_GENERATOR1 = 17,
|
CREATURE_GENERATOR1 = 17,
|
||||||
@ -203,6 +205,7 @@ namespace Obj
|
|||||||
MONSTER = 54,
|
MONSTER = 54,
|
||||||
OBELISK = 57,
|
OBELISK = 57,
|
||||||
PYRAMID = 63,
|
PYRAMID = 63,
|
||||||
|
SEER_HUT = 83,
|
||||||
CRYPT = 84,
|
CRYPT = 84,
|
||||||
SHIPWRECK = 85,
|
SHIPWRECK = 85,
|
||||||
STABLES = 94,
|
STABLES = 94,
|
||||||
|
@ -84,6 +84,7 @@ void registerTypes1(Serializer &s)
|
|||||||
|
|
||||||
s.template registerType<CBonusSystemNode>();
|
s.template registerType<CBonusSystemNode>();
|
||||||
s.template registerType<CArtifact>();
|
s.template registerType<CArtifact>();
|
||||||
|
s.template registerType<CGrowingArtifact>();
|
||||||
s.template registerType<CCreature>();
|
s.template registerType<CCreature>();
|
||||||
s.template registerType<CStackInstance>();
|
s.template registerType<CStackInstance>();
|
||||||
s.template registerType<CCommanderInstance>();
|
s.template registerType<CCommanderInstance>();
|
||||||
|
Loading…
Reference in New Issue
Block a user