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