1 #using scripts\codescripts\struct;
3 #using scripts\shared\array_shared;
4 #using scripts\shared\math_shared;
5 #using scripts\shared\callbacks_shared;
6 #using scripts\shared\clientfield_shared;
7 #using scripts\shared\exploder_shared;
8 #using scripts\shared\flag_shared;
9 #using scripts\shared\spawner_shared;
10 #using scripts\shared\system_shared;
11 #using scripts\shared\trigger_shared;
12 #using scripts\shared\turret_shared;
13 #using scripts\shared\vehicles\_auto_turret;
14 #using scripts\shared\util_shared;
15 #using scripts\shared\vehicleriders_shared;
16 #using scripts\shared\vehicle_death_shared;
18 #insert scripts\shared\shared.gsh;
19 #insert scripts\shared\version.gsh;
21 #define MAX_LIGHTFX_GROUPS 3 // match MAX_LIGHTFX_GROUPS in vehiclecustomsettings.awi
22 #define MAX_AMBIENT_ANIM_GROUPS 3 // match MAX_AMBIENT_ANIM_GROUPS in vehiclecustomsettings.awi
24 #define ANIMTREE "generic"
26 #precache( "material", "black" );
27 #precache( "eventstring", "hud_vehicle_turret_fire" );
71 #using_animtree( ANIMTREE );
128 if(isdefined(level.bypassVehicleScripts))
133 level.heli_default_decel = 10;
151 level array::thread_all_ents( level.vehicle_processtriggers, &
trigger_process );
154 level.vehicle_processtriggers = undefined;
158 level.vehicle_enemy_tanks = [];
159 level.vehicle_enemy_tanks[
"vehicle_ger_tracked_king_tiger" ] =
true;
167 a_all_spawners = GetVehicleSpawnerArray();
175 if( isdefined( trigger.script_gatetrigger ) )
177 return level.vehicle_gatetrigger[ trigger.script_gatetrigger ];
185 if( isdefined( trigger.classname ) && ( trigger.classname ==
"trigger_multiple" || trigger.classname ==
"trigger_radius" || trigger.classname ==
"trigger_lookat" || trigger.classname ==
"trigger_box" ))
191 bTriggeronce =
false;
195 if( isdefined( trigger.script_noteworthy ) && trigger.script_noteworthy ==
"trigger_multiple" )
197 bTriggeronce =
false;
200 trigger.processed_trigger = undefined;
230 if( isdefined( trigger.enabled ) && !trigger.enabled )
232 trigger waittill(
"enable" );
235 if ( isdefined( trigger.script_flag_set ) )
237 if ( isdefined(other) && isdefined( other.vehicle_flags ) )
239 other.vehicle_flags[ trigger.script_flag_set ] =
true;
242 if ( isdefined(other) )
244 other notify(
"vehicle_flag_arrived", trigger.script_flag_set );
250 if ( isdefined( trigger.script_flag_clear ) )
252 if ( isdefined(other) && isdefined( other.vehicle_flags ) )
254 other.vehicle_flags[ trigger.script_flag_clear ] =
false;
260 if( isdefined(other) && script_vehicledetour )
264 else if ( detoured && isdefined( other ) )
276 if ( isdefined( trigger.script_vehicleGroupDelete ) )
278 if( !isdefined( level.vehicle_DeleteGroup[ trigger.script_vehicleGroupDelete ] ) )
280 /#println(
"failed to find deleteable vehicle with script_vehicleGroupDelete group number: ", trigger.script_vehicleGroupDelete );#/
281 level.vehicle_DeleteGroup[ trigger.script_vehicleGroupDelete ] = [];
283 array::delete_all( level.vehicle_DeleteGroup[ trigger.script_vehicleGroupDelete ] );
286 if( isdefined( trigger.script_vehiclespawngroup ) )
288 level notify(
"spawnvehiclegroup" + trigger.script_vehiclespawngroup );
289 level waittill(
"vehiclegroup spawned" + trigger.script_vehiclespawngroup );
292 if ( gates.size > 0 && bTriggeronce )
297 if ( isdefined( trigger ) && isdefined( trigger.script_VehicleStartMove ) )
299 if ( !isdefined( level.vehicle_StartMoveGroup[ trigger.script_VehicleStartMove ] ) )
301 /#println(
"^3Vehicle start trigger is: ", trigger.script_VehicleStartMove );#/
305 foreach ( vehicle
in ArrayCopy( level.vehicle_StartMoveGroup[ trigger.script_VehicleStartMove ] ) )
307 if ( isdefined( vehicle ) )
318 detourpath = undefined;
319 for( j = 0; j < level.vehicle_detourpaths[ detournode.script_vehicledetour ].size; j++ )
321 if( level.vehicle_detourpaths[ detournode.script_vehicledetour ][ j ] != detournode )
323 if( !
islastnode( level.vehicle_detourpaths[ detournode.script_vehicledetour ][ j ] ) )
325 detourpath = level.vehicle_detourpaths[ detournode.script_vehicledetour ][ j ];
336 if( isdefined( detourpath ) )
338 self thread
paths( detourpath );
347 isdefined( detourpath.script_crashtype )
350 isdefined(
self.deaddriver )
352 || detourpath.script_crashtype ==
"forced"
356 !isdefined( detourpath.derailed )
357 || ( isdefined( detourpath.script_crashtype ) && detourpath.script_crashtype ==
"plane" )
364 return isdefined( detourpath.derailed ) && detourpath.derailed;
369 detournode = getvehiclenode( node.target,
"targetname" );
373 if( !isdefined( detourpath ) )
378 if( node.detoured && !isdefined( detourpath.script_vehicledetourgroup ) )
385 self notify(
"crashpath", detourpath );
386 detourpath.derailed = 1;
387 self notify(
"newpath" );
388 self setSwitchNode( node, detourpath );
399 if( isdefined( detourpath.script_vehicledetourgroup ) )
401 if( !isdefined(
self.script_vehicledetourgroup ) )
406 if( detourpath.script_vehicledetourgroup !=
self.script_vehicledetourgroup )
418 if( isdefined( vehicle.script_linkname ) )
420 level.vehicle_link =
array_2d_add( level.vehicle_link, vehicle.script_linkname, vehicle );
423 if( isdefined( vehicle.script_VehicleSpawngroup ) )
425 level.vehicle_SpawnGroup =
array_2d_add( level.vehicle_SpawnGroup, vehicle.script_VehicleSpawngroup, vehicle );
428 if( isdefined( vehicle.script_VehicleStartMove ) )
430 level.vehicle_StartMoveGroup =
array_2d_add( level.vehicle_StartMoveGroup, vehicle.script_VehicleStartMove, vehicle );
433 if( isdefined( vehicle.script_vehicleGroupDelete ) )
435 level.vehicle_DeleteGroup =
array_2d_add( level.vehicle_DeleteGroup, vehicle.script_vehicleGroupDelete, vehicle );
448 for( i = 0; i < ai.size; i++ )
455 living_ai[ living_ai.size ] = ai[ i ];
467 if ( !isdefined( ai ) )
472 if ( !isdefined( ai.classname ) )
477 return ai.classname ==
"script_model";
485 for ( i = 0 ; i < guysarray.size ; i++ )
487 if ( isdefined( guysarray[ i ].script_startingposition ) )
489 firstarray[ firstarray.size ] = guysarray[ i ];
493 secondarray[ secondarray.size ] = guysarray[ i ];
497 return ArrayCombine( firstarray, secondarray,
true,
false );
502 if ( !isdefined(
self.script_vehiclewalk ) )
507 if ( isdefined(
self.script_followmode ) )
509 self.FollowMode =
self.script_followmode;
513 self.FollowMode =
"cover nodes";
517 if ( !isdefined(
self.target ) )
522 node = getnode(
self.target,
"targetname" );
523 if( isdefined( node ) )
525 self.NodeAftervehicleWalk = node;
531 realdetournode = getvehiclenode( node.targetname,
"target" );
532 if( !isdefined( realdetournode ) )
537 realdetournode.detoured = 0;
545 if( isdefined( trigger.processed_trigger ) )
550 ARRAY_ADD( level.vehicle_processtriggers, trigger );
551 trigger.processed_trigger =
true;
556 if( !isdefined( node.target ) )
571 self endon(
"death" );
573 assert( isdefined( node ) || isdefined(
self.attachedpath ),
"vehicle_path() called without a path" );
574 self notify(
"newpath" );
577 if( isdefined( node ) )
579 self.attachedpath = node;
582 pathstart =
self.attachedpath;
583 self.currentNode =
self.attachedpath;
585 if ( !isdefined( pathstart ) )
590 self endon(
"newpath" );
592 currentPoint = pathstart;
594 while ( isdefined( currentPoint ) )
596 self waittill(
"reached_node", currentPoint );
600 if ( !isdefined(
self ) )
605 self.currentNode = currentPoint;
606 self.nextNode = ( isdefined( currentPoint.target ) ? GetVehicleNode( currentPoint.target,
"targetname" ) : undefined );
608 if ( isdefined( currentPoint.gateopen ) && !currentPoint.gateopen )
614 currentPoint notify(
"trigger",
self );
618 if( isdefined( currentPoint.script_dropbombs ) && currentPoint.script_dropbombs > 0 )
620 amount = currentPoint.script_dropbombs;
624 if( isdefined( currentPoint.script_dropbombs_delay ) && currentPoint.script_dropbombs_delay > 0 )
626 delay = currentPoint.script_dropbombs_delay;
629 if( isdefined( currentPoint.script_dropbombs_delaytrace ) && currentPoint.script_dropbombs_delaytrace > 0 )
631 delaytrace = currentPoint.script_dropbombs_delaytrace;
634 self notify(
"drop_bombs", amount,
delay, delaytrace );
637 if ( isdefined( currentPoint.script_noteworthy ) )
639 self notify( currentPoint.script_noteworthy );
640 self notify(
"noteworthy", currentPoint.script_noteworthy );
643 if ( isdefined( currentPoint.script_notify) )
645 self notify( currentPoint.script_notify );
646 level notify( currentPoint.script_notify );
651 if ( !isdefined(
self ) )
656 if (
IS_TRUE( currentPoint.script_delete ) )
658 if ( isdefined(
self.riders ) &&
self.riders.size > 0 )
660 array::delete_all(
self.riders );
667 if( isdefined( currentPoint.script_sound ) )
669 self playsound( currentPoint.script_sound );
672 if ( isdefined( currentPoint.script_noteworthy ) )
674 if ( currentPoint.script_noteworthy ==
"godon" )
678 else if ( currentPoint.script_noteworthy ==
"godoff" )
682 else if ( currentPoint.script_noteworthy ==
"drivepath" )
686 else if ( currentPoint.script_noteworthy ==
"lockpath" )
690 else if ( currentPoint.script_noteworthy ==
"brake" )
692 if (
self.isphysicsvehicle )
694 self SetBrake(
true );
697 self SetSpeed( 0, 60, 60 );
699 else if ( currentPoint.script_noteworthy ==
"resumespeed" )
702 if ( isdefined( currentPoint.script_float ) )
704 accel = currentPoint.script_float;
706 self ResumeSpeed( accel );
710 if ( isdefined( currentPoint.script_crashtypeoverride ) )
712 self.script_crashtypeoverride = currentPoint.script_crashtypeoverride;
715 if ( isdefined( currentPoint.script_badplace ) )
717 self.script_badplace = currentPoint.script_badplace;
720 if ( isdefined( currentPoint.script_team ) )
722 self.team = currentPoint.script_team;
725 if ( isdefined( currentPoint.script_turningdir ) )
727 self notify(
"turning", currentPoint.script_turningdir );
730 if ( isdefined( currentPoint.script_deathroll ) )
732 if ( currentPoint.script_deathroll == 0 )
742 if ( isdefined( currentPoint.script_exploder ) )
747 if ( isdefined( currentPoint.script_flag_set ) )
749 if ( isdefined(
self.vehicle_flags ) )
751 self.vehicle_flags[ currentPoint.script_flag_set ] =
true;
754 self notify(
"vehicle_flag_arrived", currentPoint.script_flag_set );
755 level
flag::set( currentPoint.script_flag_set );
758 if ( isdefined( currentPoint.script_flag_clear ) )
760 if ( isdefined(
self.vehicle_flags ) )
762 self.vehicle_flags[ currentPoint.script_flag_clear ] =
false;
768 if (
IS_HELICOPTER(
self ) && isdefined(
self.drivepath ) &&
self.drivepath == 1 )
773 self.attachedpath =
self.nextNode;
774 self DrivePath(
self.attachedpath );
785 if ( isdefined( currentPoint.script_wait ) )
791 if ( isdefined( currentPoint.script_waittill ) )
797 if( isdefined( currentPoint.script_flag_wait ) )
799 if ( !isdefined(
self.vehicle_flags ) )
801 self.vehicle_flags = [];
804 self.vehicle_flags[ currentPoint.script_flag_wait ] =
true;
805 self notify(
"vehicle_flag_arrived", currentPoint.script_flag_wait );
812 if ( !level
flag::get( currentPoint.script_flag_wait ) )
821 if ( isdefined(
self.set_lookat_point ) )
823 self.set_lookat_point = undefined;
824 self clearLookAtEnt();
827 if ( isdefined( currentPoint.script_lights_on ) )
829 if ( currentPoint.script_lights_on )
839 if ( isdefined( currentPoint.script_stopnode ) )
844 if ( isdefined(
self.switchNode ) )
846 if ( currentPoint ==
self.switchNode )
848 self.switchNode = undefined;
853 if ( !isdefined( currentPoint.target ) )
862 self notify(
"reached_dynamic_path_end" );
864 if ( isdefined(
self.script_delete ) )
872 if ( !
IS_TRUE(
self.vehicle_paused ) )
874 if (
self.isphysicsvehicle )
876 self SetBrake(
true );
884 self SetVehGoalPos(
self.origin,
true );
888 self SetSpeed( 0, 100, 100 );
893 self SetSpeed( 0, 35, 35 );
896 self.vehicle_paused =
true;
902 if (
IS_TRUE(
self.vehicle_paused ) )
904 if (
self.isphysicsvehicle )
906 self SetBrake(
false );
914 self DrivePath(
self.currentNode );
917 self ResumeSpeed( 100 );
921 self ResumeSpeed( 35 );
924 self.vehicle_paused = undefined;
940 if( IsString( path_start ) )
942 path_start = GetVehicleNode( path_start, str_key );
945 if( !isdefined( path_start ) )
947 if( isdefined(
self.targetname ) )
949 AssertMsg(
"Start Node not defined for vehicle: " +
self.targetname );
953 AssertMsg(
"Start Node not defined for vehicle: " +
self.targetname );
960 if( isdefined(
self.hasstarted ) )
962 self.hasstarted = undefined;
965 self.attachedpath = path_start;
970 self AttachPath( path_start );
973 if(
self.disconnectPathOnStop ===
true && !IsSentient(
self) )
978 if (
IS_TRUE(
self.isphysicsvehicle))
989 self ClearVehGoalPos();
1007 for( i = 0; i < vehicleArray.size; i++ )
1009 if (isdefined(vehicleArray[ i ]))
1014 return vehicleArray;
1039 self endon(
"death" );
1040 self endon(
"stop path" );
1042 if(
self.isphysicsvehicle )
1044 self SetBrake(
false);
1047 if( isdefined(
self.script_vehiclestartmove ) )
1049 ArrayRemoveValue( level.vehicle_StartMoveGroup[
self.script_vehiclestartmove ],
self );
1052 if( isdefined(
self.hasstarted ) )
1054 /#println(
"vehicle already moving when triggered with a startmove" );#/
1059 self.hasstarted =
true;
1064 self notify(
"start_vehiclepath" );
1068 self DrivePath(
self.attachedpath );
1079 self waittill(
"reached_end_node" );
1081 if (
self.disconnectPathOnStop ===
true && !IsSentient(
self ) )
1086 if( isdefined(
self.currentnode ) && isdefined(
self.currentnode.script_noteworthy ) &&
self.currentnode.script_noteworthy ==
"deleteme" )
1094 node.gateopen =
true;
1095 node notify(
"gate opened" );
1100 self endon(
"death" );
1101 self.waitingforgate =
true;
1102 self set_speed( 0, 15,
"path gate closed" );
1103 pathspot waittill(
"gate opened" );
1104 self.waitingforgate =
false;
1106 if(
self.health > 0 )
1117 level waittill(
"spawnvehiclegroup" + spawngroup );
1119 spawned_vehicles = [];
1122 for( i = 0; i < level.vehicle_spawners[ spawngroup ].size; i++ )
1125 spawned_vehicles[ spawned_vehicles.size ] =
_vehicle_spawn( level.vehicle_spawners[ spawngroup ][ i ] );
1129 level notify(
"vehiclegroup spawned" + spawngroup, spawned_vehicles );
1147 level waittill(
"vehiclegroup spawned" + group, vehicles );
1154 level notify(
"spawnvehiclegroup" + group );
1159 if ( isdefined( vehicle.script_deathflag ) )
1171 if( !isdefined( vspawner ) || !vspawner.count )
1176 str_targetname = undefined;
1177 if( isdefined( vspawner.targetname ) )
1179 str_targetname = vspawner.targetname +
"_vh";
1184 if( !isdefined( vspawner ) || !vspawner.count )
1189 vehicle = vspawner SpawnFromSpawner( str_targetname,
true );
1192 if ( !isdefined( vehicle ) )
1203 if ( isdefined( vspawner.script_team ) )
1205 vehicle SetTeam( vspawner.script_team );
1208 if ( isdefined( vehicle.lockheliheight ) )
1210 vehicle SetHeliHeightLock( vehicle.lockheliheight );
1213 if( isdefined( vehicle.targetname ) )
1215 level notify(
"new_vehicle_spawned" + vehicle.targetname, vehicle );
1218 if( isdefined( vehicle.script_noteworthy ) )
1220 level notify(
"new_vehicle_spawned" + vehicle.script_noteworthy, vehicle );
1223 if( isdefined(vehicle.script_animname))
1225 vehicle.animname = vehicle.script_animname;
1228 if ( isdefined( vehicle.script_animscripted ) )
1230 vehicle.supportsAnimScripted = vehicle.script_animscripted;
1240 vehicle UseAnimTree( #animtree );
1242 if ( isdefined( vehicle.e_dyn_path ) )
1244 vehicle.e_dyn_path LinkTo( vehicle );
1248 vehicle.takedamage = !
IS_TRUE(vehicle.script_godmode);
1250 vehicle.zerospeed =
true;
1252 if( !isdefined( vehicle.modeldummyon ) )
1254 vehicle.modeldummyon =
false;
1257 if (
IS_TRUE( vehicle.isphysicsvehicle ) )
1259 if (
IS_TRUE( vehicle.script_brake ) )
1261 vehicle SetBrake(
true );
1265 type = vehicle.vehicletype;
1273 vehicle.getoutrig = [];
1274 if( isdefined( level.vehicle_attachedmodels ) && isdefined( level.vehicle_attachedmodels[ type ] ) )
1276 rigs = level.vehicle_attachedmodels[ type ];
1277 strings = getarraykeys( rigs );
1278 for( i = 0; i < strings.size; i++ )
1280 vehicle.getoutrig[ strings[ i ] ] = undefined;
1281 vehicle.getoutriganimating[ strings[ i ] ] =
false;
1286 if( isdefined(
self.script_badplace ) )
1291 if ( isdefined( vehicle.scriptbundlesettings ) )
1295 if ( isdefined( settings ) && isdefined( settings.lightgroups_numGroups ) )
1297 if ( settings.lightgroups_numGroups >= 1 && settings.lightgroups_1_always_on ===
true )
1301 if ( settings.lightgroups_numGroups >= 2 && settings.lightgroups_2_always_on ===
true )
1305 if ( settings.lightgroups_numGroups >= 3 && settings.lightgroups_3_always_on ===
true )
1309 if ( settings.lightgroups_numGroups >= 4 && settings.lightgroups_4_always_on ===
true )
1326 if( isdefined( vehicle.script_physicsjolt ) && vehicle.script_physicsjolt )
1336 vehicle.disconnectPathOnStop = undefined;
1341 vehicle.disconnectPathOnStop =
self.script_disconnectpaths;
1344 vehicle.disconnectPathDetail =
self.script_disconnectpath_detail;
1345 if ( !isdefined( vehicle.disconnectPathDetail ) )
1347 vehicle.disconnectPathDetail = 0;
1356 if ( !isdefined( vehicle.script_nonmovingvehicle ) )
1358 if ( isdefined( vehicle.target ) )
1360 path_start = GetVehicleNode( vehicle.target,
"targetname" );
1361 if ( !isdefined( path_start ) )
1363 path_start = GetEnt(vehicle.target,
"targetname" );
1364 if ( !isdefined( path_start ) )
1366 path_start =
struct::get( vehicle.target,
"targetname" );
1371 if ( isdefined( path_start ) && vehicle.vehicletype !=
"inc_base_jump_spotlight" )
1377 if ( isdefined( vehicle.script_vehicleattackgroup ) )
1379 vehicle thread attack_group_think();
1385 if(!level.clientscripts)
1396 if ( isdefined( vehicle.script_targetset ) && vehicle.script_targetset == 1 )
1398 offset = ( 0, 0, 0 );
1399 if ( isdefined( vehicle.script_targetoffset ) )
1401 offset = vehicle.script_targetoffset;
1404 Target_Set( vehicle, offset );
1407 if (
IS_TRUE( vehicle.script_vehicleavoidance ) )
1409 vehicle SetVehicleAvoidance(
true );
1414 if( isdefined( level.vehicleSpawnCallbackThread ) )
1416 level thread [[ level.vehicleSpawnCallbackThread ]]( vehicle );
1422 if ( !isdefined(
self.getoutrig ) )
1424 if ( !
self.getoutrig.size )
1426 keys = GetArrayKeys(
self.getoutrig );
1427 for ( i = 0; i < keys.size; i++ )
1429 self.getoutrig[ keys[ i ] ] Unlink();
1435 if ( !isdefined( veh ) )
1440 if (
IS_TRUE(
self.script_enable_turret0 ) )
1445 if (
IS_TRUE(
self.script_enable_turret1 ) )
1450 if (
IS_TRUE(
self.script_enable_turret2 ) )
1455 if (
IS_TRUE(
self.script_enable_turret3 ) )
1460 if (
IS_TRUE(
self.script_enable_turret4 ) )
1465 if ( isdefined(
self.script_enable_turret0 ) && !
self.script_enable_turret0 )
1470 if ( isdefined(
self.script_enable_turret1 ) && !
self.script_enable_turret1 )
1475 if ( isdefined(
self.script_enable_turret2 ) && !
self.script_enable_turret2 )
1480 if ( isdefined(
self.script_enable_turret3 ) && !
self.script_enable_turret3 )
1485 if ( isdefined(
self.script_enable_turret4 ) && !
self.script_enable_turret4 )
1494 self notify(
"kill_disconnect_paths_forever" );
1495 self.disconnectPathOnStop =
false;
1501 if( IsPathfinder(
self) )
1503 self.disconnectPathOnStop =
false;
1507 if ( isdefined(
self.script_disconnectpaths ) && !
self.script_disconnectpaths )
1509 self.disconnectPathOnStop =
false;
1513 self endon(
"death" );
1514 self endon(
"kill_disconnect_paths_forever" );
1519 while ( isdefined(
self ) )
1521 if ( LengthSquared(
self.velocity ) <
SQR( threshold ) )
1523 if (
self.disconnectPathOnStop ===
true )
1526 self notify(
"speed_zero_path_disconnect" );
1529 while( LengthSquared(
self.velocity ) <
SQR( threshold ) )
1537 while( LengthSquared(
self.velocity ) >=
SQR( threshold ) )
1579 if(
self getspeedmph() == 0 && speed == 0 )
1587 self setspeed( speed, rate );
1593 self notify(
"new debug_vehiclesetspeed" );
1594 self endon(
"new debug_vehiclesetspeed" );
1595 self endon(
"resuming speed" );
1596 self endon(
"death" );
1599 while( GetDvarString(
"debug_vehiclesetspeed" ) !=
"off" )
1601 print3d(
self.origin + ( 0, 0, 192 ),
"vehicle setspeed: " + msg, ( 1, 1, 1 ), 1, 3 );
1611 self endon(
"death" );
1613 type =
"resumespeed";
1614 if( !isdefined(
self.resumemsgs ) )
1616 self.resumemsgs = [];
1618 if( isdefined(
self.waitingforgate ) &&
self.waitingforgate )
1623 if( isdefined(
self.attacking ) &&
self.attacking )
1625 fSetspeed =
self.attackspeed;
1629 self.zerospeed =
false;
1630 if( fSetspeed == 0 )
1632 self.zerospeed =
true;
1634 if( type ==
"resumespeed" )
1636 self resumespeed( rate );
1638 else if( type ==
"setspeed" )
1640 self set_speed( fSetspeed, 15,
"resume setspeed from attack" );
1642 self notify(
"resuming speed" );
1648 self notify(
"newresumespeedmsag" );
1649 self endon(
"newresumespeedmsag" );
1650 self endon(
"death" );
1651 while( gettime() <
timer && isdefined(
self.resumemsgs ) )
1653 if(
self.resumemsgs.size > 6 )
1655 start =
self.resumemsgs.size - 5;
1661 for( i = start; i <
self.resumemsgs.size; i++ )
1664 /#print3d(
self.origin + ( 0, 0, position ),
"resuming speed: " +
self.resumemsgs[ i ], ( 0, 1, 0 ), 1, 3 );#/
1672 self.takedamage =
false;
1677 self.takedamage =
true;
1682 animtime =
self getanimtime( animation );
1683 animlength = getanimlength( animation );
1688 return self getanimtime( animation ) / getanimlength( animation );
1693 prevnode = [[ get_func ]]( pathnode.targetname );
1694 assert( isdefined( prevnode ),
"detour can't be on start node" );
1695 prevnode.detoured = 0;
1725 if( !isdefined(
array[ firstelem ] ) )
1727 array[ firstelem ] = [];
1729 array[ firstelem ][
array[ firstelem ].size ] = newelem;
1735 return isdefined( pathnode.classname ) && pathnode.classname ==
"script_origin";
1741 processtrigger =
false;
1746 if( isdefined(
self.script_crashtype ) )
1748 level.vehicle_crashpaths[ level.vehicle_crashpaths.size ] =
self;
1751 level.vehicle_startnodes[ level.vehicle_startnodes.size ] =
self;
1754 if( isdefined(
self.script_vehicledetour ) && isdefined(
self.targetname ) )
1756 get_func = undefined;
1758 if( isdefined( get_from_entity(
self.targetname ) ) )
1760 get_func =&get_from_entity_target;
1762 if( isdefined( get_from_spawnstruct(
self.targetname ) ) )
1764 get_func =&get_from_spawnstruct_target;
1767 if( isdefined( get_func ) )
1770 processtrigger =
true;
1777 level.vehicle_detourpaths =
array_2d_add( level.vehicle_detourpaths,
self.script_vehicledetour,
self );
1779 if( level.vehicle_detourpaths[
self.script_vehicledetour ].size > 2 )
1781 println(
"more than two script_vehicledetour grouped in group number: ",
self.script_vehicledetour );
1787 if( isdefined(
self.script_gatetrigger ) )
1789 level.vehicle_gatetrigger =
array_2d_add( level.vehicle_gatetrigger,
self.script_gatetrigger,
self );
1790 self.gateopen =
false;
1794 if ( isdefined(
self.script_flag_set ) )
1796 if ( !isdefined(level.flag) || !isdefined( level.flag[
self.script_flag_set ] ) )
1803 if ( isdefined(
self.script_flag_clear ) )
1820 if (isdefined(
self.script_VehicleSpawngroup )
1821 || isdefined(
self.script_VehicleStartMove )
1822 || isdefined(
self.script_gatetrigger )
1823 || isdefined(
self.script_Vehiclegroupdelete ))
1825 processtrigger =
true;
1828 if( processtrigger )
1845 level.vehicle_processtriggers = [];
1848 triggers = ArrayCombine( getallvehiclenodes(), getentarray(
"script_origin",
"classname" ),
true,
false );
1849 triggers = ArrayCombine( triggers, level.struct,
true,
false );
1857 a_nodes = GetAllVehicleNodes();
1858 foreach ( node
in a_nodes )
1860 if ( isdefined( node.script_flag_set ) )
1872 if ( !isdefined( node.targetname ) )
1877 return isdefined(
struct::get( node.targetname,
"targetname" ) );
1885 foreach ( spawner
in a_veh_spawners )
1887 if ( isdefined( spawner.script_vehiclespawngroup ) )
1889 ARRAY_ADD( spawnvehicles[ spawner.script_vehiclespawngroup ], spawner );
1891 addgroup[ 0 ] = spawner.script_vehiclespawngroup;
1892 groups = ArrayCombine( groups, addgroup,
false,
false );
1898 foreach ( spawngroup
in groups )
1900 a_veh_spawners = spawnvehicles[ spawngroup ];
1902 level.vehicle_spawners[ spawngroup ] = [];
1904 foreach ( sp
in a_veh_spawners )
1914 ARRAY_ADD( level.vehicle_spawners[ spawngroup ], sp );
1923 if (isdefined(
self.destructibledef))
1925 self.health = 99999;
1929 type =
self.vehicletype;
1931 if( isdefined(
self.script_startinghealth ) )
1933 self.health =
self.script_startinghealth;
1937 if(
self.healthdefault == -1 )
1943 self.health =
self.healthdefault;
1965 if( !isdefined(
self.script_cheap ) )
1970 if( !
self.script_cheap )
1996 eModel = get_dummy();
1997 effectorigin =
sys::spawn(
"script_origin", eModel.origin );
1999 self endon(
"fire_extinguish" );
2003 playfx( effect, effectorigin.origin, effectorigin.upvec );
2010 effectorigin.angles =
self gettagangles( tag );
2011 effectorigin.origin =
self gettagorigin( tag );
2012 effectorigin.forwardvec = anglestoforward( effectorigin.angles );
2013 effectorigin.upvec = anglestoup( effectorigin.angles );
2014 while( isdefined(
self ) &&
self.classname ==
"script_vehicle" &&
self getspeedmph() > 0 )
2016 eModel = get_dummy();
2017 effectorigin.angles = eModel gettagangles( tag );
2018 effectorigin.origin = eModel gettagorigin( tag );
2019 effectorigin.forwardvec = anglestoforward( effectorigin.angles );
2020 effectorigin.upvec = anglestoup( effectorigin.angles );
2028 if( GetDvarString(
"debug_vehicleresume" ) ==
"" )
2030 SetDvar(
"debug_vehicleresume",
"off" );
2032 if( GetDvarString(
"debug_vehiclesetspeed" ) ==
"" )
2034 SetDvar(
"debug_vehiclesetspeed",
"off" );
2041 level.vehicle_ResumeSpeed = 5;
2042 level.vehicle_DeleteGroup = [];
2043 level.vehicle_SpawnGroup = [];
2044 level.vehicle_StartMoveGroup = [];
2045 level.vehicle_DeathSwitch = [];
2046 level.vehicle_gatetrigger = [];
2047 level.vehicle_crashpaths = [];
2048 level.vehicle_link = [];
2049 level.vehicle_detourpaths = [];
2051 level.vehicle_startnodes = [];
2052 level.vehicle_spawners = [];
2053 level.a_vehicle_types = [];
2054 level.a_vehicle_targetnames = [];
2057 level.vehicle_walkercount = [];
2059 level.helicopter_crash_locations = getentarray(
"helicopter_crash_location",
"targetname" );
2061 level.playervehicle =
sys::Spawn(
"script_origin", ( 0, 0, 0 ) );
2062 level.playervehiclenone = level.playervehicle;
2064 if( !isdefined( level.vehicle_death_thread ) )
2066 level.vehicle_death_thread = [];
2068 if( !isdefined( level.vehicle_DriveIdle ) )
2070 level.vehicle_DriveIdle = [];
2072 if( !isdefined( level.vehicle_DriveIdle_r ) )
2074 level.vehicle_DriveIdle_r = [];
2076 if( !isdefined( level.attack_origin_condition_threadd ) )
2078 level.attack_origin_condition_threadd = [];
2080 if( !isdefined( level.vehiclefireanim ) )
2082 level.vehiclefireanim = [];
2084 if( !isdefined( level.vehiclefireanim_settle ) )
2086 level.vehiclefireanim_settle = [];
2088 if( !isdefined( level.vehicle_hasname ) )
2090 level.vehicle_hasname = [];
2092 if( !isdefined( level.vehicle_turret_requiresrider ) )
2094 level.vehicle_turret_requiresrider = [];
2096 if( !isdefined( level.vehicle_isStationary ) )
2098 level.vehicle_isStationary = [];
2100 if( !isdefined( level.vehicle_compassicon ) )
2102 level.vehicle_compassicon = [];
2104 if( !isdefined( level.vehicle_unloadgroups ) )
2106 level.vehicle_unloadgroups = [];
2112 if( !isdefined( level.vehicle_unloadwhenattacked ) )
2114 level.vehicle_unloadwhenattacked = [];
2116 if( !isdefined( level.vehicle_deckdust ) )
2118 level.vehicle_deckdust = [];
2120 if( !isdefined( level.vehicle_types ) )
2122 level.vehicle_types = [];
2124 if( !isdefined( level.vehicle_compass_types ) )
2126 level.vehicle_compass_types = [];
2128 if( !isdefined( level.vehicle_bulletshield ) )
2130 level.vehicle_bulletshield = [];
2132 if( !isdefined( level.vehicle_death_badplace ) )
2134 level.vehicle_death_badplace = [];
2144 if( ( isdefined( attacker ) ) && isdefined( attacker.team ) && ( isdefined(
self.team ) ) && ( attacker.team ==
self.team ) )
2156 if ( isdefined(
self.team ) &&
self.team ==
"allies" && isdefined( attacker ) && isdefined(level.player) && attacker == level.player )
2160 else if( isai( attacker ) && attacker.team ==
self.team )
2172 if ( !isdefined(
self.script_bulletshield ) )
2177 type = tolower( type );
2179 if ( ! isdefined( type ) || ! issubstr( type,
"bullet" ) )
2184 if (
self.script_bulletshield )
2196 self.friendlyfire_shield =
true;
2198 if ( isdefined( level.vehicle_bulletshield[
self.vehicletype ] ) && !isdefined(
self.script_bulletshield ) )
2200 self.script_bulletshield = level.vehicle_bulletshield[
self.vehicletype ];
2206 if( !isdefined(
self.friendlyfire_shield) || !
self.friendlyfire_shield )
2212 ( ! isdefined( attacker ) &&
self.team !=
"neutral" ) ||
2215 is_destructible() ||
2251 self endon(
"kill_badplace_forever" );
2252 self endon(
"death" );
2253 self endon(
"delete" );
2255 if( isdefined( level.custombadplacethread ) )
2257 self thread [[ level.custombadplacethread ]]();
2261 hasturret = isdefined(
self.turretweapon ) &&
self.turretweapon != level.weaponNone;
2262 const bp_duration = .5;
2263 const bp_height = 300;
2264 const bp_angle_left = 17;
2265 const bp_angle_right = 17;
2269 if( !
self.script_badplace )
2272 while ( !
self.script_badplace )
2278 speed =
self GetSpeedMPH();
2289 else if ( ( speed > 5 ) && ( speed < 8 ) )
2298 if ( isdefined(
self.BadPlaceModifier ) )
2300 bp_radius = ( bp_radius *
self.BadPlaceModifier );
2303 v_turret_angles =
self GetTagAngles(
"tag_turret" );
2305 if ( hasturret && isdefined( v_turret_angles ) )
2307 bp_direction = AnglesToForward( v_turret_angles );
2311 bp_direction = AnglesToForward(
self.angles );
2317 wait bp_duration + .05;
2344 path_start = GetVehicleNode( target,
"targetname" );
2346 if ( !isdefined( path_start ) )
2348 path_start = GetEnt( target,
"targetname" );
2353 PrintLn(
"helicopter node targetname: " + path_start.targetname );
2354 PrintLn(
"vehicletype: " +
self.vehicletype );
2356 AssertMsg(
"helicopter on vehicle path( see console for info )" );
2359 if ( !isdefined( path_start ) )
2370 if ( isdefined(
self.currentnode.target ) )
2375 if ( isdefined( node ) )
2377 self ResumeSpeed( 35 );
2384 self setNearGoalNotifyDist( 2 );
2385 self sethoverparams( 0, 0, 10 );
2386 self cleargoalyaw();
2389 self waittill(
"goal" );
2394 if(
self.health <= 0 )
2398 if( isdefined(
self.originheightoffset ) )
2400 origin += ( 0, 0,
self.originheightoffset );
2402 self setvehgoalpos( origin, bStop );
2407 if( !isdefined( height ) )
2411 dest =
self.origin + ( 0, 0, height );
2412 self setNearGoalNotifyDist( 10 );
2414 self waittill(
"goal" );
2421 const stabletime = 400;
2422 timer = gettime() + stabletime;
2423 while( isdefined(
self ) )
2425 if(
self.angles[ 0 ] > offset ||
self.angles [ 0 ] < ( - 1 * offset ) )
2427 timer = gettime() + stabletime;
2429 if(
self.angles[ 2 ] > offset ||
self.angles [ 2 ] < ( - 1 * offset ) )
2431 timer = gettime() + stabletime;
2445 if( isdefined(
self.custom_unload_function ) )
2447 [[
self.custom_unload_function ]]();
2474 self SetHoverParams( 0, 0, 10 );
2480 unload( node.script_unload );
2491 return ( isdefined(
self.script_unload ) && (
self.script_unload !=
"none" ) );
2498 if( isdefined(
self.custom_unload_function ) )
2500 self thread [[
self.custom_unload_function ]]();
2503 self SetHoverParams( 0, 0, 10 );
2505 goal =
self.nextNode.origin;
2508 start =
self.nextNode.origin;
2509 end = start - ( 0, 0, 10000 );
2512 trace = BulletTrace( start,
end,
false, undefined,
true );
2513 if (
trace[
"fraction"] <= 1 )
2515 goal = (
trace[
"position"][0],
trace[
"position"][1],
trace[
"position"][2] +
self.fastropeoffset );
2519 drop_offset_tag =
"tag_fastrope_ri";
2522 if( isdefined(
self.drop_offset_tag ) )
2523 drop_offset_tag =
self.drop_offset_tag;
2526 drop_offset =
self GetTagOrigin(
"tag_origin" ) -
self GetTagOrigin( drop_offset_tag );
2529 goal += ( drop_offset[0], drop_offset[1], 0 );
2531 self SetVehGoalPos( goal, 1 );
2532 self waittill(
"goal" );
2533 self notify(
"unload",
self.nextNode.script_unload );
2535 self waittill(
"unloaded" );
2540 self.attachedpath = undefined;
2541 self notify(
"newpath" );
2544 self setvehgoalpos(
self.origin + ( 0, 0, 4 ), 1 );
2549 level.vehicle_targetname_array = [];
2551 vehicles = getentarray(
"script_vehicle",
"classname" );
2553 n_highest_group = 0;
2555 foreach ( vh
in vehicles )
2557 if ( isdefined( vh.script_vehicleSpawnGroup ) )
2559 n_spawn_group = Int( vh.script_vehicleSpawnGroup );
2561 if ( n_spawn_group > n_highest_group )
2563 n_highest_group = n_spawn_group;
2568 for( i = 0; i < vehicles.size; i++ )
2570 vehicle = vehicles[ i ];
2572 if ( isdefined( vehicle.targetname ) && IsVehicleSpawner( vehicle ) )
2574 if( !isdefined( vehicle.script_vehicleSpawnGroup ) )
2578 vehicle.script_vehicleSpawnGroup = n_highest_group;
2581 if( !isdefined( level.vehicle_targetname_array[ vehicle.targetname ] ) )
2583 level.vehicle_targetname_array[ vehicle.targetname ] = [];
2586 level.vehicle_targetname_array[ vehicle.targetname ][ vehicle.script_vehicleSpawnGroup ] =
true;
2596 Assert( b_supress_assert || isdefined( level.vehicle_targetname_array[
name ] ),
"No vehicle spawners had targetname " +
name );
2599 if ( isdefined( level.vehicle_targetname_array[
name ] ) )
2605 keys = GetArrayKeys(
array );
2607 foreach ( key
in keys )
2610 vehicles = ArrayCombine( vehicles, vehicle_array,
true,
false );
2621 Assert( b_supress_assert || vehicle_array.size == 1,
"Tried to spawn a vehicle from targetname " +
name +
" but it returned " + vehicle_array.size +
" vehicles, instead of 1" );
2623 if ( vehicle_array.size > 0 )
2625 return vehicle_array[ 0 ];
2633 assert( vehicleArray.size == 1,
"Tried to spawn a vehicle from targetname " +
name +
" but it returned " + vehicleArray.size +
" vehicles, instead of 1" );
2635 vehicleArray[ 0 ] thread
go_path();
2636 return vehicleArray[ 0 ];
2643 for( i = 0; i < vehicleArray.size; i++ )
2645 vehicleArray[ i ] thread
go_path();
2648 return vehicleArray;
2652 function spawn( modelname, targetname, vehicletype, origin, angles, destructibledef )
2654 assert(isdefined(targetname));
2655 assert(isdefined(vehicletype));
2656 assert(isdefined(origin));
2657 assert(isdefined(angles));
2659 return SpawnVehicle( vehicletype, origin, angles, targetname, destructibledef );
2664 self endon(
"death" );
2665 self endon(
"death_finished" );
2666 self endon(
"stop_kicking_up_dust" );
2668 assert( isdefined(
self.vehicletype ) );
2670 const maxHeight = 1200;
2671 const minHeight = 350;
2673 const slowestRepeatWait = 0.15;
2674 const fastestRepeatWait = 0.05;
2676 const numFramesPerTrace = 3;
2677 doTraceThisFrame = numFramesPerTrace;
2679 const defaultRepeatRate = 1.0;
2680 repeatRate = defaultRepeatRate;
2686 if ( isdefined( model ) )
2691 while( isdefined(
self ) )
2693 if( repeatRate <= 0 )
2695 repeatRate = defaultRepeatRate;
2699 if( !isdefined(
self ) )
2704 doTraceThisFrame -- ;
2707 if( doTraceThisFrame <= 0 )
2709 doTraceThisFrame = numFramesPerTrace;
2711 trace = bullettrace( trace_ent.origin, trace_ent.origin - ( 0, 0, 100000 ),
false, trace_ent );
2720 d = distance( trace_ent.origin,
trace[
"position" ] );
2722 repeatRate = ( ( d - minHeight ) / ( maxHeight - minHeight ) ) * ( slowestRepeatWait - fastestRepeatWait ) + fastestRepeatWait;
2725 if( !isdefined(
trace ) )
2730 assert( isdefined( d ) );
2734 repeatRate = defaultRepeatRate;
2738 if( isdefined(
trace[
"entity" ] ) )
2740 repeatRate = defaultRepeatRate;
2744 if( !isdefined(
trace[
"position" ] ) )
2746 repeatRate = defaultRepeatRate;
2750 if( !isdefined(
trace[
"surfacetype" ] ) )
2752 trace[
"surfacetype" ] =
"dirt";
2754 assert( isdefined( level._vehicle_effect[
self.vehicletype ] ),
self.vehicletype +
" vehicle script hasn't run _tradfx properly" );
2755 assert( isdefined( level._vehicle_effect[
self.vehicletype ][
trace[
"surfacetype" ] ] ),
"UNKNOWN SURFACE TYPE: " +
trace[
"surfacetype" ] );
2758 if( level._vehicle_effect[
self.vehicletype ][
trace[
"surfacetype" ] ] != -1 )
2760 playfx( level._vehicle_effect[
self.vehicletype ][
trace[
"surfacetype" ] ],
trace[
"position" ] );
2767 if ( isdefined( fxname ) )
2769 body =
self GetTagOrigin(
"tag_body" );
2770 if ( !isdefined( body ) )
2772 body =
self.origin + (0,0,10);
2775 trace = BulletTrace( body, body - (0,0,2 *
self.radius),
false,
self );
2776 if(
trace[
"fraction"] < 1.0 && !isdefined(
trace[
"entity" ] ) && ( !isdefined(surfaceTypes) || array::contains( surfaceTypes,
trace[
"surfacetype"] ) ) )
2778 pos = 0.5 * (
self.origin +
trace[
"position"] );
2779 up = 0.5 * (
trace[
"normal"] + AnglesToUp(
self.angles ) );
2780 forward = AnglesToForward(
self.angles );
2781 PlayFx( fxname, pos, up, forward );
2788 if( !isdefined( level.vehicle_deckdust[
self.model ] ) )
2792 self endon(
"death" );
2795 self waittill(
"weapon_fired" );
2796 playfxontag( level.vehicle_deckdust[
self.model ],
self,
"tag_engine_exhaust" );
2797 barrel_origin =
self gettagorigin(
"tag_flash" );
2798 ground = physicstrace( barrel_origin, barrel_origin + ( 0, 0, -128 ) );
2799 physicsExplosionSphere( ground, 192, 100, 1 );
2811 if( IsDefined( team ) )
2813 if( team ==
"allies" )
2817 else if( team ==
"axis" )
2857 deathfxtype = ( (
self.died_by_emp === true ) ? 2 : 1 );
2876 assert( special_status >= 0 && special_status <= 3 );
2885 for( i = 0; i < numDynents; i++ )
2887 hidetag = GetStructField(
self.settings,
"servo_gib_tag" + i );
2888 if ( isdefined( hidetag ) )
2890 self HidePart( hidetag,
"",
true );
2903 if ( !isdefined( settings ) )
2908 currentRatio =
math::clamp(
float( currentHealth ) /
float( maxHealth ), 0.0, 1.0 );
2909 afterDamageRatio =
math::clamp(
float( currentHealth -
damage ) /
float( maxHealth ), 0.0, 1.0 );
2910 currentLevel = undefined;
2911 afterDamageLevel = undefined;
2912 switch(
VAL( settings.damagestate_numStates, 0 ) )
2915 if ( settings.damagestate_lv6_ratio >= afterDamageRatio )
2917 afterDamageLevel = 6;
2919 if ( settings.damagestate_lv6_ratio < currentRatio )
2926 if ( settings.damagestate_lv5_ratio >= afterDamageRatio )
2928 afterDamageLevel = 5;
2930 if ( settings.damagestate_lv5_ratio < currentRatio )
2937 if ( settings.damagestate_lv4_ratio >= afterDamageRatio )
2939 afterDamageLevel = 4;
2941 if ( settings.damagestate_lv4_ratio < currentRatio )
2948 if ( settings.damagestate_lv3_ratio >= afterDamageRatio )
2950 afterDamageLevel = 3;
2952 if ( settings.damagestate_lv3_ratio < currentRatio )
2959 if ( settings.damagestate_lv2_ratio >= afterDamageRatio )
2961 afterDamageLevel = 2;
2963 if ( settings.damagestate_lv2_ratio < currentRatio )
2970 if ( settings.damagestate_lv1_ratio >= afterDamageRatio )
2972 afterDamageLevel = 1;
2974 if ( settings.damagestate_lv1_ratio < currentRatio )
2984 if ( !isdefined( currentLevel ) || !isdefined( afterDamageLevel ) )
2989 if ( currentLevel != afterDamageLevel )
2991 return afterDamageLevel;
3002 if ( newDamageLevel > 0 )
3033 if( !isdefined( normalspeed ) )
3037 level.vehicle_DriveIdle[
self.model ] = forward;
3041 level.vehicle_DriveIdle_r[
self.model ] =
reverse;
3043 level.vehicle_DriveIdle_normal_speed[
self.model ] = normalspeed;
3044 if( isdefined( rate ) )
3046 level.vehicle_DriveIdle_animrate[
self.model ] = rate;
3107 function get_from_spawnstruct( target )
3112 function get_from_entity( target )
3114 return getent( target,
"targetname" );
3117 function get_from_spawnstruct_target( target )
3122 function get_from_entity_target( target )
3124 return getent( target,
"target" );
3127 function is_destructible()
3129 return isdefined(
self.destructible_type );
3135 function attack_group_think()
3137 self endon (
"death");
3138 self endon (
"switch group");
3139 self endon (
"killed all targets");
3141 if (isdefined (
self.script_vehicleattackgroupwait))
3143 wait (
self.script_vehicleattackgroupwait);
3149 group = getentarray(
"script_vehicle",
"classname");
3153 for (i = 0; i< group.size; i++)
3156 if( !isdefined( group[i].script_vehiclespawngroup ) )
3161 if (group[i].script_vehiclespawngroup ==
self.script_vehicleattackgroup)
3164 if (group[i].team !=
self.team)
3172 if (valid_targets.size == 0)
3181 current_target = undefined;
3182 if (valid_targets.size != 0)
3184 current_target =
self get_nearest_target(valid_targets);
3189 self notify (
"killed all targets");
3193 if (current_target.health <= 0)
3195 ArrayRemoveValue(valid_targets, current_target);
3201 self setturrettargetent( current_target, (0,0,50) );
3204 if( isdefined(
self.fire_delay_min ) && isdefined(
self.fire_delay_max ) )
3207 if(
self.fire_delay_max <
self.fire_delay_min )
3209 self.fire_delay_max =
self.fire_delay_min;
3212 wait ( randomintrange(
self.fire_delay_min,
self.fire_delay_max) );
3217 wait (randomintrange(4, 6));
3231 function get_nearest_target(valid_targets)
3233 nearest_distsq = 99999999;
3234 nearest = undefined;
3236 for (i = 0; i < valid_targets.size; i++)
3238 if( !isdefined( valid_targets[i] ) )
3242 current_distsq = distancesquared(
self.origin, valid_targets[i].origin );
3243 if (current_distsq < nearest_distsq)
3245 nearest_distsq = current_distsq;
3246 nearest = valid_targets[i];
3256 function debug_vehicle()
3258 self endon(
"death" );
3260 if( GetDvarString(
"debug_vehicle_health" ) ==
"" )
3262 SetDvar(
"debug_vehicle_health",
"0" );
3267 if( GetDvarInt(
"debug_vehicle_health" ) > 0 )
3269 print3d(
self.origin,
"Health: " +
self.health, ( 1, 1, 1 ), 1, 3 );
3277 function get_dummy()
3279 if (
IS_TRUE(
self.modeldummyon ) )
3281 eModel =
self.modeldummy;
3290 function add_main_callback( vehicleType,
main )
3292 if ( !isdefined( level.vehicle_main_callback ) )
3294 level.vehicle_main_callback = [];
3298 if ( isdefined( level.vehicle_main_callback[ vehicleType ] ) )
3300 PrintLn(
"WARNING! Main callback function for vehicle " + vehicleType +
" already exists. Proceeding with override" );
3304 level.vehicle_main_callback[ vehicleType ] =
main;
3307 function vehicle_get_occupant_team()
3309 occupants =
self GetVehOccupants();
3311 if ( occupants.size != 0 )
3314 occupant = occupants[0];
3316 if ( isplayer(occupant) )
3318 return occupant.team;
3403 if ( isdefined( veh ) )
3409 else if ( isdefined( veh.classname ) && ( veh.classname ==
"script_vehicle_corpse" ) )
3447 if(!isdefined(
self.viewlockedentity))
3451 else if(
self.viewlockedentity == vehicle)
3456 if(!isdefined(
self.groundentity))
3460 else if(
self.groundentity == vehicle)
3484 func[
"function" ] =spawn_func;
3485 func[
"param1" ] = param1;
3486 func[
"param2" ] = param2;
3487 func[
"param3" ] = param3;
3488 func[
"param4" ] = param4;
3490 DEFAULT( level.a_vehicle_targetnames, [] );
3492 ARRAY_ADD( level.a_vehicle_targetnames[ veh_targetname ], func );
3511 func[
"function" ] =spawn_func;
3512 func[
"param1" ] = param1;
3513 func[
"param2" ] = param2;
3514 func[
"param3" ] = param3;
3515 func[
"param4" ] = param4;
3517 DEFAULT( level.a_vehicle_types, [] );
3519 ARRAY_ADD( level.a_vehicle_types[ veh_type ], func );
3538 func[
"function" ] =spawn_func;
3539 func[
"param1" ] = param1;
3540 func[
"param2" ] = param2;
3541 func[
"param3" ] = param3;
3542 func[
"param4" ] = param4;
3544 DEFAULT( level.a_vehicle_hijack_targetnames, [] );
3546 ARRAY_ADD( level.a_vehicle_hijack_targetnames[ veh_targetname ], func );
3553 level waittill(
"ClonedEntity", clone );
3555 str_targetname = clone.targetname;
3556 if (isdefined( str_targetname ) && StrEndsWith( str_targetname,
"_ai" ) )
3558 str_targetname = GetSubStr( str_targetname, 0, str_targetname.size - 3 );
3563 if ( isdefined( str_targetname ) && isdefined( level.a_vehicle_hijack_targetnames ) && isdefined( level.a_vehicle_hijack_targetnames[ str_targetname ] ) )
3565 foreach ( func
in level.a_vehicle_hijack_targetnames[ str_targetname ] )
3567 util::single_thread( clone, func[
"function" ], func[
"param1" ], func[
"param2" ], func[
"param3" ], func[
"param4" ] );
3582 self DisconnectPaths( detail_level, move_allowed );
3583 self EnableObstacle(
false );
3594 self ConnectPaths();
3595 self EnableObstacle(
true );
3600 self.target_group = [];
3605 assert( isdefined(
self.target_group ),
"Call init_target_group() first." );
3612 assert( isdefined(
self.target_group ),
"Call init_target_group() first." );
3614 ArrayRemoveValue(
self.target_group, target_ent );
3619 monitored_entity =
self;
3621 monitored_entity endon(
"death" );
3623 assert( isdefined( monitored_entity.target_group ),
"Call init_lock_on_group() first." );
3625 player endon(
"stop_monitor_missile_locked_on_to_me" );
3626 player endon(
"disconnect" );
3627 player endon(
"joined_team" );
3634 player SetVehicleLockedOnByEnt( closest_attacker );
3642 self notify(
"stop_monitor_missile_locked_on_to_me" );
3649 assert( isdefined( monitored_entity.target_group ),
"Call init_lock_on_group() first." );
3652 closest_attacker = undefined;
3653 closest_attacker_dot = -999;
3655 view_origin = player GetPlayerCameraPos();
3656 view_forward = AnglesToForward( player GetPlayerAngles() );
3659 remaining_locked_on_flags = 0;
3660 foreach( target_ent
in monitored_entity.target_group )
3662 if ( isdefined( target_ent ) && isdefined( target_ent.locked_on ) )
3664 remaining_locked_on_flags |= target_ent.locked_on;
3669 for ( i = 0; remaining_locked_on_flags && i < level.players.size; i++ )
3671 attacker = level.players[ i ];
3672 if ( isdefined( attacker ) )
3674 client_flag = ( 1 << attacker getEntityNumber() );
3675 if ( client_flag & remaining_locked_on_flags )
3677 to_attacker = VectorNormalize( attacker.origin - view_origin );
3678 attacker_dot = VectorDot( view_forward, to_attacker );
3680 if ( attacker_dot > closest_attacker_dot )
3682 closest_attacker = attacker;
3683 closest_attacker_dot = attacker_dot;
3686 remaining_locked_on_flags &= ~client_flag;
3691 return closest_attacker;
3696 end_time_ms = GetTime() + duration_ms;
3705 self SetVehicleDrivableDuration( duration_ms );
3706 self SetVehicleDrivableEndTime( end_time_ms );
3711 damage_taken_normalized =
math::clamp( damage_taken / max_health, 0.0, 1.0 );
3712 self SetVehicleDamageMeter( damage_taken_normalized );
3719 self notify(
"stop_monitor_damage_as_occupant" );
3724 player endon(
"disconnect" );
3725 player notify(
"stop_monitor_damage_as_occupant" );
3726 player endon(
"stop_monitor_damage_as_occupant" );
3727 self endon(
"death" );
3729 if( !IsDefined(
self.maxhealth ) )
3731 self.maxhealth =
self.healthdefault;
3739 self waittill(
"damage" );
3749 damageOrigin =
self.origin + (0,0,1);
3750 self finishVehicleRadiusDamage(attacker, attacker, 32000, 32000, 10, 0,
"MOD_EXPLOSIVE", level.weaponNone, damageOrigin, 400, -1, (0,0,1), 0);
3755 if ( !IsAlive(
self ) )
3760 vehicle =
self GetVehicleOccupied();
3762 if ( isdefined( vehicle ) )
3764 seat = vehicle GetOccupantSeat(
self );
3766 if ( isdefined( seat ) && seat == 0 )
3778 allvehicles = GetEntArray(
"script_vehicle",
"classname" );
3782 foreach( veh
in allvehicles )
3784 vehicletypes[ veh.vehicletype ] = veh.model;
3787 if( IsAssetLoaded(
"vehicle",
"civ_pickup_mini" ) )
3789 veh = SpawnVehicle(
"civ_pickup_mini", (0,0,10000), (0,0,0),
"debug_spawn_vehicle" );
3790 vehicletypes[ veh.vehicletype ] = veh.model;
3794 if( IsAssetLoaded(
"vehicle",
"atv" ) )
3796 veh = SpawnVehicle(
"atv", (0,0,10000), (0,0,0),
"debug_spawn_vehicle" );
3797 vehicletypes[ veh.vehicletype ] = veh.model;
3801 if( IsAssetLoaded(
"vehicle",
"prowler_quad" ) )
3803 veh = SpawnVehicle(
"prowler_quad", (0,0,10000), (0,0,0),
"debug_spawn_vehicle" );
3804 vehicletypes[ veh.vehicletype ] = veh.model;
3808 if( IsAssetLoaded(
"vehicle",
"rc_car_racer" ) )
3810 veh = SpawnVehicle(
"rc_car_racer", (0,0,10000), (0,0,0),
"debug_spawn_vehicle" );
3811 vehicletypes[ veh.vehicletype ] = veh.model;
3815 if( IsAssetLoaded(
"vehicle",
"jeep_fav_player" ) )
3817 veh = SpawnVehicle(
"jeep_fav_player", (0,0,10000), (0,0,0),
"debug_spawn_vehicle" );
3818 vehicletypes[ veh.vehicletype ] = veh.model;
3822 types = getArrayKeys( vehicletypes );
3824 if( types.size == 0 )
3831 if( GetDvarInt(
"debug_vehicle_spawn" ) > 0 )
3833 player = GetPlayers()[0];
3835 dynamic_spawn_hud = NewClientHudElem( player );
3836 dynamic_spawn_hud.alignX =
"left";
3837 dynamic_spawn_hud.x = 20;
3838 dynamic_spawn_hud.y = 395;
3839 dynamic_spawn_hud.fontscale = 2;
3841 dynamic_spawn_dummy_model =
sys::Spawn(
"script_model", (0,0,0) );
3843 const waittime = 0.3;
3845 while( GetDvarInt(
"debug_vehicle_spawn" ) > 0 )
3847 origin = player.origin + AnglesToForward( player getPlayerAngles() ) * 270.0;
3850 if( player UseButtonPressed() )
3852 dynamic_spawn_dummy_model Hide();
3853 vehicle = SpawnVehicle( types[type_index], origin, player.angles,
"debug_spawn_vehicle" );
3854 vehicle MakeVehicleUsable();
3856 if( GetDvarInt(
"debug_vehicle_spawn" ) == 1 )
3858 SetDvar(
"debug_vehicle_spawn",
"0" );
3863 if( player buttonpressed(
"DPAD_RIGHT") )
3865 dynamic_spawn_dummy_model Hide();
3867 if( type_index >= types.size )
3871 if( player buttonpressed(
"DPAD_LEFT") )
3873 dynamic_spawn_dummy_model Hide();
3875 if( type_index < 0 )
3876 type_index = types.size - 1;
3879 type = types[type_index];
3880 dynamic_spawn_hud settext(
"Press X to spawn vehicle " + type );
3882 dynamic_spawn_dummy_model SetModel( vehicletypes[type] );
3883 dynamic_spawn_dummy_model Show();
3884 dynamic_spawn_dummy_model NotSolid();
3885 dynamic_spawn_dummy_model.origin = origin;
3886 dynamic_spawn_dummy_model.angles = player.angles;
3891 dynamic_spawn_dummy_model
delete();
3906 level
flag::set_val(
"debug_vehicle_splines", GetDvarInt(
"g_vehicleDrawSplines" ) );
3917 foreach ( nd
in GetAllVehicleNodes() )
3928 self.n_debug_display_count = 0;
3935 if ( isdefined(
self.script_notify ) )
3940 if (
IS_TRUE(
self.script_delete ) )
3948 self.n_debug_display_count++;
3949 Print3D(
self.origin - ( 0, 0,
self.n_debug_display_count * 20 ), str_info,
BLUE, 1, 1 );