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

VCAI can now exchange armies between heroes. By default, it will pass army to main hero.

This commit is contained in:
DjWarmonger 2012-08-28 15:04:05 +00:00
parent 830d94064e
commit e913d94c62
2 changed files with 85 additions and 11 deletions

View File

@ -641,6 +641,21 @@ void VCAI::heroExchangeStarted(si32 hero1, si32 hero2)
{
NET_EVENT_HANDLER;
LOG_ENTRY;
auto firstHero = cb->getHero(hero1);
auto secondHero = cb->getHero(hero2);
requestActionASAP([=]()
{
if (firstHero->getHeroStrength() > secondHero->getHeroStrength())
pickBestCreatures (firstHero, secondHero);
else
pickBestCreatures (secondHero, firstHero);
completeGoal(CGoal(VISIT_HERO).sethero(firstHero)); //TODO: what if we were visited by other hero in the meantime?
completeGoal(CGoal(VISIT_HERO).sethero(secondHero));
//TODO: exchange artifacts
});
}
void VCAI::heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val)
@ -1815,6 +1830,16 @@ void VCAI::tryRealize(CGoal g)
// throw cannotFulfillGoalException("There's a blocked gate!, we should never be here"); //CLEAR_WAY_TO should get keymaster tent
}
break;
case VISIT_HERO:
{
if(!g.hero->movement)
throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
if (ai->moveHeroToTile(g.tile, g.hero.get()))
{
throw goalFulfilledException("");
}
}
break;
case BUILD_STRUCTURE:
{
const CGTownInstance *t = g.town;
@ -1844,7 +1869,7 @@ void VCAI::tryRealize(CGoal g)
throw cannotFulfillGoalException("Cannot build a given structure!");
}
break;
case DIG_AT_TILE:
case DIG_AT_TILE:
{
assert(g.hero->visitablePos() == g.tile);
if (g.hero->diggingStatus() == CGHeroInstance::CAN_DIG)
@ -2742,6 +2767,17 @@ TSubgoal CGoal::whatToDoToAchieve()
return CGoal(VISIT_TILE).settile(pos);
}
break;
case VISIT_HERO:
{
const CGObjectInstance * obj = cb->getObj(objid);
if(!obj)
return CGoal(EXPLORE);
int3 pos = cb->getObj(objid)->visitablePos();
if (hero && ai->isAccessibleForHero(obj->pos, hero, true))
return CGoal(*this).settile(pos).setisElementar(true);
}
break;
case GET_ART_TYPE:
{
TSubgoal alternativeWay = CGoal::lookForArtSmart(aid); //TODO: use
@ -3120,22 +3156,61 @@ TSubgoal CGoal::whatToDoToAchieve()
}
else
{
if (hero == ai->primaryHero()) //we can get army from other heroes
{
auto otherHeroes = cb->getHeroesInfo();
auto heroDummy = hero;
erase_if(otherHeroes, [heroDummy](const CGHeroInstance * h)
{
return (h == heroDummy.h || !ai->isAccessibleForHero(heroDummy->pos, h, true));
});
if (otherHeroes.size())
{
boost::sort(otherHeroes, compareArmyStrength); //TODO: check if hero has at least one stack more powerful than ours? not likely to fail
int primaryPath, secondaryPath;
auto h = otherHeroes.back();
cb->setSelection(hero.h);
primaryPath = cb->getPathInfo(h->pos)->turns;
cb->setSelection(h);
secondaryPath = cb->getPathInfo(hero->pos)->turns;
if (primaryPath < secondaryPath)
return CGoal(VISIT_HERO).setisAbstract(true).setobjid(h->id).sethero(hero); //go to the other hero if we are faster
else
return CGoal(VISIT_HERO).setisAbstract(true).setobjid(hero->id).sethero(h); //let the other hero come to us
}
}
std::vector<const CGObjectInstance *> objs; //here we'll gather all dwellings
ai->retreiveVisitableObjs(objs);
erase_if(objs, [&](const CGObjectInstance *obj)
{
return (obj->ID != Obj::CREATURE_GENERATOR1); //not town/ dwelling
return (obj->ID != Obj::CREATURE_GENERATOR1);
});
if(objs.empty()) //no possible objects, we did eveyrthing already
return CGoal(EXPLORE).sethero(hero);
//TODO: check if we can recruit any creatures there, evaluate army
boost::sort(objs, isCloser);
BOOST_FOREACH(const CGObjectInstance *obj, objs)
{ //find safe dwelling
auto pos = obj->visitablePos();
if (isSafeToVisit(hero, pos) && ai->isAccessibleForHero(pos, hero)) //TODO: make use of multiple heroes
return CGoal(VISIT_TILE).sethero(hero).settile(pos);
if (objs.size())
{
boost::sort(objs, isCloser);
HeroPtr h = NULL;
BOOST_FOREACH(const CGObjectInstance *obj, objs)
{ //find safe dwelling
auto pos = obj->visitablePos();
if (shouldVisit (hero, obj)) //creatures fit in army
h = hero;
else
{
BOOST_FOREACH(auto ourHero, cb->getHeroesInfo()) //make use of multiple heroes
{
if (shouldVisit(ourHero, obj))
h = ourHero;
}
}
if (h && isSafeToVisit(h, pos) && ai->isAccessibleForHero(pos, h))
return CGoal(VISIT_TILE).sethero(h).settile(pos);
}
}
}
@ -3319,6 +3394,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
case Obj::SEER_HUT:
case Obj::QUEST_GUARD:
{
return false; //fixme: avoid crash
BOOST_FOREACH (auto q, ai->myCb->getMyQuests())
{
if (q.obj == obj)

View File

@ -78,15 +78,13 @@ enum EGoals
OBJECT_GOALS_BEGIN,
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)
VISIT_HERO, //heroes can move around - set goal abstract and track hero every turn
GET_ART_TYPE,
//BUILD_STRUCTURE,
ISSUE_COMMAND,
//hero
//VISIT_OBJ, //hero + tile
VISIT_TILE, //tile, in conjunction with hero elementar; assumes tile is reachable
CLEAR_WAY_TO,
DIG_AT_TILE //elementar with hero on tile