HoS_PRC8/_mod/_module/nss/antistuck_h.nss
Jaysyn904 04165202c0 Initial upload
Initial upload
2024-11-25 19:36:07 -05:00

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(){}