#using scripts\codescripts\struct; #using scripts\shared\array_shared; #using scripts\shared\flag_shared; #using scripts\shared\flagsys_shared; #using scripts\shared\util_shared; #namespace array; /@ @/ function filter( &array, b_keep_keys, func_filter, arg1, arg2, arg3, arg4, arg5 ) { a_new = []; foreach ( key, val in array ) { if ( util::single_func( self, func_filter, val, arg1, arg2, arg3, arg4, arg5 ) ) { if ( IsString( key ) || IsWeapon( key ) ) { // by default, string and weapon object keys are kept if ( isdefined( b_keep_keys ) && !b_keep_keys ) { a_new[ a_new.size ] = val; } else { a_new[ key ] = val; } } else { // by default, int keys are not kept if ( ( isdefined( b_keep_keys ) && b_keep_keys ) ) { a_new[ key ] = val; } else { a_new[ a_new.size ] = val; } } } } return a_new; } /@ @/ function remove_dead( &array, b_keep_keys ) { return filter( array, b_keep_keys, &_filter_dead ); } function _filter_undefined( val ) { return isdefined( val ); } /@ @/ function remove_undefined( &array, b_keep_keys ) { return filter( array, b_keep_keys, &_filter_undefined ); } // This function crashes if called but seems like it should work and would be useful function cleanup( &array, b_keep_empty_arrays = false ) { a_keys = GetArrayKeys( array ); for ( i = a_keys.size - 1; i >= 0; i-- ) { key = a_keys[ i ]; if ( IsArray( array[ key ] ) && array[ key ].size ) { cleanup( array[ key ], b_keep_empty_arrays ); } else if ( !isdefined( array[ key ] ) || ( !b_keep_empty_arrays && IsArray( array[ key ] ) && !array[ key ].size ) ) { ArrayRemoveIndex( array, key ); } } } /@ @/ function filter_classname( &array, b_keep_keys, str_classname ) { return filter( array, b_keep_keys, &_filter_classname, str_classname ); } function get_touching( &array, b_keep_keys ) { return filter( array, b_keep_keys, &IsTouching ); } /@ "Name: array::remove_index( , , [b_keep_keys] )" "Summary: Removes a specified index from an array, returns a new array with the specified index removed." "Module: Array" "MandatoryArg: : The array we will remove an index from." "MandatoryArg: : The index we will remove from the array." "OptionalArg: [b_keep_keys] : If true, retain existing keys. If false or undefined, existing keys of original array will be replaced by ints." "Example: a_new = array::remove_index( array, 3 );" "SPMP: both" @/ function remove_index( array, index, b_keep_keys ) { a_new = []; foreach ( key, val in array ) { if( key == index ) { continue; } else { if ( ( isdefined( b_keep_keys ) && b_keep_keys ) ) { a_new[ key ] = val; } else { a_new[ a_new.size ] = val; } } } return a_new; } /@ "Name: array::delete_all( )" "Summary: Delete all the elements in an array" "Module: Array" "MandatoryArg: : The array whose elements to delete." "Example: array::delete_all( GetAITeamArray( "axis" ) );" "SPMP: both" @/ function delete_all( &array, is_struct ) { foreach ( ent in array ) { if ( isdefined( ent ) ) { if ( ( isdefined( is_struct ) && is_struct ) ) { ent struct::delete(); } else if ( isdefined( ent.__vtable ) ) { ent notify( "death" ); ent = undefined; // class } else { ent Delete(); } } } } /@ "Name: array::notify_all( , )" "Summary: Sends a notify to every element within the array" "Module: Utility" "MandatoryArg: : the array of entities to wait on" "MandatoryArg: : the string notify sent to the elements" "Example: array::notify_all( soldiers, "fire" );" "SPMP: both" @/ function notify_all( &array, str_notify ) { foreach ( elem in array ) { elem notify( str_notify ); } } /@ "Name: thread_all( , , [arg1], [arg2], [arg3], [arg4], [arg5], [arg6] )" "Summary: Threads the < func > function on every entity in the < entities > array. The entity will become "self" in the specified function." "Module: Array" "CallOn: " "MandatoryArg: entities : array of entities to thread the function" "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: array::thread_all( GetAITeamArray( "allies" ), &set_ignoreme, false );" "SPMP: both" @/ function thread_all( &entities, func, arg1, arg2, arg3, arg4, arg5, arg6 ) { Assert( isdefined( entities ), "Undefined entity array passed to array::thread_all" ); Assert( isdefined( func ), "Undefined function passed to array::thread_all" ); if ( IsArray( entities ) ) { if ( isdefined( arg6 ) ) { foreach ( ent in entities ) { ent thread [[ func ]]( arg1, arg2, arg3, arg4, arg5, arg6 ); } } else if ( isdefined( arg5 ) ) { foreach ( ent in entities ) { ent thread [[ func ]]( arg1, arg2, arg3, arg4, arg5 ); } } else if ( isdefined( arg4 ) ) { foreach ( ent in entities ) { ent thread [[ func ]]( arg1, arg2, arg3, arg4 ); } } else if ( isdefined( arg3 ) ) { foreach ( ent in entities ) { ent thread [[ func ]]( arg1, arg2, arg3 ); } } else if ( isdefined( arg2 ) ) { foreach ( ent in entities ) { ent thread [[ func ]]( arg1, arg2 ); } } else if ( isdefined( arg1 ) ) { foreach ( ent in entities ) { ent thread [[ func ]]( arg1 ); } } else { foreach ( ent in entities ) { ent thread [[ func ]](); } } } else { util::single_thread( entities, func, arg1, arg2, arg3, arg4, arg5, arg6 ); } } /@ "Name: thread_all_ents( , , [arg1], [arg2], [arg3], [arg4], [arg5] )" "Summary: Threads the function on self for every entity in the array, passing the entity has the first argument." "Module: Array" "CallOn: NA" "MandatoryArg: entities : array of entities to thread the function" "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::thread_all_ents( GetAITeamArray( "allies" ), &do_something, false );" "SPMP: both" @/ function thread_all_ents( &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++ ) { util::single_thread( self, func, entities[keys[i]], arg1, arg2, arg3, arg4, arg5 ); } } } else { util::single_thread( self, func, entities, arg1, arg2, arg3, arg4, arg5 ); } } /@ "Name: run_all( , , [arg1], [arg2], [arg3], [arg4], [arg5], [arg6] )" "Summary: Runs the < func > function on every entity in the < entities > array. The entity will become "self" in the specified function." "Module: Array" "CallOn: " "MandatoryArg: entities : array of entities to run the function" "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: array::run_all( GetAITeamArray( "allies" ), &set_ignoreme, false );" "SPMP: both" @/ function run_all( &entities, func, arg1, arg2, arg3, arg4, arg5, arg6 ) { Assert( isdefined( entities ), "Undefined entity array passed to array::run_all" ); Assert( isdefined( func ), "Undefined function passed to array::run_all" ); if ( IsArray( entities ) ) { if ( isdefined( arg6 ) ) { foreach ( ent in entities ) { ent [[ func ]]( arg1, arg2, arg3, arg4, arg5, arg6 ); } } else if ( isdefined( arg5 ) ) { foreach ( ent in entities ) { ent [[ func ]]( arg1, arg2, arg3, arg4, arg5 ); } } else if ( isdefined( arg4 ) ) { foreach ( ent in entities ) { ent [[ func ]]( arg1, arg2, arg3, arg4 ); } } else if ( isdefined( arg3 ) ) { foreach ( ent in entities ) { ent [[ func ]]( arg1, arg2, arg3 ); } } else if ( isdefined( arg2 ) ) { foreach ( ent in entities ) { ent [[ func ]]( arg1, arg2 ); } } else if ( isdefined( arg1 ) ) { foreach ( ent in entities ) { ent [[ func ]]( arg1 ); } } else { foreach ( ent in entities ) { ent [[ func ]](); } } } else { util::single_func( entities, func, arg1, arg2, arg3, arg4, arg5, arg6 ); } } /@ "Name: array::exclude( , )" "Summary: Returns an array excluding all members of < array_exclude > " "Module: Array" "CallOn: " "MandatoryArg: : Array containing all items" "MandatoryArg: : Array containing all items to remove or individual entity" "Example: newArray = array::exclude( array1, array2 );" "SPMP: both" @/ function exclude( array, array_exclude )// returns "array" minus all members of array_exclude { newarray = array; if ( IsArray( array_exclude ) ) { foreach ( exclude_item in array_exclude ) { ArrayRemoveValue( newarray, exclude_item ); } } else { ArrayRemoveValue( newarray, array_exclude ); } return newarray; } /@ "Name: array::add( , , )" "Summary: Adds to . Will not add the new value if undefined." "Module: Array" "CallOn: " "MandatoryArg: The array to add to." "MandatoryArg: The item to be added. This can be anything." "OptionalArg: If true, will add the new value if it already exists." "Example: array::add( nodes, new_node );" "SPMP: both" @/ function add( &array, item, allow_dupes = true ) { if ( isdefined( item ) ) { if ( allow_dupes || !IsInArray( array, item ) ) { array[ array.size ] = item; } } } /@ "Name: array::add_sorted( , , )" "Summary: Adds to in sorted order from smallest to biggest. Will not add the new value if undefined." "Module: Array" "CallOn: " "MandatoryArg: The array to add to." "MandatoryArg: The item to be added. This can be anything." "OptionalArg: If true, will add the new value if it already exists." "Example: array::add_sorted( a_numbers, 4 );" "SPMP: both" @/ function add_sorted( &array, item, allow_dupes = true ) { if ( isdefined( item ) ) { if ( allow_dupes || !IsInArray( array, item ) ) { for ( i = 0; i <= array.size; i++ ) { if ( ( i == array.size ) || ( item <= array[i] ) ) { ArrayInsert( array, item, i ); break; } } } } } /@ "Name: array::wait_till( , , [n_timeout] )" "Summary: waits for every entry in the to recieve the notify, die, or n_timeout" "Module: Utility" "MandatoryArg: : the array of entities to wait on" "MandatoryArg: : the notify each array entity will wait on. Can also be an array of notifies (will wait for *any* of the notifies)." "OptionalArg: [n_timeout]: n_timeout to kill the wait prematurely" "Example: array::wait_till( guys, "at the hq" );" "SPMP: both" @/ function wait_till( &array, notifies, n_timeout ) { if ( isdefined( n_timeout ) ) { __s = SpawnStruct(); __s endon( "timeout" ); __s util::delay_notify( n_timeout, "timeout" ); }; s_tracker = SpawnStruct(); s_tracker._wait_count = 0; foreach ( ent in array ) { if ( isdefined( ent ) ) { ent thread util::timeout( n_timeout, &util::_waitlogic, s_tracker, notifies ); } } if ( s_tracker._wait_count > 0 ) { s_tracker waittill( "waitlogic_finished" ); } } /@ "Name: array::wait_till_match( , , , [n_timeout] )" "Summary: waits for every entry in the to recieve the notify with a match parameter, die, or n_timeout" "Module: Utility" "MandatoryArg: : the array of entities to wait on" "MandatoryArg: : the notify each array entity will wait on. Can also be an array of notifies (will wait for *any* of the notifies)." "MandatoryArg: : the notify match value to wait for." "OptionalArg: : n_timeout to kill the wait prematurely" "Example: array::wait_till( guys, "at the hq" );" "SPMP: both" @/ function wait_till_match( &array, str_notify, str_match, n_timeout ) { if ( isdefined( n_timeout ) ) { __s = SpawnStruct(); __s endon( "timeout" ); __s util::delay_notify( n_timeout, "timeout" ); }; s_tracker = SpawnStruct(); s_tracker._array_wait_count = 0; foreach ( ent in array ) { if ( isdefined( ent ) ) { s_tracker._array_wait_count++; ent thread util::timeout( n_timeout, &_waitlogic_match, s_tracker, str_notify, str_match ); ent thread util::timeout( n_timeout, &_waitlogic_death, s_tracker ); } } if ( s_tracker._array_wait_count > 0 ) { s_tracker waittill( "array_wait" ); } } function _waitlogic_match( s_tracker, str_notify, str_match ) { self endon( "death" ); self waittillmatch( str_notify, str_match ); update_waitlogic_tracker( s_tracker ); } function _waitlogic_death( s_tracker ) { self waittill( "death" ); update_waitlogic_tracker( s_tracker ); } function update_waitlogic_tracker( s_tracker ) { s_tracker._array_wait_count--; if ( s_tracker._array_wait_count == 0 ) { s_tracker notify( "array_wait" ); } } /@ @/ function flag_wait( &array, str_flag ) { do { recheck = false; for ( i = 0; i < array.size; i++ ) { ent = array[ i ]; if ( isdefined( ent ) && !ent flag::get( str_flag ) ) { ent util::waittill_either( "death", str_flag ); recheck = true; break; } } } while ( recheck ); } /@ @/ function flagsys_wait( &array, str_flag ) { do { recheck = false; for ( i = 0; i < array.size; i++ ) { ent = array[ i ]; if ( isdefined( ent ) && !ent flagsys::get( str_flag ) ) { ent util::waittill_either( "death", str_flag ); recheck = true; break; } } } while ( recheck ); } /@ @/ function flagsys_wait_any_flag( &array, ... ) { do { recheck = false; for ( i = 0; i < array.size; i++ ) { ent = array[i]; if ( isdefined( ent ) ) { b_flag_set = false; foreach ( str_flag in vararg ) { if ( ent flagsys::get( str_flag ) ) { b_flag_set = true; break; } } if ( !b_flag_set ) { ent util::waittill_any_array( vararg ); recheck = true; } } } } while( recheck ); } /@ @/ function flagsys_wait_any( &array, str_flag ) { foreach ( ent in array ) { if ( ent flagsys::get( str_flag ) ) { return ent; } } wait_any( array, str_flag ); } /@ @/ function flag_wait_clear( &array, str_flag ) { do { recheck = false; for ( i = 0; i < array.size; i++ ) { ent = array[i]; if ( ent flag::get( str_flag ) ) { ent waittill( str_flag ); recheck = true; } } } while( recheck ); } /@ @/ function flagsys_wait_clear( &array, str_flag, n_timeout ) { if ( isdefined( n_timeout ) ) { __s = SpawnStruct(); __s endon( "timeout" ); __s util::delay_notify( n_timeout, "timeout" ); }; do { recheck = false; for ( i = 0; i < array.size; i++ ) { ent = array[i]; if ( IsDefined( ent ) && ent flagsys::get( str_flag ) ) { ent waittill( str_flag ); recheck = true; } } } while( recheck ); } /@ "Name: wait_any( , , )" "Summary: waits for any entry in the to recieve the notify, die, or n_timeout" "Module: Utility" "MandatoryArg: : the array of entities to wait on" "MandatoryArg: : the msg each array entity will wait on" "OptionalArg: : n_timeout to kill the wait prematurely" "Example: array_wait_any( guys, "at the hq" );" "SPMP: both" @/ function wait_any( array, msg, n_timeout ) { if ( isdefined( n_timeout ) ) { __s = SpawnStruct(); __s endon( "timeout" ); __s util::delay_notify( n_timeout, "timeout" ); }; s_tracker = SpawnStruct(); foreach ( ent in array ) { if ( isdefined( ent ) ) { level thread util::timeout( n_timeout, &_waitlogic2, s_tracker, ent, msg ); } } s_tracker endon( "array_wait" ); wait_till( array, "death" ); } function _waitlogic2( s_tracker, ent, msg ) { s_tracker endon( "array_wait" ); if( msg != "death" ) { ent endon( "death" ); } ent util::waittill_any_array( msg ); s_tracker notify( "array_wait" ); } function flag_wait_any( array, str_flag ) { self endon( "death" ); foreach ( ent in array ) { if ( ent flag::get( str_flag ) ) { return ent; } } wait_any( array, str_flag ); } /@ "Name: random( )" "Summary: returns a random element from the passed in array " "Module: Array" "Example: random_spawner = random( event_1_spawners );" "MandatoryArg: : the array from which to pluck a random element" "SPMP: both" @/ function random( array ) { if ( array.size > 0 ) { keys = GetArrayKeys( array ); return array[ keys[RandomInt( keys.size )] ]; } } /@ "Name: randomize( )" "Summary: returns a randomized new array from the passed in array " "Module: Array" "Example: a_spawn_pos = randomize( a_spawn_pos );" "MandatoryArg: : the array from which to create the new random array from" "SPMP: both" @/ function randomize( array ) { for ( i = 0; i < array.size; i++ ) { j = RandomInt( array.size ); temp = array[ i ]; array[ i ] = array[ j ]; array[ j ] = temp; } return array; } /@ "Name: clamp_size( , )" "Summary: returns a chopped off version of the array with only n_count number of elements." "Example: a_spawn_pos = clamp_size( a_spawn_pos, 255 );" "MandatoryArg: : the array from which to create the new array from" "MandatoryArg: : the size of the array to return" @/ function clamp_size( array, n_size ) { a_ret = []; for ( i = 0; i < n_size; i++ ) { a_ret[ i ] = array[ i ]; } return a_ret; } /@ "Name: array::reverse( )" "Summary: Reverses the order of the array and returns the new array." "Module: Array" "CallOn: " "MandatoryArg: : Array to be reversed." "Example: patrol_nodes = array::reverse( patrol_nodes );" "SPMP: both" @/ function reverse( array ) { a_array2 = []; for ( i = array.size - 1; i >= 0; i-- ) { a_array2[ a_array2.size ] = array[ i ]; } return a_array2; } /@ @/ function remove_keys( array ) { a_new = []; foreach ( _, val in array ) { if ( isdefined( val ) ) { a_new[ a_new.size ] = val; } } return a_new; } /@ @/ function swap( &array, index1, index2 ) { temp = array[ index1 ]; array[ index1 ] = array[ index2 ]; array[ index2 ] = temp; } function pop( &array, index, b_keep_keys = true ) { if ( array.size > 0 ) { if ( !isdefined( index ) ) { keys = GetArrayKeys( array ); index = keys[ 0 ]; } if ( isdefined( array[index] ) ) { ret = array[ index ]; ArrayRemoveIndex( array, index, b_keep_keys ); return ret; } } } function pop_front( &array, b_keep_keys = true ) { keys = GetArrayKeys( array ); index = keys[ keys.size - 1 ]; return pop( array, index, b_keep_keys ); } function push( &array, val, index ) { if ( !isdefined( index ) ) { // use max free integer as index index = 0; foreach ( key in GetArrayKeys( array ) ) { if ( IsInt( key ) && ( key >= index ) ) { index = key + 1; } } } ArrayInsert( array, val, index ); } function push_front( &array, val ) { push( array, val, 0 ); } /@ "Name: get_closest( , , )" "Summary: Returns the closest entity in < array > to location < org > " "Module: Distance" "CallOn: " "MandatoryArg: : Origin to be closest to." "MandatoryArg: : Array of entities to check distance on" "OptionalArg: : Minimum distance to check" "Example: friendly = array::get_closest( GetPlayers()[0].origin, allies );" "SPMP: singleplayer" @/ function get_closest( org, &array, dist ) { assert( 0, "Deprecated function. Use 'ArrayGetClosest' instead." ); } /@ "Name: getFarthest( , , )" "Summary: Returns the farthest entity in < array > to location < org > " "Module: Distance" "CallOn: " "MandatoryArg: : Origin to be farthest from." "MandatoryArg: : Array of entities to check distance on" "OptionalArg: : Maximum distance to check" "Example: target = getFarthest( level.player.origin, targets );" "SPMP: singleplayer" @/ function get_farthest( org, &array, dist = undefined ) { assert( 0, "Deprecated function. Use 'ArrayGetFarthest' instead." ); } function closerFunc( dist1, dist2 ) { return dist1 >= dist2; } function fartherFunc( dist1, dist2 ) { return dist1 <= dist2; } /@ "Name: get_all_farthest( , , [a_exclude] , [n_max], [n_maxdist] )" "Summary: Returns an array of all the entities in < array > sorted in order of farthest to closest." "MandatoryArg: : Origin to be farthest from." "MandatoryArg: : Array of entities (anything that contain .origin) to check distance on." "OptionalArg: : Array of entities to exclude from the check." "OptionalArg: : max size of the array to return" "OptionalArg: : max distance from the origin to return acceptable entities" "Example: allies_sort = get_all_farthest( originFC1.origin, allies );" @/ function get_all_farthest( org, &array, a_exclude, n_max, n_maxdist ) { if(!isdefined(n_max))n_max=array.size; a_ret = exclude( array, a_exclude ); if ( isdefined( n_maxdist ) ) { a_ret = ArraySort( a_ret, org, false, n_max, n_maxdist ); } else { a_ret = ArraySort( a_ret, org, false, n_max ); } return a_ret; } /@ "Name: get_all_closest( , , [a_exclude] , [n_max], [n_maxdist] )" "Summary: Returns an array of all the entities in < array > sorted in order of closest to farthest." "CallOn: " "MandatoryArg: : Origin to be closest to." "MandatoryArg: : Array of entities to check distance on." "OptionalArg: : Array of entities to exclude from the check." "OptionalArg: : max size of the array to return" "OptionalArg: : max distance from the origin to return acceptable entities" "Example: allies_sort = get_all_closest( originFC1.origin, allies );" @/ function get_all_closest( org, &array, a_exclude, n_max, n_maxdist ) { if(!isdefined(n_max))n_max=array.size; a_ret = exclude( array, a_exclude ); if ( isdefined( n_maxdist ) ) { a_ret = ArraySort( a_ret, org, true, n_max, n_maxdist ); } else { a_ret = ArraySort( a_ret, org, true, n_max ); } return a_ret; } function alphabetize( &array ) { return sort_by_value( array, true ); } /@ function Name: sort_by_value( array, b_lowest_first = true ) Summary: sorts a list of ents by their value Module: Utility CallOn: n/a ManditoryArg: : array of values to sort OptionalArg: [b_lowest_first]: sort from lowest to highest function Example: list = array::sort_by_value( array ); SPMP: singleplayer @/ //Use ArraySort for distance based sorting of entities function sort_by_value( &array, b_lowest_first = false ) { return merge_sort( array, &_sort_by_value_compare_func, b_lowest_first ); } function _sort_by_value_compare_func( val1, val2, b_lowest_first ) { if ( b_lowest_first ) { return val1 < val2; } else { return val1 > val2; } } /@ function Name: sort_by_script_int( a_ents, b_lowest_first = true ) Summary: sorts a list of ents by their script_int value Module: Utility CallOn: n/a ManditoryArg: : array of entities to sort OptionalArg: [b_lowest_first]: sort from lowest to highest function Example: list = array::sort_by_script_int( a_ents ); SPMP: singleplayer @/ //Use ArraySort for distance based sorting of entities function sort_by_script_int( &a_ents, b_lowest_first = false ) { return merge_sort( a_ents, &_sort_by_script_int_compare_func, b_lowest_first ); } function _sort_by_script_int_compare_func( e1, e2, b_lowest_first ) { if ( b_lowest_first ) { return e1.script_int < e2.script_int; } else { return e1.script_int > e2.script_int; } } function merge_sort( ¤t_list, func_sort, param ) { if ( current_list.size <= 1 ) { return current_list; } left = []; right = []; middle = current_list.size / 2; for ( x = 0; x < middle; x++ ) { if ( !isdefined( left ) ) left = []; else if ( !IsArray( left ) ) left = array( left ); left[left.size]=current_list[ x ];; } for ( ; x < current_list.size; x++ ) { if ( !isdefined( right ) ) right = []; else if ( !IsArray( right ) ) right = array( right ); right[right.size]=current_list[ x ];; } left = merge_sort( left, func_sort, param ); right = merge_sort( right, func_sort, param ); result = merge( left, right, func_sort, param ); return result; } function merge( left, right, func_sort, param ) { result = []; li = 0; ri = 0; while ( li < left.size && ri < right.size ) { b_result = undefined; if ( isdefined( param ) ) { b_result = [[ func_sort ]]( left[ li ], right[ ri ], param ); } else { b_result = [[ func_sort ]]( left[ li ], right[ ri ] ); } if ( b_result ) { result[ result.size ] = left[ li ]; li++; } else { result[ result.size ] = right[ ri ]; ri++; } } while ( li < left.size ) { result[ result.size ] = left[ li ]; li++; } while ( ri < right.size ) { result[ result.size ] = right[ ri ]; ri++; } return result; } /@ "Name: insertion_sort( , , )" "Summary: performs and insertion sort into of the value based on result of . input must already be sorted! must have integer keys. "Module: Array" "CallOn: " "MandatoryArg: : array to operate on, works in place" "MandatoryArg: : foo(a,b); function that returns the results of comparison, <0 if a0 if a>b" "MadatoryArg: : the value to insert" "Example: array::insertion_sort( a, foo, b );" "SPMP: Both" @/ function insertion_sort( &a, compareFunc, val ) { if (!IsDefined(a)) { a=[]; a[0]=val; return ; } for (i=0;i , , , , )" "Summary: Threads the < process > function on every entity in the < entities > array. Each thread is started 1 network frame apart from the next." "Module: Array" "CallOn: " "MandatoryArg: : array of entities to thread the process" "MandatoryArg: : pointer to a script function" "OptionalArg: : parameter 1 to pass to the process" "OptionalArg: : parameter 2 to pass to the process" "OptionalArg: : parameter 3 to pass to the process" "Example: array::spread_all( GetAITeamArray( "allies" ),&set_ignoreme, false );" "SPMP: Both" @/ function spread_all( &entities, func, arg1, arg2, arg3, arg4, arg5 ) { Assert( isdefined( entities ), "Undefined entity array passed to array::spread_all_ents" ); Assert( isdefined( func ), "Undefined function passed to array::spread_all_ents" ); if ( IsArray( entities ) ) { foreach ( ent in entities ) { if( isdefined(ent) ) { util::single_thread( ent, func, arg1, arg2, arg3, arg4, arg5 ); } wait randomfloatrange(.1-.1/3,.1+.1/3); } } else { util::single_thread( entities, func, arg1, arg2, arg3, arg4, arg5 ); wait randomfloatrange(.1-.1/3,.1+.1/3); } } /@ "Name: wait_till_touching( , )" "Summary: Waits until all entities in are touching at the same time" "Module: array" "CallOn: " "MandatoryArg: The array of entities." "MandatoryArg: The volume to check for touching" "Example: array::wait_till_touching(a_group_of_dudes, e_volume_to_wait_for);" @/ function wait_till_touching( &a_ents, e_volume ) { while ( !is_touching( a_ents, e_volume ) ) { wait 0.05; } } /@ "Name: is_touching( , )" "Summary: Returns true if all entities in are touching " "Module: array" "CallOn: " "MandatoryArg: The array of entities." "MandatoryArg: The volume to check for touching" "Example: array::is_touching(a_group_of_dudes, e_volume);" @/ function is_touching( &a_ents, e_volume ) { foreach ( e_ent in a_ents ) { if ( !e_ent IsTouching( e_volume ) ) { return false; } } return true; } /@ "Name: contains( , )" "Summary: Returns true if is found in " "Module: array" "MandatoryArg: The array of possible values. can be a single value." "MandatoryArg: The value to search for" "Example: array::contains(array_numbers_1_to_10, 5) || array::contains(8, 8);" @/ function contains( array_or_val, value ) { if ( isArray ( array_or_val ) ) { foreach( element in array_or_val ) { if ( element === value ) { return true; } } return false; } return array_or_val === value; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function _filter_dead( val ) { return IsAlive( val ); } function _filter_classname( val, arg ) { return IsSubStr( val.classname, arg ); } // Quick Sort - pass it an array it will come back sorted function quickSort(array, compare_func) { return quickSortMid(array, 0, array.size -1, compare_func); } function quickSortMid(array, start, end, compare_func) { i = start; k = end; if(!IsDefined(compare_func)) compare_func = &quickSort_compare; if (end - start >= 1) { pivot = array[start]; while (k > i) { while ( [[ compare_func ]](array[i], pivot) && i <= end && k > i) i++; while ( ![[ compare_func ]](array[k], pivot) && k >= start && k >= i) k--; if (k > i) swap(array, i, k); } swap(array, start, k); array = quickSortMid(array, start, k - 1, compare_func); array = quickSortMid(array, k + 1, end, compare_func); } else return array; return array; } function quicksort_compare(left, right) { return left<=right; }