925 lines
40 KiB
Plaintext
925 lines
40 KiB
Plaintext
////////////////////////////////////////////////////////////////////////////////
|
|
// Slaver and slaves - AI Routines for movement, camping, etc.
|
|
// By Deva Bryson Winblood. 12/28/2003
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#include "prc_inc_racial"
|
|
|
|
//////////////////////////
|
|
// PROTOTYPES
|
|
//////////////////////////
|
|
#include "antistuck_h"
|
|
void fnDespawn(object oCr); // despawn creatures if not talking or in combat
|
|
void fnCheckHealSelf(object oCr); // if hurt bad heal yourself
|
|
void fnSorceressDefense(object oTarg); // deal with danger to caravan master
|
|
void fnGuardFollow(object oMaster,float fDist=5.0); // follow routine for slaver guards
|
|
void fnDespawnIfNoSlavers(); // for campfire and cage
|
|
int fnClosestTransition(object oDest,object oSCM); // use closest transition
|
|
|
|
void fnRelaunch(int nCompare)
|
|
{
|
|
if (GetLocalInt(GetModule(),"nSlaverLaunch")==nCompare) ExecuteScript("slaver_and_slave",OBJECT_SELF);
|
|
} // recall program
|
|
|
|
/////////////////////////////////////////////////////////////// MAIN ///////////
|
|
void main()
|
|
{
|
|
object oMod=GetModule();
|
|
object oSCM=GetLocalObject(oMod,"oSCM");
|
|
object oSG1=GetLocalObject(oMod,"oSG1");
|
|
object oSG2=GetLocalObject(oMod,"oSG2");
|
|
object oSG3=GetLocalObject(oMod,"oSG3");
|
|
object oSG4=GetLocalObject(oMod,"oSG4");
|
|
object oSSO=GetLocalObject(oMod,"oSSO");
|
|
object oSIL=GetLocalObject(oMod,"oSIL");
|
|
object oSFire;
|
|
object oSlave;
|
|
object oDest=GetLocalObject(oMod,"oSlaverDest");
|
|
int nSLAVEC=GetLocalInt(oMod,"nSLAVEC");
|
|
int nSlaverPower=GetLocalInt(oMod,"nSlaverPower");
|
|
int nSState=GetLocalInt(oMod,"nSlaverState");
|
|
int nSDestNum=GetLocalInt(oMod,"nSlaverDestNum");
|
|
int nSHuntNum=GetLocalInt(oMod,"nSlaverHuntNum");
|
|
int nSpeed=GetLocalInt(oMod,"nSlaverSpeed");
|
|
int nC;
|
|
int nR;
|
|
int nP;
|
|
int nSNS=GetLocalInt(oMod,"nSlaverLaunch");
|
|
float fDist;
|
|
float fLDist=GetLocalFloat(oMod,"fSlaverLDist");
|
|
object oDistTest=GetLocalObject(oMod,"oSlaverDistTest");
|
|
object oTarg;
|
|
object oWP=GetWaypointByTag("SLAVER_SPAWN");
|
|
float fClosest=GetLocalFloat(oMod,"fSlaverClosest");
|
|
int nDisableNonEssential=GetLocalInt(oMod,"nDisableNonEssential");
|
|
if (nDisableNonEssential!=TRUE)
|
|
{ // it is not disabled
|
|
nC=GetCalendarDay();
|
|
if (oSCM!=OBJECT_INVALID&&GetIsDead(oSCM)!=TRUE)
|
|
{ // caravan master still lives
|
|
SetLocalInt(oMod,"nSLVDay",nC);
|
|
nC=FALSE; // in combat/conversation
|
|
if (GetIsInCombat(oSCM)==TRUE||IsInConversation(oSCM)==TRUE) nC=TRUE;
|
|
if (GetIsInCombat(oSG1)==TRUE||IsInConversation(oSG1)==TRUE) nC=TRUE;
|
|
if (GetIsInCombat(oSG2)==TRUE||IsInConversation(oSG2)==TRUE) nC=TRUE;
|
|
if (GetIsInCombat(oSG3)==TRUE||IsInConversation(oSG3)==TRUE) nC=TRUE;
|
|
if (GetIsInCombat(oSG4)==TRUE||IsInConversation(oSG4)==TRUE) nC=TRUE;
|
|
if (GetIsInCombat(oSSO)==TRUE||IsInConversation(oSSO)==TRUE) nC=TRUE;
|
|
if (GetIsInCombat(oSIL)==TRUE||IsInConversation(oSIL)==TRUE) nC=TRUE;
|
|
if (nC!=TRUE)
|
|
{ // not in conversation or combat
|
|
switch(nSState)
|
|
{ // Main slaver caravan switch
|
|
case 0: { // initialize
|
|
SetLocalInt(oMod,"nSlaverState",1);
|
|
SetLocalInt(oMod,"nSlaverSpeed",0);
|
|
break;
|
|
} // initialize
|
|
case 1: { // pick next SLAVER_# destination
|
|
nSDestNum++;
|
|
oWP=GetWaypointByTag("SLAVER_"+IntToString(nSDestNum));
|
|
SetLocalFloat(oMod,"fSlaverClosest",999.0);
|
|
while(oWP==OBJECT_INVALID&&nSDestNum<40)
|
|
{ // OI
|
|
nSDestNum++;
|
|
oWP=GetWaypointByTag("SLAVER_"+IntToString(nSDestNum));
|
|
} // OI
|
|
if (oWP!=OBJECT_INVALID&&GetArea(oWP)==GetArea(oSCM))
|
|
{ // target found
|
|
SetLocalObject(oMod,"oSlaverDest",oWP);
|
|
SetLocalInt(oMod,"nSlaverState",2);
|
|
SetLocalInt(oMod,"nSlaverDestNum",nSDestNum);
|
|
AssignCommand(oSCM,ASActionMoveToObject(oWP,FALSE,1.0));
|
|
} // target found
|
|
else if (oWP!=OBJECT_INVALID)
|
|
{ // different areas
|
|
SetLocalObject(oMod,"oSlaverDest",oWP);
|
|
SetLocalInt(oMod,"nSlaverState",11);
|
|
SetLocalInt(oMod,"nSlaverDestNum",nSDestNum);
|
|
nSpeed=1;
|
|
} // different areas
|
|
else
|
|
{ //
|
|
AssignCommand(oSCM,SpeakString("I am broken!! Slaver destinations not working!"));
|
|
SetLocalInt(oMod,"nSlaverState",10);
|
|
} //
|
|
break;
|
|
} // pick next SLAVER_# destination
|
|
case 2: { // move to destination with anti-stuck
|
|
if (GetArea(oDest)==GetArea(oSCM))
|
|
{ // same area movement
|
|
fDist=GetDistanceBetween(oSCM,oDest);
|
|
if (fDist<=2.0)
|
|
{ // arrived
|
|
SetLocalInt(oMod,"nSlaverState",3);
|
|
AssignCommand(oSCM,SetFacing(GetFacing(oDest)));
|
|
SetLocalInt(oMod,"nSlaverASC",0);
|
|
} // arrived
|
|
else
|
|
{ // move
|
|
AssignCommand(oSCM,ASActionMoveToObject(oDest,FALSE,1.0));
|
|
} // move
|
|
SetLocalFloat(oMod,"fSlaverLDist",fDist);
|
|
} // same area movement
|
|
else
|
|
{ // moving to another area
|
|
if(oDistTest==OBJECT_INVALID)
|
|
{ // find arbitrary nearby object for distance comparisons
|
|
oDistTest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oSCM,d20());
|
|
if (oDistTest==OBJECT_INVALID) oDistTest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oSCM,1);
|
|
SetLocalObject(oMod,"oSlaverDistTest",oDistTest);
|
|
} // find arbitrary nearby object for distance comparisons
|
|
fDist=GetDistanceBetween(oDistTest,oSCM);
|
|
AssignCommand(oSCM,ASActionMoveToObject(oDest,FALSE,1.0));
|
|
SetLocalFloat(oMod,"fSlaverLDist",fDist);
|
|
} // moving to another area
|
|
break;
|
|
} // move to destination with anti-stuck
|
|
case 3: { // arrived at and interpret destination
|
|
if (GetName(oDest)=="END")
|
|
{ SetLocalInt(oMod,"nSlaverState",10); }
|
|
else if (GetName(oDest)=="CAMP")
|
|
{ SetLocalInt(oMod,"nSlaverState",4); }
|
|
else if (GetName(oDest)=="HUNT")
|
|
{ SetLocalInt(oMod,"nSlaverState",7); }
|
|
else { SetLocalInt(oMod,"nSlaverState",1); }
|
|
nSpeed=2;
|
|
break;
|
|
} // arrived at and interpret destination
|
|
case 4: { // setup camp
|
|
oWP=GetNearestObjectByTag("SLAVER_FIRE",oSCM,1);
|
|
oSFire=CreateObject(OBJECT_TYPE_PLACEABLE,"plc_campfrwpot",GetLocation(oWP));
|
|
SetLocalObject(oSFire,"oMaster",oSCM);
|
|
AssignCommand(oSFire,fnDespawnIfNoSlavers());
|
|
oWP=GetNearestObjectByTag("SLAVER_CAGE",oSCM,1);
|
|
oSFire=CreateObject(OBJECT_TYPE_PLACEABLE,"cage",GetLocation(oWP));
|
|
AssignCommand(oSFire,fnDespawnIfNoSlavers());
|
|
SetLocalObject(oSFire,"oMaster",oSCM);
|
|
oWP=GetNearestObjectByTag("SLAVER_GUARD1",oSCM,1);
|
|
if (oSG1!=OBJECT_INVALID) { AssignCommand(oSG1,ClearAllActions()); AssignCommand(oSG1,ASActionMoveToObject(oWP,TRUE,1.0)); SetLocalInt(oSG1,"nMode",1); }
|
|
oWP=GetNearestObjectByTag("SLAVER_GUARD2",oSCM,1);
|
|
if (oSG2!=OBJECT_INVALID) { AssignCommand(oSG2,ClearAllActions()); AssignCommand(oSG2,ASActionMoveToObject(oWP,TRUE,1.0)); SetLocalInt(oSG2,"nMode",1); }
|
|
oWP=GetNearestObjectByTag("SLAVER_GUARD3",oSCM,1);
|
|
if (oSG3!=OBJECT_INVALID) { AssignCommand(oSG3,ClearAllActions()); AssignCommand(oSG3,ASActionMoveToObject(oWP,TRUE,1.0)); SetLocalInt(oSG3,"nMode",1); }
|
|
oWP=GetNearestObjectByTag("SLAVER_GUARD4",oSCM,1);
|
|
if (oSG4!=OBJECT_INVALID) { AssignCommand(oSG4,ClearAllActions()); AssignCommand(oSG4,ASActionMoveToObject(oWP,TRUE,1.0)); SetLocalInt(oSG4,"nMode",1); }
|
|
nC=0;
|
|
oWP=GetNearestObjectByTag("SLAVER_CAGE",oSCM,1);
|
|
while(nC<nSLAVEC)
|
|
{ // move slaves into cage
|
|
nC++;
|
|
oSlave=GetLocalObject(oMod,"oSLAVE"+IntToString(nC));
|
|
if (oSlave!=OBJECT_INVALID) { AssignCommand(oSlave,ClearAllActions()); AssignCommand(oSlave,JumpToObject(oWP)); SetLocalInt(oSlave,"nMode",1); }
|
|
} // move slaves into cage
|
|
SetLocalInt(oMod,"nSlaverState",5);
|
|
DelayCommand(HoursToSeconds(4),SetLocalInt(oMod,"nSlaverState",6));
|
|
break;
|
|
} // setup camp
|
|
case 5: { // camping
|
|
break;
|
|
} // camping
|
|
case 6: { // take down camp
|
|
oDest=GetNearestObjectByTag("Cage",oSCM,1); // cage
|
|
DestroyObject(oDest);
|
|
oDest=GetNearestObjectByTag("CampfireCauldron",oSCM,1); // campfire
|
|
DestroyObject(oDest);
|
|
if (oSG1!=OBJECT_INVALID) SetLocalInt(oSG1,"nMode",0);
|
|
if (oSG2!=OBJECT_INVALID) SetLocalInt(oSG2,"nMode",0);
|
|
if (oSG3!=OBJECT_INVALID) SetLocalInt(oSG3,"nMode",0);
|
|
if (oSG4!=OBJECT_INVALID) SetLocalInt(oSG4,"nMode",0);
|
|
nC=0;
|
|
while(nC<nSLAVEC)
|
|
{ // make slaves follow again
|
|
nC++;
|
|
oDest=GetLocalObject(oMod,"oSLAVE"+IntToString(nC));
|
|
if (oDest!=OBJECT_INVALID) SetLocalInt(oDest,"nMode",0);
|
|
} // make slaves follow again
|
|
SetLocalInt(oMod,"nSlaverState",1);
|
|
break;
|
|
} // take down camp
|
|
case 7: { // pick hunt destination
|
|
nSHuntNum++;
|
|
oWP=GetNearestObjectByTag("SLAVER_HUNT"+IntToString(nSHuntNum),oSCM,1);
|
|
SetLocalFloat(oMod,"fSlaverClosest",999.0);
|
|
if (oWP!=OBJECT_INVALID)
|
|
{ // target found
|
|
SetLocalObject(oMod,"oSlaverDest",oWP);
|
|
SetLocalInt(oMod,"nSlaverState",8);
|
|
SetLocalInt(oMod,"nSlaverHuntNum",nSHuntNum);
|
|
} // target found
|
|
else
|
|
{ //
|
|
SetLocalInt(oMod,"nSlaverState",1); // done hunting
|
|
} //
|
|
break;
|
|
} // pick hunt destination
|
|
case 8: { // move to hunt destination
|
|
if (GetArea(oDest)==GetArea(oSCM))
|
|
{ // same area movement
|
|
fDist=GetDistanceBetween(oSCM,oDest);
|
|
if (fDist<=2.0)
|
|
{ // arrived
|
|
SetLocalInt(oMod,"nSlaverState",9);
|
|
AssignCommand(oSCM,SetFacing(GetFacing(oDest)));
|
|
SetLocalInt(oMod,"nSlaverASC",0);
|
|
} // arrived
|
|
else
|
|
{ // move
|
|
AssignCommand(oSCM,ASActionMoveToObject(oDest,FALSE,1.0));
|
|
} // move
|
|
SetLocalFloat(oMod,"fSlaverLDist",fDist);
|
|
} // same area movement
|
|
else
|
|
{ // moving to another area
|
|
if(oDistTest==OBJECT_INVALID)
|
|
{ // find arbitrary nearby object for distance comparisons
|
|
oDistTest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oSCM,d20());
|
|
if (oDistTest==OBJECT_INVALID) oDistTest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oSCM,1);
|
|
SetLocalObject(oMod,"oSlaverDistTest",oDistTest);
|
|
} // find arbitrary nearby object for distance comparisons
|
|
fDist=GetDistanceBetween(oDistTest,oSCM);
|
|
AssignCommand(oSCM,ActionMoveToObject(oDest,FALSE,1.0));
|
|
SetLocalFloat(oMod,"fSlaverLDist",fDist);
|
|
} // moving to another area
|
|
break;
|
|
} // move to hunt destination
|
|
case 9: { // arrived at hunt destination look for nearby potential slaves
|
|
if (nSLAVEC>4)
|
|
{ // have plenty of slaves
|
|
SetLocalInt(oMod,"nSlaverState",1);
|
|
} // have plenty of slaves
|
|
else
|
|
{ // hunt
|
|
nC=1;
|
|
oWP=GetWaypointByTag("DWF_RESOURCES");
|
|
oDest=CreateObject(OBJECT_TYPE_CREATURE,"mancommon",GetLocation(oWP));
|
|
oWP=OBJECT_INVALID;
|
|
oTarg=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oSCM,nC,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_NEUTRAL,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
|
|
while(oWP==OBJECT_INVALID&&oTarg!=OBJECT_INVALID)
|
|
{ // !OI
|
|
if(GetFactionEqual(oTarg,oDest)==TRUE) oWP=oTarg;
|
|
nC++;
|
|
oTarg=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oSCM,nC,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_NEUTRAL,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
|
|
} // !OI
|
|
if (oWP==OBJECT_INVALID)
|
|
{ // check enemy types
|
|
nC=1;
|
|
oTarg=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oSCM,nC,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
|
|
while(oWP==OBJECT_INVALID&&oTarg!=OBJECT_INVALID)
|
|
{ // !OI
|
|
if(GetFactionEqual(oTarg,oDest)==TRUE) oWP=oTarg;
|
|
nC++;
|
|
oTarg=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oSCM,nC,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY,CREATURE_TYPE_PERCEPTION,PERCEPTION_SEEN);
|
|
} // !OI
|
|
} // check enemy types
|
|
DestroyObject(oDest);
|
|
if (oWP!=OBJECT_INVALID)
|
|
{ // have a target
|
|
nC=0;
|
|
if (oSG1!=OBJECT_INVALID) { AssignCommand(oSG1,ClearAllActions()); AssignCommand(oSG1,ActionAttack(oWP)); nC++;}
|
|
if (oSG2!=OBJECT_INVALID) { AssignCommand(oSG2,ClearAllActions()); AssignCommand(oSG2,ActionAttack(oWP)); nC++;}
|
|
if (oSG3!=OBJECT_INVALID) { AssignCommand(oSG3,ClearAllActions()); AssignCommand(oSG3,ActionAttack(oWP)); nC++;}
|
|
if (oSG4!=OBJECT_INVALID) { AssignCommand(oSG4,ClearAllActions()); AssignCommand(oSG4,ActionAttack(oWP)); nC++;}
|
|
if (oSSO!=OBJECT_INVALID) { AssignCommand(oSSO,ClearAllActions()); AssignCommand(oSSO,ActionAttack(oWP)); nC++;}
|
|
if (oSIL!=OBJECT_INVALID) { AssignCommand(oSIL,ClearAllActions()); AssignCommand(oSIL,ActionAttack(oWP)); nC++;}
|
|
if (nC<2) {AssignCommand(oSCM,ClearAllActions()); AssignCommand(oSCM,ActionAttack(oWP)); }
|
|
} // have a target
|
|
else
|
|
{ // nothing left to hunt
|
|
SetLocalInt(oMod,"nSlaverState",7);
|
|
} // nothing left to hunt
|
|
} // hunt
|
|
break;
|
|
} // arrived at hunt destination look for nearby potential slaves
|
|
case 10: { // disband slave caravan
|
|
if (oSCM!=OBJECT_INVALID) fnDespawn(oSCM);
|
|
if (oSG1!=OBJECT_INVALID) fnDespawn(oSG1);
|
|
if (oSG2!=OBJECT_INVALID) fnDespawn(oSG2);
|
|
if (oSG3!=OBJECT_INVALID) fnDespawn(oSG3);
|
|
if (oSG4!=OBJECT_INVALID) fnDespawn(oSG4);
|
|
if (oSSO!=OBJECT_INVALID) fnDespawn(oSSO);
|
|
if (oSIL!=OBJECT_INVALID) fnDespawn(oSIL);
|
|
nR=GetLocalInt(oMod,"nSLAVEC");
|
|
nC=1;
|
|
nP=0;
|
|
while(nC<=nR)
|
|
{ // despawn the slaves
|
|
oTarg=GetLocalObject(oMod,"oSLAVE"+IntToString(nC));
|
|
if (oTarg!=OBJECT_INVALID) { fnDespawn(oTarg); nP++; }
|
|
nC++;
|
|
} // despawn the slaves
|
|
nC=GetLocalInt(oMod,"nSlaverPower");
|
|
nC=nC+(nP*2);
|
|
SetLocalInt(oMod,"nSlaverPower",nC);
|
|
SetLocalInt(oMod,"nSLAVEC",0);
|
|
SetLocalInt(oMod,"nSlaverState",0);
|
|
SetLocalInt(oMod,"nSlaverDestNum",0);
|
|
SetLocalInt(oMod,"nSlaverHuntNum",0);
|
|
SetLocalInt(oMod,"nSlaverSpeed",36);
|
|
nSpeed=36;
|
|
break;
|
|
} // disband slave caravan
|
|
case 11: { // look for nearest area transition
|
|
nC=fnClosestTransition(oDest,oSCM);
|
|
if (nC==TRUE)
|
|
{
|
|
SetLocalInt(oMod,"nSlaverState",2);
|
|
AssignCommand(oSCM,ClearAllActions());
|
|
AssignCommand(oSCM,ASActionMoveToObject(oDest,FALSE,1.0));
|
|
}
|
|
nSpeed=4;
|
|
break;
|
|
} // look for nearest area transition
|
|
} // Main slaver caravan switch
|
|
} // not in conversation or combate
|
|
else
|
|
{ // conversation or combat
|
|
if (GetIsInCombat(oSCM)==TRUE)
|
|
{ // keep caravan master protected
|
|
oTarg=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oSCM,1,CREATURE_TYPE_REPUTATION,REPUTATION_TYPE_ENEMY);
|
|
if (GetDistanceBetween(oTarg,oSCM)<10.0)
|
|
{ // move away
|
|
AssignCommand(oSCM,ClearAllActions(TRUE));
|
|
AssignCommand(oSCM,ActionMoveAwayFromObject(oTarg,TRUE,15.0));
|
|
nSpeed=6;
|
|
// look for nearby guards not engaged in combat
|
|
if (oSG1!=OBJECT_INVALID&&GetIsInCombat(oSG1)!=TRUE)
|
|
{ // move this guard to intercept nearest enemy
|
|
AssignCommand(oSG1,ClearAllActions());
|
|
AssignCommand(oSG1,ASActionMoveToObject(oTarg,TRUE,3.0));
|
|
AssignCommand(oSG1,ActionAttack(oTarg));
|
|
AssignCommand(oSG1,SpeakString("Protect the caravan master!"));
|
|
} // move this guard to intercept nearest enemy
|
|
if (oSG2!=OBJECT_INVALID&&GetIsInCombat(oSG1)!=TRUE)
|
|
{ // move this guard to intercept nearest enemy
|
|
AssignCommand(oSG2,ClearAllActions());
|
|
AssignCommand(oSG2,ASActionMoveToObject(oTarg,TRUE,3.0));
|
|
AssignCommand(oSG2,ActionAttack(oTarg));
|
|
AssignCommand(oSG2,SpeakString("Protect the caravan master!"));
|
|
} // move this guard to intercept nearest enemy
|
|
if (oSG3!=OBJECT_INVALID&&GetIsInCombat(oSG1)!=TRUE)
|
|
{ // move this guard to intercept nearest enemy
|
|
AssignCommand(oSG3,ClearAllActions());
|
|
AssignCommand(oSG3,ASActionMoveToObject(oTarg,TRUE,3.0));
|
|
AssignCommand(oSG3,ActionAttack(oTarg));
|
|
AssignCommand(oSG3,SpeakString("Protect the caravan master!"));
|
|
} // move this guard to intercept nearest enemy
|
|
if (oSG4!=OBJECT_INVALID&&GetIsInCombat(oSG1)!=TRUE)
|
|
{ // move this guard to intercept nearest enemy
|
|
AssignCommand(oSG4,ClearAllActions());
|
|
AssignCommand(oSG4,ASActionMoveToObject(oTarg,TRUE,3.0));
|
|
AssignCommand(oSG4,ActionAttack(oTarg));
|
|
AssignCommand(oSG4,SpeakString("Protect the caravan master!"));
|
|
} // move this guard to intercept nearest enemy
|
|
if (oSSO!=OBJECT_INVALID&&GetIsInCombat(oSSO)!=TRUE)
|
|
{ // move this guard to intercept nearest enemy
|
|
AssignCommand(oSSO,ClearAllActions());
|
|
AssignCommand(oSSO,SpeakString("Those that attack the caravan master are mine to kill!"));
|
|
AssignCommand(oSSO,fnSorceressDefense(oTarg));
|
|
} // move this guard to intercept nearest enemy
|
|
} // Move Away
|
|
fnCheckHealSelf(oSCM);
|
|
} // keep caravan master protected
|
|
} // conversation or combat
|
|
} // caravan master still lives
|
|
else
|
|
{ // caravan master is either dead or does not exist
|
|
nC=FALSE;
|
|
if (oSG1!=OBJECT_INVALID||oSG2!=OBJECT_INVALID||oSG3!=OBJECT_INVALID||oSG4!=OBJECT_INVALID) nC=TRUE;
|
|
if (oSSO!=OBJECT_INVALID||oSIL!=OBJECT_INVALID) nC=TRUE;
|
|
if (nC==TRUE)
|
|
{ // remenants of a caravan still exists
|
|
if (oSG1!=OBJECT_INVALID) fnDespawn(oSG1);
|
|
if (oSG2!=OBJECT_INVALID) fnDespawn(oSG2);
|
|
if (oSG3!=OBJECT_INVALID) fnDespawn(oSG3);
|
|
if (oSG4!=OBJECT_INVALID) fnDespawn(oSG4);
|
|
if (oSSO!=OBJECT_INVALID) fnDespawn(oSSO);
|
|
if (oSIL!=OBJECT_INVALID) fnDespawn(oSIL);
|
|
SetLocalInt(oMod,"nSlaverState",0);
|
|
SetLocalInt(oMod,"nSLAVEC",0);
|
|
} // remenants of a caravan still exists
|
|
else
|
|
{ // create a new caravan
|
|
SetLocalInt(oMod,"nSlaverState",0);
|
|
SetLocalInt(oMod,"nSLAVEC",0);
|
|
SetLocalObject(oMod,"oSlaverDest",OBJECT_INVALID);
|
|
SetLocalObject(oMod,"oSlaverDistTest",OBJECT_INVALID);
|
|
SetLocalInt(oMod,"nSlaverDestNum",0);
|
|
SetLocalInt(oMod,"nSlaverHuntNum",0);
|
|
SetLocalFloat(oMod,"fSlaverLDist",0.0);
|
|
oSCM=CreateObject(OBJECT_TYPE_CREATURE,"slv",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSCM",oSCM);
|
|
SetAILevel(oSCM,AI_LEVEL_NORMAL);
|
|
SetLocalInt(oMod,"nSlaverSpeed",0);
|
|
if (nSlaverPower<21)
|
|
{ // less than 21
|
|
oSG1=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG1",oSG1);
|
|
SetAILevel(oSG1,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG1,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG1,"nMode",0);
|
|
oSG2=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG2",oSG2);
|
|
SetAILevel(oSG2,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG2,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG2,"nMode",0);
|
|
oSG3=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG3",oSG3);
|
|
SetAILevel(oSG3,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG3,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG3,"nMode",0);
|
|
oSG4=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG4",oSG4);
|
|
SetAILevel(oSG4,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG4,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG4,"nMode",0);
|
|
} // less than 21
|
|
else if (nSlaverPower<41)
|
|
{ // less than 41
|
|
oSG1=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG1",oSG1);
|
|
SetAILevel(oSG1,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG1,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG1,"nMode",0);
|
|
oSG2=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG2",oSG2);
|
|
SetAILevel(oSG2,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG2,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG2,"nMode",0);
|
|
oSG3=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG3",oSG3);
|
|
SetAILevel(oSG3,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG3,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG3,"nMode",0);
|
|
oSG4=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG4",oSG4);
|
|
SetAILevel(oSG4,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG4,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG4,"nMode",0);
|
|
oSSO=CreateObject(OBJECT_TYPE_CREATURE,"slvg2",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSSO",oSSO);
|
|
SetAILevel(oSSO,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSSO,fnGuardFollow(oSCM,3.0));
|
|
SetLocalInt(oSSO,"nMode",0);
|
|
} // less than 41
|
|
else if (nSlaverPower<61)
|
|
{ // less than 61
|
|
oSG1=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG1",oSG1);
|
|
SetAILevel(oSG1,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG1,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG1,"nMode",0);
|
|
oSG2=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG2",oSG2);
|
|
SetAILevel(oSG2,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG2,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG2,"nMode",0);
|
|
oSG3=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG3",oSG3);
|
|
SetAILevel(oSG3,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG3,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG3,"nMode",0);
|
|
oSG4=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG4",oSG4);
|
|
SetAILevel(oSG4,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG4,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG4,"nMode",0);
|
|
oSSO=CreateObject(OBJECT_TYPE_CREATURE,"slvg2",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSSO",oSSO);
|
|
SetAILevel(oSSO,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSSO,fnGuardFollow(oSCM,3.0));
|
|
SetLocalInt(oSSO,"nMode",0);
|
|
} // less than 61
|
|
else if (nSlaverPower<81)
|
|
{ // less than 81
|
|
oSG1=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG1",oSG1);
|
|
SetAILevel(oSG1,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG1,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG1,"nMode",0);
|
|
oSG2=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG2",oSG2);
|
|
SetAILevel(oSG2,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG2,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG2,"nMode",0);
|
|
oSG3=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG3",oSG3);
|
|
SetAILevel(oSG3,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG3,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG3,"nMode",0);
|
|
oSG4=CreateObject(OBJECT_TYPE_CREATURE,"slvg1",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG4",oSG4);
|
|
SetAILevel(oSG4,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG4,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG4,"nMode",0);
|
|
oSSO=CreateObject(OBJECT_TYPE_CREATURE,"slvg2",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSSO",oSSO);
|
|
SetAILevel(oSSO,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSSO,fnGuardFollow(oSCM,3.0));
|
|
SetLocalInt(oSSO,"nMode",0);
|
|
} // less than 41
|
|
else if (nSlaverPower<61)
|
|
{ // less than 61
|
|
oSG1=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG1",oSG1);
|
|
SetAILevel(oSG1,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG1,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG1,"nMode",0);
|
|
oSG2=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG2",oSG2);
|
|
SetAILevel(oSG2,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG2,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG2,"nMode",0);
|
|
oSG3=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG3",oSG3);
|
|
SetAILevel(oSG3,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG3,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG3,"nMode",0);
|
|
oSG4=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG4",oSG4);
|
|
SetAILevel(oSG4,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG4,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG4,"nMode",0);
|
|
oSSO=CreateObject(OBJECT_TYPE_CREATURE,"slvg2",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSSO",oSSO);
|
|
SetAILevel(oSSO,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSSO,fnGuardFollow(oSCM,3.0));
|
|
SetLocalInt(oSSO,"nMode",0);
|
|
} // less than 61
|
|
else if (nSlaverPower<81)
|
|
{ // less than 81
|
|
oSG1=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG1",oSG1);
|
|
SetAILevel(oSG1,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG1,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG1,"nMode",0);
|
|
oSG2=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG2",oSG2);
|
|
SetAILevel(oSG2,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG2,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG2,"nMode",0);
|
|
oSG3=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG3",oSG3);
|
|
SetAILevel(oSG3,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG3,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG3,"nMode",0);
|
|
oSG4=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG4",oSG4);
|
|
SetAILevel(oSG4,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG4,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG4,"nMode",0);
|
|
oSSO=CreateObject(OBJECT_TYPE_CREATURE,"slvg2",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSSO",oSSO);
|
|
SetAILevel(oSSO,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSSO,fnGuardFollow(oSCM,3.0));
|
|
SetLocalInt(oSSO,"nMode",0);
|
|
oSIL=CreateObject(OBJECT_TYPE_CREATURE,"slvg4",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSIL",oSIL);
|
|
SetAILevel(oSIL,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSIL,fnGuardFollow(oSCM,3.0));
|
|
SetLocalInt(oSIL,"nMode",0);
|
|
} // less than 81
|
|
else
|
|
{ // most powerful slave caravan
|
|
oSG1=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG1",oSG1);
|
|
SetAILevel(oSG1,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG1,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG1,"nMode",0);
|
|
oSG2=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG2",oSG2);
|
|
SetAILevel(oSG2,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG2,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG2,"nMode",0);
|
|
oSG3=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG3",oSG3);
|
|
SetAILevel(oSG3,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG3,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG3,"nMode",0);
|
|
oSG4=CreateObject(OBJECT_TYPE_CREATURE,"slvg3",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSG4",oSG4);
|
|
SetAILevel(oSG4,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSG4,fnGuardFollow(oSCM));
|
|
SetLocalInt(oSG4,"nMode",0);
|
|
oSSO=CreateObject(OBJECT_TYPE_CREATURE,"slvg2",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSSO",oSSO);
|
|
SetAILevel(oSSO,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSSO,fnGuardFollow(oSCM,3.0));
|
|
SetLocalInt(oSSO,"nMode",0);
|
|
oSIL=CreateObject(OBJECT_TYPE_CREATURE,"slvg5",GetLocation(oWP));
|
|
SetLocalObject(oMod,"oSIL",oSIL);
|
|
SetAILevel(oSIL,AI_LEVEL_NORMAL);
|
|
AssignCommand(oSIL,fnGuardFollow(oSCM,3.0));
|
|
SetLocalInt(oSIL,"nMode",0);
|
|
} // most powerful slave caravan
|
|
nSpeed=3;
|
|
} // create a new caravan
|
|
} // caravan master is either dead or does not exist
|
|
//////// End
|
|
if (nSpeed<1) DelayCommand(8.0,fnRelaunch(nSNS));
|
|
else { DelayCommand(IntToFloat(nSpeed),fnRelaunch(nSNS)); }
|
|
} // it is not disabled
|
|
else
|
|
{ // disabled
|
|
if (oSCM!=OBJECT_INVALID) fnDespawn(oSCM);
|
|
if (oSG1!=OBJECT_INVALID) fnDespawn(oSG1);
|
|
if (oSG2!=OBJECT_INVALID) fnDespawn(oSG2);
|
|
if (oSG3!=OBJECT_INVALID) fnDespawn(oSG3);
|
|
if (oSG4!=OBJECT_INVALID) fnDespawn(oSG4);
|
|
if (oSSO!=OBJECT_INVALID) fnDespawn(oSSO);
|
|
if (oSIL!=OBJECT_INVALID) fnDespawn(oSIL);
|
|
} // disabled
|
|
|
|
}
|
|
////////////////////////////////////////////////////////////// MAIN ////////////
|
|
|
|
//////////////////////
|
|
// FUNCTIONS
|
|
//////////////////////
|
|
void fnDespawn(object oCr)
|
|
{ // despawn object
|
|
if (oCr!=OBJECT_INVALID)
|
|
{ // !OI
|
|
if (IsInConversation(oCr)==TRUE||GetIsInCombat(oCr)==TRUE)
|
|
{ DelayCommand(10.0,fnDespawn(oCr)); } // wait for conv/combat end
|
|
else { DestroyObject(oCr); }
|
|
} // !OI
|
|
} // fnDespawn()
|
|
|
|
void fnCheckHealSelf(object oCr)
|
|
{ // if hurt bad try to heal self
|
|
if(GetCurrentHitPoints(oCr)<(GetMaxHitPoints(oCr)/2))
|
|
{ // 50% health or less - heal self
|
|
if (GetHasSpell(SPELL_CURE_SERIOUS_WOUNDS,oCr)!=0)
|
|
{ // cast cure serious wounds
|
|
ActionCastSpellAtObject(SPELL_CURE_SERIOUS_WOUNDS,oCr);
|
|
} // cast cure serious wounds
|
|
else if (GetHasSpell(SPELL_CURE_MODERATE_WOUNDS,oCr)!=0)
|
|
{ // cast cure moderate wounds
|
|
ActionCastSpellAtObject(SPELL_CURE_MODERATE_WOUNDS,oCr);
|
|
} // cast cure moderate wounds
|
|
else if (GetHasSpell(SPELL_CURE_LIGHT_WOUNDS,oCr)!=0)
|
|
{ // cure light wounds
|
|
ActionCastSpellAtObject(SPELL_CURE_LIGHT_WOUNDS,oCr);
|
|
} // cure light wounds
|
|
else if (GetHasSpell(SPELL_CURE_MINOR_WOUNDS,oCr)!=0)
|
|
{ // cure minor wounds
|
|
ActionCastSpellAtObject(SPELL_CURE_MINOR_WOUNDS,oCr);
|
|
} // cure minor wounds
|
|
} // 50% health or less - heal self
|
|
} // fnCheckHealSelf()
|
|
|
|
int mod_GetHasEffect(object oTarg,effect eE)
|
|
{ // returns TRUE if has the effect
|
|
int nRet=FALSE;
|
|
effect eEff=GetFirstEffect(oTarg);
|
|
while(GetEffectType(eEff)!=EFFECT_TYPE_INVALIDEFFECT&&nRet!=TRUE)
|
|
{ // check effects
|
|
if (eEff==eE) nRet=TRUE;
|
|
eEff=GetNextEffect(oTarg);
|
|
} // check effects
|
|
return nRet;
|
|
} // GetHasEffect()
|
|
|
|
int fnGetIsPerson(object oTarg)
|
|
{ // returns TRUE if this creature can be classified as a person
|
|
int nRet=FALSE;
|
|
if (MyPRCGetRacialType(oTarg)==RACIAL_TYPE_DWARF||MyPRCGetRacialType(oTarg)==RACIAL_TYPE_ELF||MyPRCGetRacialType(oTarg)==RACIAL_TYPE_GNOME||MyPRCGetRacialType(oTarg)==RACIAL_TYPE_HALFELF) nRet=TRUE;
|
|
else if (MyPRCGetRacialType(oTarg)==RACIAL_TYPE_HALFLING||MyPRCGetRacialType(oTarg)==RACIAL_TYPE_HALFORC||MyPRCGetRacialType(oTarg)==RACIAL_TYPE_HUMAN) nRet=TRUE;
|
|
else if (MyPRCGetRacialType(oTarg)==RACIAL_TYPE_HUMANOID_GOBLINOID||MyPRCGetRacialType(oTarg)==RACIAL_TYPE_HUMANOID_ORC) nRet=TRUE;
|
|
return nRet;
|
|
} // fnGetIsPerson()
|
|
|
|
void fnSorceressDefense(object oTarg)
|
|
{ // check oTarg and disable it - protect caravan master
|
|
if (GetChallengeRating(oTarg)<2.1)
|
|
{ // lesser target
|
|
if (GetHasSpellEffect(SPELL_SLEEP,oTarg)!=TRUE&&GetHasSpell(SPELL_SLEEP,OBJECT_SELF)!=0&&MyPRCGetRacialType(oTarg)!=RACIAL_TYPE_UNDEAD&&MyPRCGetRacialType(oTarg)!=RACIAL_TYPE_CONSTRUCT)
|
|
{ // cast sleep
|
|
ActionCastSpellAtObject(SPELL_SLEEP,oTarg);
|
|
} // cast sleep
|
|
else
|
|
{ // next spell
|
|
if(GetHasSpellEffect(SPELL_SLEEP,oTarg)==TRUE)
|
|
{ // sleeping
|
|
ActionAttack(oTarg); // attack with light crossbow and poisoned bolts
|
|
} // sleeping
|
|
else
|
|
{ // not sleeping
|
|
if(GetHasSpellEffect(SPELL_DAZE,oTarg)!=TRUE&&GetHasSpell(SPELL_DAZE,OBJECT_SELF)!=0&&MyPRCGetRacialType(oTarg)!=RACIAL_TYPE_UNDEAD&&MyPRCGetRacialType(oTarg)!=RACIAL_TYPE_CONSTRUCT)
|
|
{ // cast daze
|
|
ActionCastSpellAtObject(SPELL_DAZE,oTarg);
|
|
} // cast daze
|
|
else
|
|
{ // next spell
|
|
if(GetHasSpell(SPELL_MAGIC_MISSILE,oTarg)!=0)
|
|
{ // cast magic missile
|
|
ActionCastSpellAtObject(SPELL_MAGIC_MISSILE,oTarg);
|
|
} // cast magic missile
|
|
else if (GetHasSpell(SPELL_ACID_SPLASH,oTarg)!=0)
|
|
{ // cast acid splash
|
|
ActionCastSpellAtObject(SPELL_ACID_SPLASH,oTarg);
|
|
} // cast acid splash
|
|
else if (GetHasSpell(SPELL_MELFS_ACID_ARROW,oTarg)!=0)
|
|
{ // cast MELFS ACID ARROW
|
|
ActionCastSpellAtObject(SPELL_MELFS_ACID_ARROW,oTarg);
|
|
} // cast MELFS ACID ARROW
|
|
else if (GetHasSpell(SPELL_LIGHTNING_BOLT,oTarg)!=0)
|
|
{ // cast Lightning Bolt
|
|
ActionCastSpellAtObject(SPELL_LIGHTNING_BOLT,oTarg);
|
|
} // cast Lightning Bolt
|
|
else
|
|
{ // no spells - use light crossbow w/ poison
|
|
ActionAttack(oTarg);
|
|
} // no spells - use light crossbow w/ poison
|
|
} // next spell
|
|
} // not sleeping
|
|
} // next spell
|
|
} // lesser target
|
|
else if (GetChallengeRating(oTarg)<6.1)
|
|
{ // medium target
|
|
if (GetHasSpellEffect(SPELL_HOLD_PERSON,oTarg)!=TRUE&&GetHasSpell(SPELL_HOLD_PERSON,OBJECT_SELF)!=0&&fnGetIsPerson(oTarg)==TRUE)
|
|
{ // cast hold person
|
|
ActionCastSpellAtObject(SPELL_HOLD_PERSON,oTarg);
|
|
} // cast hold person
|
|
else
|
|
{ // might be held or other spell
|
|
if (GetHasSpellEffect(SPELL_HOLD_PERSON,oTarg)==TRUE)
|
|
{ // held - shoot with crossbow
|
|
ActionAttack(oTarg);
|
|
} // held - shoot with crossbow
|
|
else
|
|
{ // not held - use tentacles
|
|
if (GetHasSpellEffect(SPELL_EVARDS_BLACK_TENTACLES,oTarg)!=TRUE&&GetHasSpell(SPELL_EVARDS_BLACK_TENTACLES,OBJECT_SELF)!=0)
|
|
{ // evard's black tentacles
|
|
ActionCastSpellAtObject(SPELL_EVARDS_BLACK_TENTACLES,oTarg);
|
|
} // evard's black tentacles
|
|
else
|
|
{ // blast them
|
|
if (GetHasSpell(SPELL_LIGHTNING_BOLT,OBJECT_SELF)!=0)
|
|
{ // lightning bolt
|
|
ActionCastSpellAtObject(SPELL_LIGHTNING_BOLT,oTarg);
|
|
} // lightning bolt
|
|
else if (GetHasSpell(SPELL_MELFS_ACID_ARROW,OBJECT_SELF)!=0)
|
|
{ // Melf's Acid Arrow
|
|
ActionCastSpellAtObject(SPELL_MELFS_ACID_ARROW,oTarg);
|
|
} // Melf's Acid Arrow
|
|
else if (GetHasSpell(SPELL_MAGIC_MISSILE,OBJECT_SELF)!=0)
|
|
{ // Magic Missile
|
|
ActionCastSpellAtObject(SPELL_MAGIC_MISSILE,oTarg);
|
|
} // Magic Missile
|
|
else if (GetHasSpell(SPELL_ACID_SPLASH,OBJECT_SELF)!=0)
|
|
{ // Acid Splash
|
|
ActionCastSpellAtObject(SPELL_ACID_SPLASH,oTarg);
|
|
} // Acid Splash
|
|
else
|
|
{ // attack with crossbow
|
|
ActionAttack(oTarg);
|
|
} // attack with crossbow
|
|
} // blast them
|
|
} // not held - use tentacles
|
|
} // might be held or other spell
|
|
} // medium target
|
|
else
|
|
{ // Dangerous target
|
|
if (GetHasSpellEffect(SPELL_EVARDS_BLACK_TENTACLES,oTarg)!=TRUE&&GetHasSpell(SPELL_EVARDS_BLACK_TENTACLES,OBJECT_SELF)!=0)
|
|
{ // evard's black tentacles
|
|
ActionCastSpellAtObject(SPELL_EVARDS_BLACK_TENTACLES,oTarg);
|
|
} // evard's black tentacles
|
|
else
|
|
{ // blast them
|
|
if (GetHasSpell(SPELL_LIGHTNING_BOLT,OBJECT_SELF)!=0)
|
|
{ // lightning bolt
|
|
ActionCastSpellAtObject(SPELL_LIGHTNING_BOLT,oTarg);
|
|
} // lightning bolt
|
|
else if (GetHasSpell(SPELL_MELFS_ACID_ARROW,OBJECT_SELF)!=0)
|
|
{ // Melf's Acid Arrow
|
|
ActionCastSpellAtObject(SPELL_MELFS_ACID_ARROW,oTarg);
|
|
} // Melf's Acid Arrow
|
|
else if (GetHasSpell(SPELL_MAGIC_MISSILE,OBJECT_SELF)!=0)
|
|
{ // Magic Missile
|
|
ActionCastSpellAtObject(SPELL_MAGIC_MISSILE,oTarg);
|
|
} // Magic Missile
|
|
else if (GetHasSpell(SPELL_ACID_SPLASH,OBJECT_SELF)!=0)
|
|
{ // Acid Splash
|
|
ActionCastSpellAtObject(SPELL_ACID_SPLASH,oTarg);
|
|
} // Acid Splash
|
|
else
|
|
{ // attack with crossbow
|
|
ActionAttack(oTarg);
|
|
} // attack with crossbow
|
|
} // blast them
|
|
} // dangerous target
|
|
} // fnSorceressDefense()
|
|
|
|
void fnGuardFollow(object oMaster,float fDist=5.0)
|
|
{ // follow the master 5.0 distance
|
|
object oMe=OBJECT_SELF;
|
|
float fCDist=GetDistanceBetween(oMaster,oMe);
|
|
int nLagCount=GetLocalInt(oMe,"nLagCount");
|
|
if (GetLocalInt(oMe,"nMode")==0&&GetIsInCombat(oMe)!=TRUE)
|
|
{ // follow
|
|
if (GetArea(oMaster)!=GetArea(oMe))
|
|
{ // teleport
|
|
AssignCommand(oMe,ClearAllActions());
|
|
AssignCommand(oMe,JumpToObject(oMaster));
|
|
} // teleport
|
|
else if (fCDist>=(fDist*2.0))
|
|
{ // run
|
|
AssignCommand(oMe,ClearAllActions());
|
|
AssignCommand(oMe,ASActionMoveToObject(oMaster,TRUE,fDist));
|
|
nLagCount++;
|
|
SetLocalInt(oMe,"nLagCount",nLagCount);
|
|
if (nLagCount>15)
|
|
{ // can't catch up - teleport
|
|
AssignCommand(oMe,ClearAllActions());
|
|
AssignCommand(oMe,JumpToObject(oMaster));
|
|
} // can't catch up - teleport
|
|
} // run
|
|
else if (fCDist>fDist)
|
|
{ // walk
|
|
AssignCommand(oMe,ClearAllActions());
|
|
AssignCommand(oMe,ASActionMoveToObject(oMaster,FALSE,fDist));
|
|
SetLocalInt(oMe,"nLagCount",0);
|
|
} // walk
|
|
else { SetLocalInt(oMe,"nLagCount",0); }
|
|
} // follow
|
|
DelayCommand(5.0,fnGuardFollow(oMaster,fDist));
|
|
} // fnGuardFollow()
|
|
|
|
void fnDespawnIfNoSlavers()
|
|
{
|
|
object oMaster=GetLocalObject(OBJECT_SELF,"oMaster");
|
|
if (oMaster==OBJECT_INVALID||GetIsDead(oMaster)==TRUE) DestroyObject(OBJECT_SELF);
|
|
DelayCommand(30.0,fnDespawnIfNoSlavers());
|
|
} // fnDespawnIfNoSlavers()
|
|
|
|
int fnClosestTransition(object oDest,object oSCM)
|
|
{ // For some reason Bioware Pathing doesn't always use the closest transition
|
|
// to an area.... even when the NPC is standing directly next to the correct
|
|
// door. This overrides that... returns TRUE when it reaches the area oDest
|
|
// is in.
|
|
int nRet=FALSE;
|
|
object oNearT;
|
|
object oNearD;
|
|
object oTT;
|
|
int nC=1;
|
|
float fDist;
|
|
int bFound=FALSE;
|
|
if (GetArea(oDest)==GetArea(oSCM)) return TRUE;
|
|
oNearT=GetNearestObject(OBJECT_TYPE_TRIGGER,oSCM,nC);
|
|
oNearD=GetNearestObject(OBJECT_TYPE_DOOR,oSCM,nC);
|
|
while((oNearT!=OBJECT_INVALID||oNearD!=OBJECT_INVALID)&&bFound!=TRUE)
|
|
{ // find transition
|
|
if (oNearT!=OBJECT_INVALID)
|
|
{ // !OI NT
|
|
oTT=GetTransitionTarget(oNearT);
|
|
if (oTT!=OBJECT_INVALID&&GetArea(oTT)==GetArea(oDest))
|
|
{ // move
|
|
bFound=TRUE;
|
|
fDist=GetDistanceBetween(oNearT,oSCM);
|
|
if (fDist<3.0)
|
|
{ // transition
|
|
AssignCommand(oSCM,ClearAllActions());
|
|
AssignCommand(oSCM,JumpToObject(oTT));
|
|
} // transition
|
|
else
|
|
{
|
|
AssignCommand(oSCM,ASActionMoveToObject(oNearT,FALSE,2.5));
|
|
}
|
|
return FALSE;
|
|
} // move
|
|
} // !OI NT
|
|
if (oNearD!=OBJECT_INVALID)
|
|
{ // !OI ND
|
|
oTT=GetTransitionTarget(oNearD);
|
|
if (oTT!=OBJECT_INVALID&&GetArea(oTT)==GetArea(oDest))
|
|
{ // move
|
|
bFound=TRUE;
|
|
fDist=GetDistanceBetween(oNearD,oSCM);
|
|
if (fDist<3.0)
|
|
{ // transition
|
|
AssignCommand(oSCM,ClearAllActions());
|
|
AssignCommand(oNearD,ActionOpenDoor(oNearD));
|
|
AssignCommand(oSCM,ActionPlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,2.0));
|
|
AssignCommand(oSCM,JumpToObject(oTT));
|
|
} // transition
|
|
else
|
|
{
|
|
AssignCommand(oSCM,ASActionMoveToObject(oNearD,FALSE,2.5));
|
|
}
|
|
return FALSE;
|
|
} // move
|
|
} // !OI ND
|
|
// next pair
|
|
nC++;
|
|
oNearT=GetNearestObject(OBJECT_TYPE_TRIGGER,oSCM,nC);
|
|
oNearD=GetNearestObject(OBJECT_TYPE_DOOR,oSCM,nC);
|
|
} // find transition
|
|
if (bFound==FALSE)
|
|
{ // could not find area transition
|
|
AssignCommand(oSCM,SpeakString("I could not find the nearest path."));
|
|
return TRUE;
|
|
} // could not find area transition
|
|
return nRet;
|
|
} // fnClosestTransition()
|