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