409 lines
15 KiB
Plaintext
409 lines
15 KiB
Plaintext
// 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()
|