// RTS - Harvest of Souls (scout routine) // By Deva Bryson Winblood // 11/29/2003 ///////////////////////////////////////// #include "rts_header" ///////////////// // PROTOTYPES ///////////////// object fnObjectOfInterest(); object fnMakeMessenger(object oMsg,string sID); object fnRandomTrans(object oArea); object fnRandomObjects(object oArea); int fnNotValid(object oArea); //////////////////////////////////////////////////////////////// MAIN void main() { object oMe=OBJECT_SELF; object oMod=GetModule(); string sID=GetLocalString(oMe,"sTeamID"); object oHome=GetWaypointByTag(sID+"_START"); int nSState=GetLocalInt(oMe,"nSState"); object oH; object oDest=GetLocalObject(oMe,"oDestWP"); float fDist; object oLArea1=GetLocalObject(oMe,"oLArea1"); object oLArea2=GetLocalObject(oMe,"oLArea2"); int nN; int nR; object oMsg; string sMsg; object oBird; object oArea=GetArea(oMe); int nRun=GetLocalInt(oMe,"nRun"); float fFacing=GetFacing(oMe); switch(nSState) { // the scout main switch case 0: { // look for anything interesting //SendMessageToPC(GetFirstPC(),GetName(oMe)+" looking for items of interest."); fFacing=fFacing+90.0; if (fFacing>=360.0) fFacing=fFacing-360.0; SetFacing(fFacing); ActionPlayAnimation(ANIMATION_LOOPING_LOOK_FAR,1.0,4.0); oH=fnObjectOfInterest(); if (oH!=OBJECT_INVALID) { // item of interest nN=GetObjectType(oH); SetLocalObject(oMe,"oDestWP",oH); if (nN==OBJECT_TYPE_CREATURE) SetLocalInt(oMe,"nSState",3); else if (nN==OBJECT_TYPE_PLACEABLE) SetLocalInt(oMe,"nSState",4); else if (nN==OBJECT_TYPE_ITEM) SetLocalInt(oMe,"nSState",5); } // item of interest else { // move on SetLocalInt(oMe,"nSState",1); } // move on break; } // look for anything interesting case 1: { // find next destination //SendMessageToPC(GetFirstPC(),GetName(oMe)+" looking for destination."); if(oArea==oHome||(d6()<4)) { // seek next area //SendMessageToPC(GetFirstPC(),GetName(oMe)+" area transition."); oH=fnRandomTrans(oArea); oH=GetTransitionTarget(oH); oArea=GetArea(oH); nN=0; while((oH==OBJECT_INVALID||(oArea==oLArea1||oArea==oLArea2||fnNotValid(oH)==TRUE))&&nN<3) { // while find oH=fnRandomTrans(GetArea(oMe)); oH=GetTransitionTarget(oH); oArea=GetArea(oH); nN++; } // while find if (oArea==oLArea1||oArea==oLArea2||fnNotValid(oH)==TRUE) { if (GetLocalInt(GetArea(oMe),"nPathingTC")!=1) { oH=OBJECT_INVALID; } } if (oH!=OBJECT_INVALID) { // pick destination nN=d4(); if (d4()<4) oDest=GetNearestObject(OBJECT_TYPE_PLACEABLE,oH,nN); else { oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oH,nN); } nN--; if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_PLACEABLE,oH,nN); if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oH,nN); nN--; if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_PLACEABLE,oH,nN); if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oH,nN); nN--; if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_PLACEABLE,oH,nN); if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oH,nN); if (oDest!=OBJECT_INVALID) { // success SetLocalObject(oMe,"oDestWP",oDest); SetLocalInt(oMe,"nSState",2); SetLocalObject(oMe,"oLArea2",oLArea1); SetLocalObject(oMe,"oLArea1",GetArea(oMe)); } // success } // pick destination else { // couldn't find a way - let's just move through one anyway oArea=GetArea(oMe); oH=fnRandomTrans(oArea); oH=GetTransitionTarget(oH); nN=d4(); if (d4()<4) oDest=GetNearestObject(OBJECT_TYPE_PLACEABLE,oH,nN); else { oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oH,nN); } nN--; if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_PLACEABLE,oH,nN); if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oH,nN); nN--; if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_PLACEABLE,oH,nN); if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oH,nN); nN--; if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_PLACEABLE,oH,nN); if (oDest==OBJECT_INVALID) oDest=GetNearestObject(OBJECT_TYPE_WAYPOINT,oH,nN); if (oDest!=OBJECT_INVALID) { // success SetLocalObject(oMe,"oDestWP",oDest); SetLocalInt(oMe,"nSState",2); SetLocalObject(oMe,"oLArea2",oLArea1); SetLocalObject(oMe,"oLArea1",GetArea(oMe)); } // success } // couldn't find a way - let's just move through one anyway } // seek next area else { // seek random object oDest=fnRandomObjects(GetArea(oMe)); if (oDest!=OBJECT_INVALID) { // success SetLocalObject(oMe,"oDestWP",oDest); SetLocalInt(oMe,"nSState",2); } // success } // seek random object break; } // find next destination case 2: { // move to destination nN=fnMoveToDestination(oDest,nRun); //SendMessageToPC(GetFirstPC(),GetName(oMe)+" moving to "+GetTag(oDest)+" in area "+GetName(GetArea(oDest))+"."); if (nN==1||(GetArea(oDest)==GetArea(oMe)&&GetDistanceBetween(oMe,oDest)<3.1)) { // should have arrived SetLocalInt(oMe,"nSState",0); } // should have arrived else if (nN==-1) { // error if(GetAbilityScore(oMe,ABILITY_INTELLIGENCE)>9) AssignCommand(oMe,SpeakString("I can't seem to reach "+GetName(oDest)+" in this area.")); SetLocalInt(oMe,"nSState",0); } // error break; } // move to destination case 3: { // message - merchant or plot creature oMsg=CreateItemOnObject("rtsa_message",oMe); sMsg="I encountered an interesting individual by the name of "+GetName(oDest)+" in area "+GetName(GetArea(oDest))+"."; SetLocalObject(oDest,"oLastSeen"+sID,GetArea(oDest)); SetLocalString(oMsg,"sMsg",sMsg); SetLocalObject(oMsg,"oDest",GetWaypointByTag(sID+"_START")); oDest=GetLocalObject(oMod,"oTeamLead"+sID); SetLocalString(oMsg,"sTo",GetName(oDest)); SetLocalString(oMsg,"sName",GetName(oMe)); oBird=fnMakeMessenger(oMsg,sID); AssignCommand(oBird,ClearAllActions()); DelayCommand(5.0,AssignCommand(oBird,ExecuteScript("rtsa_ai_birdmsg",oBird))); SetLocalInt(oMe,"nSState",0); break; } // message - merchant or plot creature case 4: { // message - mana pool sMsg="I saw a "+GetName(oDest)+" in area "; sMsg=sMsg+GetName(GetArea(oDest))+"."; oMsg=CreateItemOnObject("rtsa_message",oMe); SetLocalObject(oDest,"oLastSeen"+sID,GetArea(oDest)); SetLocalString(oMsg,"sMsg",sMsg); SetLocalObject(oMsg,"oDest",GetWaypointByTag(sID+"_START")); oDest=GetLocalObject(oMod,"oTeamLead"+sID); SetLocalString(oMsg,"sTo",GetName(oDest)); SetLocalString(oMsg,"sName",GetName(oMe)); oBird=fnMakeMessenger(oMsg,sID); AssignCommand(oBird,ClearAllActions()); DelayCommand(5.0,AssignCommand(oBird,ExecuteScript("rtsa_ai_birdmsg",oBird))); SetLocalInt(oMe,"nSState",0); break; } // message - mana pool case 5: { // message - item of value sMsg="I saw what looked to be an interesting item lying on the ground in "+GetName(GetArea(oDest))+"."; sMsg=" I did not attempt to take it because, I thought I should report it first."; oH=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,oDest,1); if (GetDistanceBetween(oH,oDest)<3.0) sMsg=sMsg+"It appears to be guarded by a "+GetName(oH)+"."; SetLocalObject(oDest,"oLastSeen"+sID,GetArea(oDest)); SetLocalString(oMsg,"sMsg",sMsg); SetLocalObject(oMsg,"oDest",GetWaypointByTag(sID+"_START")); oDest=GetLocalObject(oMod,"oTeamLead"+sID); SetLocalString(oMsg,"sTo",GetName(oDest)); SetLocalString(oMsg,"sName",GetName(oMe)); oBird=fnMakeMessenger(oMsg,sID); AssignCommand(oBird,ClearAllActions()); DelayCommand(5.0,AssignCommand(oBird,ExecuteScript("rtsa_ai_birdmsg",oBird))); SetLocalInt(oMe,"nSState",0); break; } // message - item of value } // the scout main switch } //////////////////////////////////////////////////////////////// MAIN ///////////////////////// // FUNCTIONS ///////////////////////// //// Randoms void fnBuildTransRand(object oArea) { // build a list of transitions from this area int nC=0; int nL=1; object oFirst=GetFirstObjectInArea(oArea); object oTrans; oFirst=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,1); //SendMessageToPC(GetFirstPC(),"fnBuildTransRand()"); if (oFirst!=OBJECT_INVALID) { oTrans=GetNearestObject(OBJECT_TYPE_TRIGGER,oFirst,nL); while(oTrans!=OBJECT_INVALID) { // triggers if(GetTransitionTarget(oTrans)!=OBJECT_INVALID) { // transition nC++; SetLocalObject(oArea,"oPathingTrans"+IntToString(nC),oTrans); } // transition nL++; oTrans=GetNearestObject(OBJECT_TYPE_TRIGGER,oFirst,nL); } // triggers nL=1; oTrans=GetNearestObject(OBJECT_TYPE_DOOR,oFirst,nL); while(oTrans!=OBJECT_INVALID) { // doors if(GetTransitionTarget(oTrans)!=OBJECT_INVALID) { // transition nC++; SetLocalObject(oArea,"oPathingTrans"+IntToString(nC),oTrans); } // transition nL++; oTrans=GetNearestObject(OBJECT_TYPE_DOOR,oFirst,nL); } // doors SetLocalInt(oArea,"nPathingTC",nC); } else { AssignCommand(OBJECT_SELF,SpeakString("This area is impossible to escape!!!")); SendMessageToPC(GetFirstPC(),"RTS SETUP ERROR: Area "+GetName(oArea)+" has no transitions!"); } } // fnBuildTransRand() void fnBuildObjectRand(object oArea) { // build a list of objects int nC=0; int nL=1; object oFirst=GetFirstObjectInArea(oArea); object oTrans; //SendMessageToPC(GetFirstPC(),"fnBuildObjectRand()"); oFirst=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,1); if (oFirst!=OBJECT_INVALID) { oTrans=GetNearestObject(OBJECT_TYPE_PLACEABLE,oFirst,nL); while(oTrans!=OBJECT_INVALID) { // placeables nC++; SetLocalObject(oArea,"oPathingObs"+IntToString(nC),oTrans); nL++; oTrans=GetNearestObject(OBJECT_TYPE_PLACEABLE,oFirst,nL); } // placeables nL=1; oTrans=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,nL); while(oTrans!=OBJECT_INVALID) { // waypoints nC++; SetLocalObject(oArea,"oPathingObs"+IntToString(nC),oTrans); nL++; oTrans=GetNearestObject(OBJECT_TYPE_WAYPOINT,oFirst,nL); } // waypoints nC++; SetLocalObject(oArea,"oPathingObs"+IntToString(nC),oFirst); SetLocalInt(oArea,"nPathingOC",nC); } } // fnBuildObjectRand() object fnRandomTrans(object oArea) { // return a random transition door or trigger object oRet=OBJECT_INVALID; int nC=GetLocalInt(oArea,"nPathingTC"); if (nC<1) { fnBuildTransRand(oArea); return OBJECT_INVALID; } else { nC=Random(nC)+1; oRet=GetLocalObject(oArea,"oPathingTrans"+IntToString(nC)); } return oRet; } // fnRandomTrans() object fnRandomObjects(object oArea) { // return an object in this area object oRet=OBJECT_INVALID; int nC=GetLocalInt(oArea,"nPathingOC"); if (nC<1) { fnBuildObjectRand(oArea); return OBJECT_INVALID; } else { nC=Random(nC)+1; oRet=GetLocalObject(oArea,"oPathingObs"+IntToString(nC)); } return oRet; } // fnRandomObjects() //////////// messenger object fnMakeMessenger(object oMsg,string sID) { // return messenger bird object oBird=OBJECT_INVALID; string sResRef=sID+"_bird"; object oSource=GetItemPossessor(oMsg); //fnDebug(" [SCOUT]fnMakeMessenger("+GetName(oMsg)+")"); if (oMsg!=OBJECT_INVALID) { // valid message oBird=CreateObject(OBJECT_TYPE_CREATURE,sResRef,GetLocation(oSource),FALSE); ChangeFaction(oBird,oSource); SetLocalString(oBird,"sTeamID",GetLocalString(oSource,"sTeamID")); SetLocalObject(oBird,"oDest",GetLocalObject(oMsg,"oDest")); SetLocalFloat(oBird,"fDelay",10.0); AssignCommand(oSource,ClearAllActions()); AssignCommand(oSource,ActionGiveItem(oMsg,oBird)); //fnDebug(" Bird:"+GetName(oBird)); SetAILevel(oBird,AI_LEVEL_NORMAL); SetDroppableFlag(oMsg,TRUE); } // valid message return oBird; } // fnMakeMessenger() /////////// find float fnGetVisionRange(object oMe) { // return distance can notice float fRet=25.0; return fRet; } // fnGetVisionRange() object fnObjectOfInterest() { // return objects of interest object oRet=OBJECT_INVALID; object oMe=OBJECT_SELF; string sID=GetLocalString(oMe,"sTeamID"); object oH; int nC; int nType; string sT; float fRange=fnGetVisionRange(oMe); object oMerch=GetObjectByTag("Wizard"); if (GetNearestObjectByTag(sID+"_START")!=OBJECT_INVALID) return OBJECT_INVALID; // in your own lair if (oMerch==OBJECT_INVALID) oMerch=GetObjectByTag("Rotund"); if (oMerch==OBJECT_INVALID) oMerch=GetObjectByTag("Fence"); if (oMerch==OBJECT_INVALID) oMerch=GetObjectByTag("Smith"); if (oMerch==OBJECT_INVALID) oMerch=GetObjectByTag("Apothecary"); nC=1; oH=GetNearestObject(OBJECT_TYPE_ALL,oMe,nC); while(oH!=OBJECT_INVALID&&GetDistanceBetween(oH,oMe)<=fRange) { // poll nearby items if(GetLocalInt(oH,"nScouted"+sID)!=TRUE) { // possible target SetLocalInt(oH,"nScouted"+sID,TRUE); nType=GetObjectType(oH); sT=GetTag(oH); if (nType==OBJECT_TYPE_CREATURE&&(GetPlotFlag(oH)==TRUE||GetFactionEqual(oMerch,oH)==TRUE)) return oH; if (nType==OBJECT_TYPE_PLACEABLE&&(sT=="MinorManaPool"||sT=="ManaPool"||sT=="StrongManaPool")) return oH; if (nType==OBJECT_TYPE_ITEM&&(GetPlotFlag(oH)==TRUE||GetGoldPieceValue(oH)>2000||sT=="")) return oH; } // possible target // next item nC++; oH=GetNearestObject(OBJECT_TYPE_ALL,oMe,nC); } // poll nearby items return oRet; } // fnObjectOfInterest() int fnNotValid(object oArea) { // if not a valid area return TRUE object oFirst=GetFirstObjectInArea(oArea); object oPath=GetNearestObjectByTag("PATHINGA",oFirst,1); if (oPath==OBJECT_INVALID) oPath=GetNearestObjectByTag("PATHINGB",oFirst,1); if (oPath==OBJECT_INVALID) { // if (GetTag(oFirst)=="PATHINGA"||GetTag(oFirst)=="PATHINGB") oPath=oFirst; } // if (oPath==OBJECT_INVALID) return TRUE; if (GetName(oPath)=="AVOID") return TRUE; return FALSE; } // fnNotValid()