handle separately water and ground

The forbidden zones must be set in the primitives, in the fauna name = "Ybers:Ground|NoGo"
This commit is contained in:
depyraken 2016-03-30 02:56:09 +02:00
parent 7517200cc7
commit 42aeac0243
8 changed files with 154 additions and 76 deletions

View file

@ -501,7 +501,7 @@ void CSpawnBotFauna::getBestTarget()
if ( canMove()
&& !player->isAggressive()
&& entity->wpos().isValid()
&& (entity->wpos().getFlags()&entity->getAStarFlag())==0)
&& isPlaceAllowed(entity->getAStarFlag(), entity->wpos().getFlags()))
{
// Suppose we can go to him
bool canChange = true;
@ -706,7 +706,7 @@ void CSpawnBotFauna::getBestTarget()
if ( profile
&& profile->getAIProfileType()==ACTIVITY_CORPSE
&& botCreat->wpos().isValid()
&& !(botCreat->wpos().getFlags()&botCreat->getAStarFlag())
&& isPlaceAllowed(botCreat->getAStarFlag(), botCreat->wpos().getFlags())
)
{
CCorpseFaunaProfile *corpseProfile=NLMISC::safe_cast<CCorpseFaunaProfile*>(profile);
@ -951,7 +951,7 @@ void CMovementMagnet::getNewDestination(RYAI_MAP_CRUNCH::CWorldPosition const& a
continue;
if ( !faunaBot->wpos().isValid()
|| (faunaBot->wpos().getFlags()&denyFlag)!=0)
|| !isPlaceAllowed(denyFlag, faunaBot->wpos().getFlags()))
continue;
// can be optimize by in avoid inversion.
@ -990,7 +990,7 @@ void CMovementMagnet::getNewDestination(RYAI_MAP_CRUNCH::CWorldPosition const& a
// check if its a nogo and water proof position.
if ( !wRndPos.isValid()
|| (wRndPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlag)!=0 )
|| !isPlaceAllowed(denyFlag, wRndPos.getTopologyRef().getCstTopologyNode().getFlags()))
continue;
#if !FINAL_VERSION
@ -1126,7 +1126,7 @@ CReturnMovementMagnet::CReturnMovementMagnet(RYAI_MAP_CRUNCH::CWorldPosition con
void CReturnMovementMagnet::getNewDestination(RYAI_MAP_CRUNCH::CWorldPosition const& alternativePos, RYAI_MAP_CRUNCH::TAStarFlag denyFlag)
{
if (_ForcedDest.isValid() && (_ForcedDest.getTopologyRef().getCstTopologyNode().getFlags()&denyFlag)==0)
if (_ForcedDest.isValid() && isPlaceAllowed(denyFlag, _ForcedDest.getTopologyRef().getCstTopologyNode().getFlags()))
_PathCont.setDestination(_ForcedDest);
else
CMovementMagnet::getNewDestination(alternativePos, denyFlag);

View file

@ -309,7 +309,7 @@ void CBotProfileFlee::updateProfile(uint ticksSinceLastUpdate)
{
RYAI_MAP_CRUNCH::CWorldPosition wpos=rootCell->getWorldPosition(_Bot->getPersistent().getChildIndex()&3);
if ( wpos.isValid()
&& (wpos.getFlags()&_DenyFlags)==0 ) // verify that we got some compatible flags ..
&& isPlaceAllowed(_DenyFlags, wpos.getFlags())) // verify that we got some compatible flags ..
{
_LastDir=startDir;
_LastStartPos=_Bot->wpos();

View file

@ -374,7 +374,7 @@ bool s_move(
0.5f);
// If we can't follow the path or the computed pos is invalid
if ( status==CFollowPath::FOLLOW_NO_PATH
|| (_Bot->wpos().isValid() && (_Bot->wpos().getFlags()&_Bot->getAStarFlag())!=0))
|| (_Bot->wpos().isValid() && !isPlaceAllowed(_Bot->getAStarFlag(), _Bot->wpos().getFlags())))
{
// Restore position
_Bot->setPos(lastPos);
@ -605,7 +605,7 @@ static void s_updateProfile(
_AtAttackDist = norm < _RangeMax;
// Check if target can be attacked
bool const targetInForbiddenZone = ((!target->wpos().isValid())||(target->wpos().getFlags()&_Bot->getAStarFlag())!=0);
bool const targetInForbiddenZone = ((!target->wpos().isValid())||!isPlaceAllowed(_Bot->getAStarFlag(), target->wpos().getFlags()));
/****************************************************************************/
/* Profile main processing */

View file

@ -836,7 +836,7 @@ bool CGrpFauna::spawnPop(uint popVersion)
if (!places()[i]->worldValidPos().isValid())
return false;
const RYAI_MAP_CRUNCH::TAStarFlag flags=places()[i]->worldValidPos().getTopologyRef().getCstTopologyNode().getFlags();
if ((flags&getAStarFlag())!=0)
if(!isPlaceAllowed(getAStarFlag(), flags)) // if place is not allowed - we now deal with creatures that can't go on the ground
return false;
}

View file

@ -97,12 +97,37 @@ IAliasCont* CMgrFauna::getAliasCont(TAIType type)
CAliasTreeOwner* CMgrFauna::createChild(IAliasCont* cont, CAIAliasDescriptionNode* aliasTree)
{
RYAI_MAP_CRUNCH::TAStarFlag flags = RYAI_MAP_CRUNCH::Nothing;
// this hack is to retrieve the AStar flags from the fauna group. We expect the groupname to be as follows : groupname:AStarFlag[|AStarFlag]
std::string key, tail;
std::string p = NLMISC::toLower(this->getAliasFullName()); // force lowercase
AI_SHARE::stringToKeywordAndTail(p, key, tail);
int bAstarFlags = 0;
if (!tail.empty()){ //AStarFlags were provided
bAstarFlags = 1;
vector<string> sFlags;
NLMISC::splitString(tail, "|", sFlags);
FOREACHC(it, vector<string>, sFlags){
TAStarFlag tmpflag = RYAI_MAP_CRUNCH::toAStarFlag(*it);
if( (tmpflag == TAStarFlag::Nothing) &&
it->compare("nothing")){ // this is not a valid AStarFlags => Let's preserve the default way the fauna is handled
bAstarFlags = 0;
break;
}
flags = RYAI_MAP_CRUNCH::TAStarFlag( flags | tmpflag);
}
}
if(!bAstarFlags){
flags = WaterAndNogo;
}
CAliasTreeOwner* child = NULL;
switch (aliasTree->getType())
{
case AITypeGrp:
child = new CGrpFauna(this, aliasTree, WaterAndNogo);
child = new CGrpFauna(this, aliasTree, flags);
break;
case AITypeEvent:
child = new CAIEventReaction(getStateMachine(), aliasTree);

View file

@ -1530,7 +1530,10 @@ bool CCellZone::findRestAndFoodFaunaZoneInCellList(CFaunaZone const*& rest, CPro
CPropertySet activities[CCellChoice::MAX_ZONE_SCORE];
activities[CCellChoice::FOOD_ZONE_SCORE].merge(foodActivity);
activities[CCellChoice::REST_ZONE_SCORE].merge(restActivity);
CPossibleTAStarFlags PossibleTAStarFlags; // possible TAStarFlags
const int nFlags = PossibleTAStarFlags.buildTAStarFlagsList(denyflags); // we build the list according to the deny flags
// Look for a conveninent zone in a convenient cell.
if (extensiveDebug) nldebug("ED0001.02: cells.size()=%d", cells.size());
// For each cell
@ -1586,22 +1589,15 @@ bool CCellZone::findRestAndFoodFaunaZoneInCellList(CFaunaZone const*& rest, CPro
continue;
}
TAStarFlag const flags = (TAStarFlag)(wpos.getFlags()&GroundFlags); // Erase unused flags.
float const score = faunaZone->getFreeAreaScore();
for (TAStarFlag possibleFlag=Nothing;possibleFlag<=GroundFlags;possibleFlag=(TAStarFlag)(possibleFlag+2)) // tricky !! -> to replace with a defined list of flags to checks.
{
const uint32 incompatibilityFlags=possibleFlag&denyflags&GroundFlags; // Erase unused flags.
if (incompatibilityFlags)
{
if (extensiveDebug) nldebug("ED0001.06: incompatibilityFlags");
continue;
}
for(int i = 0;i < nFlags;i++){
TAStarFlag possibleFlag = PossibleTAStarFlags.get(i);
const uint32 masterTopo=wpos.getTopologyRef().getCstTopologyNode().getMasterTopo(possibleFlag);
if (masterTopo==~0)
if(masterTopo==CTopology::TTopologyId::UNDEFINED_TOPOLOGY)
{
if (extensiveDebug) nldebug("ED0001.07: masterTopo==~0");
if (extensiveDebug) nldebug("ED0001.07: CTopology::TTopologyId::UNDEFINED_TOPOLOGY");
continue;
}
@ -1611,7 +1607,7 @@ bool CCellZone::findRestAndFoodFaunaZoneInCellList(CFaunaZone const*& rest, CPro
continue;
}
CCellChoice::CZoneScore &zoneScore=searchMap[possibleFlag][masterTopo].zones[typeZone];
CCellChoice::CZoneScore &zoneScore=searchMap[possibleFlag & WaterAndNogo][masterTopo].zones[typeZone];
if (score<zoneScore.score)
{
@ -1662,8 +1658,8 @@ bool CCellZone::findRestAndFoodFaunaZoneInCellList(CFaunaZone const*& rest, CPro
#if !FINAL_VERSION
const RYAI_MAP_CRUNCH::TAStarFlag restFlags=rest->worldValidPos().getTopologyRef().getCstTopologyNode().getFlags();
const RYAI_MAP_CRUNCH::TAStarFlag foodFlags=food->worldValidPos().getTopologyRef().getCstTopologyNode().getFlags();
nlassert((restFlags&denyflags)==0);
nlassert((foodFlags&denyflags)==0);
nlassert(isPlaceAllowed(denyflags, restFlags));
nlassert(isPlaceAllowed(denyflags, foodFlags));
#endif
return true;
}
@ -1740,7 +1736,7 @@ const CFaunaZone *CCellZone::lookupFaunaZone(const CPropertySet &activity, TASta
}
const RYAI_MAP_CRUNCH::TAStarFlag flags=faunaZone->worldValidPos().getTopologyRef().getCstTopologyNode().getFlags();
if (flags&denyflags)
if (!isPlaceAllowed(denyflags, flags))
continue;
const float score=faunaZone->getFreeAreaScore();

View file

@ -34,6 +34,9 @@ NL_BEGIN_STRING_CONVERSION_TABLE (TAStarFlag)
NL_STRING_CONVERSION_TABLE_ENTRY(NoGo)
NL_STRING_CONVERSION_TABLE_ENTRY(WaterAndNogo)
NL_STRING_CONVERSION_TABLE_ENTRY(GroundFlags)
NL_STRING_CONVERSION_TABLE_ENTRY(Ground)
NL_STRING_CONVERSION_TABLE_ENTRY(GroundAndNogo)
NL_STRING_CONVERSION_TABLE_ENTRY(GroundAndWaterAndNogo)
NL_END_STRING_CONVERSION_TABLE(TAStarFlag, AStarFlagConversion, Nothing)
const std::string& toString(TAStarFlag flag)
@ -781,14 +784,14 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
return false;
tmpPos=tmpPos.getPosS();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
if (!tmpPos.getCellLinkage().isESlotValid())
return false;
tmpPos=tmpPos.getPosE();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
}
@ -798,7 +801,7 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
return false;
tmpPos=tmpPos.getPosE();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
if (!tmpPos.getCellLinkage().isSSlotValid())
@ -819,14 +822,14 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
return false;
tmpPos=tmpPos.getPosN();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
if (!tmpPos.getCellLinkage().isESlotValid())
return false;
tmpPos=tmpPos.getPosE();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
}
@ -836,7 +839,7 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
return false;
tmpPos=tmpPos.getPosE();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
if (!tmpPos.getCellLinkage().isNSlotValid())
@ -856,14 +859,14 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
return false;
tmpPos=tmpPos.getPosN();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
if (!tmpPos.getCellLinkage().isWSlotValid())
return false;
tmpPos=tmpPos.getPosW();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
}
@ -873,7 +876,7 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
return false;
tmpPos=tmpPos.getPosW();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
if (!tmpPos.getCellLinkage().isNSlotValid())
@ -893,14 +896,14 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
return false;
tmpPos=tmpPos.getPosS();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
if (!tmpPos.getCellLinkage().isWSlotValid())
return false;
tmpPos=tmpPos.getPosW();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
}
@ -910,7 +913,7 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
return false;
tmpPos=tmpPos.getPosW();
if ((tmpPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0)
if (!isPlaceAllowed(denyFlags, tmpPos.getTopologyRef().getCstTopologyNode().getFlags()))
return false;
if (!tmpPos.getCellLinkage().isSSlotValid())
@ -1348,29 +1351,21 @@ void CWorldMap::countCells(uint &compute, uint &white, uint &simple, uint &multi
const CTopology &startTopoNode=startPos.getTopologyRef().getCstTopologyNode();
const CTopology &endTopoNode=endPos.getTopologyRef().getCstTopologyNode();
TAStarFlag startFlag=(TAStarFlag)(startTopoNode.getFlags()&WaterAndNogo);
// if (!allowStartRestriction)
startFlag=Nothing;
CPossibleTAStarFlags PossibleTAStarFlags; // build a list of possible flags given the denyflags
const int nFlags = PossibleTAStarFlags.buildTAStarFlagsList(denyflags);
for (TAStarFlag possibleFlag=Nothing;possibleFlag<=WaterAndNogo;possibleFlag=(TAStarFlag)(possibleFlag+2)) // tricky !! -> to replace with a defined list of flags to checks.
{
const uint32 incompatibilityFlags=(possibleFlag&(denyflags&~startFlag))&WaterAndNogo;
if (incompatibilityFlags)
continue;
const uint32 startMasterTopo=startTopoNode.getMasterTopo(possibleFlag);
const uint32 endMasterTopo=endTopoNode.getMasterTopo(possibleFlag);
if ( (startMasterTopo^endMasterTopo)!=0
|| startMasterTopo == std::numeric_limits<uint32>::max()) // if not same masterTopo or invalid masterTopo then bypass ..
continue;
res.set(possibleFlag, startMasterTopo);
res.setValid();
if (((possibleFlag&denyflags)&WaterAndNogo)==0) // it was the optimal case ?
break;
for(int i = 0;i < nFlags;i++){ // for each possible flag
TAStarFlag possibleFlag = PossibleTAStarFlags.get(i);
uint32 startMasterTopo=startTopoNode.getMasterTopo(possibleFlag);
uint32 endMasterTopo=endTopoNode.getMasterTopo(possibleFlag);
if( (startMasterTopo^endMasterTopo)!=0 ||
(startMasterTopo == CTopology::TTopologyId::UNDEFINED_TOPOLOGY)){ // if not same masterTopo or invalid masterTopo then continue
continue;
}
res.set(possibleFlag, startMasterTopo);
res.setValid();
break;
}
}
@ -1665,7 +1660,7 @@ bool CWorldMap::findAStarPath(const CTopology::TTopologyId &start, const CTopolo
const CTopology &ntp = next.getCstTopologyNode();
// don't examine not accessible nodes
if ((ntp.Flags & denyflags) != 0)
if (!isPlaceAllowed(denyflags,(RYAI_MAP_CRUNCH::TAStarFlag) ntp.Flags))
continue;
// compute actual node distance
@ -1821,7 +1816,7 @@ bool CWorldMap::findInsideAStarPath(CWorldPosition const& start, CWorldPosition
continue;
// If that point's flags are not compatible skip it
if ((denyflags & mv.getTopologyRef().getCstTopologyNode().getFlags()) != 0)
if (!isPlaceAllowed(denyflags, mv.getTopologyRef().getCstTopologyNode().getFlags()))
continue;
// Build an A* node
@ -1927,7 +1922,7 @@ bool CWorldMap::move(CWorldPosition &pos, CAStarPath &path, uint &currentstep) c
bool CWorldMap::move(CWorldPosition& pos, CMapPosition const& end, TAStarFlag const denyFlags) const
{
CWorldPosition tempPos(pos);
BOMB_IF((tempPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0, "Error in CWorldMap::mode, invalid flag "<<RYAI_MAP_CRUNCH::toString(tempPos.getTopologyRef().getCstTopologyNode().getFlags())
BOMB_IF(!isPlaceAllowed(denyFlags, tempPos.getTopologyRef().getCstTopologyNode().getFlags()), "Error in CWorldMap::mode, invalid flag "<<RYAI_MAP_CRUNCH::toString(tempPos.getTopologyRef().getCstTopologyNode().getFlags())
<<"on world pos "<<pos.toString()<<" while going to map pos "<<end.toString()<<" with denyflags "<<RYAI_MAP_CRUNCH::toString(denyFlags), return false);
// not optimum but it will be rewrite for each specialized rootcell type.
const sint32 x0 = pos.x();
@ -1945,7 +1940,7 @@ bool CWorldMap::move(CWorldPosition& pos, CMapPosition const& end, TAStarFlag co
if ( !move(tempPos, CDirection(dx,dy))
|| (tempPos.getTopologyRef().getCstTopologyNode().getFlags()&denyFlags)!=0) // Arghh !!
|| !isPlaceAllowed(denyFlags, tempPos.getTopologyRef().getCstTopologyNode().getFlags())) // Arghh !!
return false;
pos=tempPos;
}

View file

@ -52,18 +52,74 @@ enum TAStarFlag
Water = 2,
NoGo = 4,
WaterAndNogo = 6,
GroundFlags = WaterAndNogo
GroundFlags = WaterAndNogo,
Ground = 8,
GroundAndNogo = 12,
GroundAndWaterAndNogo = 14
};
const std::string& toString(TAStarFlag flag);
TAStarFlag toAStarFlag(const std::string& str);
inline int isPlaceAllowed(TAStarFlag denyFlags, TAStarFlag flags){ // check if the place is allowed given the denyFlags and flags
if(denyFlags & Ground){ // in case of ground is denied
return ((flags & denyFlags) == 0) && // denied flags against the current flags
(flags & Water); // check the current flag is in the water
} else {
return (flags & denyFlags) == 0; // denied flags against the current flags
}
}
uint const WorldMapGridSize = 256;
double const WorldGridResolution = 1.;
NLMISC::CVectorD const WorldStartOffset = NLMISC::CVectorD(0., 0., 0.);
typedef sint TLevel;
class CPossibleTAStarFlags { // class to create a list of possible TAStarFlags
private:
uint8 nFlags;
uint8 aFlags[3];
public:
CPossibleTAStarFlags() : nFlags(0){ // default constructor
}
int buildTAStarFlagsList(const TAStarFlag denyflags){
nFlags = 0;
if(denyflags & Ground){ // ground forbidden
if(!(denyflags & Water)){ // Water possible
aFlags[nFlags++] = (uint8)(Water | Ground);
if(!(denyflags & NoGo)){ // Water and NoGo possible
aFlags[nFlags++] = (uint8)(Water | NoGo | Ground);
}
}
} else { // ground possible
aFlags[nFlags++] = (uint8)(Nothing);
if(!(denyflags & Water)){ // Ground and Water possible
aFlags[nFlags++] = (uint8)(Water);
if(!(denyflags & NoGo)){ // Ground, Water and NoGo possible
aFlags[nFlags++] = (uint8)(Water | NoGo);
}
} else {
if(!(denyflags & NoGo)){ // Ground and NoGo possible
aFlags[nFlags++] = (uint8)(NoGo);
}
}
}
return nFlags;
}
int size(){ // returns the size of the list of possible TAStarFlags
return nFlags;
}
TAStarFlag get(int nIndex){ // returns a possible TAStarFlag
return (TAStarFlag)aFlags[nIndex];
}
CPossibleTAStarFlags(const TAStarFlag denyflags){ //constructor, build a possible TAStarFlag list
buildTAStarFlagsList(denyflags);
}
};
//////////////////////////////////////////////////////////////////////////////
@ -1573,17 +1629,23 @@ void CTopology::updateTopologyRef(CWorldMap* worldMapPtr)
inline
uint32 CTopology::getMasterTopo(TAStarFlag const& flags) const
{
switch (flags&WaterAndNogo)
{
case Nothing:
default:
return MasterTopL;
case Water:
return MasterTopLW;
case NoGo:
return MasterTopLN;
case WaterAndNogo:
return MasterTopLNW;
switch (flags&(WaterAndNogo | Ground))
{
case Nothing:
default:
return MasterTopL;
case Water:
return MasterTopLW;
case NoGo:
return MasterTopLN;
case WaterAndNogo:
return MasterTopLNW;
case Water|Ground:
return (MasterTopL == TTopologyId::UNDEFINED_TOPOLOGY) ? MasterTopLW : TTopologyId::UNDEFINED_TOPOLOGY;
case Water|Ground|NoGo:
return (MasterTopL == TTopologyId::UNDEFINED_TOPOLOGY) ? MasterTopLNW : TTopologyId::UNDEFINED_TOPOLOGY;
case NoGo|Ground:
return TTopologyId::UNDEFINED_TOPOLOGY;
}
}