239 lines
9.0 KiB
Plaintext
239 lines
9.0 KiB
Plaintext
////////////////////////////////////////////////////////////////////////
|
|
// antistuck_h - Anti-Stuck Movement replacement
|
|
// By Deva Bryson Winblood. 04/22/2005
|
|
////////////////////////////////////////////////////////////////////////
|
|
/* Bioware ActionMoveToObject() can become stuck in places and it turns
|
|
out that it uses a tremendous amount of CPU time in some case while
|
|
it continues to try to move. This header has a replacement
|
|
function that can be used in place of the ActionMoveToObject(). It
|
|
will attempt to assist the NPC in becoming unstuck. It will
|
|
eventually teleport the NPC if the NPC cannot appear to get to
|
|
the destination any other way. This function will use up slightly
|
|
more CPU than ActionMoveToObject() but, the idea is that it may
|
|
head off some of the larger CPU eating stuck issues. */
|
|
|
|
////////////////////
|
|
// PROTOTYPES
|
|
////////////////////
|
|
|
|
// FILE: antistuck_h FUNCTION: ASActionMoveToObject()
|
|
// This function is a replacement function for ActionMoveToObject()
|
|
// that will attempt to keep an NPC from becoming stuck and continuously
|
|
// consuming additional CPU cycles.
|
|
void ASActionMoveToObject(object oDest,int bRun=FALSE,float fRange=1.0);
|
|
|
|
// FILE: antistuck_h FUNCTION: ASActionMoveToLocation()
|
|
// This function is a replacement function for ActionMoveToLocation()
|
|
// that will attempt to keep an NPC from becoming stuck and continuously
|
|
// consuming additional CPU cycles.
|
|
void ASActionMoveToLocation(location lLoc,int bRun=FALSE);
|
|
|
|
////////////////////
|
|
// FUNCTIONS
|
|
////////////////////
|
|
|
|
void fnASClearASVariables()
|
|
{ // PURPOSE: Deallocate variables
|
|
object oMe=OBJECT_SELF;
|
|
DeleteLocalObject(oMe,"oASDest");
|
|
DeleteLocalLocation(oMe,"lASRelative");
|
|
DeleteLocalFloat(oMe,"fASLDist");
|
|
DeleteLocalInt(oMe,"nASSC");
|
|
DeleteLocalInt(oMe,"nASSR");
|
|
DeleteLocalLocation(oMe,"lASLoc");
|
|
} // fnASClearASVariables()
|
|
|
|
void fnASError(string sMsg)
|
|
{ // PURPOSE: Report and log the error
|
|
string sPrefix="Error: (antistuck_h): ";
|
|
//SendMessageToPC(GetFirstPC(),sPrefix+sMsg);
|
|
PrintString(sPrefix+sMsg);
|
|
} // fnASError()
|
|
|
|
void fnTeleport(object oDest,float fRange=3.0)
|
|
{ // PURPOSE: Try to teleport
|
|
object oMe=OBJECT_SELF;
|
|
int nC=GetLocalInt(oMe,"nASTCount");
|
|
if (GetArea(oMe)!=GetArea(oDest)||GetDistanceBetween(oMe,oDest)>fRange&&nC<6)
|
|
{ // teleport
|
|
nC++;
|
|
SetLocalInt(oMe,"nASTCount",nC);
|
|
AssignCommand(oMe,ClearAllActions(TRUE));
|
|
AssignCommand(oMe,JumpToObject(oDest));
|
|
DelayCommand(1.0,fnTeleport(oDest,fRange));
|
|
} // teleport
|
|
else
|
|
{ // count
|
|
DeleteLocalInt(oMe,"nASTCount");
|
|
} // count
|
|
} // fnTeleport()
|
|
|
|
void fnASHandleAntiStuck(object oDest,int bRun,float fRange,location lLoc,int nType=0)
|
|
{ // PURPOSE: The anti-stuck portion of this script
|
|
object oMe=OBJECT_SELF;
|
|
object oOb;
|
|
int nASSC=GetLocalInt(oMe,"nASSC");
|
|
int nASSR=GetLocalInt(oMe,"nASSR");
|
|
vector vCur=GetPosition(oMe);
|
|
string sS;
|
|
int nX;
|
|
int nY;
|
|
nASSC++;
|
|
if (nASSC>1&&nASSC<3)
|
|
{ // do nothing
|
|
AssignCommand(oMe,ClearAllActions());
|
|
if (nType==0) AssignCommand(oMe,ActionMoveToObject(oDest,bRun,fRange));
|
|
else if (nType==1) AssignCommand(oMe,ActionMoveToLocation(lLoc,bRun));
|
|
} // do nothing
|
|
if (nASSC>2&&nASSR<3)
|
|
{ // try to move to nearby object first
|
|
oOb=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d100());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d20());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_WAYPOINT,oMe,d12());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_PLACEABLE,oMe,d20());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_PLACEABLE,oMe,d12());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_TRIGGER,oMe,d20());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_TRIGGER,oMe,d12());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_DOOR,oMe,d20());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_DOOR,oMe,d12());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_ALL,oMe,d20());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_ALL,oMe,d8());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_ALL,oMe,d4());
|
|
if (oOb==OBJECT_INVALID) oOb=GetNearestObject(OBJECT_TYPE_ALL,oMe,1);
|
|
if (oOb==OBJECT_INVALID)
|
|
{ // no objects in area
|
|
fnASError(GetName(GetArea(oMe))+" has no objects to assist in anti-stuck pathing. Place some waypoints about the area.");
|
|
} // no objects in area
|
|
else if (oOb!=OBJECT_INVALID)
|
|
{ // move
|
|
AssignCommand(oMe,ClearAllActions(TRUE));
|
|
AssignCommand(oMe,ActionMoveToObject(oOb,TRUE,2.0));
|
|
DelayCommand(5.0,ClearAllActions(TRUE));
|
|
} // move
|
|
nASSC++;
|
|
nASSR++;
|
|
} // try to move to nearby object first
|
|
else if (nASSC>2&&nASSR<6)
|
|
{ // try to teleport
|
|
AssignCommand(oMe,ClearAllActions(TRUE));
|
|
if (nType==0) AssignCommand(oMe,fnTeleport(oDest,fRange));
|
|
else if (nType==1) AssignCommand(oMe,JumpToLocation(lLoc));
|
|
nASSR++;
|
|
} // try to teleport
|
|
else if (nASSC>2&&nASSR>5)
|
|
{ // destination unreachable
|
|
nX=FloatToInt(vCur.x);
|
|
nY=FloatToInt(vCur.y);
|
|
fnASError(GetName(oMe)+" in area "+GetName(GetArea(oMe))+" destination unreachable "+GetTag(oDest)+" currently at location X:"+IntToString(nX)+",Y:"+IntToString(nY));
|
|
fnASClearASVariables();
|
|
} // destination unreachable
|
|
SetLocalInt(oMe,"nASSC",nASSC);
|
|
SetLocalInt(oMe,"nASSR",nASSR);
|
|
} // fnASHandleAntiStuck()
|
|
|
|
void ASActionMoveToObject(object oDest,int bRun=FALSE,float fRange=1.0)
|
|
{ // PURPOSE: Replacement anti-stuck version of ActionMoveToObject()
|
|
object oMe=OBJECT_SELF;
|
|
object oASDest=GetLocalObject(oMe,"oASDest");
|
|
float fLDist=GetLocalFloat(oMe,"fASLDist");
|
|
float fDist;
|
|
location lRelative=GetLocalLocation(oMe,"lASRelative");
|
|
if (oDest==OBJECT_INVALID)
|
|
{ // invalid destination
|
|
fnASError(GetName(oMe)+" tried to move to a destination that does not exist. In area ["+GetName(GetArea(oMe))+"]");
|
|
return;
|
|
} // invalid destination
|
|
if (GetCurrentAction(oMe)!=ACTION_MOVETOPOINT) AssignCommand(oMe,ActionMoveToObject(oDest,bRun,fRange));
|
|
if (oDest!=oASDest)
|
|
{ // new destination
|
|
fnASClearASVariables();
|
|
SetLocalObject(oMe,"oASDest",oDest);
|
|
fLDist=10000.0;
|
|
} // new destination
|
|
if (GetArea(oDest)==GetArea(oMe))
|
|
{ // same area pathing
|
|
fDist=GetDistanceBetween(oDest,oMe);
|
|
if (fDist==fLDist)
|
|
{ // we might be stuck
|
|
fnASHandleAntiStuck(oDest,bRun,fRange,lRelative);
|
|
} // we might be stuck
|
|
else
|
|
{ // not stuck
|
|
DeleteLocalInt(oMe,"nASSC");
|
|
} // not stuck
|
|
SetLocalFloat(oMe,"fASLDist",fDist);
|
|
} // same area pathing
|
|
else
|
|
{ // different area pathing
|
|
if (GetAreaFromLocation(lRelative)!=GetArea(oMe))
|
|
{ // need to set the relative location
|
|
lRelative=GetLocation(oMe);
|
|
SetLocalLocation(oMe,"lASRelative",lRelative);
|
|
} // need to set the relative location
|
|
fDist=GetDistanceBetweenLocations(lRelative,GetLocation(oMe));
|
|
if (fDist==fLDist)
|
|
{ // we might be stuck
|
|
fnASHandleAntiStuck(oDest,bRun,fRange,lRelative);
|
|
} // we might be stuck
|
|
else
|
|
{ // not stuck
|
|
DeleteLocalInt(oMe,"nASSC");
|
|
} // not stuck
|
|
SetLocalFloat(oMe,"fASLDist",fDist);
|
|
} // different area pathing
|
|
} // ASActionMoveToObject()
|
|
|
|
void ASActionMoveToLocation(location lLoc,int bRun=FALSE)
|
|
{ // PURPOSE: Replacement anti-stuck version of ActionMoveToLocation()
|
|
object oMe=OBJECT_SELF;
|
|
location lASLLoc=GetLocalLocation(oMe,"lASLLoc");
|
|
float fLDist=GetLocalFloat(oMe,"fASLDist");
|
|
float fDist;
|
|
location lRelative=GetLocalLocation(oMe,"lASRelative");
|
|
if (GetAreaFromLocation(lLoc)==OBJECT_INVALID)
|
|
{ // invalid destination
|
|
fnASError(GetName(oMe)+" tried to move to a destination that does not exist");
|
|
return;
|
|
} // invalid destination
|
|
if (GetCurrentAction(oMe)!=ACTION_MOVETOPOINT) AssignCommand(oMe,ActionMoveToLocation(lLoc,bRun));
|
|
if (lLoc!=lASLLoc)
|
|
{ // new destination
|
|
fnASClearASVariables();
|
|
SetLocalLocation(oMe,"lASLLoc",lLoc);
|
|
fLDist=10000.0;
|
|
} // new destination
|
|
if (GetAreaFromLocation(lLoc)==GetArea(oMe))
|
|
{ // same area pathing
|
|
fDist=GetDistanceBetweenLocations(lLoc,GetLocation(oMe));
|
|
if (fDist==fLDist)
|
|
{ // we might be stuck
|
|
fnASHandleAntiStuck(OBJECT_INVALID,bRun,0.0,lLoc,1);
|
|
} // we might be stuck
|
|
else
|
|
{ // not stuck
|
|
DeleteLocalInt(oMe,"nASSC");
|
|
} // not stuck
|
|
SetLocalFloat(oMe,"fASLDist",fDist);
|
|
} // same area pathing
|
|
else
|
|
{ // different area pathing
|
|
if (GetAreaFromLocation(lRelative)!=GetArea(oMe))
|
|
{ // need to set the relative location
|
|
lRelative=GetLocation(oMe);
|
|
SetLocalLocation(oMe,"lASRelative",lRelative);
|
|
} // need to set the relative location
|
|
fDist=GetDistanceBetweenLocations(lRelative,GetLocation(oMe));
|
|
if (fDist==fLDist)
|
|
{ // we might be stuck
|
|
fnASHandleAntiStuck(OBJECT_INVALID,bRun,0.0,lLoc,1);
|
|
} // we might be stuck
|
|
else
|
|
{ // not stuck
|
|
DeleteLocalInt(oMe,"nASSC");
|
|
} // not stuck
|
|
SetLocalFloat(oMe,"fASLDist",fDist);
|
|
} // different area pathing
|
|
} // ASActionMoveToLocation()
|
|
|
|
//void main(){}
|