boiii-scripts/shared/util_shared.csc
2023-04-13 17:30:38 +02:00

1720 lines
48 KiB
Plaintext

#using scripts\shared\flagsys_shared;
#using scripts\shared\trigger_shared;
#using scripts\shared\util_shared;
/*
util.gsc
This is a utility script common to all game modes. Don't add anything with calls to game type
specific script API calls.
*/
#namespace util;
/@
"Name: empty( <a>, <b>, <c>, <d>, <e> )"
"Summary: Empty function mainly used as a place holder or default function pointer in a system."
"Module: Utility"
"CallOn: "
"OptionalArg: <a> : option arg"
"OptionalArg: <b> : option arg"
"OptionalArg: <c> : option arg"
"OptionalArg: <d> : option arg"
"OptionalArg: <e> : option arg"
"Example: default_callback = &empty;"
"SPMP: both"
@/
function empty( a, b, c, d, e )
{
}
function waitforallclients()
{
localClient = 0;
if(!isdefined(level.localPlayers))
{
while(!isdefined(level.localPlayers))
{
{wait(.016);};
}
}
while( level.localPlayers.size <= 0 )
{
{wait(.016);};
}
while (localClient < level.localPlayers.size)
{
waitforclient(localClient);
localClient++;
}
}
function waitforclient(client)
{
while(!clienthassnapshot(client))
{
{wait(.016);};
}
//syncsystemstates(client);
}
function get_dvar_float_default( str_dvar, default_val )
{
value = GetDvarString( str_dvar );
return ( value != "" ? Float( value ) : default_val );
}
function get_dvar_int_default( str_dvar, default_val )
{
value = GetDvarString( str_dvar );
return ( value != "" ? Int( value ) : default_val );
}
/@
"Name: spawn_model(<model_name>, [origin], [angles])"
"Summary: Spawns a model at an origin and angles."
"Module: Utility"
"MandatoryArg: <model_name> the model name."
"OptionalArg: [origin] the origin to spawn the model at."
"OptionalArg: [angles] the angles to spawn the model at."
"Example: fx_model = spawn_model("tag_origin", org, ang);"
"SPMP: SP"
@/
function spawn_model( n_client, str_model, origin = ( 0, 0, 0 ), angles = ( 0, 0, 0 ) )
{
model = Spawn( n_client, origin, "script_model" );
model SetModel( str_model );
model.angles = angles;
return model;
}
// ----------------------------------------------------------------------------------------------------
// -- Arrays ------------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------------------
function waittill_string( msg, ent )
{
if ( msg != "entityshutdown" )
{
self endon ("entityshutdown");
}
ent endon( "die" );
self waittill( msg );
ent notify( "returned", msg );
}
/@
"Name: waittill_multiple( <string1>, <string2>, <string3>, <string4>, <string5> )"
"Summary: Waits for all of the the specified notifies."
"MandatoryArg: The notifies to wait on."
"Example: guy waittill_multiple( "goal", "pain", "near_goal", "bulletwhizby" );"
@/
function waittill_multiple( ... )
{
s_tracker = SpawnStruct();
s_tracker._wait_count = 0;
for ( i = 0; i < vararg.size; i++ )
{
self thread _waitlogic( s_tracker, vararg[ i ] );
}
if ( s_tracker._wait_count > 0 )
{
s_tracker waittill( "waitlogic_finished" );
}
}
/@
"Name: waittill_multiple_ents( ... )"
"Summary: Waits for all of the the specified notifies on their associated entities."
"MandatoryArg: List of ents and the notifies to wait on."
"Example: waittill_multiple_ents( guy, "goal", guy, "pain", guy, "near_goal", player, "weapon_change" );"
@/
function waittill_multiple_ents( ... )
{
a_ents = [];
a_notifies = [];
for ( i = 0; i < vararg.size; i++ )
{
if ( i % 2 )
{
if ( !isdefined( a_notifies ) ) a_notifies = []; else if ( !IsArray( a_notifies ) ) a_notifies = array( a_notifies ); a_notifies[a_notifies.size]=vararg[ i ];;
}
else
{
if ( !isdefined( a_ents ) ) a_ents = []; else if ( !IsArray( a_ents ) ) a_ents = array( a_ents ); a_ents[a_ents.size]=vararg[ i ];;
}
}
s_tracker = SpawnStruct();
s_tracker._wait_count = 0;
for ( i = 0; i < a_ents.size; i++ )
{
ent = a_ents[ i ];
if ( isdefined( ent ) )
{
ent thread _waitlogic( s_tracker, a_notifies[ i ] );
}
}
if ( s_tracker._wait_count > 0 )
{
s_tracker waittill( "waitlogic_finished" );
}
}
function _waitlogic( s_tracker, notifies )
{
s_tracker._wait_count++;
if ( !isdefined( notifies ) ) notifies = []; else if ( !IsArray( notifies ) ) notifies = array( notifies ); notifies[notifies.size]="entityshutdown";;
waittill_any_array( notifies );
s_tracker._wait_count--;
if ( s_tracker._wait_count == 0 )
{
s_tracker notify( "waitlogic_finished" );
}
}
/@
"Name: waittill_any_return( <string1>, <string2>, <string3>, <string4>, <string5> )"
"Summary: Waits for any of the the specified notifies and return which one it got."
"Module: Utility"
"CallOn: Entity"
"MandatoryArg: <string1> name of a notify to wait on"
"OptionalArg: <string2> name of a notify to wait on"
"OptionalArg: <string3> name of a notify to wait on"
"OptionalArg: <string4> name of a notify to wait on"
"OptionalArg: <string4> name of a notify to wait on"
"OptionalArg: <string6> name of a notify to wait on"
"OptionalArg: <string7> name of a notify to wait on"
"Example: which_notify = guy waittill_any( "goal", "pain", "near_goal", "bulletwhizby" );"
"SPMP: both"
@/
function waittill_any_return( string1, string2, string3, string4, string5, string6, string7 )
{
if ((!isdefined (string1) || string1 != "entityshutdown") &&
(!isdefined (string2) || string2 != "entityshutdown") &&
(!isdefined (string3) || string3 != "entityshutdown") &&
(!isdefined (string4) || string4 != "entityshutdown") &&
(!isdefined (string5) || string5 != "entityshutdown") &&
(!isdefined (string6) || string6 != "entityshutdown") &&
(!isdefined (string7) || string7 != "entityshutdown"))
self endon ("entityshutdown");
ent = SpawnStruct();
if (isdefined (string1))
self thread waittill_string (string1, ent);
if (isdefined (string2))
self thread waittill_string (string2, ent);
if (isdefined (string3))
self thread waittill_string (string3, ent);
if (isdefined (string4))
self thread waittill_string (string4, ent);
if (isdefined (string5))
self thread waittill_string (string5, ent);
if (isdefined (string6))
self thread waittill_string (string6, ent);
if (isdefined (string7))
self thread waittill_string (string7, ent);
ent waittill ("returned", msg);
ent notify ("die");
return msg;
}
/@
"Name: waittill_any_ex( <timeout>, <ent1>, <string1_1>, <string1_2>, <string1_3>... <ent2>, <string2_1>, <string2_2>... ... )"
"Summary: Waits for any of the the specified notifies and returns which one it got. NOTE: you can send any number of ents and arguments that you want. The first <ent1> is optional. In this case, self will be used as the first ent."
"Module: Utility"
"CallOn: Entity"
"OptionalArg: <timeout> timeout value (in seconds)"
"OptionalArg: <ent1> name of a notify to wait on"
"OptionalArg: <string1_1> name of a notify to wait on (ent1 or self)"
"OptionalArg: <string1_2> name of a notify to wait on (ent1 or self)"
"OptionalArg: <string1_3> name of a notify to wait on (ent1 or self)"
"MandatoryArg: <ent2> name of a notify to wait on"
"OptionalArg: <string2_1> name of a notify to wait on (ent2)"
"OptionalArg: <string2_2> name of a notify to wait on (ent2)"
"OptionalArg: <string2_3> name of a notify to wait on (ent2)"
"Example: which_notify = self waittill_any( "stop_waiting", guy1, "goal", "pain", "near_goal", "bulletwhizby", guy2, "death" );"
"SPMP: both"
@/
function waittill_any_ex( ... )
{
s_common = SpawnStruct();
// You can run on an ent if you like instead of passing in an ent as the first argument.
e_current = self;
// if the first parameter is a number, it's a timeout value
n_arg_index = 0;
if ( StrIsNumber( vararg[ 0 ] ) )
{
n_timeout = vararg[ 0 ];
n_arg_index++;
if ( n_timeout > 0 )
{
s_common thread _timeout( n_timeout );
}
}
// If we have an array, use that as the argument list
if ( IsArray( vararg[ n_arg_index ] ) )
{
a_params = vararg[ n_arg_index ];
n_start_index = 0;
}
// Otherwise use the full parameter list.
else
{
a_params = vararg;
n_start_index = n_arg_index;
}
// Run through the parameter list.
// If the parameter is a string, assume it's for the last specified ent
// If the paramter is not a string, assume it's a new ent specification.
for( i=n_start_index; i<a_params.size; i++ )
{
if ( !IsString( a_params[i] ) )
{
// Non string parameter == ent specification. All strings that follow are notifies to wait for on this ent.
e_current = a_params[i];
}
else
{
// string parameter == notify to check for
if ( isdefined( e_current ) )
{
e_current thread waittill_string ( a_params[i], s_common );
}
}
}
s_common waittill ( "returned", str_notify );
s_common notify ( "die" );
return str_notify;
}
/@
"Name: waittill_any_array_return( <a_notifies> )"
"Summary: Waits for any of the the specified notifies and return which one it got."
"Module: Utility"
"CallOn: Entity"
"MandatoryArg: <a_notifies> array of notifies to wait on"
"Example: str_which_notify = guy waittill_any_array_return( array( "goal", "pain", "near_goal", "bulletwhizby" ) );"
"SPMP: both"
@/
function waittill_any_array_return( a_notifies )
{
if ( IsInArray( a_notifies, "entityshutdown" ) )
{
self endon("entityshutdown");
}
s_tracker = SpawnStruct();
foreach ( str_notify in a_notifies )
{
if ( isdefined( str_notify ) )
{
self thread waittill_string( str_notify, s_tracker );
}
}
s_tracker waittill( "returned", msg );
s_tracker notify( "die" );
return msg;
}
/@
"Name: waittill_any( <str_notify1>, <str_notify2>, <str_notify3>, <str_notify4>, <str_notify5> )"
"Summary: Waits for any of the the specified notifies."
"Module: Utility"
"CallOn: Entity"
"MandatoryArg: <str_notify1> name of a notify to wait on"
"OptionalArg: <str_notify2> name of a notify to wait on"
"OptionalArg: <str_notify3> name of a notify to wait on"
"OptionalArg: <str_notify4> name of a notify to wait on"
"OptionalArg: <str_notify5> name of a notify to wait on"
"Example: guy waittill_any( "goal", "pain", "near_goal", "bulletwhizby" );"
"SPMP: both"
@/
function waittill_any( str_notify1, str_notify2, str_notify3, str_notify4, str_notify5 )
{
Assert( isdefined( str_notify1 ) );
waittill_any_array( array( str_notify1, str_notify2, str_notify3, str_notify4, str_notify5 ) );
}
/@
"Name: waittill_any_array( <a_notifies> )"
"Summary: Waits for any of the the specified notifies in the array."
"Module: Utility"
"CallOn: Entity"
"MandatoryArg: <a_notifies> array of notifies to wait on"
"Example: guy waittill_any_array( array( "goal", "pain", "near_goal", "bulletwhizby" ) );"
"SPMP: both"
@/
function waittill_any_array( a_notifies )
{
assert( isdefined( a_notifies[0] ),
"At least the first element has to be defined for waittill_any_array." );
for ( i = 1; i < a_notifies.size; i++ )
{
if ( isdefined( a_notifies[i] ) )
{
self endon( a_notifies[i] );
}
}
self waittill( a_notifies[0] );
}
/@
"Name: waittill_any_timeout( <n_timeout>, <str_notify1>, [str_notify2], [str_notify3], [str_notify4], [str_notify5] )"
"Summary: Waits for any of the the specified notifies or times out."
"Module: Utility"
"CallOn: Entity"
"MandatoryArg: <n_timeout> timeout in seconds"
"MandatoryArg: <str_notify1> name of a notify to wait on"
"OptionalArg: <str_notify2> name of a notify to wait on"
"OptionalArg: <str_notify3> name of a notify to wait on"
"OptionalArg: <str_notify4> name of a notify to wait on"
"OptionalArg: <str_notify5> name of a notify to wait on"
"Example: guy waittill_any_timeout( 2, "goal", "pain", "near_goal", "bulletwhizby" );"
"SPMP: both"
@/
function waittill_any_timeout( n_timeout, string1, string2, string3, string4, string5 )
{
if ( ( !isdefined( string1 ) || string1 != "entityshutdown" ) &&
( !isdefined( string2 ) || string2 != "entityshutdown" ) &&
( !isdefined( string3 ) || string3 != "entityshutdown" ) &&
( !isdefined( string4 ) || string4 != "entityshutdown" ) &&
( !isdefined( string5 ) || string5 != "entityshutdown" ) )
self endon( "entityshutdown" );
ent = spawnstruct();
if ( isdefined( string1 ) )
self thread waittill_string( string1, ent );
if ( isdefined( string2 ) )
self thread waittill_string( string2, ent );
if ( isdefined( string3 ) )
self thread waittill_string( string3, ent );
if ( isdefined( string4 ) )
self thread waittill_string( string4, ent );
if ( isdefined( string5 ) )
self thread waittill_string( string5, ent );
ent thread _timeout( n_timeout );
ent waittill( "returned", msg );
ent notify( "die" );
return msg;
}
function _timeout( delay )
{
self endon( "die" );
wait( delay );
self notify( "returned", "timeout" );
}
/@
"Name: waittill_notify_or_timeout( <msg>, <timer> )"
"Summary: Waits until the owner receives the specified notify message or the specified time runs out. Do not thread this!"
"CallOn: an entity"
"Example: tank waittill_notify_or_timeout( "turret_on_target", 10 ); "
"MandatoryArg: <msg> : The notify to wait for."
"MandatoryArg: <timer> : The amount of time to wait until overriding the wait statement."
@/
function waittill_notify_or_timeout( msg, timer )
{
self endon( msg );
wait( timer );
}
/@
"Name: waittill_any_ents( ent1, string1, ent2, string2, ent3, string3, ent4, string4 )"
"Summary: Waits for any of the the specified notifies on their associated entities."
"Module: Utility"
"CallOn: Entity"
"MandatoryArg: <ent1> entity to wait for <string1> on"
"MandatoryArg: <string1> notify to wait for on <ent1>"
"OptionalArg: <ent2> entity to wait for <string2> on"
"OptionalArg: <string2> notify to wait for on <ent2>"
"OptionalArg: <ent3> entity to wait for <string3> on"
"OptionalArg: <string3> notify to wait for on <ent3>"
"OptionalArg: <ent4> entity to wait for <string4> on"
"OptionalArg: <string4> notify to wait for on <ent4>"
"Example: guy waittill_any_ents( guy, "goal", guy, "pain", guy, "near_goal", player, "weapon_change" );"
"SPMP: both"
@/
function waittill_any_ents( ent1, string1, ent2, string2, ent3, string3, ent4, string4, ent5, string5, ent6, string6,ent7, string7 )
{
assert( isdefined( ent1 ) );
assert( isdefined( string1 ) );
if ( ( isdefined( ent2 ) ) && ( isdefined( string2 ) ) )
ent2 endon( string2 );
if ( ( isdefined( ent3 ) ) && ( isdefined( string3 ) ) )
ent3 endon( string3 );
if ( ( isdefined( ent4 ) ) && ( isdefined( string4 ) ) )
ent4 endon( string4 );
if ( ( isdefined( ent5 ) ) && ( isdefined( string5 ) ) )
ent5 endon( string5 );
if ( ( isdefined( ent6 ) ) && ( isdefined( string6 ) ) )
ent6 endon( string6 );
if ( ( isdefined( ent7 ) ) && ( isdefined( string7 ) ) )
ent7 endon( string7 );
ent1 waittill( string1 );
}
/@
"Name: waittill_any_ents_two( ent1, string1, ent2, string2)"
"Summary: Waits for any of the the specified notifies on their associated entities [MAX TWO]."
"Module: Utility"
"CallOn: Entity"
"MandatoryArg: <ent1> entity to wait for <string1> on"
"MandatoryArg: <string1> notify to wait for on <ent1>"
"OptionalArg: <ent2> entity to wait for <string2> on"
"OptionalArg: <string2> notify to wait for on <ent2>"
"Example: guy waittill_any_ents_two( guy, "goal", guy, "pain");"
"SPMP: both"
@/
function waittill_any_ents_two( ent1, string1, ent2, string2 )
{
assert( isdefined( ent1 ) );
assert( isdefined( string1 ) );
if ( ( isdefined( ent2 ) ) && ( isdefined( string2 ) ) )
ent2 endon( string2 );
ent1 waittill( string1 );
}
/@
"Name: single_func( <entity>, <func>, [arg1], [arg2], [arg3], [arg4], [arg5], [arg6] )"
"Summary: Runs the < func > function on the entity. The entity will become "self" in the specified function."
"Module: Utility"
"CallOn: NA"
"MandatoryArg: entity : the entity to run through <func>"
"MandatoryArg: func> : pointer to a script function"
"OptionalArg: arg1 : parameter 1 to pass to the func"
"OptionalArg: arg2 : parameter 2 to pass to the func"
"OptionalArg: arg3 : parameter 3 to pass to the func"
"OptionalArg: arg4 : parameter 4 to pass to the func"
"OptionalArg: arg5 : parameter 5 to pass to the func"
"OptionalArg: arg6 : parameter 6 to pass to the func"
"Example: single_func( guy,&set_ignoreme, false );"
"SPMP: both"
@/
function single_func( entity, func, arg1, arg2, arg3, arg4, arg5, arg6 )
{
if ( !isdefined( entity ) )
{
entity = level;
}
if ( isdefined( arg6 ) )
{
return entity [[ func ]]( arg1, arg2, arg3, arg4, arg5, arg6 );
}
else if ( isdefined( arg5 ) )
{
return entity [[ func ]]( arg1, arg2, arg3, arg4, arg5 );
}
else if ( isdefined( arg4 ) )
{
return entity [[ func ]]( arg1, arg2, arg3, arg4 );
}
else if ( isdefined( arg3 ) )
{
return entity [[ func ]]( arg1, arg2, arg3 );
}
else if ( isdefined( arg2 ) )
{
return entity [[ func ]]( arg1, arg2 );
}
else if ( isdefined( arg1 ) )
{
return entity [[ func ]]( arg1 );
}
else
{
return entity [[ func ]]();
}
}
/@
"Name: new_func( <func>, [arg1], [arg2], [arg3], [arg4], [arg5], [arg6] )"
"Summary: Creates a new func with the args stored on a struct that can be called with call_func."
"Module: Utility"
"CallOn: NA"
"MandatoryArg: func> : pointer to a script function"
"OptionalArg: arg1 : parameter 1 to pass to the func"
"OptionalArg: arg2 : parameter 2 to pass to the func"
"OptionalArg: arg3 : parameter 3 to pass to the func"
"OptionalArg: arg4 : parameter 4 to pass to the func"
"OptionalArg: arg5 : parameter 5 to pass to the func"
"OptionalArg: arg6 : parameter 6 to pass to the func"
"Example: s_callback = new_func(&set_ignoreme, false );"
"SPMP: both"
@/
function new_func( func, arg1, arg2, arg3, arg4, arg5, arg6 )
{
s_func = SpawnStruct();
s_func.func = func;
s_func.arg1 = arg1;
s_func.arg2 = arg2;
s_func.arg3 = arg3;
s_func.arg4 = arg4;
s_func.arg5 = arg5;
s_func.arg6 = arg6;
return s_func;
}
/@
"Name: call_func( <func_struct> )"
"Summary: Runs the func and args stored on a struct created with new_func."
"Module: Utility"
"CallOn: NA"
"MandatoryArg: func_struct> : struct return by new_func"
"Example: self call_func( s_callback );"
"SPMP: both"
@/
function call_func( s_func )
{
return single_func( self, s_func.func, s_func.arg1, s_func.arg2, s_func.arg3, s_func.arg4, s_func.arg5, s_func.arg6 );
}
/@
"Name: array_ent_thread( <entities>, <func>, [arg1], [arg2], [arg3], [arg4], [arg5] )"
"Summary: Threads the <func> function on self for every entity in the <entities> array, passing the entity has the first argument."
"Module: Array"
"CallOn: NA"
"MandatoryArg: entities : array of entities to thread the process"
"MandatoryArg: func : pointer to a script function"
"OptionalArg: arg1 : parameter 1 to pass to the func (after the entity)"
"OptionalArg: arg2 : parameter 2 to pass to the func (after the entity)"
"OptionalArg: arg3 : parameter 3 to pass to the func (after the entity)"
"OptionalArg: arg4 : parameter 4 to pass to the func (after the entity)"
"OptionalArg: arg5 : parameter 5 to pass to the func (after the entity)"
"Example: array_ent_thread( GetAITeamArray("allies"),&do_something, false );"
"SPMP: both"
@/
function array_ent_thread( entities, func, arg1, arg2, arg3, arg4, arg5 )
{
Assert( isdefined( entities ), "Undefined entity array passed to util::array_ent_thread" );
Assert( isdefined( func ), "Undefined function passed to util::array_ent_thread" );
if ( IsArray( entities ) )
{
if ( entities.size )
{
keys = GetArrayKeys( entities );
for ( i = 0; i < keys.size; i++ )
{
single_thread( self, func, entities[keys[i]], arg1, arg2, arg3, arg4, arg5 );
}
}
}
else
{
single_thread( self, func, entities, arg1, arg2, arg3, arg4, arg5 );
}
}
/@
"Name: single_thread( <entity>, <func>, [arg1], [arg2], [arg3], [arg4], [arg5], [arg6] )"
"Summary: Threads the < func > function on the entity. The entity will become "self" in the specified function."
"Module: Utility"
"CallOn: "
"MandatoryArg: <entity> : the entity to thread <func> on"
"MandatoryArg: <func> : pointer to a script function"
"OptionalArg: [arg1] : parameter 1 to pass to the func"
"OptionalArg: [arg2] : parameter 2 to pass to the func"
"OptionalArg: [arg3] : parameter 3 to pass to the func"
"OptionalArg: [arg4] : parameter 4 to pass to the func"
"OptionalArg: [arg5] : parameter 5 to pass to the func"
"OptionalArg: [arg6] : parameter 6 to pass to the func"
"Example: single_func( guy,&special_ai_think, "some_string", 345 );"
"SPMP: both"
@/
function single_thread(entity, func, arg1, arg2, arg3, arg4, arg5, arg6 )
{
Assert( isdefined( entity ), "Undefined entity passed to util::single_thread()" );
if ( isdefined( arg6 ) )
{
entity thread [[ func ]]( arg1, arg2, arg3, arg4, arg5, arg6 );
}
else if ( isdefined( arg5 ) )
{
entity thread [[ func ]](arg1, arg2, arg3, arg4, arg5);
}
else if ( isdefined( arg4 ) )
{
entity thread [[ func ]]( arg1, arg2, arg3, arg4 );
}
else if ( isdefined( arg3 ) )
{
entity thread [[ func ]]( arg1, arg2, arg3 );
}
else if ( isdefined( arg2 ) )
{
entity thread [[ func ]]( arg1, arg2 );
}
else if ( isdefined( arg1 ) )
{
entity thread [[ func ]]( arg1 );
}
else
{
entity thread [[ func ]]();
}
}
function add_listen_thread( wait_till, func, param1, param2, param3, param4, param5 )
{
level thread add_listen_thread_internal( wait_till, func, param1, param2, param3, param4, param5 );
}
function add_listen_thread_internal( wait_till, func, param1, param2, param3, param4, param5 )
{
for( ;; )
{
level waittill( wait_till );
single_thread(level, func, param1, param2, param3, param4, param5);
}
}
/@
"Name: timeout( <n_time>, <func>, [arg1], [arg2], [arg3], [arg4], [arg5], [arg6] )"
"Summary: Run any function with a timeout. The function will exit when the timeout is reached."
"CallOn: any"
"MandatoryArg: <n_time> : the timeout"
"MandatoryArg: <func> : the function"
"OptionalArg: [arg1] : parameter 1 to pass to the func"
"OptionalArg: [arg2] : parameter 2 to pass to the func"
"OptionalArg: [arg3] : parameter 3 to pass to the func"
"OptionalArg: [arg4] : parameter 4 to pass to the func"
"OptionalArg: [arg5] : parameter 5 to pass to the func"
"OptionalArg: [arg6] : parameter 6 to pass to the func"
"Example: ent timeout( 10, &my_function, 12, "hi" );"
@/
function timeout( n_time, func, arg1, arg2, arg3, arg4, arg5, arg6 )
{
self endon( "entityshutdown" );
if ( isdefined( n_time ) ) { __s = SpawnStruct(); __s endon( "timeout" ); __s util::delay_notify( n_time, "timeout" ); };
single_func( self, func, arg1, arg2, arg3, arg4, arg5, arg6 );
}
/@
"Name: delay(<time_or_notify>, [str_endon], <function>, [arg1], [arg2], [arg3], [arg4], [arg5])"
"Summary: Delay the execution of a thread."
"MandatoryArg: <time_or_notify> : Time to wait( in seconds ) or notify to wait for before sending the notify."
"OptionalArg: [str_endon] : endon to cancel the function call"
"MandatoryArg: <function> : The function to run."
"OptionalArg: [arg1] : parameter 1 to pass to the process"
"OptionalArg: [arg2] : parameter 2 to pass to the process"
"OptionalArg: [arg3] : parameter 3 to pass to the process"
"OptionalArg: [arg4] : parameter 4 to pass to the process"
"OptionalArg: [arg5] : parameter 5 to pass to the process"
"Example: delay( &flag::set, "player_can_rappel", 3 );"
@/
function delay( time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6 )
{
self thread _delay( time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6 );
}
function _delay( time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6 )
{
self endon( "entityshutdown" );
if ( isdefined( str_endon ) )
{
self endon( str_endon );
}
if ( IsString( time_or_notify ) )
{
self waittill( time_or_notify );
}
else
{
wait time_or_notify;
}
single_func( self, func, arg1, arg2, arg3, arg4, arg5, arg6 );
}
/@
"Name: delay_notify( <n_delay>, <str_notify>, [str_endon] )"
"Summary: Notifies self the string after waiting the specified delay time"
"Module: Entity"
"CallOn: An entity"
"MandatoryArg: <time_or_notify> : Time to wait( in seconds ) or notify to wait for before sending the notify."
"MandatoryArg: <str_notify> : The string to notify"
"OptionalArg: <str_endon> : Endon to cancel the notify"
"Example: vehicle delay_notify( 3.5, "start_to_smoke" );"
"SPMP: singleplayer"
@/
function delay_notify( time_or_notify, str_notify, str_endon )
{
self thread _delay_notify( time_or_notify, str_notify, str_endon );
}
function _delay_notify( time_or_notify, str_notify, str_endon )
{
self endon( "entityshutdown" );
if ( isdefined( str_endon ) )
{
self endon( str_endon );
}
if ( IsString( time_or_notify ) )
{
self waittill( time_or_notify );
}
else
{
wait time_or_notify;
}
self notify( str_notify );
}
// Time
function new_timer( n_timer_length )
{
s_timer = SpawnStruct();
s_timer.n_time_created = GetTime();
s_timer.n_length = n_timer_length;
return s_timer;
}
function get_time()
{
t_now = GetTime();
return t_now - self.n_time_created;
}
function get_time_in_seconds()
{
return get_time() / 1000;
}
function get_time_frac( n_end_time )
{
if(!isdefined(n_end_time))n_end_time=self.n_length;
return ( LerpFloat( 0, 1, get_time_in_seconds() / n_end_time ) );
}
function get_time_left()
{
if ( isdefined( self.n_length ) )
{
n_current_time = get_time_in_seconds();
return ( Max( self.n_length - n_current_time, 0 ) );
}
return -1;
}
function is_time_left()
{
return ( get_time_left() != 0 );
}
function timer_wait( n_wait )
{
if ( isdefined( self.n_length ) )
{
n_wait = Min( n_wait, get_time_left() );
}
wait n_wait;
n_current_time = get_time_in_seconds();
return n_current_time;
}
function add_remove_list( &a, on_off )
{
if(!isdefined(a))a=[];
if ( on_off )
{
if ( !IsInArray( a, self ) )
{
ArrayInsert(a,self,a.size);
}
}
else
{
ArrayRemoveValue( a, self, false );
}
}
function clean_deleted( &array )
{
done = false;
while ( !done && array.size > 0 )
{
done = true;
foreach( key, val in array )
{
if (!IsDefined(val))
{
ArrayRemoveIndex(array,key,false);
done = false;
break;
}
}
}
}
/@
"Name: get_eye()"
"Summary: Get eye position accurately even on a player when linked to an entity."
"Module: Utility"
"CallOn: Player or AI"
"Example: eye_pos = player get_eye();"
"SPMP: both"
@/
function get_eye()
{
if( SessionModeIsCampaignGame() )
{
if (self IsPlayer())
{
linked_ent = self GetLinkedEnt();
if (isdefined(linked_ent) && (GetDvarInt("cg_cameraUseTagCamera") > 0))
{
camera = linked_ent GetTagOrigin("tag_camera");
if (isdefined(camera))
{
return camera;
}
}
}
}
pos = self GetEye();
return pos;
}
function spawn_player_arms()
{
arms = spawn(self GetLocalClientNumber(), self.origin + ( 0, 0, -1000 ), "script_model");
if (isdefined(level.player_viewmodel))
{
// level specific viewarms
arms SetModel(level.player_viewmodel);
}
else
{
// default viewarms
arms SetModel("c_usa_cia_masonjr_viewhands"); // updated default viewarms to match _loadout.gsc - TravisJ 12/13/2011
}
return arms;
}
function lerp_dvar( str_dvar, n_start_val, n_end_val, n_lerp_time, b_saved_dvar, b_client_dvar, n_client = 0 )
{
if(!isdefined(n_start_val))n_start_val=GetDvarFloat( str_dvar );
s_timer = new_timer();
do
{
n_time_delta = s_timer timer_wait( .01666 );
n_curr_val = LerpFloat( n_start_val, n_end_val, n_time_delta / n_lerp_time );
if ( ( isdefined( b_saved_dvar ) && b_saved_dvar ) )
{
SetSavedDvar( str_dvar, n_curr_val );
}
/*else if ( IS_TRUE( b_client_dvar ) )//TODO T7 - not supported in MP
{
SetClientDvar( str_dvar, n_curr_val );
} */
else
{
SetDvar( str_dvar, n_curr_val );
}
}
while ( n_time_delta < n_lerp_time );
}
function is_valid_type_for_callback(type)
{
switch(type)
{
case "actor":
case "vehicle":
case "player":
case "NA":
case "general":
case "trigger":
case "missile":
case "scriptmover":
case "turret":
case "plane":
case "helicopter":
{
return true;
}
default:
{
return false;
}
}
}
/@
"Name: wait_till_not_touching( <ent> )"
"Summary: Blocking function. Returns when entity one is no longer touching entity two or either entity dies."
"Module: Util"
"MandatoryArg: <e_to_check>: The entity you want to check"
"MandatoryArg: <e_to_touch>: The entity you want to touch"
"Example: util::wait_till_not_touching( player, t_player_safe )"
"SPMP: singleplayer"
@/
function wait_till_not_touching( e_to_check, e_to_touch )
{
Assert( isdefined( e_to_check ), "Undefined check entity passed to util::wait_till_not_touching" );
Assert( isdefined( e_to_touch ), "Undefined touch entity passed to util::wait_till_not_touching" );
e_to_check endon( "entityshutdown" );
e_to_touch endon( "entityshutdown" );
while( e_to_check IsTouching( e_to_touch ) )
{
wait( 0.05 );
}
}
/#
function error( message )
{
println( "^c * ERROR * ", message );
wait 0.05;
}
#/
function register_system(sSysName, cbFunc)
{
if(!isdefined(level._systemStates))
{
level._systemStates = [];
}
if(level._systemStates.size >= 32)
{
/#error("Max num client systems exceeded.");#/
return;
}
if(isdefined(level._systemStates[sSysName]))
{
/#error("Attempt to re-register client system : " + sSysName);#/
return;
}
else
{
level._systemStates[sSysName] = spawnstruct();
level._systemStates[sSysName].callback = cbFunc;
}
}
function field_set_lighting_ent( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
{
level.light_entity = self;
}
function field_use_lighting_ent( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
{
//TODO T7 - SetLightingEntity not on MP
/*if ( newVal )
{
self SetLightingEntity( level.light_entity );
}
else
{
self SetLightingEntity( self );
}*/
}
function waittill_dobj(localClientNum)
{
while( isdefined( self ) && !(self hasdobj(localClientNum)) )
{
{wait(.016);};
}
}
function server_wait( localClientNum, seconds, waitBetweenChecks, level_endon )//serverwait
{
if ( isdefined( level_endon ) )
{
level endon( level_endon );
}
if ( level.isDemoPlaying && seconds != 0 )
{
if ( !isdefined( waitBetweenChecks ) )
{
waitBetweenChecks = 0.2;
}
waitCompletedSuccessfully = false;
startTime = level.serverTime;
lastTime = startTime;
endTime = startTime + (seconds * 1000);
while( level.serverTime < endTime && level.serverTime >= lastTime )
{
lastTime = level.serverTime;
wait( waitBetweenChecks );
}
if ( lastTime < level.serverTime )
{
waitCompletedSuccessfully = true;
}
}
else
{
waitrealtime( seconds );
waitCompletedSuccessfully = true;
}
return waitCompletedSuccessfully;
}
function friend_not_foe( localClientIndex, predicted )//friendnotfoe
{
player = GetNonPredictedLocalPlayer( localClientIndex ); // Get the local client player not the predicted player
// use the predicted local player when we want to see what they saw
if ( ( isdefined( predicted ) && predicted ) || isdefined( player ) && isdefined( player.team ) && ( player.team == "spectator" ))
{
player = GetLocalPlayer( localClientIndex ); // if spectating use the team info from the predicted/spectated client
}
if ( isdefined( player ) && isdefined( player.team ))
{
team = player.team;
// using the player team to determine team base games
if ( team == "free" )
{
owner = self GetOwner( localClientIndex );
if ( isdefined( owner ) && owner == player )
{
return true;
}
}
else if ( self.team == team )
{
return true;
}
}
return false;
}
function friend_not_foe_team( localClientIndex, team, predicted )//friendnotfoe
{
player = GetNonPredictedLocalPlayer( localClientIndex ); // Get the local client player not the predicted player
// use the predicted local player when we want to see what they saw
if ( ( isdefined( predicted ) && predicted ) || isdefined( player ) && isdefined( player.team ) && ( player.team == "spectator" ))
{
player = GetLocalPlayer( localClientIndex ); // if spectating use the team info from the predicted/spectated client
}
if ( isdefined( player ) && isdefined( player.team ))
{
if ( player.team == team )
{
return true;
}
}
return false;
}
function IsEnemyPlayer( player )
{
assert( isdefined( player ) );
if( !player IsPlayer() )
return false;
if( player.team != "free" )
{
if ( player.team == self.team )
{
return false;
}
}
else
{
if ( player == self )
{
return false;
}
}
return true;
}
function is_player_view_linked_to_entity(localClientNum)//isplayerviewlinkedtoentity
{
if ( self IsDriving( localClientNum ) )
{
return true;
}
if ( self IsLocalPlayerWeaponViewOnlyLinked( ) )
{
return true;
}
return false;
}
function init_utility()
{
level.IsDemoPlaying = IsDemoPlaying();
level.localPlayers = [];
level.numGametypeReservedObjectives = [];
level.releasedObjectives = [];
maxLocalClients = GetMaxLocalClients();
for( localClientNum = 0; localClientNum < maxLocalClients; localClientNum++ )
{
level.releasedObjectives[localClientNum] = [];
level.numGametypeReservedObjectives[localClientNum] = 0;
}
util::WaitForClient( 0 );
level.localPlayers = GetLocalPlayers();
}
/@
"Name: within_fov( <start_origin> , <start_angles> , <end_origin> , <fov> )"
"Summary: Returns true if < end_origin > is within the players field of view, otherwise returns false."
"Module: Vector"
"CallOn: "
"MandatoryArg: <start_origin> : starting origin for FOV check( usually the players origin )"
"MandatoryArg: <start_angles> : angles to specify facing direction( usually the players angles )"
"MandatoryArg: <end_origin> : origin to check if it is in the FOV"
"MandatoryArg: <fov> : cosine of the FOV angle to use"
"Example: qBool = within_fov( level.player.origin, level.player.angles, target1.origin, cos( 45 ) );"
"SPMP: multiplayer"
@/
function within_fov( start_origin, start_angles, end_origin, fov )
{
normal = VectorNormalize( end_origin - start_origin );
forward = AnglesToForward( start_angles );
dot = VectorDot( forward, normal );
return dot >= fov;
}
function is_mature()
{
return IsMatureContentEnabled();
}
function is_gib_restricted_build()
{
if( !(IsMatureContentEnabled() && IsShowGibsEnabled() ))
{
return true;
}
return false;
}
// fancy quicker struct array handling, assumes array elements are objects with which an index can be asigned to( IE: can't do 5.struct_array_index )
// also have to be sure that objects can't be a part of another structarray setup as the index position is asigned to the object
function registerSystem(sSysName, cbFunc)
{
if(!isdefined(level._systemStates))
{
level._systemStates = [];
}
if(level._systemStates.size >= 32)
{
/#error("Max num client systems exceeded.");#/
return;
}
if(isdefined(level._systemStates[sSysName]))
{
/#error("Attempt to re-register client system : " + sSysName);#/
return;
}
else
{
level._systemStates[sSysName] = spawnstruct();
level._systemStates[sSysName].callback = cbFunc;
}
}
function getStatsTableName()
{
if ( SessionModeIsCampaignGame() )
{
return "gamedata/stats/cp/cp_statstable.csv";
}
else if ( SessionModeIsZombiesGame() )
{
return "gamedata/stats/zm/zm_statstable.csv";
}
else
{
return "gamedata/stats/mp/mp_statstable.csv";
}
}
/*setFootstepEffect(name, fx)
{
assert(isdefined(name), "Need to define the footstep surface type.");
assert(isdefined(fx), "Need to define the " + name + " effect.");
if (!isdefined(level._optionalStepEffects))
level._optionalStepEffects = [];
level._optionalStepEffects[level._optionalStepEffects.size] = name;
level._effect["step_" + name] = fx;
}*/
function add_trigger_to_ent(ent, trig)
{
if(!isdefined(ent._triggers))
{
ent._triggers = [];
}
ent._triggers[trig getentitynumber()] = 1;
}
function remove_trigger_from_ent(ent, trig)
{
if(!isdefined(ent._triggers))
return;
if(!isdefined(ent._triggers[trig getentitynumber()]))
return;
ent._triggers[trig getentitynumber()] = 0;
}
function ent_already_in_trigger(trig)
{
if(!isdefined(self._triggers))
return false;
if(!isdefined(self._triggers[trig getentitynumber()]))
return false;
if(!self._triggers[trig getentitynumber()])
return false;
return true; // We're already in this trigger volume.
}
function trigger_thread(ent, on_enter_payload, on_exit_payload)
{
ent endon("entityshutdown");
if(ent ent_already_in_trigger(self))
return;
add_trigger_to_ent(ent, self);
// iprintlnbold("Trigger " + self.targetname + " hit by ent " + ent getentitynumber());
if(isdefined(on_enter_payload))
{
[[on_enter_payload]](ent);
}
while(isdefined(ent) && ent istouching(self))
{
{wait(.016);};
}
// iprintlnbold(ent getentitynumber() + " leaves trigger " + self.targetname + ".");
if(isdefined(ent) && isdefined(on_exit_payload))
{
[[on_exit_payload]](ent);
}
if(isdefined(ent))
{
remove_trigger_from_ent(ent, self);
}
}
// This function differs from trigger_thread in that it does not end on entityshutdown
// and it will always call the on_exit_payload even if the ent is not defined.
// Use cases are on players where you want the exit to be called even if the player goes into killcam
function local_player_trigger_thread_always_exit( ent, on_enter_payload, on_exit_payload)
{
if(ent ent_already_in_trigger(self))
return;
add_trigger_to_ent(ent, self);
if(isdefined(on_enter_payload))
{
[[on_enter_payload]](ent);
}
while(isdefined(ent) && ent istouching(self) && ent issplitscreenhost() )
{
{wait(.016);};
}
if(isdefined(on_exit_payload))
{
[[on_exit_payload]](ent);
}
if(isdefined(ent))
{
remove_trigger_from_ent(ent, self);
}
}
function local_player_entity_thread( localClientNum, entity, func, arg1, arg2, arg3, arg4 )
{
entity endon("entityshutdown");
entity waittill_dobj( localClientNum );
single_thread(entity, func, localClientNum, arg1, arg2, arg3, arg4);
}
/@
"Name: local_players_entity_thread( <entity> , <func> , <arg1> , <arg2> , <arg3>, <arg4> )"
"Summary: Threads the < func > function on entity on all local players when the dobj becomes valid. The entity will become "self" in the specified function."
"Module: Array"
"CallOn: "
"MandatoryArg: <entity> : entity to thread the process"
"MandatoryArg: <func> : pointer to a script function. Function must have the first parameter of localCientNum"
"OptionalArg: <arg1> : parameter 1 to pass to the func"
"OptionalArg: <arg2> : parameter 2 to pass to the func"
"OptionalArg: <arg3> : parameter 3 to pass to the func"
"OptionalArg: <arg4> : parameter 4 to pass to the func"
"Example: local_players_entity_thread( chopper,&spawn_fx );"
"SPMP: mp"
@/
function local_players_entity_thread( entity, func, arg1, arg2, arg3, arg4 )
{
players = level.localPlayers;
for (i = 0; i < players.size; i++)
{
players[i] thread local_player_entity_thread( i, entity, func, arg1, arg2, arg3, arg4 );
}
}
function debug_line( from, to, color, time )
{
/#
level.debug_line = GetDvarInt( "scr_debug_line", 0 ); // debug mode, draws debugging info on screen
if ( isdefined( level.debug_line ) && level.debug_line == 1.0 )
{
if ( !isdefined(time) )
{
time = 1000;
}
Line( from, to, color, 1, 1, time);
}
#/
}
function debug_star( origin, color, time )
{
/#
level.debug_star = GetDvarInt( "scr_debug_star", 0 ); // debug mode, draws debugging info on screen
if ( isdefined( level.debug_star ) && level.debug_star == 1.0 )
{
if ( !isdefined(time) )
{
time = 1000;
}
if ( !isdefined(color) )
{
color = (1,1,1);
}
debugstar( origin, time, color );
}
#/
}
function serverTime()
{
for (;;)
{
level.serverTime = getServerTime( 0 );
{wait(.016);};
}
}
function getNextObjID( localClientNum )
{
nextID = 0;
if ( level.releasedObjectives[localClientNum].size > 0 )
{
nextID = level.releasedObjectives[localClientNum][ level.releasedObjectives[localClientNum].size - 1 ];
level.releasedObjectives[localClientNum][ level.releasedObjectives[localClientNum].size - 1 ] = undefined;
}
else
{
nextID = level.numGametypeReservedObjectives[localClientNum];
level.numGametypeReservedObjectives[localClientNum]++;
}
/#
//No longer an assert, but still print a warning so we know when it happens.
if( nextId > 32 - 1 )
{
println("^3SCRIPT WARNING: Ran out of objective IDs");
}
assert( nextId < 32 );
#/
// if for some reason we ever overrun the objective array then just going
// to keep using the last objective id. This should only happen in extreme
// situations (ie. trying to make this happen).
if ( nextId > 32 - 1 )
nextId = 32 - 1;
return nextID;
}
function releaseObjID( localClientNum, objID )
{
assert( objID < level.numGametypeReservedObjectives[localClientNum] );
for( i = 0; i < level.releasedObjectives[localClientNum].size; i++ )
{
if( objID == level.releasedObjectives[localClientNum][i] )
return;
}
level.releasedObjectives[localClientNum][level.releasedObjectives[localClientNum].size] = objID;
}
function get_next_safehouse( str_next_map )
{
switch( str_next_map )
{
case "cp_mi_sing_blackstation":
case "cp_mi_sing_biodomes":
case "cp_mi_sing_sgen":
return "cp_sh_singapore";
case "cp_mi_cairo_infection":
case "cp_mi_cairo_aquifer":
case "cp_mi_cairo_lotus":
return "cp_sh_cairo";
default:
return "cp_sh_mobile";
}
}
function is_safehouse( str_next_map )
{
if(!isdefined(str_next_map))str_next_map=ToLower( GetDvarString( "mapname" ) );
switch ( str_next_map )
{
case "cp_sh_cairo":
case "cp_sh_mobile":
case "cp_sh_singapore":
return true;
default:
return false;
}
}
/#
function button_held_think( which_button )
{
self endon( "disconnect" );
if(!isdefined(self._holding_button))self._holding_button=[];
self._holding_button[ which_button ] = false;
time_started = 0;
const use_time = 250; // GetDvarInt("g_useholdtime");
while ( true )
{
if ( self._holding_button[ which_button ] )
{
if ( !self [[ level._button_funcs[ which_button ]]]() )
{
self._holding_button[ which_button ] = false;
}
}
else
{
if ( self [[ level._button_funcs[ which_button ]]]() )
{
if ( time_started == 0 )
{
time_started = GetTime();
}
if ( ( GetTime() - time_started ) > use_time )
{
self._holding_button[ which_button ] = true;
}
}
else
{
if ( time_started != 0 )
{
time_started = 0;
}
}
}
{wait(.016);};
}
}
function init_button_wrappers()
{
if ( !isdefined( level._button_funcs ) )
{
level._button_funcs[ 4 ] = &up_button_pressed;
level._button_funcs[ 5 ] = &down_button_pressed;
}
}
function up_button_held()
{
init_button_wrappers();
if ( !isdefined( self._up_button_think_threaded ) )
{
self thread button_held_think( 4 );
self._up_button_think_threaded = true;
}
return self._holding_button[ 4 ];
}
function down_button_held()
{
init_button_wrappers();
if ( !isdefined( self._down_button_think_threaded ) )
{
self thread button_held_think( 5 );
self._down_button_think_threaded = true;
}
return self._holding_button[ 5 ];
}
function up_button_pressed()
{
return ( self ButtonPressed( "UPARROW" ) || self ButtonPressed( "DPAD_UP" ) );
}
function waittill_up_button_pressed()
{
while ( !self up_button_pressed() )
{
{wait(.05);};
}
}
function down_button_pressed()
{
return ( self ButtonPressed( "DOWNARROW" ) || self ButtonPressed( "DPAD_DOWN" ) );
}
function waittill_down_button_pressed()
{
while ( !self down_button_pressed() )
{
{wait(.05);};
}
}
#/