1 #using scripts\codescripts\struct;
3 #using scripts\shared\ai_shared;
4 #using scripts\shared\array_shared;
5 #using scripts\shared\flag_shared;
6 #using scripts\shared\system_shared;
7 #using scripts\shared\trigger_shared;
8 #using scripts\shared\spawner_shared;
9 #using scripts\shared\util_shared;
11 #insert scripts\shared\shared.gsh;
13 #define COLOR_NODE_BIG_RADIUS 1024
14 #define COLOR_FIXED_NODE_RADIUS 64
37 nodes = GetAllNodes();
40 level
flag::init(
"player_looks_away_from_spawner" );
46 level.arrays_of_colorCoded_nodes = [];
47 level.arrays_of_colorCoded_nodes[
"axis" ] = [];
48 level.arrays_of_colorCoded_nodes[
"allies" ] = [];
50 level.colorCoded_volumes = [];
51 level.colorCoded_volumes[
"axis" ] = [];
52 level.colorCoded_volumes[
"allies" ] = [];
54 volumes = GetEntArray(
"info_volume",
"classname" );
57 for( i=0;i<nodes.size;i++ )
59 if( IsDefined( nodes[ i ].script_color_allies ) )
64 if( IsDefined( nodes[ i ].script_color_axis ) )
71 for( i=0;i<volumes.size;i++ )
73 if( IsDefined( volumes[ i ].script_color_allies ) )
78 if( IsDefined( volumes[ i ].script_color_axis ) )
84 level.color_node_type_function = [];
109 level.colorList = [];
110 level.colorList[ level.colorList.size ] =
"r";
111 level.colorList[ level.colorList.size ] =
"b";
112 level.colorList[ level.colorList.size ] =
"y";
113 level.colorList[ level.colorList.size ] =
"c";
114 level.colorList[ level.colorList.size ] =
"g";
115 level.colorList[ level.colorList.size ] =
"p";
116 level.colorList[ level.colorList.size ] =
"o";
118 level.colorCheckList[
"red" ] =
"r";
119 level.colorCheckList[
"r" ] =
"r";
120 level.colorCheckList[
"blue" ] =
"b";
121 level.colorCheckList[
"b" ] =
"b";
122 level.colorCheckList[
"yellow" ]=
"y";
123 level.colorCheckList[
"y" ] =
"y";
124 level.colorCheckList[
"cyan" ] =
"c";
125 level.colorCheckList[
"c" ] =
"c";
126 level.colorCheckList[
"green" ] =
"g";
127 level.colorCheckList[
"g" ] =
"g";
128 level.colorCheckList[
"purple" ]=
"p";
129 level.colorCheckList[
"p" ] =
"p";
130 level.colorCheckList[
"orange" ]=
"o";
131 level.colorCheckList[
"o" ] =
"o";
133 level.currentColorForced = [];
134 level.currentColorForced[
"allies" ] = [];
135 level.currentColorForced[
"axis" ] = [];
137 level.lastColorForced = [];
138 level.lastColorForced[
"allies" ] = [];
139 level.lastColorForced[
"axis" ] = [];
141 for( i = 0; i < level.colorList.size; i++ )
143 level.arrays_of_colorForced_ai[
"allies" ][ level.colorList[ i ] ] = [];
144 level.arrays_of_colorForced_ai[
"axis" ][ level.colorList[ i ] ] = [];
145 level.currentColorForced[
"allies" ][ level.colorList[ i ] ] = undefined;
146 level.currentColorForced[
"axis" ][ level.colorList[ i ] ] = undefined;
154 if ( isdefined( trig.script_color_allies ) )
159 if ( isdefined( trig.script_color_axis ) )
178 self.script_forceColor = level.colorCheckList[
self.script_forceColor ];
183 if( !IsDefined(
self.currentColorCode ) )
188 nodes = level.arrays_of_colorCoded_nodes[
self.team ][
self.currentColorCode ];
189 ARRAY_ADD( nodes, level.colorCoded_volumes[
self.team ][
self.currentColorCode ] );
193 if( !isalive(
self ) )
205 for( i=0; i <nodes.size; i++ )
208 if ( isalive( node.color_user ) && !IsPlayer(node.color_user) )
219 /#println(
"AI with export " +
self.export +
" was told to go to color node but had no node to go to." );#/
227 colorList[ colorList.size ] =
"r";
228 colorList[ colorList.size ] =
"b";
229 colorList[ colorList.size ] =
"y";
230 colorList[ colorList.size ] =
"c";
231 colorList[ colorList.size ] =
"g";
232 colorList[ colorList.size ] =
"p";
233 colorList[ colorList.size ] =
"o";
240 colorCodes = strtok( color_team,
" " );
242 colorCodesByColorIndex = [];
243 usable_colorCodes = [];
247 for( i = 0; i < colorCodes.size; i++ )
250 for( p = 0; p < colorList.size; p++ )
252 if( issubstr( colorCodes[ i ], colorList[ p ] ) )
254 color = colorList[ p ];
260 if( !IsDefined( level.arrays_of_colorCoded_nodes[ team ][ colorCodes[ i ] ] )
261 && !IsDefined( level.colorCoded_volumes[ team ][ colorCodes[ i ] ] )
269 assert( IsDefined( color ),
"Trigger at origin " +
self getorigin() +
" had strange color index " + colorCodes[ i ] );
271 colorCodesByColorIndex[ color ] = colorCodes[ i ];
272 colors[ colors.size ] = color;
273 usable_colorCodes[ usable_colorCodes.size ] = colorCodes[ i ];
277 colorCodes = usable_colorCodes;
280 array[
"colorCodes" ] = colorCodes;
281 array[
"colorCodesByColorIndex" ] = colorCodesByColorIndex;
282 array[
"colors" ] = colors;
288 self endon(
"death" );
291 colorCodes =
array[
"colorCodes" ];
292 colorCodesByColorIndex =
array[
"colorCodesByColorIndex" ];
293 colors =
array[
"colors" ];
295 if ( isdefined(
self.target ) )
298 foreach( s_target
in a_s_targets )
300 if (
IS_EQUAL( s_target.script_string,
"hero_catch_up" ) )
302 DEFAULT(
self.a_s_hero_catch_up, [] );
303 ARRAY_ADD(
self.a_s_hero_catch_up, s_target );
304 if( isdefined( s_target.script_num ) )
306 self.num_hero_catch_up_dist = s_target.script_num;
314 self waittill(
"trigger" );
316 if( IsDefined(
self.activated_color_trigger ) )
319 self.activated_color_trigger = undefined;
323 if( !IsDefined(
self.color_enabled ) || ( IsDefined(
self.color_enabled ) &&
self.color_enabled ) )
334 if( !IsDefined(
self.script_color_stay_on ) )
336 self.script_color_stay_on =
false;
339 if( !IsDefined(
self.color_enabled ) )
341 if(
IS_TRUE(
self.script_color_stay_on ) )
343 self.color_enabled =
true;
347 self.color_enabled =
false;
354 if ( team ==
"allies" )
367 colorCodes =
array[
"colorCodes" ];
368 colorCodesByColorIndex =
array[
"colorCodesByColorIndex" ];
369 colors =
array[
"colors" ];
376 n_player_fov = GetDvarFloat(
"cg_fov" );
377 n_dot_check = cos( n_player_fov );
380 if ( !IsVec( target ) )
382 v_pos = target.origin;
385 foreach ( player
in level.players )
387 v_eye = player GetEye();
388 v_facing = AnglesToForward( player GetPlayerAngles() );
389 v_to_ent = VectorNormalize( v_pos - v_eye );
390 n_dot = VectorDot( v_facing, v_to_ent );
392 if ( n_dot > n_dot_check )
396 else if ( IsVec( target ) )
398 a_trace = BulletTrace( v_eye, target,
false, player );
399 if ( a_trace[
"fraction"] == 1 )
404 else if ( target SightConeTrace( v_eye, player ) != 0 )
419 self notify(
"_hero_catch_up_teleport_" );
420 self endon(
"_hero_catch_up_teleport_" );
421 self endon(
"stop_hero_catch_up_teleport" );
423 const n_telefrag_radius = 16.0;
424 const n_teleport_cooldown_ms = 2000;
426 n_min_player_dist_sq = n_min_dist_from_player * n_min_dist_from_player;
428 self endon(
"death" );
430 a_teleport = s_teleport;
432 a_teleport = array::randomize( a_teleport );
436 b_player_nearby =
false;
437 foreach( player
in level.players )
439 if ( DistanceSquared( player.origin,
self.origin ) < n_min_player_dist_sq )
441 b_player_nearby =
true;
446 if ( !b_player_nearby )
449 if ( isdefined(
self.goal ) )
451 n_ai_dist =
self CalcPathLength(
self.node );
454 foreach( s
in a_teleport )
456 if ( PositionWouldTelefrag( s.origin ) )
461 if ( isdefined( s.teleport_cooldown ) )
463 if ( GetTime() < s.teleport_cooldown )
471 if (
self.team ==
"allies" && isdefined( level.heroes ) )
473 hit_hero = ArrayGetClosest( s.origin, level.heroes, n_telefrag_radius );
474 if ( isdefined( hit_hero ) )
481 if ( isdefined(
self.node ) && n_ai_dist >= 0.0 )
484 n_teleport_distance = PathDistance( s.origin,
self.node.origin );
485 if ( n_teleport_distance > n_ai_dist )
505 if ( isdefined(
self.script_forceColor ) || b_disable_colors )
507 if (
self ForceTeleport( s.origin, s.angles,
true,
true ) )
509 self PathMode(
"move allowed" );
511 s.teleport_cooldown = GetTime() + n_teleport_cooldown_ms;
513 self notify(
"hero_catch_up_teleport" );
515 if ( b_disable_colors )
524 if ( isdefined( func_callback ) )
526 self [[ func_callback ]]();
549 for( i = 0; i < colorCodes.size; i++ )
551 if( !IsDefined( level.arrays_of_colorCoded_spawners[ team ][ colorCodes[ i ] ] ) )
557 ArrayRemoveValue( level.arrays_of_colorCoded_spawners[ team ][ colorCodes[ i ] ], undefined );
560 for( p = 0; p < level.arrays_of_colorCoded_spawners[ team ][ colorCodes[ i ] ].size; p++ )
562 level.arrays_of_colorCoded_spawners[ team ][ colorCodes[ i ] ][ p ].currentColorCode = colorCodes[ i ];
566 for( i = 0; i < colors.size; i++ )
569 level.arrays_of_colorForced_ai[ team ][ colors[ i ] ] = array::remove_dead( level.arrays_of_colorForced_ai[ team ][ colors[ i ] ] );
573 level.lastColorForced[ team ][ colors[ i ] ] = level.currentColorForced[ team ][ colors[ i ] ];
576 level.currentColorForced[ team ][ colors[ i ] ] = colorCodesByColorIndex[ colors[ i ] ];
579 assert( IsDefined( level.arrays_of_colorCoded_nodes[ team ][ level.currentColorForced[ team ][ colors[ i ] ] ] )
580 || IsDefined( level.colorCoded_volumes[ team ][ level.currentColorForced[ team ][ colors[ i ] ] ] ),
581 "Trigger tried to set colorCode " + colors[ i ] +
" but there are no nodes for " + team +
" that use that color combo." );
587 for ( i = 0; i < colorCodes.size; i++ )
595 colorCode = colorCodes[ i ];
597 if ( !IsDefined( level.arrays_of_colorCoded_ai[ team ][ colorCode ] ) )
604 if ( isdefined(
self.a_s_hero_catch_up ) && ai_array.size > 0 )
606 if( isdefined( ai_array[ colorCode ] ) )
608 for ( j = 0; j < ai_array[ colorCode ].size; j++ )
610 ai = ai_array[ colorCode ][ j ];
611 if (
IS_TRUE( ai.is_hero ) && IsDefined( ai.script_forceColor ) )
620 for( i = 0; i < colorCodes.size; i++ )
622 colorCode = colorCodes[ i ];
623 if ( !IsDefined( ai_array[ colorCode ] ) )
634 if ( !IsDefined( level.arrays_of_colorCoded_ai[ team ][ colorCode ] ) )
645 if( !IsDefined( level.lastColorForced[ team ][ color ] ) )
650 return level.lastColorForced[ team ][ color ] == level.currentColorForced[ team ][ color ];
657 if( issubstr( node.script_color_allies, lastColor ) )
659 self.cover_nodes_last[
self.cover_nodes_last.size ] = node;
663 self.cover_nodes_first[
self.cover_nodes_first.size ] = node;
670 if( issubstr( node.script_color_axis, lastColor ) )
672 self.cover_nodes_last[
self.cover_nodes_last.size ] = node;
676 self.cover_nodes_first[
self.cover_nodes_first.size ] = node;
682 self.cover_nodes_first[
self.cover_nodes_first.size ] = node;
687 self.path_nodes[
self.path_nodes.size ] = node;
692 nodes = level.arrays_of_colorCoded_nodes[ team ][ colorCode ];
697 ent.cover_nodes_first = [];
698 ent.cover_nodes_last = [];
700 lastColorForced_exists = IsDefined( level.lastColorForced[ team ][ color ] );
703 for( i=0 ; i < nodes.size; i++ )
706 ent [ [ level.color_node_type_function[ node.type ][ lastColorForced_exists ][ team ] ] ]( node, level.lastColorForced[ team ][ color ] );
709 ent.cover_nodes_first = array::randomize( ent.cover_nodes_first );
710 nodes = ent.cover_nodes_first;
713 for( i=0; i < ent.cover_nodes_last.size; i++ )
715 nodes[ nodes.size ] = ent.cover_nodes_last[ i ];
718 for( i=0; i < ent.path_nodes.size; i++ )
720 nodes[ nodes.size ] = ent.path_nodes[ i ];
723 level.arrays_of_colorCoded_nodes[ team ][ colorCode ] = nodes;
728 if ( IsDefined( level.arrays_of_colorCoded_nodes[ team ][ colorCode ] ) )
729 return level.arrays_of_colorCoded_nodes[ team ][ colorCode ];
731 if ( IsDefined( level.colorCoded_volumes[ team ][ colorCode ] ) )
732 return level.colorCoded_volumes[ team ][ colorCode ];
738 level.arrays_of_colorCoded_ai[ team ][ colorCode ] = array::remove_dead( level.arrays_of_colorCoded_ai[ team ][ colorCode ] );
739 ai = level.arrays_of_colorCoded_ai[ team ][ colorCode ];
740 ai = ArrayCombine( ai, level.arrays_of_colorForced_ai[ team ][ color ],
true,
false );
742 for( i=0;i<ai.size;i++ )
745 if( IsDefined( ai[ i ].currentColorCode ) && ai[ i ].currentColorCode == colorCode )
749 newArray[ newArray.size ] = ai[ i ];
758 for( i=0; i < ai.size; i++ )
768 original_ai_array = ai;
774 if( nodes.size < ai.size )
776 println(
"^3Warning, ColorNumber system tried to make " + ai.size +
" AI go to " + nodes.size +
" nodes." );
782 for( i=0; i < nodes.size; i++ )
786 if( isalive( node.color_user ) )
791 closestAI = ArraySort( ai, node.origin,
true, 1 )[0];
792 assert( isalive( closestAI ) );
793 ArrayRemoveValue( ai, closestAI );
807 self notify(
"stop_color_move" );
808 self.script_careful =
true;
809 self.currentColorCode = colorCode;
818 playerNode = undefined;
819 if( !IsDefined(
self.node ) )
825 olduser =
self.node.color_user;
827 playerNode =
self.node;
828 playerNode.color_user =
self;
832 if( !IsDefined(
self.node ) )
836 if(
self.node != playerNode )
843 playerNode.color_user = undefined;
851 if ( IsDefined(
self.script_color_allies ) )
856 if ( IsDefined(
self.script_color_axis ) )
864 if ( IsDefined(
self.color_user ) )
870 colorCodes = strtok( colorCodeString,
" " );
876 color = colorCode[ 0 ];
877 assert(
colorIsLegit( color ),
"Color " + color +
" is not legit" );
879 if ( !IsDefined( level.currentColorForced[ team ][ color ] ) )
885 if ( level.currentColorForced[ team ][ color ] != colorCode )
897 for ( i = 0; i < ai.size; i++ )
913 if ( !IsDefined(
self.currentColorCode ) )
918 return self.currentColorCode == colorCode;
923 self endon(
"death" );
935 self notify(
"stop_going_to_node" );
938 volume = level.colorCoded_volumes[
self.team ][
self.currentColorCode ];
949 if ( IsDefined(
self._colors_go_line ) )
951 self notify(
"colors_go_line_done" );
952 self._colors_go_line = undefined;
957 self.goalradius = node.radius;
960 if (
IS_TRUE( node.script_forcegoal ) )
966 self SetGoal( node );
969 volume = level.colorCoded_volumes[
self.team ][
self.currentColorCode ];
970 if ( IsDefined( volume ) )
972 self SetGoal( volume );
976 self ClearFixedNodeSafeVolume();
979 if( IsDefined( node.fixedNodeSafeRadius ) )
981 self.fixedNodeSafeRadius = node.fixedNodeSafeRadius;
992 self thread
ai::force_goal( node, undefined,
true,
"stop_color_forcegoal",
true );
994 self notify(
"stop_color_forcegoal" );
999 self endon(
"death" );
1000 self endon(
"stop_being_careful" );
1001 self endon(
"stop_going_to_node" );
1015 self endon(
"death" );
1016 self endon(
"stop_going_to_node" );
1017 self waittill(
"stop_being_careful" );
1025 self SetGoal(
self.origin );
1027 if ( IsDefined( volume ) )
1033 if (
self isKnownEnemyInRadius( node.origin,
self.fixedNodeSafeRadius ) )
1037 if (
self isKnownEnemyInVolume( volume ) )
1049 if ( !(
self isKnownEnemyInRadius( node.origin,
self.fixedNodeSafeRadius ) ) )
1061 if ( IsDefined( volume ) )
1065 if (
self IsKnownEnemyInRadius( node.origin,
self.fixedNodeSafeRadius ) )
1070 if (
self IsKnownEnemyInVolume( volume ) )
1082 if (
self IsKnownEnemyInRadius( node.origin,
self.fixedNodeSafeRadius ) )
1094 if ( !IsDefined(
self.node ) )
1106 self endon(
"stop_color_move" );
1107 self endon(
"death" );
1109 if ( IsDefined( trigger ) )
1115 if( IsDefined( trigger ) )
1117 if( IsDefined( trigger.script_flag_wait ) )
1123 if ( IsDefined( counter ) )
1125 wait( counter * RandomFloatRange( 0.2, 0.35 ) );
1132 self.color_ordered_node_assignment = node;
1136 self waittill(
"node_taken", taker );
1145 if( IsDefined( node ) )
1147 assert( !isalive( node.color_user ),
"Node already had color user!" );
1148 if( isalive(
self.color_node.color_user ) &&
self.color_node.color_user ==
self )
1150 self.color_node.color_user = undefined;
1152 self.color_node = node;
1153 node.color_user =
self;
1163 assert(
self.team !=
"neutral" );
1164 assert( IsDefined(
self.script_forceColor ),
"AI with export " +
self.export +
" lost his script_forcecolor.. somehow." );
1165 colorCode = level.currentColorForced[
self.team ][
self.script_forceColor ];
1169 assert( nodes.size > 0,
"Tried to make guy with export " +
self.export +
" go to forcecolor " +
self.script_forceColor +
" but there are no nodes of that color enabled" );
1170 for( i=0; i < nodes.size; i++ )
1172 if( !isalive( nodes[ i ].color_user ) )
1181 assert(
self.team !=
"neutral" );
1182 assert( IsDefined(
self.script_forceColor ),
"AI with export " +
self.export +
" lost his script_forcecolor.. somehow." );
1183 colorCode = level.currentColorForced[
self.team ][
self.script_forceColor ];
1186 assert( nodes.size > 0,
"Tried to make guy with export " +
self.export +
" go to forcecolor " +
self.script_forceColor +
" but there are no nodes of that color enabled" );
1188 nodes = ArraySort( nodes,
self.origin );
1190 for( i=0; i < nodes.size; i++ )
1192 if( !isalive( nodes[ i ].color_user ) )
1201 self endon(
"stopScript" );
1202 self endon(
"death" );
1204 if( IsDefined(
self.node ) )
1210 if( distancesquared( node.origin,
self.origin ) < 32*32 )
1219 currentTime = gettime();
1221 newTime = gettime();
1224 if( newTime - currentTime >= 1000 )
1232 self endon(
"killanimscript" );
1242 for( i=0;i<ai.size;i++ )
1244 if( !IsDefined( ai[ i ].node ) )
1249 if( ai[ i ].node != node )
1254 ai[ i ] notify(
"eject_from_my_node" );
1256 self notify(
"eject_from_my_node" );
1265 node.color_user =
self;
1266 self.color_node = node;
1268 self endon(
"stop_color_move" );
1269 self waittill(
"death" );
1270 self.color_node.color_user = undefined;
1275 for( i = 0; i < level.colorList.size; i++ )
1277 if( color == level.colorList[ i ] )
1287 colors = strtok( colorCode,
" " );
1289 for( p = 0; p < colors.size; p++ )
1291 assert( !IsDefined( level.colorCoded_volumes[ team ][ colors[ p ] ] ),
"Multiple info_volumes exist with color code " + colors[ p ] );
1293 level.colorCoded_volumes[ team ][ colors[ p ] ] =
self;
1299 self.color_user = undefined;
1300 colors = strtok( colorCode,
" " );
1302 for( p = 0; p < colors.size; p++ )
1304 if( IsDefined( level.arrays_of_colorCoded_nodes[ team ] ) && IsDefined( level.arrays_of_colorCoded_nodes[ team ][ colors[ p ] ] ) )
1307 ARRAY_ADD( level.arrays_of_colorCoded_nodes[ team ][ colors[ p ] ],
self );
1312 level.arrays_of_colorCoded_nodes[ team ][ colors[ p ] ][ 0 ] =
self;
1313 level.arrays_of_colorCoded_ai[ team ][ colors[ p ] ] = [];
1314 level.arrays_of_colorCoded_spawners[ team ][ colors[ p ] ] = [];
1320 if( !IsDefined(
self.color_node ) )
1325 if( IsDefined(
self.color_node.color_user ) &&
self.color_node.color_user ==
self )
1327 self.color_node.color_user = undefined;
1330 self.color_node = undefined;
1331 self notify(
"stop_color_move" );
1338 if( issubstr(
self.classname,
"axis" ) || issubstr(
self.classname,
"enemy" ) )
1340 array[
"team" ] =
"axis";
1341 array[
"colorTeam" ] =
self.script_color_axis;
1344 if(( issubstr(
self.classname,
"ally" ) ) ||( issubstr(
self.classname,
"civilian" ) ) )
1346 array[
"team" ] =
"allies";
1347 array[
"colorTeam" ] =
self.script_color_allies;
1350 if( !IsDefined(
array[
"colorTeam" ] ) )
1361 if( !IsDefined( colorNumberArray ) )
1366 team = colorNumberArray[
"team" ];
1367 colorTeam = colorNumberArray[
"colorTeam" ];
1370 colors = strtok( colorTeam,
" " );
1371 for( i=0;i<colors.size;i++ )
1373 ArrayRemoveValue( level.arrays_of_colorCoded_spawners[ team ][ colors[ i ] ],
self );
1397 level endon(
"kill_color_replacements" );
1401 while(level.friendly_spawners_types[friendly_spawners_type] > 0)
1407 if( !level
flag::get(
"respawn_friendlies" ) )
1409 if( !IsDefined( level.friendly_respawn_vision_checker_thread ) )
1418 if ( level
flag::get(
"player_looks_away_from_spawner" ) || level
flag::get(
"respawn_friendlies" ) )
1423 level
flag::set(
"friendly_spawner_locked" );
1429 level.friendly_spawners_types[friendly_spawners_type] = level.friendly_spawners_types[friendly_spawners_type] - 1;
1441 level notify(
"reinforcement_spawned",
spawn );
1448 if( !IsDefined( fromColor ) )
1457 fromColor = level.current_color_order[ fromColor ];
1459 if( IsDefined( fromColor ) )
1466 if( IsDefined( level.friendly_startup_thread ) )
1468 spawn thread [ [ level.friendly_startup_thread ] ]();
1477 level endon(
"kill_color_replacements" );
1479 assert( isalive(
self ),
"Tried to do replace on death on something that was not alive" );
1480 self endon(
"_disable_reinforcement" );
1483 if(
self.team ==
"axis" )
1493 self.replace_on_death =
true;
1494 assert( !IsDefined(
self.respawn_on_death ),
"Guy with export " +
self.export +
" tried to run respawn on death twice." );
1498 classname =
self.classname;
1499 color =
self.script_forceColor;
1504 if( isalive(
self ) )
1507 self waittill(
"death" );
1510 color_order = level.current_color_order;
1512 if( !IsDefined(
self.script_forceColor ) )
1520 if(!isdefined(level.friendly_spawners_types) || !isdefined(level.friendly_spawners_types[friendly_spawners_type])
1521 || level.friendly_spawners_types[friendly_spawners_type] <= 0)
1523 level.friendly_spawners_types[friendly_spawners_type] = 1;
1530 level.friendly_spawners_types[friendly_spawners_type] = level.friendly_spawners_types[friendly_spawners_type] + 1;
1534 if( IsDefined(
self ) && IsDefined(
self.script_forceColor ) )
1536 color =
self.script_forceColor;
1539 if( IsDefined(
self ) && IsDefined(
self.origin ) )
1541 origin =
self.origin;
1557 correct_colored_friendlies = array::filter_classname( correct_colored_friendlies,
true, classname );
1560 if( !correct_colored_friendlies.size )
1567 players = GetPlayers();
1569 correct_colored_guy = ArraySort( correct_colored_friendlies, players[0].origin, 1 )[0];
1570 assert( correct_colored_guy.script_forceColor != color,
"Tried to replace a " + color +
" guy with a guy of the same color!" );
1575 if( !isalive( correct_colored_guy ) )
1584 if( IsDefined( level.friendly_promotion_thread ) )
1586 correct_colored_guy [ [ level.friendly_promotion_thread ] ]( color );
1589 color = color_order[ color ];
1595 if( !IsDefined( color ) )
1600 if( !IsDefined( color_order ) )
1605 if( !IsDefined( color_order[ color ] ) )
1610 return color_order[ color ];
1615 level.friendly_respawn_vision_checker_thread =
true;
1625 if( !IsDefined( level.respawn_spawner ) )
1630 spawner = level.respawn_spawner;
1632 players = GetPlayers();
1635 for( q = 0; q < players.size; q++ )
1637 difference_vec = players[q].origin - spawner.origin;
1638 if( length( difference_vec ) < 200 )
1645 forward = anglesToForward(( 0, players[q] getplayerangles()[ 1 ], 0 ) );
1646 difference = vectornormalize( difference_vec );
1647 dot = vectordot( forward, difference );
1668 level
flag::set(
"player_looks_away_from_spawner" );
1675 specificFromColor =
false;
1677 if( IsDefined( level.respawn_spawners_specific ) && IsDefined( level.respawn_spawners_specific[fromColor] ) )
1679 specificFromColor =
true;
1682 if( !IsDefined( level.respawn_spawner ) )
1685 if( !IsDefined( fromColor ) || !specificFromColor )
1687 ASSERTMSG(
"Tried to spawn a guy but neither level.respawn_spawner or level.respawn_spawners_specific is defined. Either set it to a spawner or use targetname trigger_friendly_respawn triggers. HINT: has the player hit a friendly_respawn_trigger for ALL allied color groups in the map by the time the player has reached this point?" );
1692 if( !IsDefined( classname ) )
1694 if( IsDefined( fromColor ) && specificFromColor )
1696 return level.respawn_spawners_specific[fromColor];
1700 return level.respawn_spawner;
1704 spawners = GetEntArray(
"color_spawner",
"targetname" );
1705 class_spawners = [];
1706 for( i=0; i < spawners.size; i++ )
1708 class_spawners[ spawners[ i ].classname ] = spawners[ i ];
1712 spawner = undefined;
1713 keys = getarraykeys( class_spawners );
1714 for( i=0; i < keys.size; i++ )
1716 if( !issubstr( class_spawners[ keys[ i ] ].classname, classname ) )
1720 spawner = class_spawners[ keys[ i ] ];
1725 if( !IsDefined( spawner ) )
1727 if( IsDefined( fromColor ) && specificFromColor )
1729 return level.respawn_spawners_specific[fromColor];
1733 return level.respawn_spawner;
1737 if( IsDefined( fromColor ) && specificFromColor )
1739 spawner.origin = level.respawn_spawners_specific[fromColor].origin;
1743 spawner.origin = level.respawn_spawner.origin;
1752 classColorHash = classname;
1754 if(isdefined(fromcolor))
1756 classColorHash +=
"##" + fromcolor;
1759 return classColorHash;
1764 level
flag::set(
"friendly_spawner_locked" );
1771 level
flag::clear(
"player_looks_away_from_spawner" );
1779 level notify(
"kill_color_replacements" );
1780 level.friendly_spawners_types = undefined;
1788 self.replace_on_death = undefined;
1805 assert(
colorIsLegit( color ),
"Tried to set force color on an undefined color: " + color );
1807 if( !IsActor(
self ) )
1813 assert( isalive(
self ),
"Tried to set force color on a dead / undefined entity." );
1817 self.script_color_axis = undefined;
1818 self.script_color_allies = undefined;
1819 self.old_forcecolor = undefined;
1821 if( IsDefined(
self.script_forcecolor ) )
1824 ArrayRemoveValue( level.arrays_of_colorForced_ai[
self.team ][
self.script_forcecolor ],
self );
1827 self.script_forceColor = color;
1830 ARRAY_ADD( level.arrays_of_colorForced_ai[
self.team ][
self.script_forceColor ],
self );
1840 script_forceColor = ai.script_forceColor;
1843 ai waittill(
"death" );
1845 level.arrays_of_colorForced_ai[ team ][ script_forceColor ] =
array::remove_undefined( level.arrays_of_colorForced_ai[ team ][ script_forceColor ] );
1850 Assert( IsDefined( level.colorCheckList[ ToLower( color ) ] ),
"Tried to set force color on an undefined color: " + color );
1851 return level.colorCheckList[ ToLower( color ) ];
1856 self.script_forceColor = color;
1857 self.old_forceColor = undefined;
1862 self notify(
"new_color_being_set" );
1863 self.new_force_color_being_set =
true;
1866 self endon(
"new_color_being_set" );
1867 self endon(
"death" );
1873 if ( IsDefined(
self.script_forceColor ) )
1876 self.currentColorCode = level.currentColorForced[
self.team ][
self.script_forceColor ];
1880 self.new_force_color_being_set = undefined;
1881 self notify(
"done_setting_new_color" );
1886 self notify(
"debug_color_update" );
1887 self endon(
"debug_color_update" );
1888 self waittill(
"death" );
1891 level notify(
"updated_color_friendlies" );
1899 if ( isdefined(
self.script_forceColor ) )
1901 level.debug_color_friendlies[
self GetEntityNumber() ] =
self.script_forceColor;
1905 level.debug_color_friendlies[
self GetEntityNumber() ] = undefined;
1909 level notify(
"updated_color_friendlies" );
1915 if (
self.team ==
"axis" )
1917 return IsDefined(
self.script_color_axis ) || IsDefined(
self.script_forceColor );
1920 return IsDefined(
self.script_color_allies ) || IsDefined(
self.script_forceColor );
1934 color =
self.script_forceColor;
1951 ai = GetAITeamArray( team );
1953 for( i = 0; i < ai.size; i++ )
1956 if( !IsDefined( guy.script_forceColor ) )
1961 if( guy.script_forceColor != color )
1965 guys[ guys.size ] = guy;
1973 ai = GetAITeamArray(
"allies" );
1975 for( i = 0; i < ai.size; i++ )
1978 if( !IsDefined( guy.script_forceColor ) )
1982 guys[ guys.size ] = guy;
1999 if( IsDefined(
self.new_force_color_being_set ) )
2001 self endon(
"death" );
2004 self waittill(
"done_setting_new_color" );
2010 if(
IS_TRUE( stop_being_careful ) )
2012 self notify(
"stop_going_to_node" );
2013 self notify(
"stop_being_careful" );
2016 self clearFixedNodeSafeVolume();
2018 if( !IsDefined(
self.script_forceColor ) )
2023 assert( !IsDefined(
self.old_forcecolor ),
"Tried to disable forcecolor on a guy that somehow had a old_forcecolor already. Investigate!!!" );
2025 self.old_forceColor =
self.script_forceColor;
2029 ArrayRemoveValue( level.arrays_of_colorForced_ai[
self.team ][
self.script_forcecolor ],
self );
2033 self.script_forceColor = undefined;
2034 self.currentColorCode = undefined;
2048 if ( IsDefined(
self.script_forceColor ) )
2053 if ( !IsDefined(
self.old_forceColor ) )
2059 self.old_forceColor = undefined;
2064 return ( isdefined(
self.script_forcecolor ) || isdefined(
self.old_forcecolor ) );