1 #using scripts\codescripts\struct;
3 #using scripts\shared\ai_shared;
4 #using scripts\shared\animation_shared;
5 #using scripts\shared\array_shared;
6 #using scripts\shared\callbacks_shared;
7 #using scripts\shared\clientfield_shared;
8 #using scripts\shared\colors_shared;
9 #using scripts\shared\flag_shared;
10 #using scripts\shared\flagsys_shared;
11 #using scripts\shared\spawner_shared;
12 #using scripts\shared\system_shared;
13 #using scripts\shared\trigger_shared;
14 #using scripts\shared\util_shared;
15 #using scripts\shared\ai\systems\gib;
16 #using scripts\shared\hostmigration_shared;
18 #insert scripts\shared\ai\systems\gib.gsh;
19 #insert scripts\shared\shared.gsh;
20 #insert scripts\shared\version.gsh;
21 #insert scripts\shared\archetype_shared\archetype_shared.gsh;
23 #using_animtree( "generic" );
37 level.vehiclerider_groups = [];
38 level.vehiclerider_groups[
"all" ] =
"all";
39 level.vehiclerider_groups[
"driver" ] =
"driver";
40 level.vehiclerider_groups[
"passengers" ] =
"passenger";
41 level.vehiclerider_groups[
"crew" ] =
"crew";
42 level.vehiclerider_groups[
"gunners" ] =
"gunner";
44 a_registered_fields = [];
47 foreach (
object in bundle.objects )
49 if ( IsString(
object.VehicleEnterAnim ) )
51 array::add( a_registered_fields,
object.position +
"_enter",
false );
54 if ( IsString(
object.VehicleExitAnim ) )
56 array::add( a_registered_fields,
object.position +
"_exit",
false );
59 if ( IsString(
object.VehicleRiderDeathAnim ) )
61 array::add( a_registered_fields,
object.position +
"_death",
false );
66 foreach ( str_clientfield
in a_registered_fields )
72 level.vehiclerider_use_index = [];
73 level.vehiclerider_use_index[
"driver" ] = 0;
76 const MAX_USE_INDEX = 4;
77 for ( i = 1; i <= MAX_USE_INDEX; i++ )
79 level.vehiclerider_use_index[
"gunner" + i ] = i;
83 const MAX_PASSENGER_INDEX = 10;
85 for ( i = MAX_USE_INDEX + 1; i <= MAX_PASSENGER_INDEX; i++ )
87 level.vehiclerider_use_index[
"passenger" + passengerIndex ] = i;
95 DEFAULT( s.HighExitLandHeight, 32 );
105 return level.vehiclerider_use_index[ str_position ];
115 if ( IsVehicle(
self ) )
132 ArrayRemoveValue( vh.riders,
self );
140 vh endon( str_pos +
"occupied" );
142 self waittill(
"death" );
152 if( seat_index <= 4 )
154 if(
self IsVehicleSeatOccupied( seat_index ) )
160 return s_rider.position;
170 if ( isdefined(
self.script_vehicleride ) )
173 a_spawners = GetSpawnerArray(
self.script_vehicleride,
"script_vehicleride" );
174 foreach ( sp
in a_spawners )
179 if ( isdefined( ai_rider ) )
181 ai_rider
get_in(
self, ai_rider.script_startingposition,
true );
207 foreach ( s_rider
in bundle.objects )
209 if ( s_rider.position == str_pos )
226 function get_in( vh, str_pos, b_teleport =
false )
228 self endon(
"death" );
231 if ( !isdefined( str_pos ) )
236 Assert( isdefined( str_pos ),
"No unoccupied seats for vehicle rider." );
238 if( !isdefined( str_pos ) )
244 if ( !isdefined( vh.ignore_seat_check ) || !vh.ignore_seat_check )
246 seat_index = level.vehiclerider_use_index[ str_pos ];
247 if( seat_index <= 4 )
249 seat_available = !(vh IsVehicleSeatOccupied( seat_index ) );
250 Assert( seat_available,
"This seat is already occupied." );
276 animation::reach(
self.rider_info.EnterAnim,
self.vehicle,
self.rider_info.AlignTag );
279 if ( isdefined(
self.rider_info.VehicleEnterAnim ) )
282 self SetAnim(
self.rider_info.VehicleEnterAnim, 1, 0, 1 );
285 self animation::play(
self.rider_info.EnterAnim,
self.vehicle,
self.rider_info.AlignTag );
288 if ( isdefined(
self.rider_info) && isdefined(
self.rider_info.RideAnim ) )
291 self thread
animation::play(
self.rider_info.RideAnim,
self.vehicle,
self.rider_info.AlignTag, 1, 0.2, 0.2, 0, 0,
false,
false );
293 else if ( !isdefined( level.vehiclerider_use_index[ str_pos ] ) )
295 assert(
"Rider is missing ride animation for seat: " + str_pos );
297 else if ( isdefined(
self.rider_info) )
301 v_tag_pos = vh GetTagOrigin(
self.rider_info.aligntag );
302 v_tag_ang = vh GetTagAngles(
self.rider_info.aligntag );
303 if (isdefined(v_tag_pos))
304 self ForceTeleport( v_tag_pos, v_tag_ang );
308 /# ErrorMsg(
"Missing rider_info" ); #/
311 if ( IsActor(
self ) )
314 self PathMode(
"dont move" );
317 self.disableAmmoDrop =
true;
318 self.dontDropWeapon =
true;
323 if ( isdefined( level.vehiclerider_use_index[ str_pos ] ) )
326 if ( !isdefined(
self.vehicle.ignore_seat_check ) || !
self.vehicle.ignore_seat_check )
328 seat_index = level.vehiclerider_use_index[ str_pos ];
329 if( seat_index <= 4 )
331 if(
self.vehicle IsVehicleSeatOccupied( seat_index ) )
339 self.vehicle UseVehicle(
self, level.vehiclerider_use_index[ str_pos ] );
349 self endon(
"exiting_vehicle" );
350 self.vehicle endon(
"death" );
352 if ( IsDefined(
self.rider_info.RideDeathAnim ) )
357 self waittill(
"death" );
359 if ( !IsDefined(
self ) )
364 if ( IsDefined(
self.vehicle ) && IsDefined(
self.rider_info ) && IsDefined(
self.rider_info.VehicleRiderDeathAnim ) )
367 self.vehicle SetAnimKnobRestart(
self.rider_info.VehicleRiderDeathAnim, 1, 0, 1 );
375 if ( IsDefined( entity ) )
383 if( IsDefined( entity ) )
387 if ( entity IsPlayingAnimScripted() )
389 entity StopAnimScripted();
392 if ( GetDvarInt(
"tu1_vehicleRidersInvincibility", 1 ) )
417 if ( IsDefined(
self.riders ) )
419 foreach ( rider
in self.riders )
433 if ( AnglesToUp( vh.angles )[2] < 0.3 )
440 if( seat_index <= 4 )
442 if( vh IsVehicleSeatOccupied( seat_index ) )
459 v_tag_org = vh GetTagOrigin( rider_info.AlignTag );
460 v_tag_ang = vh GetTagAngles( rider_info.AlignTag );
462 v_enter_pos = GetStartOrigin( v_tag_org, v_tag_ang, rider_info.EnterAnim );
464 if ( !
self FindPath(
self.origin, v_enter_pos ) )
472 #define GROUND_HEIGHT 5
484 self endon(
"death" );
486 self notify(
"exiting_vehicle" );
488 Assert( IsAlive(
self ),
"Dead or undefined vehicle rider." );
489 Assert( isdefined(
self.vehicle ),
"AI is not on vehicle." );
501 n_hover_height = bundle.LowExitHeight;
504 if ( isdefined(
self.rider_info.VehicleExitAnim ) )
507 self.vehicle SetAnim(
self.rider_info.VehicleExitAnim, 1, 0, 1 );
527 default: AssertMsg(
"Invalid mode for vehicle unload." );
530 if ( IsActor(
self ) )
533 self PathMode(
"move allowed" );
536 self.disableAmmoDrop =
false;
537 self.dontDropWeapon =
false;
540 if( isdefined(
self.vehicle ) )
546 if ( isdefined( level.vehiclerider_use_index[
self.rider_info.position ] ) && (
self flagsys::get(
"in_vehicle" )) )
548 self.vehicle UseVehicle(
self, level.vehiclerider_use_index[
self.rider_info.position ] );
554 self.vehicle = undefined;
555 self.rider_info = undefined;
560 self notify(
"exited_vehicle" );
569 else if ( !isdefined(
self.target ) )
571 self SetGoal(
self.origin );
584 function unload( str_group =
"all", str_mode, remove_rider_before_unloading, remove_riders_wait_time )
586 self notify(
"unload", str_group );
588 Assert( isdefined( level.vehiclerider_groups[ str_group ] ), str_group +
" is not a valid unload group." );
590 str_group = level.vehiclerider_groups[ str_group ];
593 foreach ( ai_rider
in self.riders )
595 if ( ( str_group ==
"all" ) || IsSubStr( ai_rider.rider_info.position, str_group ) )
597 ai_rider thread
get_out( str_mode );
602 if ( a_ai_unloaded.size > 0 )
604 if ( remove_rider_before_unloading ===
true )
609 array::flagsys_wait_clear( a_ai_unloaded,
"in_vehicle",
VAL(
self.unloadTimeout, 4 ) );
610 self notify(
"unload", a_ai_unloaded );
618 if ( isdefined( a_riders_to_remove ) )
620 foreach( ai
in a_riders_to_remove )
622 ArrayRemoveValue(
self.riders, ai );
629 self endon(
"exited_vehicle" );
631 self waittill(
"death" );
633 if ( IsActor(
self ) && !
self IsRagdoll() )
644 if ( !IsDefined(
self.rider_info.ExitGroundDeathAnim ) )
649 Assert( IsString(
self.rider_info.ExitGroundAnim ),
"No exit animation for '" +
self.rider_info.position +
"'. Can't unload specified group." );
651 if ( IsString(
self.rider_info.ExitGroundAnim ) )
653 animation::play(
self.rider_info.ExitGroundAnim,
self.vehicle,
self.rider_info.AlignTag );
660 Assert( isdefined(
self.rider_info.ExitLowAnim ),
"No exit animation for '" +
self.rider_info.position +
"'. Can't unload specified group." );
661 animation::play(
self.rider_info.ExitLowAnim,
self.vehicle,
self.rider_info.AlignTag );
666 self endon(
"landed" );
668 self waittill(
"death" );
670 if ( IsActor(
self ) )
681 integrationStep = 0.1;
682 position =
self.origin;
683 velocity = (0, 0, -n_initial_speed);
684 gravity = (0, 0, -385.8);
688 previousPosition = position;
691 velocity = velocity + gravity * integrationStep;
693 position = position + velocity * integrationStep;
696 if ( ( position[2] + velocity[2] * integrationStep ) <= v_target_landing[2] )
700 position = v_target_landing;
705 e_move MoveTo( position, integrationStep );
709 wait integrationStep;
717 self endon(
"death" );
719 self notify(
"exiting_vehicle" );
724 Assert( isdefined(
self.rider_info.ExitHighAnim ),
"No exit animation for '" +
self.rider_info.position +
"'. Can't unload specified group." );
725 animation::play(
self.rider_info.ExitHighAnim,
self.vehicle,
self.rider_info.AlignTag, 1, 0, 0 );
732 n_target_height = bundle.HighExitLandHeight;
734 if(
IS_TRUE(
self.rider_info.DropUnderVehicleOrigin ) ||
IS_TRUE(
self.DropUnderVehicleOriginOverride ) )
735 v_target_landing = (
self.vehicle.origin[0],
self.vehicle.origin[1],
self.origin[2] - n_cur_height + n_target_height );
737 v_target_landing = (
self.origin[0],
self.origin[1],
self.origin[2] - n_cur_height + n_target_height );
739 if( isdefined(
self.overrideDropPosition ) )
740 v_target_landing = (
self.overrideDropPosition[0],
self.overrideDropPosition[1], v_target_landing[2] );
742 if( isdefined(
self.targetAngles ) )
743 angles =
self.targetAngles;
745 angles =
self.angles;
753 distance = n_target_height - n_cur_height;
754 initialSpeed = bundle.DropSpeed;
755 acceleration = 385.8;
761 n_fall_time = ( -initialSpeed + Sqrt( Pow( initialSpeed, 2 ) - 2 * acceleration * distance ) ) / acceleration;
763 self notify(
"falling", n_fall_time );
767 e_move waittill(
"movedone" );
769 self notify(
"landing" );
774 self notify(
"landed" );
786 self endon(
"death" );
787 self endon(
"landing" );
791 animation::play(
self.rider_info.ExitHighLoopAnim, e_parent,
"tag_origin" );
799 const height_diff = 10;
800 trace = GroundTrace(
self.origin + (0,0,height_diff),
self.origin + ( 0, 0, -10000 ),
false, e_ignore,
false );
802 return Distance(
self.origin,
trace[
"position" ] );
807 Assert( isdefined(
self.vehicleridersbundle ),
"No vehicleriders bundle specified for this vehicle (in the vehiclesettings gdt)." );
813 Assert( isdefined(
self.vehicleridersrobotbundle ),
"No vehicleriders robot bundle specified for this vehicle (in the vehiclesettings gdt)." );
827 if ( isdefined(
self.riders ) )
829 foreach ( ai
in self.riders )
831 if ( IsDefined( ai ) && ( ai.rider_info.position == str_pos ) )
844 Assert( isdefined(
self.vehicle ) || isdefined( vh ),
"No vehicle specified for rider." );
845 Assert( isdefined(
self.rider_info ) || isdefined( str_pos ),
"No position specified for rider." );
847 if ( isdefined( vh ) )
852 DEFAULT( str_pos,
self.rider_info.position );