//////////////////////////////////////////////////////////////////////// // 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()