mirror of
https://github.com/reaaLx/nx1-gsc-dump.git
synced 2025-06-27 23:01:49 +00:00
Incomplete SP dump provided by Louvenarde
This commit is contained in:
981
animscripts/hummer_turret/common.gsc
Normal file
981
animscripts/hummer_turret/common.gsc
Normal file
@ -0,0 +1,981 @@
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
#include maps\_anim;
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
humvee_turret_init( turret, turretType )
|
||||
{
|
||||
self endon( "killanimscript" );// code
|
||||
|
||||
Assert( IsDefined( turret ) );
|
||||
|
||||
animscripts\utility::initialize( turretType );
|
||||
|
||||
self.no_ai = true;
|
||||
self.noDrop = true;
|
||||
self.a.movement = "stop";
|
||||
self.a.special = turretType;
|
||||
self.a.usingTurret = turret;
|
||||
self.ignoreme = true;
|
||||
self.isCustomAnimating = false;
|
||||
self SetTurretAnim( self.primaryTurretAnim );
|
||||
self SetAnimKnobRestart( self.primaryTurretAnim, 1, 0.2, 1 );
|
||||
|
||||
if ( IsDefined( self.weapon ) )
|
||||
{
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "none" );
|
||||
}
|
||||
|
||||
self.onRotatingVehicleTurret = true;
|
||||
self.getOffVehicleFunc = ::turret_cleanup_on_unload;
|
||||
|
||||
// end some _vehicle and _mgturret threads that we don't want
|
||||
self notify( "guy_man_turret_stop" );
|
||||
turret notify( "stop_burst_fire_unmanned" );
|
||||
|
||||
// setup the turret
|
||||
turret.turretState = "start";
|
||||
turret.aiOwner = self;
|
||||
turret.fireTime = 0;
|
||||
turret SetMode( "sentry" );
|
||||
turret SetSentryOwner( self );
|
||||
turret SetDefaultDropPitch( 0 );
|
||||
turret SetTurretCanAIDetach( false );
|
||||
|
||||
if ( IsDefined( turret.hummer_turret_intial_mode ) )
|
||||
{
|
||||
turret SetMode( turret.hummer_turret_intial_mode );
|
||||
}
|
||||
|
||||
self gunner_pain_init();
|
||||
level thread handle_gunner_pain( self, turret );
|
||||
level thread handle_gunner_death( self, turret );
|
||||
|
||||
// start tracking the turret rotation
|
||||
turret thread turret_track_rotatedirection( self );
|
||||
|
||||
// start turret fire director
|
||||
turret.doFiring = false;
|
||||
self thread fireDirector( turret );
|
||||
|
||||
wait( 0.05 );
|
||||
if ( IsAlive( self ) )
|
||||
{
|
||||
self thread gunner_turning_anims( turret );
|
||||
}
|
||||
}
|
||||
|
||||
gunner_pain_init()
|
||||
{
|
||||
self.allowPain = false; // we're going to handle it ourselves
|
||||
self setFlashbangImmunity( true );
|
||||
|
||||
self.og_health = self.health;
|
||||
self.health = 200;
|
||||
}
|
||||
|
||||
gunner_pain_reset()
|
||||
{
|
||||
self.allowPain = true;
|
||||
self setFlashbangImmunity( false );
|
||||
self.health = self.og_health;
|
||||
}
|
||||
|
||||
handle_gunner_pain( gunner, turret )
|
||||
{
|
||||
gunner endon( "death" );
|
||||
turret endon( "death" );
|
||||
gunner endon( "dismount" );
|
||||
gunner endon( "jumping_out" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
flashedNotify = "flashbang";
|
||||
|
||||
//gunner waittill( "damage", damage, attacker, direction_vec, point, type, modelName, tagName, partName, dflags );
|
||||
msg = gunner waittill_any_return( "damage", flashedNotify );
|
||||
|
||||
/* custom anim pre-empts pain or flash
|
||||
if( gunner.isCustomAnimating )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
painAnim = random( gunner.turretPainAnims );
|
||||
if ( msg == flashedNotify )
|
||||
{
|
||||
painAnim = gunner.turretFlashbangedAnim;
|
||||
gunner animscripts\face::SayGenericDialogue( "flashbang" );
|
||||
}
|
||||
|
||||
//turret thread turret_recenter();
|
||||
gunner DoCustomAnim( turret, painAnim, false );
|
||||
turret notify( "pain_done" );
|
||||
}
|
||||
}
|
||||
|
||||
turret_recenter()
|
||||
{
|
||||
self turret_aim_straight();
|
||||
self waittill( "pain_done" );
|
||||
self turret_aim_restore();
|
||||
}
|
||||
|
||||
handle_gunner_death( gunner, turret )
|
||||
{
|
||||
gunner endon( "dismount" );
|
||||
turret endon( "turret_cleanup" );
|
||||
|
||||
gunner.deathanim = gunner.turretDeathAnim;
|
||||
gunner.noragdoll = true;
|
||||
|
||||
gunner waittill( "death" );
|
||||
level thread turret_cleanup( gunner, turret );
|
||||
}
|
||||
|
||||
// for when _vehicle_aianim wants to unload the gunner, it doesn't know as much as this script yet
|
||||
turret_cleanup_on_unload()
|
||||
{
|
||||
Assert( IsDefined( self.ridingVehicle ) );
|
||||
|
||||
turret = self.ridingVehicle.mgturret[ 0 ];
|
||||
Assert( IsDefined( turret ) );
|
||||
|
||||
// clean up AI - moved it here since it's only needed for unloading.
|
||||
if ( IsAlive( self ) )
|
||||
{
|
||||
self.no_ai = undefined;
|
||||
self.noDrop = undefined;
|
||||
self.ignoreme = false;
|
||||
self.a.special = "none";
|
||||
self.a.usingTurret = undefined;
|
||||
self.deathanim = undefined;
|
||||
self gunner_pain_reset();
|
||||
self.isCustomAnimating = undefined;
|
||||
|
||||
self.turretSpecialAnims = undefined;
|
||||
self.turretPainAnims = undefined;
|
||||
|
||||
self.onRotatingVehicleTurret = undefined;
|
||||
self.getOffVehicleFunc = undefined;
|
||||
|
||||
self StopUseTurret();
|
||||
|
||||
if ( IsDefined( self.weapon ) )
|
||||
{
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "right" );
|
||||
}
|
||||
}
|
||||
|
||||
level thread turret_cleanup( self, turret );
|
||||
}
|
||||
|
||||
turret_cleanup( gunner, turret )
|
||||
{
|
||||
if ( !IsDefined( turret ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
turret notify( "kill_fireController" );
|
||||
turret notify( "turret_cleanup" );
|
||||
turret SetMode( "manual" );
|
||||
turret ClearTargetEntity();
|
||||
|
||||
turret SetDefaultDropPitch( turret.default_drop_pitch );
|
||||
|
||||
if ( IsDefined( gunner ) )
|
||||
{
|
||||
gunner ClearAnim( gunner.additiveUsegunRoot, 0 );
|
||||
gunner ClearAnim( gunner.additiveRotateRoot, 0 );
|
||||
gunner ClearAnim( gunner.turretSpecialAnimsRoot, 0 );
|
||||
}
|
||||
|
||||
// clean up turret
|
||||
turret.fireInterval = undefined;
|
||||
turret.closeEnoughAimDegrees = undefined;
|
||||
turret.fireControllerFunc = undefined;
|
||||
|
||||
turret.turretState = "free";
|
||||
turret.aiOwner = undefined;
|
||||
turret.fireTime = undefined;
|
||||
|
||||
if ( IsDefined( turret.specialCleanupFunc ) )
|
||||
{
|
||||
level [[ turret.specialCleanupFunc ]]( gunner, turret );
|
||||
}
|
||||
}
|
||||
|
||||
// tracks the rotational direction of the turret
|
||||
turret_track_rotatedirection( gunner )
|
||||
{
|
||||
self endon( "turret_cleanup" );
|
||||
self endon( "death" );
|
||||
gunner endon( "death" );
|
||||
gunner endon( "detach" );
|
||||
|
||||
tag = "tag_aim";
|
||||
lastAngles = self GetTagAngles( tag );
|
||||
|
||||
self turret_update_rotatedirection( "none" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
currentAngles = self GetTagAngles( tag );
|
||||
|
||||
// the vectordot of the old right angles and the current forward angles is going to tell us whether
|
||||
// the turret is rotating left, right, or not at all
|
||||
oldRight = AnglesToRight( lastAngles );
|
||||
currentForward = AnglesToForward( currentAngles );
|
||||
|
||||
dot = VectorDot( oldRight, currentForward );
|
||||
|
||||
if ( dot == 0 )
|
||||
{
|
||||
self turret_update_rotatedirection( "none" );
|
||||
}
|
||||
else if ( dot > 0 )
|
||||
{
|
||||
self turret_update_rotatedirection( "right" );
|
||||
}
|
||||
else
|
||||
{
|
||||
self turret_update_rotatedirection( "left" );
|
||||
}
|
||||
|
||||
lastAngles = self GetTagAngles( tag );
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
turret_update_rotatedirection( direction )
|
||||
{
|
||||
if ( !IsDefined( self.rotateDirection ) || self.rotateDirection != direction )
|
||||
{
|
||||
self.rotateDirection = direction;
|
||||
|
||||
//println( "spin direction change: " + self.rotateDirection );
|
||||
}
|
||||
}
|
||||
|
||||
gunner_turning_anims( turret )
|
||||
{
|
||||
self endon( "death" );
|
||||
turret endon( "death" );
|
||||
self endon( "dismount" );
|
||||
turret endon( "turret_cleanup" );
|
||||
|
||||
blendInTime = 0.3;
|
||||
blendOutTime = 0.3;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
turret waittill( "new_fireTarget" );
|
||||
wait( 0.05 );// give him a chance to start rotating to the new target so the direction updates
|
||||
|
||||
if ( !IsDefined( turret.fireTarget ) || self.isCustomAnimating )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
anime = undefined;
|
||||
|
||||
if ( !turret turret_aiming_near_target( turret.fireTarget, turret.closeEnoughAimDegrees ) )
|
||||
{
|
||||
if ( turret.rotateDirection == "right" )
|
||||
{
|
||||
anime = self.additiveTurretRotateRight;
|
||||
//println( "gunner anim RIGHT" );
|
||||
}
|
||||
else if ( turret.rotateDirection == "left" )
|
||||
{
|
||||
anime = self.additiveTurretRotateLeft;
|
||||
//println( "gunner anim LEFT" );
|
||||
}
|
||||
|
||||
if ( IsDefined( anime ) )
|
||||
{
|
||||
// dial the parent branch up
|
||||
self SetAnimLimited( self.additiveRotateRoot, 1, blendInTime, 1 );
|
||||
// also tell it which leaf anim to use
|
||||
// (this is inheriting its parent's blend in time so we can set the time to 0)
|
||||
self SetAnimKnobLimited( anime, 1, 0, 1 );
|
||||
|
||||
while ( IsDefined( turret.fireTarget ) && !turret turret_aiming_near_target( turret.fireTarget, turret.closeEnoughAimDegrees ) )
|
||||
{
|
||||
if ( self.isCustomAnimating )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
|
||||
//println( "gunner anim CLEAR" );
|
||||
self ClearAnim( self.additiveRotateRoot, blendOutTime );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// makes a passenger into the turret gunner - call instead of UseTurret()
|
||||
vehicle_passenger_2_turret( vehicle, pos, turret, animation )
|
||||
{
|
||||
vehicle.usedPositions[ self.vehicle_position ] = false;
|
||||
//vehicle.riders = array_remove( vehicle.riders, self );
|
||||
self maps\_vehicle_aianim::guy_cleanup_vehiclevars();
|
||||
guy_gets_on_turret( vehicle, pos, turret, animation );
|
||||
}
|
||||
|
||||
// makes a passenger into the turret gunner - call instead of UseTurret()
|
||||
guy_goes_directly_to_turret( vehicle, pos, turret, animation )
|
||||
{
|
||||
guy_gets_on_turret( vehicle, pos, turret, animation );
|
||||
}
|
||||
|
||||
guy_gets_on_turret( vehicle, pos, turret, animation )
|
||||
{
|
||||
self endon( "death" );
|
||||
turret endon( "death" );
|
||||
|
||||
// forget about being a regular vehicle rider
|
||||
self StopAnimScripted();
|
||||
self notify( "newanim" );
|
||||
|
||||
self.drivingVehicle = undefined;
|
||||
|
||||
self.no_ai = true;
|
||||
animation = %humvee_passenger_2_turret;
|
||||
if ( !isdefined( animation ) )
|
||||
animation = self.passenger_2_turret_anim;
|
||||
|
||||
// get the origin/angles of the vehicle tag where this guy is riding
|
||||
animpos = maps\_vehicle_aianim::anim_pos( vehicle, pos );
|
||||
org = vehicle GetTagOrigin( animpos.sittag );
|
||||
angles = vehicle GetTagAngles( animpos.sittag );
|
||||
|
||||
turret SetDefaultDropPitch( 0 );
|
||||
turret thread turret_animate( turret.passenger2turret_anime );
|
||||
|
||||
// animate into position
|
||||
self AnimScripted( "passenger2turret", org, angles, animation );
|
||||
wait( GetAnimLength( animation ) );
|
||||
self StopAnimScripted();
|
||||
|
||||
turret turret_aim_restore();
|
||||
|
||||
// now start running the regular turret scripts - GDT points to minigun_hummer\stand::main()
|
||||
self UseTurret( turret );
|
||||
}
|
||||
|
||||
turret_animate( anime )
|
||||
{
|
||||
if ( IsDefined( self.idleAnim ) )
|
||||
{
|
||||
self ClearAnim( self.idleAnim, 0 );
|
||||
self.idleAnim = undefined;
|
||||
}
|
||||
|
||||
self SetFlaggedAnimKnobRestart( "minigun_turret", anime, 1, 0, 1 );
|
||||
self waittillmatch( "minigun_turret", "end" );
|
||||
self ClearAnim( anime, 0 );
|
||||
}
|
||||
|
||||
turret_animfirstframe( anime )
|
||||
{
|
||||
self SetAnimKnobRestart( anime, 1, 0, 0 );
|
||||
self.idleAnim = anime;
|
||||
}
|
||||
|
||||
// "directs" the turret about whether it should be firing or not
|
||||
// note: works with either code-controlled sentry targets or manually setting turret target
|
||||
// - to make an AI aim without firing, set his .ignoreall to true
|
||||
fireDirector( turret )
|
||||
{
|
||||
self endon( "death" );
|
||||
turret endon( "death" );
|
||||
self endon( "dismount" );
|
||||
turret endon( "kill_fireController" );
|
||||
|
||||
turret thread turret_target_updater( self );
|
||||
wait( 0.05 );// let the target updater kick off
|
||||
|
||||
self thread [[ turret.fireControllerFunc ]]( turret );
|
||||
|
||||
target = undefined;
|
||||
|
||||
wait_duration_after_aiming_before_firing = 0.0;
|
||||
if ( IsDefined( turret.wait_duration_after_aiming_before_firing ) )
|
||||
{
|
||||
wait_duration_after_aiming_before_firing = turret.wait_duration_after_aiming_before_firing;
|
||||
}/*
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
// get a target
|
||||
target = turret.fireTarget;
|
||||
|
||||
// wait for the right time to start shooting
|
||||
while ( turret target_confirm( target ) )
|
||||
{
|
||||
// tried a CanSee check here too, didn't seem necessary after testing
|
||||
if ( turret turret_aiming_near_target( target, turret.closeEnoughAimDegrees ) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
wait( 0.05 );
|
||||
}
|
||||
|
||||
// wait while aiming at target before firing
|
||||
if ( wait_duration_after_aiming_before_firing > 0.0 )
|
||||
{
|
||||
wait( wait_duration_after_aiming_before_firing );
|
||||
}
|
||||
|
||||
//TagCC<NOTE>: What if the state changes between the time target_confirmed was true and was aiming towards target and now?
|
||||
if ( turret target_confirm( target ) && !self.ignoreall )
|
||||
{
|
||||
// shoot at him
|
||||
turret.doFiring = true;
|
||||
}
|
||||
|
||||
// wait for his death, or for the code/script to pick/designate a new target
|
||||
while ( turret target_confirm( target ) && !self.ignoreall && !self.isCustomAnimating )
|
||||
{
|
||||
wait( 0.05 );
|
||||
}
|
||||
|
||||
// stop shooting
|
||||
if ( turret.Dofiring || self.ignoreall )
|
||||
{
|
||||
turret.doFiring = false;
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
while( true )
|
||||
{
|
||||
target = turret.fireTarget;
|
||||
|
||||
//short circuit the loop if self is ignore all.
|
||||
if( self.ignoreall || !IsDefined( target ) )
|
||||
{
|
||||
wait 0.05;
|
||||
continue;
|
||||
}
|
||||
|
||||
//wait until target is confirmed and the turret is aiming towards the actor.
|
||||
while( !IsDefined( target ) || !( (turret target_confirm( target )) && (turret turret_aiming_near_target( target, turret.closeEnoughAimDegrees )) ) )
|
||||
{
|
||||
wait 0.05;
|
||||
target = turret.fireTarget;
|
||||
}
|
||||
|
||||
if ( wait_duration_after_aiming_before_firing > 0.0 )
|
||||
{
|
||||
wait wait_duration_after_aiming_before_firing;
|
||||
}
|
||||
|
||||
turret.doFiring = true;
|
||||
|
||||
//once firing begins, wait until target is no longer confirmed (usually death of target), then stop.
|
||||
while ( turret target_confirm( target ) && !self.ignoreall && !self.isCustomAnimating )
|
||||
{
|
||||
wait 0.05;
|
||||
}
|
||||
|
||||
turret.doFiring = false;
|
||||
|
||||
wait 0.05;
|
||||
}
|
||||
}
|
||||
|
||||
// makes sure the target that the fireDirector is thinking about is still synced with turret_target_updater
|
||||
target_confirm( target )
|
||||
{
|
||||
if ( IsDefined( self.dontshoot ) )
|
||||
{
|
||||
AssertEx( self.dontshoot, ".dontshoot must be true or undefined." );
|
||||
return false;
|
||||
}
|
||||
|
||||
// maybe the turret can't see the target anymore
|
||||
if ( !IsDefined( self.fireTarget ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !turret_target_validate( target ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( target != self.fireTarget )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// make sure the script knows about the most recent turret target
|
||||
// (this is necessary because code sets the turret target silently and behind the scenes)
|
||||
turret_target_updater( gunner )
|
||||
{
|
||||
gunner endon( "death" );
|
||||
self endon( "death" );
|
||||
gunner endon( "dismount" );
|
||||
self endon( "kill_fireController" );
|
||||
|
||||
|
||||
// initialize this, other threads are looking for it
|
||||
self.fireTarget = undefined;
|
||||
|
||||
target = undefined;
|
||||
lastTarget = undefined;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
target = self GetTurretTarget( false );
|
||||
|
||||
doUpdate = false;
|
||||
|
||||
// target can come back undefined if the turret loses sight of its target
|
||||
if ( turret_target_validate( target ) || !IsDefined( target ) )
|
||||
{
|
||||
// if the old target was defined and the new target is undefined
|
||||
// (e.g., the turret lost its target) we want to update
|
||||
if ( !IsDefined( target ) && IsDefined( lastTarget ) )
|
||||
{
|
||||
doUpdate = true;
|
||||
}
|
||||
// or, if the new target is defined and the old one isn't, do the update
|
||||
else if ( IsDefined( target ) && !IsDefined( lastTarget ) )
|
||||
{
|
||||
doUpdate = true;
|
||||
}
|
||||
// or, if the new target is defined and different from before, do the update
|
||||
else if ( IsDefined( target ) && target != lastTarget )
|
||||
{
|
||||
doUpdate = true;
|
||||
}
|
||||
|
||||
if ( doUpdate )
|
||||
{
|
||||
self.fireTarget = target;
|
||||
lastTarget = target;
|
||||
self notify( "new_fireTarget" );
|
||||
}
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
turret_target_validate( target )
|
||||
{
|
||||
if ( !IsDefined( target ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( IsDefined( target.ignoreme ) && target.ignoreme )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// can't use IsSentient because the sentient AIs will turn into non-sentient corpses
|
||||
if ( IsSubStr( target.code_classname, "actor" ) && !IsAlive( target ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// manually designate a target for the turret
|
||||
// - fireTime_min: minimum amount of time to fire once the turret has centered on the target
|
||||
// - fireTime_max (optional): if set, function will pick a random time between min and max
|
||||
// - fireTime_message (optional): will fire until the turret is notified the message. will ignore min and max time.
|
||||
set_manual_target( target, fireTime_min, fireTime_max, fireTime_message )
|
||||
{
|
||||
AssertEx( IsDefined( target ), "undefined target passed to set_manual_target()." );
|
||||
|
||||
self endon( "turret_cleanup" );
|
||||
|
||||
oldMode = self GetMode();
|
||||
if ( oldMode != "manual" )
|
||||
{
|
||||
self SetMode( "manual" );
|
||||
}
|
||||
|
||||
if ( !IsDefined( fireTime_min ) && !IsDefined( fireTime_max ) )
|
||||
{
|
||||
fireTime_min = 1.5;
|
||||
fireTime_max = 3;
|
||||
}
|
||||
|
||||
self animscripts\hummer_turret\common::custom_anim_wait();
|
||||
self SetTargetEntity( target );
|
||||
//println( "target set" );
|
||||
|
||||
self waittill( "turret_on_target" );
|
||||
//println( "turret on target" );
|
||||
|
||||
if ( IsDefined( fireTime_message ) )
|
||||
{
|
||||
self waittill( fireTime_message );
|
||||
}
|
||||
else if ( IsDefined( fireTime_max ) )
|
||||
{
|
||||
wait( RandomFloatRange( fireTime_min, fireTime_max ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
wait( fireTime_min );
|
||||
}
|
||||
|
||||
self custom_anim_wait();
|
||||
self ClearTargetEntity( target );
|
||||
|
||||
if ( IsDefined( oldMode ) )
|
||||
{
|
||||
self SetMode( oldMode );
|
||||
}
|
||||
}
|
||||
|
||||
DoShoot( turret )
|
||||
{
|
||||
self notify( "doshoot_starting" );
|
||||
|
||||
self SetAnimLimited( self.additiveUsegunRoot, 1, .1 );
|
||||
self SetAnimKnobLimited( self.additiveTurretFire, 1, .1 );
|
||||
|
||||
turret.turretState = "fire";
|
||||
turret thread fire( self );
|
||||
}
|
||||
|
||||
fire( gunner )
|
||||
{
|
||||
gunner endon( "death" );
|
||||
self endon( "death" );
|
||||
gunner endon( "dismount" );
|
||||
self endon( "kill_fireController" );
|
||||
self endon( "stopfiring" );
|
||||
self endon( "custom_anim" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self ShootTurret();
|
||||
wait( self.fireInterval );
|
||||
}
|
||||
}
|
||||
|
||||
DoAim( turret )
|
||||
{
|
||||
turret.turretState = "aim";
|
||||
turret notify( "stopfiring" );
|
||||
|
||||
self thread DoAim_idle_think( turret );
|
||||
}
|
||||
|
||||
DoAim_idle_think( turret )
|
||||
{
|
||||
self notify( "doaim_idle_think" );
|
||||
self endon( "doaim_idle_think" );
|
||||
|
||||
self endon( "custom_anim" );
|
||||
self endon( "doshoot_starting" );
|
||||
self endon( "death" );
|
||||
|
||||
turret endon( "death" );
|
||||
assertex( isdefined( turret ), "The turret is gone!" );
|
||||
assertex( isalive( self ), "No, I can't die!" );
|
||||
|
||||
Assert( IsDefined( turret.ownervehicle ) );
|
||||
vehicle = turret.ownervehicle;
|
||||
assertex( isdefined( vehicle ), "There is no vehicle!" );
|
||||
|
||||
idle = -1;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( vehicle Vehicle_GetSpeed() < 1 && idle )
|
||||
{
|
||||
self SetAnimLimited( self.additiveUsegunRoot, 1, 0.1 );
|
||||
self SetAnimKnobLimited( self.additiveTurretIdle, 1, 0.1 );
|
||||
idle = 0;
|
||||
}
|
||||
else
|
||||
if ( vehicle Vehicle_GetSpeed() >= 1 && !idle )
|
||||
{
|
||||
self SetAnimLimited( self.additiveUsegunRoot, 1, 0.1 );
|
||||
self SetAnimKnobLimited( self.additiveTurretDriveIdle, 1, 0.1 );
|
||||
idle = 1;
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
///ScriptDocBegin
|
||||
"Name: turret_gunner_custom_anim( <turret> , <animStr> , <centerTurretFirst> )"
|
||||
"Summary: Call on a turret gunner do one of his predefined custom animations. All the custom anims for a turret gunner get set up in the array self.turretSpecialAnims, in the main script for the turret type - for example, animscripts\hummer_turret\minigun_stand.gsc."
|
||||
"Module: Entity"
|
||||
"CallOn: An AI using a vehicle turret. (Note: this only works for 360 degree vehicle turrets, for example those on the hummer or the suburban.)"
|
||||
"MandatoryArg: <turret> The turret the AI is using."
|
||||
"MandatoryArg: <animStr> The name of the animation, as a string. used as the lookup index for self.turretSpecialAnims."
|
||||
"OptionalArg: <centerTurretFirst>: Whether the turret should re-center to its "home" location before the animation plays. Defaults to false."
|
||||
"Example: gunner animscripts\hummer_turret\common::turret_gunner_custom_anim( turret, anime, true );"
|
||||
"SPMP: singleplayer"
|
||||
///ScriptDocEnd
|
||||
=============
|
||||
*/
|
||||
turret_gunner_custom_anim( turret, animStr, centerTurretFirst )
|
||||
{
|
||||
// this section of endons should be identical to the ones in the function below
|
||||
self endon( "death" );
|
||||
turret endon( "death" );
|
||||
self endon( "dismount" );
|
||||
self endon( "jumping_out" );
|
||||
|
||||
anime = self.turretSpecialAnims[ animStr ];
|
||||
Assert( IsDefined( anime ) );
|
||||
|
||||
self custom_anim_wait();
|
||||
|
||||
disabledReload = turret reload_disable_safe();
|
||||
|
||||
self DoCustomAnim( turret, anime, centerTurretFirst );
|
||||
|
||||
if ( disabledReload )
|
||||
{
|
||||
turret reload_enable();
|
||||
}
|
||||
}
|
||||
|
||||
reload_disable_safe()
|
||||
{
|
||||
disabledReload = false;
|
||||
if ( !IsDefined( self.disableReload ) || !self.disableReload )
|
||||
{
|
||||
disabledReload = true;
|
||||
self.disableReload = true;
|
||||
}
|
||||
|
||||
return disabledReload;
|
||||
}
|
||||
|
||||
reload_enable()
|
||||
{
|
||||
self.disableReload = false;
|
||||
}
|
||||
|
||||
DoReload( turret )
|
||||
{
|
||||
if ( IsDefined( turret.disableReload ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// this section of endons should be identical to the ones in the function above
|
||||
self endon( "death" );
|
||||
turret endon( "death" );
|
||||
self endon( "dismount" );
|
||||
self endon( "jumping_out" );
|
||||
|
||||
self thread custom_battlechatter( "inform_reloading" );
|
||||
|
||||
turret notify( "starting_reload" );
|
||||
|
||||
self DoCustomAnim( turret, self.turretReloadAnim, turret.centerTurretForReload, turret.reloadDuration );
|
||||
}
|
||||
|
||||
DoCustomAnim( turret, anime, centerTurretFirst, duration )
|
||||
{
|
||||
// NOTE! To stop behavior, don't notify do_custom_anim, do self notify( "special_anim", "end" );
|
||||
self notify( "do_custom_anim" );
|
||||
self endon( "do_custom_anim" );
|
||||
|
||||
if ( IsDefined( duration ) )
|
||||
{
|
||||
anim_rate = GetAnimLength( anime ) / duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
anim_rate = 1.0;
|
||||
}
|
||||
|
||||
/*
|
||||
// these endons are dupes
|
||||
|
||||
self endon( "death" );
|
||||
turret endon( "death" );
|
||||
self endon( "dismount" );
|
||||
self endon( "jumping_out" );
|
||||
*/
|
||||
|
||||
Assert( IsDefined( anime ) );
|
||||
|
||||
self.isCustomAnimating = true;
|
||||
self.customAnim = anime;
|
||||
turret.turretState = "customanim";
|
||||
turret TurretFireDisable();
|
||||
|
||||
if ( turret GetBarrelSpinRate() > 0 )
|
||||
{
|
||||
turret StopBarrelSpin();
|
||||
}
|
||||
|
||||
// turn off threads that can mess up the animtree
|
||||
turret notify( "kill_fireController" );
|
||||
self notify( "custom_anim" );
|
||||
|
||||
if ( IsDefined( centerTurretFirst ) && centerTurretFirst )
|
||||
{
|
||||
turret turret_aim_straight();
|
||||
}
|
||||
|
||||
// "knob" dials down all the siblings of the specialanimsroot, so we don't need to manually
|
||||
// dial down self.primaryTurretAnim or self.additiveUsegunRoot right here
|
||||
self SetAnimKnobLimitedRestart( self.turretSpecialAnimsRoot, 1, 0.2 );
|
||||
self SetFlaggedAnimKnobRestart( "special_anim", anime, 1, 0, anim_rate );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
// broke into a loop so I can debug the notetracks
|
||||
self waittill( "special_anim", notetrack );
|
||||
if ( notetrack == "end" )
|
||||
break;
|
||||
}
|
||||
|
||||
// turn the ROOT down, not the anim under the root
|
||||
self ClearAnim( self.turretSpecialAnimsRoot, 0.2 );
|
||||
// dial these up individually - can't use "knob" cause we want them both to be active
|
||||
self SetAnimLimited( self.primaryTurretAnim, 1 ); // 0.2 blend time is the default
|
||||
self SetAnimLimited( self.additiveUsegunRoot, 1 );
|
||||
|
||||
if ( IsDefined( centerTurretFirst ) && centerTurretFirst )
|
||||
{
|
||||
turret turret_aim_restore();
|
||||
}
|
||||
|
||||
self.customAnim = undefined;
|
||||
self.isCustomAnimating = false;
|
||||
turret TurretFireEnable();
|
||||
|
||||
// turn those animtree-messing-up threads back on
|
||||
self thread fireDirector( turret );
|
||||
}
|
||||
|
||||
// use this if you're manually setting the turret target entity - call this first (non-threaded)
|
||||
// to make sure that the DoCustomAnim function doesn't clear out your custom target
|
||||
custom_anim_wait()
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
if ( !IsDefined( self.isCustomAnimating ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while ( self.isCustomAnimating )
|
||||
{
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
turret_aim_straight( straightAngles )
|
||||
{
|
||||
if ( !IsDefined( straightAngles ) )
|
||||
{
|
||||
currentAngles = self GetTagAngles( "tag_flash" );
|
||||
straightAngles = ( 0, currentAngles[ 1 ], currentAngles[ 2 ] );// just keep the yaw
|
||||
}
|
||||
|
||||
self.oldMode = self GetMode();
|
||||
self SetMode( "manual" );
|
||||
|
||||
// use a temp target to make the gun point straight forward
|
||||
forward = AnglesToForward( straightAngles );
|
||||
scalevec = vector_multiply( forward, 96 );
|
||||
targetOrigin = self GetTagOrigin( "tag_aim" ) + scalevec;
|
||||
self.tempTarget = Spawn( "script_origin", targetOrigin );
|
||||
self.tempTarget.ignoreme = true;
|
||||
|
||||
self.tempTarget LinkTo( self.ownerVehicle );// if the vehicle is moving we have to link the target to the gun so the gun doesn't rotate around as the vehicle angles change
|
||||
|
||||
self ClearTargetEntity();
|
||||
self SetTargetEntity( self.tempTarget );
|
||||
|
||||
self waittill( "turret_on_target" );
|
||||
}
|
||||
|
||||
turret_aim_restore()
|
||||
{
|
||||
self ClearTargetEntity();
|
||||
|
||||
if ( IsDefined( self.tempTarget ) )
|
||||
{
|
||||
self.tempTarget Unlink();
|
||||
self.tempTarget Delete();
|
||||
}
|
||||
|
||||
if ( IsDefined( self.oldMode ) )
|
||||
{
|
||||
self SetMode( self.oldMode );
|
||||
self.oldMode = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// - closeEnoughAngle: we want to be pointing within [+/- of this value in degrees]
|
||||
// to the target to return true
|
||||
turret_aiming_near_target( target, closeEnoughAngle )
|
||||
{
|
||||
//delta = self turret_get_angle_to_target( target );
|
||||
|
||||
turret_angles = AnglesToForward( self GetTagAngles( "tag_flash" ) );
|
||||
|
||||
delta = acos(VectorDot( VectorNormalize(target.origin - self.origin), turret_angles ));
|
||||
|
||||
if ( delta <= closeEnoughAngle )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
turret_get_angle_to_target( target )
|
||||
{
|
||||
// get the yaw angle of the vector between the target origin and the turret origin
|
||||
yawAngleToTarget = VectorToYaw( target.origin - self.origin ); //tagCC<NOTE>: I don't think this is being used right. Doesn't take into account self's angles.
|
||||
|
||||
// normalize the difference between the yaw angle and the angles of the end of the barrel:
|
||||
// this tells us how far away we are from being perfectly centered on the target
|
||||
turretYawAngle = self GetTagAngles( "tag_flash" )[ 1 ];
|
||||
delta = animscripts\utility::AbsAngleClamp180( turretYawAngle - yawAngleToTarget );
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
lerp_out_drop_pitch( time )
|
||||
{
|
||||
blend = self create_blend( ::blend_dropPitch, 20, 0 );
|
||||
blend.time = time;
|
||||
}
|
||||
|
||||
blend_dropPitch( progress, start, end )
|
||||
{
|
||||
val = start * ( 1 - progress ) + end * progress;
|
||||
self SetDefaultDropPitch( val );
|
||||
}
|
||||
|
203
animscripts/hummer_turret/minigun_code.gsc
Normal file
203
animscripts/hummer_turret/minigun_code.gsc
Normal file
@ -0,0 +1,203 @@
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
#include animscripts\hummer_turret\common;
|
||||
|
||||
main( turret )
|
||||
{
|
||||
turret.fireInterval = 0.1; // time between shots
|
||||
turret.closeEnoughAimDegrees = 35; // how many degrees away from aiming exactly at the target should we be before we start doing "on/near target" stuff
|
||||
turret.fireControllerFunc = ::fireController_minigun; // the function that tells the turret how exactly to shoot when the fireDirector tells it that it should be firing
|
||||
turret.specialCleanupFunc = ::minigun_cleanup_func; // gets called when the turret is no longer in use
|
||||
turret.default_drop_pitch = 20;
|
||||
turret.secsOfFiringBeforeReload = 15; // secs; the weapon will need periodic operator "maintenance"
|
||||
|
||||
humvee_turret_init( turret, "minigun" );
|
||||
wait( 0.05 );
|
||||
|
||||
turret notify( "turret_ready" );
|
||||
}
|
||||
|
||||
minigun_cleanup_func( gunner, turret )
|
||||
{
|
||||
if ( turret GetBarrelSpinRate() > 0 )
|
||||
{
|
||||
turret StopBarrelSpin();
|
||||
}
|
||||
|
||||
// could be disabled if we're in a custom anim when the actor dies
|
||||
turret TurretFireEnable();
|
||||
}
|
||||
|
||||
// controls spinning & firing the minigun, responding to commands from fireDirector()
|
||||
fireController_minigun( turret )
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "dismount" );
|
||||
|
||||
assert( isdefined( turret ) );
|
||||
|
||||
turret endon( "kill_fireController" );
|
||||
turret endon( "death" );
|
||||
|
||||
// "extra" fire time makes the operator look like he has human reaction time
|
||||
extraFireTime_min = 600; // ms
|
||||
extraFireTime_max = 900;
|
||||
if ( IsDefined( turret.extraFireTime_min ) )
|
||||
{
|
||||
extraFireTime_min = turret.extraFireTime_min;
|
||||
}
|
||||
if ( IsDefined( turret.extraFireTime_max ) )
|
||||
{
|
||||
extraFireTime_max = turret.extraFireTime_max;
|
||||
}
|
||||
startFireTime = -1;
|
||||
ceaseFireTime = undefined;
|
||||
extraFireTime = undefined;
|
||||
|
||||
// extra spin time makes it look like the operator is scanning for more targets
|
||||
turret.extraSpinTime_min = 250;
|
||||
turret.extraSpinTime_max = 2250;
|
||||
startExtraSpinningTime = -1;
|
||||
extraSpinTime = undefined;
|
||||
|
||||
isFiring = false;
|
||||
isSpinning = false;
|
||||
|
||||
turret.fireTime = 0;
|
||||
|
||||
self DoAim( turret );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
// if we're supposed to be firing but we're not, and if we're not doing a custom anim...
|
||||
if ( turret.doFiring && !isFiring && !self.isCustomAnimating )
|
||||
{
|
||||
isFiring = true;
|
||||
|
||||
// spin the barrel if need be
|
||||
if ( !isSpinning )
|
||||
{
|
||||
//println( "start spin" );
|
||||
turret minigun_spinup();
|
||||
isSpinning = true;
|
||||
}
|
||||
|
||||
// start firing
|
||||
//println( "start firing" );
|
||||
turret notify( "startfiring" );
|
||||
startFireTime = GetTime();
|
||||
self DoShoot( turret );
|
||||
wait( 0.05 ); // let the shooting thread start before potentially killing it on the same frame
|
||||
}
|
||||
// if we're currently not supposed to be firing but still actually are...
|
||||
else if ( !turret.doFiring && isFiring )
|
||||
{
|
||||
if ( !IsDefined( ceaseFireTime ) )
|
||||
{
|
||||
ceaseFireTime = GetTime(); // time when the turret stops firing
|
||||
}
|
||||
|
||||
if ( !IsDefined( extraFireTime ) )
|
||||
{
|
||||
extraFireTime = RandomFloatRange( extraFireTime_min, extraFireTime_max );
|
||||
}
|
||||
|
||||
// have we fired long enough after being told to stop?
|
||||
if ( GetTime() - ceaseFireTime >= extraFireTime )
|
||||
{
|
||||
isFiring = false;
|
||||
|
||||
//println( "stop firing" );
|
||||
self DoAim( turret );
|
||||
startExtraSpinningTime = GetTime();
|
||||
|
||||
// reset counters
|
||||
ceaseFireTime = undefined;
|
||||
extraFireTime = undefined;
|
||||
}
|
||||
}
|
||||
// if all we're still doing is spinning...
|
||||
else if ( !turret.doFiring && !isFiring && isSpinning )
|
||||
{
|
||||
if ( !IsDefined( extraSpinTime ) )
|
||||
{
|
||||
extraSpinTime = RandomFloatRange( turret.extraSpinTime_min, turret.extraSpinTime_max );
|
||||
}
|
||||
|
||||
// stop spin immediately for custom anims, or wait for extra spin time
|
||||
if ( self.isCustomAnimating || ( GetTime() - startExtraSpinningTime >= extraSpinTime ) )
|
||||
{
|
||||
//println( "stop spin" );
|
||||
turret StopBarrelSpin();
|
||||
isSpinning = false;
|
||||
|
||||
extraSpinTime = undefined; // reset
|
||||
}
|
||||
}
|
||||
|
||||
if ( turret.turretstate == "fire" )
|
||||
turret.fireTime += 0.05;// ( GetTime() - startFireTime ) / 1000;
|
||||
|
||||
if ( turret.fireTime > turret.secsOfFiringBeforeReload )
|
||||
{
|
||||
//println( "reload" );
|
||||
turret.doFiring = false;
|
||||
isFiring = false;
|
||||
self DoAim( turret );
|
||||
startExtraSpinningTime = -1;
|
||||
ceaseFireTime = undefined;
|
||||
extraFireTime = undefined;
|
||||
|
||||
self thread DoReload( turret );
|
||||
turret.fireTime = 0; // reset counter
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
|
||||
if ( !isdefined( turret ) )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// spins the minigun up to the full rate needed to fire
|
||||
minigun_spinup()
|
||||
{
|
||||
if ( self GetBarrelSpinRate() == 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self StartBarrelSpin();
|
||||
|
||||
wait( 0.05 );
|
||||
|
||||
// Dan: Wait for spin up only if this weapon actually spins up.
|
||||
if ( self GetBarrelSpinRate() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if ( self GetBarrelSpinRate() == 1 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
|
||||
while ( self GetBarrelSpinRate() < 1 )
|
||||
{
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================
|
||||
// SRS TEMP - so I don't clutter generic_human with stuff I'm not using atm
|
||||
/*
|
||||
humveeGunner : complete nonloopsync
|
||||
{
|
||||
//humvee_turret_2_passenger
|
||||
//humvee_turret_duck
|
||||
//humvee_turret_duck_left
|
||||
//humvee_turret_duck_right
|
||||
//humvee_turret_death
|
||||
}
|
||||
*/
|
63
animscripts/hummer_turret/minigun_stand.gsc
Normal file
63
animscripts/hummer_turret/minigun_stand.gsc
Normal file
@ -0,0 +1,63 @@
|
||||
#include maps\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
// self = the guy using the turret
|
||||
main()
|
||||
{
|
||||
turret = self getTurret();
|
||||
|
||||
self.desired_anim_pose = "stand";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
// .primaryTurretAnim is used by code so don't change this variable name
|
||||
self.primaryTurretAnim = %humveeGunner_aim;
|
||||
|
||||
self.additiveTurretRotateLeft = %humvee_turret_aim_6_add;
|
||||
self.additiveTurretRotateRight = %humvee_turret_aim_4_add;
|
||||
self.additiveRotateRoot = %additive_humveeGunner_aim_leftright;
|
||||
|
||||
self.additiveTurretIdle = %humvee_turret_idle;
|
||||
self.additiveTurretDriveIdle = %humvee_turret_driveidle;
|
||||
self.additiveTurretFire = %humvee_turret_fire;
|
||||
self.additiveUsegunRoot = %additive_humveeGunner_usegun;
|
||||
|
||||
self.turretDeathAnimRoot = %humveeGunner_death;
|
||||
self.turretDeathAnim = %humvee_turret_death;
|
||||
|
||||
self.turretPainAnims[ 0 ] = %humvee_turret_painA;
|
||||
self.turretPainAnims[ 1 ] = %humvee_turret_painB;
|
||||
|
||||
self.turretFlashbangedAnim = %humvee_turret_flinchA;
|
||||
|
||||
self.turretReloadAnim = %humvee_turret_rechamber;
|
||||
|
||||
self.turretSpecialAnimsRoot = %humveeGunner;
|
||||
arr = [];
|
||||
arr[ "humvee_turret_bounce" ] = %humvee_turret_bounce;
|
||||
arr[ "humvee_turret_idle_lookback" ] = %humvee_turret_idle_lookback;
|
||||
arr[ "humvee_turret_idle_lookbackB" ] = %humvee_turret_idle_lookbackB;
|
||||
arr[ "humvee_turret_idle_signal_forward" ] = %humvee_turret_idle_signal_forward;
|
||||
arr[ "humvee_turret_idle_signal_side" ] = %humvee_turret_idle_signal_side;
|
||||
arr[ "humvee_turret_radio" ] = %humvee_turret_radio;
|
||||
arr[ "humvee_turret_flinchA" ] = %humvee_turret_flinchA;
|
||||
arr[ "humvee_turret_flinchB" ] = %humvee_turret_flinchB;
|
||||
arr[ "humvee_turret_rechamber" ] = %humvee_turret_rechamber;
|
||||
self.turretSpecialAnims = arr;
|
||||
|
||||
turret setup_turret_anims();
|
||||
|
||||
self thread animscripts\hummer_turret\minigun_code::main( turret );
|
||||
|
||||
turret.reloadDuration = 2.0;
|
||||
turret.centerTurretForReload = true;
|
||||
}
|
||||
|
||||
#using_animtree( "vehicles" );
|
||||
setup_turret_anims()
|
||||
{
|
||||
self UseAnimTree( #animtree );
|
||||
self.passenger2turret_anime = %humvee_passenger_2_turret_minigun;
|
||||
self.turret2passenger_anime = %humvee_turret_2_passenger_minigun;
|
||||
}
|
Reference in New Issue
Block a user