IW4-Dump-Files/maps/_leapfrog.gsc

268 lines
6.5 KiB
Plaintext

/**** LEAPFROG SYSTEM ****
Thread maps\_leapfrog::leapfrog() on any AI that uses a chain of nodes.
Make sure to check the NOT_CHAIN check box on each node in the chain to allow chains to merge or loop.
You need at least two chains for this to look good.
level.leap_delay_min and max determines how fast they try to advance.
set script_delay on a node to have the ai use a delay instead of waiting for a leap notify.
script_delay = 0 will make them run past that node before going to the next one.
*************************/
#include maps\_utility;
main()
{
// Set delays to tweak how fast the advance should be.
level.leap_delay_min = 6;
level.leap_delay_max = 14;
level.leap_delay_override = false;
// there will never be more ai on one leap node then what this is set to.
level.leapfrog_max_node_ai = 6;
level.leap_node_array = [];
level.leapfrog_random_int = randomint( 5 );
// lower threat threatbias group for when leaping.
createthreatbiasgroup( "leapfrog" );
setthreatbiasagainstall( "leapfrog", -200 );
level thread leapfrog_masterthread();
}
leapfrog_masterthread()
{
while ( true )
{
if ( !level.leap_delay_override )
wait( randomFloatRange( level.leap_delay_min, level.leap_delay_max ) );
else
wait .05;
level.leap_delay_override = false;
// used to make ai take the same fork in a path when script_delay is set.
level.leapfrog_random_int = randomint( 5 );
node_arr = [];
high_weight = -1000000;
if ( !level.leap_node_array.size )
continue;
for ( i = 0; i < level.leap_node_array.size; i++ )
{
weight = level.leap_node_array[ i ].leap_weight;
if ( !isdefined( node_arr[ weight ] ) )
node_arr[ weight ] = [];
node_arr[ weight ][ node_arr[ weight ].size ] = level.leap_node_array[ i ];
if ( weight > high_weight )
high_weight = weight;
}
assertEx( isdefined( node_arr[ high_weight ] ), "high_weight is: " + high_weight );
assertEx( isdefined( high_weight >= 0 ), "high_weight is below zero: " + high_weight );
node = node_arr[ high_weight ][ randomint( node_arr[ high_weight ].size ) ];
assert( isdefined( node.target ) );// there should always be a new node or it shouldn't be in the array.
node_arr = getnodearray( node.target, "targetname" );
next_node = node_arr[ randomint( node_arr.size ) ];
// reset future ai count
if ( isdefined( next_node.leapfrog_ai_count ) )
next_node.leapfrog_future_ai_count = next_node.leapfrog_ai_count;
else
next_node.leapfrog_future_ai_count = 0;
// increase the weight of all none chosen nodes.
array_thread( level.leap_node_array, ::increment_leap_weight, node );
new_weight = int( node.leap_weight * - .25 );
if ( isdefined( next_node.leap_weight ) )
new_weight += next_node.leap_weight;
add_leap_node( next_node, new_weight );
node notify( "leapfrog", next_node );
remove_leap_node( node );
}
}
increment_leap_weight( node )
{
if ( self == node )
return;
diff_weight = node.leap_weight - self.leap_weight;
self.leap_weight += ( int( diff_weight * 0.5 ) + 1 );// old .75;
}
leapfrog()
{
self endon( "death" );
self endon( "stop_leapfrog" );
self notify( "stop_going_to_node" );
// get first node
node_arr = getnodearray( self.target, "targetname" );
node = node_arr[ randomint( node_arr.size ) ];
while ( true )
{
if ( node.radius != 0 )
self.goalradius = node.radius;
if ( isdefined( node.height ) )
self.goalheight = node.height;
self setgoalnode( node );
old_maxsightdistsqrd = self.maxsightdistsqrd;
self.maxsightdistsqrd = 350 * 350;
old_group = self getthreatbiasgroup();
self setthreatbiasgroup( "leapfrog" );
self waittill( "goal" );
// Notify the node and pass the guy. Might be good for something
node notify( "trigger", self );
self.maxsightdistsqrd = old_maxsightdistsqrd;
self setthreatbiasgroup( old_group );
self thread leapfrog_on_death( node );
if ( !isdefined( node.target ) )
break;
if ( isdefined( node.script_delay ) )
{
node script_delay();
node_arr = getnodearray( node.target, "targetname" );
next_node = node_arr[ level.leapfrog_random_int % node_arr.size ];
}
else
{
if ( !add_leap_node( node ) )
break;
node waittill( "leapfrog", next_node );
next_node.leapfrog_future_ai_count++ ;
max_node_ai = level.leapfrog_max_node_ai;
if ( isdefined( node.script_noteworthy ) )
max_node_ai = int( node.script_noteworthy );
if ( next_node.leapfrog_future_ai_count > max_node_ai )
{
level.leap_delay_override = true;
if ( isdefined( next_node.leap_weight ) )
{
next_node.leap_weight += 1; // make the full node more likely to leap.
}
next_node = node; // stay on old node.
}
}
node = next_node;
}
// notify level and pass the guy that reached his final leapfrog node.
level notify( "leapfrog_completed", self );
}
leapfrog_on_death( node )
{
node endon( "leapfrog" );
if ( !isdefined( node.leapfrog_ai_count ) )
node.leapfrog_ai_count = 0;
node.leapfrog_ai_count++ ;
self waittill( "death" );
node.leapfrog_ai_count -- ;
if ( isdefined( node.leap_weight ) )
{
new_weight = node.leap_weight - 1;
if ( new_weight < 1 )
new_weight = 1;
node.leap_weight = new_weight;
}
if ( !node.leapfrog_ai_count )
remove_leap_node( node );
}
add_leap_node( node, weight )
{
if ( !isdefined( node.target ) || isdefined( node.script_delay ) )
return false;
if ( getdvar( "debug" ) == "1" )
node thread debug_leap_node();
if ( !is_in_array( level.leap_node_array, node ) )
{
level.leap_node_array = array_add( level.leap_node_array, node );
node.leap_weight = 0;
}
if ( isdefined( weight ) )
node.leap_weight = weight;
else
node.leap_weight += 2;
return true;
}
remove_leap_node( node )
{
node.leap_weight = undefined;
node.leapfrog_ai_count = undefined;
level.leap_node_array = array_remove( level.leap_node_array, node );
}
/* debug stuff */
debug_leap_node()
{
if ( isdefined( self.debug_leapnode ) )
return;
self.debug_leapnode = true;
while ( true )
{
if ( isdefined( self.leap_weight ) )
self thread print3Dmessage( self.leap_weight, .5 );
if ( isdefined( self.leapfrog_ai_count ) )
self thread print3Dmessage( self.leapfrog_ai_count, 0.5, ( 1, 0, 0 ), ( 0, 0, 128 ), 3 );
wait .5;
}
}
print3Dmessage( message, show_time, color, offset, scale )
{
if ( !isdefined( color ) )
color = ( 0.5, 1, 0.5 );
if ( !isdefined( offset ) )
offset = ( 0, 0, 56 );
if ( !isdefined( scale ) )
scale = 6;
show_time = gettime() + ( show_time * 1000 );
while ( gettime() < show_time )
{
print3d( self.origin + offset, message, color, 1, scale );
wait( 0.05 );
}
}