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>
256 lines
13 KiB
Plaintext
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
|
|
|