Yea, I remember that one. The Main Problem I had when messing with it was that the Object it is applied to has to be seen by the PC. if it is not seen by the PC then they notice no quake effect. I Can remember firing it off as a DM appling the effect to myself and having all the players wonder why they where falling over, OOPS.
Here is the include for the last version I had. At least I hope it was may last version. One warning I never got around to placing a check to not knock over the DM. My DM fell many times due to the quakes.
// File Name: are_eff_quake
// Time Delays are is rounds.
// Min Should be at least the amount of time of the quakes.
// There are 10 rounds per minute
int MIN_RND_BETWEEN_QUAKES = 5; // 0.5 min
int MAX_RND_BETWEEN_QUAKES = 100; // 10 min
int MAX_LENGHT_OF_QUAKE = 4; // 9 sec
int INCREAS_DC_PER_LENGTH = 5; // For evey extra round the quake lasts add 5 to the DC.
// @ nDuration - the number of rounds the effect lasts for.
// creatures make a save every round.
// @ nDC - The DC for the reflex save to not fall down.
// @ oCenter - The Object the effect is centered at.
// - if oCenter is an area the function will pick an object to center on.
void QuakeEarth( int nDuration = 1, int nDC = 20 , object oCenter=OBJECT_SELF );
// If any of the arguments are set thy will override the Defaults set in the Include file.
void RandomQuakes(int nMinRnd = -1,int nMaxRnd = -1,int nMaxLength = -1 ,int IncDc = -1);
//Returns true if a PC is in the area.
int GetIsPCInArea(object oArea=OBJECT_SELF);
// Sets up a Delayed Quake Per the Constants above.
void SetUpQuake(int bForce= FALSE);
// Private function to the QuakeEarth function
void Fall( );
// @ nDuration - the number of rounds the effect lasts for.
// creatures make a save every round.
// @ nDC - The DC for the reflex save to not fall down.
// @ oCenter - The Object the effect is centered at.
// - if oCenter is an area the function will pick an object to center on.
void QuakeEarth( int nDuration = 1, int nDC = 20 , object oCenter=OBJECT_SELF );
// Privat function to make sure the Effect is seen buy all PC's in the area.
void ApplyShakeToArea(object oArea)
{
object oPC = GetFirstPC();
effect eShake = EffectVisualEffect(356);
int nCount= 0;
int i;
int bNotSeen;
while(GetIsObjectValid(oPC))
{
if (GetArea(oPC) == oArea)
{
bNotSeen=TRUE;
for(i=0;i<nCount;i++)
{
if (LineOfSightObject(GetLocalObject(OBJECT_SELF,"ShLoc"+IntToString(i)),oPC))
{
bNotSeen = FALSE;
break;
}
}
if (bNotSeen)
{
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eShake, GetLocation(oPC),4.5);
//fill in effect Dead spot if running more then one round.
DelayCommand(4.5,ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eShake, GetLocation(oPC),1.5));
SetLocalObject(OBJECT_SELF,"ShLoc"+IntToString(i),oPC);
nCount++;
}
}
oPC=GetNextPC();
}
// clean up unneeded locals
for (i=0;i<nCount;i++) DeleteLocalObject( OBJECT_SELF,"ShLoc"+IntToString(i));
}
void QuakeEarth( int nDuration = 1, int nDC = 20 , object oCenter=OBJECT_SELF )
{
int nCount;
int nSave;
float fDelay;
object oCreature;
// Adjust for if oCenter is running on the area and not an object.
if (GetArea( oCenter) == oCenter) oCenter=GetNearestCreature(CREATURE_TYPE_IS_ALIVE,TRUE,GetFirstObjectInArea(oCenter) ,1) ;
if (oCenter==OBJECT_INVALID) return;
ApplyShakeToArea(GetArea(oCenter));
// Set up for first time through kd loop.
if(GetObjectType(oCenter)== OBJECT_TYPE_CREATURE)
{
oCreature = oCenter;
nCount= 0;
}
else
{
oCreature = GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oCenter ,1);
nCount = 1;
}
//Loop through creatures to see who falls down.
do
{
if (!ReflexSave(oCreature, nDC ))
{
fDelay= GetDistanceBetween (oCreature,oCenter);
fDelay= (fDelay /5 - FloatToInt(fDelay/5))*4;
DelayCommand ( fDelay ,AssignCommand (oCreature,Fall()));
}
nCount++;
oCreature=GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, oCenter ,nCount );
}
while (GetIsObjectValid(oCreature));
nDuration--;
if( nDuration ) DelayCommand(6.0,QuakeEarth(nDuration, nDC-INCREAS_DC_PER_LENGTH, oCenter));
}
void Fall( )
{
int nAnination;
float fDelay=IntToFloat(Random(4)+2);
int nRoll = d4();
switch (nRoll)
{
case 1: nAnination = ANIMATION_LOOPING_DEAD_BACK; break;
case 2: nAnination = ANIMATION_LOOPING_DEAD_FRONT; break;
case 3: nAnination = ANIMATION_LOOPING_SIT_CROSS; break;
case 4: nAnination = ANIMATION_LOOPING_PAUSE_DRUNK; fDelay=fDelay/2; break;
}
ClearAllActions();
PlayAnimation(nAnination, 1.0 ,fDelay);
SetCommandable(FALSE);
DelayCommand( fDelay, SetCommandable(TRUE));
}
void SetUpQuake(int bForce= FALSE)
{
// set a random delay for PC just entering or still in the area.
if (( bForce || GetIsPCInArea()) && GetArea(OBJECT_SELF)== GetLocalObject(OBJECT_SELF,"QuakeArea") )
{
float fDelay = RoundsToSeconds( Random ( MAX_RND_BETWEEN_QUAKES - MIN_RND_BETWEEN_QUAKES )+ MIN_RND_BETWEEN_QUAKES);
int nLength = Random(MAX_LENGHT_OF_QUAKE)+1;
int nDC = INCREAS_DC_PER_LENGTH * (nLength-1) + 20;
DelayCommand (fDelay, QuakeEarth( nLength,nDC));
DelayCommand (fDelay+ 0.5 , SetUpQuake());
}
// no PC here so end the quakes
else
{
SetLocalInt(OBJECT_SELF,"TimmerRunning",FALSE);
//SendMessageToPC(GetFirstPC(),"quakes shutting down");
}
}
int GetIsPCInArea(object oArea=OBJECT_SELF)
{
object oPC = GetFirstPC();
oArea = GetArea(oArea);
while (GetIsObjectValid(oPC))
{
if (GetArea(oPC) == oArea) return TRUE;
oPC = GetNextPC();
}
return FALSE;
}
// If any of the arguments are set thy will override the Defaults set in the Include file.
void RandomQuakes(int nMinRnd = -1,int nMaxRnd = -1,int nMaxLength = -1 ,int IncDc = -1)
{
object oPC = GetEnteringObject();
int bTimmer = GetLocalInt(OBJECT_SELF,"TimmerRunning");
// exit if the timmer is already running or it is not a PC unless it is not being ran from the area.
if ( bTimmer || (!GetIsPC(oPC) && (GetArea(OBJECT_SELF)==OBJECT_SELF)) ) return;
// Set a Flag that the timmer is running.
SetLocalInt(OBJECT_SELF,"TimmerRunning",TRUE);
if(nMinRnd != -1) MIN_RND_BETWEEN_QUAKES = nMinRnd;
if(nMaxRnd != -1) MAX_RND_BETWEEN_QUAKES = nMaxRnd;
if(nMaxLength != -1) MAX_LENGHT_OF_QUAKE = nMaxLength;
if(IncDc != -1) INCREAS_DC_PER_LENGTH = IncDc;
SetLocalObject(OBJECT_SELF,"QuakeArea",GetArea(OBJECT_SELF));
SetUpQuake( TRUE );
}
To just do a Single Quake IT is a simple as.
[quote]
#include "are_eff_quake"
void main()
{
QuakeEarth();
}
[/quote]
If you wanted an Area to have random quakes all the time. you could just add this to the OnEnter Script.
[quote]
#include "are_eff_quake"
void main ()
{
RandomQuakes(5,10,5,10);
}
[/quote]
The Random Quakes are set up on a Self Terminating pseudo HB that stops when all the PC's leave the area.
It also makes sure that all PC in the area have a visual line of site to the Effect. Fall Patterns follow a ripple from the quake center to similate the roll of the earth, (Everyone will not fall down at the same time if the fail there save).