1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

- Unified interface for visitable objects

- AI will manage visitable objects smarter
This commit is contained in:
DjWarmonger 2012-03-14 13:02:38 +00:00
parent c8c4c5b682
commit a3f36ccc71
4 changed files with 105 additions and 24 deletions

View File

@ -374,12 +374,6 @@ ui64 evaluateDanger(const CGObjectInstance *obj)
case Obj::DERELICT_SHIP: //derelict ship
case Obj::PYRAMID:
return fh->estimateBankDanger (VLC->objh->bankObjToIndex(obj));
case Obj::WHIRLPOOL: //whirlpool
case Obj::MONOLITH1:
case Obj::MONOLITH2:
case Obj::MONOLITH3:
//TODO mechanism for handling monoliths
return 1000000000;
default:
return 0;
}
@ -559,9 +553,8 @@ void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visi
LOG_ENTRY;
if (start)
{
visitedObject = const_cast<CGObjectInstance *>(visitedObj); // remember teh object and wait for return
if(visitedObj->ID != Obj::MONSTER) //TODO: poll bank if it was cleared
alreadyVisited.push_back(visitedObj);
visitedObject = const_cast<CGObjectInstance *>(visitedObj); // remember the object and wait for return
markObjectVisited (visitedObj);
}
}
@ -1098,7 +1091,7 @@ std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(const CGHero
std::vector<const CGObjectInstance *> possibleDestinations;
BOOST_FOREACH(const CGObjectInstance *obj, visitableObjs)
{
if(cb->getPathInfo(obj->visitablePos())->reachable() &&
if(cb->getPathInfo(obj->visitablePos())->reachable() && !obj->wasVisited(playerID) &&
(obj->tempOwner != playerID || isWeeklyRevisitable(obj))) //flag or get weekly resources / creatures
possibleDestinations.push_back(obj);
}
@ -1113,6 +1106,9 @@ std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(const CGHero
if(!isSafeToVisit(h, obj->visitablePos()))
return true;
if (!shouldVisit(h, obj))
return true;
return false;
}),possibleDestinations.end());
@ -1134,7 +1130,7 @@ void VCAI::wander(const CGHeroInstance * h)
if(!goVisitObj(obj, h))
{
BNLOG("Hero %s apparently used all MPs (%d left)\n", h->name % h->movement);
alreadyVisited.push_back(obj); //reserve that object - we predict it will be reached soon
markObjectVisited(obj); //reserve that object - we predict it will be reached soon
setGoal(h, CGoal(VISIT_TILE).sethero(h).settile(obj->visitablePos()));
break;
}
@ -1183,6 +1179,15 @@ void VCAI::waitTillFree()
status.waitTillFree();
}
void VCAI::markObjectVisited (const CGObjectInstance *obj)
{
if(dynamic_cast<const CGVisitableOPH *>(obj) || //we may want to wisit it with another hero
dynamic_cast<const CGBonusingObject *>(obj) || //or another time
(obj->ID == Obj::MONSTER))
return;
alreadyVisited.push_back(obj);
}
void VCAI::validateVisitableObjs()
{
std::vector<const CGObjectInstance *> hlp;
@ -2476,7 +2481,9 @@ void SectorMap::write(crstring fname)
bool isWeeklyRevisitable (const CGObjectInstance * obj)
{ //TODO: allow polling of remaining creatures in dwelling
if (dynamic_cast<const CGVisitableOPW *>(obj) || dynamic_cast<const CGDwelling *>(obj)) //ensures future compatibility, unlike IDs
if (dynamic_cast<const CGVisitableOPW *>(obj) || //ensures future compatibility, unlike IDs
dynamic_cast<const CGDwelling *>(obj) ||
dynamic_cast<const CBank *>(obj)) //banks tend to respawn often in mods
return true;
switch (obj->ID)
{
@ -2486,6 +2493,36 @@ bool isWeeklyRevisitable (const CGObjectInstance * obj)
return false;
}
bool shouldVisit (const CGHeroInstance * h, const CGObjectInstance * obj)
{
if (obj->wasVisited(h))
return false;
switch (obj->ID)
{
case Obj::CREATURE_GENERATOR1:
{
bool canRecruitCreatures = false;
const CGDwelling * d = dynamic_cast<const CGDwelling *>(obj);
BOOST_FOREACH(auto level, d->creatures)
{
BOOST_FOREACH(auto c, level.second)
{
if (h->getSlotFor(c) != -1)
canRecruitCreatures = true;
}
}
return canRecruitCreatures;
}
case Obj::MONOLITH1:
case Obj::MONOLITH2:
case Obj::MONOLITH3:
case Obj::WHIRLPOOL:
//TODO: mehcanism for handling monoliths
return false;
}
return true;
}
int3 SectorMap::firstTileToGet(const CGHeroInstance *h, crint3 dst)
{
int sourceSector = retreiveTile(h->visitablePos()),

View File

@ -265,6 +265,7 @@ public:
void waitTillFree();
void addVisitableObj(const CGObjectInstance *obj);
void markObjectVisited (const CGObjectInstance *obj);
//void removeVisitableObj(const CGObjectInstance *obj);
void validateVisitableObjs();
void retreiveVisitableObjs(std::vector<const CGObjectInstance *> &out, bool includeOwned = false) const;
@ -292,4 +293,5 @@ bool objWithID(const CGObjectInstance *obj)
return obj->ID == id;
}
bool isWeeklyRevisitable (const CGObjectInstance * obj);
bool isWeeklyRevisitable (const CGObjectInstance * obj);
bool shouldVisit (const CGHeroInstance * h, const CGObjectInstance * obj);

View File

@ -74,6 +74,15 @@ void IObjectInterface::initObj()
void IObjectInterface::setProperty( ui8 what, ui32 val )
{}
bool IObjectInterface::wasVisited (ui8 player) const
{
return false;
}
bool IObjectInterface::wasVisited (const CGHeroInstance * h) const
{
return false;
}
void IObjectInterface::postInit()
{}
@ -86,7 +95,7 @@ void CPlayersVisited::setPropertyDer( ui8 what, ui32 val )
players.insert((ui8)val);
}
bool CPlayersVisited::hasVisited( ui8 player ) const
bool CPlayersVisited::wasVisited( ui8 player ) const
{
return vstd::contains(players,player);
}
@ -2424,6 +2433,11 @@ bool CGTownInstance::hasBuilt(int buildingID) const
return vstd::contains(builtBuildings, buildingID);
}
bool CGVisitableOPH::wasVisited (const CGHeroInstance * h) const
{
return vstd::contains(visitors, h->id);
}
void CGVisitableOPH::onHeroVisit( const CGHeroInstance * h ) const
{
if(visitors.find(h->id)==visitors.end())
@ -3479,6 +3493,10 @@ void CGVisitableOPW::newTurn() const
cb->setHoverName(id,&ms);
}
}
bool CGVisitableOPW::wasVisited(ui8 player) const
{
return !visited; //TODO: other players should see object as unvisited
}
void CGVisitableOPW::onHeroVisit( const CGHeroInstance * h ) const
{
@ -4642,7 +4660,7 @@ void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
InfoWindow iw;
iw.soundID = soundBase::gazebo;
iw.player = h->getOwner();
if(!hasVisited(h->tempOwner))
if(!wasVisited(h->tempOwner))
cb->setObjProperty(id,10,h->tempOwner);
if(h->getSecSkillLevel(static_cast<CGHeroInstance::SecondarySkill>(ability))) //you alredy know this skill
@ -4669,7 +4687,7 @@ void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const
const std::string & CGWitchHut::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
if(hasVisited(cb->getCurrentPlayer())) //TODO: use local player, not current
if(wasVisited(cb->getCurrentPlayer())) //TODO: use local player, not current
{
hoverName += "\n" + VLC->generaltexth->allTexts[356]; // + (learn %s)
boost::algorithm::replace_first(hoverName,"%s",VLC->generaltexth->skillName[ability]);
@ -4680,6 +4698,11 @@ const std::string & CGWitchHut::getHoverText() const
return hoverName;
}
bool CGBonusingObject::wasVisited (const CGHeroInstance * h) const
{
return h->hasBonusFrom(Bonus::OBJECT, ID);
}
void CGBonusingObject::onHeroVisit( const CGHeroInstance * h ) const
{
bool visited = h->hasBonusFrom(Bonus::OBJECT,ID);
@ -5302,7 +5325,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const
return;
}
if(!hasVisited(h->tempOwner))
if(!wasVisited(h->tempOwner))
cb->setObjProperty(id,10,h->tempOwner);
InfoWindow iw;
@ -5357,7 +5380,7 @@ void CGShrine::initObj()
const std::string & CGShrine::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
if(hasVisited(cb->getCurrentPlayer())) //TODO: use local player, not current
if(wasVisited(cb->getCurrentPlayer())) //TODO: use local player, not current
{
hoverName += "\n" + VLC->generaltexth->allTexts[355]; // + (learn %s)
boost::algorithm::replace_first(hoverName,"%s",VLC->spellh->spells[spell]->name);
@ -5597,7 +5620,7 @@ const std::string & CGOnceVisitable::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID] + " ";
hoverName += (hasVisited(cb->getCurrentPlayer())
hoverName += (wasVisited(cb->getCurrentPlayer())
? (VLC->generaltexth->allTexts[352]) //visited
: ( VLC->generaltexth->allTexts[353])); //not visited
@ -5872,6 +5895,11 @@ void CBank::newTurn() const
cb->setObjProperty (id, 11, 1); //daycounter++
}
}
bool CBank::wasVisited (ui8 player) const
{
return !bc;
}
void CBank::onHeroVisit (const CGHeroInstance * h) const
{
if (bc)
@ -6162,6 +6190,11 @@ const std::string & CGKeymasterTent::getHoverText() const
return hoverName;
}
bool CGKeymasterTent::wasVisited (ui8 player) const
{
return wasMyColorVisited (player);
}
void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
{
InfoWindow iw;
@ -6492,7 +6525,7 @@ void CGShipyard::onHeroVisit( const CGHeroInstance * h ) const
void CCartographer::onHeroVisit( const CGHeroInstance * h ) const
{
if (!hasVisited (h->getOwner()) ) //if hero has not visited yet this cartographer
if (!wasVisited (h->getOwner()) ) //if hero has not visited yet this cartographer
{
if (cb->getResource(h->tempOwner, 6) >= 1000) //if he can afford a map
{
@ -6567,7 +6600,7 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const
assert(ts);
int team = ts->id;
if(!hasVisited(team))
if(!wasVisited(team))
{
iw.text.addTxt(MetaString::ADVOB_TXT, 96);
cb->sendAndApply(&iw);
@ -6597,7 +6630,7 @@ void CGObelisk::initObj()
const std::string & CGObelisk::getHoverText() const
{
hoverName = VLC->generaltexth->names[ID];
if(hasVisited(cb->getCurrentPlayer()))
if(wasVisited(cb->getCurrentPlayer()))
hoverName += " " + VLC->generaltexth->allTexts[352]; //not visited
else
hoverName += " " + VLC->generaltexth->allTexts[353]; //visited

View File

@ -93,6 +93,9 @@ public:
virtual void newTurn() const;
virtual void initObj(); //synchr
virtual void setProperty(ui8 what, ui32 val);//synchr
//unified interface, AI helpers
virtual bool wasVisited (ui8 player) const;
virtual bool wasVisited (const CGHeroInstance * h) const;
static void preInit(); //called before objs receive their initObj
static void postInit();//caleed after objs receive their initObj
@ -177,6 +180,7 @@ public:
//CGObjectInstance(const CGObjectInstance & right);
//CGObjectInstance& operator=(const CGObjectInstance & right);
virtual const std::string & getHoverText() const;
//////////////////////////////////////////////////////////////////////////
void initObj();
void onHeroVisit(const CGHeroInstance * h) const;
@ -210,7 +214,7 @@ class DLL_LINKAGE CPlayersVisited: public CGObjectInstance
public:
std::set<ui8> players; //players that visited this object
bool hasVisited(ui8 player) const;
bool wasVisited(ui8 player) const;
virtual void setPropertyDer( ui8 what, ui32 val );
template <typename Handler> void serialize(Handler &h, const int version)
@ -464,6 +468,7 @@ public:
void onHeroVisit(const CGHeroInstance * h) const;
void onNAHeroVisit(int heroID, bool alreadyVisited) const;
void initObj();
bool wasVisited (const CGHeroInstance * h) const;
void treeSelected(int heroID, int resType, int resVal, expType expVal, ui32 result) const; //handle player's anwer to the Tree of Knowledge dialog
void schoolSelected(int heroID, ui32 which) const;
void arenaSelected(int heroID, int primSkill) const;
@ -921,7 +926,7 @@ public:
void offerLeavingGuards(const CGHeroInstance *h) const;
void endBattle(BattleResult *result, ui8 attackingPlayer) const;
void fight(ui32 agreed, const CGHeroInstance *h) const;
void onHeroVisit(const CGHeroInstance * h) const;
void flagMine(ui8 player) const;
@ -941,6 +946,7 @@ public:
ui8 visited; //true if object has been visited this week
void setPropertyDer(ui8 what, ui32 val);//synchr
bool wasVisited(ui8 player) const;
void onHeroVisit(const CGHeroInstance * h) const;
void newTurn() const;
@ -970,6 +976,7 @@ public:
class DLL_LINKAGE CGBonusingObject : public CGObjectInstance //objects giving bonuses to luck/morale/movement
{
public:
bool wasVisited (const CGHeroInstance * h) const;
void onHeroVisit(const CGHeroInstance * h) const;
const std::string & getHoverText() const;
void initObj();
@ -1047,6 +1054,7 @@ public:
class DLL_LINKAGE CGKeymasterTent : public CGKeys
{
public:
bool wasVisited (ui8 player) const;
void onHeroVisit(const CGHeroInstance * h) const;
const std::string & getHoverText() const;
@ -1132,6 +1140,7 @@ class DLL_LINKAGE CBank : public CArmedInstance
void initialize() const;
void reset(ui16 var1);
void newTurn() const;
bool wasVisited (ui8 player) const;
virtual void onHeroVisit (const CGHeroInstance * h) const;
virtual void fightGuards (const CGHeroInstance *h, ui32 accept) const;
virtual void endBattle (const CGHeroInstance *h, const BattleResult *result) const;