generated from Jaysyn/ModuleTemplate
Merged redundant hak files
Merged redundant hak files. Moved hak scripts into module. Updated gitignore. Full Compile. Added release folder & archive.
This commit is contained in:
873
_mod/_module/nss/rtsa_headera.nss
Normal file
873
_mod/_module/nss/rtsa_headera.nss
Normal file
@@ -0,0 +1,873 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// REAL TIME STRATEGY ADVENTURE - Kit
|
||||
// FILE: rtsa_headera
|
||||
// NAME: header functions for unit AI
|
||||
// SCRIPTED BY: Deva Bryson Winblood
|
||||
// DATE: 4/13/2003
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// This header contains pathing and other AI critical parts for the AI
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
#include "rtsa_headere" // errors & debug
|
||||
#include "rtsa_headers" // stacks
|
||||
|
||||
/////////////////////////////////////////
|
||||
// FUNCTIONS
|
||||
/////////////////////////////////////////
|
||||
object fnRandomObject(object oArea,int nObType=0,object oOBT=OBJECT_INVALID)
|
||||
{ // This will return a random object from the area of the specified type
|
||||
// if none is specified it will return a random object placeable, door, waypoint,
|
||||
// or trigger
|
||||
// This WILL NOT return area transition objects use fnRandomTrans for that
|
||||
object oRet=OBJECT_INVALID;
|
||||
int nObT=nObType;
|
||||
int nR;
|
||||
int nC;
|
||||
float fDist=0.0;
|
||||
int nLim=0;
|
||||
object oObB=GetFirstObjectInArea(oArea);
|
||||
if (oOBT!=OBJECT_INVALID) oObB=oOBT;
|
||||
fnDebug(" fnRandomObject("+GetName(oArea)+","+IntToString(nObType)+")");
|
||||
fnDebug(" First Object in Area:"+GetTag(oObB)+" Type:"+IntToString(GetObjectType(oObB)));
|
||||
while(fDist<4.0&&nLim<3)
|
||||
{ // find something not close
|
||||
if (nObType==0)
|
||||
{
|
||||
nR=d4();
|
||||
if (nR==1) nObT=OBJECT_TYPE_PLACEABLE;
|
||||
else if (nR==2) nObT=OBJECT_TYPE_WAYPOINT;
|
||||
else if (nR==3) nObT=OBJECT_TYPE_DOOR;
|
||||
else if (nR==4) nObT=OBJECT_TYPE_TRIGGER;
|
||||
}
|
||||
fnDebug(" Object type chosen:"+IntToString(nObT));
|
||||
nC=0;
|
||||
if (oOBT==OBJECT_INVALID)
|
||||
while(nC<4&&(nObT==GetObjectType(oObB)||oObB==OBJECT_INVALID))
|
||||
{ // make sure checker object is of a different type
|
||||
if(nObT!=OBJECT_TYPE_WAYPOINT)
|
||||
oObB=GetNearestObject(OBJECT_TYPE_WAYPOINT,oObB,1);
|
||||
else
|
||||
oObB=GetNearestObject(OBJECT_TYPE_PLACEABLE,oObB,1);
|
||||
nC++;
|
||||
} // make sure checker object is of a different type
|
||||
fnDebug(" Object to compare against:"+GetTag(oObB));
|
||||
if (nObT==OBJECT_TYPE_PLACEABLE)
|
||||
nC=GetLocalInt(oArea,"nNumPlaceables");
|
||||
else if (nObT==OBJECT_TYPE_WAYPOINT)
|
||||
nC=GetLocalInt(oArea,"nNumWP");
|
||||
else if (nObT==OBJECT_TYPE_DOOR)
|
||||
nC=GetLocalInt(oArea,"nNumDoors");
|
||||
else if (nObT==OBJECT_TYPE_TRIGGER)
|
||||
nC=GetLocalInt(oArea,"nNumTriggers");
|
||||
if (nC==0&&nObType==0)
|
||||
{ // no objects of that type exist
|
||||
if (nObT!=OBJECT_TYPE_PLACEABLE&&GetObjectType(oObB)!=OBJECT_TYPE_PLACEABLE&&GetLocalInt(oArea,"nNumPlaceables")>0)
|
||||
{ // try for placeables
|
||||
nObT=OBJECT_TYPE_PLACEABLE;
|
||||
nC=GetLocalInt(oArea,"nNumPlaceables");
|
||||
} // try for placeables
|
||||
else if (nObT!=OBJECT_TYPE_WAYPOINT&&GetObjectType(oObB)!=OBJECT_TYPE_WAYPOINT&&GetLocalInt(oArea,"nNumWP")>0)
|
||||
{ // try for waypoints
|
||||
nObT=OBJECT_TYPE_WAYPOINT;
|
||||
nC=GetLocalInt(oArea,"nNumWP");
|
||||
} // try for waypoints
|
||||
else if (nObT!=OBJECT_TYPE_DOOR&&GetObjectType(oObB)!=OBJECT_TYPE_DOOR&&GetLocalInt(oArea,"nNumDoors")>0)
|
||||
{ // try a door
|
||||
nObT=OBJECT_TYPE_DOOR;
|
||||
nC=GetLocalInt(oArea,"nNumDoors");
|
||||
} // try a door
|
||||
else if (nObT!=OBJECT_TYPE_TRIGGER&&GetObjectType(oObB)!=OBJECT_TYPE_TRIGGER&&GetLocalInt(oArea,"nNumTriggers")>0)
|
||||
{ // try a trigger
|
||||
nObT=OBJECT_TYPE_TRIGGER;
|
||||
nC=GetLocalInt(oArea,"nNumTriggers");
|
||||
} // try a trigger
|
||||
} // no objects of that type exist
|
||||
if (nC>0&&oObB!=OBJECT_INVALID)
|
||||
{ // get the random object
|
||||
nR=Random(nC)+1;
|
||||
if (nObT==OBJECT_TYPE_PLACEABLE)
|
||||
oRet=GetNearestObject(OBJECT_TYPE_PLACEABLE,oObB,nR);
|
||||
else if (nObT==OBJECT_TYPE_WAYPOINT)
|
||||
oRet=GetNearestObject(OBJECT_TYPE_WAYPOINT,oObB,nR);
|
||||
else if (nObT==OBJECT_TYPE_DOOR)
|
||||
oRet=GetLocalObject(oArea,"oDoor"+IntToString(nR));
|
||||
else if (nObT==OBJECT_TYPE_TRIGGER)
|
||||
oRet=GetLocalObject(oArea,"oTrigger"+IntToString(nR));
|
||||
} // get the random object
|
||||
else if (oObB==OBJECT_INVALID)
|
||||
oRet=GetFirstObjectInArea(oArea);
|
||||
nLim++;
|
||||
fDist=GetDistanceToObject(oRet);
|
||||
} // find something not close
|
||||
return oRet;
|
||||
} // fnRandomObject()
|
||||
|
||||
object fnRandomTrans(object oArea)
|
||||
{ // Returns a random area transition target (trigger or door)
|
||||
object oRet=OBJECT_INVALID;
|
||||
int nC=GetLocalInt(oArea,"nNumTrans");
|
||||
int nR=Random(nC)+1;
|
||||
if (nC>0)
|
||||
oRet=GetLocalObject(oArea,"oTrans"+IntToString(nR));
|
||||
return oRet;
|
||||
} // fnRandomTrans()
|
||||
|
||||
object fnDirectConnection(object oStart,object oEnd)
|
||||
{ // find out if there is a direct area transition between the two places
|
||||
object oRet=OBJECT_INVALID;
|
||||
int nX=GetLocalInt(oStart,"nNumTrans");
|
||||
int nC=1;
|
||||
object oT=GetLocalObject(oStart,"oTrans"+IntToString(nC));
|
||||
object oX;
|
||||
oX=GetTransitionTarget(oT);
|
||||
while (nC<=nX&&GetArea(oX)!=oEnd)
|
||||
{ // look
|
||||
oT=GetLocalObject(oStart,"oTrans"+IntToString(nC));
|
||||
oX=GetTransitionTarget(oT);
|
||||
nC++;
|
||||
} // look
|
||||
if (GetArea(oX)==oEnd) oRet=oT;
|
||||
return oRet;
|
||||
} // fnDirectConnection()
|
||||
|
||||
int fnBuildPath(object oEnd,int nMax=10)
|
||||
{ // build a reverse path between this location and me
|
||||
int nRet=FALSE;
|
||||
object oMe=OBJECT_SELF;
|
||||
int nX;
|
||||
int nR;
|
||||
int nDepth=0;
|
||||
object oAt=oEnd;
|
||||
object oPrev;
|
||||
object oH1;
|
||||
object oH2;
|
||||
fnPush("Pathing","",0,oEnd); // put end point on stack
|
||||
oH1=fnDirectConnection(GetArea(oEnd),GetArea(oMe));
|
||||
if (oH1!=OBJECT_INVALID)
|
||||
{ // direct connection
|
||||
fnPush("Pathing","",0,oH1);
|
||||
fnPush("Pathing","",0,fnRandomObject(GetArea(oH1),0,oH1));
|
||||
return TRUE;
|
||||
} // direct connection
|
||||
while(oAt!=oMe&&nDepth<=nMax)
|
||||
{ // traverse nodes
|
||||
oH1=fnDirectConnection(GetArea(oAt),GetArea(oMe));
|
||||
if (oH1!=OBJECT_INVALID)
|
||||
{ // direct connection
|
||||
oH1=GetTransitionTarget(oH1);
|
||||
if(GetTransitionTarget(oH1)!=OBJECT_INVALID)
|
||||
{ // !OI-TT
|
||||
oH1=fnRandomObject(GetArea(oH1),0,oH1);
|
||||
} // !OI-TT
|
||||
fnPush("Pathing","",0,oH1);
|
||||
return TRUE;
|
||||
} // direct connection
|
||||
oH1=fnRandomTrans(GetArea(oAt));
|
||||
oH1=GetTransitionTarget(oH1);
|
||||
nX=0;
|
||||
while (GetArea(oH1)==oPrev&&nX<3)
|
||||
{ // keep looking
|
||||
oH1=fnRandomTrans(GetArea(oAt));
|
||||
oH1=GetTransitionTarget(oH1);
|
||||
nX++;
|
||||
} // keep looking
|
||||
if (GetArea(oH1)!=oPrev)
|
||||
{ // found a direction to try
|
||||
oPrev=GetArea(oAt);
|
||||
if(GetTransitionTarget(oH1)!=OBJECT_INVALID)
|
||||
{ // !OI-TT
|
||||
oH1=fnRandomObject(GetArea(oH1),0,oH1);
|
||||
} // !OI-TT
|
||||
fnPush("Pathing","",0,oH1);
|
||||
oAt=oH1;
|
||||
nDepth++;
|
||||
} // found a direction to try
|
||||
} // traverse nodes
|
||||
return nRet;
|
||||
} // fnBuildPath()
|
||||
|
||||
int fnFindPathTo(object oDest,int nMaxNodes=10)
|
||||
{ // find a path
|
||||
object oMe=OBJECT_SELF;
|
||||
object oMyArea=GetArea(oMe);
|
||||
object oDestArea=GetArea(oDest);
|
||||
int nRet=0;
|
||||
int nFoundPath=FALSE;
|
||||
int nPathing=GetLocalInt(oMe,"nPathing");
|
||||
if (nPathing!=TRUE)
|
||||
{ // starting pathing
|
||||
fnFlushS("Pathing");
|
||||
fnInitializeStack("Pathing",3); // object stack
|
||||
if (oMyArea==oDestArea)
|
||||
{ // same area - no pathing needed
|
||||
//SendMessageToPC(GetFirstPC(),"Pathing: Same Area");
|
||||
fnPush("Pathing","",0,oDest);
|
||||
nFoundPath=TRUE;
|
||||
} // same area - no pathing needed
|
||||
else if (fnDirectConnection(oMyArea,oDestArea)!=OBJECT_INVALID)
|
||||
{ // there is a direct link - no pathing needed
|
||||
fnPush("Pathing","",0,oDest);
|
||||
fnPush("Pathing","",0,fnRandomObject(GetArea(oDest),0,oDest));
|
||||
//SendMessageToPC(GetFirstPC(),"Pathing: Direct link");
|
||||
nFoundPath=TRUE;
|
||||
} // there is a direct link - no pathing needed
|
||||
else
|
||||
{ // build a path
|
||||
//SendMessageToPC(GetFirstPC(),"Call fnBuildPath");
|
||||
nFoundPath=fnBuildPath(oDest,nMaxNodes);
|
||||
} // build a path
|
||||
if (nFoundPath==TRUE)
|
||||
SetLocalInt(oMe,"nPathing",FALSE);
|
||||
} // starting pathing
|
||||
else
|
||||
{ // still looking
|
||||
//SendMessageToPC(GetFirstPC(),"Pathing: Still calling fnBuildPath");
|
||||
nFoundPath=fnBuildPath(oDest,nMaxNodes);
|
||||
if (nFoundPath==TRUE)
|
||||
SetLocalInt(oMe,"nPathing",FALSE);
|
||||
} // still looking
|
||||
return nRet;
|
||||
} // fnFindPathTo()
|
||||
|
||||
float fnPlanarDistance(location lLoc1,location lLoc2)
|
||||
{ // get planar distance
|
||||
float fRet=0.0;
|
||||
vector vVec=GetPositionFromLocation(lLoc1);
|
||||
float fY1=vVec.y;
|
||||
float fX1=vVec.x;
|
||||
vVec=GetPositionFromLocation(lLoc2);
|
||||
float fX2=vVec.x;
|
||||
float fY2=vVec.y;
|
||||
fY1=(fY1-fY2);
|
||||
fX1=(fX1-fX2);
|
||||
fRet=(fY1+fX1);
|
||||
if (fRet<0.0) fRet=fRet*-1.0;
|
||||
fRet=fRet/2.0;
|
||||
return fRet;
|
||||
} // fnPlanarDistance()
|
||||
|
||||
int fnMoveToDestination(object oDest,int nAS,float fRange=2.5)
|
||||
{ // the actual movement command - handles anti-stuck as well
|
||||
if (oDest!=OBJECT_INVALID&&GetIsPC(oDest)!=TRUE&&GetObjectType(oDest)!=OBJECT_TYPE_CREATURE)
|
||||
{ // !OI
|
||||
int nRet=0;
|
||||
object oMe=OBJECT_SELF;
|
||||
float fDist=GetDistanceToObject(oDest);
|
||||
float fDistR=GetLocalFloat(oMe,"fDistR");
|
||||
int nASC=GetLocalInt(oMe,"nASC");
|
||||
int nWander=GetLocalInt(oMe,"nWander");
|
||||
object oInArea=GetLocalObject(oMe,"oInArea");
|
||||
location lMe=GetLocation(oMe);
|
||||
location lDest=GetLocation(oDest);
|
||||
int nRun=GetLocalInt(oMe,"nRun");
|
||||
object oTrans;
|
||||
int nC;
|
||||
int nErr;
|
||||
int nWC=GetLocalInt(oMe,"nWC"); // wander count
|
||||
object oPC=GetNearestCreature(CREATURE_TYPE_PLAYER_CHAR,PLAYER_CHAR_IS_PC,oMe); // PC
|
||||
fnDebug(" ["+GetName(oMe)+"]fnMoveToDestination("+GetTag(oDest)+","+IntToString(nAS)+","+FloatToString(fRange)+")");
|
||||
if (oDest==OBJECT_INVALID) return -1;
|
||||
if (fDist==-1.0)
|
||||
{
|
||||
if(oInArea==OBJECT_INVALID)
|
||||
{
|
||||
oInArea=fnRandomObject(GetArea(oMe));
|
||||
SetLocalObject(oMe,"oInArea",oInArea);
|
||||
}
|
||||
}
|
||||
else if (fDist!=-1.0&&fDist<=fRange)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (oInArea!=OBJECT_INVALID)
|
||||
DeleteLocalObject(oMe,"oInArea");
|
||||
if (nWander!=TRUE)
|
||||
{ // okay to process movement - not wandering
|
||||
SetLocalFloat(oMe,"fDistR",fDist);
|
||||
if (fDist==-1.0)
|
||||
SetLocalFloat(oMe,"fDistR",GetDistanceToObject(oInArea));
|
||||
fnDebug(" fnMoveToDestination:"+GetTag(oDest)+" nASC:"+IntToString(nASC)+" fDist:"+FloatToString(fDist)+" fDistR:"+FloatToString(fDistR)+" MvR:"+IntToString(GetMovementRate(oMe))+" Currently At:"+GetName(GetArea(oMe)));
|
||||
if (nAS==TRUE&&((fDist==fDistR&&fDist!=-1.0)||(GetDistanceToObject(oInArea)==fDistR&&fDist==-1.0)))
|
||||
{ // Possibly stuck and ANTI-STUCK is enabled
|
||||
nASC++;
|
||||
SetLocalInt(oMe,"nASC",nASC);
|
||||
if (oPC==OBJECT_INVALID)
|
||||
{ // no PCs in area - use speed method
|
||||
nC=13-GetMovementRate(oMe);
|
||||
if (nASC>(nC+2))
|
||||
{ // teleport failed - return error
|
||||
return -1;
|
||||
} // teleport failed - return error
|
||||
else if (nASC>nC)
|
||||
{ // teleport
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,JumpToObject(oDest));
|
||||
} // teleport
|
||||
else
|
||||
{ // move
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
} // move
|
||||
} // no PCs in area - use speed method
|
||||
else
|
||||
{ // PCs in area - use visible method
|
||||
nC=8-GetMovementRate(oMe);
|
||||
if (nASC>(nC+7))
|
||||
{ // teleport failed - return error
|
||||
return -1;
|
||||
} // teleport failed - return error
|
||||
else if (nASC>(nC+6))
|
||||
{ // compare locations (disregard Z)
|
||||
if (fnPlanarDistance(lMe,lDest)<fRange)
|
||||
return 1;
|
||||
} // compare locations (disregard Z)
|
||||
else if (nASC>(nC+5))
|
||||
{ // Teleport
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,JumpToObject(oDest));
|
||||
} // Teleport
|
||||
else if (nASC>(nC+3))
|
||||
{ // Wander mode
|
||||
if (nWC<2)
|
||||
{ // have not wandered too much
|
||||
oTrans=fnRandomObject(GetArea(oMe));
|
||||
SetLocalInt(oMe,"nWander",TRUE);
|
||||
DelayCommand(8.0,SetLocalInt(oMe,"nWander",FALSE));
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,ActionMoveToObject(oTrans,nRun,3.0));
|
||||
DelayCommand(7.5,AssignCommand(oMe,ClearAllActions()));
|
||||
DelayCommand(7.7,AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange)));
|
||||
nWC++;
|
||||
SetLocalInt(oMe,"nWC",nWC);
|
||||
} // have not wandered too much
|
||||
} // Wander mode
|
||||
else if (nASC>(nC+1))
|
||||
{ // active kickstart
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
} // active kickstart
|
||||
else
|
||||
{ // issue move command
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
} // issue move command
|
||||
} // PCs in area - use visible method
|
||||
} // Possibly stuck and ANTI-STUCK is enabled
|
||||
else
|
||||
{ // Not STUCK or ANTI-STUCK disabled
|
||||
if (fDist<=fRange&&fDist!=-1.0)
|
||||
{ // arrived
|
||||
SetLocalInt(oMe,"nWC",0);
|
||||
SetLocalInt(oMe,"nASC",0);
|
||||
SetLocalInt(oMe,"nWander",FALSE);
|
||||
return 1;
|
||||
} // arrived
|
||||
else
|
||||
{ // have not arrived
|
||||
if (GetTransitionTarget(oDest)!=OBJECT_INVALID)
|
||||
{ // transition target
|
||||
oTrans=GetTransitionTarget(oDest);
|
||||
oTrans=fnRandomObject(GetArea(oTrans),0,oTrans);
|
||||
nC=2;
|
||||
while((GetTransitionTarget(oTrans)!=OBJECT_INVALID||GetIsPC(oTrans)==TRUE||GetObjectType(oTrans)==OBJECT_TYPE_CREATURE)&&nC<10)
|
||||
{
|
||||
oTrans=GetNearestObject(OBJECT_TYPE_ALL,oTrans,nC);
|
||||
nC++;
|
||||
}
|
||||
if (GetTransitionTarget(oTrans)==OBJECT_INVALID&&GetIsPC(oTrans)!=TRUE&&GetObjectType(oTrans)!=OBJECT_TYPE_CREATURE)
|
||||
{ // go to this object
|
||||
nErr=fnMoveToDestination(oTrans,nAS,fRange);
|
||||
return nErr;
|
||||
} // go to this object
|
||||
else
|
||||
return -1;
|
||||
} // transition target
|
||||
else
|
||||
{ // in our area
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
SetLocalInt(oMe,"nASC",0);
|
||||
} // in our area
|
||||
} // have not arrived
|
||||
} // Not STUCK or ANTI-STUCK disabled
|
||||
} // okay to process movement - not wandering
|
||||
return nRet;
|
||||
} // OI
|
||||
else
|
||||
return -1; // OBJECT_INVALID
|
||||
} // fnMoveToDestination()
|
||||
|
||||
int fnMovePath(object oDest,int nAS,float fRange=2.5)
|
||||
{ // Main movement function
|
||||
int nRet=0;
|
||||
object oMe=OBJECT_SELF;
|
||||
object oDirect;
|
||||
object oD2;
|
||||
int nErr;
|
||||
int nTop=fnSizeS("Pathing");
|
||||
float fDist=GetDistanceToObject(oDest);
|
||||
if (oDest==OBJECT_INVALID) return -1;
|
||||
else fnDebug(" fnMovePath("+GetTag(oDest)+"/"+GetName(oDest)+"/"+GetResRef(oDest)+")");
|
||||
if (nTop==0)
|
||||
{ // no path build one
|
||||
fnDebug(" Initialize Stack & Find Path");
|
||||
fnInitializeStack("Pathing",3); // Object stack
|
||||
nErr=fnFindPathTo(oDest); // build pathing
|
||||
if (nErr==-1)
|
||||
return -1;
|
||||
} // no path build one
|
||||
else if (nTop==1)
|
||||
{ // single destination
|
||||
oDirect=fnPopObject("Pathing",FALSE);
|
||||
fnDebug(" Single Destination Remains:"+GetTag(oDirect));
|
||||
if (GetTransitionTarget(oDirect)!=OBJECT_INVALID)
|
||||
{ // transition target
|
||||
fDist=GetDistanceToObject(oDirect);
|
||||
if (fDist!=-1.0&&fDist<20.1)
|
||||
{ // close enough
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
if (nErr==1)
|
||||
{ // arrived
|
||||
oDirect=fnPopObject("Pathing");
|
||||
return 1;
|
||||
} // arrived
|
||||
else
|
||||
{ // seek target close to transition first
|
||||
oD2=fnRandomObject(GetArea(oDirect),0,oDirect);
|
||||
if (GetTransitionTarget(oD2)!=OBJECT_INVALID)
|
||||
oD2=fnRandomObject(GetArea(oDirect),0,oDirect);
|
||||
nErr=fnMoveToDestination(oD2,nAS,fRange);
|
||||
if (nErr==1)
|
||||
{ // arrived at mid-point
|
||||
fDist=GetDistanceToObject(oDirect);
|
||||
if (fDist!=-1.0&&fDist>20.0)
|
||||
{ // still not close enough
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
if (fDist<30.0)
|
||||
DelayCommand(3.0,ClearAllActions());
|
||||
else if (fDist<50.0)
|
||||
DelayCommand(5.0,ClearAllActions());
|
||||
else
|
||||
DelayCommand(8.0,ClearAllActions());
|
||||
} // still not close enough
|
||||
} // arrived at mid-point
|
||||
else if (nErr==-1)
|
||||
{ // mid-point error
|
||||
oD2=fnRandomObject(GetArea(oDirect),0,oDirect);
|
||||
nErr=fnMoveToDestination(oD2,nAS,fRange);
|
||||
if (nErr==-1)
|
||||
{ // mid-point 2 fail
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
} // mid-point 2 fail
|
||||
} // mid-point error
|
||||
} // seek target close to transition first
|
||||
} // close enough
|
||||
} // transition target
|
||||
else
|
||||
{ // not a transition target
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
if (nErr==1)
|
||||
{ // arrived
|
||||
oDirect=fnPopObject("Pathing");
|
||||
return 1;
|
||||
} // arrived
|
||||
else if (nErr==-1)
|
||||
{ // error
|
||||
fnFlushS("Pathing");
|
||||
return -1;
|
||||
} // error
|
||||
} // not a transition target
|
||||
} // single destination
|
||||
else
|
||||
{ // stack of destinations
|
||||
oDirect=fnPopObject("Pathing",FALSE);
|
||||
fnDebug(" Stack of destinations Current="+GetTag(oDirect));
|
||||
if (GetTransitionTarget(oDirect)!=OBJECT_INVALID)
|
||||
{ // transition target -- TRANSITION
|
||||
fDist=GetDistanceToObject(oDirect);
|
||||
if (fDist!=-1.0&&fDist<20.1)
|
||||
{ // close enough
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
if (nErr==1)
|
||||
{ // arrived
|
||||
oDirect=fnPopObject("Pathing");
|
||||
return 0;
|
||||
} // arrived
|
||||
} // close enough
|
||||
else
|
||||
{ // seek target close to transition first
|
||||
oD2=fnRandomObject(GetArea(oDirect),0,oDirect);
|
||||
if (GetTransitionTarget(oD2)!=OBJECT_INVALID)
|
||||
oD2=fnRandomObject(GetArea(oDirect),0,oDirect);
|
||||
nErr=fnMoveToDestination(oD2,nAS,fRange);
|
||||
if (nErr==1)
|
||||
{ // arrived at mid-point
|
||||
fDist=GetDistanceToObject(oDirect);
|
||||
if (fDist!=-1.0&&fDist>20.0)
|
||||
{ // still not close enough
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
if (fDist<30.0)
|
||||
DelayCommand(3.0,ClearAllActions());
|
||||
else if (fDist<50.0)
|
||||
DelayCommand(5.0,ClearAllActions());
|
||||
else
|
||||
DelayCommand(8.0,ClearAllActions());
|
||||
} // still not close enough
|
||||
} // arrived at mid-point
|
||||
else if (nErr==-1)
|
||||
{ // mid-point error
|
||||
oD2=fnRandomObject(GetArea(oDirect),0,oDirect);
|
||||
nErr=fnMoveToDestination(oD2,nAS,fRange);
|
||||
if (nErr==-1)
|
||||
{ // mid-point 2 fail
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
} // mid-point 2 fail
|
||||
} // mid-point error
|
||||
} // seek target close to transition first
|
||||
} // transition target -- TRANSITION
|
||||
else
|
||||
{ // not transition target -- NON-TRANSITION
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
if (nErr==1)
|
||||
{ // arrived
|
||||
oDirect=fnPopObject("Pathing");
|
||||
return 0;
|
||||
} // arrived
|
||||
else if (nErr==-1)
|
||||
{ // error - cannot reach
|
||||
fnFlushS("Pathing");
|
||||
return -1;
|
||||
} // error - cannot reach
|
||||
} // not transition target -- NON-TRANSITION
|
||||
} // stack of destinations
|
||||
return nRet;
|
||||
} // fnMovePath()
|
||||
|
||||
/*
|
||||
void fnMakeSureNotImpossible(object oDest,float fRange)
|
||||
{
|
||||
float fDist=GetDistanceToObject(oDest);
|
||||
object oMe=OBJECT_SELF;
|
||||
if (fDist>fRange)
|
||||
{ // not possible
|
||||
SetLocalInt(oMe,"nWanderCount",0);
|
||||
SetLocalFloat(oMe,"fDistR",fDist);
|
||||
SetLocalInt(oMe,"nASC",1000);
|
||||
} // not possible
|
||||
} // fnMakeSureNotImpossible() */
|
||||
|
||||
/* int fnMoveToDestination(object oDest,int nAS=TRUE,float fRange=2.5)
|
||||
{ // Move to destination and anti-stuck procedures
|
||||
// RETURN VALUES 0 = moving, 1 = appear to have arrived, -1 = unreachable
|
||||
int nRet=0;
|
||||
object oMe=OBJECT_SELF;
|
||||
object oNear=GetLocalObject(oMe,"oNear");
|
||||
int nASC=GetLocalInt(oMe,"nASC"); // Anti-Stuck counter
|
||||
float fDistR=GetLocalFloat(oMe,"fDistR"); // distance recorded last time
|
||||
float fDist=GetDistanceToObject(oDest);
|
||||
int nRun=GetLocalInt(oMe,"nRun");
|
||||
object oBackup;
|
||||
int nSpeedB=0;
|
||||
int nWander=GetLocalInt(oMe,"nWander");
|
||||
int nR=GetMovementRate(oMe);
|
||||
int nWC=GetLocalInt(oMe,"nWanderCount");
|
||||
nSpeedB=7-nR;
|
||||
if (oNear!=OBJECT_INVALID&&fDist!=-1.0)
|
||||
DeleteLocalObject(oMe,"oNear");
|
||||
if (nSpeedB<1) nSpeedB=0;
|
||||
if (nWander!=TRUE)
|
||||
{ // not currently wandering
|
||||
SendMessageToPC(GetFirstPC(),"fnMoveToDestination:"+GetTag(oDest)+" nASC:"+IntToString(nASC)+" fDist:"+FloatToString(fDist)+" fDistR:"+FloatToString(fDistR)+" nSpeedB:"+IntToString(nSpeedB));
|
||||
if (GetTransitionTarget(oDest)!=OBJECT_INVALID)
|
||||
{ // this is a transition object
|
||||
oBackup=GetNearestObject(OBJECT_TYPE_ALL,oDest,1);
|
||||
if (GetTransitionTarget(oBackup)!=OBJECT_INVALID)
|
||||
oBackup=GetNearestObject(OBJECT_TYPE_ALL,oDest,2);
|
||||
if (GetTransitionTarget(oBackup)!=OBJECT_INVALID)
|
||||
oBackup=GetNearestObject(OBJECT_TYPE_ALL,oDest,3);
|
||||
if (oBackup!=OBJECT_INVALID)
|
||||
{ // destination
|
||||
oDest=oBackup;
|
||||
} // destination
|
||||
else
|
||||
return -1;
|
||||
fDist=GetDistanceToObject(oDest);
|
||||
} // this is a transition object
|
||||
if (fDist!=-1.0&&fDist==fDistR&&nAS==TRUE)
|
||||
{ // appears to be stuck
|
||||
nASC++;
|
||||
if (nASC>5+nSpeedB)
|
||||
{ // extreme anti-stuck cannot reach destination
|
||||
SetLocalObject(oMe,"oDest",OBJECT_INVALID);
|
||||
SetLocalInt(oMe,"nASC",0);
|
||||
SetLocalInt(oMe,"nWanderCount",0);
|
||||
return -1; // signal failure to reach area
|
||||
} // extreme anti-stuck cannot reach destination
|
||||
else if (nASC>3+nSpeedB)
|
||||
{ // badly stuck - teleport
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,JumpToObject(oDest));
|
||||
SetLocalInt(oMe,"nWanderCount",0);
|
||||
SetLocalFloat(oMe,"fDistR",GetDistanceToObject(oDest));
|
||||
DelayCommand(2.5,fnMakeSureNotImpossible(oDest,fRange));
|
||||
} // badly stuck - teleport
|
||||
else if (nASC>1+nSpeedB)
|
||||
{ // pick a nearby target to move to
|
||||
if (nWC<2)
|
||||
{ // only 2 wander tries
|
||||
if (nWander!=TRUE)
|
||||
{ // pick target
|
||||
oBackup=fnRandomObject(GetArea(oMe));
|
||||
if (oBackup==OBJECT_INVALID)
|
||||
{ // pick our own
|
||||
oBackup=GetNearestObject(OBJECT_TYPE_ALL,oMe,d6());
|
||||
if (GetTransitionTarget(oBackup)!=OBJECT_INVALID)
|
||||
oBackup=OBJECT_INVALID;
|
||||
} // pick our own
|
||||
if (oBackup!=OBJECT_INVALID)
|
||||
{ // valid object
|
||||
SetLocalInt(oMe,"nWander",TRUE);
|
||||
nWC++;
|
||||
SetLocalInt(oMe,"nWanderCount",nWC);
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,ActionMoveToObject(oBackup,nRun,3.0));
|
||||
nR=4+d4();
|
||||
DelayCommand(IntToFloat(nR),AssignCommand(oMe,ClearAllActions()));
|
||||
DelayCommand(IntToFloat(nR)+0.1,AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange)));
|
||||
DelayCommand(IntToFloat(nR)+4.0,SetLocalInt(oMe,"nWander",FALSE));
|
||||
} // valid object
|
||||
SetLocalFloat(oMe,"fDistR",fDist);
|
||||
} // pick target
|
||||
} // only 2 wander tries
|
||||
else
|
||||
{ // abort - set to teleport time
|
||||
SetLocalFloat(oMe,"fDistR",GetDistanceToObject(oDest));
|
||||
SetLocalInt(oMe,"nASC",3+nSpeedB);
|
||||
} // abort - set to teleport time
|
||||
} // pick a nearby target to move to
|
||||
else if (nASC==2)
|
||||
{ // kick start - move to object
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
SetLocalFloat(oMe,"fDistR",fDist);
|
||||
} // kick start - move to object
|
||||
else
|
||||
{ // move to object
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
SetLocalFloat(oMe,"fDistR",fDist);
|
||||
} // move to object
|
||||
SetLocalInt(oMe,"nASC",nASC);
|
||||
} // appears to be stuck
|
||||
else if (nAS!=TRUE&&fDist!=-1.0&&fDist==fDistR)
|
||||
{ // Might be stuck but, don't use anti-stuck
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
} // Might be stuck but, don't use anti-stuck
|
||||
else if (fDist==-1.0)
|
||||
{ // different area
|
||||
if (oNear==OBJECT_INVALID)
|
||||
{ // near
|
||||
oNear=GetNearestObject(OBJECT_TYPE_ALL,oMe,1);
|
||||
fDist=GetDistanceToObject(oNear);
|
||||
if (fDist!=fDistR)
|
||||
{ // seems to be moving
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
SetLocalInt(oMe,"nASC",0);
|
||||
SetLocalFloat(oMe,"fDistR",fDist);
|
||||
} // seems to be moving
|
||||
else
|
||||
{ // might be stuck
|
||||
nASC++;
|
||||
SetLocalInt(oMe,"nASC",nASC);
|
||||
if (nASC>3)
|
||||
{ // abort this
|
||||
return -1;
|
||||
} // abort this
|
||||
else if (nASC==2)
|
||||
{ // kickstart
|
||||
AssignCommand(oMe,ClearAllActions());
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
} // kickstart
|
||||
else
|
||||
{ // kickstart
|
||||
AssignCommand(oMe,ActionMoveToObject(oDest,nRun,fRange));
|
||||
} // kickstart
|
||||
} // might be stuck
|
||||
} // near
|
||||
|
||||
} // different area
|
||||
else
|
||||
{ // not stuck
|
||||
SetLocalInt(oMe,"nASC",0);
|
||||
SetLocalFloat(oMe,"fDistR",fDist);
|
||||
if (fDist!=-1.0&&fDist<(fRange+0.1))
|
||||
{ // arrived
|
||||
SetLocalInt(oMe,"nWanderCount",0);
|
||||
return 1;
|
||||
} // arrived
|
||||
} // not stuck
|
||||
} // not currently wandering
|
||||
return nRet;
|
||||
} // fnMoveToDestination() */
|
||||
|
||||
/*
|
||||
int fnBuildPath(object oEnd,int nMax=10)
|
||||
{ // build a reverse path between this location and me
|
||||
int nRet=FALSE;
|
||||
object oMe=OBJECT_SELF;
|
||||
int nX;
|
||||
int nR;
|
||||
int nDepth=0;
|
||||
object oAt=oEnd;
|
||||
object oPrev;
|
||||
object oH1;
|
||||
object oH2;
|
||||
fnPush("Pathing","",0,oEnd); // put end point on stack
|
||||
oH1=fnDirectConnection(GetArea(oEnd),GetArea(oMe));
|
||||
if (oH1!=OBJECT_INVALID)
|
||||
{ // direct connection
|
||||
oH2=GetTransitionTarget(oH1);
|
||||
fnPush("Pathing","",0,oH2);
|
||||
fnPush("Pathing","",0,GetNearestObject(OBJECT_TYPE_ALL,oH1,1));
|
||||
return TRUE;
|
||||
} // direct connection
|
||||
while(oAt!=oMe&&nDepth<=nMax)
|
||||
{ // traverse nodes
|
||||
oH1=fnDirectConnection(GetArea(oAt),GetArea(oMe));
|
||||
if (oH1!=OBJECT_INVALID)
|
||||
{ // direct connection
|
||||
oH1=GetTransitionTarget(oH1);
|
||||
fnPush("Pathing","",0,oH1);
|
||||
return TRUE;
|
||||
} // direct connection
|
||||
oH1=fnRandomTrans(GetArea(oAt));
|
||||
oH1=GetTransitionTarget(oH1);
|
||||
nX=0;
|
||||
while (GetArea(oH1)==oPrev&&nX<3)
|
||||
{ // keep looking
|
||||
oH1=fnRandomTrans(GetArea(oAt));
|
||||
oH1=GetTransitionTarget(oH1);
|
||||
nX++;
|
||||
} // keep looking
|
||||
if (GetArea(oH1)!=oPrev)
|
||||
{ // found a direction to try
|
||||
oPrev=GetArea(oAt);
|
||||
fnPush("Pathing","",0,oH1);
|
||||
oAt=oH1;
|
||||
nDepth++;
|
||||
} // found a direction to try
|
||||
} // traverse nodes
|
||||
return nRet;
|
||||
} // fnBuildPath()
|
||||
|
||||
void fnFindPathTo(object oDest,int nMaxNodes=10)
|
||||
{ // find a path
|
||||
object oMe=OBJECT_SELF;
|
||||
object oMyArea=GetArea(oMe);
|
||||
object oDestArea=GetArea(oDest);
|
||||
int nFoundPath=FALSE;
|
||||
int nPathing=GetLocalInt(oMe,"nPathing");
|
||||
if (nPathing!=TRUE)
|
||||
{ // starting pathing
|
||||
fnFlushS("Pathing");
|
||||
fnInitializeStack("Pathing",3); // object stack
|
||||
if (oMyArea==oDestArea)
|
||||
{ // same area - no pathing needed
|
||||
SendMessageToPC(GetFirstPC(),"Pathing: Same Area");
|
||||
fnPush("Pathing","",0,oDest);
|
||||
nFoundPath=TRUE;
|
||||
} // same area - no pathing needed
|
||||
else if (fnDirectConnection(oMyArea,oDestArea)!=OBJECT_INVALID)
|
||||
{ // there is a direct link - no pathing needed
|
||||
fnPush("Pathing","",0,GetNearestObject(OBJECT_TYPE_ALL,oDest,1));
|
||||
fnPush("Pathing","",0,oDest);
|
||||
SendMessageToPC(GetFirstPC(),"Pathing: Direct link");
|
||||
nFoundPath=TRUE;
|
||||
} // there is a direct link - no pathing needed
|
||||
else
|
||||
{ // build a path
|
||||
SendMessageToPC(GetFirstPC(),"Call fnBuildPath");
|
||||
nFoundPath=fnBuildPath(oDest,nMaxNodes);
|
||||
} // build a path
|
||||
if (nFoundPath==TRUE)
|
||||
SetLocalInt(oMe,"nPathing",FALSE);
|
||||
} // starting pathing
|
||||
else
|
||||
{ // still looking
|
||||
SendMessageToPC(GetFirstPC(),"Pathing: Still calling fnBuildPath");
|
||||
nFoundPath=fnBuildPath(oDest,nMaxNodes);
|
||||
if (nFoundPath==TRUE)
|
||||
SetLocalInt(oMe,"nPathing",FALSE);
|
||||
} // still looking
|
||||
} // fnFindPathTo()
|
||||
|
||||
int fnMovePath(object oDest,int nAS,float fRange=2.5)
|
||||
{ // move following a path - this is the main movement function
|
||||
int nRet=0;
|
||||
object oMe=OBJECT_SELF;
|
||||
object oDirect;
|
||||
int nErr;
|
||||
int nTop=fnSizeS("Pathing");
|
||||
float fDist=GetDistanceToObject(oDest);
|
||||
SendMessageToPC(GetFirstPC(),"fnMovePath("+GetTag(oDest)+",AS:"+IntToString(nAS)+",RANGE:"+FloatToString(fRange)+")");
|
||||
if (nTop==0)
|
||||
{ // no path
|
||||
if (fDist==-1.0||fDist>fRange)
|
||||
{ // build a path
|
||||
SendMessageToPC(GetFirstPC(),"Building path");
|
||||
fnFindPathTo(oDest);
|
||||
nErr=fnMovePath(oDest,nAS,fRange);
|
||||
if (nErr==-1) return -1;
|
||||
} // build a path
|
||||
else
|
||||
{ // we have arrived
|
||||
return 1;
|
||||
} // we have arrived
|
||||
} // no path
|
||||
else if (nTop==1)
|
||||
{ // direct link
|
||||
oDirect=fnPopObject("Pathing",FALSE);
|
||||
fDist=GetDistanceToObject(oDirect);
|
||||
if (fDist!=-1.0&&fDist<=fRange)
|
||||
{ // arrived
|
||||
SendMessageToPC(GetFirstPC(),"We arrived");
|
||||
oDirect=fnPopObject("Pathing");
|
||||
nRet=fnMovePath(oDest,nAS,fRange);
|
||||
} // arrived
|
||||
else
|
||||
{ // move
|
||||
SendMessageToPC(GetFirstPC(),"Call Move");
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
if (nErr==-1)
|
||||
{ // error
|
||||
return nErr;
|
||||
} // error
|
||||
} // move
|
||||
} // direct link
|
||||
else
|
||||
{ // complex path
|
||||
SendMessageToPC(GetFirstPC(),"Complex path");
|
||||
oDirect=fnPopObject("Pathing",FALSE);
|
||||
fDist=GetDistanceToObject(oDirect);
|
||||
if (fDist!=-1.0&&fDist<=fRange)
|
||||
{ // arrived at that node
|
||||
oDirect=fnPopObject("Pathing");
|
||||
nRet=fnMovePath(oDest,nAS,fRange);
|
||||
} // arrived at that node
|
||||
else
|
||||
{ // move
|
||||
nErr=fnMoveToDestination(oDirect,nAS,fRange);
|
||||
if (nErr==-1)
|
||||
{ // cannot reach node
|
||||
fnFlushS("Pathing");
|
||||
nRet=nErr;
|
||||
} // cannot reach node
|
||||
} // move
|
||||
} // complex path
|
||||
return nRet;
|
||||
} // fnMovePath() */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user