something like this?
author:
Axe Murderer's// Tessla Placeable library script
//::////////////////////////////////////////////////////////////////////////
//
//
// Contains the constants and functions required to create and manage tessla
// placeables. A tessla placeable is one where a beam dances about above it
// continuously throughout its existence, by default a lightening beam (bolt).
//::////////////////////////////////////////////////////////////////////////
#include "nw_i0_spells"
//::////////////////////////////////////////////////////////////////////////
// Constants used by the tessla p_tessla_plac_inclaceable system
//::////////////////////////////////////////////////////////////////////////
const string TESSLA_BOLT_RESREF = "tesslabolttarg"; // Placeable blueprint used for bolt targets. Must be a non-static, unuseable placeable blueprint with no inventory. These will be made indestructable and forced to not occupy any space. Its appearance must be invisible object. Stats, locks, traps, etc settings will all be irrelevant on this blueprint.
const int TESSLA_BOLT_CHANGE = 546358; // UDE number sent to tessla placeables when the bolt needs to jump around to a new target.
//::////////////////////////////////////////////////////////////////////////
// int GetIsLocationValid( location lLoc )
// Determines if a given location is valid
//::////////////////////////////////////////////////////////////////////////
// Parameters: location lLoc - the location to verify
//
// Returns: TRUE if the location is valid, FALSE otherwise.
//::////////////////////////////////////////////////////////////////////////
int GetIsLocationValid( location lLoc );
int GetIsLocationValid( location lLoc )
{ object oArea = GetAreaFromLocation( lLoc );
return (GetIsObjectValid( oArea ) && (GetArea( oArea ) == oArea));
}
//::////////////////////////////////////////////////////////////////////////
// void DestroyTesslaPlaceableBoltTargets( object oTessla = OBJECT_SELF )
// Destroys all of a tessla placeable's bolt targets leaving
// the tessla placeable itself alone.
// This must be called whenever a tessla placeable is
// destroyed or killed. The best place to call it is from the
// placeable's OnDeath event script.
// Calling this function effectively turns off the tessla
// visual effects feature of the placeable, and once disabled
// in this manner, the tessla feature cannot be restored
// again without destroying the tessla placeable and
// recreating it via the CreateTesslaPlaceable function.
//::////////////////////////////////////////////////////////////////////////
// Parameters: object oTessla - the tessla placeable whose bolt targets are to be destroyed.
//
// Notes: failure to call this function when a tessla placeable
// is destroyed will make a mess of your module since all
// the invisible beam target placeables associated with it
// will remain. Not so bad for just one placeable, but if
// you spawn and destroy them over and over the build up
// of these undestroyed target placeables will eventually
// bring the module to its knees. To avoid this, always
// add a call to this function from the OnDeath event
// script of all your tessla placeables.
//
// Returns: none.
//::////////////////////////////////////////////////////////////////////////
void DestroyTesslaPlaceableBoltTargets( object oTessla = OBJECT_SELF );
void DestroyTesslaPlaceableBoltTargets( object oTessla = OBJECT_SELF )
{ if( !GetIsObjectValid( oTessla )) return;
int iBoltCount = GetLocalInt( oTessla, "MaxBolt" );
while( --iBoltCount >= 0 ) DestroyObject( GetLocalObject( oTessla, "Bolt_" +IntToString( iBoltCount +1 )));
DeleteLocalInt( oTessla, "MaxBolt" );
}
//::////////////////////////////////////////////////////////////////////////
// void DestroyTesslaPlaceable( object oTessla )
// Destroys a tessla placeable along with all its bolt targets.
// This can be called from anywhere to destroy a tessla placeable that
// was created using the CreateTesslaPlaceable function.
//::////////////////////////////////////////////////////////////////////////
// Parameters: object oTessla - the tessla placeable to destroy.
//
// Returns: none.
//::////////////////////////////////////////////////////////////////////////
void DestroyTesslaPlaceable( object oTessla );
void DestroyTesslaPlaceable( object oTessla )
{ if( !GetIsObjectValid( oTessla )) return;
DestroyTesslaPlaceableBoltTargets( oTessla );
DestroyObject( oTessla );
}
//::////////////////////////////////////////////////////////////////////////
// object CreateTesslaPlaceable( string sResref, location lSpot, int iBeamVFX = VFX_BEAM_LIGHTNING, int nBolts = 16, float fMaxHeight = 6.0 )
// Creates a tessla placeable from the blueprint resref given by sResref at
// the location specified in lSpot with the number of bolt targets requested
// in nBolts using the maximum bolt height defined in fMaxHeight.
//::////////////////////////////////////////////////////////////////////////
// Parameters: string sResref - the placeable blueprint to create as a tessla placeable.
// location lSpot - the location where the placeable will appear.
// int iBeamVFX - the beam type to use for the tessla effect (VFX_BEAM_*). Default is lightning.
// int nBolts - the number of targets that the tessla bolt will jump around between. Default is 20.
// float fMaxHeight - the maximum height above the placeable that the tessla bolts will extend to (approximate). Default is 6.0.
//
// Notes:
// sResref must refer to a placeable blueprint with its static condition
// set to off (unchecked) a custom OnUserDefined event script that calls
// the ChangeTesslaBolt function when the user-defined event number is
// equal to TESSLA_BOLT_CHANGE.
// nBolts must be between 5 and 50 inclusive.
// fMaxHeight must be between 3.0 and 10.0 inclusive.
// iBeamType can be any VFX_BEAM_* constant, however not many of them look good enough to use.
//
// Returns the placeable it creates or OBJECT_INVALID if the placeable could
// not be created.
//::////////////////////////////////////////////////////////////////////////
object CreateTesslaPlaceable( string sResref, location lSpot, int iBeamVFX = VFX_BEAM_LIGHTNING, int nBolts = 16, float fMaxHeight = 6.0 );
object CreateTesslaPlaceable( string sResref, location lSpot, int iBeamVFX = VFX_BEAM_LIGHTNING, int nBolts = 16, float fMaxHeight = 6.0 )
{ if( (sResref == "") || !GetIsLocationValid( lSpot )) return OBJECT_INVALID;
nBolts = (nBolts < 2) ? 2 : ((nBolts > 32) ? 32 : nBolts);
fMaxHeight = (fMaxHeight < 3.0) ? 3.0 : ((fMaxHeight > 10.0) ? 10.0 : fMaxHeight);
object oTessla = CreateObject( OBJECT_TYPE_PLACEABLE, sResref, lSpot );
if( !GetIsObjectValid( oTessla )) return OBJECT_INVALID;
int iBoltCount = 0;
object oArea = GetArea( oTessla );
vector vTessla = GetPosition( oTessla );
while( --nBolts >= 0)
{ vector vBolt = VectorNormalize( AngleToVector( GetRandomDelay( 0.0, 359.9 )));
vBolt *= GetRandomDelay( 0.0, 3.0 ); // this controls the variance in spread away from the placeable in the xy plane.
vBolt += vTessla;
vBolt.z = vTessla.z +GetRandomDelay( 3.0, fMaxHeight ); // this controls the variance in height above the placeable.
object oBolt = CreateObject( OBJECT_TYPE_PLACEABLE, TESSLA_BOLT_RESREF, Location( oArea, vBolt, 0.0 ));
if( GetIsObjectValid( oBolt ))
{ ++iBoltCount;
SetPlotFlag( oBolt, TRUE );
ApplyEffectToObject( DURATION_TYPE_PERMANENT, EffectCutsceneGhost(), oBolt );
SetLocalObject( oTessla, "Bolt_" +IntToString( iBoltCount ), oBolt );
SetLocalInt( oTessla, "MaxBolt", iBoltCount );
}
}
if( iBoltCount < 1 ) { DestroyObject( oTessla ); return OBJECT_INVALID; }
SetLocalInt( oTessla, "BoltType", iBeamVFX );
SignalEvent( oTessla, EventUserDefined( TESSLA_BOLT_CHANGE ));
return oTessla;
}
// Used internally by the ChangeTesslaBolt function to invoke secondary bolt
// branches at the appropriate times when required. Should never be called
// directly as that would likely cause either undesireable effects or no
// effect at all.
int SecondaryTesslaBranch( int iBoltCount, int iStartBolt, object oStartBolt, float fBoltDur, int iBranchBolt1 = -1 , int iBranchBolt2 = -1 );
int SecondaryTesslaBranch( int iBoltCount, int iStartBolt, object oStartBolt, float fBoltDur, int iBranchBolt1 = -1 , int iBranchBolt2 = -1 )
{ int iNextBolt = Random( iBoltCount ) +1;
object oNextBolt = GetLocalObject( OBJECT_SELF, "Bolt_" +IntToString( iNextBolt ));
if( GetIsObjectValid( oNextBolt ) && (iNextBolt != iStartBolt) &&
((iBranchBolt1 == -1) || (iNextBolt != iBranchBolt1)) &&
((iBranchBolt2 == -1) || (iNextBolt != iBranchBolt2)) )
{ float zStart = (GetPosition( oStartBolt )).z;
float zNext = (GetPosition( oNextBolt )).z;
if( zNext > zStart )
{ float fNextDur = GetRandomDelay( 0.1, fBoltDur -0.25 );
if( fNextDur > 0.0 )
{ float fDurDiff = fBoltDur -fNextDur;
float fDelayNext = GetRandomDelay( 0.0, fDurDiff );
effect eBolt = EffectBeam( GetLocalInt( OBJECT_SELF, "BoltType" ), oStartBolt, BODY_NODE_CHEST );
if( fDelayNext > 0.0 )
DelayCommand( fDelayNext, ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eBolt, oNextBolt, fNextDur ));
else ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eBolt, oNextBolt, fNextDur );
return iNextBolt;
}
}
}
return -1;
}
// Needs to be called from all tessla placeables' OnUserDefined script when
// the user defined event number is equal to TESSLA_BOLT_CHANGE
// Causes the tessla bolt to dance around between bolt targets by setting
// up a new beam when the previous one expires.
void ChangeTesslaBolt();
void ChangeTesslaBolt()
{ // Make a new beam appear above the tessla placeable.
float fBoltDur = GetRandomDelay( 0.5, 1.5 );
int iBoltCount = GetLocalInt( OBJECT_SELF, "MaxBolt" );
int iStartBolt = Random( iBoltCount ) +1;
object oStartBolt = GetLocalObject( OBJECT_SELF, "Bolt_" +IntToString( iStartBolt ));
if( GetIsObjectValid( oStartBolt ))
{ // Random bolt target was successfully selected.
effect eBolt = EffectBeam( GetLocalInt( OBJECT_SELF, "BoltType" ), OBJECT_SELF, BODY_NODE_CHEST );
ApplyEffectToObject( DURATION_TYPE_TEMPORARY, eBolt, oStartBolt, fBoltDur );
// Secondary branch possibilities
int iBranchBolt1 = -1;
int iBranchBolt2 = -1;
iBranchBolt1 = SecondaryTesslaBranch( iBoltCount, iStartBolt, oStartBolt, fBoltDur );
if( d2() == 1 ) iBranchBolt2 = SecondaryTesslaBranch( iBoltCount, iStartBolt, oStartBolt, fBoltDur, iBranchBolt1 );
if( d2() == 1 ) SecondaryTesslaBranch( iBoltCount, iStartBolt, oStartBolt, fBoltDur, iBranchBolt1, iBranchBolt2 );
}
// Signal another bolt change when this beam expires.
DelayCommand( fBoltDur +0.1, SignalEvent( OBJECT_SELF, EventUserDefined( TESSLA_BOLT_CHANGE )));
}
//void main() {}
//
// Example OnUserDefined script for a tessla placeable
//
// #include "_tessla_plac_inc"
//
// void main()
// { switch( GetUserDefinedEventNumber() )
// { case TESSLA_BOLT_CHANGE: ChangeTesslaBolt(); break;
//
// ... case blocks for other user defined events go here if applicable
//
// }
// }
//
//
// Example OnDeath script for a tessla placeable
//
// #include "_tessla_plac_inc"
//
// void main()
// { DestroyTesslaPlaceableBoltTargets();
//
// ... rest of OnDeath code goes here if required
//
// }
//
Modifié par Cursed Eclipse, 31 mai 2013 - 12:12 .