2323 lines
No EOL
40 KiB
Text
2323 lines
No EOL
40 KiB
Text
// guzzo's peleliu 2 util file for various purposes
|
|
|
|
#include maps\_utility;
|
|
#include common_scripts\utility;
|
|
#include maps\_anim;
|
|
|
|
|
|
/////////////
|
|
//
|
|
// sets up players for starts
|
|
//
|
|
///////////////////
|
|
|
|
start_teleport_players( start_name, coop )
|
|
{
|
|
|
|
// grab all players
|
|
players = get_players();
|
|
|
|
// Grab the starting points
|
|
if( isdefined( coop ) && coop )
|
|
{
|
|
starts = get_sorted_starts( start_name );
|
|
}
|
|
else
|
|
{
|
|
starts = getstructarray( start_name, "targetname" );
|
|
}
|
|
|
|
// make sure there are enough points to start from
|
|
assertex( starts.size >= players.size, "Need more start positions for players!" );
|
|
|
|
// set up each player
|
|
for (i = 0; i < players.size; i++)
|
|
{
|
|
// Set the players' origin to each start point
|
|
players[i] setOrigin( starts[i].origin );
|
|
|
|
|
|
if( isdefined( starts[i].angles ) )
|
|
{
|
|
// Set the players' angles to face the right way.
|
|
players[i] setPlayerAngles( starts[i].angles );
|
|
}
|
|
else
|
|
{
|
|
// in case the script struct doesn't have angles set
|
|
players[i] setPlayerAngles( ( 0, 0, 0 ) );
|
|
}
|
|
|
|
}
|
|
|
|
// CODER_MOD : DSL
|
|
// Initialise the breadcrumb positions to the positions provided.
|
|
set_breadcrumbs(starts);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the points to warp the starting AI and players to
|
|
get_sorted_starts( start_name )
|
|
{
|
|
|
|
player_starts = [];
|
|
|
|
player_starts = getstructarray( start_name, "targetname" );
|
|
|
|
for( i = 0; i < player_starts.size; i++ )
|
|
{
|
|
for( j = i; j < player_starts.size; j++ )
|
|
{
|
|
if( player_starts[j].script_int < player_starts[i].script_int )
|
|
{
|
|
temp = player_starts[i];
|
|
player_starts[i] = player_starts[j];
|
|
player_starts[j] = temp;
|
|
}
|
|
}
|
|
}
|
|
|
|
return player_starts;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// sets up ai for starts
|
|
//
|
|
///////////////////////////////
|
|
|
|
start_teleport_ai( start_name )
|
|
{
|
|
|
|
// grab all friendly ai
|
|
friendly_ai = getentarray( "friendly_squad_ai", "script_noteworthy" );
|
|
|
|
// Grab the starting point, should be a script_struct
|
|
ai_starts = getstructarray( start_name + "_ai", "targetname");
|
|
|
|
|
|
assertex( ai_starts.size >= friendly_ai.size, "Need more start positions for ai!" );
|
|
|
|
for (i = 0; i < friendly_ai.size; i++)
|
|
{
|
|
// Set the ai's origin to each start point
|
|
friendly_ai[i] teleport( ai_starts[i].origin );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Because force teleporting of ai isn't allowed, warp player where none are visible
|
|
//
|
|
///////////////////////////////
|
|
|
|
start_trick_teleport_player()
|
|
{
|
|
|
|
// grab all players
|
|
players = get_players();
|
|
|
|
orig = getstruct( "orig_fake_test", "targetname" );
|
|
|
|
// set up each player, make sure there are four points to start from
|
|
for (i = 0; i < players.size; i++)
|
|
{
|
|
players[i] setOrigin( orig.origin );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Wrapper for start teleporting
|
|
//
|
|
///////////////////////////////
|
|
|
|
start_teleport( start_name )
|
|
{
|
|
|
|
start_trick_teleport_player();
|
|
start_teleport_ai( start_name );
|
|
start_teleport_players( start_name );
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Wrapper for setting the current color chain
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_color_chain( name )
|
|
{
|
|
|
|
color_trigger = getent( name, "targetname" );
|
|
assertex( isdefined( color_trigger ), "color_trigger: " + name + " isn't defined!" );
|
|
|
|
color_trigger notify( "trigger" );
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// doesn't assert if the trigger doesn't exist
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_color_chain_safe( name )
|
|
{
|
|
|
|
color_trigger = getent( name, "targetname" );
|
|
color_trigger notify( "trigger" );
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// A simple way to use the util func trigger_wait with a timeout condition attached
|
|
//
|
|
///////////////////////////////
|
|
|
|
trigger_wait_or_timeout( trig_name, time, key )
|
|
{
|
|
|
|
assertex( isdefined( time ), "time needs to be defined!" );
|
|
|
|
if( !isdefined( key ) )
|
|
{
|
|
key = "targetname";
|
|
}
|
|
|
|
// dont want trigger_once types involved here...
|
|
trig = getent( trig_name, key );
|
|
assertex( ( trig.classname == "trigger_multiple" || trig.classname == "trigger_lookat" ), "trigger must be a trigger_multiple or trigger_lookat to use this function!" );
|
|
|
|
// trigger it if timeout happens
|
|
level thread trigger_wait_or_timeout_helper( trig_name, time, key );
|
|
|
|
trigger_wait( trig_name, key );
|
|
|
|
}
|
|
|
|
|
|
|
|
trigger_wait_or_timeout_helper( trig_name, time, key)
|
|
{
|
|
|
|
trig = getent( trig_name, key );
|
|
|
|
// in case it's triggered normally, don't need this thread running anymore
|
|
trig endon( "trigger" );
|
|
|
|
wait( time );
|
|
trig notify( "trigger" );
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Manually triggers a lookat trig if its targetted trigger is hit first. a call to this function should be followed by a trigger_wait() for the same trigger
|
|
//
|
|
///////////////////////////////
|
|
|
|
trig_override( original_trig_name )
|
|
{
|
|
|
|
// ends override behavior if original trig is hit
|
|
original_trig = getent( original_trig_name, "targetname" );
|
|
assertex( ( original_trig.classname == "trigger_multiple" || original_trig.classname == "trigger_lookat" ), "trigger must be a trigger_multiple or trigger_lookat to use this function!" );
|
|
original_trig endon( "trigger" );
|
|
|
|
// waittill override trig is hit
|
|
override_trig = getent( original_trig.target, "targetname" );
|
|
override_trig waittill( "trigger" );
|
|
|
|
quick_text( original_trig.targetname + " overridden!", 3, true );
|
|
|
|
// notify original trig and delete override trig
|
|
original_trig notify( "trigger" );
|
|
override_trig delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Set the force color of heroes
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_color_heroes( color )
|
|
{
|
|
|
|
for( i = 0; i < level.heroes.size; i++ )
|
|
{
|
|
level.heroes[i] set_force_color( color );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Set the force color of all allies
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_color_allies( color )
|
|
{
|
|
|
|
guys = getAIArray( "allies" );
|
|
for(i = 0; i < guys.size; i++)
|
|
{
|
|
guys[i] set_force_color( color );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
disable_arrivals( arrivals, exits )
|
|
{
|
|
self.disableArrivals = arrivals;
|
|
self.disableexits = exits;
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Can the ent see any player?
|
|
//
|
|
///////////////////////////////
|
|
|
|
cant_see_any_player()
|
|
{
|
|
|
|
players = get_players();
|
|
|
|
for( i = 0; i < players.size; i++ )
|
|
{
|
|
|
|
if( ( self cansee( players[i] ) ) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// returns true if no players are within range of spot
|
|
//
|
|
///////////////////////////////
|
|
|
|
players_nearby( spot, range )
|
|
{
|
|
|
|
players = get_players();
|
|
|
|
for( i = 0; i < players.size; i++ )
|
|
{
|
|
|
|
if( distance( players[i].origin, spot ) <= range )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// deletes all ents with a specified targetname
|
|
//
|
|
///////////////////////////////
|
|
|
|
delete_targetname_ents( name )
|
|
{
|
|
|
|
ents = getentarray( name, "targetname" );
|
|
|
|
for( i = 0; i < ents.size; i++ )
|
|
{
|
|
ents[i] delete();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// deletes all ents with a specified script_noteworthy
|
|
//
|
|
///////////////////////////////
|
|
|
|
delete_noteworthy_ents( name )
|
|
{
|
|
|
|
ents = getentarray( name, "script_noteworthy" );
|
|
|
|
for( i = 0; i < ents.size; i++ )
|
|
{
|
|
if( isdefined( ents[i] ) )
|
|
{
|
|
ents[i] delete();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// AI
|
|
//
|
|
///////////////////////////////////////
|
|
//////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
//////////////
|
|
//
|
|
// wrapper for using _spawner's flood_spawner_scripted(). equivalent to using a trigger w/ floodspawn set
|
|
//
|
|
////////////////////////
|
|
simple_floodspawn( name, spawn_func )
|
|
{
|
|
|
|
spawners = getEntArray( name, "targetname" );
|
|
|
|
assertex( spawners.size, "no spawners with targetname " + name + " found!" );
|
|
|
|
// add spawn function to each spawner if specified
|
|
if( isdefined( spawn_func ) )
|
|
{
|
|
for( i = 0; i < spawners.size; i++ )
|
|
{
|
|
spawners[i] add_spawn_function( spawn_func );
|
|
}
|
|
}
|
|
|
|
for( i=0; i< spawners.size; i++ )
|
|
{
|
|
|
|
if( i % 2 )
|
|
{
|
|
//wait for a new network frame to be sent out before spawning in another guy
|
|
wait_network_frame();
|
|
}
|
|
|
|
spawners[i] thread maps\_spawner::flood_spawner_init();
|
|
spawners[i] thread maps\_spawner::flood_spawner_think();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////
|
|
//
|
|
// simple way to spawn guys just once (no floodspawning!)
|
|
//
|
|
////////////////////////
|
|
simple_spawn( name, spawn_func )
|
|
{
|
|
|
|
spawners = getEntArray( name, "targetname" );
|
|
|
|
assertex( spawners.size, "no spawners with targetname " + name + " found!" );
|
|
|
|
// add spawn function to each spawner if specified
|
|
if( isdefined( spawn_func ) )
|
|
{
|
|
for( i = 0; i < spawners.size; i++ )
|
|
{
|
|
spawners[i] add_spawn_function( spawn_func );
|
|
}
|
|
}
|
|
|
|
ai_array = [];
|
|
|
|
for( i = 0; i < spawners.size; i++ )
|
|
{
|
|
|
|
if( i % 2 )
|
|
{
|
|
//wait for a new network frame to be sent out before spawning in another guy
|
|
wait_network_frame();
|
|
}
|
|
|
|
// check if we want to forcespawn him
|
|
if( IsDefined( spawners[i].script_forcespawn ) )
|
|
{
|
|
ai = spawners[i] StalingradSpawn();
|
|
}
|
|
else
|
|
{
|
|
ai = spawners[i] DoSpawn();
|
|
}
|
|
|
|
spawn_failed( ai );
|
|
|
|
// for debug purposes (so entinfo displays their name)
|
|
if( isdefined( ai ) )
|
|
{
|
|
ai.targetname = name + "_alive";
|
|
}
|
|
|
|
ai_array = add_to_array( ai_array, ai );
|
|
}
|
|
|
|
return ai_array;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////
|
|
//
|
|
// simple way to spawn just one guy one time only (no floodspawning!)
|
|
//
|
|
////////////////////////
|
|
simple_spawn_single( name, spawn_func )
|
|
{
|
|
|
|
spawner = getEnt( name, "targetname" );
|
|
|
|
assertex( isdefined( spawner ), "no spawner with targetname " + name + " found!" );
|
|
|
|
// add spawn function to each spawner if specified
|
|
if( isdefined( spawn_func ) )
|
|
{
|
|
spawner add_spawn_function( spawn_func );
|
|
}
|
|
|
|
// check if we want to forcespawn him
|
|
if( IsDefined( spawner.script_forcespawn ) )
|
|
{
|
|
ai = spawner StalingradSpawn();
|
|
}
|
|
else
|
|
{
|
|
ai = spawner DoSpawn();
|
|
}
|
|
|
|
spawn_failed( ai );
|
|
|
|
// for debug purposes (so entinfo displays their name)
|
|
// also check that he doesn't have a targetname set already (such as from a custom spawn func...)
|
|
if( isdefined( ai ) && !isdefined( ai.targetname ) )
|
|
{
|
|
ai.targetname = name + "_alive";
|
|
}
|
|
|
|
return ai;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// use with array_thread on ai to set their ignoreme value to 1
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_ignoreme_on()
|
|
{
|
|
if( isalive( self ) )
|
|
{
|
|
self.ignoreme = 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// use with array_thread on ai to set their ignoreme value to 0
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_ignoreme_off()
|
|
{
|
|
if( isalive( self ) )
|
|
{
|
|
self.ignoreme = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// use with array_thread on ai to set their ignoresuppression value to 1
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_ignoresuppression_on()
|
|
{
|
|
if( isalive( self ) )
|
|
{
|
|
self.ignoresuppression = 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// use with array_thread on ai to set their ignoresuppression value to 0
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_ignoresuppression_off()
|
|
{
|
|
if( isalive( self ) )
|
|
{
|
|
self.ignoresuppression = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// use with array_thread on ai to set their pacifist value to 1
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_pacifist_on()
|
|
{
|
|
|
|
if( isalive( self ) )
|
|
{
|
|
self.pacifist = 1;
|
|
self.pacifistwait = 0.05;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// use with array_thread on ai to set their pacifist value to 0
|
|
//
|
|
///////////////////////////////
|
|
|
|
set_pacifist_off()
|
|
{
|
|
|
|
if( isalive( self ) )
|
|
{
|
|
self.pacifist = 0;
|
|
self.pacifistwait = 20;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set_players_ignoreme( ignore_val )
|
|
{
|
|
|
|
players = get_players();
|
|
|
|
for( i = 0; i < players.size; i++ )
|
|
{
|
|
|
|
players[i].ignoreme = ignore_val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// changes the goal radius of a group of guys based on aigroup
|
|
//
|
|
///////////////////////////////
|
|
|
|
change_ai_group_goalradii( name, new_radius )
|
|
{
|
|
|
|
assertex( isdefined( name ), "ai_group name needs to be defined!" );
|
|
|
|
guys = get_ai_group_ai( name );
|
|
|
|
if( !guys.size )
|
|
{
|
|
return;
|
|
}
|
|
|
|
for( i = 0; i < guys.size; i++ )
|
|
{
|
|
guys[i].goalradius = new_radius;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// changes the goal radius of a group of guys based on script_noteworthy
|
|
//
|
|
///////////////////////////////
|
|
|
|
change_noteworthy_goalradii( name, new_radius )
|
|
{
|
|
|
|
guys = get_specific_ai( name );
|
|
|
|
for( i = 0; i < guys.size; i++ )
|
|
{
|
|
|
|
guys[i].goalradius = new_radius;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Kills all non-hero ai. may take up to 3 seconds if there are 32 ai alive
|
|
//
|
|
///////////////////////////////
|
|
|
|
kill_all_ai( allies_only )
|
|
{
|
|
|
|
if( isdefined( allies_only ) && allies_only == "allies" )
|
|
{
|
|
ai = getaiarray( "allies" );
|
|
}
|
|
else
|
|
{
|
|
ai = getaiarray();
|
|
}
|
|
|
|
for( i = 0; i < ai.size; i++ )
|
|
{
|
|
|
|
// ignore if it's a hero
|
|
if( isdefined( ai[i].targetname ) && ai[i].targetname == "friendly_squad" )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// ignore if it's an enemy we don't want killed
|
|
if( isdefined( ai[i].script_noteworthy ) && ai[i].script_noteworthy == "dont_kill_me" )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// they shouldn't have magic bullet shield on at this point, so turn it off
|
|
if( IsDefined( ai[i].magic_bullet_shield ) && ai[i].magic_bullet_shield )
|
|
{
|
|
println( "stopping magic bullet shield on guy at: " + ai[i].origin + " with export: " + ai[i].export );
|
|
ai[i] stop_magic_bullet_shield();
|
|
wait( 0.05 );
|
|
}
|
|
|
|
ai[i] dodamage( ai[i].health + 10, ( 0, 0, 0 ) );
|
|
wait( 0.1 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Kills all axis ai. may take up to 3 seconds if there are 32 ai alive
|
|
//
|
|
///////////////////////////////
|
|
|
|
kill_all_axis_ai( delay )
|
|
{
|
|
|
|
if( !isdefined( delay ) )
|
|
{
|
|
delay = 0.15;
|
|
}
|
|
|
|
ai = getaiarray( "axis" );
|
|
|
|
for( i = 0; i < ai.size; i++ )
|
|
{
|
|
|
|
if( isalive( ai[i] ) )
|
|
{
|
|
ai[i] dodamage( ai[i].health + 10, ( 0, 0, 0 ) );
|
|
wait( delay );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Kills all axis ai using bloody death. may take up to 3 seconds if there are 32 ai alive
|
|
//
|
|
///////////////////////////////
|
|
|
|
kill_all_axis_ai_bloody( delay )
|
|
{
|
|
|
|
if( !isdefined( delay ) )
|
|
{
|
|
delay = 0.15;
|
|
}
|
|
|
|
ai = getaiarray( "axis" );
|
|
|
|
for( i = 0; i < ai.size; i++ )
|
|
{
|
|
|
|
if( isalive( ai[i] ) )
|
|
{
|
|
self thread bloody_death( true );
|
|
wait( delay );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Kills specific ai with specified script_aigroup
|
|
//
|
|
///////////////////////////////
|
|
|
|
kill_aigroup( name )
|
|
{
|
|
|
|
ai = get_ai_group_ai( name );
|
|
|
|
for( i = 0; i < ai.size; i++ )
|
|
{
|
|
|
|
// stop magic bullet shield if it's on
|
|
if ( isdefined( ai[i].magic_bullet_shield ) && ai[i].magic_bullet_shield )
|
|
{
|
|
ai[i] stop_magic_bullet_shield();
|
|
}
|
|
wait( 0.05 );
|
|
|
|
if( isalive( ai[i] ) )
|
|
{
|
|
ai[i] dodamage( ai[i].health + 1, ( 0, 0, 0 ) );
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Kills specific ai with specified script_noteworthy
|
|
//
|
|
///////////////////////////////
|
|
|
|
kill_noteworthy_group( name )
|
|
{
|
|
|
|
ai = get_specific_ai( name );
|
|
|
|
for( i = 0; i < ai.size; i++ )
|
|
{
|
|
ai[i] dodamage( ai[i].health + 10, ( 0, 0, 0 ) );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// delete all active drones
|
|
//
|
|
///////////////////////////////
|
|
|
|
delete_drones()
|
|
{
|
|
|
|
drones = getentarray( "drone", "targetname" );
|
|
|
|
for( i = 0; i < drones.size; i++ )
|
|
{
|
|
drones[i] maps\_drones::drone_delete();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// return a single guy alive that has the given script_noteworthy (there should only be one)
|
|
//
|
|
///////////////////////////////
|
|
|
|
get_specific_single_ai( name )
|
|
{
|
|
|
|
guys = getentarray( name, "script_noteworthy" );
|
|
|
|
// should grab two, the spawner and the ai
|
|
assertex( guys.size < 3, "shouldn't have more than 2 of these guys!" );
|
|
|
|
for( i = 0; i < guys.size; i++ )
|
|
{
|
|
|
|
if( isalive( guys[i] ) )
|
|
{
|
|
return guys[i];
|
|
}
|
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// return an array of guys that are alive with the given script_noteworthy
|
|
//
|
|
///////////////////////////////
|
|
|
|
get_specific_ai( name )
|
|
{
|
|
|
|
guys = getentarray( name, "script_noteworthy" );
|
|
|
|
ai_array = [];
|
|
|
|
for( i = 0; i < guys.size; i++ )
|
|
{
|
|
|
|
if( isalive( guys[i] ) )
|
|
{
|
|
ai_array = array_add ( ai_array, guys[i] );
|
|
}
|
|
|
|
}
|
|
|
|
return ai_array;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Moves a script origin to its targetted script_struct and back, continually
|
|
//
|
|
///////////////////////////////
|
|
|
|
flame_move_target( orig, move_time )
|
|
{
|
|
|
|
orig endon( "stop_fakefire_mover" );
|
|
|
|
targ_1 = orig.origin;
|
|
targ_2 = getstruct( orig.target, "targetname" ).origin;
|
|
|
|
while( 1 )
|
|
{
|
|
orig MoveTo( targ_2, move_time );
|
|
orig waittill( "movedone" );
|
|
orig MoveTo( targ_1, move_time );
|
|
orig waittill( "movedone" );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// take a script struct that targets another struct and create a script origin for the purposes of using moveto() and setentitytarget()
|
|
//
|
|
///////////////////////////////
|
|
|
|
convert_aiming_struct_to_origin( struct_name )
|
|
{
|
|
|
|
aim_struct = getstruct( struct_name, "targetname" );
|
|
|
|
orig = spawn( "script_origin", aim_struct.origin );
|
|
orig.target = aim_struct.target;
|
|
|
|
orig.health = 100000;
|
|
|
|
orig.targetname = struct_name + "_converted";
|
|
|
|
return orig;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// get all the vehicles that are alive with the specified script_noteworthy value
|
|
//
|
|
///////////////////////////////
|
|
|
|
get_alive_noteworthy_tanks( name )
|
|
{
|
|
|
|
tanks = getentarray( name, "script_noteworthy" );
|
|
|
|
alive_tanks = [];
|
|
|
|
for( i = 0; i < tanks.size; i++ )
|
|
{
|
|
|
|
if( tanks[i].classname == "script_vehicle" && tanks[i].health > 0 )
|
|
{
|
|
alive_tanks = array_add( alive_tanks, tanks[i] );
|
|
}
|
|
|
|
}
|
|
|
|
return alive_tanks;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// magic bullet shield for tanks
|
|
//
|
|
///////////////////////////////
|
|
|
|
keep_tank_alive()
|
|
{
|
|
assertex( self.classname == "script_vehicle", "keep_tank_alive() must be used with script_vehicles!" );
|
|
self.keep_tank_alive = 1;
|
|
self maps\_vehicle::godon();
|
|
}
|
|
|
|
|
|
|
|
stop_keep_tank_alive()
|
|
{
|
|
self.keep_tank_alive = 0;
|
|
self notify( "stop_friendlyfire_shield" );
|
|
self maps\_vehicle::godoff();
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Handles friendly tank pathing
|
|
//
|
|
///////////////////////////////
|
|
|
|
tank_move( pathstart )
|
|
{
|
|
|
|
level endon( "end_current_tank_paths" );
|
|
|
|
pathpoint = pathstart;
|
|
arraycount = 0;
|
|
pathpoints = [];
|
|
|
|
self setspeed( 16, 8, 6 );
|
|
|
|
// set up pathpoints
|
|
while( isdefined ( pathpoint ) )
|
|
{
|
|
|
|
pathpoints[arraycount] = pathpoint;
|
|
arraycount++;
|
|
|
|
if( isdefined ( pathpoint.target ) )
|
|
{
|
|
pathpoint = getent( pathpoint.target, "targetname" );
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
// actually send tank to point
|
|
for( i = 0; i < pathpoints.size - 1; i++ )
|
|
{
|
|
|
|
self setVehGoalPos( pathpoints[i].origin + ( 0, 0, 0 ) , 0 );
|
|
//self setGoalYaw ( pathpoints[i].angles[1] );
|
|
|
|
self waittillmatch( "goal" );
|
|
|
|
}
|
|
|
|
self setVehGoalPos( pathpoints[pathpoints.size - 1].origin + ( 0, 0, 0 ) , 1 );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Have a tank fire its turret at a script_struct
|
|
//
|
|
///////////////////////////////
|
|
|
|
tank_fire_at_struct( struct_targ, timeout )
|
|
{
|
|
|
|
self endon( "death" );
|
|
self endon( "end_tank_fire_at" );
|
|
|
|
if( !isdefined( timeout ) )
|
|
{
|
|
timeout = 5;
|
|
}
|
|
|
|
self SetTurretTargetVec( struct_targ.origin );
|
|
self waittill_notify_or_timeout( "turret_on_target", timeout );
|
|
wait ( 1 );
|
|
self ClearTurretTarget();
|
|
self fireweapon();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Have a tank fire its turret at an entity
|
|
//
|
|
///////////////////////////////
|
|
|
|
tank_fire_at_ent( ent_name, timeout )
|
|
{
|
|
|
|
self endon( "death" );
|
|
self endon( "end_tank_fire_at" );
|
|
|
|
if( !isdefined( timeout ) )
|
|
{
|
|
timeout = 5;
|
|
}
|
|
|
|
spot = getent( ent_name, "targetname" );
|
|
|
|
self SetTurretTargetEnt( spot );
|
|
self waittill_notify_or_timeout( "turret_on_target", timeout );
|
|
wait ( 1 );
|
|
self ClearTurretTarget();
|
|
self fireweapon();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Have a tank set its turret forward and not track any target
|
|
//
|
|
///////////////////////////////
|
|
|
|
tank_reset_turret( timeout )
|
|
{
|
|
|
|
self endon( "death" );
|
|
|
|
if( !isdefined( timeout ) )
|
|
{
|
|
timeout = 5;
|
|
}
|
|
|
|
// get its turret facing forward
|
|
forward = AnglesToForward( self.angles );
|
|
vec = vectorScale( forward, 1000 );
|
|
|
|
// to see where its forward vec is
|
|
//self thread draw_line_from_ent_to_vec( vec );
|
|
|
|
self SetTurretTargetVec( self.origin + vec );
|
|
|
|
self waittill_notify_or_timeout( "turret_on_target", timeout );
|
|
|
|
// once it's facing forward, don't let it track any previously set turret target
|
|
self ClearTurretTarget();
|
|
|
|
}
|
|
|
|
|
|
|
|
draw_line_from_ent_to_vec( vec, color )
|
|
{
|
|
|
|
if( !isdefined( color ) )
|
|
{
|
|
color = (1,0,0);
|
|
}
|
|
|
|
for( ;; )
|
|
{
|
|
line( self.origin, vec, color, 0.9 );
|
|
wait( 0.05 );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tank_can_see_ent( seen_ent, tank_ent )
|
|
{
|
|
|
|
success = BulletTracePassed( seen_ent geteye(), tank_ent gettagorigin( "tag_flash" ), false, undefined );
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Stops a vehicle once it reaches its goal node
|
|
//
|
|
///////////////////////////////
|
|
|
|
veh_stop_at_node( node_name, accel, decel, dont_stop_flag )
|
|
{
|
|
|
|
if( !isdefined( accel ) )
|
|
{
|
|
accel = 15;
|
|
}
|
|
|
|
if( !isdefined( decel ) )
|
|
{
|
|
decel = 15;
|
|
}
|
|
|
|
vnode = getvehiclenode( node_name, "script_noteworthy" );
|
|
vnode waittill( "trigger" );
|
|
|
|
if( !isdefined( dont_stop_flag ) || ( isdefined( dont_stop_flag ) && !flag( dont_stop_flag ) ) )
|
|
{
|
|
self setspeed( 0, accel, decel );
|
|
// println( "*** debug tank stop node: node " + node_name + "... now stopping" );
|
|
}
|
|
|
|
// extra time for wasp to come to complete stop before firing
|
|
if( self.vehicletype == "wasp" )
|
|
{
|
|
wait( 0.5 );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// For helping guys retreat in specific instances
|
|
//
|
|
///////////////////////////////
|
|
|
|
goto_retreat_nodes( guys )
|
|
{
|
|
|
|
nodes = getnodearray( "node_" + guys[0].script_aigroup, "targetname" );
|
|
|
|
// make sure we have enough nodes to retreat to
|
|
// (may want to allow having less nodes... so some guys stay behind)
|
|
// if( guys.size > nodes.size )
|
|
// {
|
|
// assertmsg( "more ai than there are nodes to retreat to" );
|
|
// return;
|
|
// }
|
|
|
|
for( i = 0; i < guys.size && i < nodes.size; i++ )
|
|
{
|
|
|
|
guys[i].pacifist = 1;
|
|
guys[i].goalradius = 30;
|
|
guys[i] setgoalnode( nodes[i] );
|
|
|
|
guys[i] thread pacifist_till_goal();
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// has a guy be pacifist until he reaches his goal
|
|
//
|
|
///////////////////////////////
|
|
|
|
pacifist_till_goal()
|
|
{
|
|
|
|
self endon( "death" );
|
|
|
|
self waittill( "goal" );
|
|
|
|
self.pacifist = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
temp_vo_no_anim( guy, sound_alias )
|
|
{
|
|
|
|
level thread temp_vo_no_anim_helper( guy, sound_alias );
|
|
|
|
}
|
|
|
|
|
|
temp_vo_no_anim_helper( guy, sound_alias )
|
|
{
|
|
|
|
guy endon( "death" );
|
|
|
|
guy playsound( sound_alias, sound_alias + "_sound_done" );
|
|
|
|
//guy waittill( sound_alias + "_sound_done" );
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// play vo on a guy (must not already be playing a special animation)
|
|
//
|
|
///////////////////////////////
|
|
|
|
play_vo( guy, vo_animname, vo_text )
|
|
{
|
|
level thread play_vo_helper( guy, vo_animname, vo_text );
|
|
}
|
|
|
|
|
|
|
|
play_vo_helper( guy, vo_animname, vo_text )
|
|
{
|
|
|
|
if( !isdefined( guy ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// guy.animname = vo_animname;
|
|
// guy anim_single_solo( guy, vo_text );
|
|
|
|
lookTarget = undefined;
|
|
notifyString = "sound_done";
|
|
|
|
guy thread anim_facialFiller( notifyString, lookTarget );
|
|
guy animscripts\face::SaySpecificDialogue( undefined, level.scr_sound[vo_animname][vo_text], 1.0, notifyString );
|
|
guy waittill( notifyString );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fake death
|
|
// self = the guy getting worked
|
|
bloody_death( die, delay )
|
|
{
|
|
self endon( "death" );
|
|
|
|
if( !is_active_ai( self ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( !isdefined( die ) )
|
|
{
|
|
die = true;
|
|
}
|
|
|
|
if( IsDefined( self.bloody_death ) && self.bloody_death )
|
|
{
|
|
return;
|
|
}
|
|
|
|
self.bloody_death = true;
|
|
|
|
if( IsDefined( delay ) )
|
|
{
|
|
wait( RandomFloat( delay ) );
|
|
}
|
|
|
|
if( !IsDefined( self ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
tags = [];
|
|
tags[0] = "j_hip_le";
|
|
tags[1] = "j_hip_ri";
|
|
tags[2] = "j_head";
|
|
tags[3] = "j_spine4";
|
|
tags[4] = "j_elbow_le";
|
|
tags[5] = "j_elbow_ri";
|
|
tags[6] = "j_clavicle_le";
|
|
tags[7] = "j_clavicle_ri";
|
|
|
|
for( i = 0; i < 2; i++ )
|
|
{
|
|
random = RandomIntRange( 0, tags.size );
|
|
//vec = self GetTagOrigin( tags[random] );
|
|
self thread bloody_death_fx( tags[random], undefined );
|
|
wait( RandomFloat( 0.1 ) );
|
|
}
|
|
|
|
if( die && IsDefined( self ) && self.health )
|
|
{
|
|
self DoDamage( self.health + 150, self.origin );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// self = the AI on which we're playing fx
|
|
bloody_death_fx( tag, fxName )
|
|
{
|
|
if( !IsDefined( fxName ) )
|
|
{
|
|
fxName = level._effect["flesh_hit"];
|
|
}
|
|
|
|
PlayFxOnTag( fxName, self, tag );
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// for use with bloody_death()
|
|
//
|
|
///////////////////////////////
|
|
|
|
is_active_ai( suspect )
|
|
{
|
|
if( IsDefined( suspect ) && IsSentient( suspect ) && IsAlive( suspect ) )
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
players_speed_set( speed, time )
|
|
{
|
|
|
|
players = get_players();
|
|
for( i = 0; i < players.size; i++ )
|
|
{
|
|
players[i] SetMoveSpeedScale( speed );
|
|
}
|
|
|
|
level.current_player_speed = speed;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Returns a random vector within the offset range (doesn't use a 'Z' offset)
|
|
//
|
|
///////////////////////////////
|
|
|
|
random_vector( offset )
|
|
{
|
|
new_vec = ( RandomIntRange( offset*-1, offset ), RandomIntRange( offset*-1, offset ), 0 );
|
|
return new_vec;
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// spawns pickup weapons based upon values in the passed-in array. this is done to save ents on load
|
|
//
|
|
///////////////////////////////
|
|
|
|
spawn_pickup_weapons( weapon_array )
|
|
{
|
|
|
|
// actually spawn each weapon and set its angles/origin
|
|
for( i = 0; i < weapon_array.size; i++ )
|
|
{
|
|
|
|
while( !OkTospawn() )
|
|
{
|
|
wait( 0.05 );
|
|
}
|
|
|
|
pickup_weapon = spawn( weapon_array[i].weapon_name, weapon_array[i].origin, 1 );
|
|
pickup_weapon.angles = weapon_array[i].angles;
|
|
|
|
// ammo count
|
|
if( isdefined( weapon_array[i].count ) )
|
|
{
|
|
pickup_weapon ItemWeaponSetAmmo( 1, 3 );
|
|
}
|
|
|
|
wait_network_frame(); // Lets not saturate our snapshots with weapons... DSL
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Handles what happens when exploders go off and an mg is in the vicinity
|
|
//
|
|
///////////////////////////////
|
|
|
|
mg_sandbag_cleanup( mg_name, killspawner_num )
|
|
{
|
|
|
|
if( isdefined( killspawner_num ) )
|
|
{
|
|
maps\_spawner::kill_spawnernum( killspawner_num );
|
|
}
|
|
|
|
mg = getent( mg_name, "targetname" );
|
|
|
|
mg_owner = mg getturretowner();
|
|
|
|
// if there is a guy on the turret
|
|
if( isdefined( mg_owner ) )
|
|
{
|
|
mg_owner dodamage( mg_owner.health + 10, (0,0,0) );
|
|
}
|
|
|
|
mg cleartargetentity();
|
|
mg SetMode( "manual" );
|
|
mg notify( "death" );
|
|
mg delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////
|
|
//
|
|
// DEBUG
|
|
//
|
|
//////////////////////////////////////
|
|
//////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
guzzo_print_3d( message )
|
|
{
|
|
|
|
self endon( "death" );
|
|
|
|
self notify( "stop_guzzo_print_3d" );
|
|
self endon( "stop_guzzo_print_3d" );
|
|
|
|
while( 1 )
|
|
{
|
|
print3d( ( self.origin +( 0, 0, 65 ) ), message, ( 0.48, 9.4, 0.76 ), 1, 1 );
|
|
wait( 0.05 );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////
|
|
//
|
|
// show the amount of guys alive with the specified script_noteworthy
|
|
//
|
|
//////////////////////////
|
|
|
|
show_alive_ai_count( name )
|
|
{
|
|
/#
|
|
// cancel any previous threads of this function
|
|
level notify( "stop_show_alive_ai_count" );
|
|
level endon( "stop_show_alive_ai_count" );
|
|
|
|
while( 1 )
|
|
{
|
|
|
|
level.extra_info setText( get_specific_ai( name ).size + " " + name + " are alive" );
|
|
|
|
wait( 1 );
|
|
|
|
}
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
///////////
|
|
//
|
|
// show the ai_group_count
|
|
//
|
|
//////////////////////////
|
|
|
|
show_alive_aigroup_count( name )
|
|
{
|
|
/#
|
|
// cancel any previous threads of this function
|
|
level notify( "stop_show_alive_ai_count" );
|
|
level endon( "stop_show_alive_ai_count" );
|
|
|
|
while( 1 )
|
|
{
|
|
|
|
level.extra_info setText( get_ai_group_sentient_count( name ) + " " + name );
|
|
|
|
wait( 1 );
|
|
|
|
|
|
}
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
//////////////
|
|
//
|
|
// count all alive axis and show the # on the level.ai_info hud_elem
|
|
//
|
|
/////////////////////
|
|
debug_ai()
|
|
{
|
|
/#
|
|
while( 1 )
|
|
{
|
|
|
|
axis_ai = GetAiArray( "axis" );
|
|
allied_ai = GetAiArray( "allies" );
|
|
|
|
if( axis_ai.size + allied_ai.size >= 30 )
|
|
{
|
|
level.ai_info.color = (1,0,0);
|
|
}
|
|
else
|
|
{
|
|
level.ai_info.color = (1,1,1);
|
|
}
|
|
|
|
level.ai_info settext( "axis: " + axis_ai.size + " allies: " + allied_ai.size + " total: " + ( axis_ai.size + allied_ai.size ) );
|
|
|
|
wait 0.6;
|
|
|
|
}
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
//////////////
|
|
//
|
|
// make ai weak
|
|
//
|
|
/////////////////////
|
|
debug_ai_health()
|
|
{
|
|
/#
|
|
|
|
if( GetDvar( "guzzo" ) == "1" )
|
|
{
|
|
|
|
spawners = getspawnerarray();
|
|
|
|
for( i = 0; i < spawners.size; i++ )
|
|
{
|
|
if( IsSubStr( spawners[i].classname, "actor_axis" ) )
|
|
{
|
|
spawners[i] add_spawn_function ( ::debug_ai_health_spawnfunc );
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
debug_ai_health_spawnfunc()
|
|
{
|
|
|
|
self.health = 25;
|
|
|
|
}
|
|
|
|
|
|
|
|
debug_tank_health()
|
|
{
|
|
|
|
while( 1 )
|
|
{
|
|
|
|
tanks = getentarray( "script_vehicle", "classname" );
|
|
dead_tanks = getentarray( "script_vehicle_corpse", "classname" );
|
|
tanks = array_combine( tanks, dead_tanks );
|
|
|
|
for( i = 0; i < tanks.size; i++ )
|
|
{
|
|
// if( tanks[i].vehicletype == "type97" || tanks[i].vehicletype == "sherman" || tanks[i].vehicletype == "model94" || tanks[i].vehicletype == "triple25" )
|
|
// {
|
|
|
|
if( isdefined( tanks[i].keep_tank_alive ) && tanks[i].keep_tank_alive == 1 )
|
|
{
|
|
print3d( tanks[i].origin + ( 0, 0, 70 ), tanks[i].health, ( 0.0, 1.0, 0.0 ), 1, 1, 1 );
|
|
if( isdefined( tanks[i].targetname ) )
|
|
{
|
|
print3d( tanks[i].origin + ( 0, 0, 80 ), tanks[i].targetname, ( 0.0, 1.0, 0.0 ), 1, 1, 1 );
|
|
}
|
|
}
|
|
else if( tanks[i].health > 0 )
|
|
{
|
|
print3d( tanks[i].origin + ( 0, 0, 70 ), tanks[i].health, ( 1.0, 1.0, 0.0 ), 1, 1, 1 );
|
|
if( isdefined( tanks[i].targetname ) )
|
|
{
|
|
print3d( tanks[i].origin + ( 0, 0, 80 ), tanks[i].targetname, ( 1.0, 1.0, 0.0 ), 1, 1, 1 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( isdefined( tanks[i].targetname ) )
|
|
{
|
|
print3d( tanks[i].origin + ( 0, 0, 80 ), tanks[i].targetname, ( 1.0, 0.0, 0.0 ), 1, 1, 1 );
|
|
}
|
|
}
|
|
}
|
|
// }
|
|
|
|
wait( 0.05 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
debug_num_vehicles()
|
|
{
|
|
|
|
while( 1 )
|
|
{
|
|
vehicles = getentarray( "script_vehicle", "classname" );
|
|
extra_text( "vehicles: " + vehicles.size );
|
|
wait( 0.5 );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
debug_turret_count()
|
|
{
|
|
|
|
while( 1 )
|
|
{
|
|
|
|
turrets = getentarray( "misc_turret", "classname" );
|
|
level.extra_info setText( "turrets: " +turrets.size );
|
|
for( i = 0; i < turrets.size; i++ )
|
|
{
|
|
println( "turret[" + i + "] at: " + turrets[i].origin );
|
|
print3d( turrets[i].origin + ( 0, 0, 30 ), "*****", ( 0.0, 1.0, 0.0 ), 1, 1, 1 );
|
|
}
|
|
|
|
wait( 0.05 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Prints the current goalradius of an ai above their head
|
|
//
|
|
///////////////////////////////
|
|
|
|
/#
|
|
draw_goal_radius()
|
|
{
|
|
|
|
while( 1 )
|
|
{
|
|
|
|
if( GetDvar( "guzzo" ) == "1" )
|
|
{
|
|
|
|
guys = GetAiArray();
|
|
|
|
for( i = 0; i < guys.size; i++ )
|
|
{
|
|
|
|
if( guys[i].team == "axis" )
|
|
{
|
|
print3d( guys[i].origin + ( 0, 0, 70 ), string( guys[i].goalradius ), ( 1.0, 0.0, 0.0 ), 1, 1, 1 );
|
|
}
|
|
else
|
|
{
|
|
print3d( guys[i].origin + ( 0, 0, 70 ), string( guys[i].goalradius ), ( 0.0, 1.0, 0.0 ), 1, 1, 1 );
|
|
}
|
|
|
|
}
|
|
|
|
wait( 0.05 );
|
|
continue;
|
|
|
|
}
|
|
|
|
wait( 0.4 );
|
|
|
|
|
|
}
|
|
|
|
}
|
|
#/
|
|
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Prints text above each ent
|
|
//
|
|
///////////////////////////////
|
|
|
|
/#
|
|
draw_ent_locations( ent_array, text, endon_string )
|
|
{
|
|
|
|
if( isdefined( endon_string ) )
|
|
{
|
|
level endon( endon_string );
|
|
}
|
|
|
|
while( 1 )
|
|
{
|
|
|
|
|
|
for( i = 0; i < ent_array.size; i++ )
|
|
{
|
|
|
|
// in case ent is deleted
|
|
if( isdefined( ent_array[i].origin ) )
|
|
{
|
|
print3d( ent_array[i].origin + ( 0, 0, 150 ), text, ( 1.0, 0.0, 1.0 ), 1, 1, 1 );
|
|
}
|
|
|
|
}
|
|
|
|
wait( 0.1 );
|
|
|
|
}
|
|
|
|
}
|
|
#/
|
|
|
|
|
|
|
|
|
|
// DEBUG
|
|
// when the dvar is set, prints out all the current existing ents that have "flag_set" as their targetname
|
|
//debug_script_flag_trigs()
|
|
//{
|
|
//
|
|
// dvar_check_old = getdvarint( "debug_script_flag_trigs" );
|
|
//
|
|
// while( 1 )
|
|
// {
|
|
//
|
|
// dvar_check_new = getdvarint( "debug_script_flag_trigs" );
|
|
//
|
|
// if( dvar_check_old != dvar_check_new )
|
|
// {
|
|
//
|
|
// trigs = getentarray( "flag_set", "targetname" );
|
|
// for( i = 0; i < trigs.size; i++ )
|
|
// {
|
|
// println( "" );
|
|
// println( "flag_trig \"" + trigs[i].script_flag + "\"" );
|
|
// println( "" );
|
|
// }
|
|
//
|
|
// dvar_checK_old = dvar_check_new;
|
|
//
|
|
// }
|
|
//
|
|
// wait( 0.05 );
|
|
//
|
|
// }
|
|
//
|
|
//}
|
|
|
|
|
|
|
|
debug_script_flag_trigs_print()
|
|
{
|
|
|
|
trigs_with_script_flag = getentarray( "flag_set", "targetname" );
|
|
|
|
for( i = 0; i < trigs_with_script_flag.size; i++ )
|
|
{
|
|
level thread debug_script_flag_trigs_print_waittill( trigs_with_script_flag[i] );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
debug_script_flag_trigs_print_waittill( trigger )
|
|
{
|
|
|
|
trigger waittill( "trigger" );
|
|
println( "" );
|
|
println( "*** trigger debug: trigger with flag: " + trigger.script_flag + " has just been triggered" );
|
|
|
|
// TODO put this in if we give up trying to find the cause of the bug where triggers dont send their notifies
|
|
// if( isdefined( trigger ) )
|
|
// {
|
|
// trigger delete();
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// DEBUG to test bug# 8490 - random triggers seem to be being deleted
|
|
//
|
|
///////////////////////////////
|
|
|
|
//debug_print_out_all_triggers()
|
|
//{
|
|
//
|
|
// println( "***" );
|
|
//
|
|
// trigger_onces = getentarray( "trigger_once", "classname" );
|
|
// for( i = 0; i < trigger_onces.size; i++ )
|
|
// {
|
|
// println( "*** trigger debug: trigger once ent #: " + trigger_onces[i] getentitynumber() + " at origin: " + trigger_onces[i].origin );
|
|
// if( isdefined( trigger_onces[i].script_flag ) )
|
|
// {
|
|
// println( "*** trigger debug: above trigger has script_flag set as: " + trigger_onces[i].script_flag );
|
|
// }
|
|
// }
|
|
//
|
|
// println( "***" );
|
|
//
|
|
// trigger_multiples = getentarray( "trigger_multiple", "classname" );
|
|
// for( i = 0; i < trigger_multiples.size; i++ )
|
|
// {
|
|
// println( "*** trigger debug: trigger multiple ent #: " + trigger_multiples[i] getentitynumber() + " at origin: " + trigger_multiples[i].origin );
|
|
// if( isdefined( trigger_multiples[i].script_flag ) )
|
|
// {
|
|
// println( "*** trigger debug: above trigger has script_flag set as: " + trigger_multiples[i].script_flag );
|
|
// }
|
|
// }
|
|
//
|
|
// println( "***" );
|
|
//
|
|
// trigger_radius = getentarray( "trigger_radius", "classname" );
|
|
// for( i = 0; i < trigger_radius.size; i++ )
|
|
// {
|
|
// println( "*** trigger debug: trigger radius ent #: " + trigger_radius[i] getentitynumber() + " at origin: " + trigger_radius[i].origin );
|
|
// if( isdefined( trigger_radius[i].script_flag ) )
|
|
// {
|
|
// println( "*** trigger debug: above trigger has script_flag set as: " + trigger_radius[i].script_flag );
|
|
// }
|
|
// }
|
|
//
|
|
// println( "***" );
|
|
//
|
|
//}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// sets up hud elements
|
|
//
|
|
////////////////////////
|
|
|
|
setup_guzzo_hud()
|
|
{
|
|
/#
|
|
level.event_info = NewHudElem();
|
|
level.event_info.alignX = "right";
|
|
level.event_info.x = 100;
|
|
level.event_info.y = 286;
|
|
level.event_info.fontscale = 1.2;
|
|
|
|
//
|
|
level.extra_info = NewHudElem();
|
|
level.extra_info.alignX = "right";
|
|
level.extra_info.x = 100;
|
|
level.extra_info.y = 300;
|
|
level.extra_info.sort = -12;
|
|
|
|
// only for displaying total ai count
|
|
level.ai_info = NewHudElem();
|
|
level.ai_info.alignX = "right";
|
|
level.ai_info.x = 100;
|
|
level.ai_info.y = 320;
|
|
|
|
// for use with quick_text() only
|
|
level.center_info = NewHudElem();
|
|
level.center_info.alignX = "center";
|
|
level.center_info.x = 330;
|
|
level.center_info.y = 90;
|
|
level.center_info.fontscale = 2.0;
|
|
level.center_info.color = ( 0.9, 0.2, 0.2 );
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
/////////////////
|
|
//
|
|
// to display text quickly and easily. uses center_info hud_elem
|
|
//
|
|
//////////////////////////////
|
|
|
|
quick_text( text, how_long, event )
|
|
{
|
|
/#
|
|
|
|
if( !isdefined( how_long ) )
|
|
{
|
|
how_long = 3;
|
|
}
|
|
|
|
if( !isdefined( event ) )
|
|
{
|
|
event = true;
|
|
}
|
|
|
|
level thread quick_text_thread( text, how_long, event );
|
|
#/
|
|
}
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// ***used internally
|
|
// sets text on center_info hud element, waits, then deletes it
|
|
//
|
|
///////////////////////////////
|
|
|
|
quick_text_thread( text, how_long, event )
|
|
{
|
|
/#
|
|
// stop other quick_texts that might be going
|
|
level notify( "stop_quick_text" );
|
|
|
|
level endon( "stop_quick_text" );
|
|
|
|
level.center_info setText( text );
|
|
// print to output so we have a record of quick_text prints
|
|
println( "quick_text print: " + text );
|
|
|
|
wait ( how_long );
|
|
|
|
level.center_info setText( "" );
|
|
|
|
if( event )
|
|
{
|
|
level.event_info settext( text );
|
|
}
|
|
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// flashes test on center_info hud element
|
|
//
|
|
///////////////////////////////
|
|
|
|
flash_center_text( text )
|
|
{
|
|
/#
|
|
level thread hud_fade( level.center_info, text );
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Sets text on event_info hudelem
|
|
//
|
|
///////////////////////////////
|
|
|
|
event_text( text )
|
|
{
|
|
/#
|
|
level.event_info settext( text );
|
|
// print to output so we have a record of quick_text prints
|
|
println( "event_text print: " + text );
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Sets text on extra_info hudelem
|
|
//
|
|
///////////////////////////////
|
|
|
|
extra_text( text )
|
|
{
|
|
/#
|
|
level.extra_info settext( text );
|
|
// print to output so we have a record of quick_text prints
|
|
println( "extra_text print: " + text );
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// ***used internally
|
|
// fades in hud_elem by setting its alpha increasingly higher
|
|
//
|
|
///////////////////////////////
|
|
|
|
hud_fade( hud_elem, text )
|
|
{
|
|
/#
|
|
flash_count = 0;
|
|
|
|
hud_elem.alpha = 0;
|
|
hud_elem setText( text );
|
|
|
|
// fade up the text
|
|
while( 1 )
|
|
{
|
|
|
|
if( ( hud_elem.alpha + 0.05 ) >= 1 )
|
|
{
|
|
hud_elem.alpha = 0;
|
|
|
|
flash_count++;
|
|
|
|
// stop displaying text after a certain number of flashes
|
|
if( ( flash_count ) > 5 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
hud_elem.alpha = hud_elem.alpha + 0.05;
|
|
maps\_spawner::waitframe();
|
|
|
|
}
|
|
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
|
|
// TEMP for testing
|
|
drawline_from_ent( ent )
|
|
{
|
|
/#
|
|
self endon( "kill_lines" );
|
|
|
|
color = ( 0, 255, 0 );
|
|
|
|
while( 1 )
|
|
{
|
|
if( IsDefined( ent ) )
|
|
{
|
|
line( self.origin, ent.origin, color );
|
|
wait( 0.05 );
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
#/
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// Does a print 3d with an asterisk showing the location of a specified tag
|
|
//
|
|
///////////////////////////////
|
|
|
|
show_tag( ent_name, tag_name, noteworthy )
|
|
{
|
|
/#
|
|
if( isdefined( noteworthy ) )
|
|
{
|
|
ent = getent( ent_name, "script_noteworthy" );
|
|
}
|
|
else
|
|
{
|
|
ent = getent( ent_name, "targetname" );
|
|
}
|
|
|
|
while( 1 )
|
|
{
|
|
|
|
orig = ent gettagorigin( tag_name );
|
|
assertex( isdefined( orig ), "tag origin for " + tag_name + " doesn't exist!" );
|
|
|
|
print3d( orig, "**", ( 0.0, 1.0, 0.0 ), 1, 1, 1 );
|
|
|
|
wait( 0.05 );
|
|
|
|
}
|
|
#/
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////
|
|
//
|
|
// only for use with skiptos, to reduce the amount of entities
|
|
//
|
|
///////////////////////////////
|
|
|
|
start_delete_garbage( left_x, right_x, top_y, bottom_y )
|
|
{
|
|
|
|
/#
|
|
|
|
deleted_ents = 0;
|
|
|
|
ents_to_delete = getentarray( "trigger_once", "classname" );
|
|
ents_to_delete_2 = getentarray( "trigger_multiple", "classname" );
|
|
|
|
ents_to_delete = array_combine( ents_to_delete, ents_to_delete_2 );
|
|
|
|
println( "" );
|
|
println( "garbage *** cleanup" );
|
|
|
|
for( i = 0; i < ents_to_delete.size; i++ )
|
|
{
|
|
|
|
if( (ents_to_delete[i].origin[0] > left_x) && (ents_to_delete[i].origin[0] < right_x) && (ents_to_delete[i].origin[1] < top_y) && (ents_to_delete[i].origin[1] > bottom_y ) )
|
|
{
|
|
println( "garbage : deleting ent at: " + ents_to_delete[i].origin );
|
|
ents_to_delete[i] delete();
|
|
}
|
|
|
|
deleted_ents++;
|
|
|
|
}
|
|
|
|
println( "garbage: total deleted ents: " + deleted_ents );
|
|
|
|
#/
|
|
|
|
} |