setModelFromArray( a ) { self setModel( a[ randomint( a.size ) ] ); } precacheModelArray( a ) { for ( i = 0; i < a.size; i++ ) precacheModel( a[ i ] ); } attachHead( headAlias, headArray ) { if ( !isdefined( level.character_head_index ) ) level.character_head_index = []; if ( !isdefined( level.character_head_index[ headAlias ] ) ) level.character_head_index[ headAlias ] = randomint( headArray.size ); assert( level.character_head_index[ headAlias ] < headArray.size ); index = ( level.character_head_index[ headAlias ] + 1 ) % headArray.size; // the designer can overwrite the character if ( isdefined( self.script_char_index ) ) { index = self.script_char_index % headArray.size; } level.character_head_index[ headAlias ] = index; self attach( headArray[ index ], "", true ); self.headModel = headArray[ index ]; } new() { self detachAll(); oldGunHand = self.anim_gunHand; if ( !isdefined( oldGunHand ) ) return; self.anim_gunHand = "none"; self [[ anim.PutGunInHand ]]( oldGunHand ); } save() { info[ "gunHand" ] = self.anim_gunHand; info[ "gunInHand" ] = self.anim_gunInHand; info[ "model" ] = self.model; info[ "hatModel" ] = self.hatModel; if ( isdefined( self.name ) ) { info[ "name" ] = self.name; println( "Save: Guy has name ", self.name ); } else println( "save: Guy had no name!" ); attachSize = self getAttachSize(); for ( i = 0; i < attachSize; i++ ) { info[ "attach" ][ i ][ "model" ] = self getAttachModelName( i ); info[ "attach" ][ i ][ "tag" ] = self getAttachTagName( i ); } return info; } load( info ) { self detachAll(); self.anim_gunHand = info[ "gunHand" ]; self.anim_gunInHand = info[ "gunInHand" ]; self setModel( info[ "model" ] ); self.hatModel = info[ "hatModel" ]; if ( isdefined( info[ "name" ] ) ) { self.name = info[ "name" ]; println( "Load: Guy has name ", self.name ); } else println( "Load: Guy had no name!" ); attachInfo = info[ "attach" ]; attachSize = attachInfo.size; for ( i = 0; i < attachSize; i++ ) self attach( attachInfo[ i ][ "model" ], attachInfo[ i ][ "tag" ] ); } precache( info ) { if ( isdefined( info[ "name" ] ) ) println( "Precache: Guy has name ", info[ "name" ] ); else println( "Precache: Guy had no name!" ); precacheModel( info[ "model" ] ); attachInfo = info[ "attach" ]; attachSize = attachInfo.size; for ( i = 0; i < attachSize; i++ ) precacheModel( attachInfo[ i ][ "model" ] ); } /* sample save / precache / load usage( precache is only required if there are any waits in the level script before load ): save: info = foley codescripts\character::save(); game[ "foley" ] = info; changelevel( "burnville", 0, true ); precache: codescripts\character::precache( game[ "foley" ] ); load: foley codescripts\character::load( game[ "foley" ] ); */ get_random_character( amount ) { self_info = strtok( self.classname, "_" ); if ( !common_scripts\utility::isSP() ) { if ( isDefined( self.pers["modelIndex"] ) && self.pers["modelIndex"] < amount ) return self.pers["modelIndex"]; index = randomInt( amount ); self.pers["modelIndex"] = index; return index; } else if ( self_info.size <= 2 ) { // some custom guy that doesn't use standard naming convention return randomint( amount ); } group = "auto"; // by default the type is an auto-selected character index = undefined; prefix = self_info[ 2 ]; // merc, marine, etc // the designer can overwrite the character if ( isdefined( self.script_char_index ) ) { index = self.script_char_index; } // the designer can hint that this guy is a member of a group of like - spawned guys, so he should use a different index if ( isdefined( self.script_char_group ) ) { type = "grouped"; group = "group_" + self.script_char_group; } if ( !isdefined( level.character_index_cache ) ) { // separately store script grouped guys and auto guys so that they dont influence each other level.character_index_cache = []; } if ( !isdefined( level.character_index_cache[ prefix ] ) ) { // separately store script grouped guys and auto guys so that they dont influence each other level.character_index_cache[ prefix ] = []; } if ( !isdefined( level.character_index_cache[ prefix ][ group ] ) ) { initialize_character_group( prefix, group, amount ); } if ( !isdefined( index ) ) { index = get_least_used_index( prefix, group ); if ( !isdefined( index ) ) { // fail safe index = randomint( 5000 ); } } while ( index >= amount ) { index -= amount; } level.character_index_cache[ prefix ][ group ][ index ]++; return index; } get_least_used_index( prefix, group ) { lowest_indices = []; lowest_use = level.character_index_cache[ prefix ][ group ][ 0 ]; lowest_indices[ 0 ] = 0; for ( i = 1; i < level.character_index_cache[ prefix ][ group ].size; i++ ) { if ( level.character_index_cache[ prefix ][ group ][ i ] > lowest_use ) { continue; } if ( level.character_index_cache[ prefix ][ group ][ i ] < lowest_use ) { // if its the new lowest, start over on the array lowest_indices = []; lowest_use = level.character_index_cache[ prefix ][ group ][ i ]; } // the equal amounts end up in the array lowest_indices[ lowest_indices.size ] = i; } assertex( lowest_indices.size, "Tried to spawn a character but the lowest indices didn't exist" ); return random( lowest_indices ); } initialize_character_group( prefix, group, amount ) { for ( i = 0; i < amount; i++ ) { level.character_index_cache[ prefix ][ group ][ i ] = 0; } } get_random_weapon( amount ) { return randomint( amount ); } random( array ) { return array [ randomint( array.size ) ]; }