RATDOG/_module/nss/otres_overland.nss
Jaysyn904 909da8ff18 Added helms and dynamic goblins
Added  helms and dynamic goblins.  Added onEnter spawner scripts to all dungeon areas.  Fixed the Dishonest Patrol to be dynamic & more like PnP.  Full compile.

Co-Authored-By: Draygoth <65428430+Draygoth@users.noreply.github.com>
2022-11-30 00:45:38 -05:00

256 lines
13 KiB
Plaintext

/*This function simulates overland travel with random encounters
and making camp. Encounters are scaled.
Encounters based on AD&D DMG tables.
On entering the trigger, they will be told how far the nearest destination and
waypoint are in hours. This script will check at the appropriate times to see
if a random encounter happens.
If an encounter occurs, it will drop the players in a random area near an object
tagged sTerrain+"Random"+int (for example, ForestRandom1) and adjust the time
for the amount "travelled". Make sure that your area tag is not the same as
the JumToObject tag (this took me a looong time to figure out!)The random area
has a large number of inactive encounters, one of which will be activated by
the OnEnter script for the area. Every 12 hours of travelling will put them
at a rest stop to camp.
If you make any changes in this script, recompile the otres_travelcall script too
smo 2002/11/29 to 2002/12/28
03/20/2003 - Added local variable to prevent two parties from arriving in
same map. Note that if there are more parties going to random maps than
there are random maps, a debug message is displayed to the activating PC
and sent to the DM. <edit 6/02/2004>
04/28/2003 - Added coefficients to travel and encounter frequency
07/07/2003 - Changed GetFirstPC() to GetPCSpeaker and then loop through
PCSpeaker's faction to jump everybody. This should be
better for PWs
9/01/2003 - Added PW local integer
10/05/2003 - Fixed intermittent "no enemies" problem by activating encounter
in otres_overland rather than in the OnEnter trigger of the
area. Code added between the end of the PW support and the
beginning of the Send PCs to random map code.
*/
#include "nw_i0_plot"
#include "otres_inc"
//------------------------------------------------------------------------------
//This subroutine sends them to a random map if there is an encounter
//------------------------------------------------------------------------------
void EncounterResult(object oPC, int iHoursToGo, int iTravelledHours, string sDestination, string sTerrain, float fFacing)
{//begin EncounterResult function
int iTime; //Time (hours)
int iMapNumber; //The random map number
int iNumberRandomForestMaps=4; //Total number of random forest maps for encounters
int iNumberRandomPlainsMaps=4; //Total number of random plains maps for encounters
string sRandomArea; //Tag of invisible object in random area where PCs will be dropped ex: Forest Random 1
object oRandomAreaJumpPoint; //Invisible object in random area where PCs will be dropped ex: Forest Random 1
object oMember; //Party members
location locRandomAreaJumpPoint;
object oMod=GetModule();
int bPW=FALSE;
if (GetLocalInt(oMod,"bPW"))
bPW=TRUE;
//Store local overland travel variables back on party
oMember=GetFirstFactionMember(oPC);
//Changed following loop to use oMember instead of oPC to fix multi-party bug
while (oMember!=OBJECT_INVALID) //Loop through for string and float vars
{
SetLocalInt(oMember,"iHoursToGo",iHoursToGo-iTravelledHours);
SetLocalInt(oMember,"iTravelledHours",iTravelledHours);
SetLocalString(oMember,"sDestination",sDestination);
SetLocalString(oMember,"sTerrain",sTerrain);
SetLocalFloat(oMember,"fFacing",fFacing);
SetLocalInt(oMember,"bEncounterDone",TRUE);//FALSE to prevent escape by running away for ALL encounters - if you do this you will have to set it to TRUE after your encounter is done
oMember=GetNextFactionMember(oPC);
} //end while loop
//debug not needed? oPC=GetPCSpeaker(); //Reset oPC
//Set time - should wrap around correctly
iTime=GetTimeHour()+iTravelledHours;
if(!bPW)
SetTime(iTime,0,0,0);
//Send to random map
if (sTerrain=="Forest")
iMapNumber=Random(iNumberRandomForestMaps)+1;
else if (sTerrain=="Plains")
iMapNumber=Random(iNumberRandomPlainsMaps)+1;
//Add additional terrain types here by copying and pasting the else if above
sRandomArea=sTerrain+"Random"+IntToString(iMapNumber);
oRandomAreaJumpPoint=GetObjectByTag(sRandomArea);
if (GetArea(oPC)==GetArea(oRandomAreaJumpPoint))//this will choose a different map than the one they are already on
{
EncounterResult(oPC,iHoursToGo,iTravelledHours,sDestination,sTerrain,fFacing);
return;
}
//This block is for persistant world support - it prevents two parties from occupying the same random map
if (bPW)
{
int i;
int iMapNum;
if (sTerrain=="Forest")
iMapNum=iNumberRandomForestMaps;
else if (sTerrain=="Plains")
iMapNum=iNumberRandomPlainsMaps;
//Add additional terrain types here by copying the else if above and changing the string
//Loop through to check if there are *any* open maps in the PW
for (i=1;i<=iMapNum;i++)
{
if (GetLocalInt(GetArea(oRandomAreaJumpPoint), "iInUse")==0)
break;//OK, the one chosen is open - go there
else //if it is not, we will take the first open one we find
{
sRandomArea=sTerrain+"Random"+IntToString(iMapNum);
oRandomAreaJumpPoint=GetObjectByTag(sRandomArea);
}
if (i==iMapNum) //We got through all the random maps and didn't find any open, but have the last one to check
{
if (GetLocalInt(GetArea(oRandomAreaJumpPoint), "iInUse")==0)
break;//OK, the last map is open - go there
FloatingTextStringOnCreature("There are no overland encounter maps available in this world,",oPC,TRUE);
FloatingTextStringOnCreature("please wait for a bit and try again.",oPC,TRUE);
FloatingTextStringOnCreature("Please notify your world builder to add more.",oPC,TRUE);
SendMessageToAllDMs("Need more OTRES random encounter maps - we just ran out!!");
return; //exit function
}
}//end for loop
}// end of block for PW support*/
//Choose encounter and activate trigger before PCs arrive
if (sTerrain=="Forest")
ExecuteScript("otres_forestrand",oRandomAreaJumpPoint);
else if (sTerrain=="Plains")
ExecuteScript("otres_plainsrand",oRandomAreaJumpPoint);
//Add new terrains here
//Set Local Int for PW support
if (bPW)
SetLocalInt(GetArea(oRandomAreaJumpPoint), "iInUse", 1);
//Send PCs to random map with message
//debug not needed? oPC=GetPCSpeaker();
oMember=GetFirstFactionMember(oPC,FALSE);
while (oMember!=OBJECT_INVALID)
{
AssignCommand(oMember,JumpToObject(oRandomAreaJumpPoint));
DelayCommand(0.5,AssignCommand(oMember,SetFacing(fFacing)));//can use switches to face the right way for a particular map, but this will lose flexibility to have any number of random maps
DelayCommand(1.,FloatingTextStringOnCreature("You were waylaid "
+IntToString(iTravelledHours)+" hours into your journey!",oMember));
oMember=GetNextFactionMember(oPC,FALSE);
}//end while to jump to random map
return;
}//end EncounterResult function
//------------------------------------------------------------------------------
//This is the start of the OverlandTravel function itself
//------------------------------------------------------------------------------
void OverlandTravel(int iHoursToGo,string sDestination,string sTerrain,float fFacing)
{//Begin Overland Travel Function
//iHoursToGo is how much time to travel to either the Wayhouse or Final Destination max of 12 hours
//sDestination is the final target destination set in the intiating dialog
//sTerrain is the type of terrain travelled through
//fFacing is the direction to face the party
object oMod=GetModule();
int bPW=FALSE;
if (GetLocalInt(oMod,"bPW"))
bPW=TRUE;
float fDieRoll; //Where virtual dice rolls go
string sRandomMapTag; //Tag of the map that group will be sent to
object oPC=GetPCSpeaker(); //The PC starting the OTRES convo//debug maybe source of multi-party weirdness? How does GetPCSpeaker work with multiple PCs speaking?
object oMember; //Members of PC's party
object oDestinationJumpPoint; //Waypoint in destination area where PCs will be dropped ex: Wayhouse 1
int iTravelledHours; //Number of hours they have been travelling
float fHoursToGo=IntToFloat(iHoursToGo)*TravelTimeCoeff(); //Hours left in this segment modified by a travel time coefficient in otres_inc
float fRoundTest=fHoursToGo-IntToFloat(FloatToInt(fHoursToGo));
if (fRoundTest>=0.5) //Correct for FloatToInt not rounding but truncating
iHoursToGo=1+FloatToInt(fHoursToGo);
else iHoursToGo=FloatToInt(fHoursToGo);
int iTime; //Time (hours)
//Forest check 3 times every 12 hours chance 1 in 10 for each; 20 miles/day
//Plains check 2 times every 12 hours, 1 in 12 for each;20 miles/day
for (iTravelledHours=1;iTravelledHours!=iHoursToGo;iTravelledHours++)
{//begin for loop to check each hour
if (sTerrain=="Forest")
{//begin forest encounter checks
switch (iTravelledHours) //Check for encounters at appropriate hours of travel
{
case 2: //First check 2 hours into journey
fDieRoll=d10()*EncounterCoeff(); //Check for encounter
if (fDieRoll>=9.5) //start if for "yes, encounter", 9.5 = 10% chance, 8=20% chance, etc (float is used for EncounterCoeff modifications)
{
EncounterResult(oPC,iHoursToGo,iTravelledHours,sDestination,sTerrain,fFacing);
return; //drop out of script and let PC's fight!
}//end if for "yes,encounter" on hour 2
break;
case 6: //Second check 6 hours into journey
fDieRoll=d10()*EncounterCoeff(); //Check for encounter
if (fDieRoll>=9.5) //start if for "yes, encounter"
{
EncounterResult(oPC,iHoursToGo,iTravelledHours,sDestination,sTerrain,fFacing);
return; //drop out of script and let PC's fight!
}//end if for "yes,encounter" on hour 6
break;
case 10: //Third check 10 hours into journey
fDieRoll=d10()*EncounterCoeff(); //Check for encounter
if (fDieRoll>=9.5) //start if for "yes, encounter"
{
EncounterResult(oPC,iHoursToGo,iTravelledHours,sDestination,sTerrain,fFacing);
return; //drop out of script and let PC's fight!
}//end if for "yes,encounter" on hour 10
break;
default: //If it is not time for an encounter check, loop through again
break;
}//end forest encounter switch, let's go to the next hour
}//end forest encounter if
if (sTerrain=="Plains")
{//begin plains encounter checks
switch (iTravelledHours) //Check for encounters at appropriate hours of travel
{
case 2: //First check 2 hours into journey
fDieRoll=d12()*EncounterCoeff(); //Check for encounter
if (fDieRoll>=11.5) //start if for "yes, encounter"
{
EncounterResult(oPC,iHoursToGo,iTravelledHours,sDestination,sTerrain,fFacing);
return; //drop out of script and let PC's fight!
}//end if for "yes,encounter" on hour 2
break;
case 10: //Second check 10 hours into journey
fDieRoll=d12()*EncounterCoeff(); //Check for encounter
if (fDieRoll>=11.5) //start if for "yes, encounter"
{
EncounterResult(oPC,iHoursToGo,iTravelledHours,sDestination,sTerrain,fFacing);
return; //drop out of script and let PC's fight!
}//end if for "yes,encounter" on hour 10
break;
default: //If it is not time for an encounter check, loop through again
break;
}//end forest encounter switch, let's go to the next hour
}//end plains encounter checks
//Add new terrains here
}//end for looping through travel hours - we are now at either a Wayhouse or destination
//Arrive code - send them to sDestination
oDestinationJumpPoint=GetObjectByTag(sDestination);
//Set time - should wrap around correctly
iTime=GetTimeHour()+iTravelledHours;
if (!bPW)
SetTime(iTime,0,0,0);
//debug - not needed? oPC=GetPCSpeaker();
oMember=GetFirstFactionMember(oPC,FALSE);
while (oMember!=OBJECT_INVALID) //Send 'em all to sDestination
{
AssignCommand(oMember,JumpToObject(oDestinationJumpPoint,TRUE));
DelayCommand(0.5,AssignCommand(oMember,SetFacing(fFacing)));//Make sure jump location makes sense for fFacing
oMember=GetNextFactionMember(oPC,FALSE);
}//end while to jump to destination map
}//end void OverlandTravel
//void main(){} //used for recompiling to check for errors, comment out when saving for the last time or you will get a "Duplicate Function" error