282 lines
8.8 KiB
Plaintext
282 lines
8.8 KiB
Plaintext
|
////////////////////////////////////////////////////////////////////////
|
||
|
// Waypoint Pathing System
|
||
|
// By Deva Bryson Winblood 12/01/2003
|
||
|
////////////////////////////////////////////////////////////////////////
|
||
|
// Pathing works exclusively between lairs with exception of option 4
|
||
|
|
||
|
void fnBuildTransRand(object oArea)
|
||
|
{ // build a list of transitions from this area
|
||
|
int nC=0;
|
||
|
int nL=1;
|
||
|
object oFirst=GetFirstObjectInArea(oArea);
|
||
|
object oTrans;
|
||
|
oFirst=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,1);
|
||
|
//SendMessageToPC(GetFirstPC(),"fnBuildTransRand()");
|
||
|
if (oFirst!=OBJECT_INVALID)
|
||
|
{
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_TRIGGER,oFirst,nL);
|
||
|
while(oTrans!=OBJECT_INVALID)
|
||
|
{ // triggers
|
||
|
if(GetTransitionTarget(oTrans)!=OBJECT_INVALID)
|
||
|
{ // transition
|
||
|
nC++;
|
||
|
SetLocalObject(oArea,"oPathingTrans"+IntToString(nC),oTrans);
|
||
|
} // transition
|
||
|
nL++;
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_TRIGGER,oFirst,nL);
|
||
|
} // triggers
|
||
|
nL=1;
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_DOOR,oFirst,nL);
|
||
|
while(oTrans!=OBJECT_INVALID)
|
||
|
{ // doors
|
||
|
if(GetTransitionTarget(oTrans)!=OBJECT_INVALID)
|
||
|
{ // transition
|
||
|
nC++;
|
||
|
SetLocalObject(oArea,"oPathingTrans"+IntToString(nC),oTrans);
|
||
|
} // transition
|
||
|
nL++;
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_DOOR,oFirst,nL);
|
||
|
} // doors
|
||
|
SetLocalInt(oArea,"nPathingTC",nC);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
AssignCommand(OBJECT_SELF,SpeakString("This area is impossible to escape!!!"));
|
||
|
SendMessageToPC(GetFirstPC(),"RTS SETUP ERROR: Area "+GetName(oArea)+" has no transitions!");
|
||
|
}
|
||
|
} // fnBuildTransRand()
|
||
|
|
||
|
void fnBuildObjectRand(object oArea)
|
||
|
{ // build a list of objects
|
||
|
int nC=0;
|
||
|
int nL=1;
|
||
|
object oFirst=GetFirstObjectInArea(oArea);
|
||
|
object oTrans;
|
||
|
//SendMessageToPC(GetFirstPC(),"fnBuildObjectRand()");
|
||
|
oFirst=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,1);
|
||
|
if (oFirst!=OBJECT_INVALID)
|
||
|
{
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_PLACEABLE,oFirst,nL);
|
||
|
while(oTrans!=OBJECT_INVALID)
|
||
|
{ // placeables
|
||
|
nC++;
|
||
|
SetLocalObject(oArea,"oPathingObs"+IntToString(nC),oTrans);
|
||
|
nL++;
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_PLACEABLE,oFirst,nL);
|
||
|
} // placeables
|
||
|
nL=1;
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,nL);
|
||
|
while(oTrans!=OBJECT_INVALID)
|
||
|
{ // waypoints
|
||
|
nC++;
|
||
|
SetLocalObject(oArea,"oPathingObs"+IntToString(nC),oTrans);
|
||
|
nL++;
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,nL);
|
||
|
} // waypoints
|
||
|
nC++;
|
||
|
SetLocalObject(oArea,"oPathingObs"+IntToString(nC),oFirst);
|
||
|
SetLocalInt(oArea,"nPathingOC",nC);
|
||
|
}
|
||
|
} // fnBuildObjectRand()
|
||
|
|
||
|
int fnPathValue(object oArea,string sID)
|
||
|
{ // returns path value for area based on team
|
||
|
int nRet=1000; // 1000 = avoid it!
|
||
|
object oFirst=GetFirstObjectInArea(oArea);
|
||
|
object oWP=GetNearestObjectByTag("PATHINGA",oFirst,1);
|
||
|
string sName;
|
||
|
int nPos;
|
||
|
string sL;
|
||
|
if (oWP==OBJECT_INVALID) oWP=GetNearestObjectByTag("PATHINGB",oFirst,1);
|
||
|
if (oWP==OBJECT_INVALID)
|
||
|
{ // check to see if the first object was the waypoint
|
||
|
if(GetTag(oFirst)=="PATHINGA"||GetTag(oFirst)=="PATHINGB") oWP=oFirst;
|
||
|
} // check to see if the first object was the waypoint
|
||
|
if (oWP!=OBJECT_INVALID)
|
||
|
{ //!OI
|
||
|
sName=GetName(oWP);
|
||
|
if (sName!="AVOID")
|
||
|
{ // !AVOID
|
||
|
if (sID=="UND") nPos=0;
|
||
|
else if (sID=="UNC") nPos=1;
|
||
|
else if (sID=="SPID") nPos=2;
|
||
|
else if (sID=="DWF") nPos=3;
|
||
|
sL=GetSubString(sName,nPos,1);
|
||
|
if (sL=="A") nRet=10;
|
||
|
else if (sL=="B") nRet=11;
|
||
|
else if (sL=="C") nRet=12;
|
||
|
else
|
||
|
{
|
||
|
nRet=StringToInt(sL);
|
||
|
}
|
||
|
} // !AVOID
|
||
|
} //!OI
|
||
|
return nRet;
|
||
|
} // fnPathValue()
|
||
|
|
||
|
|
||
|
object fnGetTransition(object oArea,int nNum)
|
||
|
{ // returns the specified transition object
|
||
|
object oTrans=OBJECT_INVALID;
|
||
|
oTrans=GetLocalObject(oArea,"oPathingTrans"+IntToString(nNum));
|
||
|
return oTrans;
|
||
|
} // fnGetTransition()
|
||
|
|
||
|
int fnIsAboveGroundDestination(object oTrans)
|
||
|
{ // does this transition lead to an above ground location
|
||
|
int nRet=FALSE;
|
||
|
object oDest=GetTransitionTarget(oTrans);
|
||
|
object oFirst=GetFirstObjectInArea(GetArea(oTrans));
|
||
|
if (GetTag(oFirst)=="PATHINGA") nRet=TRUE;
|
||
|
else
|
||
|
{ // test
|
||
|
oDest=GetNearestObjectByTag("PATHINGA",oFirst,1);
|
||
|
if (oDest!=OBJECT_INVALID) nRet=TRUE;
|
||
|
} // test
|
||
|
return nRet;
|
||
|
} // fnIsAboveGroundDestination()
|
||
|
|
||
|
object fnPathNextDestination(object oCurrentArea,string sDestID,int nOpt=0)
|
||
|
{ /* Find an object in next destination and return it
|
||
|
OPTIONS: 0 = Path choosing preferably the same area type as current
|
||
|
1 = Path choosing preferably underground ways
|
||
|
2 = Path choosing preferably aboveground ways
|
||
|
3 = Path choosing below ground during day, above ground at night
|
||
|
4 = Below ground a MUST! Also seek below ground shelter
|
||
|
NOTE: the above ground areas are generally less cluttered and thus offer
|
||
|
faster travel. So, option 3 is best for creatures with low light sensitivity.
|
||
|
Option 4 is suggested for light fatal creatures DURING THE day
|
||
|
*/
|
||
|
object oRet=OBJECT_INVALID;
|
||
|
int nCurrentPos=fnPathValue(oCurrentArea,sDestID);
|
||
|
object oBest=OBJECT_INVALID;
|
||
|
int nBest=100;
|
||
|
object oNonPref=OBJECT_INVALID;
|
||
|
int nNonPref=101;
|
||
|
int nL;
|
||
|
int nCur;
|
||
|
object oTrans;
|
||
|
object oDest;
|
||
|
int nC=GetLocalInt(oCurrentArea,"nPathingTC");
|
||
|
if (nC==0)
|
||
|
{ // need to build pathing info
|
||
|
fnBuildTransRand(oCurrentArea);
|
||
|
nC=GetLocalInt(oCurrentArea,"nPathingTC");
|
||
|
} // need to builg pathing info
|
||
|
nL=1;
|
||
|
while(nL<=nC)
|
||
|
{ // test transitions
|
||
|
oTrans=fnGetTransition(oCurrentArea,nL);
|
||
|
oDest=GetTransitionTarget(oTrans);
|
||
|
nCur=fnPathValue(GetArea(oDest),sDestID);
|
||
|
if (nCur<nBest||(nCur==nBest&&d4()<3))
|
||
|
{ // might be a good destination
|
||
|
if (nOpt==0)
|
||
|
{ // whatever works
|
||
|
nBest=nCur;
|
||
|
oBest=oDest;
|
||
|
} // whatever works
|
||
|
else if (nOpt==1)
|
||
|
{ // prefer underground
|
||
|
if (fnIsAboveGroundDestination(oTrans)==TRUE)
|
||
|
{ // above ground
|
||
|
if (nCur<=nNonPref)
|
||
|
{ // set nonpref
|
||
|
nNonPref=nCur;
|
||
|
oNonPref=oDest;
|
||
|
} // set nonpref
|
||
|
} // above ground
|
||
|
else
|
||
|
{ // below ground
|
||
|
nBest=nCur;
|
||
|
oBest=oDest;
|
||
|
} // below ground
|
||
|
} // prefer underground
|
||
|
else if (nOpt==2)
|
||
|
{ // prefer aboveground
|
||
|
if (fnIsAboveGroundDestination(oTrans)==TRUE)
|
||
|
{ // above ground
|
||
|
nBest=nCur;
|
||
|
oBest=oDest;
|
||
|
} // above ground
|
||
|
else
|
||
|
{ // below ground
|
||
|
if (nCur<nNonPref||(nCur==nNonPref&&d4()<3))
|
||
|
{ // set nonpref
|
||
|
nNonPref=nCur;
|
||
|
oNonPref=oDest;
|
||
|
} // set nonpref
|
||
|
} // below ground
|
||
|
} // prefer aboveground
|
||
|
else if (nOpt==3)
|
||
|
{ // day/night preference
|
||
|
if (GetIsDay()==TRUE||GetIsDawn()==TRUE)
|
||
|
{ // day time
|
||
|
if (fnIsAboveGroundDestination(oTrans)==TRUE)
|
||
|
{ // above ground
|
||
|
if (nCur<nNonPref||(nCur==nNonPref&&d4()<3))
|
||
|
{ // set nonpref
|
||
|
nNonPref=nCur;
|
||
|
oNonPref=oDest;
|
||
|
} // set nonpref
|
||
|
} // above ground
|
||
|
else
|
||
|
{ // below ground
|
||
|
nBest=nCur;
|
||
|
oBest=oDest;
|
||
|
} // below ground
|
||
|
} // day time
|
||
|
else
|
||
|
{ // night time
|
||
|
if (fnIsAboveGroundDestination(oTrans)==TRUE)
|
||
|
{ // above ground
|
||
|
nBest=nCur;
|
||
|
oBest=oDest;
|
||
|
} // above ground
|
||
|
else
|
||
|
{ // below ground
|
||
|
if (nCur<nNonPref||(nCur==nNonPref&&d4()<3))
|
||
|
{ // set nonpref
|
||
|
nNonPref=nCur;
|
||
|
oNonPref=oDest;
|
||
|
} // set nonpref
|
||
|
} // below ground
|
||
|
} // night time
|
||
|
} // day/night preference
|
||
|
else if (nOpt==4)
|
||
|
{ // if day MUST use below ground
|
||
|
if (GetIsDay()==TRUE||GetIsDawn()==TRUE)
|
||
|
{
|
||
|
if (fnIsAboveGroundDestination(oTrans)==FALSE)
|
||
|
{ // good destination
|
||
|
oBest=oDest;
|
||
|
nBest=nCur;
|
||
|
} // good destination
|
||
|
}
|
||
|
else
|
||
|
{ // any will do
|
||
|
oBest=oDest;
|
||
|
nBest=nCur;
|
||
|
} // any will do
|
||
|
} // if day MUST use below ground
|
||
|
} // might be a good destination
|
||
|
nL++;
|
||
|
} // test transitions
|
||
|
if (nNonPref<nBest)
|
||
|
{ // use non-prefered
|
||
|
oDest=oNonPref;
|
||
|
} // use non-prefered
|
||
|
else
|
||
|
{ // use the best
|
||
|
oDest=oBest;
|
||
|
} // use the best
|
||
|
if (oDest!=OBJECT_INVALID)
|
||
|
{ // choose nearby dest
|
||
|
oTrans=GetNearestObject(OBJECT_TYPE_WAYPOINT,oDest,d4());
|
||
|
if (oTrans==OBJECT_INVALID) oTrans=GetNearestObject(OBJECT_TYPE_WAYPOINT,oDest,1);
|
||
|
if (oTrans==OBJECT_INVALID) oTrans=GetNearestObject(OBJECT_TYPE_PLACEABLE,oDest,1);
|
||
|
oRet=oTrans;
|
||
|
} // choose nearby dest
|
||
|
return oRet;
|
||
|
} // fnPathNextDestination()
|